Split out from the #403 fixer work (the codex resize vector is fixed in #412). This is the separate opencode vector the coordinator flagged (typing-during-stream, "reconciler fired + repaired").
Reproduction
- Does NOT reproduce as an isolated workload:
npm run test:term-fidelity -- --cli=opencode with TERM_FIDELITY_WORKLOAD=typing-during-stream was 12/12 clean. It needs the accumulated full-matrix context (prior workloads / warmed state).
- Reproduces intermittently on the full opencode matrix (
--cli=opencode, all 6 workloads): ~2 in 10 runs, observed firing on both typing-during-stream and resize-mid-stream.
- Failure mode is a reconciler repair (telemetry-only):
[terminal] viewport diverged from broker screen; repainted from snapshot (repair #1). The matrix fails on any repair by design (to surface creation vectors); the grid self-heals.
Byte evidence (captured resize-mid-stream instance)
Using a raw-stream discriminator (tap onPtyChunk, replay the exact delivered bytes through a clean @xterm/headless at broker dims, diff vs broker):
rawBytes=621184 bufferType=alternate rawVsBroker=0 rawVsRenderer=0 verdict=RENDERER-INTERNAL
telemetry: [resize-mid-stream] viewport diverged from broker screen; repainted from snapshot (repair #1)
rawVsBroker=0 — the full delivered byte stream, replayed through a clean emulator, equals the broker screen exactly. Delivery is byte-clean end to end.
bufferType=alternate — opencode runs on the alternate screen.
What this EXCLUDES
Assessment (narrowing, not a pinned fix)
The transient divergence is renderer-internal: the live xterm's incremental rendering drifted from a faithful batch render of the same (clean) bytes, and the reconciler correctly repaired it from the broker snapshot. This is the AGENTS.md "diff-painting TUI preserves a one-time grid divergence" class the reconciler backstop was built for.
- resize-mid-stream: consistent with xterm reflowing during the resize storm differently than the broker PTY emulator, in the transient window before opencode's post-SIGWINCH repaint. opencode's diff-paint then skips cells it believes unchanged, so the divergence persists until the reconciler repairs. Plausibly inherent (the reconciler may be the correct/only handling), which would make the matrix's "fail on any repair" too strict for this class — worth a policy discussion.
- typing-during-stream (coordinator's cited case): NOT separately byte-captured yet. A pure-content live-vs-batch divergence would be more surprising (xterm's streaming parser is batch-equivalent for content), so this one may have a distinct creation vector (e.g. an input-echo / coalescing ordering interaction) and deserves its own capture.
Next steps
- Land the raw-stream discriminator + scroll-probe + telemetry-artifact byte capture into the term-fidelity harness (in the accompanying PR) so any future opencode repair auto-classifies DELIVERY-LOSS vs RENDERER-INTERNAL and dumps
raw.bin for the typing case.
- Capture a typing-during-stream repair with the discriminator; if
rawVsBroker=0 there too, investigate the renderer write-path ordering under concurrent input+stream; if it's the inherent reflow class, decide whether the matrix should tolerate a bounded reconciler repair rate for alt-screen TUIs.
Isolated brokers only; port 3889 untouched; all work on a git worktree.
Split out from the #403 fixer work (the codex resize vector is fixed in #412). This is the separate opencode vector the coordinator flagged (
typing-during-stream, "reconciler fired + repaired").Reproduction
npm run test:term-fidelity -- --cli=opencodewithTERM_FIDELITY_WORKLOAD=typing-during-streamwas 12/12 clean. It needs the accumulated full-matrix context (prior workloads / warmed state).--cli=opencode, all 6 workloads): ~2 in 10 runs, observed firing on bothtyping-during-streamandresize-mid-stream.[terminal] viewport diverged from broker screen; repainted from snapshot (repair #1). The matrix fails on any repair by design (to surface creation vectors); the grid self-heals.Byte evidence (captured resize-mid-stream instance)
Using a raw-stream discriminator (tap
onPtyChunk, replay the exact delivered bytes through a clean@xterm/headlessat broker dims, diff vs broker):rawVsBroker=0— the full delivered byte stream, replayed through a clean emulator, equals the broker screen exactly. Delivery is byte-clean end to end.bufferType=alternate— opencode runs on the alternate screen.What this EXCLUDES
rawVsBroker=0.erasePredictionRegion(relay#1326) — opencode is alt-screen, and the echo-router kills predictions on alt-screen (onUserInput→if (isAltScreen) killPredictions()). Predictions never engage here.#412is a no-op for opencode.Assessment (narrowing, not a pinned fix)
The transient divergence is renderer-internal: the live xterm's incremental rendering drifted from a faithful batch render of the same (clean) bytes, and the reconciler correctly repaired it from the broker snapshot. This is the AGENTS.md "diff-painting TUI preserves a one-time grid divergence" class the reconciler backstop was built for.
Next steps
raw.binfor the typing case.rawVsBroker=0there too, investigate the renderer write-path ordering under concurrent input+stream; if it's the inherent reflow class, decide whether the matrix should tolerate a bounded reconciler repair rate for alt-screen TUIs.Isolated brokers only; port 3889 untouched; all work on a git worktree.