Commit Graph
16536 Commits
Author SHA1 Message Date
Brennan Benson f71120551f Stop workers from taking over the Run they work for (#29008)
* fix(orchestration): refuse run-use by a worker on the Run it works for

A worker holding an active Dispatch in a Run could bind that Run as its coordinator.
That silently unbound the real coordinator, remembered the worker's address as a
coordinator address (so the worker's own mail in that Run routed to the Run mailbox
from then on), and when the worker later bound its own sub-Run, left the parent Run
with no coordinator at all.

bindRun now refuses a caller whose handle holds an active Dispatch in the Run, with
worker_cannot_coordinate_own_run, before any effect. Creating its own Run for
sub-workers is unchanged.

* fix(orchestration): tell a worker naming its own Run where its mail is

Workers that made a sub-Run ran `check --run <parent>`, were told "This
coordinator terminal is bound to X, not Y", and ran run-use on the parent
to "switch back", unbinding their coordinator. That refusal now says the
Run belongs to their coordinator, that their own mail arrives through
plain `check`, and that they report with `send`; it never mentions run-use.

The run-use refusal now matches the caller the way check and send do
(address, then pane, so a reminted terminal handle is still caught),
also covers Runs above the caller's own through recorded creator_dispatch_id
lineage, skips context-only self-dispatches so a coordinator can still
rebind its own Run, and passes its code through the RPC wire.

* feat(orchestration): refuse run-use over a live coordinator without --takeover

run-use silently took a Run from whoever coordinated it, even a chat or
agent that was still running. It now refuses with run_coordinator_live
when there is positive evidence the current coordinator is running (its
chat is still reachable, or the agent hooks prove its terminal agent
live) unless the caller passes --takeover. Anything unproven (closed chat,
exited or unhooked terminal, another host) rebinds as before, so restart
handoffs need no flag. The probe is async in the RPC handler; bindRun
enforces it only if the Run is still bound to the probed party.

A caller working a Dispatch can never take over, with or without the
flag (worker_cannot_take_over_run). The help text now says run-use is
for resuming a Run and that workers never use it.

* fix(orchestration): stop pointing workers at run-use

Workers learned run-use from error text: "No Run is bound. Use run-create
or run-use first", "Rebind with orchestration run-use", and "Rebind this
terminal with orchestration run-use". Each now says what the caller can
do instead. An unbound worker is told its mail arrives through plain
check and it reports with send; a displaced coordinator is told to stop
and take the Run back only if the user asks. The orchestration skill now
says run-use resumes your own Run, --takeover needs the user's word, and
workers never run it.

* fix(orchestration): stop routing mail to addresses that grabbed a Run's seat

Every address that ever bound a Run is remembered as one of its
coordinator addresses, so mail to it routes to the Run mailbox. When a
worker bound the Run it was working for, its own address joined that
list for good, and its direct mail in that Run kept landing in the
coordinator's inbox. The live database has 45 such rows since
2026-08-20.

All four readers of the remembered addresses now skip one that was first
bound while it worked an unsettled, delegated Dispatch in the same Run.
It is derived from existing rows, so no migration or delete is needed and
rows written by older builds stop mattering. The active-Dispatch check
also matches a worker's orca_session_id spelling, not only its handle.

* fix(cli): keep the orchestration spec file within its line limit

* fix(orchestration): read remembered coordinator Run ids without a type assertion

* fix(orchestration): compare seat-grab times at whole seconds

first_bound_at has no milliseconds, so a worker bound in the same second its
Dispatch settled was counted as grabbing the seat. Compare completed_at at
whole seconds with a strict >.

* fix(orchestration): a worker coordinates only Runs it created

The worker refusals depended on proving the target's coordinator alive, so
a worker could still take any Run whose coordinator was closed, unhooked,
remote or headless. Replace them with one rule derived from existing rows:
a caller working a Dispatch may bind only a Run it legitimately
coordinated before (a remembered, non-seat-grab address of that Run, or a
Run it dispatched work into), never the Run it works for, and never with
--takeover. A same-binding no-op is never refused, and workers are
classified before the legacy gate so they never see its
--takeover-legacy hint. The refusal names the Dispatch and how to end it
with worker-abandon if it is stale. The ancestor walk is gone.

run-use now records which coordinator it probed. If the binding moved
before the transaction, it probes again (three tries) and then refuses
with a retryable run_binding_changed instead of binding over a party
nobody probed. run_coordinator_live names the chat by its title and
worktree, or the terminal by its title and worktree, says it is still
open, and that closing it clears the refusal.

* fix(orchestration): say what happens to mail on takeover and stop naming run-use to readers

The help now says --takeover replaces the coordinator and replays its
unacknowledged mail to you. A replaced mailbox reader is told only that
another session coordinates the Run and to stop reading it.

* refactor(orchestration): throw one non-null refusal from the live gate

* refactor(runtime): host the coordinator presence probe beside the hook presence seam

Main moved the orphan-adoption runtime file; keeping the one-line probe next
to checkHookAgentPresenceFn leaves this PR off that file.

* fix(orchestration): use findLast for the worktree name

* refactor(runtime): move the coordinator presence probe beside the pty presence recheck

Main is moving the runtime construction files; the probe now sits with
recheckHookAgentPresenceForPty, which reads the same seam, so this PR stays
off the files being moved.

* fix(orchestration): keep workers out of their own Run seat

* fix(orchestration): clarify worker Run handoffs in skill

* test: align explicit Run gate refusal wording

* Move coordinator presence beside terminal presence checks

* Walk complete worker creator lineage when binding Runs

* Restore main documentation after merge hook formatting

* perf(orchestration): check run bindings without terminal snapshots

* test(orchestration): narrow SQLite instrumentation before access

* test(orchestration): import the explicit RPC methods module

* test: cover orchestration restart and continued Run handoff

* test: place orchestration CLI integration in CLI project

* test(cli): use explicit module extensions in restart handoff test

* test(orchestration): isolate source CLI integration in subprocesses

* refactor(orchestration): leave the live-coordinator takeover rule to #29292

#29008 is the worker fix: a worker cannot bind the Run it works for or an
ancestor, cannot abandon itself to get around that, and addresses it held while
grabbing a seat stop redirecting its mail. The separate rule that refuses any
second coordinator while the first is still open (the presence probe, the
--takeover flag and the run_coordinator_live / run_binding_changed refusals)
moves to #29292, which models Run ownership and hand-over and already builds on
it. run-use binds synchronously again, as on main.

* test(orchestration): cover delegated worker legacy takeover refusal

* test(orchestration): explain source CLI integration timeout
2026-10-26 00:46:27 -07:00
Jinjing e4b1e4d22b Revert "fix(native-chat): preserve Claude approval choices across model chang…" (#33823)
This reverts commit 4833b736f7.
2026-10-26 00:44:45 -07:00
Brennan Benson 9149d77de4 fix(chat-rename): skip invisible legacy tab names during rename migration (#33678)
* fix(chat-rename): skip invisible legacy tab names during rename migration

* test(chat-rename): bound legacy migration reconciliation work
2026-10-26 00:41:38 -07:00
OrcaWinandOrcaWin a25a5f1fa7 perf(devex): parallel pnpm lint (169s → 50s), capped typecheck threads, fresh shard timings (#33817)
* perf(devex): parallel lint, capped typecheck threads, fresh shard timings

- pnpm lint runs its 37 steps in a bounded pool (run-lint.mjs).
- tsrs defaults to 8 checkers; check:changed --maxWorkers=N passes 2N.
- ci-shard-timings refreshed from an 8-vCPU PR run (old one lacked 1,976 files).
- tc/typecheck/dev/postinstall call node directly instead of nested pnpm run.

* fix(typecheck): keep resolveTypecheckCommand args inferred for mobile's strict test typecheck

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 00:39:55 -07:00
Neil 83ca5b6b6f fix(agents): re-list a host's terminal agents when contact returns (#33816)
* fix(agents): re-list a host's terminal agents when contact returns after a failed probe

* fix(agents): list recordKey in the detection effect's dependencies
2026-10-26 00:38:42 -07:00
Brennan Benson 56025f21a4 Give native chats a fresh automatic name after /clear (#32287)
* Chat renames are saved as the chat's name, so Session History shows them after the tab closes

Renaming a native chat tab only changed that window's tab. Session History, phones and other windows read the host's saved name, so the rename vanished from History once the tab closed or Orca restarted.

A rename now goes to the host that owns the chat (agentSession.rename) and is saved as the chat's one name, the field History, tabs, sidebars and phones already read. The record remembers that the user chose it, so automatic naming never replaces it. A window's pre-upgrade tab rename is uploaded once and only fills a name Orca chose. Hosts without the new capability keep the old tab-only rename. Every native agent's History row now shows the chat's name once it has one.

* Keep saved chat names consistent across readers and reconnects

* Carry qualified chat names into cached readers

* Reuse the history recorder context across platforms

* Use recorded chat ownership for legacy name transfer

* Transfer legacy chat names only from known catalog ownership

* Correct recorder path matching and History subscription order

* Require complete evidence for bridged parity exclusions

* Preserve sparse array lengths in complete recording comparisons

* Initialize History observation before loading workspace context

* Integrate measured History recordings and scoped parity evidence

* fix chat naming retries and certify both replay modes

* fix ambiguous chat rename labels after navigation

* preserve chat rename intent across tab updates

* type dashboard snapshot fixtures without assertions

* fix: align chat name observation with store contracts

* test: update chat name consumer fixtures

* test: distinguish sender naming metadata from status

* Preserve saved Activity chat names across tab focus

* Clarify Activity tab projection identity

* Remove package-manager lockfile churn from main merge

* Refresh automatic chat names after clearing context

* fix(runtime): validate tab property edits before saving chat names

* Preserve naming eligibility and refresh cleared chat titles

* Fix checked naming projection types and logging metadata

* Supply context floor in status-feed journal fixtures

* fix: refresh History ownership after conversation clear

* fix: commit History request identity before refresh effects

* Fix History scan scope typing and integration test placement

* test: cover saved chat name reader contracts

* fix: bound chat naming work through generation settlement

* Remove duplicate History name-transition refresh

* Restore cache option in tab History test

* Consolidate naming test imports

* test: align naming fixtures with checked contracts

* test: name the discovery child fixture contract

* test: initialize writable child fixture streams

* test: account for ownership head and key reads
2026-10-26 00:31:24 -07:00
fcf5e7b418 fix(native): pin node-pty cfset*speed with legacy baud codes for glibc 2.42+ (#33803)
* fix(native): pin node-pty cfset*speed with legacy baud codes for glibc 2.42+

glibc 2.42 versioned cfsetispeed/cfsetospeed (GLIBC_2.42) to take literal
rates and redefined B38400 as 38400U, so node-pty built on 2.42+ fails the
Ubuntu 20.04 floor gate. Pin both to the compat version alongside the
existing openpty/forkpty/pthread_sigmask pins, and pass the legacy CBAUD
code (__B38400 on 2.42+ headers, B38400 otherwise): the compat setters
reject literal rates with EINVAL, which left every PTY at speed 0.

Fixes #19420. Supersedes #19421.

Co-authored-by: MK <mkjung.github@gmail.com>

* fix(native): fail the build if pinned cfset*speed would get a non-legacy baud code

A 2.42+ header set without __B38400 would otherwise silently pass 38400U to the
compat setters and open every terminal at B0.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: MK <mkjung.github@gmail.com>
2026-10-26 00:29:36 -07:00
Brennan Benson 761cddff38 fix(native-chat): stop retrying final startup answers (#33685) 2026-10-26 00:27:28 -07:00
Neilandfettpl 0efc989713 fix(worktrees): an unqualified id two hosts share resolves to nothing, not the first copy (#33818)
A worktree id or project host setup id repeats across hosts. Lookups that
named no host picked the first match, so a delete or setup mutation could
land on the other host's copy. They now go through one sole-copy rule and
refuse when the matches span more than one host; callers that know the
host (settings Remove, ephemeral VM rollback) now name it.

Co-authored-by: fettpl <38704082+fettpl@users.noreply.github.com>
2026-10-26 00:26:29 -07:00
Brennan Benson 407069bc63 Unify terminal starts under one host operation (#32076)
* Unify terminal starts under one host operation

* Pin winning geometry across a late terminal join

* Use terminal creation options type in launch race test

* Check closed panes after acquiring the terminal spawn lease

* Preserve terminal start resource and join boundaries

* Keep terminal attach regression within project boundaries

* Capture terminal spawn authority and preserve image coverage

* Use checked fixtures for terminal image replay regression

* test: expose persisted pane to main layout in attach race

* test: contract terminal spawn scaling and retention

* test: correct spawn scaling fixture types and CI selection

* test(terminal): cover exited prompt claims and adopted team cleanup

* test(pty): consolidate mock registry imports

* fix(pty): retain untyped IPC resume inputs in common contract
2026-10-26 00:25:37 -07:00
5fea2893f6 fix(computer-use): send correct named keys and hotkey letters on Linux (#22494)
* fix(computer-use): send correct named keys and hotkey letters on Linux

press_key passed the keysym for named keys (Return, Tab, arrows, Escape)
to AT-SPI as PRESSRELEASE, which expects a hardware keycode, so a
different key was pressed. Synthesize with SYM instead.

hotkey forwarded upper-case letters such as CmdOrCtrl+A to xdotool,
which reads them as shifted keysyms and sends Ctrl+Shift+A. Lower-case
single letters in key combinations.

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

* test(computer-use): drop the unreachable lone-key hotkey case

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 00:13:41 -07:00
OrcaWinandOrcaWin df4d4824c6 perf(lint): skip JS plugin rules on files that cannot match (#33813)
Each custom oxlint JS rule now checks the file text first and returns no
visitors when it cannot report, so oxlint skips the AST transfer to JS.
app-store-performance only resolves scopes for tracked hook names.
anti-slop rules are wrapped with per-rule text prefilters. react-doctor
rules are off for folders without React (the old cloud/** ignore never
matched: config/ globs need a leading **/).

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 00:13:01 -07:00
Neil 04ba0aec20 refactor: colocate task page composition hooks (#33808) 2026-10-26 00:09:15 -07:00
OrcaWinandOrcaWin b759a9566f test: remove low-value renderer predicates and wrapper suites (#33811)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 00:00:54 -07:00
fettplandOrcaWin 37399943ab fix(updater): probe latest-linux-arm64.yml on Linux arm64 (#18339)
* fix(updater): probe latest-linux-arm64.yml on Linux arm64

Preflight HEAD of the Linux updater manifest used latest-linux.yml on
every arch, so arm64 could pin a tag whose arm64 yml was still missing
(or skip a tag that was arm64-ready). Match electron-updater and probe
latest-linux-arm64.yml when process.arch is not x64.

* test(updater): accept arch-suffixed Linux manifests in updater feed mocks

On a Linux arm64 runner the feed now requests latest-linux-arm64.yml, which the
[a-z]+ suffix in these mocks rejected (12 failures with process.arch=arm64).

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 23:56:40 -07:00
Wooseong Kimandbbingz 38d28bd6f8 fix(computer-use): probe Linux editables via get_editable_text_iface (#10586)
set_value looked up node.is_editable_text before attempt() ran. GI bindings
from at-spi2-core < 2.53 (e.g. Ubuntu 24.04) do not expose that function, so
the AttributeError escaped and every set-value failed. Probe with
get_editable_text_iface, which has been bound since 2.9.2 and checks the same
interface.

Closes #10569

Co-authored-by: bbingz <zzb@gxsmjx.com>
2026-10-25 23:56:36 -07:00
0cbb973440 fix(agent-awake): warn once while the Linux lid sleep assertion keeps failing (#24839)
* fix(agent-awake): back off and warn once when the Linux lid sleep assertion keeps failing

On a headless Linux host, systemd-inhibit starts and then exits with code 1.
start() reset the failure streak right after the spawn, so every 30 s retry
logged a fresh warning and the retry never backed off.

Keep the streak until an intentional stop or until an inhibitor has held for
a full retry interval, and double the retry delay on consecutive failures
(30 s up to 30 min).

Fixes #20739

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

* fix(agent-awake): keep the lid assertion failure streak across idle/active cycles

stop() reset the warn-once dedupe and backoff, so a host where logind denies
the inhibitor still warned once per agent turn. Reset only after an inhibitor
was actually held for a retry interval.

* fix(agent-awake): keep the 30s lid assertion retry instead of backing off

Backoff delayed re-acquiring the lid inhibitor on laptops after transient
failures; warning once per failure streak already fixes the log flood.

---------

Co-authored-by: brynnclaw <261708852+brynnclaw@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 23:56:31 -07:00
OrcaWinandOrcaWin de93f326ea test: remove low-value inventories, passthroughs and redundant cases (#33796)
* test: remove low-value inventories, passthroughs and redundant cases

* style: format test suites after pruning redundant cases

* test: remove obsolete workflow and flaky-test references

* test: prune deleted builder test from Windows shim allowlist

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 23:41:49 -07:00
OrcaWinandOrcaWin 35af10dded build(deps): bump vite 8.3.5, oxlint 1.89.0, oxlint-tsgolint 7.0.2005 (#33794)
oxlint 1.89 adds eslint(no-setter-return), which flagged one test setter.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 23:19:26 -07:00
Chad TolkienandOrcaWin a710783e13 perf(daemon): skip drain-waiter filter when none are pending (#30996)
releaseDrainWaiters runs on every stream-socket read, but waiters only exist
while a disconnect drains. Return early when the list is empty so each read
no longer allocates a throwaway filter array and callback closure.

Co-authored-by: OrcaWin <alpha-eng@stably.ai>
2026-10-25 23:19:21 -07:00
Jinjing 6cb6d0d44d Fix native chat hover colors for live theme changes (#33791) 2026-10-25 23:13:53 -07:00
OrcaWinandOrcaWin cc3ca668d8 test: remove low-value predicates, inventories and helper echoes (#33778)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 22:57:11 -07:00
Jinwoo Hong a66f6bf011 fix(agent-resume): keep a background agent launch's flags when it is resumed (#33776)
* fix(agent-resume): record a background agent launch's recipe so resume keeps its flags

* test: narrow the reveal's notifier so the test needs no cast

* refactor(agent-resume): one recipe registration path; skip adopted panes

* test: add the launch-recipe listener to the remaining window mocks
2026-10-26 01:49:54 -04:00
Jinjing b0a33e03ea Clip retained panes until their anchors resolve (#33788) 2026-10-25 22:42:36 -07:00
Neilandmys de16d987fb fix(codex): resume a thread with the permissions it was last given, not Orca's launch flag (#33460)
* fix(codex): resume a thread with the permissions it was last given, not Orca's launch flag

Codex restores a resumed thread's saved approval/sandbox settings unless the
launch passes a permission flag. Orca replayed its launch-time recipe
(--dangerously-bypass-approvals-and-sandbox, --approve-for-me, or the Ask
flags) on every resume, so a session switched to "Approve for me" came back
as Full Access after a restart, and that override was saved to the thread.

Fixes #10886

Co-authored-by: mys <4546173+wowpotato@users.noreply.github.com>

* test(mobile): Codex AI Vault resume no longer replays Orca's permission flag

The mobile AI Vault resume builds its command through the shared resume plan,
so it now omits --dangerously-bypass-approvals-and-sandbox like desktop does.

Co-authored-by: mys <4546173+wowpotato@users.noreply.github.com>

---------

Co-authored-by: mys <4546173+wowpotato@users.noreply.github.com>
2026-10-25 22:39:00 -07:00
Jinwoo Hong 64bba690ad feat(connector): inbox with held long poll, two confirmations and expiry, on connector tokens (#33734) 2026-10-26 01:27:26 -04:00
Neil 1b712dd08a feat(tools): resize the PTY mid-capture with --resize-at (#33781) 2026-10-25 22:27:16 -07:00
Jinwoo Hong 8cc8024504 feat(connector): connector service skeleton that checks auth-service tokens (#33723) 2026-10-26 01:20:53 -04:00
Neil 4843f85f2a refactor(renderer): group agent-status records and reducers (#33665)
* refactor(renderer): group agent-status records and reducers

* refactor(renderer): consolidate concrete type owner imports
2026-10-25 22:20:14 -07:00
Jinwoo Hong 44ac5e284e refactor(cloud): share push's database layer as a package (#33714)
Moves the push gateway's database layer into a shared cloud/packages/cloud-database package (service name and schema passed in). Push's behaviour, log names, SQLite file and tests are unchanged.
2026-10-26 01:10:55 -04:00
Neil d7cec1c3f8 fix(wsl): keep a UNC drive-folder repo's worktrees in its own spelling (#33706)
A repo saved as \\wsl.localhost\<distro>\mnt\c\... runs Git in WSL, which
lists its worktrees as /mnt/c/.... The listing mapped those to C:\..., so the
primary worktree got the id <repo>::C:\... instead of the saved
<repo>::\\wsl.localhost\...\mnt\c\.... Its tabs, agents and terminal history
are keyed by the saved id: the renderer dropped them as belonging to no
worktree, and the C:\ row showed up as a hidden discovered worktree.

Map drvfs output to the distro's UNC view when the repo itself is saved
under it. Repos saved as drive paths (Git routed to WSL) and in-distro repos
keep today's drive mapping.
2026-10-25 22:05:53 -07:00
Jinwoo Hong 869ae4933a feat(connector): wire contract between Orca and the cloud connector service (inert) (#33670)
Adds cloud/packages/connector-contract: the shapes the desktop and the cloud connector service exchange (hello, held poll, received/done acks, events with per-hello seq, replies), limits, error codes and the contract version. Nothing calls it yet.
2026-10-26 00:38:21 -04:00
OrcaWinandOrcaWin e152113981 test: remove low-value renderer predicates, inventories and copy checks (#33772)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 21:34:54 -07:00
Jinwoo Hong a1da3c0a3b fix(agent-resume): resume Claude sessions at their own effort level (#33765)
* fix(agent-resume): resume Claude sessions at their own effort level

* fix(agent-resume): keep effort through persistence and /clear; simplify ensure shaping
2026-10-26 00:30:08 -04:00
Neil 327c152cca fix(runtime): keyboard tab switches tell a paired server which tab this desktop shows (#33761)
* fix(runtime): keyboard tab switches tell a paired server which tab this desktop shows

A paired server keeps one tab selection per device and a server workspace
reopens on it. Clicks, Cmd+1..9 and the palette updated it, but the next,
previous, recent and terminal-only shortcuts changed the tab locally only, so
the server kept an older pick and the desktop could reopen on the wrong tab.

* fix(runtime): keyboard switches to agent chats and server browser tabs also reach the server

Browser activations carry the visible local tab so later navigation cancels
their deferred focus, matching terminals.

* fix(runtime): keep keyboard agent-chat switches local in workspaces no server owns

* fix(runtime): scope keyboard agent-chat activation to this client on old and new servers

* fix(runtime): a keyboard switch to an agent chat reaches the server that hosts that chat
2026-10-25 21:19:45 -07:00
OrcaWinandOrcaWin ac003332de test: remove redundant configuration, shortcut and recovery coverage (#33770)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 21:18:47 -07:00
OrcaWinandOrcaWin 585f7efe2b test: remove redundant browser, runtime and secret registry coverage (#33767)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 21:05:51 -07:00
NeilandClaude 4c9a6a4055 fix(agent-status): keep Codex's hidden title-thread prompt off the sidebar heading (#33746)
* fix(agent-status): keep Codex's hidden title-thread prompt off the sidebar heading

Codex titles a new thread in a hidden ephemeral thread. When managed config pins hooks on,
that thread's SessionStart (source startup) took the pane and its prompt became the row heading.
Drop its prompt as a foreign ephemeral thread and keep the row's prompt across rollout-less starts.

Fixes #30049

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

* fix(agent-status): hold a rollout-less Codex start until its prompt shows what it is

The hidden title thread's SessionStart no longer swaps the row's state, session or tool snapshot.
A held start is dropped with the title prompt, or replayed as SessionStart on a new conversation's
first prompt so relayed desktops still let it take the pane. Covers a main Stop arriving first.

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

* fix(agent-status): also hold Codex's hidden recap thread and clear the old completion stamp on takeover

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-25 21:00:28 -07:00
Jinwoo Hong bbaa33ce65 chore(mobile): bump to 0.0.59 and Android versionCode 23 (#33764)
Matches the iOS 0.0.59 build.
mobile-android-v0.0.59
2026-10-25 23:54:23 -04:00
Jinjing 4597d3f249 Render unsupported Markdown drafts in preview mode (#33733)
- Preserve source syntax while allowing preview and PDF export
- Keep Source available for editing and reserve fallback styling for neutral guidance
2026-10-25 20:53:41 -07:00
Neil ad1684435e fix(wsl): open, save and rename a UNC drive-mount project's files through its drive path (#33756)
* fix(wsl): open, save and rename a UNC drive-mount project's files through its drive path

WSL 2.7 refuses Windows file access to its drive mounts over UNC. #33735 fixed listing a saved
\\wsl.localhost\<distro>\mnt\c\... project, but opening a file from it still failed with EPERM, as
did saving, renaming, creating and copying.

The open/read helpers (editor reads, ranged reads, media previews), the save path (write probe,
disk precondition, its locks), rename, create, copy, the file stat/exists checks, the runtime
provider used by remote clients and the document-folder realpaths now hand the filesystem the
drive path. Authorization is unchanged: it still runs on the caller's UNC spelling against the
UNC roots. Delete already runs inside the distro.

* fix(wsl): check a missing path's ancestors for links through the drive path

Authorizing a path that does not exist yet walks up to the nearest existing folder and refuses a
dangling link on the way; that link check ran lstat on the UNC spelling, which WSL 2.7 refuses for
drive mounts. So New File, New Folder, a first save, an upload and a copy or rename into a new
folder all failed with EPERM (failing closed). The check now lstats the drive path, where Windows
still reports junctions and symlinks.
2026-10-25 20:48:32 -07:00
OrcaWinandOrcaWin 852dfcd282 test: remove redundant browser and transport coverage (#33757)
* test: remove redundant browser and transport coverage

* test: retire deleted suites from reliability manifest

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 20:46:39 -07:00
Neil 7b5f50d917 fix(codex): let Codex's elevated Windows sandbox read Orca's managed Codex home (#33748)
* fix(codex): let Codex's elevated Windows sandbox read Orca's managed Codex home

Fixes #24306

* fix(codex): run the sandbox read grant off the launch path, once per home

* fix(codex): skip the sandbox read grant when the home already has it

* fix(codex): grant the sandbox only resource folders, retry failures, cover first elevated session

* fix(codex): machine-qualify the sandbox group and verify full propagation
2026-10-25 20:41:29 -07:00
Neil ddcedee37c fix(remote): a desktop no longer serves other runtimes its tabs on its servers' files (#33424) (#33752)
* fix(remote): a desktop ignores its own workspaces echoed back by a server it serves (#33424)

When two desktops pair to each other, each server republishes the tabs it
mirrors from its own servers. Desktop A then received B's mirror of A's own
workspace under the real workspace id and grafted it onto its local copy as
B-hosted tabs, so opening those files asked B (selector_not_found) and closing
them closed B's tabs.

A session-tabs frame from a paired server no longer writes a workspace this
app lists as its own (a stamped local or direct SSH row) unless that server
also lists a copy. Other servers' workspaces stay open to every runtime.

* fix(remote): retire echoes already taken and replay frames a twin's late row releases

An echo fenced out of this app's own workspace now applies as that server's
tombstone, so rows it left before the fence (restored sessions, or frames that
arrived before this app's own row listed) are retired without closing anything.
A held frame replays once the server's own copy of the workspace lists, so a
same-id twin that publishes before its row loads still mirrors. The e2e waits
on a later frame from the same stream instead of a fixed delay.

* fix(remote): serve a desktop's tabs on its servers' files only to its phone, not to other runtimes

Redesign of the #33424 fix at the source. A desktop publishes every editor tab in
its window, including ones on files of its paired servers; its phone uses those
through the desktop's relay. Served to another runtime, such a tab routes the file
to the desktop, and in a pairing cycle it is that runtime's own workspace coming
back as the desktop's tab: file reads fail with selector_not_found and closing it
closes the desktop's real tab.

Publishers now stamp those rows with hostRuntimeEnvironmentId (window, layout-owner
main projection and the windowless projection alike). projectSessionTabsForClient
strips the stamp for every caller and drops the stamped rows for runtime-scope
callers, keeping groups, layout and the active tab consistent. Phones and local
callers see what they saw before. The receiver-side fence is removed.

* refactor(remote): keep the file-host stamp helper outside the old-client boundary; test an all-server snapshot
2026-10-25 20:28:07 -07:00
Neil 5d6a110706 fix(sharing): name a headless host's missing sharing service instead of the device setting (#33754)
Part of #33593
2026-10-25 20:27:25 -07:00
Neil 454b8dd65f fix(ai-vault): resume OpenCode sessions under the account that owns them (#33753)
History lists every managed OpenCode account's sessions since #33658, but
resume still launched with the active account's XDG_DATA_HOME, so OpenCode
looked in the wrong database and reported "Session not found".

Derive the owning account from the row's store path and request it via a
spawn env key; the host validates it against registered accounts and falls
back to the active one when the owner was removed.

Refs #28790, #33658
2026-10-25 20:27:18 -07:00
Neil d5ee28d716 fix(program-status): keep a Pi row working while a pi-subagents child outlives the parent's done (#33738)
* fix(program-status): keep a Pi row working while a pi-subagents child outlives the parent's done

OSC 7501 projected the root record's done straight onto the row even when
live child records remained, so a Pi parent showed Done/IDLE while an async
pi-subagents worker kept running. Fold child liveness with the existing
foldMainAgentWithRowChildWork; mainAgent keeps the lead's own verdict so the
row settles to done once the last child ends.

Fixes #33657

* fix(program-status): announce a held turn's done on time and keep hook verdicts authoritative

- Stamp turnCompletedAt on the child-held row and its all-clear so the lead's
  done is announced once, when it happens, as hook rows do.
- Hold only a finished (non-boundary) turn, only for working/waiting children;
  in-turn rows and failed/idle children keep the root's state.
- A settled hook row is never reopened by a program's child-held working row,
  so the 2-minute silence fallback cannot flip done -> working -> done.

* fix(program-status): lapse an unrefreshed child hold to the lead's done

Children report only changes, so a pi-subagents that dies or hangs inside a
live Pi would hold the row working until decay. The lease timer now settles a
child-held row no report refreshed within AGENT_STATUS_STALE_AFTER_MS minus one
renewal interval (20-30 min) to the lead's done, keeping turnCompletedAt so it
is not announced again.
2026-10-25 20:24:34 -07:00
Neil dfde70b519 fix(ai-vault): list Claude sessions from a wrapper or launch-setting CLAUDE_CONFIG_DIR (#33751)
* fix(ai-vault): list Claude sessions from a wrapper or launch-setting CLAUDE_CONFIG_DIR

History, usage and transcript lookup now also scan Claude config folders Orca saw in Claude hook transcript paths (kept across restarts) and the CLAUDE_CONFIG_DIR set in Orca's Claude launch environment.

Fixes #23505

* fix(ai-vault): normalize observed Claude folders and cache missing ones

Adds tests that only Claude hooks record a folder (not same-layout CodeBuddy), non-transcript paths are ignored, and the 32-entry cap holds.
2026-10-25 20:21:43 -07:00
NeilandArnobrizwan 165412b9ac fix(terminal): send native Alt+Left/Right on local Windows ConPTY so Codex can switch agents (#33463)
Co-authored-by: Arnobrizwan <147672066+Arnobrizwan@users.noreply.github.com>
2026-10-25 20:19:34 -07:00
Neil f460c92cc5 fix(terminal): deliver batched output when a paired view pauses, so its queries get answered (#33749)
Main yields a chunk's query replies to a receiving remote view at ingestion.
If that view paused while the chunk was still in the 5 ms output batcher,
the pause flushed it into the paused gate and dropped it, so a fish DA1
went unanswered and fish stalled 10 s. Flush the batcher before applying
the pause; the desktop's hidden-pane path already answers queries in
bytes that arrive after it paused.

Refs #32944
2026-10-25 20:14:52 -07:00