mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
* fix(terminal): reset stale mouse tracking on cold restore (#12101); stop OSC color-reply echo leak in POSIX agent panes (#12112) #12101: a force-killed TUI never emits its DECRST reset, so its armed mouse mode is latched into the on-disk checkpoint and re-derived into the replacement process's emulator via the cold-restore history seed -- through both rehydrateSequences and SerializeAddon's own mode trailer. The revived bare shell then echoed SGR motion reports at the prompt. Seed a RESET_MOUSE_REPORTING segment after the snapshot (before the torn escape tail), only when there is real recovered content so the empty-array "nothing to recover" sentinel survives. #12112: agent panes arm a main-side PtyStartupIngress that answered opencode's startup OSC 10/11 queries synchronously inside node-pty's onData, while the POSIX tty still had ECHO on. The line discipline echoed Orca's own reply back out as visible text. Echo suppression existed but was gated on windows-conpty. Add PtyStartupReplyDelivery: POSIX defers the write off the query's turn and recognizes its own echo anywhere in a span (bounded, non-destructive); ConPTY keeps its synchronous write; windows-wsl is byte-identical to before. Fixes #12101 Co-authored-by: Orca <help@stably.ai> * fix(terminal): read the slave's ECHO bit before answering a color query The startup color reply was written into a PTY still in cooked mode, so the line discipline echoed it back as visible junk (#12112). Whether that will happen is readable state on the slave rather than something to infer from returning bytes, so the reply now waits until the ECHO bit is observably clear instead of guessing at echo shapes. Two echo sources exist and only one is readable. A `quiet` verdict proves the kernel will not echo, so it retires the caret projection; readline echoes a master write in software with the tty already raw, so that projection stays armed on every path. Scoping `quiet` narrowly is the whole correctness argument here: reading it as "no suppression needed" reintroduces the bug at a plain shell prompt. Polling is bounded by a wall-clock budget rather than an attempt count, because each probe is a subprocess and a multi-pane restore serializes them on fork. Withholding measures flat at ~210ms from 1 to 100 panes. Also resets a cold-restored pane's mouse reporting (#12101). The armed mode is re-derived from the dead process's own persisted bytes through two channels, so the daemon seeds a reset into recovered history and the renderer stops trusting a persisted "live agent" signal after a cold restore. The reset literals move to one shared profile module. Fixes #12101 Fixes #12112 Co-authored-by: Orca <help@stably.ai> * test(terminal): pin the cold-restore reset on the spawn-adopted reattach path A spawn can be answered with an adopted session, which reaches the reattach handler by a door that skips the restored-session path. Pin that the cold-restore signal survives it, so #12101's junk cannot come back through it. Co-authored-by: Orca <help@stably.ai> * test(terminal): note why the adopted-reattach snapshot leaves the cursor visible Co-authored-by: Orca <help@stably.ai> * fix(terminal): harden startup reply delivery --------- Co-authored-by: Orca <help@stably.ai>