docs: one gateway path for live viewing, durable rows for history#252
Conversation
Records the measured streaming model and pins the property the docs claim. Invariant 6 gains a "Live viewing vs history" section: the platform session gateway is the only live-viewing mechanism, the durable assistant row is the only history mechanism, and the gateway's hot buffer stays short BY DESIGN because its cost is TTL x viewers x bytes-per-event (measured 814 B/event, 27.3 GiB at 10k concurrent watched sandboxes, swinging to 198 GiB purely on answer length). Raising bufferTtlMs is the failure mode, not the fix. Both platform lanes now fan out to the session bus, but only on agent-dev-container's develop -- #4114 is not on main, so production still delivers 0 turn events on the run/stream (detach) lane. Documented as merged-not-deployed rather than done. /turn-stream is NOT retired. Its broadcast/replay half is superseded by the gateway for sandbox turns, but createDurableTurnLock is single-flight mutual exclusion the gateway does not provide -- the gateway's only lock is SubscriptionMutex, an in-process per-instance guard that goes silent across instances. /stream gets its own row, correcting export names and marking the turn buffer as the sandbox-free lane only. tests/chat-routes/lane-portability.test.ts pins createSandboxChatProducer at 1.000x streamed and persisted across eight lane shapes. The two lanes disagree on text semantics -- run/stream sends deltas, the message lane re-sends the whole accumulated part -- and incremental persistence writes the draft before the terminal receipt, so the pre-receipt projection has to be right on its own. Proven failable: removing the reconciliation in textDelta inflates a five-update turn to 3.133x and the probes fail.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — ed5f6eda
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
tangletools · auto-approval · reason: drewstone_author · 2026-07-25T02:17:55Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Concerns | 0 (none) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 133.9s (2 bridge agents) |
| Total | 133.9s |
💰 Value — sound
Docs correct a real live-vs-history conflation and add a focused regression test pinning the pre-receipt draft projection that incremental persistence (#250) made load-bearing; no duplication or better approach found.
- What it does: Three edits: (a) AGENTS.md invariant 6 gains a 'Live viewing vs history' section — live viewing = platform session gateway, history = durable assistant row written incrementally (#250), single-flight lock = createDurableTurnLock; documents the measured hot-buffer cost (814 B/event, 27.3 GiB at 10k) and that raising bufferTtlMs is the failure mode; flags agent-dev-container #4114 as merged-to-devel
- Goals it achieves: 1) Stop products/fleet apps from hand-rolling a Durable Object to broadcast sandbox turns by recording that the gateway owns live viewing and the durable row owns history. 2) Pin the exact invariant the docs now claim (1.000x across both lanes, pre-receipt), so the textDelta reconciliation can't silently regress and inflate a durable row 3.133x without a failing test. 3) Correct a prior doc that c
- Assessment: Good change, in the grain of the codebase. The docs fix a real conflation: the old ARCHITECTURE.md row ('Durable turn replay + live-viewer fanout + the single-flight turn lock') pointed everything at turn-stream, which is wrong now that the gateway and incremental persistence exist. The split into three rows is accurate and matches the code (textDelta reconciliation at sandbox-producer.ts:122, dra
- Better / existing approach: none — this is the right approach. Checked for duplication: the existing tests/chat-routes/sandbox-producer.test.ts (797 lines) broadly tests producer behavior (tools, usage, reasoning, severance, interactions) but only touches delta-vs-snapshot once, with a receipt, for one part id. The pre-receipt draft invariant — the one the docs now claim and that #250 made critical — is not asserted anywhere
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content
🎯 Usefulness — sound
A focused guard test plus accurate docs that pin a real, load-bearing property of the production chat producer — lane-portable text projection across the two platform lanes.
- Integration: The test exercises createSandboxChatProducer, which is the actual producer seam for createChatTurnRoutes (src/chat-routes/turn-routes.ts:140) and runDetachedTurn (src/chat-routes/detached-turn.ts:319), and the documented reference producer in examples/chat-app.md:84. It is deeply reached in production, not orphaned. The test's synthetic event shape ({type:'message.part.updated', data:{part, delta}
- Fit with existing patterns: Follows the repo's established pattern of focused guard tests for documented invariants (e.g. tests/theme/tokens-contract.test.ts pins the theme contract the docs claim). It complements, not duplicates, the existing 30 KB sandbox-producer.test.ts by framing cases by platform lane (run/stream deltas vs message-lane snapshots) rather than by producer feature. The docs section it pins (AGENTS.md 'Liv
- Real-world viability: The 8 cases cover both lane semantics (delta vs snapshot), with/without part id, with/without terminal receipt, whole-message echo, and a transcript split across two part ids — and a dedicated test asserts the pre-receipt draft projection is already correct, which is precisely the hazard #250 incremental persistence creates (the durable row is written before the terminal result). The reconciliatio
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
No concerns — sound change, no better or existing approach found. ✅
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
|
Overlap heads-up from #253 ( #253 is the code-side half you don't have: One thing I took from you, verified independently: adc #4114 is merged to One place I'd push back: your Merge order: yours is ahead in the CI queue. If it lands first I'll rebase #253, drop my |
Records the streaming model that the live 4-arm A/B proved, and pins the one property the docs now claim.
The model
lastEventIdreplay)/chat-routescreateDurableTurnLock(/turn-stream)No Durable Object for sandbox live-viewing. The hot buffer stays short by design: its cost is
TTL x viewers x bytes-per-event— measured 814 B/event, 27.3 GiB at 10k concurrent watched sandboxes, and 198 GiB at the long-answer end because every part update re-sends the whole accumulated part (79.7% snapshot redundancy). RaisingbufferTtlMsbuys history at permanent linear memory cost. It is the failure mode, not the fix.What is NOT claimed as done
agent-dev-container#4114 (run/stream lane publishes to the session bus) is merged todevelop, not onmain. Productionsandbox.tangle.toolsstill delivers 0 turn events on the detach lane. The docs say merged-not-deployed./turn-streamis not retiredIts broadcast/replay half is superseded by the gateway for sandbox turns.
createDurableTurnLockis not — the gateway's only lock isSubscriptionMutexinsse-bridge.ts, an in-process per-instance guard that goes silent across instances. gtm-agent'sSessionStreamDOalso uses the base for product seams (Vault endpoints, interaction rendezvous, persistence queue) that have no gateway analogue.New guard test
tests/chat-routes/lane-portability.test.tspinscreateSandboxChatProducerat 1.000x streamed and persisted across eight lane shapes. The lanes disagree on text semantics — run/stream sends deltas, the message lane re-sends the whole accumulated part — and incremental persistence writes the draft before the terminalresultreceipt, so the pre-receipt projection must be correct on its own rather than relying on the receipt to rescue it.Proven capable of failing: removing the snapshot reconciliation in
textDeltainflates a five-update turn to 3.133x and the snapshot probes fail, while the delta probes stay green.Verification
pnpm typecheckpnpm testagent-docs --checkdocs are fresh, exit 0origin/maingit merge-tree)