fix(terminal): deliver escape sequences to ConPTY conin atomically (backspace types a space after resume)#9396
fix(terminal): deliver escape sequences to ConPTY conin atomically (backspace types a space after resume)#9396OrcaWin wants to merge 1 commit into
Conversation
…ackspace-types-space after resume) ConPTY's input parser drops VT state at conin write boundaries: an escape sequence split across two writes loses its head (silently swallowed) and delivers its tail to the foreground app as literal keystrokes. A split bracketed-paste end marker leaves TUIs (Claude Code composer) stuck in paste mode, where every keystroke buffers invisibly and Backspace inserts a blank-rendering literal — the field report 'backspace types a space after resuming sessions'. Add a daemon-side conin sequence-atomicity guard (win32 sessions only): hold a trailing partial escape sequence, join its continuation into one atomic write, flush bare ESC after 15ms (real Escape keypress) and other partials after 150ms, cap held state at 4KB, and emit env-gated breadcrumbs (coninJoinedSplitSequence / coninFlushedDanglingPartial) so field data can pinpoint the upstream split producer. Registers reliability gate terminal-input.windows-conpty-write-atomicity with a real-ConPTY red/green oracle.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes the recurring "backspace types a space in my terminal after I come back + resume sessions" report (native Windows, daemon ConPTY panes; prior partial fix: #9259).
Root cause (empirically established on Windows 11 26200)
ConPTY's input parser does not keep VT parser state across conin write boundaries. Measured with a raw-stdin child under a real ConPTY:
\x1b[?997;1+nwritten as two writes (any gap, including immediate) → the head is silently swallowed and the app receives literal"n". Deterministic, 3/3.…\x1b[+201~→ the paste never closes app-side. In Claude Code's composer this leaves paste-buffering stuck: subsequent keystrokes buffer invisibly and Backspace stops deleting / inserts a blank-rendering literal — exactly the field symptom (the reporter's live session history log shows caret-advance-with-no-glyph per keypress, then self-healing after a full composer redraw).Fix
ConinAtomicSequenceWriter, wired into the daemonSessionwrite path for win32 sessions only:terminal-partial-escape-tail, the scanner already trusted on the output path);Reliability contract
terminal-input.windows-conpty-write-atomicity(new manifest gate,experimental, wired commands).conin-atomic-sequence-writer.conpty.integration.test.ts.coninJoinedSplitSequence/coninFlushedDanglingPartial(ORCA_DAEMON_STREAM_BACKLOG_FILE) to identify the upstream split producer in the field.Verification
vitest run src/main/daemon/conin-atomic-sequence-writer.test.ts src/main/daemon/session.test.ts— 84+ tests green (join/hold/flush/ESC-disambiguation/cap/dispose, win32 session routing, non-win32 granularity untouched).vitest run src/main/daemon/conin-atomic-sequence-writer.conpty.integration.test.ts— green on Windows 11 26200 against a real ConPTY: documents the raw defect and proves guarded whole-sequence delivery.pastedab→ 2× Backspace →pasted); unguarded, the same pattern reproduces the stuck-composer corruption (timing-dependent, matching the intermittent field behavior).pnpm run typecheck:nodeandoxlintclean. Pre-existing unrelated failure on this Windows host:osc7-file-uri.test.ts(fails identically on clean HEAD).Residual gaps