From 36459fbc69d3fc9f9fa3ec4f6936809fc3c8bf53 Mon Sep 17 00:00:00 2001 From: bong-water-water-bong Date: Thu, 5 Nov 2026 14:22:22 -0400 Subject: [PATCH] os/v3/puppy/console-tui: the README documents the two c26 console changes and stops saying 52 tests The crate's README describes the frame heal (#1093) but not the two changes that arrived with it, so a reader of the shipped crate cannot see why a control byte from Lemonade's log is harmless, or why an interrupted paint does not end the screen: * #1118 - facts::screen_text() cleans text from outside (CSI and OSC removed whole, TAB to a space, other C0/DEL dropped) before it becomes a cell. Measured against the recorded take's own log: the shipped c26 candidate (5b21a0a8, heal and no sanitiser) leaves 4 escape bytes in one rendered frame and on a 240x67 pty cuts its progress row at the first ESC[K; this build is 0 bytes. On the appliance's own 160x50 VT (booted c26 candidate, QEMU) the same wrapped progress line came back whole on BOTH binaries - the once-a-second full paint rewrites the cells the erase cleared - so the README calls this defence in depth rather than a visible repair, which is what the measurement says. Test: a_log_line_or_a_model_name_cannot_carry_an_escape_into_the_screen * #1102 - a paint that fails with ErrorKind::Interrupted repaints instead of ending the console (crossterm's SIGWINCH handler makes an ssh resize the realistic trigger); every other kind still exits to the dialog menu. Test: an_interrupted_paint_is_repainted_but_a_dead_terminal_ends_the_console Also corrects the test count: cargo test is 55, not the 52 the README has said since #1050/#1059. Docs only - no code, no frame, no gate string touched. cargo test 55/55, tools/copyright.py --check rc 0. Co-Authored-By: Claude Fable 5.1 --- os/v3/puppy/console-tui/README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/os/v3/puppy/console-tui/README.md b/os/v3/puppy/console-tui/README.md index e4f779fd6..9e63e6101 100644 --- a/os/v3/puppy/console-tui/README.md +++ b/os/v3/puppy/console-tui/README.md @@ -121,6 +121,26 @@ remains arithmetic (one escape plus 4.5 KiB) - a person at the monitor or a 60 f This is insurance, not the fix for a noisy writer: a writer that paints this screen is still a defect in the writer. +**Text from outside is cleaned before it becomes a cell.** Two of the pane's inputs are not ours - the tail of Lemonade's +log and the catalogue's names - and a cell's symbol is written to the terminal unchanged, so a control byte that arrives +as *data* is a control byte on the appliance's screen. It is reachable without malice: at `log_level: debug` that log +carries the demo pages' prompts, and the engine's progress-bar lines carry `ESC[K` (erase to end of line) and a bare CR. +Measured against the take's own log, the shipped c26 candidate (`5b21a0a8…`, which has the heal and not this) leaves +**4 escape bytes in one frame**, and on a 240x67 pty its progress row is cut at the first `ESC[K` with the wrapped +remainder gone; this build is **0 bytes**. On the appliance's own 160x50 text console the same line came back whole on +both binaries - the once-a-second full paint rewrites the cells the erase cleared - so this is defence in depth, not a +visible repair: a cell is simply not the place to execute what a log file says. +`facts::screen_text()` removes CSI and OSC whole (the bytes after an escape are control, not text), turns TAB into a +space and drops the other C0/DEL; everything else is untouched (`SoC 78°C`, `café`, `┌─┐`), and it is applied where +external text enters, so no draw site can forget it (`a_log_line_or_a_model_name_cannot_carry_an_escape_into_the_screen`). + +**An interrupted paint repaints; a terminal that cannot be written still ends the console.** A paint that fails with +`ErrorKind::Interrupted` drew nothing - a signal arrived before the write reached the terminal - so the next pass simply +paints again instead of ending the screen. That is reachable in normal use: crossterm's event source installs a SIGWINCH +handler, so an ssh user dragging a window edge is the realistic trigger. Every other error kind still exits, which is +what hands tty1 to the `dialog` menu (`paint_failed()`; +`an_interrupted_paint_is_repainted_but_a_dead_terminal_ends_the_console`). + ## Keys | key | what it does | @@ -212,7 +232,7 @@ dynamic one (`readelf` PT_INTERP, `ldd`). ## Tests ```sh -cargo test # 52 tests: the probe parsers, the QR drawing (incl. a literal known answer), the links, the short-window degradation, the two renders, the engine row's model choice +cargo test # 55 tests: the probe parsers, the QR drawing (incl. a literal known answer), the links, the short-window degradation, the two renders, the engine row's model choice, the escape sanitiser, the interrupted paint cargo run -- --snapshot 240x67 --fixture # the frame tests/snapshots/240x67.txt holds cargo run -- --snapshot 80x25 --fixture cargo run -- --status # the same facts as plain text (what a shell or a gate row can read)