Skip to content

fix(tui): repaint Superset terminal after missed resize events#17967

Draft
fcoury-oai wants to merge 2 commits intomainfrom
fcoury/superset-resize-watchdog
Draft

fix(tui): repaint Superset terminal after missed resize events#17967
fcoury-oai wants to merge 2 commits intomainfrom
fcoury/superset-resize-watchdog

Conversation

@fcoury-oai
Copy link
Copy Markdown
Contributor

PR Description

Problem

Codex relies on crossterm resize events to know when terminal geometry has changed and when ratatui's viewport assumptions need to be invalidated. Superset's xterm.js terminal host can miss those resize events when the split-pane terminal is resized while the terminal pane is not focused. The visible symptom is stale table and prompt rendering that remains wrong until a later input or app focus transition causes another repaint.

Mental model

The TUI now treats resize as a first-class event distinct from an ordinary scheduled draw. A draw says "render another frame because app state changed." A resize says "terminal geometry may have changed under cached viewport state, so repaint more conservatively." For Superset only, a small watchdog periodically samples terminal size and synthesizes the same resize event when the terminal size changed but crossterm did not report it.

Non-goals

This change does not attempt to make xterm.js repaint correctly in every host, reflow historical transcript content immediately on every resize, or replace the existing debounced transcript reflow path. It also does not enable size polling for every terminal. The workaround is intentionally gated to Superset detection and Superset environment markers.

Tradeoffs

The watchdog adds periodic terminal-size reads when Codex is running in Superset. That is acceptable there because the host has a demonstrated missed-event failure mode, but it would be unnecessary churn in terminals that already deliver resize events reliably. The repaint path also favors correctness over minimal output on resize by clearing and invalidating the viewport instead of trusting a cursor-position heuristic that can be stale in xterm.js split-pane resize scenarios.

Architecture

Terminal detection now recognizes Superset from TERM_PROGRAM and keeps it available through TerminalInfo. TuiEventStream constructs a ResizeWatchdog only when Superset is detected directly or through the SUPERSET_TERMINAL_ID and SUPERSET_WORKSPACE_ID marker pair. Normal crossterm resize events update the watchdog's cached size, while watchdog ticks compare the current terminal size to the last observed size and emit TuiEvent::Resize only when the size changed after initial seeding. App::handle_tui_event handles resize through the same draw path as scheduled draw events, but first asks Tui to force a full repaint. Tui::draw then skips the cursor-position viewport heuristic, clears the terminal, and invalidates the viewport buffer for that frame.

Observability

There is no persistent production logging in this narrower change. The best debug path is to inspect terminal detection inputs (TERM_PROGRAM, TERM_PROGRAM_VERSION, SUPERSET_TERMINAL_ID, SUPERSET_WORKSPACE_ID) and then verify whether resize events are arriving through crossterm or only through the watchdog tests. The xterm harness remains useful for manual reproduction, but it is not referenced by Rust code and is not part of this committed behavior.

Tests

The event stream tests cover the Superset gate, watchdog seeding, watchdog resize emission, and synchronization between normal crossterm resize events and the watchdog's cached size. Terminal detection tests cover Superset identification through TERM_PROGRAM. Existing TUI tests continue to cover the general draw and event-stream plumbing.

Add Superset terminal detection and a narrowly gated resize watchdog so missed split-pane resize notifications still trigger a visible repaint.

Keep transcript reflow on the existing debounced path and do not port the immediate scrollback repaint behavior from the feature stack.
Clarify the event-stream resize watchdog and the TUI repaint path so reviewers can distinguish scheduled draws from geometry-driven repaints.

Document the Superset-specific gate and the cached-size contract without changing runtime behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant