Commit Graph
16002 Commits
Author SHA1 Message Date
Neil 5447a26fd1 perf(lint): keep JS plugins out of default oxlint and adopt ast-grep (#33430)
* perf(lint): keep JS plugins out of default oxlint and adopt ast-grep

Any jsPlugin makes Oxlint hand every file's AST to Node, so the seven custom
plugins cost the default `oxlint` run several times its native time.

- Move app-store-performance, quadratic-buffer-concat, renderer-scrollbar-style
  and ime-enter-guard (scope- or dataflow-aware) to config/oxlint-js-plugins.json,
  run by `pnpm lint:js-plugins`, CI, lint-staged and the changed-lines gate.
- Port sort-comparator-performance, mobile-pairing and native-chat-design-tokens
  to ast-grep rules with rule tests, and delete the plugins.
- Add @ast-grep/cli, config/sgconfig.yml, `pnpm lint:ast-grep` / `test:ast-grep`,
  a CI step, and an ast-grep pass in check-changed-code-quality.
- Add flaky-test rules (wall-clock reads, real-time waits, polling loops,
  unquarantined skips, unexplained timeout bumps), baselined by a count ratchet.

* Enforce flaky-test ratchet on changed files; refresh baseline

* docs(agents): keep custom-rule details out of AGENTS.md

* Resolve ast-grep from the repo so gate scans of other roots work
2026-10-25 00:23:38 -07:00
Neil a30d4f4f28 feat(devex): component fixtures with headless screenshots for fast UI checks (#33406)
* feat(devex): component fixtures with headless screenshots for fast UI checks

Colocated *.fixture.tsx files export named fixtures (render + optional store
seed, setup, interact, width). A dev-only Vite entry (vite.fixtures.config.ts,
extending vite.web.config.ts) renders one fixture in isolation with the real
I18nProvider, TooltipProvider, theme class, default-seeded store, and the web
client's preload bridge (installWebPreloadApi) as window.api.

`pnpm fixtures:shot <id|glob> [--theme dark|light|both]` starts or reuses a
detached server (Vite + one headless Chromium) and writes PNGs to
.cache/fixtures/. A warm page re-renders in place (~100ms/shot) and reloads
only after source changes. A stdio MCP server (registered in .mcp.json)
exposes list_fixtures and screenshot_fixture.

Fixtures load only through import.meta.glob in the fixture entry, which is
not a production build input; oxlint rejects static imports of *.fixture.

* Keep fixture config and agent config inside reviewed root entries

* Baseline the fixture page's default-settings seed in the focus-read ratchet

* docs(agents): shorten fixtures pointer

* Allowlist the dev-only fixture explorer's labels in localization coverage
2026-10-25 00:23:32 -07:00
Neilandbbingz cae5e983a7 fix(terminal): send ESC d for Option+Forward-Delete on macOS (#21491) (#33296)
macOS: Option+Forward-Delete sends ESC d (delete word forward) for shells and inline agent TUIs, so Claude Code deletes a word instead of the whole line; full-screen non-agent apps (vim, nano, less) keep the native CSI 3;3~. Linux/Windows unchanged. Fixes #21491. Supersedes #21893.

Co-authored-by: bbingz <11211020+bbingz@users.noreply.github.com>
2026-10-25 00:16:59 -07:00
Neil d81958f0e8 refactor: group local and WSL filesystem watchers (#33407)
* refactor: group local and WSL filesystem watchers

* test: isolate startup ordering from watcher initialization

* test: collect the startup preflight subject once
2026-10-25 00:13:36 -07:00
NeilandSTiFLeR7 dc13e74cd5 fix(terminal): keep Windows Codex multiline Ctrl+V and Edit > Paste as one draft (#33339)
Windows + Codex: Ctrl+V, Shift+Insert and Edit > Paste send multi-line pastes with Alt+Enter newlines like right-click already does (restoring #14456 wiring lost in a refactor), so pasted lines no longer submit one by one when Codex's paste-burst heuristic doesn't catch them (e.g. disable_paste_burst = true). macOS/Linux clients unchanged. Fixes #30470. Supersedes #30550.

Co-authored-by: STiFLeR7 <157357792+STiFLeR7@users.noreply.github.com>
2026-10-25 00:08:31 -07:00
NeilandMaple e13e5e8b7d fix(orchestration): submit mail pointers to Cursor CLI instead of leaving them in the composer (#33347)
Orchestration mailbox pointers now get their delayed Enter for Cursor too (the Cursor no-Enter skip from #3156 left mail delivered but never acted on). Verified with real cursor-agent. Fixes #19760. Supersedes #19761.

Co-authored-by: Maple <54388301+zleo-ai@users.noreply.github.com>
2026-10-25 00:07:42 -07:00
Neil a6d4a4fea5 fix(windows): respawn a ConPTY pane that started without keyboard input (#33423)
* fix(windows): respawn a ConPTY pane that started without an input reader

Bundled ConPTY occasionally starts a pane whose console host never reads
its input pipe: the shell prints its banner and prompt, but every keystroke
and the typed launch command are dropped. Such a pane is identifiable from
its first output, because a healthy one always queries DA1 before relaying
anything else. The daemon now waits for that first output, respawns once
when it is missing, and replays the buffered startup output so no byte is
lost. The table stress probe now waits for node-pty's own readiness rather
than typed input.

* fix(windows): bound the ConPTY startup check and never re-run a command

- Respawn only when no command rode in the shell's argv; otherwise keep the
  pane and say on screen that it cannot take input.
- Accept the pane unverified after 5s of silence instead of stalling the spawn.
- Distrust the check after two misses with no pane ever announcing, so a
  changed ConPTY build cannot respawn every pane.
- Kill a discarded pane through its job before closing the pseudoconsole.
- Report a cancel during the wait as an attach cancel, not a spawn failure.
- Assert on real Windows ConPTY that a fresh pane announces its input reader.

* fix(windows): respawn only Orca's own shell argv and close an unready pane now

- Treat user shell args like an argv startup command: never respawn, show
  the notice instead, so a command such as pwsh -Command never runs twice.
- Close a discarded pane's pseudoconsole directly; node-pty defers kill()
  until first output, which a silent pane never produces. Kill the shell by
  pid when no job owns it.
- Reconcile a master node-pty retired during the startup wait.
- Drop the test-only respawn counter; the count rides in the daemon log.

* fix(windows): tear a discarded unready pane down through node-pty's agent

node-pty defers kill() until first output, so closing only the native
pseudoconsole left the input pipe and output worker of a silent discarded
pane alive until daemon exit. The agent's kill closes all three.

* fix(windows): discard startup panes by handle only; account for the mock prelude

A pid-addressed kill could hit a recycled pid when the shell exited during
startup; the job and the agent's native kill both act on handles. Lifecycle
assertions now expect the replayed DA1 query when the suite runs on Windows.

* test(e2e): give the mocked Windows pane its ConPTY prelude
2026-10-24 23:59:37 -07:00
Neil ae6062bade fix(runtime): a paired runtime's frame no longer drops another runtime's terminals in a shared workspace (#33414)
* fix(runtime): keep another paired runtime's terminals when one runtime republishes a shared workspace

Desktop B can mirror one SSH workspace from two paired runtimes: the host's
server, which runs its terminals, and desktop A's app, which hosts a browser
tab A opened there. Any frame from A's app replaced every mirrored terminal
row in the workspace, so B dropped the server's terminals until the server's
next frame re-created them. A frame now replaces only the mirrored terminals
and chats its own runtime owns, matching how browser and editor rows were
already scoped.

Fixes #31983

Reported-by: amara-black

* fix(runtime): retire an omitted host's rows without waiting on a sibling host's replay

A tombstone now retires only its own host's rows, so the visibility-resume
repair no longer has to hold it back until every surviving host has a frame
to replay over the wiped workspace.

* refactor(runtime): one ownership rule for rows a paired runtime's frame may retire

Bindings first, then the frames that last published the row, then the
workspace's own server; owners that were removed no longer count, so any
runtime's frame can retire their rows.

* fix(runtime): address review on cross-runtime mirror ownership

Drop the workspace-owner guess for rows with no evidence, let a frame that
publishes the same chat take its row over, and refocus a surviving runtime's
terminal when the active one is retired.

* refactor(runtime): a mirrored terminal stays while any other live runtime claims it

Union pane bindings and last-frame mappings into one claim set, so a row two
runtimes share survives one runtime's retraction. Drop the chat ownership
extension: chats are shared across runtimes by session id, and the reported
bug is terminals only.

* refactor(runtime): claims come from the frames that published a terminal

A runtime that stopped publishing a terminal no longer claims it through a
cached pane binding; bindings only speak before any frame this session.
Keep the visibility-resume repair's survivor deferral as it was.

* fix(runtime): bound pane resources decide a mirrored terminal's runtime; chats follow the same rule

A shared terminal whose bound runtime drops it is retired and rebuilt by the
other runtime's next frame, so it never streams from a runtime that left.
Chats another live runtime owns survive this frame unless it publishes or
replaces them.

* fix(terminal): close another paired runtime's terminal on that runtime

A workspace can now keep terminals another runtime publishes, so a close
follows the runtime the tab's own PTY names before the workspace catalog.

* fix(runtime): only this machine or a live paired runtime keeps a chat another frame omits
2026-10-24 23:59:21 -07:00
Neil 75855c7ccd fix(agent-prompt): press Enter again while a Windows Codex composer still holds a dispatch (#33295)
Windows Codex: when a large dispatch/worker-start/agent prompt paste is still held in Codex's composer (Codex reads the paste as key events and treats an early Enter as a newline), Orca re-presses Enter only while the composer visibly holds exactly that pasted prompt, re-checking turn start, permission and the deadline right before each Enter, within the worker-start budget. Non-Windows unchanged except the blind launch retry is skipped once a turn starts. Fixes #11343.
2026-10-24 23:56:31 -07:00
Neil e575cc19a3 fix(opencode): refuse model launches on OpenCode 2.x releases that drop the startup prompt (#33436)
OpenCode 2.x model-selection launches require 2.0.19+ (upstream #51938 waits for agent/model before auto-submitting --prompt) or a native-prompt version (2.0.12, 2.0.16), fixing a regression from #33307 where 2.0.14/15/17/18 accepted a picked model but silently dropped the first prompt.
2026-10-24 23:56:27 -07:00
Neilandmarcdhansen d058e8f026 fix(claude): run the native Windows hook exe for spaced profile paths (#33364)
Windows Claude hooks for profile paths with a space register in Claude's exec form (orca-agent-hook.exe + args) instead of the slow encoded-PowerShell fallback (~650ms → ~15ms per event); the script path in args lets older Orca builds recognise and replace the entry. Older Claude keeps the PowerShell launcher. Fixes #19187. Supersedes #19255.

Co-authored-by: marcdhansen <7607160+marcdhansen@users.noreply.github.com>
2026-10-24 23:54:05 -07:00
OrcaWinandOrcaWin b961e5c087 test: remove inventory mirrors and repair behavioral assertions (#33437)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 23:51:39 -07:00
Neil e39330e15d docs: slim STYLEGUIDE.md into a core guide plus topic deep dives (#33402)
Keep the rules most UI changes need in docs/STYLEGUIDE.md (32.9KB -> 10.1KB)
and move per-component specs, native chat scale, UX rationale, and the
screen review rubric into docs/styleguide/. Values now point at main.css
instead of being restated. Lint messages and comments that cited moved
sections now point at the new files.
2026-10-24 23:50:21 -07:00
NeilandMatt Bass ee38c3047b fix(hermes): keep a finished Hermes pane done when its background memory review calls tools (#33418)
Hermes: after the pane's turn ends, tool hooks from Hermes' hidden background memory/skill review are ignored until the next pre_llm_call, so a finished pane no longer flips back to Working. Delegate children (platform: subagent) don't end the parent's turn; approvals are always admitted. Fixes #31798. Supersedes #31807.

Co-authored-by: Matt Bass <76124126+mattjax16@users.noreply.github.com>
2026-10-24 23:14:11 -07:00
Neil fef00e4461 feat(dev): give each worktree its own pnpm dev profile and ports (#33416)
Linked worktrees now get a per-worktree userData profile under
orca-dev-wt/<hash>, a deterministic collision-checked renderer port
(15200+) and CDP port (9333+), so parallel `pnpm dev` runs no longer hit
the single-instance lock. The main checkout keeps the shared orca-dev
profile; --shared-profile / --worktree-profile / ORCA_DEV_PROFILE override.

The runner prints `ORCA_DEV_INSTANCE {json}` on stdout and mirrors it to
out/dev-instance.json so agents can attach over CDP. orca-dev.mjs and the
terminal wrappers follow the profile the worktree's dev app used.

Adds profile seeding (pnpm dev:seed-profile, pnpm dev --seed-profile,
pnpm dev:fresh --seed-from): an allowlisted slim copy of projects,
workspaces, settings, SSH targets, and the account session, written as
orca-data.json for Orca's own import; the source is only read.

Storage reclaim removes per-worktree profiles once their worktree is gone
and no app, runtime, or daemon still uses them. dev-fresh-profile.sh is
replaced by a cross-platform dev-fresh-profile.mjs.
2026-10-24 23:08:52 -07:00
OrcaWinandOrcaWin 4633fa9d07 fix(sidebar): keep the workspace hover card open behind link actions (#33409)
* fix(sidebar): keep the workspace hover card open behind link actions and system-browser opens

* fix(sidebar): scope the unfocused hover hold to external opens and fix chooser dismissal edge cases

* perf(sidebar): register the refocus listener only while a hover hold is set

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 23:07:54 -07:00
OrcaWinandOrcaWin e1066973f2 fix(worktrees): never leave the create-worktree dialog stuck on a stalled preflight (#33400)
* fix(worktrees): never leave the create-worktree dialog stuck on a stalled preflight

Bound the same-repo PR branch fetch with the review-head fetch timeout, and
hand a slow composer submit off to a staged sidebar row so the dialog closes.

* fix(worktrees): harden create-worktree handoff from adversarial review

Dedupe handed-off submits against linked creations resolved during preflight,
bound the staged sidebar row with a deadline, offer Reopen on handed-off
failures, and bound the GitLab MR branch fetch.

* test(worktrees): expect the bounded PR/MR branch fetch timeout

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 23:00:47 -07:00
Neilandinnocarpe 10005e5d15 fix(hermes): use the Windows %LOCALAPPDATA%\hermes home for hooks and session history (#33413)
Hermes home resolves like Hermes itself on Windows (HERMES_HOME, else %LOCALAPPDATA%\hermes, else a legacy ~\.hermes that alone exists), shared by hook install/status, skill discovery and session reading; session reading also honors HERMES_HOME. Fixes #24966. Supersedes #25058.

Co-authored-by: innocarpe <2222333+innocarpe@users.noreply.github.com>
2026-10-24 22:56:51 -07:00
NeilandNaveen Chatlapalli 062ebbaf26 fix(agents): pre-trust the folder for Kimi Code so its trust menu does not swallow the prompt (#33411)
Kimi Code workspace pre-trust: Orca writes Kimi's own trust record (<KIMI_CODE_HOME or ~/.kimi-code>/workspace-trust/wd_<slug>_<hash>) for the exact launch folder, so Kimi's "Trust this folder?" menu no longer swallows Orca's prompt. Never pre-trusts the home folder or a filesystem root. Fixes #26680. Supersedes #26738, #26741.

Co-authored-by: Naveen Chatlapalli <54518943+1aifanatic@users.noreply.github.com>
2026-10-24 22:56:46 -07:00
Neil 4ff84bb835 fix(mobile): stop phones losing terminal output sent as output spans (#33405)
* fix(mobile): stop losing phone terminal output sent as output spans

Hosts sent stripped/transformed terminal output to terminal.subscribe as
OutputSpan (opcode 15), which no phone has ever decoded. The phone dropped
it silently, e.g. the reset after a killed full-screen program, leaving
the phone stuck on the alternate screen.

- Host: terminal.subscribe sends spans as plain Output text; only the
  desktop multiplex (which decodes spans) keeps OutputSpan.
- Mobile: decode OutputSpan for older hosts, use the shared protocol
  table, and end the stream with a logged error on any frame it can't read.

* fix(mobile): throttle unreadable-frame resets and log once per stream

* fix(mobile): reset a throttled stream after the window; forget released stream ids

* fix(mobile): defer throttled unreadable-frame resets instead of dropping them
2026-10-24 22:56:11 -07:00
OrcaWinandOrcaWin 3d24e61726 test: remove self-validating checks and exercise intended boundaries (#33412)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 22:52:08 -07:00
NeilandClaude Opus 5.5 8e9f86b119 feat(managed-server): Update and Update anyway for a managed SSH server, keeping its running terminals (#33397)
* feat(managed-server): offer Update and Update anyway on a managed SSH server's row

A managed SSH server only updated on connect, and every connect deferred while
a terminal ran there. Its row now offers Update when this desktop bundles a
newer build than the Orca that runs the host. When running terminals defer it,
Update anyway restarts the server past them; the terminal daemon carries them
across the restart.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(managed-server): Update anyway passes only counted live terminals and keeps Update's version admission

Update anyway now sends the incumbent build it confirmed over; under the host
fence it is refused if another desktop activated a build since, keeps the
newer-host downgrade refusal, and never passes an uncounted terminal census.
The offer also covers hosts activated before the Orca version was recorded,
for the build this desktop already deferred there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(managed-server): Update anyway also confirms a menu Update the row does not advertise

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(managed-server): the row shows one confirmation at a time

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci(e2e): route managed-server update sources to the Update anyway Docker spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 22:49:18 -07:00
NeilandClaude 1592ef1fc9 fix(terminal): a slept WSL pane on Windows wakes in the folder its shell was in (#33398)
* fix(terminal): a slept WSL pane on Windows wakes in the folder its shell was in

Bash in a WSL pane on Windows reports no folder (no OSC 7), so Sleep's final checkpoint kept the
folder the pane was spawned in, and Wake reopened every such pane at the workspace root. Before
that checkpoint, the daemon client now reads the pane shell's folder inside its distro, from
/proc, by the ORCA_PANE_KEY its processes inherit, and stores it in the checkpoint Wake restores
from. The read is one fixed script per distro per Sleep batch, shared while in flight, capped at
3 s and a quarter of the Sleep's remaining budget. It only runs in a distro that is already
running. Any failure keeps today's spawn folder.

After an app relaunch, the client learns each live WSL session's distro and pane key from the
sessions it adopts at startup. A pane slept before the window reopened it therefore keeps its
folder too.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(terminal): read only Orca pane processes, skip the running check for live panes, wake at the asked folder when the kept one is gone

Review of #33398:
- Speed: the guest script forked about a dozen times per /proc entry (2.3 s for 405 processes),
  so busy distros spent the whole 3 s budget. One `grep -l` over every environ now picks the
  Orca pane processes first, and only those are read, so the cost no longer grows with the
  distro's process count. A test counts the tool calls for 5 and 400 other processes and
  expects the same number.
- Fewer launches: a live pane's own wsl.exe keeps its distro running, so a Sleep of a live pane
  skips the `wsl --list --running` check and costs one launch per distro instead of two.
- Deleted folder: a pane whose kept folder is deleted before Wake failed to spawn when the
  guest could not answer the folder probe. Wake now retries once in the folder the pane asked
  for, as before the folder was kept.
- Drops the unused sid and argc fields.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(terminal): skip the running check only for a distro last seen running; keep the asked folder through the restore re-spawn

Review of #33398:
- A live pane skips the `wsl --list --running` check only when its distro is also in the last
  confirmed running list. The client can still hold a session as live after its distro was
  terminated or across a daemon disconnect, and reading that distro would boot it.
- The probe-to-create race re-spawn now reads back the folder the spawn actually used, so after
  the deleted-folder retry neither `initialCwds` nor the cold-restore payload keep the gone path.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 22:47:57 -07:00
OrcaWinandOrcaWin e7a567b178 fix(worktrees): explain the shallow-clone local base warning and let users stop the refresh (#33260)
* fix(worktrees): explain the shallow-clone local base warning and let users stop the refresh

When a shallow clone hides the shared history, the local base fast-forward
refusal now says so and shows the git fetch --unshallow command, instead of
blaming local-only commits. Every refresh-failure toast also gets a
"Stop updating local main" action that turns off Keep Local Main Up to Date.

* feat(worktrees): add an Unshallow button that runs the fetch in a new terminal tab

* feat(worktrees): rename the opt-out to Disable Check and explain it in a tooltip

* fix(worktrees): harden the Unshallow launch

Reuse createNewTerminalTab (owner-routed, no focus read) instead of a
parallel launcher, report real host-launch outcomes before dismissing,
only offer the button for shell-inert remote names, route activation by
the creation host, ignore double clicks, and treat only a silent exit 1
from merge-base as a missing merge base.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 22:45:21 -07:00
Neil 62d9706c5a fix(agents): start a Claude worker on its composer when its terminal title is off (#33384)
Claude worker-start also becomes ready when Claude's empty composer (❯ + NBSP, only after Claude's DECSET 2031) draws, racing the title-based tui-idle wait, so worker-start no longer times out when Claude's terminal title is disabled. Fixes #22655.
2026-10-24 22:23:08 -07:00
Neil 95df4c74ed refactor: group Parcel watcher process ownership (#33401) 2026-10-24 22:14:52 -07:00
OrcaWinandOrcaWin 1d2b5361ef test: remove duplicate assertions and repair misleading fixtures (#33394)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 21:52:14 -07:00
Neil 4fa91acb4f fix(repos): drop a paired server's old workspace rows when it relists them under new project ids (#33396)
* fix(repos): drop a repo's worktree rows when its host's catalog no longer lists it

A paired server that relists its checkouts under new repo ids (a project
copied into another profile, then that profile switched to) left the
desktop showing the old rows beside the new ones, the old under Unknown.
Every catalog fetch now drops the rows of the repo registrations it
removed, scoped to the dropped host.

Refs STA-12076

* fix(repos): purge a dropped repo's workspaces like a vanished checkout

Clears selection, tabs and per-workspace state of the dropped rows through
the same bulk purge an authoritative scan uses, flushing delayed editor
text first; the three catalog fetch paths share one finalize step.

* fix(repos): drop rows only, never a registration added after the request

Review: purging tabs and selection could race repo add/remove and lose
state. Keep the change to rows, and fence it to registrations the store
held when the catalog request went out.

* test(e2e): drop the fixed settle wait from the repo id change repro
2026-10-24 21:51:22 -07:00
Neil f3104c80bf fix(daemon): a Windows terminal's output-relay write error no longer kills the PTY daemon (#33391)
* fix(daemon): contain ConPTY output-relay write errors to the one terminal instead of killing the daemon

* fix(daemon): end a Windows terminal whose output relay dies before connecting

* fix(daemon): kill a Windows terminal whose output relay fails before its first output
2026-10-24 21:45:06 -07:00
Neil c25fad76df fix(agent-teams): run the tmux shim through the headless host's CLI, never the GUI binary (#33389)
* fix(agent-teams): run the tmux shim through the headless host's CLI, never the GUI binary

On an orca serve host the runtime has no Electron resources directory, so the
shim fell back to PATH and picked the AppImage's Electron binary, which booted
Chromium and died on the SUID sandbox. Prefer the host's profile-scoped CLI
launcher, and route agent-teams-tmux through the packaged CLI redirect so a
direct Electron invocation never initializes the GUI.

Fixes #33354

* fix(agent-teams): prefer a fresh CLI over a shim bin inherited from an older leader pane
2026-10-24 21:35:18 -07:00
Neilandyasyf 1b54aba056 fix(orchestration): hold mailbox pointers while the agent shows an open dialog (#21745) (#33366)
Orchestration mailbox pointers (typing and the delayed Enter) are held while a Claude pane shows an open dialog (AskUserQuestion / permission / plan approval chrome on screen, or a fresh waiting row when the screen can't be read), capped at 10 minutes, so mail no longer answers the dialog. Recheck backs off to 2s while held. Fixes #21745. Supersedes #26928, #21880.

Co-authored-by: yasyf <709645+yasyf@users.noreply.github.com>
2026-10-24 21:27:02 -07:00
OrcaWinandOrcaWin 5efcbf41f7 test: remove redundant checks and strengthen runtime regression coverage (#33385)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 21:08:47 -07:00
Neil 75ecad41d5 test(git-bash): give ssh-agent a load-tolerant bound in the Windows pane proof (#33287)
The detached ssh-agent proof waited 10s for eval "$(ssh-agent -s)" to print
its pid. On a loaded runner the shell had already accepted and started the
command (OSC 133;C) when the bound tripped; the leading terminal queries are
the pane's normal prelude, not a missing marker. Across eight instrumented
CI runs the marker took 0.5-1.1s, so keep waiting on the marker but cap it
at 30s.
2026-10-24 21:05:19 -07:00
Neil fc508bd19e test(windows): read the grandchild pid from accumulated pane output (#33320)
The ConPTY job-ownership proof matched ORCA_GC=<pid> against each onData
chunk, and once gave up after its 20s poll with no pane output to show why.
Two causes are possible: a chunk boundary inside the marker, which per-chunk
matching never recovers from, or a pane that trails the preceding table
stress test. Match the accumulated output and require a non-digit after the
pid, bound the poll at 40s, and include the pane tail if it still fails.
2026-10-24 20:56:24 -07:00
NeilandLuis Urrutia aa32d9b9d9 fix(terminal): keep fish's startup XTVERSION reply out of the launched agent (#33381)
A complete XTVERSION reply is delivered immediately (past the daemon shell-ready gate) and echo-filtered like colour/private-DSR replies, so fish's startup XTVERSION reply no longer leaks into Codex's composer. Fixes #16489. Supersedes #16491.

Co-authored-by: Luis Urrutia <3771248+LuisUrrutia@users.noreply.github.com>
2026-10-24 20:53:23 -07:00
NeilandMinidoracat b94ad9870e fix(terminal): don't resume an agent whose spawned PTY is still live (#33380)
The daemon records each terminal's spawn pane key and reports it in session listings; the sleeping-agent activation gate uses it as an exact-match fallback to find a live agent PTY after the host re-keys its tab, so paired clients and phone wake no longer start a duplicate `claude --resume`. Fixes #21235, #24385. Supersedes #24386.

Co-authored-by: Minidoracat <11269639+Minidoracat@users.noreply.github.com>
2026-10-24 20:51:22 -07:00
7d0103e8a6 fix(jira): keep the Tasks Board view selected after you leave the page (#30588)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-25 03:43:08 +00:00
Neil 4e1acc99a3 fix(codex): write folder trust into the managed-account CODEX_HOME the launch uses (#33377)
Codex workspace trust is also written to the launch CODEX_HOME (managed-account home) at spawn, and native Codex chats pick their launch home before writing trust, so managed-account Codex launches no longer stall on "Trust this folder?". Fixes #27235.
2026-10-24 20:31:05 -07:00
OrcaWinandOrcaWin f392c6bd46 test: remove redundant checks and strengthen runtime regression coverage (#33373)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 20:24:40 -07:00
Neil ad1b81d53a refactor: group PTY delivery and drain ownership (#33358) 2026-10-24 20:22:31 -07:00
Neilandinnocarpe fd240408b4 fix(pty): let agents run exit hooks before an immediate local-provider close SIGKILLs them (#33367)
Local (in-process) PTY provider: an immediate close now SIGTERMs descendants and waits up to the shutdown grace before SIGKILL (same as the daemon path since #22232), so Claude's SessionEnd hooks run. Refs #23865, #22039. Supersedes #24314.

Co-authored-by: innocarpe <2222333+innocarpe@users.noreply.github.com>
2026-10-24 20:09:42 -07:00
Kelvin Amoaba 25b9ce5168 feat(browser): show a hovered or focused link's URL in a bubble at the bottom of the page (#32978) 2026-10-25 03:09:30 +00:00
Neilandluisgonzaleznf 0fa161ba42 fix(agents): skip Codex's startup update prompt on Orca-driven launches (#33355)
Orca-driven Codex launches that type their prompt after start (workers, automations, continuation/handoff, pane-spawn and other submit-after-ready flows) pass `-c check_for_update_on_startup=false`, so Codex's "Update now" screen can't block them or be accepted by Orca's Enter. User-typed launches and resumes are unchanged. Fixes #15814, #18153. Supersedes #18156.

Co-authored-by: luisgonzaleznf <47302972+luisgonzaleznf@users.noreply.github.com>
2026-10-24 19:56:41 -07:00
Neil f076731231 fix(omp): replace the ACP child when OMP drops the chat's session (#33359)
Native OMP chat (ACP): when OMP reports its session was closed (-32603 "ACP cancel cleanup timed out" / "Unsupported ACP session: <this session>"), Orca replaces the child so the next send or Retry reloads the session instead of failing forever. Other ACP agents unchanged. Fixes #32684. Refs #32161.
2026-10-24 19:53:58 -07:00
Kelvin Amoaba 76f0f35bad feat(browser): speaker icon on tabs playing sound, with tab mute (#32981) 2026-10-25 02:51:37 +00:00
OrcaWinandOrcaWin b7476f5457 test: remove redundant cases and strengthen regression assertions (#33356)
* test: remove redundant cases and strengthen regression assertions

* test: let upstream empty typecheck baseline take precedence

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 19:51:11 -07:00
Kelvin Amoaba 695fc0081c feat(browser): bigger new tab tiles and roomier workspace card (#33178) 2026-10-25 02:44:03 +00:00
OrcaWinandOrcaWin fdcf887bf0 chore(lint): fix suppressed lint violations instead of ignoring them (#33294)
* chore(lint): remove disable directives that suppress nothing

Each was reported unused by the oxlint config that owns its rule (root,
casting, react-doctor, anti-slop, native-plugins), including 17 file-level
react-doctor blanket disables whose rule no longer fires. An unused
react-hooks disable was masking a react/purity finding in
useAgentBucketCounts (compiler rules skip functions with hook
suppressions); suppress that one explicitly where the code explains it.

* test(tab-bar): use typed tab/file fixtures instead of @ts-expect-error partials

* chore(lint): fix misc suppressed lint violations instead of disabling

- consistent-type-imports: the "vi.importActual requires inline import()"
  rationale was wrong; use typed vi.mock(import(...), importOriginal) or a
  type-only namespace import.
- no-control-regex: source-control commit/push failure summaries, shell PATH
  hydration, and ipynb ANSI parsing reuse the shared ansi-escape-sequences
  stripper and control-character pattern instead of private copies.
- no-explicit-any / no-useless-spread / no-this-alias: typed `this` in
  bridge test mocks, drop blanket file-level disables, drop a this-alias.

* refactor(main): replace avoidable type assertions with checked narrowing

17 production cast suppressions in main/wsl-guest removed: untrusted IPC
and RPC payloads (Jira issue update, WSL guest plugin install, handshake
type) now narrow through isRecord/type guards and build typed results;
redundant casts dropped; hand-rolled object checks and errno casts use the
existing isRecord / hasErrorCode helpers.

* refactor(renderer,mobile): replace avoidable type assertions with checked types

13 production cast suppressions removed: RPC failures read through the
`ok` discriminant instead of casting to RpcFailure; react-native-web host
refs narrowed with instanceof HTMLElement; redundant reply/diff casts
become checked annotations; the TUI agent param uses z.custom(isTuiAgent)
like its sibling schemas; the agent-status slice cast that hid missing
actions is gone so the creator's return type checks the whole slice.

* chore(lint): drop dead tiptap wrapper; scope anti-slop mocking rule to test support

- safe-react-node-view-renderer patched handleSelectionUpdate, which
  @tiptap/react 3.31.3 no longer has, so it always returned early. Use the
  stock ReactNodeViewRenderer.
- The anti-slop test override only matched *.test.{ts,tsx}, forcing
  file-level no-module-mocking disables in test harnesses and fixtures.
  Match *-test-harness, *-test-fixture(s), .test-fixture and *.test.mjs,
  then drop those disables and the now-redundant per-file exemptions.

* test: replace repeated cast suppressions with typed fixtures (main/shared/e2e)

Net -119 cast directives. Typed fixtures replace recurring casts:
unusedSshConnection/unusedOrcadHostTransport placeholders, a typed
readPersistedState harness read (exposed a test treating optional
httpProxyUrl as always set), real Response objects in fetch spies, an
updater main-window fixture, a CDP webContents adapter, one shared
releaseModuleExport for cross-version tests, and requireOverlayDir in
place of `as string` on possibly-undefined overlay paths.

* fix(runtime): validate loaded device rows and host scope instead of casting

Two cast suppressions claimed checks that did not happen:
- device-registry-file-read: "normalizeLoadedDeviceRow re-validates every
  field" was false; deviceId, token, name and timestamps were never
  checked. Rows without an identity are now dropped and the file is set
  aside through the existing corrupt-file path (registry reads as
  doubtful, so no revocation verdicts); a non-string token is stripped
  so the row stays listed but cannot authenticate.
- client-ui: "only optionality differs" was false; any string reached
  persisted workspaceHostScope. Narrow it with isWorkspaceHostScope and
  ignore unknown scopes (wire schema unchanged for mixed versions). The
  remaining cast now states what it actually covers.

* test(runtime,ipc): drop redundant cast suppressions; typed runtime store fixture

-98 cast directives across runtime/ipc tests: 61 casts that typecheck
without the assertion; a typed vi.fn for scoped invalidation; a
partialRuntimeStore fixture in place of `store as never` for
OrcaRuntimeService; typed worker terminal/authority builders in the
incarnation-fallback suite (the old stub lacked runtimeId, ptyId,
worktreeId and launchTokenHash) plus removal of stacked duplicate
directives there.

* chore(lint): typed vi.mock imports and explicit listener snapshot in shared-bucket tests

Remaining files from the misc-rule pass that overlapped other buckets:
codex-accounts mocks use the typed vi.mock(import(...)) form instead of
a consistent-type-imports disable; the daemon late-exit fixture copies
its listener set with Array.from instead of a no-useless-spread disable.

* refactor(github,mobile): narrow routing settings type; drop remaining avoidable casts

- work-item-routing cast a one-field object to AppState['settings'] under
  a claim that readers only consume activeRuntimeEnvironmentId. Return the
  existing RuntimeFocusSettings pick instead and narrow the cache-key
  chain's parameters, so the compiler enforces that claim.
- mobile file preview reads refusals through the RpcResponse `ok`
  discriminant rather than a cast.
- terminal document host-notify accepts `unknown` errors, removing the
  message-bridge cast.
- native chat readability drops a redundant repo-list cast.

* test(renderer): replace repeated cast suppressions with typed fixtures

-140 cast directives (and ~150 unsuppressed casts of the same shapes):
- mockPanePtyArgs owns the connectPanePty fixture casts, so a wrong
  argument order or fixture is now a type error; drop binding casts for
  members PanePtyBinding already declares.
- Seed AppState tab rows with the typed makeTerminalTab; this exposed a
  split direction 'row' that is not a TerminalPaneSplitDirection.
- Partial GlobalSettings use getDefaultSettings overrides; Jira-only
  stores use createTestStore; runtime environment rows/statuses come from
  a typed paired-runtime-environment fixture.

* chore(lint): drop no-module-mocking disable now covered by the test-fixture glob

* test(e2e): fix all 221 grandfathered e2e type errors; baseline to zero

The e2e typecheck baseline grandfathered 221 errors in 119 files. About a
third were tests drifted from the current API, several of which would
fail or mislead at runtime:
- terminal-shortcuts called a nonexistent xterm buffer method;
- the daemon-lifecycle fake lacked terminateOwnedTree, hidden by importing
  its type from a module that does not export it;
- arguments in the wrong position (listProcesses(hostId, opts), a dropped
  pty.write inputKind, an extra toWebTerminalSurfaceTabId argument);
- removed enum values ('drawer', 'idle', 'editor',
  'session-insecure-origin') and a launch_source the telemetry schema
  rejects;
- missing required fields (turnScope, childWorkOpen, providerIdentity,
  reviewLookupOutcome, runtimeServiceAccount behind an `as RelayConfig`);
- dead reads (tab.customTitle, bucket.targets, changedPixels).
Also lifts variables that narrowed to `never` after poll-callback
assignment, and adds a typed xterm render-dimensions accessor. Includes
the cross-version suites' shared releaseModuleExport adoption.

* chore(typecheck): gate the now-clean e2e typecheck in local lint

The e2e baseline is empty, so the ratchet now rejects any tests/ type
error. CI already runs it via run-ratchets; add it to pnpm lint's
explicit ratchet list and replace the stale 'not yet clean' note.

* test(mobile): typecheck every mobile test; baseline 105 files -> 0

mobile/tests-typecheck-baseline.txt grandfathered 105 test files (531
errors) whose types CI never checked. Contract changes had landed without
these tests following, and type pins in them silently checked nothing.

- Root cause: salvagedOptional (src/shared/zod-salvage.ts) cast away
  zod's optional marker, so every reply type built on it claimed
  salvaged fields were always present. Return a real ZodOptional;
  runtime is unchanged (the outer optional short-circuits undefined).
- Production now takes the port it uses: RpcOperationSender instead of
  RpcClient for send-only callers, a narrow fetch signature, and only the
  request fields push-receive reads.
- findAllByHostType/findByHostType replace `'Text' as never` lookups;
  stubRpcClient gives tests a typed RpcClient.
- Real test bugs: settings-host-client-lifecycle "relay" hosts were
  direct hosts (relayHostId no longer exists); two toEqualTypeOf pins
  could never hold; a recovery hook ran with an undefined scope key;
  a create-PR test cast to a never-imported type; "no URL" assertions
  passed on null; plus stale required props, args and enum values.

* test(e2e): parse workerStart result instead of casting it

* test(runtime): typed partial runtime stores with production-shaped fixture data

Route every partial store passed to OrcaRuntimeService through
partialRuntimeStore with typed row builders, removing 60 cast directives
that hid fixture data production never produces:
- paired-client-navigation-test-harness keyed setWorktreeMeta writes by
  `[object Object]` (it took an id where the store takes a target), so
  reads never saw them;
- invalid worktree lineage origin/capture and incomplete workspace lineage;
- getWorkspaceSession returning null where the store returns the default
  session; getGitHubCache returning undefined;
- orcad migration states missing migrationId/manifest/receipt, with a
  toEqual pinned to that incomplete shape;
- partial repos, metadata, folders, project groups and notification rows.

* refactor(renderer): resolve suppressed React hook lint instead of disabling it

109 of 187 react-hooks/react-doctor suppressions fixed:
- ~95 exhaustive-deps disables only hid stable refs and setters passed
  through controller objects; list them (identity never changes, so
  nothing re-runs), plus a few real stale closures (tabId/worktreeId).
- Effects keyed on one value that read the latest props now use
  useEffectEvent (WebConnect, skill freshness, Bitbucket dialog seeding,
  Landing preflight, automation catalog, structured-session recovery,
  file explorer).
- The conditional layout-owner hook is selected once at module load from
  the build constant instead of a rules-of-hooks disable that also hid
  the whole controller from compiler and react-doctor rules.
- A hook disable was masking a react/purity Date.now() in the palette's
  recent-tabs memo; sample it when the snapshot is captured.
- Three identical debounced-search effects share
  useTaskSearchDebouncedApply; layout snapshot merge helpers move out to
  stay under max-lines.
Remaining suppressions are mount-once resources, invalidation epochs,
deliberately keyed fields, and test harnesses that mock the dispatcher.

* chore(ratchet): exempt test harnesses and fixtures from the focus-read ratchet

The ratchet skipped *.test-fixture.ts but scanned *-test-harness,
*-test-fixture(s) and *.test-support files. Those seed settings with
getDefaultSettings (which the ratchet discovers as a focus reader) and
never route host work, so 17 baseline entries were false positives, and
replacing a test's `settings: {...} as never` with typed defaults tripped
it. Match the repo's test-support names and prune (which also drops one
stale entry), and rename the frame-ordering harness to *-test-harness like
its siblings. A blanket "-harness" match would also exempt
e2e-terminal-pty-harness, which production imports, so the names stay
explicit.

* test: merge duplicate shared/constants imports

* revert(file-explorer): restore original tree load effects pending SSH e2e investigation

* test(runtime): drop RuntimeStore cast now that the fixture is typed

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 19:37:19 -07:00
Neil 219ad610a4 fix(terminal): keep keys typed into a starting agent pane as an unsubmitted draft (#33315)
* fix(terminal): keep keys typed into a starting agent pane as an unsubmitted draft

* fix(terminal): keys typed after the bind always go live; never paste over a driven screen

* test(terminal): a deferred split with late startup work drops its held keys

* fix(terminal): capture only before the first bind; drop drafts on attach or reattach binds

* fix(terminal): leave paired-server panes' type-ahead to their own transport
2026-10-24 19:35:48 -07:00
Kelvin Amoaba 07026d586d fix(keybindings): zoom in with the + key on layouts where it needs no Shift (#33014) 2026-10-25 02:34:32 +00:00