Skip to content

fix(web): suppress xterm.js terminal query auto-responses#272

Merged
skulidropek merged 5 commits into
ProverCoderAI:mainfrom
konard:issue-271-6e1a0e1d8cfa
May 11, 2026
Merged

fix(web): suppress xterm.js terminal query auto-responses#272
skulidropek merged 5 commits into
ProverCoderAI:mainfrom
konard:issue-271-6e1a0e1d8cfa

Conversation

@konard
Copy link
Copy Markdown
Contributor

@konard konard commented May 11, 2026

Summary

Fixes #271 — the web terminal was showing raw escape sequences such as ^[]10;rgb:f4f4/f7f7/fbfb^[\ and ^[[?1;2c inside Claude Code's prompt, breaking navigation and rendering.

Root cause

xterm.js@5.3.0 answers TUI capability probes out of the box:

  • OSC 4/10/11/12 color queries (\x1b]10;?\x1b\\, etc.)
  • CSI ... c device attributes — DA1, DA2, DA3
  • CSI ... n device status / cursor position reports

The replies are emitted via Terminal.onData, which the web frontend forwards to the host PTY as if the user typed them. Claude Code (and other TUIs) read those bytes as keystrokes inside their prompt loop and render them verbatim — exactly what the screenshot in the issue shows.

Fix

A new module (packages/app/src/web/terminal-query-suppression.ts) installs custom OSC/CSI handlers immediately after the Terminal is constructed in createTerminalRuntime:

  • For OSC 4/10/11/12 the handler returns true only when the payload contains a ? segment (a query). Plain set-color payloads return false so the default theme-change handler still applies.
  • For CSI ... c (DA1/DA2/DA3) and CSI ... n (DSR/CPR) the handler always returns true so xterm never reports back to the PTY.

Handlers are tracked as disposables, so callers (and the unit tests) can roll the registration back without touching xterm's internal parser state.

Test plan

  • bun run --bun vitest run tests/docker-git/terminal-query-suppression.test.ts — 7 new unit tests covering query detection, handler registration order, OSC fall-through for set commands, CSI consumption, and disposal cleanup.
  • Full test suite passes.
  • bun run typecheck passes.
  • Linter passes.
  • bun run build:web succeeds.
  • Manual: start the web build, attach a TUI inside the container, run printf "\\033]10;?\\033\\\\" — no echoed garbage in the prompt.

Files

  • packages/app/src/web/terminal-query-suppression.ts (new) — suppression module
  • packages/app/src/web/terminal-panel-runtime-core.ts — wire suppression into createTerminalRuntime
  • packages/app/tests/docker-git/terminal-query-suppression.test.ts (new) — unit tests
  • experiments/terminal-query-suppression.md — root-cause notes
  • experiments/verify-suppression.html — manual browser verification scaffold

Fixes #271

konard added 2 commits May 11, 2026 15:36
Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: ProverCoderAI#271
xterm.js answers TUI capability probes (OSC 4/10/11/12 color queries,
DA1/DA2/DA3 device attributes, DSR/CPR) by emitting reply bytes through
onData. Those bytes were forwarded to the PTY as if the user had typed
them, so Claude Code rendered the raw escape sequences inside its prompt.

Install a parser shim right after constructing the Terminal that
consumes color queries (while letting set-color commands fall through)
and always consumes device-attribute and cursor-position queries. The
shim is returned as a disposable so tests can roll it back.

Fixes ProverCoderAI#271
@konard konard changed the title [WIP] Почему терминал для Claude Code ломается постоянно? не работает навигация и ничего fix(web): suppress xterm.js terminal query auto-responses May 11, 2026
@konard konard marked this pull request as ready for review May 11, 2026 15:50
@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

Working session summary

CI is running. Done — committed the fix, pushed, updated PR #272's title/body, and marked it ready for review.

PR: #272

Summary of changes shipped on issue-271-6e1a0e1d8cfa:

  • packages/app/src/web/terminal-query-suppression.ts — new module that overrides xterm.js OSC 4/10/11/12 and CSI DA1/DA2/DA3/DSR/CPR handlers so terminal probes are consumed without replying through onData.
  • packages/app/src/web/terminal-panel-runtime-core.ts — wires the suppression into createTerminalRuntime right after the Terminal is constructed.
  • packages/app/tests/docker-git/terminal-query-suppression.test.ts — 7 unit tests covering query detection, handler registration, fall-through for set-color commands, and disposal.
  • experiments/terminal-query-suppression.md + experiments/verify-suppression.html — root-cause notes and manual verification scaffold.

