docs(plans): add viewport-relative cursor and server-side sub-status plans - #537
Open
RonenMars wants to merge 3 commits into
Open
docs(plans): add viewport-relative cursor and server-side sub-status plans#537RonenMars wants to merge 3 commits into
RonenMars wants to merge 3 commits into
Conversation
…plans PlanCup fixes absolute cursor positioning in tb-mobile's terminal emulator, which resolves CSI H/f/A/B against the whole scrollback grid rather than the 40-row viewport the TUI paints against. One footer repaint past 41 rows loses two transcript lines and mangles a third, and terminal_replay seeds ~200 rows on every subscribe, so it fires on every session resume. PlanIndicator replaces the closed PR #647 by deriving agent phase in the streamer, where a correct headless screen and a throttled scrape pass already exist, rather than on the client against the broken emulator. Both plans carry their full review logs, including two review questions that each caught defects after two sign-offs: run any input used to reject an alternative against the accepted design, and ask what reused machinery already does on every call.
This was referenced Aug 12, 2026
…am findings A capture of Claude Code v2.1.228 at the streamer's real 120x40 geometry validates PlanCup against a reference emulator: the fix reproduces `@xterm/headless` output where `origin/main` does not, and absolute cursor moves address a maximum row of exactly 40, so `VIEWPORT_ROWS = 40` is measured rather than assumed. Three findings taken from that capture were wrong and are corrected here. `CSI 2J`, `CSI r` and `ESC 7`/`ESC 8` were each read as firing ~30 times mid-turn and each proposed for promotion out of the deferred queue; all three are one startup sequence replayed once per snapshot, because every snapshot is a full ring-buffer dump. Nothing in the deferred family is reachable mid-turn, so the queue is downgraded uniformly rather than reordered. The capture README is committed alongside because the raw bytes live outside any repo and two PRs cite them.
This was referenced Aug 12, 2026
Registers what is done, what is blocked, and what remains across both plans and both repos, so the state does not live only in a conversation. Records the deliberately-not-filed decisions too — conditional wire geometry, capture housekeeping, the stale worktree — so they are not re-derived. Carries the method notes this work earned: run the test that killed the thing you are replacing before proposing the replacement, and ask per statistic whether it is sensitive to how the evidence file was assembled.
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.
Two implementation plans, each validated across multiple review rounds with every load-bearing claim independently reproduced before it was written down.
PlanCup — viewport-relative cursor positioning (tb-mobile)
services/virtual-terminal.tsresolves absolute cursor moves against its whole append-only scrollback grid instead of the 40-row viewport the TUI paints against, so every footer repaint lands in the middle of the transcript.Measured on
origin/main: one repaint after 41+ seeded rows loses two transcript lines and mangles a third into"tr✻ Brewing… (12s · ↑ 3.4k tokens)", and a spinner repeats it for the whole turn.It fires on every session resume, not only long sessions, because
terminal_replayseeds ~200 rendered rows before the first live frame arrives.Scope is the four cursor-moving handlers —
H,f,A,B— chosen by two independent principles that select the same set: handlers that move the cursor become viewport-relative, handlers that mutate grid structure do not; and only defects with measured impact are in.The prototype is 152/152 across eleven terminal suites with
tscclean and zero test rewrites.PlanIndicator — server-side agent sub-status (tb-streamer + tb-mobile)
Replaces the closed #647, which derived the indicator on the client by scraping mobile's own emulator and never worked because of the bug above.
The streamer already runs a correct headless screen at the geometry the TUI paints against, already scrapes it on every chunk, and already ships
model/effort/permissionModeoff the same footer.The plan carries the clearing rule that keeps the phase from latching, a bespoke scoped frame rather than a session copy, and an always-emit-null contract.
Review notes
Two questions each caught a defect that had already cleared two sign-offs, and both are recorded in the plans:
mainlost none — and then caught a phase field that latched exactly as #647's pill did.!= nullguard silently drops an explicit null, and anelapsedMsthat recomputes every call and would have re-rendered the app ~3x/second for a whole turn.Line-anchor drift occurred twice during review, so every
path:linereference in both documents was extracted and machine-checked against the cited file.Docs only — no code changes.