Skip to content

One parse / one write path + write-path consistency check - #385

Merged
Firehed merged 6 commits into
mainfrom
slice/S3.4
Jul 31, 2026
Merged

One parse / one write path + write-path consistency check#385
Firehed merged 6 commits into
mainfrom
slice/S3.4

Conversation

@Firehed

@Firehed Firehed commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Slice

  • Slice: S3.4 — One parse / one write path + consistency check
  • Plan step: Plan 0002 Step 3a(iv) (docs/architecture/0002-execution-plan.md)
  • RFC: 0001-foundational-architecture.md §4.3 (Read/Write Segregation — exactly one write path), §5.2 (SymbolSink write contract)

What this does

Collapses the sink's double write into one parse feeding both stores, and adds a
consistency guard so the two structures cannot silently diverge.

Before, DocumentSymbolSink::write() registered class metadata and indexed symbols
via two independent code paths, each of which parsed the document (the content-keyed
parse memo made this one actual parse, but two parse calls / two extraction
entries). Now the sink parses once and feeds that single AST to both the class-lookup
registration and the symbol index:

  • DocumentIndexer::indexParsed(TextDocument, array $ast) indexes a supplied AST
    instead of reparsing; index() is now parse()indexParsed(). The sink drives
    the index through indexParsed, so the indexer no longer reparses.
  • The two stores stay distinct structures (Plan 0002 §5.5 permits this — ClassInfo
    for lookup, lightweight Symbols for enumeration/search), but are written
    transactionally from the one AST.

Because the Step P parity harness compares only observable outputs, an internal
divergence between the two structures could pass parity. assertStoresAgree() guards
the invariant directly: every class-like registered for lookup must also be present in
the symbol index, so a name is never resolvable through one surface yet invisible to
the other. The check is one-directional — the index is a legitimate superset (it also
records class-likes declared inside conditional/nested statements, which the top-level
lookup registration does not), so the reverse would false-positive on valid PHP. The
divergence branch is an unreachable LogicException.

This discharges the Teardown-ledger row "Step 2 facade hides today's double write
(§5.5) → Step 3a(iv)"
: the scaffolding was the double write inside the sink (S3.3
already replaced the illustrative DelegatingSymbolSource with DocumentSymbolSink),
now collapsed.

Behavior-preserving (Step 3a): the Step P parity goldens (class-like lookup,
childrenOf, prefix-search, write-path symbol state) are unchanged and the full suite
is green. The consistency guard is a new internal invariant, so it carries its own
unit coverage rather than a parity golden.

Acceptance criteria

  • One parse per didOpen/didChange write, feeding both stores (the sink parses; the indexer no longer reparses — indexParsed)
  • The two structures may stay distinct, written transactionally from the same parse (§4.3, Plan 0002 §5.5)
  • Consistency check that both stores are written from the same parse and agree (assertStoresAgree)
  • Teardown-ledger row (Step 2 double write, §5.5) discharged
  • Behavior-preserving: Step P parity goldens unchanged; full suite green

Candidate closes

None — the manifest lists no Closes for S3.4.

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.25%. Comparing base (98a7cea) to head (ae52373).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main     #385      +/-   ##
============================================
+ Coverage     98.23%   98.25%   +0.02%     
- Complexity     1725     1728       +3     
============================================
  Files           111      111              
  Lines          4356     4360       +4     
============================================
+ Hits           4279     4284       +5     
+ Misses           77       76       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@Firehed
Firehed merged commit f92844e into main Jul 31, 2026
7 checks passed
@Firehed
Firehed deleted the slice/S3.4 branch July 31, 2026 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant