fix(engine,web): F1 bound every terminal replay (WI-125) - #668
Closed
thedancingdeveloper wants to merge 1 commit into
Closed
fix(engine,web): F1 bound every terminal replay (WI-125)#668thedancingdeveloper wants to merge 1 commit into
thedancingdeveloper wants to merge 1 commit into
Conversation
The stale warm reattach flood: when a client's resume cursor had aged out of the scrollback ring, snapshot_for_attach returned the FULL untrimmed ring with reset:true — up to 4 MiB parsed into an xterm that keeps 5000 lines, 4x worse than a cold attach, and above a screen the client already had stale. An oversized in-window delta had the same problem. Engine (pty.rs): snapshot_tail_bytes is now the replay budget on every path. A warm reattach whose cursor is retained and whose delta fits the budget is still returned byte-exact with reset:false; a delta that aged out OR exceeds the budget returns a ground-state-aligned tail of at most the budget with reset:true. The in-band resync path (tail_bytes=None) is unchanged. Web (api.ts): openAttach always sends snapshot_tail_bytes: REPLAY_TAIL_MAX_BYTES alongside resume_from, so warm reattaches are bounded too. Terminal.tsx already resets and clears its cache on any reset:true; the snapshot-start position arithmetic is extracted into snapshotStartPosition() so the re-anchor after a reset-following-a-resume is unit-tested (the client discards its stale cursor, re-anchors to scrollback_pos - scrollback_bytes, and resumes gap-free). Tests: - H1 (a)/(b) "before" flood assertions flipped to bounded (len <= budget, reset:true, ground-state aligned). - warm_attach_is_not_narrowed_by_a_tail_hint inverted to warm_attach_over_budget_is_a_bounded_reset; new warm_attach_within_budget_stays_a_byte_exact_delta keeps the reset:false byte-exact case. - web: snapshotStartPosition.test.ts; attachAuthFrame.test.ts updated for the always-sent budget. Verification: cargo test -p vogt-engine-server --test integration 104 passed; fmt + clippy clean; web typecheck clean; pnpm vitest 906 passed; scripts/check_docs.py clean. docs/ENGINE.md §5 documents the budget contract. WI-125. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UtEFLJAhLiq4NfZCN2vuBb
This was referenced Sep 9, 2026
Contributor
Author
|
Cleanup: superseded by the single promotion PR #676. All of this work is already integrated into |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second PR of the terminal-attach-budget initiative (WI-121). Stacked on #667 (H1) — its base is
feat/terminal-attach-h1-harness, so this diff shows only F1's changes; both land onfeat/terminal-attach-budget, nothing tomainuntil H3 is green. Merge #667 first (or merge this into the feature branch after it).The bug (WI-125)
When a warm reattach's resume cursor had aged out of the ring (a parked session produced more than the 4 MiB ring while away, or the cache was stale),
snapshot_for_attachreturned the whole untrimmed ring withreset:true— up to 4 MiB parsed into an xterm that keeps 5000 lines, 4× worse than a cold attach (capped at 1 MiB), and painted above a screen the client already had stale. An oversized in-window delta had the same problem.The fix
Engine (
pty.rs) —snapshot_tail_bytesis now the replay budget on every path:reset:false(an ordinary switch-away/switch-back still appends);reset:true;tail_bytes=None) → unchanged.Web (
api.ts) —openAttachnow always sendssnapshot_tail_bytesalongsideresume_from.Terminal.tsxalready resets + clears cache on anyreset:true; the snapshot-start position arithmetic is extracted tosnapshotStartPosition()and unit-tested, so the re-anchor after a reset-following-a-resume (discard stale cursor → re-anchor toscrollback_pos - scrollback_bytes→ resume gap-free) is pinned.Tests
large_stale_warm_reattach_*andfour_mib_ring_stale_reattach_*"before" flood assertions flipped to bounded (len ≤ budget,reset:true, ground-state aligned).warm_attach_is_not_narrowed_by_a_tail_hintinverted →warm_attach_over_budget_is_a_bounded_reset; newwarm_attach_within_budget_stays_a_byte_exact_deltakeeps thereset:falsebyte-exact case.snapshotStartPosition.test.ts;attachAuthFrame.test.tsupdated for the always-sent budget.Verification
cargo test -p vogt-engine-server --test integration— 104 passed;cargo fmt --check+clippy --testsclean.pnpm typecheckclean;pnpm vitest— 906 passed.scripts/check_docs.pyclean.docs/ENGINE.md§5 documents the budget contract (reset:truemay follow aresume_from).🤖 Generated with Claude Code
https://claude.ai/code/session_01UtEFLJAhLiq4NfZCN2vuBb