mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
`tty7 capture %n` answered a live pane with zero bytes and exit 0, which is byte-identical to a pane that had genuinely never printed. The report guessed at the replay grid. It is not the grid — it is the segment the grid was handed. The daemon's replay ring splits on resize: `ReplayRing::resize` seals the segment holding the output and pushes an empty one at the new geometry, and `ReplayRing::replay` sends every segment it holds, empty tail included. `RealBackend::capture` then kept "the newest segment" for the default (non-`--scrollback`) form, and for any pane resized since it last printed, the newest segment is that empty placeholder. A pane restored from disk lands in the same state, because seeding the ring ends in a resize too. Measured end to end against a real daemon before the fix: a pane holding 954 bytes of scrollback answered `capture` and `capture --plain` with 0 bytes and exit 0 while `capture --scrollback` returned all 954. The fix drops byte-less segments before choosing the newest one — they carry nothing in either form, so `--scrollback` drops them too and both forms describe the same bytes. The daemon still sends them: its trailing `Size` is how an attaching client learns the pane's current geometry, and that is not the CLI's to take away. What this does not explain is the reporter's other half — that `--scrollback` came back empty in the same episode. Filtering empty segments cannot cause that, and neither could I reproduce it: 60 rounds of `capture` against a pane spewing 4000 escape-laden lines produced no empty result, and an 8 MiB ring (the cap) replayed whole in ~400 ms, well inside the 300 ms per-frame settle window that was the other suspect. So the silent-empty class is left distinguishable rather than declared closed: `--json` now carries `bytes`, the size of the replay counted before anything renders or trims it, and the one case where an empty answer is not an empty replay — bytes in, no text out — says so in a line on stderr. Zero bytes is a pane that printed nothing; bytes with no text is a screen whose content did not survive the grid. Deliberately no retry loop and no warning on a condition that has not been established. Claude-Session: https://claude.ai/code/session_01UUyWQXzcBAoBzaSX8pc7nU