Skip to content

fix: remote Codex scrolling replays duplicate frames when history capture misses tmux #13

Closed

Description

@johoja12

w1-hdai (remote fullscreen Codex on the Mac mini) shows repeated prompts/output when scrolling.

Read-only production diagnosis:

  • Both local wrapper and canonical remote tmux report history_size=0, alternate_on=1, mouse_any_flag=1.
  • Current wheel gate excludes Codex even with observed tracking, so it can scroll repaint frames locally rather than Codex's native transcript. Tracked-Codex support is already measured in upstream PR fix(terminal): isolate scroll batches and support tracked Codex scrolling Ark0N/Codeman#645 but not present in current local production source.
  • /terminal?full=1 degrades to source=mux-visible and returns ~572KB containing 62 copies of collect_node_topology and 81 copies of the prior prompt.
  • The new remote scrollback helper invokes tmux without the shared remote PATH bootstrap. Direct execution of its exact generated command returns stderr zsh:1: command not found: tmux and just two NULs on stdout. This is logged misleadingly as no such remote tmux session. The actual session exists and is readable with the normal bootstrap.

Fix remote history command PATH parity and verify capture does not replay raw redraw history; restore observed-tracking Codex scroll routing using authentic isolated evidence and regression tests. Never send test prompts or scroll reports into the user's active session.

Activity

  1. johoja12 commented on Oct 21, 2026

    @johoja12
    OwnerAuthor

    Confirmed RCA and implemented 9eaefed0 on local branch fix/13-remote-codex-replay (/tmp/codeman-13-remote-codex-replay).

    Two causes combine:

    1. The remote scrollback helper omitted withRemotePathBootstrap, unlike launch/frame capture. The exact production-generated command returned zsh:1: command not found: tmux and only its two NUL delimiters; the fallback log incorrectly read “no such remote tmux session”. The live session exists under the stored remote name on codeman-remote.
    2. The deployed frontend excludes Codex from native wheel forwarding even with observed mouse tracking. Both the local SSH wrapper and remote Codex pane report alternate_on=1, mouse_any_flag=1, history_size=0; local scrolling therefore exposes retained repaint frames instead of the CLI's native transcript.

    The fix uses the shared PATH bootstrap for remote history reads and admits measured tracked Codex through the shared primary/tile/touch forwarding gate. Inline/untracked Codex, Shift/local-history opt-outs and native xterm routing remain as before. Metadata and docs now describe the observed behavior. No text deduplication is applied.

    Evidence/verification:

    • Before: /terminal?full=1 fell back to mux-visible and returned ~572KB containing 62 script-name and 81 old-prompt occurrences. Direct SSH confirmed tmux was absent from the non-interactive PATH.
    • Patched reader, pointed read-only at the exact live remote pane: succeeded, historyBytes=0, screenRows=34, no occurrences of those old prompt/script strings. No prompt, wheel input, resize or process restart was sent to w1-hdai.
    • The Mac mini and isolated local CLI are both Codex 0.163.0. Fresh authentic native measurement: flags 1/1, one SGR Up moved first marker 60 to 59, Down restored the identical frame. Wheel input over a real approval prompt left its selected option unchanged and did not execute the command. Evidence: /tmp/codeman-13-native-evidence.json.
    • 294 focused tests + 237 route tests passed (531 total, 1 existing skip); 4 browser checks passed across primary routing, tiles and touch paging. The browser routing test exercises the installed capture listener with only cell hit-testing and transport stubbed.
    • Typecheck, lint, format, lockfile, public assets, frontend syntax, browser exclusions and CLI catalogue check passed.
    • Realistic isolated Claude/Codex/shell smoke: 112 pass, 0 failures, 1 explicit unconfigured remote-host skip. All temporary sessions were deleted and servers stopped. Artifact: /tmp/codeman-dev-smoke-artifacts-2026-10-21T21-52-07-137Z-p4098695-r6e6c60a5b5664d26be7247729bbe7691/summary.json.
    • The bundled smoke initially exposed fixture issues: its awk command emitted literal backslash-n sequences, and its assertions expected markers older than the configured tmux retention after intentionally generating more than that limit. A temporary copy corrected the newline escaping and raised only the isolated fixture's tmux retention before session creation; all assertions then passed. Installed skill files and production settings were not changed.

    Not merged, pushed or deployed. Production checkout remains clean on local at 05252ccc; service lifecycle and the user's active session are unchanged.

  2. johoja12 commented on Oct 21, 2026

    @johoja12
    OwnerAuthor

    Merged 9eaefed0 into local, pushed to origin/local, built successfully and deployed to codeman-web.

    Fresh production evidence:

    • Service active/running, HTTP 200.
    • w1-hdai retains its existing session ID and reports cliMouseTracking=true.
    • /api/sessions/33d9a0f4-47f1-43b0-af67-bf0278b3f090/terminal?full=1 now returns source=mux-full-history, 5610 bytes at 170×33, with zero occurrences of the reported old prompt/script text. Before deployment it returned source=mux-visible and ~572KB of repaint data.
    • Deployed-browser native routing regression passed, with production writes and terminal WebSockets blocked in the test browser. No test prompts or wheel reports were sent to the user's session.

    Upstream PR Ark0N#645 is updated at 242bbfcd with the remote-history PATH fix/regression, a reusable helper suitable for upstream, and the latest review's rounding/comment/doc follow-ups. That exact branch passed 290 focused tests, 5 browser tests, full pre-push static checks, and isolated realistic smoke (108 pass / 0 fail / 5 documented skips). Fresh GitHub CI is running; PR is mergeable. Review response: Ark0N#645 (comment)

    Production source stays on local at 9eaefed0, matching origin/local. Upstream's PR-only gesture helper rounding changes are on its separate branch; the fork's existing per-event normalization already rounds isolated coarse wheel events.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions