feat(web): F4 dormant terminal panes — keep the socket open, buffer instead of re-streaming (WI-128) - #674
Closed
thedancingdeveloper wants to merge 1 commit into
Conversation
Switching away from a terminal parked its socket (closed it); returning reattached and re-streamed everything produced while away (bounded by F1, but still a re-stream, and the source of the switch-away flood). F4 keeps the socket open for inactive panes and stops writing to xterm — output buffers into the in-memory ring — so returning renders the buffered delta with no reattach. - terminalDormancy.ts (pure, unit-tested): a per-document budget of MAX_DORMANT_SOCKETS (4), most-recently-active kept, the rest evicted to parking; and planDormantResume() deciding delta-write vs reset+tail on return. - Terminal.tsx state machine: active | dormant (socket open, buffering, no "Suspended" banner — e.g. the unfocused half of a split) | parked (socket closed, "Suspended"). suspend() goes dormant if the budget allows and the pane is past its snapshot, else parks; activate() resumes a live dormant socket in place with a SYNCHRONOUS catch-up (flip the flag before any write so live frames queue in order — no gap), or reconnects if the socket died while dormant (mobile OS reclaim). Preserves the no-second-socket invariant and the cache-load initial-connect path; releases the slot on park and unmount. - Docs: USER_GUIDE (dormant vs Suspended) and ENGINE.md (client note: dormant panes are extra broadcast subscribers, bounded). Tests: terminalDormancy.test.ts (budget, MRU eviction, release, resume plan); the setup resets the shared registry between tests. Verification: pnpm typecheck clean; pnpm vitest 947 passed (9 new); pnpm build bundles. LIVE ACCEPTANCE STILL OWED: the switch-away-under-load symptom-1 assertion is H3's live spec (WI-124) against a real stack — not reachable from an agent session — so review this against that before merge. WI-128. 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 |
thedancingdeveloper
deleted the
feat/terminal-attach-f4-dormant-panes
branch
September 9, 2026 20:59
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.
Eighth PR of the terminal-attach-budget initiative (WI-121). Stacked on #673 (D6); all land on
feat/terminal-attach-budget.What this does (F4 / WI-128)
Switching away from a terminal parked its socket (closed it); returning reattached and re-streamed everything produced while away (bounded by F1, but still a re-stream — the switch-away flood). F4 keeps the socket open for inactive panes and stops writing to xterm — output buffers into the in-memory ring — so returning renders the buffered delta with no reattach and no re-stream.
terminalDormancy.ts(pure, unit-tested) — a per-document budget ofMAX_DORMANT_SOCKETS(4), most-recently-active kept, the rest evicted to parking; andplanDormantResume()deciding delta-write vs reset+tail on return.Terminal.tsxstate machine —active | dormant | parked. A dormant pane has an open socket, buffers, and shows no "Suspended" banner (e.g. the unfocused half of a split keeps its screen).suspend()goes dormant if the budget allows and the pane is past its snapshot, else parks.activate()resumes a live dormant socket in place with a synchronous catch-up (flip the flag before any write, so live frames queue in order — no gap), or reconnects if the socket died while dormant (a mobile OS reclaim). Preserves the no-second-socket invariant and the cache-load initial-connect path; releases the slot on park and unmount.Tests
terminalDormancy.test.ts— budget, MRU eviction, release, and the resume plan. The shared registry is reset between tests insetup.ts.Verification & the one gap
pnpm typecheckclean;pnpm vitest— 947 passed (9 new);pnpm buildbundles.🤖 Generated with Claude Code
https://claude.ai/code/session_01UtEFLJAhLiq4NfZCN2vuBb