CI is currently pending across all jobs.


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $5.497444

📊 Context and tokens usage:

Claude Opus 4.7: (2 sub-sessions)

  1. 117.4K / 1M (12%) input tokens, 27.2K / 128K (21%) output tokens
  2. 39.1K / 1M (4%) input tokens, 3.3K / 128K (3%) output tokens

Total: (2.0K new + 134.5K cache writes + 7.3M cache reads) input tokens, 35.7K output tokens, $5.405814 cost

Claude Haiku 4.5:

  • 40.9K / 200K (20%) input tokens, 3.3K / 64K (5%) output tokens

Total: (593 new + 40.3K cache writes + 241.6K cache reads) input tokens, 3.3K output tokens, $0.091631 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Main model: Claude Opus 4.7 (claude-opus-4-7)
  • Additional models:
    • Claude Haiku 4.5 (claude-haiku-4-5-20251001)

📎 Log file uploaded as Gist (2959KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

🔄 Auto-restart triggered (iteration 1)

Reason: CI failures detected

Starting new session to address the issues.


Auto-restart-until-mergeable mode is active. This run will stop after 5 restart iterations.

The Lint Effect-TS check forbids `as`/`<T>` casts outside src/core/axioms.ts,
and the new tests for terminal-query-suppression cast a mock to `Terminal`
via `as never`. Replace the parameter type with a structural
`TerminalQuerySuppressionTarget` that the real xterm `Terminal` already
satisfies, so the mock can be passed directly without any cast.
@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

Working session summary

All 15 PR checks are SUCCESS — including the previously failing Lint Effect-TS.

Summary

The Lint Effect-TS check was failing because the new test file packages/app/tests/docker-git/terminal-query-suppression.test.ts had five as never casts (lines 74, 80, 92, 101, 109), and the lint rule no-restricted-syntax forbids TSAsExpression/TSTypeAssertion outside of src/core/axioms.ts.

Fix (commit a00ffc3): Replaced the Terminal-typed parameter on installTerminalQuerySuppression with a structural type TerminalQuerySuppressionTarget that only declares the parser.registerOscHandler/parser.registerCsiHandler methods the function actually uses. The real xterm Terminal already satisfies this structural shape (parameter contravariance + return covariance), and the test's mock now satisfies it too — so no casts are needed.

Verified locally: bun run --cwd packages/app lint:effect clean, full app tests 262/262 pass. PR 272 is now green on all 15 checks.

PR: #272


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

🔄 Auto-restart-until-mergeable Log (iteration 1)

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $2.200154

📊 Context and tokens usage:

  • 84.4K / 1M (8%) input tokens, 12.6K / 128K (10%) output tokens

Total: (52 new + 78.3K cache writes + 2.8M cache reads) input tokens, 12.6K output tokens, $2.200154 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Model: Claude Opus 4.7 (claude-opus-4-7)

📎 Log file uploaded as Gist (4076KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

🔄 Auto-restart triggered (iteration 2)

Reason: Uncommitted changes detected

Starting new session to address the issues.


Auto-restart-until-mergeable mode is active. This run will stop after 5 restart iterations.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

Working session summary

Everything is in order:

  • Working tree: clean (removed stale ci-logs/ artifacts)
  • Branch: up to date with origin and merged with latest upstream/main (no conflicts)
  • PR fix(web): suppress xterm.js terminal query auto-responses #272: OPEN, MERGEABLE, mergeStateStatus CLEAN, not draft
  • CI: all 15 checks passing (Build, Lint, Lint Effect-TS, Test, Types, Snapshot, 7 E2E jobs, Dist deps prune × 2)
  • Local tests: 7/7 terminal-query-suppression tests pass; effect-ts lint clean

PR: #272


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

🔄 Auto-restart-until-mergeable Log (iteration 2)

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $0.828325

📊 Context and tokens usage:

  • 48.5K / 1M (5%) input tokens, 4.3K / 128K (3%) output tokens

Total: (34 new + 52.1K cache writes + 787.8K cache reads) input tokens, 4.3K output tokens, $0.828325 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Model: Claude Opus 4.7 (claude-opus-4-7)

📎 Log file uploaded as Gist (4639KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 11, 2026

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

@skulidropek skulidropek merged commit 664f237 into ProverCoderAI:main May 11, 2026
14 of 15 checks passed
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.

Почему терминал для Claude Code ломается постоянно? не работает навигация и ничего

2 participants