From ed29cdce47b944a35c832a30cb0c8bb8576185a6 Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Sun, 16 Aug 2026 11:05:39 +0800 Subject: [PATCH] docs: a restored pane is a resized pane, as far as capture is concerned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--scrollback`'s help said the flag makes no difference "for a never-resized pane", and the reference said the same. Both are wrong for the panes where the difference matters most. I killed a daemon under a running GUI, watched it come back, and captured a pane that had `RESTORE-MARKER-7788` in it. Plain `capture` answered with two lines — the restore banner and a prompt — while `--scrollback` had the marker and everything around it. Nothing had been resized. `ReplayRing::seeded` ends with `resize(size)`, deliberately: the restored screen is replayed at the size it was recorded at, and the new shell writes at the size the pane came back as. When those differ the restored screen is sealed into an earlier segment, and the default capture cannot see it. That is the agent-facing primitive answering "almost nothing" for a pane that kept its screen, with the help explaining that this only happens after a resize. Both now say restores count, and say what a plain capture looks like when it does. `resize` returns early on an unchanged size, so a pane that comes back the same shape really does keep one segment — the test covers both sides of that, which is the part the wording turns on. --- crates/tty7-cli/src/cli.rs | 7 ++++-- crates/tty7-core/src/daemon/pane.rs | 38 +++++++++++++++++++++++++++++ docs/cli/reference.mdx | 5 ++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/crates/tty7-cli/src/cli.rs b/crates/tty7-cli/src/cli.rs index 63ccb3ee..8230a4b4 100644 --- a/crates/tty7-cli/src/cli.rs +++ b/crates/tty7-cli/src/cli.rs @@ -409,8 +409,11 @@ pub struct CaptureArgs { #[arg( long, help = "Print the whole scrollback ring; the ring splits into segments on resize, \ - and without this flag only the last segment is printed (for a \ - never-resized pane the two are identical)" + and without this flag only the last segment is printed. A pane restored \ + after its daemon died counts as resized: the screen it was seeded with was \ + recorded at the size it had then, so it sits in an earlier segment unless \ + the new pane happens to match it, and plain `capture` shows the banner and \ + the new prompt alone" )] pub scrollback: bool, diff --git a/crates/tty7-core/src/daemon/pane.rs b/crates/tty7-core/src/daemon/pane.rs index 8c58a049..9454e2bc 100644 --- a/crates/tty7-core/src/daemon/pane.rs +++ b/crates/tty7-core/src/daemon/pane.rs @@ -3660,6 +3660,44 @@ mod tests { assert!(rx.try_recv().is_err()); } + /// The seam a restore leaves is the snapshot's *size*, not the restore. + /// + /// `tty7 capture` prints the last segment alone, so this decides whether a + /// restored pane answers with the screen it kept or with the banner and a + /// prompt. Restoring at the size the screen was recorded at leaves one + /// segment and the capture holds everything; a pane that comes back a + /// different shape does not, which is what the flag's help now says. + #[test] + fn a_restore_only_starts_a_segment_when_the_pane_comes_back_a_different_size() { + use crate::daemon::scrollback::Segment; + + let seed = |at: WinSize, back: WinSize| { + let mut ring = ReplayRing::seeded( + vec![Segment { + size: at, + bytes: b"what the dead pane had on it".to_vec(), + }], + back, + ); + ring.append(b"the new shell's prompt"); + ring + }; + + let same = seed(ws(80, 24), ws(80, 24)); + assert_eq!( + same.segments.len(), + 1, + "the same size, so the new shell writes on into the restored screen" + ); + + let different = seed(ws(100, 24), ws(80, 30)); + assert_eq!( + different.segments.len(), + 2, + "a different size, so the restored screen is left behind in its own segment" + ); + } + #[test] fn a_seeded_ring_replays_the_old_screen_at_the_size_it_was_written() { use crate::daemon::scrollback::Segment; diff --git a/docs/cli/reference.mdx b/docs/cli/reference.mdx index 046fa8d3..601b46e0 100644 --- a/docs/cli/reference.mdx +++ b/docs/cli/reference.mdx @@ -161,6 +161,11 @@ The pane's replay. Two independent choices: `--scrollback`. The ring splits into segments on resize, so for a pane that was never resized the two are identical. +A pane restored after its daemon died counts as resized. The screen it was +seeded with was recorded at whatever size it had then, so unless the new pane +comes back that same shape, plain `capture` answers with the restore banner and +the new prompt alone — everything above the banner needs `--scrollback`. + **In what form** — without `--plain`, the stored bytes with ANSI escapes intact, decoded as UTF-8 (invalid bytes become U+FFFD). With `--plain`, those bytes replayed through a terminal grid and printed as the text they produced.