Commit Graph
720 Commits
Author SHA1 Message Date
Jinwoo Hong f341558b82 feat(cli): match folder workspaces by path: and name:, keep same-id ps rows apart (#39637)
* feat(cli): match folder workspaces by path: and name:, and keep same-id ps rows apart

Adds one runtime matcher for worktrees and folder workspaces. With the new
matchFolderWorkspaces opt-in (advertised as workspace-selector.folder-match.v1),
path: and name: also match folder workspaces; branch:, issue: and identity:
stay repo-backed. Several matches refuse with each choice's kind, host, path
and selector; a folder id shared by two folder workspaces refuses with the
repair step. The CLI resolves path:/name: through it, so terminal, file and
ports commands reach a folder workspace, and create/set parents record a
folder parent. Explicit ambiguous parents report LINEAGE_PARENT_AMBIGUOUS.

worktree ps now keeps rows that share an id on different hosts apart, with
their own host, identity, metadata and activity; activity whose host can't
be proven attaches to neither.

* test: let the cross-version ps harness pass the host-qualified summary lookup

* fix(cli): read each ps row's own host session; qualify folder selector help

* fix(runtime): refuse unscoped duplicate folder ids; hand lineage the matcher's typed result

Unscoped folder:<id> refuses a duplicated id even when only one copy's host
is derivable; a host-scoped lookup still picks that host's copy. A wsl: hook
stamp counts as local host evidence. The lineage controller receives the
worktree-or-folder candidate directly instead of re-deriving the kind.

* docs(cli): guide the ambiguity fallback through truncated ps and id: selectors

* fix(cli): report an ambiguous parent by its own choices; cover per-host sessions

* fix(cli): send parents to the runtime parent resolver as typed; translate WSL paths for folders too

Parent selectors skip the CLI's show-based folder lookup, so worktree.create
and worktree.set classify them with parent rules: a folder spanning hosts is
a valid parent, and ambiguity reports LINEAGE_PARENT_AMBIGUOUS. Caller-distro
Linux path translation now also matches folder workspaces.

* chore(rpc): import the computer-use recovery data directly instead of through an alias

* fix(runtime): report a missing set parent as LINEAGE_PARENT_NOT_FOUND, as create does

worktree set and worktree create now share one explicit-parent error
conversion: several matches give LINEAGE_PARENT_AMBIGUOUS and none give
LINEAGE_PARENT_NOT_FOUND, so a missing parent is no longer reported as a
bare selector_not_found that could mean the child.
2026-11-07 23:35:33 -05:00
OrcaWinandOrcaWin 35547956dd test: fake-clock the agent-session start backoff; drop the CLI owner-choice work-count suite (#39685)
* test(agent-session): jump the start retry backoff on a fake clock

The five-attempt cases waited 1.5s of real 100·2^n ms backoff each. Route the
backoff's promise delay through fake timers and jump it while real time still
passes for file and database work.

* test(cli): delete the owner-choice work-count suite

It asserted property visits, serialized bytes and call counts under spied
globals at 10,000 workspaces; owner election behavior stays covered by
index-workspace-owner-choice.test.ts.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 19:10:56 -08:00
OrcaWinandOrcaWin e4a479ceec test: remove 282 low-value tests (#39632)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 16:51:15 -08:00
OrcaWinandOrcaWin eb9312fc7c test: remove 660 low-value tests (#39547)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 09:18:17 -08:00
OrcaWinandOrcaWin 4243da77d5 test: remove 414 low-value tests (#39539)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 08:41:24 -08:00
OrcaWinandOrcaWin 5c5c7ca235 test: remove 283 low-value tests (#39533)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 08:11:30 -08:00
OrcaWinandOrcaWin 5c487a8be4 test: remove 328 low-value tests (#39525)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 07:44:08 -08:00
OrcaWinandOrcaWin 9b98b38506 test: remove 137 low-value tests (#39522)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 07:20:11 -08:00
OrcaWinandOrcaWin deb834db05 test: remove 244 low-value tests (#39507)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 06:33:36 -08:00
OrcaWinandOrcaWin c8ed5c6be4 test: remove 295 low-value tests (#39480)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 04:03:51 -08:00
Neil 51f3c956ed feat(plugins): let plugins ship web fonts for the terminal, editor and interface (#39416)
* feat(plugins): let plugins contribute web fonts to the font pickers

Plugins declare font families under contributes.fonts (WOFF/WOFF2 only).
Install checks each file's signature against its extension and caps file
size, family count and plugin total; main never parses a font. Files are
served over the plugin image scheme only while the plugin is enabled,
typed and nosniff. The renderer registers each family under a name that
carries the plugin key, so a plugin font cannot shadow an installed or
built-in font, and it applies only once the user picks it. Disabling or
uninstalling removes the faces; uninstalling also resets font settings
that named them.

Refs #38607

* fix(plugins): harden plugin fonts and re-measure editors when they load

- Refuse WOFF/WOFF2-wrapped font collections by checking the flavor bytes.
- Check dev folders' font files at discovery, not only at install.
- Re-check family, weight and style from the plugin list in the renderer.
- Track loaded families (case-insensitively) from document font loads, so
  the code editor re-measures and terminals, previews, the SSH terminal and
  the dashboard popout re-apply only when their own font changes.
- Register plugin fonts in the dashboard popout window.
- Give dev-folder font URLs their change count so edits reload.
- Keep monospace fallbacks unless the chosen family is exactly that font.

* fix(terminal): keep every fallback only for plugin font families

System font choices keep their existing fallback list unchanged.

* fix(plugins): leave the dashboard popout's plugin list alone; add the font row string

Registering fonts there started the plugin auto-update watcher in a window with no toaster, which could consume update notices. Adds the new contribution-row string to the English catalog and the fonts list to the RPC test manifest.
2026-11-07 02:08:35 -08:00
Neil e1379b34f3 feat(pairing): Add server and orca environment add exchange the link for their own token (#38948)
* feat(pairing): Add server and orca environment add exchange the link for their own token

After verifying the host, Add server (and repair) swap the access link's
token for one generated on this computer when the host advertises
pairing.ticket-exchange.v1, and save that instead. orca environment add does
the same with a short best-effort probe. Any failure saves the link as today;
the host keeps accepting it until the new token is used.

* test(pairing): Add server and CLI leave links unchanged for a released host

* fix(pairing): Add server and orca environment add sign in once after exchanging, and the CLI rejects a refused code

After exchanging a link, sign in once with the new token so the host
retires the link right away instead of at the first later use; a host
downgraded in between would not know the new token.

orca environment add no longer saves a pairing code the host refuses
(for example one another device already used); it asks for a new code.
2026-11-07 01:48:16 -08:00
Jinwoo Hong 0e36bfa4a7 fix(automations): send managed SSH host automations to its Orca server (#39160)
* fix(automations): send managed SSH host automations to its Orca server

A managed SSH host's automations live on its Orca server (#24863), but the
create dialog, CLI and mobile still saved desktop copies that never ran.

- Desktop dialog: the host's desktop SSH entry is no longer offered; its
  key resolves to the host's server entry.
- CLI create routes to the server by project id, or asks to move the
  project there first; mobile hands the create to the server's editor.
- Existing desktop copies skip with "{host} now runs automations on its
  Orca server" and offer "Move to {host}" through the editor's move save.

STA-13422

* fix(automations): address review on managed SSH host routing

- CLI: refuse a desktop copy when the desktop reports a managed host this
  CLI holds no server for; pass the workspace by id to the server; check
  field support on the server too.
- Main: the skip follows the owner selector, so local rows pinned to a
  managed host's workspace skip too.
- Editor: a destination host whose project table loads after open keeps
  the chosen project.

* fix(automations): refuse new desktop rows on a managed SSH host and move leftovers

Per review and the owner's follow-up:
- The desktop's automation create/update refuses a row on a managed SSH
  host ("Move this project to {host} first."), covering CLI, mobile, raw
  RPC and older clients.
- Existing desktop copies move to the host's Orca server on startup, on
  managed connect and on their due tick: created there keyed by the
  desktop row id, then removed here. A server without the project leaves
  the skip and the Move button.
- Mobile drops the Save-time hand-off; its picker no longer offers a
  managed host's desktop SSH setup.
- CLI routes only for a local client, using that client's profile.

* fix(automations): drop the automatic leftover move

A managed host's leftover desktop rows keep the skip reason and the
Move to {host} button; moving them automatically will extend the existing
managed-host migration in a follow-up.

* fix(cli): resolve an automation's SSH destination from the repo's routing id

* chore: prune the repo host read baseline for the CLI destination

* fix(automations): migrate a leftover automation in one click

The detail banner's Migrate runs the editor's own move-to-server save without
opening the dialog. Leftovers show Needs migration instead of Enabled, and
their skipped runs read Needs migration to {host}.

* fix(automations): wrap the Needs migration status instead of cutting it off

* fix(automations): name a leftover's project from its migrated copy

* fix(automations): save a host move against the project table loaded after the editor opened

Migrate loads the server's repo table first, but the save transaction read the
destination captured before that load, so the first click on a cold catalog was
refused. Save now reads the same derived destination the form already shows.

* fix(automations): drop the leftover project-name fallback

The global id lookup could name another host's project. Scoping it to the
leftover's server is not worth the code for a display-only label, so a leftover
whose project moved shows Unknown project again.

* fix(automations): name a leftover's project from its migrated copy

A managed SSH leftover's project always moves to the host's Orca server with
the same id, so only those rows fall back to the id lookup; any other row with a
missing project stays Unknown project.
2026-11-07 01:47:06 -05:00
Brennan Benson f308486115 Show Source Control for folder workspaces (#38831)
* Separate editor tab placement from content ownership

* Show scoped Source Control sections for attached worktrees

* Preserve active diff refresh and validate section catalogs

* Complete folder section test worktree metadata

* Use contextual types for scoped Source Control actions

* Preserve optional scoped action parameters

* Preserve editor ownership through restore, mirroring and workspace removal

* Retire Source Control drafts only after confirmed owner removal

* Limit section work to visible expanded repositories

* Keep editor follow-up actions and bulk closes in their invoking views

* Track the consolidated editor order writer in its owning module

* Use complete typed fixtures for repair contracts

* Preserve live editor placement during layout readback

* Pass projected editor placement directly to serialization

* Read attached worktree lineage from shared graph module

* Retain inferred owner checks and scope placement retirement

* Preserve selection in untouched workspaces during purge

* Exercise editor placements in existing launch and lifecycle fixtures

* Preserve shared buffer prompts and editor strip order

* Pause inactive section context subscriptions

* Keep section recovery and file actions in the folder workspace

* Describe attached Source Control in folder workspace CLI help

* Attribute Git metadata signals once per dispatch

* Watch mounted source control sections outside the warm budget

* Resolve section watches only for served filesystem roots

* Restore restart-stable editor identity across SSH opens

* Apply section terminal routing to explicit Chat choices

* Include cross-store descendants in folder workspace panels

* Keep cross-host recovery on its existing workspace route

* Start cross-host section agents in their workspace without navigation

* Update memoized Source Control labels on language changes

* Remove unused terminal close-to-right implementation

* Suspend inactive Source Control body observers

* Retain base ref query while section observation pauses

* Cover retained base ref search across section visibility

* Resolve note menu ownership from the retained snapshot

* Preserve section agent working directories and background placement

* Keep Source Control sections active while their overlays are open

* Read current settings when Source Control commands execute

* Adapt editor and browser test stores to view subscriptions

* Preserve bound store hooks for ordinary app views

* Trust agent starts outside the placement workspace

* Trust the section worktree through transient launch ownership

* Extract editor follow-up file actions from the panel

* Fail section launches when trust capability lookup fails

Preserve explicit unsupported-host fallback, propagate lookup failures to the existing launch error path, and let the existing transport retry refresh rejected capability probes.

* Follow the moved pane launch test in web configs

* Preserve section file ownership during refresh and close

* Share tab order removal across editor close paths

* Verify companion editor close through the real store

* Close all workspace split copies for legacy mobile file requests

* Keep unmatched mobile close requests within their workspace

* Reuse the agent menu render snapshot

* Keep attached folder roots scoped to their resolved host

* Apply repository trust decisions to the launch trust owner
2026-11-06 18:25:57 -08:00
Neil 0efe201fbf feat(remote-runtime): use E2EE v2 for desktop and CLI connections to remote runtimes (#39218)
* feat(remote-runtime): use E2EE v2 for desktop and CLI connections to remote runtimes

Desktop connections to remote runtimes (orca serve, orcad, managed SSH,
browser bridge) and the orca CLI now use E2EE v2 framing for hosts that
support it, and fall back to the legacy framing for hosts that do not.

- One-shot requests try v2 first. A host that refuses the v2 hello
  (hosts from before v2) or refuses capabilities on v2 token auth gets
  one transparent legacy redial; nothing but the handshake is sent before
  authentication, so the redial is safe.
- After a v2 sign-in succeeds, the host's pinned key is remembered in the
  profile (shared by the app and the CLI). Every connection to that host,
  including long-lived sockets, then uses v2 and never falls back.
- Long-lived sockets keep legacy framing until a host has proven v2, so
  they never see an older host refuse a v2 hello.
- Hosts accept clientCapabilities on direct v2 token auth, so desktop and
  CLI clients keep their capability negotiation on v2. Relay token auth
  stays exact.

* feat(remote-runtime): recover a latched host that was downgraded, without a legacy downgrade path

A host this profile had signed in to over v2 was refused for good if it
was later downgraded below capability-carrying v2 token auth. Hosts now
advertise pairing.e2ee-v2-token-capabilities.v1. When a latched host
refuses v2, a one-shot request asks the host over legacy framing (keyed
to its pinned key, so only the real host can answer) for status.get:

- no capability: the host itself says it was downgraded; the latch is
  dropped and the request goes ahead over legacy;
- capability present, or no answer: the request fails with an error
  that says to update the host or check the network path. Only the
  read-only status check ever ran over legacy.

A refusal faked on the path cannot produce the host's answer, so it
cannot force legacy framing for a latched host.
2026-11-06 17:14:56 -08:00
Neil 3c866a31db feat(serve): refuse public source addresses on orca serve unless allowed (#39207)
* feat(serve): refuse public source addresses on orca serve unless allowed

`orca serve` listens on every interface. It now accepts connections from
loopback, private LAN (10/8, 172.16/12, 192.168/16, 169.254/16, fc00::/7,
fe80::/10) and Tailscale (100.64/10, fd7a:115c:a1e0::/48) sources, and drops
public-source TCP connections before HTTP parsing or the WebSocket upgrade.

Public sources stay accepted when:
- --allow-public is passed (orca serve, orcad, serve service install);
- a paired device has authenticated from a public address (persisted flag);
- --pairing-address is a hostname or a public IP literal;
- any device paired before this server first ran the check is still paired.

The startup log states which rule applies; the first refused public address
each hour is logged with the flag name. Desktop listeners and Orca Relay are
unaffected.

* feat(serve): accept on-link public addresses and add --refuse-public

A public source inside a prefix of one of this host's own interfaces (os.networkInterfaces, re-read at most every 5 s) is a same-network peer, such as a LAN client using global IPv6, and is now admitted. Prefixes wider than /16 (IPv4) or /48 (IPv6) are ignored.

--refuse-public (orca serve, orcad, serve service install) refuses public addresses regardless of grandfathered pairings, a remembered public connection or the pairing address; it cannot be combined with --allow-public.
2026-11-06 17:02:15 -08:00
047e113783 feat(cli): pair clients with a running Orca via orca pair (#36469)
* feat(cli): pair clients with a running Orca via `orca pair`

A headless Orca could only print a pairing offer at startup, so pairing a
phone with `orca serve service install` meant stopping the service. `orca
pair` asks the running runtime for an offer over the owner's local socket
through a new `pairing.createOffer` method (pairing-admin, never granted to
paired clients or phones). It reuses the desktop's offer logic, now shared
by the Settings IPC handlers: mobile offers stay LAN-only unless --relay,
and the first network pairing widens a loopback bind as the desktop does.

Also honor an explicit ORCA_SERVE_RUNTIME=orcad on packaged macOS. Electron
serve needs a desktop login and aborts in an SSH session with nobody logged
in; orcad is plain Node and serves there, at the cost of no in-app updater.

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

* refactor(cli): move the serve-restore and pair handler groups out of the manifest

handler-group-manifest.ts was already at the 300-line limit on main, so
adding the pair group failed lint. Group the two serve/pairing entries in
their own file, as jira, linear and reference already are.

* test(mobile): pin the desktop pairing IPC handlers' replies and runtime calls

Characterizes mobile:getPairingQR and mobile:getRuntimePairingUrl across
every branch (explicit and default address, LAN-only with no address,
Relay without an address, relay failures, this-computer reach, widening
and its failure, unavailable offers). The same file passes unchanged on
main and on this branch, so moving the offer logic into
pairing-offer-requests.ts did not change the desktop path.

* test(mobile): type the QR stub instead of casting it

---------

Co-authored-by: Office exitnote <h@Offices-MBP.lan>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Neil <neil@stably.ai>
2026-11-06 17:01:32 -08:00
Jinwoo Hong 555bd481bc Let multi-repo folder workspaces parent and nest workspaces, including on other machines (#38904)
Multi-repo folder workspaces can parent workspaces on this machine and on paired servers, and their children nest under them in the sidebar and on the phone. Task parents are inferred at creation instead of on every lineage refresh.
2026-11-06 19:03:51 -05:00
0b5a293fa2 feat(serve): add bind address option (#35095)
* feat(serve): add bind address option

* fix(serve): validate service bind address

* fix(serve): validate bind flag values

* fix(serve): reject scoped bind addresses

* docs(serve): document bind option paths

* docs(serve): note that --mobile-pairing needs an all-interfaces bind

* fix(serve): move bind address parsing to shared so the packaged CLI can load it

The packaged CLI ships out/cli and out/shared but not out/main/orcad, so
cli/runtime/serve-bind-flag.js failed the packaged runtime-import check
(and would fail to load) when it imported main/orcad/orcad-bind-address.
Move the module, unchanged, to src/shared and point orcad, Electron serve
and the CLI at it.

* test(serve): pin down the default listener and the --bind startup paths

- Extract the Electron serve listener pin into resolveServePinnedBindHost
  and test that serve without --bind stays unpinned (all interfaces, as
  before), an explicit --bind pins it from either argv form, and the orcad
  browser sidecar stays on loopback.
- Golden the orcad and Electron serve argv without --bind against the
  pre---bind output.
- Test that the CLI passes bind only when given and refuses --bind with
  --mobile-pairing before launching.
- Guard that serve-bind-flag and the shared serve validation load only CLI
  and shared modules, which is what the packaged CLI ships.

---------

Co-authored-by: lw <13579959+bertramlongwuyan@user.noreply.gitee.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: xuanchangfeng <210147232+xuanchangfeng@users.noreply.github.com>
2026-11-06 15:47:42 -08:00
Brennan Benson e0005f5cbf Attach existing worktrees to folder workspaces from the CLI (#39018)
* feat(cli): attach existing worktrees to folder workspaces

worktree set accepts --parent-worktree folder:<id> (hosts advertise
worktree.set.folder-parent.v1), keeping each worktree to one parent in the
store. --parent-worktree active/current resolves to a folder workspace from
its terminal or enclosing directory, and worktree create without --repo under
a folder workspace lists the folder's Git repositories with a ready command.

* fix(cli): report folder parents and keep typed flags in folder repo choices

worktree show/set report a folder parent; the missing-repo error lists --repo
choices to add to the user's command and names the Attached worktrees panel.
Load and import repairs skip malformed rows and only touch imported worktrees,
an import keeps a worktree's existing parent, a twin-owned folder parent warns,
and folder ambiguity keeps its choices.

* fix(persistence): settle one parent per imported worktree before writing

An Orca server migration import now decides each touched worktree's parent
before any write: an explicit folder parent replaces an inferred worktree
parent, any other disagreement refuses the import. --parent-worktree active
in a folder terminal still lists the folder's repositories.

* fix(persistence): let a folder parent beat hydrate's inferred worktree parent

Load repair and import reconciliation share one rule: an inferred worktree parent loses
to a folder parent when the folder was chosen explicitly or the worktree parent carries
hydrate's orchestration stamp. Import tests now run payloads through the manifest parser
and cover a conflict that appears after staging.

* fix(cli): list folder repos when active resolves to the enclosing folder

worktree create without --repo used only the terminal's env to find the folder, so
--parent-worktree active run outside an Orca terminal fell back to the generic
missing-repo error. Use the parent create already resolved.
2026-11-06 15:13:57 -08:00
Neil b9a4b5fd2f fix(plugins): re-review any plugin whose catalog moves it to another repository (#36643)
* fix(plugins): drop a plugin's approval when its catalog moves it to another repository

* plugins: revokePluginConsent refuses when the plugin service is not running

* cli: orca plugin install/update ask again when a plugin moves to another repository, for every plugin kind
2026-11-06 14:41:29 -08:00
Neil 1824515698 fix(plugins): warn, not fail, when a language pack translates protected security text (#39187)
Orca already drops protected strings when it loads a language pack and keeps
its own English text for trust, permission and destructive dialogs.
validate:plugin and orca plugin validate still rejected the whole pack, so the
community directory refused otherwise-good packs. They now report how many
protected strings are ignored as a warning; every other pack rule stays strict.
2026-11-06 14:35:22 -08:00
Neil be3b87f3ac cli: add orca plugin install, update, uninstall and catalog list/add/rm (#36647)
* cli: add orca plugin install, update, uninstall and catalog list/add/rm

* plugins: escape the invisible-character regex so the orcad bundle stays ASCII

* plugins: split approval re-run helpers and plugin RPC binding to stay under max-lines
2026-11-06 14:20:27 -08:00
Neil f0bfce8fce fix(automations): accept Antigravity model and effort extra arguments (#39161)
Antigravity automations refused --extra-agent-args, so unattended agy jobs
could only use the model and effort from agy's global settings.json. Allow
--model and --effort through the existing allowlist; permission, mode, and
other flags stay refused.

Part of #35234 (STA-12678).
2026-11-06 12:55:54 -08:00
Neilandggbdpq a53c00219d fix(workspace): wake a sleeping recipe VM when a client opens its workspace (#39038)
A recipe VM workspace runs on its VM's own Orca server, so a phone, the CLI or
the desktop reaching it while the VM slept dialed a server that was not there
and failed. Only the host window's click ran the recipe's resume.

- The VM wake owner (WorkspaceSleepCoordinator) tracks the VM operations it
  was asked for and answers where the VM stands: a pending wake or a running
  suspend outranks the stored record.
- The host holds a request that opens the workspace (worktree.activate,
  defined once in shared code) until the VM is up: three minutes for the
  desktop and the CLI, and for a phone only as long as still lets the relay
  connect inside the phone's 30-second deadline. A VM still up keeps a sleep
  on its way from suspending it; a VM asleep or suspending wakes after what is
  running, joining a wake already pending. The open answers waking only when
  the hold runs out, wake_failed when the wake fails, and asleep when a Sleep
  asked for while it was held won; that open then wakes nothing more. Other
  requests answer waking or asleep instead of dialing nothing. A Sleep asked
  for during a wake keeps its place in the lifecycle queue and starts once the
  wake is done. A caller that gives up stops waiting and frees its queue
  place; the wake goes on.
- An open of a server the user disconnected is refused before anything wakes
  its VM, and cancelled if they disconnect while it waits. A wake carries the
  SSH host's user hold from when it was accepted and every Disconnect since,
  so its connect never lifts a hold; the VM still resumes and its new SSH
  address is saved for the user's own Connect.
- A wake re-pairs a paired VM's server. The request that waited for it is
  held to its caller's pairing as of before the wake (a stale caller is
  refused before it can wake anything), then to exactly the pairing revision
  the resume produced (including a re-pair its SSH reconnect made), whatever
  process now serves it; any other change still
  refuses it. A phone link still preparing for an open survives only the
  re-pair its own wake made; any other retirement, or a user Disconnect, ends
  it, and a link preparing for anything else is retired at once.
- The hold lives in the desktop's environment preparation, which its own calls
  and subscriptions, the phone relay and the CLI all go through. A phone open
  on a link to a server whose VM is not up gets a fresh link; the old link's
  requests are answered waking or asleep. Further opens join a link already
  waiting on the wake. A phone link's whole open (server preparation with any
  hold, grant sync and the socket) shares one deadline inside the phone's
  own, for every server.
- The CLI dials a VM directly, so `orca worktree activate` asks the desktop
  (runtimeEnvironment.wakeRecipeVm) to open the VM and reads the server's
  pairing again; the refusals (including runtime_manually_disconnected) keep
  their codes over RPC, and a host without recipe VMs answers that one RPC
  with method_not_found. Hosts that do this advertise
  host.recipe-vm-wake.v1.
- A workspace this host runs on a recipe VM over its SSH target wakes on this
  host's own activation, through the resume's explicit connect
  (wakeWorkspaceVm -> resumeVm -> connectRuntimeOwnedSshTarget). That connect
  runs whenever the VM is in SSH mode, even when its recipe had no resume step,
  since suspend tore down the transport.

Fixes #36923

Co-authored-by: ggbdpq <ggbdpq@gmail.com>
2026-11-06 06:51:09 -08:00
NeilandFlorin Timbuc 239e17f84f feat(cli): add orca host rm, and clean up after every SSH target removal in main (#38774)
* feat(cli): add orca host rm for saved SSH targets

orca host rm --host ssh:<target-id> calls the runtime RPC ssh.removeTarget,
the same removeSshTarget the Settings UI reaches, so the tombstone keeps the
passive ~/.ssh/config import from adding the alias back.

Also document how the import treats Match blocks and Include files.

* fix(ssh): clear a removed target's live state and rename in main for every removal path

Removing an SSH target through ssh.removeTarget (orca host rm, paired clients)
left open tabs with stale reconnect state and kept the host's rename, because
only the Settings dialogs cleaned up after their own IPC call. The shared
removal mutation now drops the display-label override and tells the renderer,
which clears the target's state once for all callers.

Fixes #37949

* fix(ssh): clean up after a removed target in the teardown every removal ends in

A recipe VM's cleanup removes its SSH target through removeRegisteredSshTarget
directly, so the window kept that target's live state. The broadcast and the
rename drop now run there, after the target is gone.

Fixes #37949

* test(cli): keep host rm's retarget-flag refusal next to its other cases

Its old file was removed on main.

Fixes #37949

* refactor(cli): give the host, managed-server and VM handler groups their own module

Keeps the handler manifest under the file-length limit.

Fixes #37949

---------

Co-authored-by: Florin Timbuc <florin@sowild.design>
2026-11-06 06:23:46 -08:00
Neil 55697aec91 fix(cli): keep remote read-only commands working when environment usage can't be recorded (#39052)
* fix(cli): keep read-only commands working when environment usage can't be recorded

The CLI recorded each environment's last-used time with a strict store write,
so a profile whose directory refuses chmod (EPERM) failed commands whose reply
had already arrived. The desktop already skipped such failures in one path.
Move that best-effort recorder to shared code and route every desktop and CLI
usage write through it.

Fixes #38673

* test: assert the usage write failure, not call counts

Refs #38673

* test: skip the chmod EPERM case on Windows and drop a cast

Refs #38673
2026-11-06 05:53:10 -08:00
352e69f09c feat(cli): select and remove any saved agent account from orca account (#38944)
* feat(cli): select and remove any saved agent account from `orca account`

`orca account select` and `orca account rm` accepted only OpenCode and
Devin. They now cover every provider with saved accounts — Claude, Codex,
OpenCode, Devin and Antigravity — through the runtime methods the
status-bar switcher and Settings already use (accounts.selectClaude,
selectCodex/selectCodexForTarget, selectData, antigravitySelect and the
matching remove methods). No runtime or wire change.

`--account` takes an id, an email/label (case-insensitive) or `system`.
A name shared by several accounts is refused with their ids rather than
guessing which subscription to bill. `system` is refused for Antigravity
(no system default), for Claude from the WSL bridge (the RPC has no
target and would reset the Windows host), and always for `rm`.

`orca account list` now prints each account's id and a `system` row,
accepts `--agent` for every provider, and adds the Antigravity block when
the host can read it.

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

* test(cli): assert the host refusal for Antigravity accounts from WSL

The host rejects every client-selected WSL target for Antigravity account
management, reads included, so the test now mirrors that refusal and checks
that no select call is made instead of asserting an impossible success path.

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

* test(cli): keep only the account-selection tests that guard this change

Moves the guards into account.test.ts (the handler layer that owns them) and
drops layer-duplicating, copy-pinning, Cartesian and mock-only cases per
AGENTS.md test rules; un-exports resolveAccountId (test-only export).

---------

Co-authored-by: Maxime AUBURTIN <m@hellomax.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 03:03:51 -08:00
Brennan BensonandNarry 7fbb47e713 fix(omp): use OMP model roles, selectors and effort in chats and workers (#38713)
* fix(omp): launch OMP chats with their saved model and accept OMP effort

OMP's Chat UI model option names only listed provider/id values, so a
worker started with an OMP role or provider/model:level selector failed
before its first message. OMP resolves those on its launch line, so the
chat's saved model now rides 'omp acp --model', and a new session counts
it as applied. OMP's launch catalog gains its thinking levels, so
--effort is accepted and applied (--thinking in a terminal, the session's
thinking option in a chat).

Tracked in STA-13562.

* fix(omp): keep OMP role chats working after a restart

OMP's ACP model option takes listed provider/id values only, and a load restores the conversation's own model, so a role-started chat failed with "Unknown ACP model" on its first send after an Orca restart.

- New chats keep the saved model on OMP's launch line; resumed chats no longer pass it, so a renamed role cannot stop a good conversation from opening.
- When OMP's model option refuses a value as unknown, Orca applies it through OMP's own /model, the resolver --model uses, as a hidden send-time command. It counts as applied only on OMP's "Model set to" reply and a normal end; cancel or timeout retires the process.
- The command's reply and title notices never reach the chat, its status or unread state.
- Proof from the launch line or /model is retired when OMP changes its model or thinking itself; ordinary model-option proof keeps its existing rule.
- A refusal names the agent and the next step; on OMP older than 18.1.9, whose /model takes ids only, it also names the release to update to, carried on the modelUnavailable fact.

Tracked in STA-13562.

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>

* fix(omp): keep role steers in order and say when OMP has no model

- A role steer that OMP's model option refuses now holds its place among queued steers: answers ahead of it are cancelled as they start, and a Stop or teardown while it waits withdraws it without sending /model or the message.
- OMP's "No model selected" (an unresolved launch role, or signed out) is reported as its own failure, "OMP has no model selected. Check your model selection and OMP sign-in, then send again.", instead of a sign-in failure; the next send applies the selection again.
- A cancelled model command reads as not sent, and an option write settles once.

Tracked in STA-13562.

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>

* fix(omp): keep OMP's no-model text in the log and test a late /model answer

Tracked in STA-13562.

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>

* fix(omp): a Stop still withdraws a waiting role steer after main's turn changes

Main now clears stopAt when a turn finishes, so reserveSteer counts Stops
instead of reading stopAt. Refusal wording moves to acpPromptRejection to
keep the turns file within its line budget; behaviour is unchanged.

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>

* fix(omp): a Stop withdraws a role message anywhere in its preparation

A message that falls back to OMP's /model now counts as a held steer from
before its option writes until it is admitted. A Stop in that window
withdraws it unsent, even with no turn running; ordinary messages keep
their Stop behaviour. Restores the launch-role no-resend test main's file
removal dropped.

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>

* fix(omp): a Stop before OMP refuses /model reads as a withdrawn message

A Stop the role message already took outranks OMP's own refusal of the
model command, so the message reads as cancelled and never sent rather
than as a model failure. Pins that a Stop with no turn running is still
refused while an idle send's first model-option write is pending: the hold
starts when the send falls back, not before its option writes (the host's
Stop aborts the send's signal there).

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>

* test(omp): put the cast's safety note on the line above the cast

* test(omp): cover the new failure copy on phone and desktop, and OMP's thinking levels

Tests the no-model sentence and the update hint in English and one
translation on each surface, every level omp --thinking takes, and that a
missing model classifies as the agent's own refusal.

* test(omp): import the launch module once in the catalog test

---------

Co-authored-by: Narry <3047793+NarryG@users.noreply.github.com>
2026-11-06 02:21:09 -08:00
OrcaWinandOrcaWin a4cad3766b test: remove 1296 low-value mock and projection tests (#38837)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 21:39:35 -08:00
AnmolandKelvin Amoaba 76d23612ba fix(cli): use the terminal's worktree when cwd is outside every worktree (#38086)
* fix(cli): use the terminal's worktree when cwd is outside every worktree

Browser, terminal and computer commands run from an unmanaged cwd fell back to the worktree focused in the window. They now use the calling terminal's ORCA_WORKTREE_ID or folder ORCA_WORKSPACE_ID before that default. Fixes #37899.

* fix(cli): resolve the terminal worktree against the catalog

Match ORCA_WORKTREE_ID on the caller's host so ids shared across hosts
go out as identity:, accept folder: ids from either terminal env var,
and keep the runtime default when worktree.list cannot be read.

* fix(cli): refuse a stale terminal worktree instead of using the focused one

When ORCA_WORKTREE_ID names a worktree the catalog no longer lists on the
caller's host, fail with a --worktree hint rather than silently targeting the
workspace focused in Orca. Clear the terminal's workspace env in the test setup
so CLI tests run the same inside an Orca terminal.

* fix(cli): keep the floating terminal on the runtime default

The floating terminal's ORCA_WORKTREE_ID is a sentinel with no catalog row, so it must not hit the stale-workspace error. Word that error as what the CLI can tell: the workspace is not listed, which also covers hidden worktrees.

* fix(cli): ignore terminal workspace ids from another Orca profile

A shell from the installed app that targets a dev build or throwaway serve carries worktree ids that runtime never issued. Reuse the runtime-source fence rule to skip them, so those commands keep the target runtime's default instead of failing.

* test(cli): drop tests that pass without the terminal-workspace fallback

Remove the list-failure and cwd-precedence cases, which pass on main, and the SSH stubs the folder case never reads.

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-06 05:15:02 +00:00
OrcaWinandOrcaWin 62eab0c434 test: remove 1148 low-value IPC and filesystem tests (#38817)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 20:45:38 -08:00
Neil ac203854bf fix(cli): point positional terminal handles at --terminal (#38793)
`orca terminal read term_abc` failed with a bare "Unknown command" because the
handle landed in the command path. When a term_/structworker_ handle follows a
command that accepts a target --terminal flag, suggest the flag form instead.
Caller-identity --terminal commands are skipped. The terminal-handle prefix
check moves to a dependency-light shared leaf reused by the session-address
codec.

Fixes #38312
2026-11-05 20:20:03 -08:00
Kelvin Amoaba 345c326a91 feat(cli): rename a chat with orca chat rename (#38719)
Fixes #38556
2026-11-06 03:44:40 +00:00
OrcaWinandOrcaWin a3c76bffda test: remove 319 low-value daemon and terminal tests (#38783)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 18:43:44 -08:00
gsxdsmandNeil 219dca09d0 fix(cli): refuse oversized local requests before dispatch (#37734)
The CLI now measures the serialized runtime request against the shared
1 MiB local transport limit before writing any bytes. Oversized requests
fail with invalid_argument and requestSent=false instead of being cut off
by the server mid-frame, and the client skips mutation recovery for these
unsent requests so it never suggests resending the same payload.

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-11-05 18:08:51 -08:00
OrcaWinandOrcaWin 4abbef34d4 test: remove 859 low-value runtime and account tests (#38763)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 17:53:55 -08:00
Neil c0b2df5d8d fix(ssh): leave an unlinked host disconnected, and name it when a project needs its server (#38746)
Forget and Stop removed the managed server but left the SSH host's transport up with nothing
serving it, so project setup offered the host and then failed with the raw connection id.
The unlink now hangs up the host's transport inside its lifecycle, so every surface offers
Connect (which sets a server up again) and a Connect queued behind the unlink still wins.
The setup error names the host and its toast offers Connect, and the forget/stop help says
the host is disconnected.

Fixes #37767
2026-11-05 16:44:40 -08:00
Jinwoo Hong a9ba59c944 Nest workspaces under parents on other machines (#38740)
* feat(lineage): store cross-store parent links beside same-store lineage (inert)

A workspace's parent can live in another Orca store. Save that link in the
child's store under a new top-level key, crossStoreLineageByChildKey, so older
builds' same-store cleanup never reads it. Nothing writes records yet.

- Types, load normalization (malformed entries dropped one by one), section label.
- Store get/set/remove by child; a child keeps at most one parent record.
- Every maintenance path acts by the child only: deletion and missing-worktree
  pruning, repo removal and deregistered-repo residue, identity migration,
  profile project transfer, WSL move projection and UNC drive conversion, and
  the orcad migration dormant payload (export, validation, import, subtraction).

* fix(lineage): gate cross-store links on host capability; one parent per child

- Migration stage/commit carrying crossStoreLineage requires the new
  orcad.migration-cross-store-lineage.v1 capability; older hosts are refused
  before staging instead of silently dropping the links. Empty arrays are omitted.
- Payload validation and destination prepare reject a child that has both a
  cross-store and a same-store parent, through one shared conflict check.
- Saved entries stay on disk as written; the map is Record<string, unknown> and
  readers go through validCrossStoreLineage. Re-keying moves unreadable entries unchanged.
- Tests: literal expectations; drop touched mock-call and work-count assertions.

* test(lineage): drop clone and save work-count assertions from project group removal test

* feat(lineage): resolve cross-store parents into the sidebar parent map (inert)

- One resolver: a saved record nests its child under the single visible
  row whose store reports the parent's installationId and whose instance
  matches; copied installs, unknown stores and stale instances stay standalone.
- getSidebarLineageParentsByIdentity merges resolved cross-store parents with
  same-store edges before cycle breaking; a valid same-store edge wins.
- Workspace delete collects descendants only from the parent's own store.
- Store identity: paired stores from their verified status hostDescriptor;
  this store from the published descriptor, else host-installation.json.
- Nothing passes a view or writes records yet, so the sidebar is unchanged.

* fix(lineage): import WorkspaceKey from workspace-scope after main move

* fix(lineage): resolve sidebar parents once over complete rows; keep unowned rows' delete rule

- resolveSidebarLineageParentIdentities resolves same-store edges and cross-store
  records once over every visible store's unfiltered rows, then drops cycles.
  Ancestor injection and nesting reuse that map, so a filtered-out twin still
  makes a parent ambiguous.
- Removed, retired or refusing paired servers leave the view: their records stay
  saved and their children standalone. Offline servers keep their last-known id.
- A row with no owner is unknown, not ours: it never resolves, and delete only
  excludes descendants whose store is known and differs from the parent's.

* fix(lineage): refuse UNC rekey collisions and transfers giving a child two parents

The UNC drive conversion rekeys cross-store child keys through the shared
collision merge, so a UNC key and its drive key with different records throw
instead of one silently overwriting the other. Profile project transfer runs the
shared child-key conflict check before writing the target.

* feat(lineage): write, carry and nest cross-machine parents

- Capability worktree.lineage.crossMachine on the child's store; the CLI
  refuses before any request when the server lacks it.
- worktree.set / worktree.create accept crossStoreParent
  { installationId, workspaceKey, instanceId } and write only
  crossStoreLineageByChildKey (refused when it names this store, or the
  child has no identity). Remove Parent clears both.
- worktree.crossStoreParentRef: the parent's own store names it with its
  installationId; reparent refuses a parent whose chain already reaches
  another store. Same-store Set Parent refuses the same.
- worktree.ps rows and lineage lists carry the records; same-store lineage
  fields stay null so older readers show the child standalone.
- The desktop sidebar resolves parents over its own and paired stores'
  records (PR 2's resolver) at the visible-worktree and row-plan call sites.
- CLI: active/current or an inferred terminal parent against a server is
  sent as a cross-store parent.

* fix(lineage): read worktree rows through the record selector; mark the test runtime cast

* fix(lineage): hydrate every store, fence refreshes, honest CLI fallback

- Each host's catalog hydration fetches its lineage snapshot, so this
  desktop's identity and records load whichever store is focused.
- Cross-store records join the per-child request-start fence: a stale
  lineage list can't restore a removed record or override a newer one.
- A failed inferred cross-store parent sends noParent instead of
  forwarding the selector a server could match to a same-store twin.
- Inferred cross-store creates record env-workspace/inferred capture.
- The writer states its trust contract; the chain rule runs at the mint.

* feat(lineage): cross-machine parents on the phone, pickers, chat resume and labels

- Phone: the list nests a child under a parent on another machine, from the
  records rows already carry and the store identities its host verified
  (status.get descriptor; relayed servers' installationId on the host list).
- Set Parent popover, context menu and the composer's parent picker offer
  parents in other visible stores. The parent's own store names it
  (worktree.crossStoreParentRef); the window checks it against that store's
  verified installationId and the child store's capability before any write.
  Remove Parent and Open parent cover cross-machine links.
- Native chat resume ancestors follow resolved cross-machine parents.
- Host sections keep a nested child under its parent and keep its own
  machine label.
- Main sidebar feed resolves cross-store parents (rows carry records; desktop
  facts and paired-host facts carry identities); paired web windows read
  their host's installationId; reveal without an occurrence plan resolves
  them; `worktree create --agent` names a parent on another machine.

* test(lineage): type the mint test's parent row through unknown

* test(lineage): give the cross-machine tests' partial-row casts their SAFETY reasons

* fix(cli): worktree set names a parent on another machine

* feat(lineage): name the machine of parent candidates on another machine

* fix(lineage): Set Parent and Remove Parent act on the clicked row's own host

* fix(lineage): phone resolves parents over every row before the repo filter

* fix(lineage): chat resume nests by host-qualified identity across machines

* fix(lineage): local create refuses a same-install parent before checkout and shares the RPC recorder

* fix(lineage): name parent machines without a focus read; keep create's probes synchronous

* fix(lineage): chat resume keys offers by their own machine; only cross-machine parents leave a section

* fix(lineage): name an older parent server before asking it for a cross-machine ref

* fix(lineage): an app-picked parent on another machine records as manual

* fix(lineage): chat resume keeps base grouping; only resolved cross-store parents move a chat

* revert(lineage): drop chat resume from cross-machine parents; it groups by machine as before

* refactor(lineage): CLI builds cross-machine parents; explicit only

- Drop worktree.crossStoreParentRef and its reparent chain walk: the CLI
  builds the ref from this desktop's installationId (worktree.lineageList
  now reports it) and the parent row it reads. Cross-machine chains are
  allowed; same-store cycle validation and same-install refusal stay.
- No inferred cross-machine parent: remove crossStoreParentInferred and
  the fallback states. Against a server, this machine's terminal, cwd and
  env context is never sent; the CLI prints how to nest explicitly.

* refactor(lineage): build cross-machine parent refs from verified ids; pickers hide only loops; one desktop install id source

* refactor(lineage): refuse moving a linked workspace instead of carrying the link

Orcad migration and profile project transfer now refuse, before any staging or
write, when a workspace in the move has a cross-store parent record (raw entries,
readable or not). Remove the carry machinery: the dormant crossStoreLineage
field, its runtime capability and destination gate, import/subtract/claim code,
transfer carry and the two-parent conflict checker. Also drop the unused
removeCrossStoreWorkspaceLineage.

* docs(lineage): describe cross-store parent refs without the removed mint RPC

* test(lineage): drop the RPC call-list assertion from the cross-store ref test

* fix(lineage): refuse linked moves before any write and for shared-repo children

- Migration refusal passes the child's own host stamp to the scope matcher and
  refuses an unstamped key whose shared repo id the move includes, so such a
  child can't move while its link stays behind.
- Profile transfer checks the read-only source snapshot before pending-move
  recovery or storage migration; the payload check stays as the final guard.

* fix(lineage): refuse a linked profile move before the profile lookup can restore the index

* fix(lineage): startup hydration of other stores loads only cross-machine links

* fix(lineage): list the child's own machine first in the parent picker

* fix(lineage): keep profile argument errors ahead of the linked-move preflight

* fix(worktrees): let the first listing replace a restored server workspace stub

A restored active server workspace starts as a session stub with no head.
If git status fills in its branch before the first listing lands, the
listing merge took that as a concurrent branch switch and kept the stub,
dropping the catalog row (instance id, lineage, provenance). The workspace
then showed standalone until the next listing.

* fix(worktrees): accept a headless row's listing only when it confirms git status

A stale listing could otherwise roll back a branch switch git status saw on
an empty-head row (e.g. an SSH fallback row) during the first connected listing.

* feat(lineage): CLI nests a create on another machine under the caller workspace

- No parent flag and no --no-parent against a server: the caller's workspace
  on this machine (env, else cwd) is sent as an inferred cross-store parent,
  the way --parent-worktree active builds it. The host records it as
  inferred from environment or cwd.
- A server without worktree.lineage.crossMachine, or a caller workspace that
  can't be linked, still creates unnested and prints one note.
- An inferred parent falls away for folder targets, as same-machine folder
  creates record none.

* fix(lineage): CLI cross-machine inference reads the caller terminal and suppresses fallbacks

- The caller terminal's workspace joins env and cwd as an inferred parent,
  with same-machine precedence: env and terminal must agree, cwd only alone.
- A fallback (old server, unlinkable or unresolved caller, ambiguous cwd)
  prints one note and sends noParent, so the server's own create-time
  inference can't nest what the CLI reported as not nested.

* feat(sidebar): drag a workspace onto one on another machine to nest it

Dropping a workspace on a workspace from another machine now sets the
parent through the same cross-machine path as Set Parent: same eligibility
(loops, older servers), same refusal messages. Drop targets carry host
identity so the child's own copy is the one written.

* refactor(lineage): this machine's Orca resolves the caller parent for a create on another machine

- New read-only worktree.resolveCallerParent runs the same-machine create
  resolver over the caller's env, terminal and cwd context, so stale
  contexts are skipped and only validated parents can conflict, and returns
  the cross-store ref or a reason.
- The CLI's own precedence and terminal lookup are removed; it keeps the
  capability gate, one note with noParent on any fallback, and silence with
  no Orca context.

* feat(orchestration): remote worker-start --worktree new-child nests under the coordinator's workspace

worker-start --on <server> --worktree new-child creates the server's worktree
under the coordinator's workspace on this machine, using the same verified
cross-machine parent ref as the CLI's caller auto-nest. A server without
cross-machine parents still starts the worker, top-level, with a warning in
the receipt. Guide, CLI help and docs describe it.

* fix(lineage): resolveCallerParent reads this store's identity without creating it

- Uses the published host descriptor's installationId, else the existing
  host-installation.json; never creates or repairs it. Missing identity
  returns a reason, so the CLI creates unnested with its note.
- Drops the read-only wording: parent resolution does the same catalog
  upkeep a same-machine create does.

* fix(sidebar): validate every cross-machine parent before a multi-select drop writes

A drop of several workspaces builds every cross-machine parent ref first, so an
older server's refusal leaves the whole selection unchanged. Drops the touched
preview-timing test cases.

* refactor(orchestration): build the remote new-child parent ref with the shared caller resolver

Orchestration still picks the caller workspace; resolveCallerParentForAnotherStore
verifies it and builds the ref, and both read the installationId the same way.
Drops the copy and mock-call tests.

* fix(lineage): narrow the inferred source with a guard instead of casts

* fix(lineage): a composer parent picked on another machine nests normally once the destination is that machine

The retained host-qualified pick is classified against the current destination:
same host gives the ordinary parent fields, another store the cross-machine ref.
Also corrects two stale comments.

* perf(lineage): read only the requested child's cross-store entry

* perf(lineage): request each store's lineage list once at startup

* perf(lineage): cap optional caller-parent inference at 3 s and skip a timed-out local Orca

* perf(lineage): return cached sidebar parents when selector inputs are unchanged

* fix(lineage): snapshot selector inputs without a type assertion

* Route startup lineage and the sidebar lineage memo through their owners
2026-11-05 19:42:19 -05:00
Neil 61803ba8ba fix(orcad): a supervised server does not start without its terminal daemon, and orcad defends its instance lock (#38709)
* fix(orcad): yield a lost instance lock and refuse non-durable terminals under a supervisor

Fixes #37605

* fix(orcad): treat an unstattable lock as unproven; scope supervised help to orcad

Fixes #37605

* fix(daemon): report fresh-terminal ownership from current spawn routing

Fixes #37605

* fix(daemon): narrow fresh-spawn routing check to degraded providers

Fixes #37605

* test(orcad): cover lock-loss yield and fix stale test paths after rebase

Fixes #37605
2026-11-05 16:41:49 -08:00
Neil 6ee3ac76ff fix(plugins): ship plugin author typings in packaged builds (#38751)
electron-builder always appends `!**/*.{...,d.ts,...}` to the app `files`
patterns, so the resources/plugins/{declarative,types}/*.d.ts listed in
asarUnpack never reached the package and `orca plugin types` / `orca plugin
create` failed with ENOENT. Ship the typings via extraResources at
<Resources>/plugins (beside plugins/launch), resolve them there when the CLI
runs from app.asar.unpacked, and fail afterPack if any checkout typing is
missing from the packaged output.

Fixes #38542
2026-11-05 16:39:52 -08:00
OrcaWinandOrcaWin 27b1ed858c test: remove 184 low-value mobile, CLI and ACP tests (#38733)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 16:02:19 -08:00
OrcaWinandOrcaWin 5bc786c1a7 test: remove 133 low-value workflow, mobile and CLI tests (#38725)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 15:52:52 -08:00
Jinwoo Hong 9fbad42864 Stop a worker's helpers when the worker is stopped (#38373)
Stopping a worker also stops the helpers it started, across levels and paired hosts; kept-open helpers are skipped and listed.
2026-11-05 16:35:59 -05:00
OrcaWinandOrcaWin 9af8f63538 test: remove 79 low-value cloud, hook and search tests (#38642)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:58:24 -08:00
OrcaWinandOrcaWin 87631616a8 test: remove 60 low-value storage and CLI tests (#38631)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:34:32 -08:00
OrcaWinandOrcaWin 64cd31458d test: remove 31 low-value interaction and state tests (#38629)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:21:57 -08:00
Neil 87788aeae5 refactor(runtime): group terminal execution owners (#38517)
* refactor(runtime): group terminal execution owners

* fix(tooling): retarget terminal ANSI consumer owner
2026-11-05 03:46:49 -08:00
NeilandMatthew Wilkinson f660d8c47d feat(plugins): add permissioned desktop appearance publication (#38524)
* feat(plugins): add permissioned desktop appearance publication

* docs(plugins): add one-line API comments for appearance provider

* chore(plugins): regenerate declarative testing kit for appearance API

---------

Co-authored-by: Matthew Wilkinson <wilkinson.m@outlook.com>
2026-11-05 11:31:23 +00:00
Neil 2f217b4d0d refactor(daemon): group endpoint, provider, session and transport owners (#38462)
* refactor(daemon): group transport, provider, endpoint, and terminal owners

* refactor(daemon): consolidate owner imports and preserve pinned baseline sources

* refactor(daemon): import termination budgets from their defining owner

* fix(ci): retain serve mode coverage for extracted orcad startup

* fix daemon build smoke to load concrete argument owner

* read daemon protocol facts from historical defining paths

* route protocol revision owners through compatibility checks
2026-11-05 01:54:51 -08:00