Skip to content

os/v3/puppy: the console TUI never draws half a block, so a short window keeps all nine actions - #983

Closed
bong-water-water-bong wants to merge 2 commits into
mainfrom
os/v3-tui-short
Closed

bong-water-water-bong wants to merge 2 commits into
mainfrom
os/v3-tui-short

Conversation

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator

Closes #982. Stacked on #981 (os/v3-tui-qrfit, same function) — merge #981 first; this branch is #981 + one commit,
so a rebase onto main after #981 lands is a no-op.

Root cause

The log pane's height was a bare remainder with a 1-row floor, and nothing bounded the total:

let log_h = h.saturating_sub(top.len() + menu.len() + footer.len()).max(1);

When top + menu + log + footer > h, the Layout::vertical Length constraints are satisfied by clipping the END of
the frame — which is the MENU. The code's comment already claimed the menu is "always whole"; that was only true at the
two sizes with committed fixtures.

Measured before (merged main, static binary, pty, TERM=linux, blank key)

size actions on screen Reboot / power off 8 Logs
80x18 7 absent absent
100x20 8 absent present

Reboot / power off is a gate string (vm-check.sh's U2 menu row, menugate) — safe on tty1 at 80x25, missing on
any ssh window shorter than 25 rows. At 40x15 only actions 1-5 were drawn, below an empty LOGS newest title, and the
footer still said "1-9 actions".

After

The nine menu rows and the footer are fixed (never trimmed). Everything above them gives way in a fixed order, whole
rows at a time: the status facts first (they are the "technical information"), then the log pane (a title needs
a row under it — a 1-row pane would only show the tail of a wrapped record, " tokens, 330.75 tok/s)", which reads as
broken output), then the CONNECT block's own tail. A one-row leftover goes back to the block above, so the footer
stays on the last row.

80x18 after — all nine actions, footer whole, log pane gone rather than half:

 MENU --------------------------------------------------------------------------
1 Show the API key
...
8 Logs (Lemonade, kernel)
9 Reboot / power off
1-9 actions arrows scroll f newest r refresh 8 logs q quits

100x20 after keeps a one-row log pane on top of the nine actions; 80x25 and 240x67: both committed snapshots are
byte-identical
and renders_at_the_two_console_sizes passes unmodified.

The diff

draw() computes avail = h - (menu + footer), drops the facts if top + facts + 2 > avail, keeps the log pane only
when it is a title plus a row, and truncates the CONNECT block to the rest — arithmetic rather than a pop loop, so the
1-row case can hand its row back. New test a_short_window_keeps_the_nine_actions_and_the_footer_whole sweeps
40x15, 60x15, 80x18, 80x20, 80x24, 100x20, 120x16, 160x13, 240x12, 240x67 and requires: frame height == terminal, all
nine actions present, the footer whole on the last row(s), and no LOGS title without a log row under it.

the_qr_never_costs_another_block_a_row (from #981) is adjusted in one place, not weakened: its "the panel grid is
present at every width >= 100" becomes "if the code is on this frame, the panel grid is present" — because a frame
too short for the panels now drops them by design (the nine actions win), which is not something the QR caused.

cargo test 45/45, clippy -D warnings clean, fmt --check clean, tools/copyright.py --check rc 0,
build-static.sh ok — 7e909e05b2725f4a, 1,554,688 B, static. README updated with the degradation order and the test
count (it also had 43 while #981 added one; now 45). No gate row touched, no image build, no board run, no device
ticket, :18097 untouched.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

bong-water-water-bong and others added 2 commits November 4, 2026 06:02
The code's row budget was a hand-counted 12 ("panels, nine menu rows, three
log rows and the footer"), so at 104x29 - a plain ssh window, the shipped
blank-key mode - the width test passed, the layout had rows left over, and
ratatui gave the panel grid's rows to the code: LEMONADE/GPU/NPU/MODELS/
FANS/DATA were gone, the log pane was gone, and the code's bottom quiet zone
painted over the MENU rule (which came back as " MENU ----      -").

The rows are the caller's question and only the caller can count them, so
qr_panel() no longer takes h and draw() decides after the footer, the panel
grid and the nine menu rows exist: the code is drawn only when
padded_top + facts + menu + 2 (log title and one log row) + footer <= h.
Where it does not fit, the URLs stay plain text - the documented fallback.

Measured at 104x29 with the static binary: before, panels 0 and the holed
MENU rule; after, the panel grid and the whole rule are back, no code, and
at 240x67 the code is still drawn (12 rows) with the panels intact. q over
ssh still exits 0 and restores icanon/echo; Ctrl-C on the console still
refuses to exit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dow keeps all nine actions

The log pane's height was a bare remainder (`h - top - menu - footer`) with no
floor, so whenever the fixed blocks did not fit, ratatui clipped the tail of
the frame: the MENU lost its last rows. Measured on the merged main with the
static binary in a pty: 80x18 drew actions 1-7 and a footer that still
promised "1-9 actions", with no `8 Logs` and no `Reboot / power off` - the
latter is a gate string vm-check.sh greps off tty1; 100x20 drew 1-8.

Now the nine actions and the footer are fixed (never trimmed) and everything
above them gives way in a fixed order, whole rows at a time: the status
facts first, then the log pane (a title needs a row under it), then the
CONNECT block's own tail. A one-row leftover is not a pane - it is the tail
of a wrapped log record ("  tokens, 330.75 tok/s)") - so that row goes back
to the block above and the footer stays on the last row.

Measured after, same pty and binary: 80x18 and 100x20 show all nine actions
including `Reboot / power off`, 100x20 keeps a one-row log pane, 80x25 and
240x67 are byte-identical to the committed snapshots.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

#983 ready for review at 50ea050a (closes #982, stacked on #981 — merge order #981 then #983, the second is a no-op rebase). Measured on ptys with the static binaries: 80x18 went from 7 actions with Reboot / power off and 8 Logs off the screen (a gate string) to all nine; 100x20 from 8 to 9 plus a one-row log pane; 80x25 and 240x67 byte-identical. 45/45 tests, clippy/fmt/copyright clean.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

CI at 50ea050a: build pass 5m46s (the only required context), hw_gate skipped (TUI-only, no device ticket). Two things that are the stack, not this diff: (1) there are no Analyze/CodeQL runs because this PR targets os/v3-tui-qrfit, not main — they return when it is retargeted after #981 merges; (2) pr_agent red in 5s is a cancel, not a review — gh api .../actions/runs/41814321449 says conclusion: cancelled (the workflow concurrency group, same as #981/#962 tonight). Re-run requested. mergeable=MERGEABLE.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

READY.

$ cd os/v3/puppy/console-tui && cargo test --offline
test result: ok. 45 passed; 0 failed; 0 ignored          (0.04 s)

Including the two arms that say what the change is for: a_short_window_keeps_the_nine_actions_and_the_footer_whole and the_qr_never_costs_another_block_a_row.

Read of the reordering: the footer is built first, and the QR is only drawn when the whole frame still fits (a log title plus one log row as the floor), so a code that does not fit takes a rule or the panel grid with it rather than being squeezed into the log pane. That is the right order — the thing a person reads first (facts, MENU) keeps its rows, and the thing that is optional (the code, which is also plain text in the URL row at 80x25) yields.

Not verified: an actual 80x25 and 132x43 terminal on the appliance (needs the VM/stick). The two sizes in the test suite are the same ones the earlier console PRs pinned, so the "whole" claims are at least anchored to a fixed geometry rather than asserted in prose.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

CHANGES (state, not content): CONFLICTING against main since #981 merged.

This PR's base is the branch os/v3-tui-qrfit (3deafc5), which merged as #981 and was deleted, so GitHub is diffing
against os/v3-tui-qrfit's absence rather than against main. The content is fine — I re-ran the suite at the rebased
head and it is 45/45.

Rebased it for you rather than leave it red: #995 (48776fe) is the same commit on top of main f63af5f. The
rebase was content-free — git diff 3deafc5 origin/main -- os/v3/puppy/console-tui/ is empty, so no merge decision
was taken — and git diff 50ea050 48776fe -- os/v3/puppy/console-tui/ is empty, so nothing of this PR moved.

Recipe, if you would rather own the branch:

git fetch origin
git checkout os/v3-tui-short
git rebase --onto origin/main 3deafc5 os/v3-tui-short
cargo test --offline            # in os/v3/puppy/console-tui -> 45 passed
git push --force-with-lease

Close this one when #995 is green; the verdict for the content is posted on #995.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

Superseded by #995 (same commit 48776fe, replayed onto main f63af5f — git diff 50ea050 48776fe -- os/v3/puppy/console-tui is empty, so nothing of this PR changed). Closing so a CONFLICTING twin of a clean PR does not sit on the board; the content, the issue it closes (#982) and the verdict live on #995.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

os/v3/puppy: the console TUI clips its own MENU on a window shorter than the layout (80x18 loses 8 Logs and Reboot / power off)

1 participant