* 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
Setup on Windows Server 2012 R2 and on Windows hosts with neither
System32\tar.exe nor Expand-Archive ended in the generic "Orca couldn't
start its server on this host. Try connecting again.", which no retry
fixes. The runtime probe that already runs before staging now also reads
the Windows build and checks for an extractor, read-only, and refuses
before anything is staged or uploaded. The refusal travels the existing
orcad_unavailable reason plumbing to the host card and the ssh:connect
error, and is rechecked on every connect like a noexec home.
Fixes#33574
Reported-by: HKLHaoBin
* fix(ssh): a migrated host's old session no longer brings closed tabs back on restart (#33539)
After an SSH host moved to a managed server, main hides its retained source
repos but still listed its frozen session partition. The window adopted that
partition at startup, and agent tabs the user had closed on the server came
back on every restart. The partition census now hides that partition exactly
when its repos are hidden; the stored rows stay for downgraded clients.
* test(ssh): pin that an uncommitted move keeps its session listed
* Keep the permission pill inside the Arguments box
* Share the Settings permission menu and commit Arguments on field exit
* Honor changed permission choices and acknowledged host picks in reset notices
* Show acknowledged permission resets with scoped Undo
* Consume removed permission recipes in the Arguments draft
* Keep reset notices separate from the inline permission field
* Show reset choices and Undo after a global permission pick
* Use Textarea variant for composite arguments field
* Fix permission test query typing and sync English runtime catalog
* Keep permission reset Undo beside the toast title
* Add permission reset localization base keys
* Complete host settings bookkeeping transport mock
* Flow arguments beneath the permission chip
* Keep composite argument typography in Textarea variant
* Share native scrolling between permission chip and arguments
* Place all-agents permission menu beside its label
* Preserve permission menu width while settings load
* Keep explicit agent permissions when changing the global default
* Use acknowledged settings for local permission notice actions
* Apply local permission notice actions at the settings owner
* test: give settings runtime mock a portable type
* test: place settings fixtures in the recognized fixture directory
* fix: update populated permission notices without dismissal
* Toast says agents still use their own permission setting
* fix(native-chat): a Claude chat saved as Approve for me keeps it when Orca can't read its model list
A chat's auto mode dropped to Ask whenever the saved model list was missing
or couldn't name the chat's model (another account home, first start in a
folder, an unlisted model id), so a resumed chat launched asking for approval.
Auto now drops to Ask only when the list shows the model without it; Claude
itself starts a model that can't run auto in its default mode.
Tracked in STA-10953.
* fix(native-chat): a model list from a CLI older than auto mode still reads as Ask
A CLI that marks no model with auto support predates the auto value (2.1.71)
and would refuse --permission-mode auto, so its listing is evidence, not a gap.
Tracked in STA-10953.
* docs(chat): correct auto support reporting version
* test(chat): type saved launch option cases
* Honor requested chat permissions across model changes
* Match outgrown child fixture to journal null contract
* fix(native-chat): preserve admitted input and current mail choices
* perf(native-chat): derive wake debt and held sends once per retirement decision
The retirement check derived wake debt (a child-work projection and a scan
for the newest turn) before asking whether open work had already decided
the outcome, and its admitted-input fallback rebuilt the provider's held-send
set once per unanswered submission, O(S x W) per decision.
Open work is now read first and wake debt only where it picks the outcome or
the refusal reason. Current work gains one batch query that reads the held
set and the handover set once, sharing the single holds rule with the
per-send reader. Outcomes and refusal reasons are unchanged.
Adds N/10N operation-count contracts on the real Claude host rig: two
retirement checks per ordinary send, each one pass over history, with a
control that the second sees a sign-out reported between them; no wake debt
mid-turn; one held-set read per refusal in a queued model-change burst.
* Keep active Claude input on its turn choices
* Fix chat admission type imports and cover turn-scan costs
* Preserve root lifecycle delivery under journal pressure
* test: construct Codex mail fixture with its source
* test: expect root retention metadata in Claude turn timing
* test: cover captured Claude full-ID Auto launch
* test(native-chat): explain queued-send test timeout
* test: supply explicit mailbox working policy
* fix(orcad): drive Android emulators from headless orca serve hosts
orcad never installed an EmulatorBridge, so every `orca emulator` verb
failed with emulator_no_active once headless serve moved to orcad. The
emulator modules now read host paths and HTTP through the host ports
instead of importing Electron, and orcad installs the bridge and stops its
managed sessions on shutdown like the desktop does.
Fixes#33650
* fix(orcad): bound emulator teardown inside the shutdown deadline
* fix(orcad): keep idle exit from stopping Orca-started emulators; update emulator skill scope
* fix(orcad): count only still-running Orca-started emulators as idle-exit work
* fix(emulator): prune managed sessions only on a successful adb census
* fix(emulator): release a pruned device's stream and never prune a record reattached mid-census
The headless CLI bundle resolved jsonc-parser to its UMD build, whose
relative requires fail beside the single-file bundle, so
`orca agent hooks status|on|off` crashed with "Cannot find module
'./impl/format'". Every orcad bundle now shares one plugin list, and the
build refuses any bundled UMD module.
Fixes#33592
* fix(ssh): don't refuse a host's move over a pane that saved no terminal history
A pane with an empty inline buffer, a deleted snapshot, or a zero-byte
snapshot has no history to lose, but the move's projection filed it
under "saved terminal history Orca could not read" and refused the whole
host. Tell absent snapshots apart from unreadable ones and move the
former without history; unreadable history still blocks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(ssh): keep looking in the fallback root when a scrollback snapshot is empty
A zero-byte snapshot in the primary root returned 'absent' without checking
the fallback root, so a pane whose history lived there moved without it.
Also check ENOENT inline rather than importing a window staging helper.
* test(e2e): seed unreadable relay scrollback as an over-limit snapshot
A missing snapshot file now means the pane saved no history, so the
leave-behind spec needs history that exists but cannot be read.
---------
Co-authored-by: Younghwan Chae <chyohw97@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(link-actions): dismiss the link chooser when an outside click stops propagation
* test(link-actions): wait for Radix to arm before the outside click
* fix(ssh): retry over system ssh when ssh2 shares no algorithm with the host
ssh2 supports fewer algorithms than OpenSSH. A host that offers only
certificate host keys (or only kex/cipher choices ssh2 lacks) fails the
handshake with "Handshake failed: no matching ...", even though the
system ssh binary connects fine. Treat any such negotiation failure as a
client capability gap: probe system ssh once, and if that also fails,
report its error, since ssh2 can never reach the host.
Fixes#33582
Co-authored-by: Kyou12138 <kyou12138@gmail.com>
* fix(ssh): keep hosts pinned in Orca's key store on ssh2 after a negotiation failure
System OpenSSH never reads Orca's own host key store, so an on-path
impostor could advertise algorithms ssh2 lacks to steer a pinned host
onto system ssh and around its pin. Only fall back when Orca has no
stored key for the endpoint.
Co-authored-by: Kyou12138 <kyou12138@gmail.com>
* fix(ssh): only the current attempt records an Orca host key pin
A superseded attempt that finished its trust read late could overwrite
the current attempt's pin marker, letting a negotiation failure on a
pinned host fall back to system ssh.
---------
Co-authored-by: Kyou12138 <kyou12138@gmail.com>
* Guard managed server restarts with host work reservations
* Protect legacy server update requests with host admission
* Reserve chat-safe restarts in SSH and WSL server updates
* Keep activation host fixtures within the module line limit
* fix(orcad): preserve session queue timing during admission
* Explain chat-safe update deferrals and superseded restarts
* Clarify managed server Force upgrades and retry instructions
* Separate chat entry delegates from conversation creation
* Report child work through main's child evidence in the restart drain test
* Drive main's snapshot-room tests through the restart reservation
Main's room tests deployed over a serving incumbent with a census that has no
chat work count and no restart admission, so the update deferred before the
room probe ran. Give them the same idle census and slot admission as the other
activation tests, and pin the probe before the reservation instead of before the
recount it replaced.
* fix(native-chat): an update keeps waiting on a chat start after its conversation is closed
The restart check counted a start only while its conversation stayed open,
so an idle close during a stalled start let a managed update through.
Every tracked attach, create, start and open now counts as restart work
in the same tracker that counts the session queue.
* fix(native-chat): keep the structured session view within its line limit once formatted
Main's copy sat at 400 lines only because one line was left unformatted; the
merge's formatter pushed it to 401. Inlining the one-use question list keeps it
at 400 with identical behavior.
* fix(orcad): a recovery stop request stops the server; only an older client's empty request waits for idle
Stopping a slot and restarting it for an older client's update were both an empty
.orcad-stop-request file, so routing that file through restart admission let a
crash recovery, stranded-setup release or rejected-candidate rollback leave the
server running. New clients now write "stop-now" into the request (renamed in
whole), which stops at once as before; an empty or unrecognized request takes the
chat-safe restart, and a deferred restart logs why. Also gives the restart
admission activation fixtures the now-required recount.
* docs(orcad): say a directory at the stop-request path is refused, not restarted
* docs(orcad): the plain stop request's comment states both of its meanings
* style: format the restart admission files for the format check
* test(wsl): count the incumbent's recount bridge after the reservation's
* fix(orcad): a Windows stop request retries its rename while antivirus holds the new file
Renaming the just-written stop-now request can briefly fail with EPERM, EACCES
or EBUSY on Windows; the stop now retries those with the same bounded delays as
record-publish instead of answering SIGNAL_FAILED and leaving the server up.
* test(orcad): a real Windows host stops on the slot's stop-now request and relaunches
* test(orcad): recovery stops a real server whose restart admission refuses
* test(orcad): the recovery-stop cell tunnels over the cell's SSH connection
* test(orcad): the recovery-stop cell names itself in the CI log
* fix(settings): a deferred WSL update shows its full reason below the row
* test(orcad): fixtures pass releaseIncumbentAdmission; the census test calls its own method
* test(orcad): the capable-server census in the fence test reports idle chat work
* Record server chat restart offers and desktop creation history
* Offer interrupted chat recovery per managed runtime
* Ship the remote chat resume action labels in the runtime catalog
* Update removal contracts for desktop chat history cleanup
* Scope remote chat recovery to each server occurrence
* Preserve recovery choices and uncertain continuation outcomes
* fix: preserve uncertain restart action outcomes
* Fix restart recovery CI imports and fixtures
* test: align resume assertions with unconfirmed outcomes
* test: bound restart recovery work across scaled populations
* fix(native-chat): title the remote resume dialog with the restart
The dialog can appear out of nowhere when another desktop updates a shared
server, so its title now says what happened: "<machine> restarted".
* fix(terminal): give the window and main's copy the daemon's ConPTY resize rule
Every PTY a Windows machine owns is ConPTY, WSL shells included, and ConPTY
repaints its own grid after a resize. The window applied xterm's ConPTY
model only to native (non-WSL) panes, and main's copy for reveals and phones
never did, so growing either pulled history into ConPTY's grid. Decide
windowsPty from the PTY's owner backend everywhere, keeping the native-only
cursor, CJK and keyboard workarounds behind isLocalNativeWindowsConpty.
* fix(terminal): keep main's copy of an SSH relay PTY off the ConPTY model before its record exists
Main's copy is built on the first byte, and a restored or adopted relay PTY
can stream before its record carries a connection id.
Reverts #29133 except its daemon async-I/O stall telemetry, so we can measure how often stalls happen on official Node before committing to a patched runtime. The macOS terminal host goes back to the official Node 24.22.1 download and the daemon protocol back to v51; no release or hourly build published v52.
* 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
* fix(runtime): validate tab property edits before saving chat names
* 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
* test: make chat naming fixtures deterministic
Claude Enterprise seats (null 5h/weekly windows, limit in spend/extra_usage) now show their spend cap as a monthly usage bar in the status bar chip, tooltip and account switcher instead of an empty meter.
Fixes#31061
Supersedes #31065
Co-authored-by: Frank Bernhardt <275327+frank-bee@users.noreply.github.com>
After agy silently refreshes its Google token (the new credential has no id_token), Orca still matches the saved Antigravity account by auth method + refresh token instead of refusing the launch with "native Antigravity account changed"; the vault accepts such refreshed snapshots while still rejecting one whose id_token names a different account.
Fixes#31579
Supersedes #33204
Co-authored-by: biojuho <258838639+biojuho@users.noreply.github.com>
Co-authored-by: Manan <100475418+thefrikidude@users.noreply.github.com>
Kiro's V3 engine (default from Kiro CLI 3.0) now reports status in Orca: Orca installs a global hooks file under KIRO_HOME/hooks (covering the built-in default agent, local and remote, never overwriting user files) and recognizes V3's PascalCase hook events.
Fixes#31577
Supersedes #24937
Co-authored-by: Dongho Lee <126236161+LDH1103@users.noreply.github.com>
Orca CLI commands inside a sandbox that blocks chmod (e.g. Claude Code's Bash sandbox) no longer fail with a misleading "file is invalid": the pre-read hardening of existing secure files ignores EPERM/EACCES/EROFS; writers still create files 0600.
Fixes#20937
* feat(agents): store each agent's permission itself instead of typing flags into Arguments
Terminals and new chats read one stored choice per agent (Use the agent's own
settings, Ask for approval, Accept edits, Approve for me, Full access). Orca adds
the flag at launch; Arguments hold only the user's own text. A one-time move
lifts Orca's flags out of saved Arguments. Older clients still see and write
the flag as part of Arguments; the host translates.
* fix(agents): say the all-agents switch resets agents set separately; keep primitives unstyled
* test(agents): the one-time move returns every launch-profile field
* Fix permission carrier ownership and surface-specific defaults
* Preserve uncertain permission operands and name the option inventory
* Check env entries without indexing typed agent maps
* Combine Chat permission capability imports
* Use folder execution-host platform for permission environment
* Preserve launch map replacement and acknowledge permission saves
* Keep permission feedback fallbacks statically discoverable
* Provide preload platform to Agents settings render tests
* Preserve Gemini approval arguments under Full access
* fix(settings): retain complete environment edits through save outcomes
* fix(settings): narrow local failure scope and preserve host messages
* fix(settings): retire argument drafts after acknowledged saves
* fix(settings): keep Goose environment editable after reset
* fix(settings): show resolved arguments for legacy hosts
* Preserve pending environment resets and bound launch settings work
* Use agent permission choices for new chats
* Let Claude resolve chat permissions from its own settings
* Keep optional settings fallback in repository metadata reads
* Consolidate permission report imports
* Update permission choice contracts for own settings
* Read repository visibility defaults through the raw settings fixtures
* Match existing translated Agents settings labels
* Update readback and legacy host test expectations
* Align Chat behavior tests with host permission capability
* Fix permission compatibility and host-owned descriptions
* Prepare whole Environment edits and retire unchanged drafts
* Handle null explicitly in permission report decoder
* Keep Environment settings transitions in an acyclic module
* Update raw settings reader test fixtures
* Place test fixture safety notes on assertion starts
* test: pin permission settings work and recovery contracts
* test: type permission settings work fixtures
* test: cover migrated permission inputs and captured CLI grammar
* Publish permission reports and reuse host capability state
* Combine mobile option state React imports
* Honor mobile status feed capability for permission reports
* test: preserve typed permissions in WSL Claude restarts
* Correct permission report child and fixture type contracts
* Delegate older-host chats to explicitly selected own settings
* Avoid rebuilding live ACP option catalogs
* test(chat): place cross-boundary permission contracts in integration project
* Preserve existing chat capability gates and complete report test fixtures
* fix(chat): preserve newer Claude startup permission reports
* test(chat): clarify startup report fixture provenance
* Show reported permission modes in chat menus
* Keep reported permissions available after chat mode picks
* Remove obsolete guard from concrete permission selection
* Report the installed approval policy for ACP chat menus
* test: keep accepted mobile mutation fixture on current fence
* test: cover installed ACP approval report for own chats
* test: align capability scaling contract with concrete permission menus
* Ship required permission help in English runtime catalog
* Adapt permission persistence test to shared menu