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)