fix(pi): forward the wheel from cliMouseTracking so scrolling survives replay

pi 1.4.0 is an alt-screen TUI that enables mouse tracking once at start.
Codeman's replay (tab switch, reload) drops that mode in xterm
(mouseTrackingMode none, baseY 0), so the wheel hit an empty local buffer
and stayed dead until a resize made pi redraw.

Same shape as copilot: altScreen strip-mux-and-mouse (the server records
the stripped DECSETs as cliMouseTracking, which survives the replay),
wheelForward always, transcriptPageKeys (PageUp/PageDown fallback for a
stale flag, measured on pi 1.4.0). _shouldForwardWheelToApp treats pi like
copilot. Registry pins and docs updated.

Tests: 2 new in terminal-scroll-routing (red before). Full run: 12989
passed, 5 red from the de_DE locale / XDG env (custom-model-run-menu-ui,
git-worktrees, edit-history-sync), all green under LANG=C.UTF-8.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 53e4136d9f4401e9250ac6a122599ffcb2a57e8a)
This commit is contained in:
Randalix authored and Codeman maintainer committed 2026-11-05 23:35:14 +01:00
1 parent 46b85fa6d0
commit 58dae1e182
8 files changed
+52 -24

No files matched your search

+10 -12
View File
@@ -304,23 +304,21 @@ function cliExportsTruecolor(mode: SessionMode): boolean {
* Codex, Claude Code, and Gemini are known, controlled (Ink/React) TUIs that
* repaint via cursor positioning, so dropping the alt-screen switch is safe —
* content stays in the normal buffer. Excluded: `shell` (arbitrary programs like
* vim/less/htop legitimately need the alt screen), `opencode` (its own MIDDLE strip,
* isMuxMouseStripMode), `pi` (below) and `grok` (a fullscreen alt-screen TUI with
* vim/less/htop legitimately need the alt screen), `opencode` and `pi` (their own MIDDLE strip,
* isMuxMouseStripMode; pi since 1.4.0) and `grok` (a fullscreen alt-screen TUI with
* mouse support). Keep parity with the replay-side strip (`stripReplayBuffer` in
* session-routes.ts); the table in `CliCapabilities.altScreen` is pinned for every
* stock CLI in test/claude-scrollback-strip.test.ts.
*
* ⚠️ Being excluded here does NOT preserve the alt screen. Every excluded mode
* falls through to isMuxAltScreenOnlyStripMode(), which strips the alt-screen
* toggles too whenever the session is tmux-backed, and pi/opencode ALWAYS are
* (both refuse the direct-PTY fallback). What exclusion actually buys is the rest
* of the full strip: `\x1b[3J` and the mouse-tracking DECSETs survive. That is the
* real reason pi is out: its default TUI renders into the MAIN screen with
* terminal-owned scrollback and is mouse-aware, so it is a `3J`/mouse consumer in
* a way an Ink TUI repainting in place is not. Consequence to know before
* debugging it: pi's runtime-switchable fullscreen TUI (`/settings`, 0.84.0+)
* still gets its `?1049h` stripped and paints into the main buffer, exactly like
* vim inside a tmux `shell` session.
* falls through to isMuxMouseStripMode() or isMuxAltScreenOnlyStripMode(), which
* strip the alt-screen toggles too whenever the session is tmux-backed, and
* pi/opencode ALWAYS are (both refuse the direct-PTY fallback). What exclusion
* actually buys is the rest of the full strip: `\x1b[3J` survives, and for the
* narrow strip the mouse-tracking DECSETs too. pi (1.4.0, measured) is a
* mouse-aware fullscreen TUI like opencode and copilot, so it takes the mouse
* strip (isMuxMouseStripMode): a drag selects locally and `cliMouseTracking`
* keeps the wheel working across a buffer replay.
*/
export function isAltScreenStripMode(mode: SessionMode): boolean {
return getCli(mode)?.capabilities.altScreen === 'strip-full';