Skip to content

Commit 8a2d71f

Browse files
Preserve terminal input across resize events with level-triggered polling
1 parent 2e198b3 commit 8a2d71f

6 files changed

Lines changed: 46 additions & 3 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 0.20.0 — native development (unreleased)
44

5+
- Native terminal input uses level-triggered polling after CI exposed dropped
6+
keys around resize events. Full-color PTY checks verify Escape closes Help
7+
before the next task submission.
8+
59
- Reviewed CLI and desktop worktree return prepare incoming commits in the source index
610
without committing. Stale reviews and active work are rejected; conflicts and
711
ignored local files are preserved for explicit resolution.

‎Cargo.lock‎

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/NATIVE_TUI.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ terminal settings. Drafts and prompt recall are currently in memory.
6868
## Verification and remaining work
6969

7070
`node scripts/test-native-tui.mjs` drives a real PTY and scripted compatible model
71-
with no display. It covers multiline Unicode paste, actual file inspection, shared
71+
with no display and full terminal colors. It checks that Escape restores the
72+
composer before the next key, and covers multiline Unicode paste, actual file inspection, shared
7273
CLI attachment, explicit command approval, planning mode, owned task cancellation
7374
and terminal restoration. Live PTY resizing covers the below-minimum warning,
7475
compact help scrolling to its final line and Home, expanded-dialog recovery, and

‎docs/NATIVE_VERIFICATION.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,25 @@ these transitions. Assertions inspect fresh complete frames because incremental
304304
ANSI updates can split words. This covers resize recovery; broader picker
305305
navigation, visual review and sustained terminal stress remain open.
306306

307+
## Terminal input after resize
308+
309+
CI run `35544397210` failed the terminal probe after Help stayed open and the
310+
following Enter did not submit the draft. Its retained ANSI recording showed
311+
the Help overlay still present. A local full-color run reproduced a related
312+
Home/resize timeout, which the previous inherited `NO_COLOR` environment had
313+
not exposed. Crossterm now uses its level-triggered `use-dev-tty` input backend
314+
instead of the edge-triggered Mio source, avoiding dropped readiness across
315+
simultaneous input and resize notifications. The PTY fixture explicitly enables
316+
truecolor and waits for the visible composer cursor after Escape before sending
317+
another key.
318+
319+
Three consecutive full-color PTY runs pass, each with eight scripted model
320+
requests, resize/help navigation, approvals, cancellation and terminal restoration.
321+
The native build, library tests and workspace Clippy pass. Dependency notice
322+
generation includes the new locked `filedescriptor` dependency and now covers
323+
576 application dependencies. These local results address the observed failure;
324+
the replacement CI run must still complete before its result is claimed.
325+
307326
## Reviewed return of worktree commits
308327

309328
Nine worktree tests pass. Return-specific scenarios exercise diverged branches,

‎native/core/Cargo.toml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ hyper = { version = "1", features = ["http1", "server"] }
3434
hyper-util = { version = "0.1", features = ["tokio"] }
3535
tower-service = "0.3"
3636
ratatui = { version = "=0.30.2", default-features = false, features = ["crossterm_0_29"] }
37-
crossterm = { version = "=0.29.0", default-features = false, features = ["event-stream", "bracketed-paste"] }
37+
# Level-triggered terminal polling preserves input readiness across resize events.
38+
crossterm = { version = "=0.29.0", default-features = false, features = ["event-stream", "bracketed-paste", "use-dev-tty"] }
3839
unicode-segmentation = "1"
3940
unicode-width = "0.2"
4041

‎scripts/test-native-tui.mjs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ await rm(path.join(artifacts, "failure.txt"), { force: true });
3333
const env = { ...process.env, TERM: "xterm-256color" };
3434
delete env.DISPLAY;
3535
delete env.WAYLAND_DISPLAY;
36+
// Exercise real color output even when the invoking tool disables colors.
37+
delete env.NO_COLOR;
38+
env.COLORTERM = "truecolor";
3639
const children = new Set(),
3740
sockets = new Set(),
3841
requests = [];
@@ -248,8 +251,11 @@ try {
248251
tui.child.stdin.write("\x1b[6~".repeat(40));
249252
await delay(150);
250253
await resize(tui, 40, 110, "unrelated tasks continue.");
254+
const closingHelp = tui.output.stdout.length;
251255
tui.child.stdin.write("\x1b");
252-
await delay(150);
256+
await until("Escape closes help before another key", () =>
257+
tui.output.stdout.slice(closingHelp).includes("\x1b[?25h"),
258+
);
253259
await resize(tui, 32, 110, "SHADOWCODE");
254260
assert.equal(
255261
requests.length,

0 commit comments

Comments
 (0)