Commit Graph
4 Commits
Author SHA1 Message Date
NeilandOrca 5ea7df1a5b fix(terminal): make DECSET 2031 subscriptions silent (#13904)
fish arms `CSI ?2031h` before painting each prompt and withdraws it when it
hands the tty to a child — a ~1ms window. Orca answered that subscribe with
`CSI ?997;Nn` across a 1-3ms renderer hop, so the reply landed after the
withdrawal and was read as stdin by the next child, corrupting `brew`/`npx`
`[y/N]` prompts.

The reply is not stale by Orca's own view when written (measured
staleReplies: 0), so no suppress-the-stale-reply scheme can close this — the
information needed to suppress does not exist yet. Nothing asked for the reply
either. The Contour spec says a terminal "should only send out the DSR when the
palette has been updated"; Ghostty (Termio.zig:729 — force=true reachable only
from the ?996n DSR), iTerm2 (VT100Terminal.m:995 — flag only) and xterm.js
(InputHandler.ts:2035 — flag only) all emit nothing on the DECSET. So stop
entering the race: record the subscription, answer nothing.

Of 17 real programs measured under a pty, only fish, tmux, claude and opencode
subscribe; none block on a reply, and answering produces one redundant palette
re-query and zero rendering difference. tmux is the only one that sends `?996n`,
which Orca still answers.

- Subscribes are record-only at all four emitters (live scan, hidden-gate fact,
  parked byte watcher, parked responder — the last is deleted, it only replied).
- `?996n` answers, the subscription registry, and the theme-flip push are
  unchanged. `paneLastThemeMode` is still seeded at subscribe so the next
  appearance re-apply is not read as a flip.
- Replay grammar carries `?2031l` alongside `?2031h`, so a late-attaching remote
  client no longer registers a subscription the TUI already retired.

Also closes fish-integration gaps found alongside: `unset` (which fish lacks)
becomes `set -e` on paths parsed by the client's login shell, `config.fish` is
parsed for agent-home detection, and bracketed-paste startup delivery is made
consistent across local/daemon/relay.

Regression test drives real fish 4.7.1 under node-pty and asserts on what the
child process reads; it fails against pre-fix code with the exact payload from
the issue. CI installs fish 4 and fails loudly rather than skipping.

Closes #9993

Co-authored-by: Orca <help@stably.ai>
2026-08-11 21:16:36 -07:00
JinjingandOrca 468f5b77b5 test(e2e): fix two stale E2E specs failing on main (runtime host seeding, alt-screen snapshot) (#10614)
* test(e2e): register a real runtime host and publish the alt-screen frame as its snapshot

Two long-running scheduled-E2E failures on main were stale test setup, not
product defects.

`onboarding.spec.ts:420` seeded the Active Server by faking a runtime
environment in the renderer store and writing `activeRuntimeEnvironmentId`
through the generic `settings:set` IPC. Since #10011 that setter strips the
key, and the dedicated `settings:set-active-runtime-environment-preference`
handler resolves the id against the main-process environment store — CI
logged `RuntimeEnvironmentStoreError: Unknown environment: env-e2e` from
`runtimeEnvironments:subscribe`/`:call` alongside the assertion failure.
Register the host for real via `runtimeEnvironments:addFromPairingCode`
(offline; no live server) and write the preference through its own channel.

`terminal-tab-switch-visual-restore.spec.ts:604` wrote alt-screen frames
straight into the renderer's xterm, so those bytes never transited the PTY
and main's model could not contain them. On cycle 0 the freshly spawned
shell still has queued startup output, so hiding the pane makes main's
hidden-delivery gate drop bytes and latch a reveal restore, which repaints
main's snapshot over the fabricated frame; later cycles run against an idle
shell and survive. Arm the existing `setHiddenSnapshotOverride` seam (already
used by sibling tests in this file) with the same frame so the live-write and
restore paths render identically, and keep the `markerPresent` assertion.

Co-authored-by: Orca <help@stably.ai>

* test(e2e): keep the alt-screen restore path observable

Numbering the snapshot frame one higher than the live-written frame keeps
the marker assertion path-agnostic while leaving the frame number on
screen as the signal for which path painted. An unrecognised frame now
fails, and the per-cycle path is recorded rather than asserted because
which cycles latch a restore is load-dependent.

Frame authoring and readback move to a helper module; the additions
crossed the spec's max-lines cap.

Co-authored-by: Orca <help@stably.ai>

* Escape regex metacharacters in alt-screen marker pattern

Marker is treated as a literal string, so escape regex metacharacters
to prevent them from being interpreted as regex syntax.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-25 15:58:40 -07:00
OrcaWin b3b5031883 test(e2e): deliver node burst via temp file so PowerShell quoting can't break OSC title (#8521) (#9391)
The e2e terminal helpers typed `node -e ${JSON.stringify(script)}` into the
PTY. JSON.stringify emits POSIX-style \" escapes, which PowerShell does not
honor: it re-splits the program on `;` inside the payload, node throws
'Expected unicode escape' before emitting a single byte, and the OSC-title
assertions fail deterministically on Windows (default shell = PowerShell).

Stage the program in a unique temp .cjs file instead and send
`node "<forward-slash path>"` — no shell ever parses the program source, so
delivery is byte-identical on PowerShell, cmd, bash, and zsh (verified with
hexdumps: 07 1b 5d 30 3b ... 07 matches exactly across shells). Forward
slashes keep the quoted path valid in both POSIX shells and PowerShell; the
Codex startup marker moves from argv into the script body so no argument
quoting remains. macOS/Linux payload bytes are unchanged — only the delivery
mechanism differs. Test infrastructure only; no product code touched.
2026-07-20 03:04:28 -04:00
Brennan BensonandOrca 17dee0861f Fix terminal tab switch resume rendering (#6041)
Co-authored-by: Orca <help@stably.ai>
2026-06-23 00:23:34 -07:00