mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
175f10e32b4901ac9219b078a2b3ee2e6a6dccbb
169
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
818055fcbb |
feat(orchestration): answer workers' permission prompts from the coordinator (#40756)
* feat(orchestration): deny a worker's permission prompt, and say when mail is held
A chat worker that stops at a permission prompt now escalates with the prompt
itself as structured data (approval id, state, worker, summary, allowed
actions). The coordinator can deny it with a reason through
`orchestration deny`; the worker carries on and gets the reason as mail.
Only a person can allow a prompt: the answer method decides "person" from
the transport, never from params. The stop report keys one escalation per
approval and sends one closing line when it is answered, and no longer tells
the coordinator that `orchestration send` answers a prompt.
`orchestration send` now warns when the delivery gate would hold the mail
right now (an open prompt, a blocked status, typed text), and says delivery
state is unknown for a worker on a paired server.
* fix(orchestration): only the desktop app counts as a person for worker approvals
A paired device can carry a remote CLI, so it is treated as an agent: it can deny with a reason but never allow.
* fix(orchestration): approval answers and held receipts follow the real gates
- A same-option answer counts as Orca's only when Orca recorded it; a retry returns the same
receipt with no second reason mail.
- An unreadable chat is not a closed prompt: the answer refuses, and the closer keeps watching.
- A closing line tells a reason only when it went to the worker as mail.
- The terminal held receipt prints the delivery gate's own refusal; the chat one prints what the
pointer's admission and queue gate would do (not attached, refused, or behind an open prompt).
* fix(orchestration): read the held receipt only after the mail is stored
An await before the insert let a worker settle meanwhile, so the mail could land on a settled
Dispatch after its follow-up scan. The closer also removes only the approval map it read.
* fix(orchestration): tell the coordinator not to block on a worker's permission prompt
The approval escalation now says the worker is waiting for permission, tells a chat
coordinator the user has been shown Allow/Deny (a terminal coordinator: a person must
answer it in Orca or the worker), asks it to carry on with other work and not message
the worker until the answer arrives, and offers deny only as the way out when the
prompt is holding up the task. The guide and CLI docs say the same.
* fix(orchestration): a paired coordinator without an Orca session id mails a deny reason from its Run
* feat(orchestration): answer a Claude terminal worker's permission prompt
A worker pane's PermissionRequest hook now waits for Orca's answer, so the coordinator can deny
it with a reason (the worker continues) and a person can allow it. One record per waiting hook,
keyed by Claude's prompt and tool call; it is answerable only while the hook waits and the dialog
is on screen, and anything else gets `{}` as before.
* test: annotate the fake screen instead of casting
* test: wait on the hang-up instead of sleeping
* fix(orchestration): claim a terminal answer only from what Claude shows
An answer is written only while a caught-up screen still shows the dialog
in the same process run, and claimed only once Claude shows it applied: the
hook's deny line for a deny, no other close for an allow. A Yes, a No or the
2:00 auto-block that wins the race is refused and named from the screen.
A hook that hangs up is not an answer: with the dialog still up the
coordinator is told a person must answer it in the worker's terminal.
A PermissionRequest entry the user made async stays async: it prints {}
first and never waits for a decision.
* fix(orchestration): name a terminal prompt's close from its tool_result
The screen could show an older prompt's close, so who answered is now read
from the tool_result Claude's transcript records for that tool call: Orca's
own deny text credits Orca, the user's No and the 2:00 safety-check block
name themselves, and a run names an allow. Hook events cannot say this: a
deny or a No fires no PostToolUse. The screen only says whether the dialog
is still up before a write, and a PostToolUse seen mid-answer is kept.
* fix(orchestration): read a prompt's tool_result without blocking main
The transcript read is async, reads only its tail, and skips any path that
is not a regular file, so a FIFO or device cannot stall the main process.
A closed prompt still awaiting its result gets one last read when the lead's
turn stops, so a result written late still names the close.
* feat(native-chat): answer workers' approvals from the coordinator chat
A worker's open permission prompt appears as a card at the end of its coordinator's chat, drawn
from the escalation payload as soon as it is stored. The person allows or denies it there; the
card's buttons answer the worker's own prompt over the desktop app's IPC, so only a person can
allow. Once answered, the card turns into a receipt saying who answered.
* fix(orchestration): read a terminal prompt's countdown when it is first escalated
* refactor(orchestration): give a terminal prompt's hold state its own module
* fix(native-chat): let a worker's approval card answer, and drop it once it lapses
The window's runtime calls never carried the orchestration contract
version, so the card's Allow and Deny were refused as an obsolete client.
The renderer ships with its main process, so desktop IPC states the current
contract. An open card whose agent's own countdown has passed, with no
closing message (the app restarted while it was open), is no longer shown.
* test: say why the desktop fence test's runtime stub is enough
* fix(orchestration): a chat worker's approval asks to allow its tool, like a terminal worker's
* fix(native-chat): pause the approval countdown while the window is hidden
* chore(i18n): protect the approval card's worker line copy
* fix(orchestration): close a terminal prompt's card as soon as Orca can't answer it
When the dialog leaves without an answer through Orca, the closing line is
published at once, so the coordinator's card becomes a receipt; a tool
result that arrives later adds a second line naming how it closed, without
waking the coordinator. On startup, open terminal prompts left by an earlier
run are closed the same way, since their holds lived in memory. A Claude
terminal card's reason is the warning Claude prints under the command.
* fix(orchestration): keep the dialog-warning patterns ASCII for the orcad bundle
* fix(native-chat): say when a deny reason reached the worker as a separate message
A coordinator's deny reason for a chat worker whose prompt takes no message is sent
as mail. The receipt showed it the same as a reason that went with the denial, so it
now labels it 'Reason, sent as a message'.
* chore(native-chat): follow main's moved window-activity and agent-session modules
* fix(orchestration): only Orca's own reports draw approval cards, and every card closes
- Cards and the startup sweep read approvals only from rows whose id is the stop report's own
stable id for that approval, through one shared parser; a worker's send cannot draw a card.
- A chat worker's card closes as soon as its own chat answers it (a journal watch replaces the
turn-edge check), when an answer finds the prompt already gone, and after a restart.
- A terminal coordinator is told nobody was shown the prompt and to tell the user; the
terminal-only close asks the same and goes out as an escalation.
- A chat coordinator's line names only the answers its card offers; a prompt with none is a
plain prompt with no card.
- A person's Deny on a chat worker mails no extra reason.
- A record a quit or budget end closed stays closed.
- One closed-approval builder; `waitingOn` becomes `awaitsReply`.
* fix(orchestration): a failing read cannot hang an answer, fail a stored send, or fail the database open
* refactor(orchestration): add the held-send line in send-delivery-hold, keeping send-methods under the size cap
* test(orchestration): read the worker's mail with a schema, not a cast
* fix(orchestration): an open approval stays visible and closes even behind many closed ones or a missing database
|
||
|
|
3477cb17d4 |
fix(agents): point DeepSeek Harness install link at the dsh-TUI it launches (#41069)
The catalog's Install link opened DeepSeek's site, which installs only dsh. Orca launches the community @deepseek-harness-tui/dsh-tui, so users either stayed undetected or guessed the dead unscoped dsh-tui package. |
||
|
|
c96271dc5b |
fix(mobile): say Update mobile on desktop chats an old phone app can't show (#41063)
An old mobile app lists a desktop-created structured chat it cannot render with the title 'Update to view', which doesn't say whether the phone or the desktop needs the update. Name the phone app, and document the symptom and recovery steps in the mobile troubleshooting docs. |
||
|
|
5f3b2fa4bf |
feat(artifacts): allow artifact publishing by default for new profiles (#40948)
New profiles default artifactSharingEnabled to true. Existing users are unchanged: stored settings win over defaults on load, and a stored profile saved before the key existed loads as false instead of inheriting the new default. The gate still requires an explicit true, sign-in is still required, and web clients still mirror the host (their local fallback no longer inherits the desktop default). showArtifactsButton is unchanged. |
||
|
|
c2e6ebbf0b |
feat(cli): read, message and wait on agent chats with orca chat list/read/send/wait (#40836)
* feat(cli): read and message agent chats with orca chat list/read/send Carried over from #33115 (squashed onto current main; conflicts with chat rename resolved). * feat(cli): wait for a chat to settle, read text from stdin, refuse paired hosts chat send --wait and chat wait poll the history's working flag until the chat is idle or waits on a question, keeping a queued message pending until it runs. chat read is one history fetch and returns a cursor. Unattached and paired-host refusals say what they mean. * fix(cli): settle a held queued message, skip subagent rows, resolve chat list --worktree * fix(cli): show chat errors, keep waiting through queue handoffs, return the whole settled turn * fix(cli): settle any queued message the host will not send, show grouped questions and only answerable prompts * test(cli): drive chat tests through a real client and fake timers * fix(cli): describe chat --session, --wait and --state in command help * fix(cli): report chat wait in chat list's states, reject unknown --state, flag truncated reads * docs(cli): say chat wait settles on the chat's own turn; no truncated flag on held * fix(cli): chat rename help asks for a session id, not a handle --------- Co-authored-by: YangNuoCheng <42427439+YangNuoCheng@users.noreply.github.com> |
||
|
|
fc156aad4b |
feat(release): publish a server-only Linux tarball for orca serve (#40280)
* feat(release): publish a server-only Linux tarball for orca serve Each release now also uploads orca-server-linux-x64.tar.gz and orca-server-linux-arm64.tar.gz (orcad slot from the qualified template, the pinned Node, and an orca-ide launcher) plus orca-server-sha256sums.txt, so a Linux host can run orca serve without the desktop package. The tarballs are packed and smoke-tested (serve --recipe-json, then pair a second profile) on both architectures, including bare ubuntu:24.04 and debian:12-slim containers. Upload runs only after the release is published and nothing depends on it, so it cannot hold the desktop release. * fix(release): keep the server tarball's launcher env out of its terminals; skip refs that predate it - The launcher runs the CLI with ELECTRON_RUN_AS_NODE=1, as the packaged app does, and the CLI strips it before starting orcad; ORCA_APP_EXECUTABLE and ORCA_SERVE_RUNTIME are cleared. - Ship Node's LICENSE beside the runtime. - Skip packing on release refs that predate the scripts, and upload only when both tarballs passed. - Run the PR smoke when the CLI's serve-runtime selection changes; document service install. |
||
|
|
a163b9fc5b |
test: remove low-value copy, inventory, and runner assertions (#40282)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
6c07eac31c |
fix(speech): move OpenAI dictation to gpt-transcribe before the gpt-4o models shut down (#40159)
OpenAI shuts gpt-4o-transcribe and gpt-4o-mini-transcribe down on 2027-02-26. Offer GPT Transcribe instead, retire both old entries so a saved choice loads as the new model, and send the language hint as languages[], which gpt-transcribe takes in place of language. |
||
|
|
80a9ed69f0 |
fix(native-chat): move open Codex chats to the account you switch to (#40148)
A Codex chat launched codex app-server on the account home saved when the chat was created, and nothing compared it with the selection, so after a switch every message kept going to the old account. A chat that had hit its usage limit kept failing with "Codex hit its usage limit" even though the new account had quota. Codex chats now follow the selection the way Claude chats do: the launch prepares the selected account's home, the started process reports that home, and the host replaces an idle chat whose account no longer matches before its next message. Codex resumes a thread only from a rollout in its own CODEX_HOME, so the launch links the thread's rollout into the new home first. The chat's usage card reads the account its next turn runs on. |
||
|
|
74106a0dbc |
Add protected telemetry milestones (#40043)
* Add protected telemetry milestones * Fix milestone provenance and acceptance * Fix telemetry test lint suppression * Relay remote accepted chat prompts to desktop telemetry * Honor paired desktop consent when chat host runs telemetry * Fix mobile typecheck for notification retry timer |
||
|
|
e1381cfa3e |
Rotate the server pairing identity when ORCA_INSTANCE_ID changes (#39217)
* Rotate the server pairing identity when ORCA_INSTANCE_ID changes * Back up replaced identity files, keep the recorded id on reset, keep staged files once the rotating marker is published * Add identity-reset files to the sync fs baseline and document the backup folder * Report a reset honestly after finishing an interrupted rotation; keep first backups and the newest one |
||
|
|
9a1c3a362d |
more accurate chat ui invocation count (#39784)
* rm doc * wip * wip * wip * wip * wip * Handle opening message receipt collisions |
||
|
|
18eadb8628 |
Reorganize the worktree context menu (#39739)
Group related actions into submenus and clarify the scope of sleep and delete actions for workspaces with descendants. |
||
|
|
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. |
||
|
|
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> |
||
|
|
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> |
||
|
|
de80cd74c0 | fix(agents): list agents found through a custom command path (#39178) | ||
|
|
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). |
||
|
|
a20e577dc9 |
feat(antigravity): manage accounts in the selected WSL distro (#39007)
Antigravity Accounts rejected a WSL account location outright. agy inside WSL keeps its login in its file store (~/.gemini/antigravity-cli/ antigravity-oauth-token; it detects WSL the same way isAntigravityFileStorageHost does), so save/select/remove now work there: - A WSL credential backend reads and writes that file through runWslProcess in the selected distro (default resolved via resolveWslDefaultDistro). It checks the distro is running before every guest command and never starts a stopped one. Writes are a compare-and-swap inside the guest (sha256 of the expected file), go through a private temp file and rename, and pass the credential on stdin rather than the command line. - runWslProcess accepts stdin input for argv-delivered commands. - Each distro gets its own encrypted vault, so accounts never cross distros or the Windows host. - Accounts "Refresh usage" is enabled for WSL now that usage reads the selected runtime (#38985), and rejects a reading tagged with another runtime's provenance. Fixes #25847 Linear: STA-9624 |
||
|
|
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> |
||
|
|
95c6a04133 |
fix(antigravity): switch agy accounts through the Linux Secret Service keyring (#38996)
* fix(antigravity): switch agy accounts through the Linux Secret Service keyring agy stores its Linux login with go-keyring's Secret Service provider (service=gemini, username=antigravity, login collection or default alias) and falls back to its credential file without a session bus, in containers, SSH and WSL. Add a secret-tool/gdbus adapter that mirrors that collection choice, refuses locked keyrings with a clear error, and keep the file store for headless hosts. Fixes #32818 (STA-11911) * test(antigravity): avoid casts in Linux keyring adapter test |
||
|
|
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> |
||
|
|
b2015a2d89 | docs: clarify multi-account setup and concurrency for Codex and Antigravity (#38880) | ||
|
|
345c326a91 |
feat(cli): rename a chat with orca chat rename (#38719)
Fixes #38556 |
||
|
|
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
|
||
|
|
9658ec48ad |
fix(automations): accept Pi model and thinking extra arguments (#38020)
* fix(automations): accept Pi model and thinking extra arguments * fix(automations): keep Pi provider pins and refuse unpinned inline keys * fix(automations): match Pi value options to its argument parser * fix(automations): refuse Pi model overrides beside unscoped inline keys * test(automations): cover Pi's last-provider-wins key pin * fix(automations): refuse any Pi custom Command text with --api-key * fix(automations): drop the Pi inline-key pin guard Pi already sends an unpinned inline key to the chosen model's provider and warns; the user typed both the key and the model, so Orca does not refuse it. |
||
|
|
9c7fe9793e |
fix(deps): backport minimatch, glob, and deepmerge security fixes (#37981)
Backport upstream matching and abort fixes plus safe deepmerge property handling across the independent workspaces. Includes installed-package regression tests and audit-tool fixture repair. Agent-reviewed at 83ca381d519e6247d7c1b3f0a52ce2907a9f9a19; CI aggregate passed. Version-based scanner alerts remain open pending documented disposition or compatible upstream releases. |
||
|
|
d2f874dbb5 | fix(terminal): rename link popover's "Open in this group" to "Open in new tab" (#37920) | ||
|
|
7f885c19a6 |
fix(skills): rename computer use to orca-computer-use (#37659)
* fix(skills): rename computer use to orca-computer-use * test(skills): resolve rename fixture after main cleanup |
||
|
|
0a1e420212 |
feat(editor): add Insert Final Newline on save (#37786)
* feat(editor): insert final newline on save Based on the community contribution in #33567 by @johnie. Co-authored-by: Johnie Hjelm <864992+johnie@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: credit community final-newline contribution Co-authored-by: Johnie Hjelm <864992+johnie@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(editor): exclude CSV previews from clean saves Restore the final-newline setting imports after the upstream settings refactor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(editor): skip unnecessary clean saves Only run the final-newline clean-save fallback when text needs a newline, while preserving empty and terminated drafts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(editor): preserve pending edits on keyboard save Use current tab state and retain loaded fallback text when pending edits have not produced a draft yet. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Johnie Hjelm <864992+johnie@users.noreply.github.com> |
||
|
|
06b8f7dc37 |
Keep Windows and Linux chat switching separate from worktree shortcuts (#37199)
* fix(shortcuts): give Windows and Linux chat switching a working default * test(shortcuts): verify the worktree and chat chords independently * fix(shortcuts): preserve agent newline keys while switching chat views * fix(shortcuts): use Ctrl+Shift+F11 for Windows and Linux chat switching The Ctrl+Alt+Shift+J default could not match non-Latin layouts or IME input, because Ctrl+Alt chords skip the physical-key fallback that protects AltGr characters. A function-key primary matches on every layout; Ctrl+Shift+J stays as the alias where Switch worktree doesn't claim it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(shortcuts): keep the chat toggle's own default alias when its shortcuts are edited Saving any change to Switch between Chat UI and terminal on Windows and Linux kept its untouched Ctrl+Shift+J alias, which the conflict check then refused against the worktree palette's default, so replacing or removing the primary failed. The check now exempts a chord per binding when it is the action's own default and every other owner also holds it as a default, so non-default explicit claims are still refused. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(shortcuts): expect the new Windows/Linux chat switch label The context menus show the toggle's primary binding, which is now Ctrl+Shift+F11 on Windows and Linux. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
54b496cef1 |
fix(cli): open ordinary directories as folder projects (#37232)
* fix(cli): open ordinary directories as folder projects * fix(cli): explain the non-Git layout in the repo add next step |
||
|
|
29479ddd3e |
Chat UI roll out implementation (#37222)
* Adjust Chat UI announcement rollout and show a nonblocking card - Assign new profiles to an 80/20 control and treatment experiment, with treatment split between all users and eligible harnesses. - Show terminal-default users a corner card and record targeting assignments to measure outcomes. * Refine the Chat UI announcement card layout and copy * Add live switching demo to Chat UI launch tip experiment * fix test * Shorten Chat UI announcement telemetry documentation * Add a swapped-button cohort to the Chat UI launch tip - Assign 10% of new enrollments to the new variant while preserving existing assignments. - Track live-switching link exposure and simplify the demo copy. * Adjust Chat UI launch tip rollout and switching options - Add a centered dialog cohort and independently vary button emphasis. - Target users who have not switched and allow switching back to terminal. - Record live-switching exposure only when the link is visible. * Validate persisted chat tip emphasis before initializing telemetry * Target chat UI launch tips using the current default surface Freeze eligibility at enrollment while preserving the historical audience. |
||
|
|
923be35090 |
docs(settings): point the Chat or CLI choice at Settings → Agents (#36871)
* docs(settings): point the Chat or CLI choice at Settings → Agents The Settings → Chat → Providers page was removed; the default and the per-agent choice now live in Settings → Agents. Tracked in STA-13195. * docs(settings): say the Chat | CLI choice is for supported agents on this computer |
||
|
|
ac99f1cb39 |
fix(emulator): list only the worktree's attached emulators, iOS and Android (#37127)
* fix(emulator): scope emulator list to the worktree's sessions emulator list ignored --worktree and returned serve-sim's global iOS helper list. It now lists the session registry's attached sessions (iOS and Android) for the selected worktree, or every worktree's for --worktree all. * fix(emulator): drop stopped devices before listing sessions * fix(emulator): point the no-active hint at emulator devices * test(emulator): assert list results, not serve-sim calls * refactor(emulator): prune stopped devices inside the registry listing |
||
|
|
5467bf3d25 |
fix: preview remote HTML outside registered workspaces (#36791)
* fix: preview remote HTML outside registered workspaces * fix(terminal): keep HTML from hosts without re-grantable files in the editor * fix(doc-preview): check outside-workspace reads by host-canonical path and page large workspace assets * fix(doc-preview): check approved folders for workspace assets of outside documents * test(e2e): read the preview guest without a type assertion * test(e2e): explain the outside-workspace preview timeout * test(doc-preview): type the pinned grant target in the share test --------- Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com> |
||
|
|
b17d408416 |
Plugin dev loop: TS workers, hot reload with state, orca plugin dev watch, authoring skill (#36982)
* feat(plugins): build-less TypeScript workers A worker's main may be .ts/.mts. The plugin host installs module.registerHooks scoped to the plugin folder: .ts files are transpiled with the frames' sucrase options (lines kept, inline source map, source maps on), relative imports fall back to the frames' candidate files, and a value import of the type-only 'orca/worker' fails with a clear error. Needs engines.orca >=1.4.246. * feat(plugins): components panels hot reload with their state - In dev folders a save swaps only the hidden guest: keyed memory atoms are handed to the new guest (ui.retain → ui.hydrate memory), dropped when an atom's version changes. - A save that fails to load keeps the last good render and shows an inline file:line:col error banner; the next good save clears it. A subtle Reloaded mark follows a reload. - Transpile and import errors carry line and column; dev worker restarts keep storage. * feat(plugins): orca plugin dev watch One command for the inner loop: refreshes .orca/types, dev-loads the folder, follows its frame and worker logs (plugins.getLogs gains an optional cursor), prints reloads (optional devChangeCount on list entries) and status changes, and unloads on Ctrl-C. --json streams NDJSON events for agents. * feat(skills): orca-plugin-authoring bundled skill guide A guide for agents to build Orca plugins end to end (decision table, build-less rules, the dev watch loop, test/check, validate, release-entry, approvals, gotchas) with references generated from the component catalog, host API table, event schemas, manifest schema and CLI specs, checked for drift. Fixes the components template's Reset to set(count, 0). * feat(plugins): orca plugin dev watch --check; test kit details in the authoring skill - --check runs orca plugin check after the load and after each reload (one at a time; saves made meanwhile fold into one rerun) and prints each panel's render or errors inline, as a `check` event with --json. Local folders only, since it runs the plugin's code here. - The orca-plugin-authoring guide's Test and check section now documents orca plugin test and check from #36969 exactly (JSON results, exit codes, test placement, the orca/testing kit and its common mistakes), and the loop uses dev watch --check. * refactor(plugins): move the components renderer's timing and helper constants to their own module |
||
|
|
a2a81cbf0a | fix(theme): built-in color pairs meet WCAG AA and dark-mode surfaces stay themed (#36561) | ||
|
|
47b7af097c |
Add --spec-file and one keep-open name to orchestration worker commands (#36545)
worker-start and task-create take --spec-file <path> (or - for stdin). worker-start --keep-open keeps a worker open after it finishes in one step, and worker-keep-open replaces worker-retain (kept as a hidden alias). Concise text output escapes terminal control characters in worker-written values. |
||
|
|
d4a14acad3 |
fix(updater): skip apt's _apt sandbox notice in the Linux .deb install command (#35643)
The copied .deb install command now passes -o Binary::file::APT::Sandbox::User=root to apt. The _apt sandbox user can't read the package in the user's private ~/.cache, so apt already fell back to root and printed an "unsandboxed as root" notice; presetting that fallback for the file: method removes the notice without changing effective privilege, and network methods stay sandboxed. Fixes #35641 Co-authored-by: Neil <neil@stably.ai> |
||
|
|
8138232c4f |
Print concise orchestration CLI output for agents, with --full for the full record (#36498)
Orchestration commands print small flat fields in text and --json by default; --full prints the previous output. Failures exit non-zero with error: <code>: <message> on stderr. |
||
|
|
01e03f9920 | fix(browser): present Electron's own user agent on Google sign-in pages (#36519) | ||
|
|
76cf164cf9 |
Chat UI leaves Experimental: each agent's Chat or CLI choice decides what opens (#36110)
* Chat UI leaves Experimental: each agent's Chat | CLI choice decides launches Remove the experimentalNativeChat switch and every gate on it. The Chat settings page, Default Agent Chat | CLI choice, + menu Chat/CLI rows, source-control surface choice, Antigravity chat section and orchestration chat-error switch are always present. What a new launch opens comes only from the per-agent choice (no saved choice opens a chat) plus the existing support checks. - One lookup, nativeChatPreferenceFor, keyed by agent id so host-registered agents read the same way; unreadable settings still open a terminal. - A relayed desktop stamp (nativeChatDefault) maps onto the launched agent; an explicit surface still wins. Old phones' createSupport keeps admitting by the host's per-agent choice. - settings.get stops publishing the retired switch keys; nothing in the repo reads them from a host. - Startup chat sync and hydration run when some agent can open as a chat or the machine already holds chats. - The retired key is stripped on load. The one-time upgrade tip from the chat upgrade is retired with its audience record; a new record, captured once from the raw profile, marks which existing profiles had Chat UI off. - The window-side AI-button tab path, which only ran with the switch off, is deleted. * Keep profiles that had Chat UI off on the terminal Existing users who never turned Chat UI on would otherwise see new agent launches open as chats, since an agent without a saved choice now opens as a chat. The one-time load step that records the new audience also sets every known agent to CLI for those profiles, in the same save and only when the record was absent, overwriting saved chat choices the old switch masked. Profiles that had Chat UI on and new profiles are untouched. Browser profiles keep their own settings, so the web client does the same once: a stored switch that is not on seeds CLI choices, and dropping the key marks the step done. Agents first seen after this step open as chats. * Agents without a saved Chat | CLI choice open as their CLI An agent with no saved choice now opens in the terminal for everyone, including fresh installs and agents first seen later. The one-time load step carries what launches opened while Chat UI was experimental: with the switch on, every known agent without a saved choice is saved as chat; with it off, chat choices the switch masked are saved as CLI. Existing profiles join the launch tip audience whether the switch was on or off. Browser profiles get the same carry from their saved key. The startup chat restore and host agent list now run only when some agent is saved as chat or the runtime holds chats. * Preserve owned terminal launches and local chat choices * Clarify chat and terminal support * Explain worker CLI integration timeout budget * Use checked annotations for chat graduation test fixtures * Store agent surface default separately from per-agent overrides * Preserve explicit Chat intent across default changes * Preserve current browser settings during host replies * Correct browser settings factory and regression types * Name exported launch fixture mock types and clarify agent defaults * Preserve settings fallbacks and complete launch test lifecycles * Check allocated tab identity before launch fixture interpolation * Register combined integration project for compiler parity probes * Use checked settings in the launch test fixture * Preserve retired Chat preference data privately * Align chat E2E fixtures and capture pane lifecycle evidence * Use typed raw settings in retention contracts * Consolidate transcript diagnostic imports * test: align chat fixtures with live pane and native menu contracts * test: capture relay tab selection loss diagnostics * test: wait for owned shells before synthetic chat fixtures * test: preserve all-host visibility in SSH observer * test: bind synthetic transcript fixtures before provider seeding * test: assert selected chat owner after narrow image preview * ci: allow fifth compiler project to complete comparison * Type the web-terminal fixture's chat map without an assertion * Right-click the selection itself in the chat copy spec |
||
|
|
2b00c57182 |
fix(agents): accept launch-time --model and --effort for grok (#36480)
* fix(agents): accept launch-time --model and --effort for grok Grok's session option catalog already maps model and reasoning effort to -m / --reasoning-effort, but it did not opt into worker launch preferences, so orchestration worker-start rejected --model/--effort for grok. Opt the catalog in and list Grok in the CLI help and docs. Fixes #36199 * test(orchestration): use an agent without launch preferences in the federation rejection test |
||
|
|
a1f7f97671 |
Orchestration v3: coordinators end their turn and Orca wakes them (#36137)
* fix(orchestration): keep a terminal's mail from being consumed by another terminal, and let settled structured workers take further tasks A plain orchestration check consumed the named terminal's mail whatever terminal ran it, so a coordinator checking a worker's handle took the worker's message. A consuming check from a terminal whose own live pane is a different terminal's is now refused; --peek and --all still read it without consuming. worker-start --terminal and dispatch --inject routed a structured worker (structworker_ handle) as a terminal and failed with terminal_unsupported_for_agent_session. Any agent-session party now takes its task as a send into its session, while a structured worker keeps the pane and process authority its first Dispatch had. * fix(orchestration): fence check by live terminal incl. acks; defer injecting structured workers Review fixes for the mail fence and structured worker reuse: - The check fence compares the caller's and the mailbox's live terminal process instead of recorded panes, so exited terminals keep the old behaviour and two processes sharing a recorded pane are told apart. It also covers --ack in every read mode. The caller lookup is shared with the lifecycle caller fence. - dispatch --inject to a structured worker stays refused as before: an injected Dispatch takes no custody, so releasing the first Dispatch could close a session working on the second. worker-start --terminal reuse transfers custody and stays supported. - worker-start decides pane-less chat authority from the resolved party and passes the session down, so delivery and next commands no longer re-derive it from the address spelling. - Receipts name an agent session, not a chat. * fix(orchestration): an exited caller's env pane names no caller The caller lookup fell back to the env pane key whenever the env handle was not live, so an exited terminal's pane resolved to whatever terminal now occupies it, and a tmux worker's own check was refused. The pane fallback now applies only when the env handle is not proven exited. * fix(terminal): keep surviving terminals streaming to main after a restart Main now attaches every live local daemon session it adopts at startup, not only ones a window pane or remote view is showing, and re-attaches after a daemon endpoint drop. The attach snapshot seeds main's screen, tail and title, and an attached-but-silent agent gets an output clock so readiness can see it has gone quiet. Waits on a survivor main could not attach fail at once instead of timing out. * fix(terminal): restore only pane-less streams after endpoint loss; one attach state - Endpoint loss re-attaches in main only sessions no renderer view reports; a pane restores its own. - The attach hide skips views mid-attach and leaves a pane's own hidden claim alone on failure. - One per-session stream state (attaching, attached, lost) replaces three sets and is forgotten on exit. - Waits retry the attach before failing, including after a failed re-attach. - The output clock starts wherever a reattach result is seeded, so pane reattaches get it too. * refactor(terminal): attach survivors at inventory adoption only; waits on unattached survivors fail at once; one ptyId output clock * test(e2e): scope the restart attach spec's terminal listing to the unopened workspace * fix(terminal): narrow survivor attach: waits behave as on main, one quiet clock per generation, keep main's hidden mark on failed attach * Teach the orchestration guide when to hand off and to end the turn after dispatch * Rewrap a messaging reference line * Keep the original placement default and skill trigger; keep the accuracy fixes * Point DAG retries at --retry-of and drop the last blocking-wait instruction * Check the served orchestration guide by its new worker heading * Apply council review: best-effort wake, full completion rule, restored safety rules, fixed scope and settled wording * Say when the orchestration skill applies, and prefer own subagents otherwise * Name the polling, steering, checkout, and worker fan-out habits to avoid * fix(orchestration): wake a coordinator whose turn ended while its program still reports working Claude Code keeps its OSC 7501 report on working while an agent-teams teammate is alive, even after the lead's own turn ends. The mailbox gate, idle edges and tui-idle all read that report, so worker mail was stored and never typed. A hook turn end newer than the program's working report now counts as rest; hook rows re-classify the PTY so the existing idle edge delivers. Agent Teams panes now join their claude hook rows. * fix(orchestration): compare the lead's own turn end, not the row's receipt A child's hook restamps the row's receivedAt while the lead's turn is still the old one, which could mark rest under a newer program working report. Use the lead's turn-end stamp on this runtime's clock, after the latest input. * feat(orchestration): a consuming check marks the batch it returns as handled * Say why watch scripts and open waits block the wake * feat(orchestration): release settled workers automatically after a grace period * fix(orchestration): use checked row reads for delivery cursors * fix(orchestration): trust a live own-process turn end instead of comparing clocks Drop programActivitySince and the turn-end clock mapping: replays and SSH host clocks made the comparison unreliable. A Claude lead counts as at rest under a program working report when its hook turn end is a live transition from this pane's host and launch, past the existing input and respawn floors. * test(orchestration): drop cast in ack no-op check * test(orchestration): seed legacy outstanding batch for held chat nudges * test(orchestration): built CLI check hands its batch over * test(orchestration): annotate unchanged casts and stub the keep item in tab menu tests * fix(orchestration): let real input, explicit release and host releases converge with automatic release - Record worker takeover at the owning runtime when it accepts UI input, before the bytes reach the PTY. - Run remote attachment releases through the same per-resource single-flight as local ones. - Apply the confirmed-release home projection when host observation reports a host-side release, and carry the host deadline in fleet snapshots. - Prove restart recovery with a file-backed database reopened by a fresh runtime. * test(orchestration): classify the keep RPC's worker fields instead of counting methods * fix(orchestration): checked delivery reads and observer and recovery help * refactor(orchestration): end a check when it hands over a batch; wake rides the wait result * fix(orchestration): refuse an automatic close after real input, join remote releases, converge the home - An automatic close checks the terminal's last driving-input time right before closing and keeps a worker someone typed into after worker_done; typing itself does no orchestration database work. - Remote releases share the per-resource single-flight with local release, so a home worker-release joins the host timer's close. - Host fleet snapshots and federationShow report released and the pending deadline; the home applies the existing release projection inside its observation fence. - Real restart tests: a file-backed database reopened by a fresh runtime releases a missed deadline once and finishes interrupted requests. * fix(orchestration): receipt a shared wake batch on arrival and report the applied Run ack * fix(orchestration): deliver the wake to a working coordinator; agents queue mid-turn input The wake was typed only into a live idle pane, so a Claude lead whose program status stayed working (teammate alive) never got it. Agents queue or steer text typed mid-turn, so a pane takes mail when live idle or working; dialogs, permission prompts, exited agents, unsettled panes and cold-parked Enter still hold it. Drops the held-batch Enter deferral and the per-turn-end hook logic. * fix(orchestration): record each remote release request before joining, publish archives only through the conditional commit - Each remote release caller records its own request before joining a close under way, and the close decides on the current row, so an explicit release that overlaps the host timer clears the automatic deadline. - Remote capture publishes its archive through commitWorkerTerminalArchiveForRelease, so a retain during capture leaves no stale archive for worker-read. - Remote worker-show projects the fenced host deadline and its next action. - The input guard lives in its own module instead of the scheduler. * feat(orchestration): start a worker in one step; worker-start creates the coordinator's Run when none is bound worker-start --spec now creates and binds a Run for a root coordinator with no bound Run, through the same path run-create uses, and names the Run it created or joined in every receipt. Workers on a Dispatch keep starting helpers in their own Run and never get a new one. A new CLI against an older runtime runs run-create and retries; old CLIs need no change. * fix(orchestration): drop the older-runtime fallback; check the spec before a Run is created The CLI fallback matched a refusal text the client decorates, could not prove the caller was a root coordinator on an older runtime, and recovered an inner run-create under the worker-start command. Older runtimes keep their refusal and the guide says to run-create first there. The prompt budget check now runs before worker-start can create a Run. * Route report-back requests to coordinators, complete the steer command, and label the wake loop branches * Say workers are done only when worker_done confirms, wait for helpers to settle, and let bare-shell workers exit * Route report-back requests away from handoff and steer supervised workers through their mailbox * docs(orchestration): teach auto-handled check, retry-request and inbox recovery in the guides * Describe the mid-turn wake in the messaging reference * docs(orchestration): say terminal workers are released 2 minutes after worker_done - The guide's Completion section, the reuse recipe and the recovery reference now describe the automatic release and its autoReleaseAt deadline: reuse or worker-retain before it; explicit worker-release still works and is required for chat workers and workers without a deadline. - The worker preamble says the terminal stays available until Orca releases it, about 2 minutes after worker_done unless retained. - Regenerated the bundled guides. * feat(orchestration): receipts say when to end the turn * feat(orchestration): tell the coordinator when a worker stops without worker_done * test+docs: worker stop reports * fix(orchestration): judge the empty-check stop with execution-host verdicts * test: drop casts from worker stop tests * Say that report-back requests still mean end the turn * Say that report-back requests still mean end the turn * fix(orchestration): stop reports wait for children, keep their Dispatch, and relay intact * fix(orchestration): a stop belongs to the Dispatch active when it was seen; restored stamps announce nothing * fix(orchestration): never say to stop while a remote worker runs * Shrink the orchestration guide to the end-state workflow * fix(orchestration): stop reports quote the agent's last words, or the screen for errors and prompts * fix(orchestration): withhold the stop while chat failure mail is off * test: a clean finish quotes the agent's last words * fix(orchestration): stop asking workers for heartbeats Workers are no longer told to send periodic heartbeats. A heartbeat that still arrives from an older worker or peer only records last_heartbeat_at: it is stored already handled, so it never lands in a coordinator inbox and never wakes a coordinator or a check --wait. Removes the stale-heartbeat warning and the heartbeat interval plumbing that only fed the preamble. * fix(settings): remove the worker heartbeat controls The Worker heartbeats switch and Heartbeat interval field only changed the worker preamble text, which no longer mentions heartbeats. Saved values are dropped on load as retired settings. * fix(orchestration): wake a coordinator that reports program status but never sets a title Program status only re-classified a pane that had a title, so a titleless agent (agy) never got a live status and the wake gate refused it. * fix(orchestration): a new Run no longer cuts a coordinator off from its earlier Run * test(orchestration): drop heartbeat-batch cases the handled heartbeat row removed * fix(orchestration): redact capabilities from a stop report's quoted output * fix(orchestration): never wake a mailbox for a heartbeat One rule at the runtime notification entry replaces per-call-site read checks, so mutation replay and federated control-mail import stay silent for heartbeats too. * Shrink the orchestration references and worker preamble to the end-state workflow * Name the older-Orca bind refusal as worker-start prints it * Owner-fence test: a refused foreign ack changes nothing, whatever the worker's own check already handled * Integration: drop the duplicate consumingCheck after merging #34043 and #35293 * Integration: await the worker-start next receipt before naming its Run * Apply review round 1: drain to zero, release without auto-release, retry after stop, Run before a DAG * Apply review round 2: start ready DAG Tasks, block when no failure wake, replay sends by request ID * Apply review round 3: one receipt-based wait rule for starts and wakes * fix(orchestration): a worker stopped without reporting needs action, and stop keeps its output worker-list projected a stop-reported attempt as live, in_progress, no action. It now projects finished_unverified with a worker-read recovery until mail reaches the worker. worker-stop closed the terminal before anything archived it, so release reported the archive unavailable; stop now archives the output first. * Revert "Owner-fence test: a refused foreign ack changes nothing, whatever the worker's own check already handled" This reverts commit |
||
|
|
dcaeaaa1fc |
feat(browser): typed snapshot flags, screenshots saved as files, and a guide that keeps browser work in Orca (#36257)
* feat(browser): typed snapshot flags and screenshots saved as files for agents orca snapshot takes --interactive, --compact, --depth, --selector, --urls, --delta and --full, passed to agent-browser on every route. The header now shows the page title and URL. orca screenshot and full-screenshot save the image where the CLI runs and print its path, in CSS pixels, with --if-changed and --annotate. Flag help for exec, wait and download is written for those commands, and the orca-cli guide sends web pages to Orca's browser unless the user picked another tool. * fix(browser): scale screenshots by the scrollbar-free axis and keep snapshot metadata behind SSH admission * fix(browser): upscale low-DPR screenshots and wrap a torn-down tab's screenshot error * fix(browser): give each screenshot its own file and keep typed screenshot errors * refactor(browser): share the agent-browser screenshot reader between Electron and orcad * refactor(browser): move snapshot and screenshot params under the line cap |
||
|
|
d6caa43719 | feat(telemetry): drop the plugin_uninstalled event; install counts are cumulative (#36214) | ||
|
|
ca2148a30d |
Settings: choose Chat or CLI in each agent's row; remove Chat → Providers (#36185)
* feat(settings): choose chat or CLI per agent in the Agents list Each agent's open-as-chat choice lived in two places: Settings > Chat > Providers and a Chat | CLI control under Default Agent. The choice now lives only in each chat agent's row of Settings > Agents > Installed, writing the same per-agent setting. Agents whose chat runs without their CLI (a downloaded chat runtime) are listed as installed with CLI unavailable, and the downloaded runtime and chat sign-in move into the agent's row. Search and the install card's hint point at Agents. Shown only while Chat UI is on, as before. * Preserve agent choices and setup across inventory changes * Fix settings regression test type conformity |
||
|
|
0426223be5 |
feat(telemetry): count plugin installs from Orca's public catalogs (#36132)
* feat(telemetry): report plugin installs and removals from Orca's public catalogs * refactor(plugins): move marketplace install origin out of the installer |
||
|
|
030c88deec |
feat(computer): return tree diffs after actions and add get-app-state --query (#36023)
* feat(computer): send tree diffs after actions and add get-app-state --query Action results now carry only the accessibility-tree lines that changed since the caller's last view of the same window (~ changed, + added, - removed as index ranges, or an explicit no-change line), plus the focused element. The runtime sidecar keeps the last tree per session/worktree and app, so all three providers get it. The CLI opts in with treeDiff; older runtimes strip the param and keep returning the full tree, and --full-tree opts out. The macOS helper now keeps an element's index across snapshots of a window: AX identity first, then the next unclaimed index with the same signature for views that rebuild their AX objects, and never reuses a removed index. get-app-state --query prints matching elements with their ancestors and --max-elements caps the output, both in the CLI over the rendered tree. Custom action names with raw newlines no longer split an element over lines. * fix(computer): preserve parent changes in snapshot diffs * fix(computer): refuse stale index reuse for lookalike controls * fix(computer): print full trees in action replies * fix(computer): keep controls located in snapshot replies |