Two O(N)-per-tick refolds remained on the MainActor after the 0.4s throttle
and structural toolGroupSignature landed:
1. AppStore.regenerateToolGroupSummaries (and its staleness guards +
open-time history baseline) re-derived summarizable units by refolding
the ENTIRE open transcript per invocation — 10-100ms+ on 30k-event
sessions. The store now owns a dedicated IncrementalTranscriptProjection
and derives units via summarizableUnits(events:), a second lazily-primed
consumer of the projector's existing seam: every display-valid seal seam
is units-valid (the units fold breaks tool runs at strictly more rows,
and seams only ever land after hard separators common to both folds).
Each consumer folds only when requested, so the view's instance never
folds units and the store's never folds display items or lock lines.
2. IncrementalTranscriptProjection capped its watermark at an open subagent
Task span's firstRef, so a long run refolded its whole (unbounded) scope
on every display tick — O(scope²) across the run. Three additions bound
the per-read cost to what actually changed:
- TailCache: the unsealed tail's partition (topLevel/byParent/parentOf)
is appended to per read instead of rebuilt.
- ScopeChildProjection: each subagent scope seals its provably closed
children (result-fenced tools, superseded messages) under the same
seam rules, recursively for nested scopes; sealed cards' descendant
scopes are cursor-snapshotted and a late event into a result-fenced
scope triggers a scope-local self-healing refold.
- WatermarkHint: when a full scan seals nothing, it records the pinning
open entities; later reads validate only new events against the pins
(sealed-id fence and seq monotonicity still checked per event), so a
pinned seam costs O(new) instead of O(tail) per tick. The fast path
never seals, so a missed trigger can only delay sealing, never corrupt
output.
Exact-output preserved: the equivalence suite now also asserts
summarizableUnits(prefix) == TranscriptProjection.summarizableUnits(prefix)
for every prefix on both a shared and a units-only instance, plus new
scenarios (long open scope with sealing/full-scan hooks, fan-out straggler,
open grandchild recursion, late-event self-heal, late units priming, root
flip leaving units intact) and open-scope fuzz. 27/27 projection tests green.
Co-Authored-By: Claude Fable 5 <[email protected]>