registry.ts: Add optional styles and fragments table types to the
solver's GeometryWorld. Previously these were attached via
(world as any).styles / .fragments, bypassing the type system.
extraction.ts:
- remapTopologyIds: accept topologySubjectIds as explicit parameter
instead of reading (world as any)._topologySubjectIds and deleting
it post-remap. Eliminates 3 smuggling accesses (read, set, delete)
- All worldAny.styles / worldAny.fragments / worldAny.strings /
worldAny.transforms / worldAny.matrices assignments now use
typed world.xxx access. worldAny variable removed entirely.
- attachMeasuredChWidths: use world.styles directly.
- (result.world as any).env mutation replaced with typed
result.world.env assignment.
- (sizeWorld as any).styles replaced with typed access.
predicates.ts: Replace all 3 (world as any).styles inline type-assert
reads (getSubjectFontSizePx, getRootFontSizePx, getSubjectChWidthPx)
with direct world.styles?.xxx access. No runtime behavior change.
Zero (world as any) casts remain in extraction.ts or predicates.ts.
658 tests pass.
predicates.ts (missing-fact discipline):
- getTopologyValueBySubject: return -1 sentinel instead of ?? 0
when topology data is missing/unset. NaN and negative values
also treated as missing. Previously returned 0 which was
indistinguishable from root subject ID.
- clippedByPredicate: return 'indeterminate' when clippingRoot < 0
- inStackingContextPredicate: return 'indeterminate' when sc < 0
or refSC < 0 (both subject and reference). Previously treated
missing data as false — a silent wrong answer.
- attachedToScrollContainerPredicate: return 'indeterminate' when
scrollContainer < 0
- escapeClippingChainOfPredicate: return 'indeterminate' when
clippingRoot < 0
extraction.ts (cleanup visibility):
- Promote fast-geometry and CDP cleanup failures from console.debug
(invisible during test execution) to console.warn. Contaminated
pages are now diagnosable without debug-log inspection.
658 tests pass.
predicates.ts: Replace defaultPredicatesRegistered boolean guard with
sentinel predicate check inside the registry. registerDefaultPredicates()
is now always safe to call — no module-scope flag that can drift out
of sync with the actual registry state. clearPredicateRegistry() no
longer needs to manually reset a flag.
extraction.ts:
- Replace compatibilityWarningEmitted process-singleton boolean with
WeakSet<ImhotepUi> (warnedUis). Each ImhotepUi instance now gets its
own compatibility warning, fixing the bug where two pages would share
a single warning gate.
- Export resetExtractionPathStats() for test isolation of fast-path
and CDP fallback counters.
598 SDK + 3 conformance + 57 E2E = 658 tests pass.
lower-to-canonical.ts: clauseEquivalent now compares compoundOperator
and compoundGroupId. Previously, compound assertions with different
operators (.and vs .or) were considered equivalent.
fol-compiler.ts: adaptGrammarFormulaToLogicAst validates node.kind
against known formula kinds (forall/exists/and/or/not/implies/predicate)
before passing through as FormulaNode. Previously any object with a
'kind' property was blindly cast.
predicates.ts / registry.ts: @deprecated tags on globalPredicateRegistry
and globalClauseRegistry. Both are still functional but consumers should
transition to explicit injection via LogicEngineOptions / EvaluationOptions.
454 solver+DSL tests pass, zero regressions.
geometry-cache.ts: replace 5 empty catch blocks with console.warn
- statSync failure, rmSync failure (x2), readCachedWorld failure,
readCachedExtractionResult failure were all silently swallowed.
Now emit context-bearing warnings so stale/corrupt caches are visible.
predicates.ts: replace __boxIndex as any mutation with WeakMap
- getBorderRect used (world as any).__boxIndex to cache a subject-to-
box-index map on the world object. Replaced with module-level WeakMap
that auto-collects when the world is GC'd. Eliminates 2 as any casts.
extraction.ts: serialize materializeSemanticSelector + debug cleanup
- 3 Promise.all sites over page.evaluate changed to sequential for..of
to eliminate DOM modification race conditions.
- 2 .catch(()=>{}) cleanup blocks now use console.debug so failed
cleanup is traceable when debugging.
- resolveViewport catch now emits console.warn on zero-viewport fallback.
648 SDK + 57 E2E tests pass.
All 27 BUILTIN_PREDICATES now have real evaluators. The
makeNotImplementedPredicate factory and its IMH_FEATURE_NOT_YET_IMPLEMENTED
path were the last remaining NYI scaffolding — no caller existed for it.
IMH_FEATURE_NOT_YET_IMPLEMENTED diagnostic code kept in the taxonomy
as a future fallback, but no evaluator produces it.
- CRITICAL: escapeClippingChainOf now has an evaluator (returns indeterminate
with clear diagnostic — full implementation requires fragment-level bounds
analysis). Previously parsed but silently produced IMH_EVALUATOR_MISSING.
- attachedToScrollContainer added to BUILTIN_PREDICATES with evaluator
(checks world.topology.scrollContainerOf). Was only in legacy engine.
- aspectRatio added to BUILTIN_PREDICATES with evaluator (compares
width/height ratio against min/max bounds). Was only in legacy engine.
- Fix all BUILTIN_PREDICATES index references shifted by new entries
(beside 17→20, nextTo 18→21, adjacent 19→22, touching 20→23,
near 21→24, under 22→25, within 23→26, separatedFrom 16→18,
inStackingContext 15→17).
- Register attachedToScrollContainer, escapeClippingChainOf, aspectRatio
in registerDefaultPredicates.
- Zero NYI/not-implemented predicates remain in the registry.
- Change BUILTIN_PREDICATES[15] arity from 1 to 2 to match binary usage
in the FOL compiler and topology engine
- Update evaluator to handle both unary (does element have stacking context)
and binary (do both elements share the same stacking context) cases
- Binary comparison: both elements must have a valid stacking context
AND their stackingContextOf values must match
- Aligns predicate semantics with the legacy engine in solver/topology.ts
and the topology query layer's inStackingContext(graph, subj, ref?) API
- Replace makeNotImplementedPredicate stubs for leftAlignedWith,
rightAlignedWith, topAlignedWith, bottomAlignedWith with real
evaluators delegating to alignedWithPredicate with axis option
- Update logic-engine.test.ts to expect real evaluation results
instead of IMH_FEATURE_NOT_YET_IMPLEMENTED
- insidePredicate: add hasClippedOverflow=1 when reference element
clips its content (contain:paint or overflow:hidden) and the
subject overflows beyond the reference bounds
- containsPredicate: same, checking the subject (container) clips
- Reads world.clipping table to determine if the container clips
- Safe when clipping data is absent (unit test fixtures)