Commit Graph

5 Commits

Author SHA1 Message Date
John Dvorak 6a98d8ce9e refactor: compiler pipeline hardening — parser diagnostics + exhaustive switches + golden equivalence
grammar.ts:
  - Replace 2 parseAssertion console.warn + return-null patterns with
    this.errorWithCode() throws, producing structured ParseError
    diagnostics instead of silently skipping invalid clauses
  - Maintain parseBlock's return-null contract for unmatched tokens
    (caller loops over tokens expecting null for non-block starters)

compiler.ts:
  - buildOptionsFromAssertion: convert 3 standalone ifs to if/else if/else
    with never-exhausted throw on unknown assertion type
  - compileToFormula: replace silent return-null with throw on unknown
    assertion type

validator.ts:
  - validateAssertion: replace silent return {valid:true} for unknown
    assertion types with throw

fol-compiler.ts:
  - compileSingleAssertion: replace silent return-null with throw

Golden equivalence tests (fol-equivalence-golden.test.ts):
  7 new deterministic tests covering gaps identified in REFACTOR item 5:
    - Size assertions: atLeast, atMost, between (fluent vs dense)
    - Compound assertions: .and chain, .or chain
    - Options: gap, tolerance in jnd
  Documents known discrepancy: fluent size.* prefix vs dense canonical name
  (fol-compiler normalizes at FormulaNode level, canonical path does not)

Existing property-based equivalence tests cover spatial, quantifier,
and frame equivalence. Topology predicates have no fluent API surface
(dense-DSL-only), so equivalence must be verified at evaluation level
(already covered by hard E2E topology tests).

662 tests pass (315 DSL + 141 core + 149 solver + 57 E2E).
2026-05-22 15:23:29 -07:00
John Dvorak 7f40224f0f fix: propagate compound state through toAst() and canonical lowering
ast.ts: Add optional compoundOperator and compoundParts fields to
  RelationAssertion, allowing compound fluent assertions to carry
  their .and / .or structure through the AST layer.

fluent.ts: toAst() now emits compoundOperator/compoundParts when
  isCompound, closing the gap where compound state was silently
  dropped in canonical extraction, preset building, and validation.

lower-to-canonical.ts: Handle RelationAssertion with compound metadata
  by lowering each part as a separate grouped clause (same groupId,
  same compoundOperator), matching DSL parser compound behavior.

validator.ts: Validate options on each compound part, closing the
  false-positive validation gap where only the final relation was checked.

3 lossy code paths (extractCanonicalFromAssertion, presets.toPresetResult,
validateRelation) now preserve compound structure. Primary FOL evaluation
path was already correct (fol-compiler reads compoundParts directly).

658 tests pass.
2026-05-22 13:46:54 -07:00
John Dvorak 6f82849b4f refactor: convert validator to use predicate spec table
Replace 5 static Sets/maps (SPATIAL_RELATIONS, SIZE_RELATIONS,
VALID_OPTIONS, QUANTIFIER_COMPATIBLE, UNARY_RELATIONS) with
derivation from the unified PredicateSpec table:
  - collectSpatialPredicateNames / collectSizePredicateNames
    for category sets
  - getPredicateValidOptions for option validation
  - collectQuantifierCompatiblePredicateNames for quantifier checks
  - isUnaryPredicate for unary detection

Local override map retained for fluent API dotted size variants
('size.atLeast' etc.) and 'aspectRatioBetween' DSL keyword, which
are input conventions, not distinct predicates.

595 SDK + 57 E2E tests pass.
2026-05-22 12:46:41 -07:00
John Dvorak 1bc92e1f7d fix: CDP extraction concurrency + topology ID remapping + predicate completeness
CDP protocol fixes:
- session.ts: getDocumentRootNodeId() now pushes {depth:-1} full DOM tree
  (was shallow default, causing querySelectorAll to find zero nodes)
- extraction.ts: serialize resolveSelector calls (was concurrent Promise.all,
  CDP DOM.querySelectorAll is not safe for concurrent calls on same session)

Topology ID mismatch fixes (critical — backendNodeId vs solver subject ID):
- extraction.ts: add remapTopologyIds() — builds Map<backendNodeId,solverId>
  from world.subjects.domNodeId/ids, remaps all 6 topology arrays +
  clipping.subjectId + scroll.containerId
- topology.ts: createsStackingContext() now checks contain:paint|layout
  (both create stacking contexts per CSS spec, was missing)
- topology.ts: evaluateInStackingContext() handles unary (no reference)

Predicate completeness:
- predicates.ts: 3 new evaluators — intersects, touches, hasGap (indices 31-33)
- predicates.ts: escapeClippingChainOf replaced indeterminate stub with
  deterministic 2-ary evaluator (overflow + clip chain + ancestry checks)
- predicates.ts: attachedToScrollContainer arity 1→2, checks reference match
- predicates.ts: 7 aliases + 4 alignment aliases promoted to BUILTIN_PREDICATES

DSL grammar fixes:
- grammar.ts: isKeywordThatCanBePredicate() extended with all missing keywords
- lower-to-canonical.ts: add TopologyAssertion lowering (was silently dropped)
- compiler.ts: add intersects/touches/hasGap relation codes
- validator.ts: add option sets for new predicates
- lexer.ts: add intersects/touches/hasGap token kinds

Safety + infrastructure:
- joins.ts: MAX_CARTESIAN_TUPLES=100,000 guard with descriptive error
- extraction.ts: computeRequiredFacts() registers defaults + broadens topology gate
- package.json: add missing imhotep-state dependency to imhotep-playwright

Tests:
- 9 new predicate tests (intersects, touches, hasGap, escapeClippingChainOf)
- Convert stale separatedFrom/contains GAP tests to working assertions
- Add computeRequiredFacts topology gating tests (public.test.ts)
2026-05-22 10:20:06 -07:00
John Dvorak 92deb689cd v1.1.0: pooled runtime, 959 tests, production hardening (0 squash) 2025-08-15 10:00:00 -07:00