Commit Graph
18085 Commits
Author SHA1 Message Date
Neil e9be993f47 cli: add orca plugin dev load/unload/reload, list, logs, enable and disable (#36288)
* cli: add orca plugin dev load/unload/reload, list, logs, enable and disable

* cli: move plugin handler groups out of the manifest
2026-10-30 01:28:26 -07:00
Neil 230166b9cd plugins: show the community catalog by default (#36294) 2026-10-30 01:20:40 -07:00
Neil ce7ca7f9a0 cli: name validated folders with the derived plugin publisher (#36296) 2026-10-30 01:11:12 -07:00
Neil 756d623955 perf(terminal): bound the in-process macOS process table's blocking calls and ps fallbacks (#31783) (#36282)
* fix(terminal): bound the in-process macOS process table's blocking calls and ps fallbacks (#31783)

Follow-up to #35987 from its post-merge reviews.

- cwd and executable path: node-pty's readProcessCwd/readProcessPath now run
  PROC_PIDVNODEPATHINFO and proc_pidpath on a libuv worker (the synchronous
  exports are gone, so an older pty.node falls back to ps/lsof). JS caps them at
  two outstanding lookups and 250ms; a wedged mount or a full cap answers from
  lsof -b, which never stats, so a dead NFS/SMB/FUSE mount cannot freeze the
  daemon's event loop or take the whole pool.
- Unreadable argv prints "(comm)", as ps does, instead of a proc_pidpath lookup
  under Orca's credentials on the table worker.
- The table exports each row's euid. Argv recovery runs setuid ps only for
  another user's processes, never for our own mid-exec or exiting ones (or
  SIDL/exiting rows), which ps cannot read either: a pane looping short
  commands forked ps on ~15% of full reads, now none.
- Recovery is coalesced per process across concurrent readers and a failed
  recovery waits 5s before costing another ps. The cache keys on comm and start
  time.
- Full-table and shell-foreground captures, which feed strict evidence with
  the capture's age, take only argv ps read after their request; display
  readers keep the 30s cache.
- While the reader is down (stalled-pool breaker open, or a rejecting addon,
  which now backs off 1s..30s), runPsInProcess runs /bin/ps itself through one
  shared budget: identical invocations share a run, a burst of 4 forks then one
  a second, and a run spawned before a request never answers it. Descendant
  teardown and foreground-group signalling keep their own full-timeout ps
  (callerRunsPs). 13 pollers at 750ms: 1,040 ps/min before, 63 after.

No daemon protocol bump: the wire format is unchanged, and each daemon loads
JS and pty.node from the same runtime copy.

* fix(terminal): make the libproc reader survive worker teardown, fail closed and share one fair fork budget (#31783)

Review follow-ups to the previous commit.

- Native: every libproc AsyncWorker derives from OrcaPromiseWorker, which skips
  JS completion once an env cleanup hook marks the env closing and swallows a
  Napi::Error thrown mid-teardown. Terminating a worker_thread with cwd or table
  reads in flight aborted the process; 200 terminates each now survive.
- (comm) in a terminal's foreground group (argv neither reader recovered, e.g.
  a root `su`) judges 'unknown', never 'agent', so the launch line is not typed
  into it.
- Fresh argv only for getFreshSnapshot captures; the 500ms TTL readers keep the
  30s cache. Argv recovery runs through its own fork budget (2, then one per
  2s). Root `su` pane, 13 pollers at 750ms: TTL 79 -> 2 ps/min, fresh 158 -> 31.
- The fork budget serves invocations in FIFO turns, grouping each one's waiters
  onto one run. 13 streams: served 80,42,1,1,2,0x8 -> 10-12 each.
- Forced subprocess captures (a held naming pass) go through the fallback
  budget: 5 readers, 400 direct ps/min -> 63, 395 of 400 captures served.
- A failed recovery is retried 5s after ps gave up, not after it started.
- Tests pin Orca's euid instead of reading the runner's and assuming root is 0.
- process-cwd keeps one lsof per pid until it exits, so a dead mount no longer
  leaks one per poll; shell readiness reads the exe path through runProcess,
  which gives up on an lsof that ignores SIGTERM.
- A #35987 pty.node (table reader, no async path reads) keeps the in-process
  table; cwd/path use lsof, with a one-time warning.
- captureProcessTable moves to process-table-ps-capture.ts.

* fix(terminal): make withheld argv unverifiable and reuse recovered argv for at most 2s (#31783)

Round-2 review follow-ups.

- Worker teardown: drop OrcaPromiseWorker and its env flag (Node drains the
  pool before cleanup hooks, so it never fired). node-pty's mac pty target now
  builds with NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS, which covers both the
  call-in and completion paths. The smoke test now calls the reads from a
  timer while terminating: the previous build aborted 2 of 3 runs, this one
  survives 3/3 x 100. pty.cc is back to the first follow-up's exact content.
- A foreground process whose argv ps withheld (`(comm)`: another user's,
  exiting, or a recovery the budget skipped) makes the batch resolver, and so
  host-stamped evidence, `argv_unreadable`/unverifiable rather than live with no
  agent; agent-foreground resolution reports it unavailable.
- judgeTerminalForeground fails closed only for an unreadable shell (`(bash)`
  from a root `su`), not our own exiting `(git)`.
- Recovered argv is reused for at most 2s per identity (pid, start, comm) for
  every reader (the next commit ages evidence by it), and
  fresh reads no longer queue behind the recovery budget. Root `su` pane, 13
  fresh pollers: p50 2,989ms -> 53ms, 31 -> 26 ps/min (TTL reader 1 -> 26).
- The fork budgets serve interactive and fresh readers before display polls
  (cheap and TTL snapshot captures), FIFO within each. 20 display streams plus
  a 3s launch-paste read every 5s: 0/12 -> 12/12 served, polls 4-7 each.
- On a selected terminal, the foreground group's argv is recovered even with no
  process of ours left (`exec su`); the root login is not.
- Budgeted captures keep the 32 MiB output ceiling.

* fix(terminal): age strict evidence by its oldest recovered argv (#31783)

Round-3 review follow-ups.

- Recovered argv carried no read time, so a capture reusing it (cached, or a
  recovery still in flight) stamped its own capture time over argv up to 2s
  older, and the remote write guard could take a same-comm re-exec for the
  agent. Rows now carry when ps read their recovered argv; runPsInProcess
  reports the oldest through onArgvReadAt, and the snapshot reader stamps
  capturedAtMs at that input, so capturedAgeMs is the age of the oldest input
  and consumers' own freshness checks (the write guard's 500ms) decide. A
  recovery begun more than 2s before a reader asked no longer answers it, and
  an older recovery finishing late cannot replace a newer one.
- resolveSpawnFileForegroundFromRows reports a withheld `(node)` foreground
  unavailable.
- One budget queue entry per invocation: an interactive request promotes a
  queued poll's, a poll joins an interactive one.
- parseShellForegroundRows gets its JSDoc back.

* fix(terminal): keep a cached name from authorizing a refused write; integer, under-2s argv ages (#31783)

Round-4 review follow-ups.

- When the relay's evidence declines a write (stale, unverifiable, another
  agent), its foreground name may still prove the shell but no longer proves
  the agent: that name can be the tracker's 1s display cache, e.g. `claude`
  cached just before Claude exited to a root shell under su. Relays that send
  no evidence keep the name as before.
- Snapshot ages round up to whole milliseconds; the wire rejects fractions
  from the monotonic-to-wall conversion.
- Recovered argv is reused for at most 1.5s, so reuse plus the 500ms snapshot
  cache stays under the 2s freshness gate; reuse ages from when that ps
  spawned, not from the wait for its fork token, and only an answer is
  remembered (a timed-out or withheld run proves nothing). Fork budget
  unchanged. Root su pane, 13 pollers: 30 ps/min; fresh p50 51ms; strict
  evidence age p50 752ms, max 1,508ms.

* fix(terminal): keep the relay's agent name behind structurally unverifiable evidence (#31783)

The previous commit refused the name fallback whenever the relay sent any
evidence, so `unverifiable` evidence for structural reasons also blocked
writes: npm Codex (node codex.js spawning native codex) and Gemini (relaunching
itself) put two agent rows in the foreground group (ambiguous_foreground_group),
and remote tmux reads multiplexer_boundary. On SSH POSIX hosts that dropped
launch prompts and failed worker briefs, conversation send/cancel and
automations with agent_not_in_foreground.

The name now cannot authorize only when the evidence saw the group (`live`:
stale, or no agent in it, as in the cached-`claude`-over-root-shell repro) or
withheld a foreground argv (`argv_unreadable`, possibly a root `su` shell).
Other unverifiable reasons keep the name fallback, as before this branch.

* fix(terminal): let a relay name complete only fresh agent-positive evidence (#31783)

The SSH name fallback still let a stale or cached name authorize a write under
any unverifiable reason but argv_unreadable: ps EAGAIN (process_table_unreadable)
after the tracker cached `claude` over a root bash, anchor_missing,
tty_boundary (`sudo -i` with use_pty, a root shell on a new pty), or a 1.5s-old
ambiguous capture.

- The name now completes evidence only when it is fresh (within the guard's
  500ms bound), its reason is one that saw an agent row
  (ambiguous_foreground_group, multiplexer_boundary,
  candidate_start_time_missing), and the name is the launched agent. Every other
  reason, including ones this build does not know, reads unknown. Relays that
  send no evidence keep the name, for mixed versions.
- The relay's evidence names one agent that holds two rows of the group (npm
  Codex: node codex.js spawning native codex; Gemini relaunching itself), so a
  new relay proves them live even when its name is `node`. Two different agents
  stay ambiguous. No wire change.

* fix(terminal): judge a relay name by the host's capture age; keep old relays' npm Codex (#31783)

- Name completion compared the capture's start with the read's start, so a
  slow response made old evidence look fresh: a capture 1,500ms old arriving
  after 1,100ms passed. It now uses the host-reported capturedAgeMs against
  the 500ms bound, which latency cannot shrink. Live evidence keeps its
  capture-start rule.
- Relays before same-agent dedupe report npm Codex (node wrapper plus native
  binary) as ambiguous_foreground_group and name it `node`. For that reason
  only, `node` now completes the evidence when the launched agent is
  npm-installed per the node entrypoint tables; other agents and reasons stay
  fail-closed.

* fix(terminal): bound relay-name completion by twice the snapshot TTL (#31783)

The 500ms bound refused ~9.5% of tmux name completions on a host with 13
pollers (cached snapshot up to one 500ms TTL old plus ~30ms capture, max
528ms), and a refusal drops the launch prompt or throws with no retry. The
bound is now 2 x PROCESS_TABLE_SNAPSHOT_MAX_STALENESS_MS (1s), still on the
host-reported age: 0 of 767 reads exceed it, the delayed 1,500ms repro still
refuses, and the cached-name hazard (the tracker's ~1s display cache) is no
wider.

* fix(terminal): complete relay evidence with a name read now, not the display cache (#31783)

With the 1s bound, a capture at 0-528ms, `codex` cached at 100ms, Codex
exiting at 101ms and the guard at 999ms still let the cached name authorize a
write over the bash that replaced it.

- Name completion (structural reasons, host age within 2x the snapshot TTL)
  now asks confirmForegroundProcess, which reads the foreground now (a fresh
  scan, or node-pty's raw process name) rather than the tracker's 1s display
  cache; a null answer reads unknown. No new wire surface: the local daemon answers
  confirmForegroundProcess, paired runtimes evaluate guards locally, and the
  production controller returns null (read as unknown, failing safe) when a
  provider lacks it. Controllers without the method, and relays sending no
  evidence, keep the cached name as the legacy path.
- Live evidence also accepts a host-reported age within 2x the TTL, so a real
  agent behind a 500-528ms cached snapshot on a fast link is no longer
  refused; a capture begun after the read was asked still counts, and
  5,000ms-old evidence still refuses.

* fix(terminal): confirm live evidence older than one snapshot TTL with a fresh read (#31783)

Accepting live evidence up to 2x the TTL reopened the window the previous
commit closed for name completion: a capture at 0-528ms, the agent exiting at
~529ms, and at 999ms `live claude` still read as agent over a bash.

Live evidence begun no more than one TTL before the read was asked (so any
host age within one TTL, however long ps took) still answers alone. Between
that and 2x the TTL, confirmForegroundProcess reads the foreground now: the
launched agent proves it, a shell reads shell, anything else unknown.
Controllers without that read fall through and refuse, as before.

Reachability: the remote (host.remote) write-guard path has no production
caller since the SSH provider's removal (#27499); the registry dispatches only
local providers and paired runtimes evaluate guards locally. This is defence
in depth for any future remote provider.
2026-10-30 01:05:34 -07:00
Jinjing e9e4e94844 Reorder same-ID worktrees independently by host (#36269)
* Reorder same-ID worktree copies independently by host

* Use host-qualified keys for Kanban drag test fixtures

* Sync board task statuses by worktree host identity

- Ensure same-ID copies update their own host's Linear issue and status

* Preserve captured workspace ownership during queued status sync

- Skip Linear updates when the original host-specific workspace is removed
- Avoid borrowing status or credentials from a same-ID twin workspace
2026-10-30 01:03:22 -07:00
Jinjing 5b505a6e94 Allow conflict-safe private storage from plugin panels (#36273)
* Support conflict-safe private storage in plugin panels

* Update frame and worker tests for host API 1.1

* Use required braces in storage conflict guard

* Update renderer handshake expectation for panel storage API

* Clarify null comparisons and exclude inherited storage keys
2026-10-30 01:02:21 -07:00
Neil f7ff1ee2ff docs(plugins): drop the donation-link and description-URL listing rule (#36291) 2026-10-30 01:00:34 -07:00
Neil 1963ac0ea8 cli: add orca plugin create, validate and inspect (#36280)
* cli: add orca plugin create, validate and inspect

* build: ship orca plugin validate's main checks as a CLI main entry
2026-10-30 01:00:15 -07:00
Neil 5dd43d0146 refactor(jira): group saved-filter picker owners (#36203) 2026-10-30 00:47:17 -07:00
Neil 8e61c440df plugins: derive the publisher from where a plugin comes from, like a Go module path (#36281)
The manifest publisher is deprecated and ignored for catalog and Git installs:
catalog installs use the listing id, Git URL installs the URL owner, folders
'local' (or their still-declared publisher). Existing installs keep their key.
A format 2 manifest may omit publisher only with engines.orca >=1.4.246, so
older Orca reports 'requires Orca X' instead of failing to parse it. The v2
catalog documents an optional ownerId, which older Orca already strips.
2026-10-30 00:45:00 -07:00
Kelvin Amoaba 4410ef318e fix(browser): let agents and users answer page alert, confirm and prompt dialogs on their page (#36268)
* fix(browser): let agents and users answer page alert, confirm and prompt dialogs on their page

* fix(browser): watch a replacement guest for dialogs and ignore the opening keypress

* fix(browser): ignore a repeated Enter in a guarded prompt field
2026-10-30 07:39:38 +00:00
Neil 9470b4618c plugins: require an explicit approve fingerprint for RPC plugin grants (#36279) 2026-10-30 00:36:49 -07:00
Brennan Benson ca84c49b35 Keep cancelled async questions hidden and show new ones (#35870)
* fix(chat): show each repeated async question

* fix(chat): keep async question identity stable across readbacks

* test(chat): preserve async question fixture types

* Keep async question cancellation scoped to individual occurrences

* Use checked types in async question test fixtures

* Share sender-aware async question retirement across chat views
2026-10-30 00:36:11 -07:00
Neil 636164029c fix(plugins): re-verify installed plugin content on every load (#36277)
* fix(plugins): re-verify installed plugin content on every load

* test: rename integrity cases
2026-10-30 00:28:38 -07:00
Brennan Benson 46595532b9 fix(pi): use discovery for shared model menus and defaults (#36194)
* fix(pi): keep the last good model list when discovery fails

* test(pi): allow void-returning catalog close mock

* fix(pi): make discovery own account model menus and defaults

* test(pi): align prewarm recovery with discovery ownership

* refactor: compact catalog default entry construction
2026-10-30 00:26:00 -07:00
Kelvin Amoaba bafbf406c9 fix(browser): keep snapshot refs on server browsers that use an external Chromium (#36276)
Every command re-selected its tab first, and agent-browser drops the last
snapshot's refs on any tab select, so each @ref failed as Unknown ref.
Select the tab only when it is not already active.
2026-10-30 07:24:24 +00:00
Neil f78b5979ca docs(plugins): add plugin listing policy (#36275)
* docs(plugins): add plugin listing policy

* docs(plugins): include GitLab owners in publisher rule
2026-10-30 00:22:57 -07:00
Neil f879c8d6f9 plugins: open only the install-source repository link and render only host-served plugin images (#36270)
* plugins: open only the install-source repository link and render only host-served plugin images

* i18n: drop the removed plugin Homepage label
2026-10-30 00:19:36 -07:00
Kelvin Amoaba 7358da227b fix(browser): keep SSH workspace browser pages from reloading when you switch back (#36266)
* fix(browser): keep SSH workspace pages from reloading when their pane remounts

* fix(browser): re-gate SSH pages after unrouted browsing and recheck verified routes on remount

* fix(browser): destroy only SSH page guests that are off the verified route

* refactor(browser): share the ready route builder and isolate SSH route tests
2026-10-30 06:55:57 +00:00
Kelvin Amoaba b67c5254f0 fix(browser): agent fill, select, upload and type change the page or fail with a reason (#36263)
* fix(browser): fill, select, upload and type act on the agent's element or fail

* refactor(browser): move agent key commands into their own bridge layer; fix test sender call
2026-10-30 06:48:58 +00:00
Kelvin Amoaba 46237aa148 fix(e2e): return from every path of the WSL boot guard's running-list read (#36261)
#36256 made one branch return the retry promise while the others fell
through, which trips noImplicitReturns (TS7030) and turns the e2e
typecheck ratchet red on main.
2026-10-30 06:36:12 +00:00
Jinjing 57f26516bf docs: prefer focused validation in agent instructions (#36264) 2026-10-29 23:35:35 -07:00
Neil 24795f5bd1 fix(agent-session): report an ACP or Pi CLI the supervisor could not spawn as missing (#36229)
* fix(agent-session): report an ACP or Pi CLI the supervisor could not spawn as missing

The ACP and Pi connections never marked a supervised spawn ENOENT on their
exit errors, so a missing OpenCode, Grok or Pi CLI read as a provider exit
or a failed start. Mark both connections' exit errors with the managed
process's spawn absence, and route marked exits through the startup failure
fact in the ACP startup end, the ACP and Pi failed-start errors, and Pi's
unexpected exit. Note why Codex's close site cannot see a spawn ENOENT.

* fix(acp): mark a failed start whose exit only the close proved

When the stream closed before the exit report and the exit landed after the
grace wait, the start rethrew its error without the spawn-absence mark. Mark
the start's error once its exit is proven, which the exit-proven wrapper also
carries as its cause.
2026-10-29 23:02:21 -07:00
Neil 480bcfc3ba fix(wsl): re-read a distro's automount root after Orca wakes it, at most every 5 min (#36225)
* fix(wsl): re-read a distro's automount root after Orca wakes it, at most every 5 min

* test(wsl): pin that an unchanged automount re-read does not notify
2026-10-29 23:02:13 -07:00
Neil 511e4feca4 docs(wsl): say what keeps a WSL distro up besides the holder (#36241)
On WSL 2.7.10 a process started through wsl.exe (orcad via setsid -f, its
terminals) keeps the distro Running with no Windows-side client; the holder
only covers the gaps when nothing runs. Reword the comments that assumed
only a Windows client keeps a distro from idling out.
2026-10-29 23:01:32 -07:00
Brennan Benson 28e4764cdd Keep existing Continue actions reliable after agent exit and failed starts (#36074)
* Fix lifecycle handling for existing Continue actions

* Preserve legacy import and owned Windows cleanup

* Match pending creation membership contract

* fix(continue): align sweep and imported source contracts

* Combine terminal claim type imports

* Classify own-property checks as layout reads

* Report pre-spawn failure in WSL cwd fixture

* Load saved CLI history without a retained source row
2026-10-29 23:00:07 -07:00
Neil a5c0c4465d test(windows): reap every process the isolated-spawner suite starts, including skipped paths (#36249) 2026-10-29 22:56:04 -07:00
Brennan Benson a856bc8af2 fix(cli): preserve runtime access across Linux PID namespaces (#35769)
* fix(cli): preserve runtime access across Linux PID namespaces

* fix(cli): give retry advice after runtime replacement

* fix(cli): preserve private offline admission policy

* test(cli): align admission and launcher contracts

* test(cli): prune resolved wall-clock allowance

* test(cli): narrow dropped runtime errors without casts

* test(cli): use explicit extension for hook service import

* test(cli): replay recorded Linux sandbox denial

* test: verify packaged Linux desktop CLI ownership

* test: handle denied FUSE mounts in desktop fixture

* test: use privileged PID namespace in desktop fixture
2026-10-29 22:55:19 -07:00
Neil 6efdd36dcb fix(ui): notification cards lift above a chat composer they would cover (#36233)
With the right sidebar closed, the bottom-right cards (Update Available,
star prompt, sign-out, Codex notice) sat over the chat composer's Send and
Stop buttons. Composers register their box; while one sits under the
cards' resting column, the stack (and the toaster above it) rises clear of it.

Fixes STA-12887
2026-10-29 22:54:27 -07:00
Neil 58c50f294a fix(wsl): user clicks on cwd-less gh may start the stopped default distro (#36230)
* fix(wsl): user clicks on cwd-less gh may start the stopped default distro

#35709 stopped background gh/glab from booting a stopped default distro,
which also refused explicit clicks for users whose gh lives only in WSL.
Starring Orca, the auth diagnosis, the project picker, opening a work
item and board edits now run as a user act on the distro the fallback
uses; the board table reload, which also runs unprompted, stays gated.
The GitHub and GitLab rate-limit cards keep their last snapshot on the
not-running refusal instead of flipping to unavailable.

* fix(wsl): only an explicit click may start the stopped distro for project gh calls

Wrapping the project-view and auth-diagnosis IPC handlers as user acts
also let mount effects (useProjectViewTable listing a restored board's
views, GhAuthErrorHelp's diagnosis) start a stopped default distro. The
handlers now wake only when the renderer passes wakeWslDistro, which the
picker browse/select, opening an item and every edit set; mount effects
leave it unset, and the auth diagnosis never wakes.
2026-10-29 22:51:03 -07:00
Neil 593e1dbc60 test(e2e): retry a WSL terminate that never took, once, when Orca launched nothing (#36256)
* test(e2e): retry a WSL terminate that never took, once, when Orca launched nothing

* test(e2e): log PTY spawns for the E9 guard and refuse the terminate retry after one
2026-10-29 22:50:41 -07:00
Neil 0b2158a394 fix(wsl): name the stopped distro, in the user's language, when main holds a terminal start (#36228)
Worktree-create startup, setup and initial terminals built their warning
from the raw terminal_held_wsl_distro_* code, and the window showed it
as is, as it did for a held pane recovery. Main now writes the readable
sentence into those warnings, and the window swaps either form for
localized copy naming the distro. The runtime spawn's hold and its
wslBackgroundStart option now share one verdict.
2026-10-29 22:47:30 -07:00
Neil 16f326ed79 test(acp): await the escalation's first check and delivery instead of fixed event-loop turns (#36238) 2026-10-29 22:44:47 -07:00
Neil 11a066b934 fix(wsl-cli): removing the WSL command from a deleted distro forgets its registration (#36227)
wsl.exe refuses any command for a distro that was unregistered, so Remove
failed and the distro stayed in wsl-cli-registrations.json for good. A
distro-not-found failure now drops every bookkeeping entry for it
(registration, inspection time, reconciliation) and reports not installed.

Fixes STA-12893
2026-10-29 22:44:40 -07:00
Kelvin Amoaba 2b6e63ee2f fix(browser): reject a ref from another tab's snapshot after a tab switch (#36251)
Each page has its own agent-browser ref map, so an unpinned `click e2` after
`tab switch` hit the new tab's e2 and reported success.
2026-10-30 05:44:04 +00:00
Brennan Benson 2e37fc4571 fix(editor): scroll combined diffs with keyboard navigation (#35004)
* fix(editor): keep combined diff keyboard cursors visible

* fix(editor): retain focused diff sections through height changes

* test(editor): bound combined diff reveal and measurement work

* fix(editor): share combined diff viewport intent across review hosts

* test: verify worktree tree navigation cancels cursor reveal

* test: assert cursor reveal clears before tree scroll

* test: use typed diff instrumentation and fixture convention

* fix: declare implemented diff content size event

* Simplify combined diff cursor reveal and keep focused regression tests

Keep keyboard cursor geometry mapped to the surrounding viewport and sticky header. Remove speculative focused-row retention, deferred following and its manual-input cancellation; restore existing section-height measurement.

Retain split/inline real-Monaco keyboard cases, click-source preservation, and both PR Files hosts covering the review-found missing viewport markers. Drop redundant timing, tree and operation-count fixtures and restore render-range baseline tests.
2026-10-29 22:36:25 -07:00
Brennan Benson f26fb1cfda Keep async question controls available after agent notices (#35758)
* fix(chat): keep async questions open across agent notices

* test(chat): cover answering async questions after agent notices
2026-10-29 22:33:23 -07:00
Kelvin Amoaba 0c99ccb3da fix(browser): save agent downloads to the requested --path and fail fast when none starts (#36240)
Orca's will-download handler picks every guest download's save path, so
agent-browser's own download (CDP download dir plus guid rename) never saw
the file: it landed in ~/Downloads and the command failed with a GUID error,
or after 30s when nothing downloaded. The bridge now claims the page's next
download for the requested path, clicks through agent-browser, and reports
the saved path, a 10s no-download error, or a failed download.
2026-10-30 05:27:46 +00:00
Neil 7971ccf1ca feat(wsl): let an idle WSL host's orcad exit after 5 minutes (#36243)
An idle orcad alone keeps its WSL distro, and the ~1.2 GB VM, running with
no Windows client. WSL launches now pass ORCA_ORCAD_IDLE_TIMEOUT_MS=300000;
orcad honours it through the same managed idle exit (no clients, terminals
or enabled automations), only to shorten its 15-minute default, with a
one-minute floor. SSH launches never carry it; older orcads ignore it.
2026-10-29 22:18:29 -07:00
Kelvin Amoaba 40552b0596 fix(browser): stop agent tabs in background worktrees reloading every ~10 s (#36245)
The hidden-worktree guest budget ranked worktrees only by user activation, so a
worktree an agent drove in the background sorted last. Its automation lease was
its only veto, and when the lease lapsed 10 s after each command the retention
pass destroyed its webview; the next command loaded a fresh page.

Paint-retention claims (agent lease, phone driver, paired viewer) now count as
use when ordering the budget, and a worktree under a veto keeps its guests
without taking one of the four slots from the user's recent worktrees.
2026-10-30 05:15:13 +00:00
Neil cd0d6d9300 ci(windows): install Electron once before the Windows boundary tests (#36248) 2026-10-29 22:14:00 -07:00
Kelvin Amoaba e284f85e70 fix(computer): preserve Unicode in Windows typing (#36244)
* test(computer): verify task event payloads

* fix(computer): preserve Unicode in Windows typing
2026-10-30 05:13:17 +00:00
Kelvin Amoaba 24cebf03b5 fix(computer): verify Linux window restoration (#36234)
* test(computer): verify task event payloads

* fix(computer): verify Linux window restoration

* fix(computer): restore managed Linux windows

Exclude unmanaged helper windows from PID fallback without
losing minimized windows.
2026-10-30 05:11:57 +00:00
Kelvin Amoaba 219e999846 test(computer): verify task event payloads (#36239) 2026-10-30 05:10:47 +00:00
Neil 303cbbbb57 refactor(cli): keep the retrying PATH command private to the idempotent write (#36237) 2026-10-29 22:10:15 -07:00
Neil 17828c78f1 fix(chat): keep unconfirmed effort menus for agents other than Pi (#36242)
#34592 made the effort picker hide any model whose effort menu is
unconfirmed (effortsKnown: false), which Pi needs because its menus are exact.
#36158 relies on OMP showing exactly such recorded menus for models that are
not running, so the two merged into failing OMP tests on main. The hide now
applies to Pi only; OMP, Claude and Codex offer unconfirmed menus as before.
2026-10-30 04:59:32 +00:00
Kelvin Amoaba 9b4c899dc8 feat(mobile): match every text input to the chat composer and rebuild the terminal dock (#36166)
* feat(mobile): give every text input the chat composer's look

Adds shared MessageBox, TextField and ComposerSendButton built from the
composer's own styles, and moves chat, form, search, Tasks, PR, review and
commit inputs onto them. The commit message becomes multi-line, every input
is 16pt (no page zoom on focus), and focus rings are gone. The terminal and
browser typing docks are unchanged.

* feat(mobile): rebuild the terminal dock around Keys and Message modes

Agent tabs open in Message mode, where you write in the chat composer and
Send types it into the terminal. Shell tabs open in Keys mode, where each
letter goes straight to the terminal through the live field. A pick made on
an agent tab lasts until the agent quits. The shell/agent rule is the one
keyboard dismissal already used, now shared.

The key row carries sticky ctrl, alt and shift (tap for the next key,
double tap to lock) and one arrow pad (tap a side, or hold and drag to
repeat through the existing held-key repeat). Paste, attachments, the
display width, the remaining keys and custom keys move to a ⋯ sheet. Return
in the composer adds a line; Send sends.

* fix(mobile): read arrow-pad taps from the pad and keep every key reachable from ⋯

A touch on a chevron made the icon the touch target, so the side was
measured against the icon's box and most taps read as left. The ⋯ sheet
now leaves out only the keys the current row shows, so agent tabs get Tab
and shell tabs get Shift+Tab and Enter back.

* fix(mobile): keep the last changed files clear of a growing commit box

The file list's bottom inset was a fixed 196 pt, so a commit message several lines long hid the last rows behind the commit bar. The inset now follows the bar's measured height.

* test(mobile): give the file list test its bottom inset
2026-10-30 04:51:47 +00:00
OrcaWinandOrcaWin 8aac9c1254 test: remove 28 low-value test suites (#36226)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 21:39:26 -07:00
Neil 067a0dd1b4 fix(runtime): delegated devices follow the device file, and quarantine keeps external adds (#36222)
* fix(runtime): plan delegated children over the device file as it is now

An unchanged child removed on disk skipped the save and its merge, so
its stale token was handed back. The upsert now adopts external edits
first and mints a fresh child; a parent removed on disk mints none.

* fix(runtime): a delegated phone stops authenticating once its desktop is gone

Removing a desktop's row on disk (or any removal short of
revokeRuntimeAccess's cascade) left its delegated phone rows valid.
Token and per-request principal auth now refuse a delegated child whose
parent device is no longer in the registry.

* fix(runtime): keep devices another writer adds while our own quarantine is unwritten

While quarantinedUntilWritten is set, the save no longer skips the disk
read; it merges with no known baseline, so the file's absence revokes
nothing but a device the pairing CLI added since is kept.
2026-10-29 21:29:32 -07:00
Jinjing a702b4ff8b Clarify when to run handoff checks (#36231) 2026-10-29 21:27:57 -07:00