* 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
* 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
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>
* 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
* 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>
* 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>
* 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>
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>
* 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
* 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>
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.
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.
* fix(agent-resume): resume Claude sessions at their own effort level
* fix(agent-resume): keep effort through persistence and /clear; simplify ensure shaping
* 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
* 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>
* 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.
* 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
* 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
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
* 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.
* 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.
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
* fix(hermes): keep named profiles' orca-status copy and pane passthrough current
A Hermes named profile loads plugins and terminal.client_env_passthrough from
profiles/<name>/, so a profile that carries Orca's managed plugin (e.g. cloned
with `hermes profile create --clone`) never got the pane-identity passthrough
or plugin updates. Install/remove now also update those profiles, locally and
over SSH.
Refs #33591
* fix(hermes): never re-enable orca-status in a profile; isolate profile failures
Only refresh named profiles that keep orca-status enabled and not disabled,
match the local managed check remotely (both plugin files), and skip a profile
or an unlistable profiles dir with a warning instead of failing the install.
* fix(hermes): write a profile's config before removing its plugin
When worker-start had to infer the coordinator terminal, the CLI scoped that
lookup with the command's own --worktree (and --terminal) flags. Those name
where the worker goes, often on another server, so the local runtime rejected
an existing remote selector with selector_not_found before any Task or
Dispatch existed. Infer the sender only from the caller's own directory.
Fixes#33579
* fix(wsl): read a UNC drive-mount project's files through its drive path
WSL 2.7 refuses Windows file access to its drive mounts over UNC: \\wsl.localhost\<distro>\mnt\c\x
answers EPERM, while the distro's own folders still open. A project saved under such a path lost
its file explorer (fs:readDir failed on the authorization realpath) and logged an EPERM warning
for every setup-script import candidate.
The authorization realpath now resolves a UNC drive-mount path through its drive and answers in
the caller's UNC spelling, so allow-list checks are unchanged; readdir and the import-candidate
reads open the same folder by drive path. Distro folders, other UNC shares and non-Windows hosts
are untouched.
* fix(wsl): read a UNC drive-mount repo's orca.yaml through its drive path; pin junction refusals
orca.yaml checks (hasHooksFile, loadHooks, the unknown-key probe) opened the UNC path, which WSL
2.7 refuses for drive mounts, so a saved /mnt/c project's setup hooks silently disappeared. They
now use the same drive mapping.
Also pin that authorization still judges a UNC drive-mount path against the UNC roots: a junction
under the project that resolves to another drive or outside the project is refused.
* test(wsl): run the UNC drive-mount fs:readDir suite in the Windows package lane
Its cases need native Windows path resolution, so they skip on Linux and macOS. Gate the suite
(not each case) on win32 and register the file with the Windows lane, so CI actually runs it.
Managed OpenCode accounts launch with XDG_DATA_HOME=<account>/data, but
history discovery only read the app process's XDG data dir, so sessions
created after selecting an account never reached History or the vault index.
* fix(sidebar): list a workspace's newest linked reviews first in the hover card
* fix(sidebar): order linked items newest-first for every surface that lists them