Skip to content

fix(terminal): do not answer replayed terminal queries again - #455

Merged
DeadWaveWave merged 2 commits into
mainfrom
fix/terminal-replay-queries
Oct 16, 2026
Merged

DeadWaveWave merged 2 commits into
mainfrom
fix/terminal-replay-queries

Conversation

@DeadWaveWave

@DeadWaveWave DeadWaveWave commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

💡 Change Scope

  • Small Change: Fast feedback, localized UI/logic, low-risk.
  • Large Change: New feature, cross-boundary logic, runtime-risk (persistence, IPC, lifecycle, recovery).

📝 What Does This PR Do?

Fixes stale terminal replies being typed into the shell after a terminal's xterm instance is recreated.

When OpenCove recreates a terminal's xterm instance (switching the terminal theme mode, restoring a terminal, and — with the upcoming transparent terminals — switching the terminal background), it replays the terminal's history into the new instance. If that history contains queries a program sent earlier — OSC colour queries (ESC ] 11 ; ?), cursor position reports (ESC [ 6n), device attributes (ESC [ c) — the new instance answers them again, and the answer arrives in the PTY as input to whatever runs now. Found while writing the transparent-terminal E2E: after a recreation, zsh received ESC ] 11 ; rgb:0909/0e0e/1212 BEL and printed command not found: 11.

  • stripTerminalQuerySequences (src/shared/terminal/automaticTerminalSequences.ts) removes the CSI queries the input bridge already recognises plus OSC 4 / 10–19 colour queries, and keeps everything else (colour sets, titles, cursor movement, styles).
  • hydrateFromSnapshot strips replayed snapshots before writing them to xterm. Live output that arrives during hydration keeps its existing routing, so programs that ask while a terminal hydrates still get answers.

🏗️ Large Change Spec (Required if "Large Change" is checked)

Not a Large change: one pure function and one call site in the replay path.

Invariant: replayed history never produces input to the PTY; live queries are still answered.


✅ Delivery & Compliance Checklist

  • The local quick gate passes: pnpm verify:quick / pnpm pre-commit is green; any additional focused tests are reported above.
  • Full CI passes on the final revision before merge; local quick checks are not reported as full regression.
  • I have signed the CLA if required (see CLA.md).
  • I have included new tests to lock down the behavior (or explicitly stated why it's untestable).
  • I have strictly adhered to the DEVELOPMENT.md architectural boundaries.
  • I have attached a screenshot or screen recording (if this touches the UI).
  • I have updated the documentation accordingly (if adding a feature or changing a contract).

Unit: automaticTerminalSequences.spec.ts (each query kind removed; colour sets, titles, cursor movement and styles kept). The end-to-end proof is the transparent-terminal E2E in the follow-up PR, which recreates xterm after an OSC 11 query and checks the next command runs cleanly (it failed before this fix).

Local (macOS arm64): pnpm verify:quick passed with this change (related Vitest 330 files / 1563 tests, native contracts 6 / 9, representative E2E 18 tests, run together with the follow-up); on this branch alone the hydration and sequence unit tests (28 files / 178 tests) and the terminal, recovery and reattach E2E files (45 files: 65 passed, 6 skipped, 1 failed). The failure was workspace-canvas.terminal-agent-restart.spec.ts:39 (codex): the restored sentinel appeared and then the screen was redrawn blank. Instrumenting the stripper showed it removes nothing in that test, so the replayed data is identical to main; across repeats it failed 2 of 13 times on this branch and passed 12 of 12 on main, which reads as a rare timing flake that this change does not touch. CI will show if it recurs.

Full CI on the final revision 8bf03a56: all 11 checks passed (run 38828073866, attempt 2). Attempt 1 failed only in web-canvas-continuity-ubuntu: workerWebCanvas.terminal-live-reattach-geometry.spec.ts:10 could not seed its state (sync.writeState failed: persistence.invalid_state), before any terminal output was replayed; it passed on the rerun. workspace-canvas.terminal-agent-restart passed on all three macOS shards.

📸 Screenshots / Visual Evidence

No UI change.

🤖 Generated with Claude Code

DeadWaveWave and others added 2 commits October 16, 2026 07:52
When a terminal's xterm instance is recreated, its history is replayed
into the new instance. Queries in that history (OSC colour queries,
cursor position and device attribute requests) were answered a second
time, and the replies were typed into whatever ran in the shell by then
(zsh: "command not found: 11"). Replayed snapshots now drop query
sequences before they reach xterm; live output still gets its answers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DeadWaveWave
DeadWaveWave merged commit 79615f3 into main Oct 16, 2026
21 of 22 checks passed
@DeadWaveWave
DeadWaveWave deleted the fix/terminal-replay-queries branch October 16, 2026 00:47
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