v9.1.0 — lazy TransactionBuffer + read-tracking policy
Perf release: backlog #13 + #14
#13 — truly lazy TransactionBuffer
The buffer (2× full-state structuredClone) is constructed on a stage's first WRITE — never on reads, never by commit. A third hidden full-state clone (the empty-commit applyPatch replay) is gone too. Measured (Apple M2, 1MB shared state): first tracked read 4.97ms → 3µs; per no-touch stage 10.19ms → µs-scale.
First-touch anchor (adversarial-review finding): the net-change diff base is anchored at the stage's first touch via a zero-cost immutable state-view reference — byte-identical to the eager engine sequentially AND under parallel forks (reachable via setGlobal/subflow output mapping inside a fork branch). See firstTouchState() in StageContext and docs/design/commit-change-semantics.md.
#14 — read-tracking policy (readTracking)
new FlowChartExecutor(chart, { readTracking: 'full' | 'summary' | 'off' }) (or executor.setReadTracking). Default 'full' is byte-identical to 9.0.0. 'summary' stores cheap type/size/preview markers; 'off' removes the last per-read clone — 50 tracked reads of a 1MB value: 130ms → 30ms ('summary') → 7µs ('off'). Narrative and ScopeRecorder.onRead identical in every mode. Example: examples/runtime-features/read-tracking/01-basic.ts.
Suite: 2847 tests green. Additive API only — no breaking changes.
🤖 Generated with Claude Code