Fix approval overlay pushing the prompt box off screen on short terminals - #597
Merged
TheGreatAxios merged 2 commits intoAug 24, 2026
Conversation
TheGreatAxios
force-pushed
the
cl-5750-the-approval-surface-pushes-the-prompt-box-off-screen-and-renders
branch
from
August 24, 2026 05:12
62e475d to
1a063d4
Compare
TheGreatAxios
enabled auto-merge (squash)
August 24, 2026 05:21
…ompt box visible on short terminals The decision overlay's context body used a fixed 8-line budget regardless of terminal height. On a short terminal the resulting chrome could exceed the overlay's own render minimum (border + title + header + at least one choice), so the geometry resolver's "nothing left to collapse" fallback accepted an overlay smaller than that minimum — the box rendered past its assigned rows or lost every choice, while the prompt box stayed on screen but unanswerable. The context budget is now computed from the terminal height, the prompt floor, and the overlay's fraction cap, shrinking (down to 0 lines) so the header and at least one choice row always fit. Recomputed on resize too.
…body text applyOverlayBodyText cached every opened overlay's raw body text for a resize to re-shape against, but a palette stacked over an open permission or operator overlay called it too, with its own (empty) body — overwriting the approval's cache. Popping the palette restores overlayBodyLines from the snapshot but not this cache, so a resize right after re-shaped the approval from the palette's stale empty string, blanking its body entirely (header included). The cache write is now scoped to decision overlays, since a palette never reads it back. Also tightens decisionContextBudget's docblock and a test comment that overclaimed the guarantee held below 10 rows; the resolver's own collapse fallback (unrelated to this budget) still has a gap below that floor.
TheGreatAxios
force-pushed
the
cl-5750-the-approval-surface-pushes-the-prompt-box-off-screen-and-renders
branch
from
August 24, 2026 05:23
d928db5 to
d7839db
Compare
This was referenced Aug 24, 2026
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.
Closes CL-5750.
Observed before the fix (permission overlay, 80-col terminal,
src/tui/shell.tsin-flow layout with a live transcript):Root cause:
composeDecisionBody's context section used a fixed 8-line budget (DECISION_CONTEXT_ROWS) regardless of terminal height. On a short terminal, the resulting overlay chrome (border + title + header + 8 lines of context) could exceed what the geometry resolver could ever grant (bounded by both the prompt's floor andOVERLAY_MAX_FRACTION). When the resolver's collapse loop ran out of zones to shrink, its fallback path (resolve.ts, "nothing left — accept best effort") silently accepted an overlay height below the overlay's own stated render minimum, instead of shrinking the overlay's own content. That produced a box whose fixed body text alone ate the whole frame, leaving no room for a single choice.Fix:
src/tui/shell.ts:decisionContextBudgetnow computes the context-line budget from the terminal height, the prompt's floor (PROMPT_BASE_ROWS), the overlay's fraction cap (OVERLAY_MAX_FRACTION), and one guaranteed choice row — shrinking down to 0 context lines on the shortest terminals. Recomputed on resize (overlayRawBodyTextis now cached so a live resize re-shapes the body instead of leaving it stuck at whatever it opened with).src/tui/overlay-body.ts:composeDecisionBodynow accepts a budget of 0, meaning the context section (and its surrounding blank rows) is skipped entirely rather than forced to cost at least one row it cannot afford.What wins when the terminal is too short for both: the approval choices win. The header (which tool / which question) is never dropped, but everything below it — the command detail, scope descriptions, "N more lines" hints — shrinks first, down to nothing, so at least one choice row and the prompt box (at its 3-row floor) are always painted together. An approval the operator cannot answer deadlocks the whole session, so it outranks readability of the context.
Tests added (
src/tui/approval-prompt-visibility.test.ts): for terminal heights 10, 12, 15, 24, and 40 rows —One existing CL-5694 overflow test asserted that a collapsed-command hint always appears in the rendered overlay body even at the shortest supported height; that assertion is now relaxed to check the hint against the raw (unrendered) body string instead, since the new priority is choices-over-context-detail at extreme heights — the hint's own source text is unaffected, only what gets painted when the terminal is too short for both.
bun run checkis green (lint 0 errors,tsc --noEmitclean, build succeeds, 5377 tests pass).