Surgical derivative of Orca. Same product surface. Residual orchestration and safety contracts closed.
Arriving cold: Orca is an application for running agent CLIs — Claude, Codex, Cursor, Grok and 32 others — across terminals, git worktrees and SSH hosts, and Odin keeps all of it. What Odin changes is the handful of places where Orca answered a question it had not actually observed, or acted on the operator's machine without being asked. Three of them, concretely, each a row in the table below:
- A worker nobody had seen die was reported as a clean exit. When the terminal host could not look up an exiting session it stamped
code: session.exitCode ?? 0and the consumer publishedverdict: 'exited'regardless of the code — the shared module beside it (terminal-exit-cause.ts:36-45) forbids exactly that — and the renderer fired a completion notification on the result (residual A). - Silence was read as "ready". A worker that simply went quiet satisfied
tui-idle's tier-3 "sustained title idle", which that module's own header calls "ABSENCE, a last resort", and the wait returned the sametrueas real on-screen evidence — so a silent worker was declared ready and an automation run declared completed (residual C, #6011). - Hooks, credentials and permission-bypass flags were applied without a recorded grant. On boot Orca wrote agent-status hooks into 14 other tools' user-global configs behind a fail-open check, copied
~/.codex/auth.jsoninto an Orca-owned runtime home on every launch and account switch with no setting or prompt, and shipped permission-bypass flags as the default launch argv for 26 agents (residuals E, G, H).
The rule for every change is the same one: the test that proves it fails at upstream 539d4d1f32 and passes on Odin, and odin/proof/run-proofs.sh reruns that check for every residual in one command. Nothing on this page is asserted that the script or an artifact under odin/proofs/ does not back.
Odin is Orca (upstream stablyai/orca at 539d4d1f32, v1.4.197, MIT © Lovecast Inc.) with a small set of patches at the exact sites where Orca still synthesised a verdict from an absence of evidence, or acted on the operator's machine without a recorded grant. Nothing in Odin's runtime behaviour changed beyond those patches: terminals, worktrees, SSH, mobile, the 36 supported agent CLIs and the UI behave exactly like Orca's. Every patch is proven the same way: its test fails at the upstream commit and passes here. Repository maintenance outside runtime code — CI hygiene, the public docs site, dependency-alert bumps — is listed, not hidden, in "Outside the contract" below.
odin/proof/run-proofs.sh # reruns every upstream-reproduced proof test at the upstream commit (must fail) and on Odin (must pass); closed-by-construction entries are exercised on Odin only
odin/proof/real-sessions.mjs # drives real claude / codex / grok workers through Orca's own orchestration on a headless host
odin/proof/ssh-boundary.mjs # drives a real desktop-mode host against a real SSH VPS through target registration and ssh.connect
git log --first-parent odin # one commit per residual, message = residual (file:line) → contract → proof files
| # | Orca residual failure (upstream citation) | Odin contract | Proof |
|---|---|---|---|
| A | Retired-incarnation tombstone minted a clean exit: code: session.exitCode ?? 0 (src/main/daemon/terminal-host.ts:132) although src/shared/terminal-exit-cause.ts:36-45 forbids exactly that; the consumer (terminal-host-process-inspection.ts:43-63) published verdict:'exited' regardless of the code, and the renderer fired a completion notification on it. Relay twin: src/relay/pty-handler.ts:2412 hard-coded code: 0 even for record-torn-down. |
The exiting session is captured, not re-looked-up; an absent status is UNVERIFIED_PROCESS_EXIT_CODE; the inspector publishes exited only when isProvenProcessExit(code), else unverifiable. The relay applies the same gate (closed by construction: its test pins the extracted mapping, because the record-torn-down race has no deterministic relay harness). |
terminal-host-process-inspection.test.ts |
| B | Worker liveness read an empty or non-enumerating host answer as death (src/main/runtime/orchestration/worker-terminal-process-liveness.ts:8-31); the local provider lists only in-process PTYs and a restarted relay omits every prior id, so worker-release settled retained resources whose process was alive (#3191). |
Only a host that enumerated this PTY under a different incarnation may report its death. Empty or unmatched listings are unverifiable. |
worker-terminal-process-liveness.test.ts |
| C | tui-idle waits settled on silence: tier-3 "sustained title idle" returned the same true as positive evidence (src/main/runtime/tui-idle-evidence.ts:127-138; the module's own header calls it "ABSENCE, a last resort"; #6011, roadmap #15190). A silent worker was declared ready and an automation run declared completed. |
Three-valued verdict observed-idle / silence / not-idle; the wire result carries evidence and satisfied is never true on silence; worker start and the automation observer treat silence as not-ready / not-completed; the CLI prints the evidence. Exit waits never settle on a disconnected PTY without a proven exit code. Two deliberate exceptions remain and are named in the module header as an explicit six-agent allowlist (NAME_ONLY_IDLE_AGENTS), not "has no synthetic-title profile": an explicit idle marker or ready prompt the agent itself paints is positive evidence, and only agents whose only rest signal is their name (grok, copilot, aider, mimo, agy, opencode) settle after the quiescence window rather than never. Every other agent — Claude, Gemini, every other agent with no synthetic-title profile, and any pane whose agent cannot be resolved at all — is held to silence until it corroborates rest itself; a profile-lookup shape that silently widened the carve-out to that whole set was closed (round-4 review finding O1). |
terminal-wait-name-only-idle.test.ts |
| S | Renderer adjudicated agent status by comparing two machines' wall clocks with no ownership requirement (src/renderer/src/runtime/web-session-tabs-sync/agent-status-patch.ts:118); a host blocked row lost to a stale client row with a later clock. The main-process copies were already closed upstream (docs/reference/agent-status-store.md, PR 1a/1b). |
A host row is replaced only by a proven, fresh, client-owned row that the host does not pierce; cross-machine updatedAt no longer decides. The renderer is still a second writer for remote-runtime and structured panes, and a stateStartedAt comparison still guards provider-session retention; both are written down in odin/OPEN.md. |
web-session-tabs-sync-host-authority.test.ts |
| D | The runtime WebSocket listener widened to 0.0.0.0 on every start once any device had ever paired (src/main/runtime/runtime-rpc/runtime-rpc-lifecycle.ts:146-158); nothing ever narrowed it back (#9963). |
Loopback unless a persisted networkExposureConsent record is true, read at every bind; pairing refuses to widen without it; flipping it off rebinds the live listener to loopback. orca serve and orcad --bind remain explicit opt-ins. |
runtime-rpc-websocket-bind-host.test.ts |
| E | Hooks were written into 14 other tools' user-global configs on boot; agentStatusHooksEnabled defaulted to true and the check was !== false, so an unset or unreadable setting installed (src/shared/default-global-settings.ts:211, managed-agent-hook-controls.ts:40-52; #9963). |
Default false; the gate is === true; an absent, null or unreadable setting installs nothing. |
managed-agent-hook-controls.test.ts |
| F | New installs were opted in to telemetry without ever seeing the banner (loaded-cohort-migrations.ts:52-57 wrote optedIn: true; the first-launch surface only renders for pre-existing installs). |
Fresh installs are opted out. | persistence-cohort-and-identity-migration.test.ts |
| G | ~/.codex/auth.json was copied into an Orca-owned runtime home from the service constructor, on every launch and account switch, with no setting or prompt (runtime-home-service-auth-sync.ts:9-84, runtime-home-service-sync.ts:95). |
codexCredentialMirrorConsent (default false) gates the copy primitive itself, so the constructor, account-switch and system-default-changed paths cannot copy without it; unreadable settings deny; any apply with consent false clears the runtime copy and snapshot. Logout bookkeeping stays ungated. |
runtime-home-system-default-mirror-readback.test.ts |
| G3 | Follow-up: the no-consent branch of restoreSystemDefaultSnapshot still read and persisted the credential into system-default-runtime-logout.json via a default argument, and revocation deleted the shared runtime auth.json / provenance file even when a retained managed pane owned them. |
The no-consent branch now passes the logout marker null explicitly (no read, no write); clearMirroredCodexCredentials() skips both deletions when provenance is owner: 'managed' and always deletes the logout marker copy. |
runtime-home-restore-consent-gate.test.ts, codex-credential-mirror-consent-revocation.test.ts |
| H | Permission bypass was the shipped default for 26 agents: DEFAULT_TUI_AGENT_ARGS = YOLO_TUI_AGENT_ARGS (src/shared/tui-agent-launch-defaults.ts:10), spread into default settings and force-migrated into profiles that never chose it (terminal-settings-migrations.ts:149-179; #9963). |
Shipped defaults carry no bypass flag; the migration hydrates keys with empty values; bypass exists only as the payload of the user's own per-agent setting or permission-mode switch. | constants.test.ts, terminal-settings-migrations.test.ts |
| I | The worker launch receipt's effective was a structural copy of requested (worker-launch-preferences.ts:23-33); model and effort were validated against a table compiled into the binary, never against the installed CLI (#10846, open). |
For Claude, effective comes from the installed CLI's own list_models answer (source: 'probe') for both model and effort. For Codex, effective's model also comes from the installed CLI's own codex debug models answer (source: 'probe'); effort stays validated against the static catalog only (effortSource: 'catalog') because that CLI's reported reasoning levels never include minimal, which the catalog offers as every model's floor — checking effort against the probe would reject a catalog-valid selection. Cursor's model now comes from the same shared discovery executor's cursor-agent --list-models answer (source: 'probe') — reused, not reimplemented, from the probe already backing commit-message generation (commit-message-agent-specs-secondary.ts); its effort also stays catalog-validated, because that probe's thinkingLevels heuristic doesn't cover every model CURSOR_SESSION_OPTION_CATALOG gives a real effort option (I3). Grok has no live probe at this receipt: GROK_SESSION_OPTION_CATALOG has no supportsWorkerLaunchPreferences, so a grok --model/--effort worker-start is rejected before any receipt is built; its model-list probe is wired and tested at the discovery layer only (grok-model-list-probe.ts), ready for the day grok's catalog opts in. A refusal carries the CLI's reason; a probe that cannot run yields effective: null, source: 'unverified' with the reason; a federated worker whose host never answered gets effective: null, never a copy; a remote or command-overridden placement skips the local probe and is unverified. source: 'probe' requires the discovery answer's own catalogOrigin to be 'probe' — a CLI that exits 0 with no parseable model list falls back to the static catalog (catalogOrigin: 'spec') and is honestly labelled 'catalog', never 'probe' (I4). A probe failure is never memoised past its own call, so a transient miss re-probes on the next worker-start instead of pinning every later launch for that agent to unverified (I4). Membership in the CLI's model list proves advertised support, not what the launched session applied. |
worker-launch-preferences.test.ts |
| K | In-process sub-agents were flattened into fake dispatches: the sidebar fabricated orchestration: { taskId: 'subagent:<id>', dispatchId: 'subagent:<id>' } for rows that have no Task or Dispatch anywhere (worktree-subagent-child-rows.ts:55-60; #8251). |
Sub-agent rows carry their own subagent: { id, parentPaneKey } identity and never masquerade as a dispatch. |
worktree-subagent-child-rows.test.ts |
| M | Dispatches created by orchestration dispatch --inject had no worker row and were invisible to crash recovery (worker-terminal-recovery.ts:13-27 inner-joins worker_dispatches), so after a restart they stayed live with a valid capability forever. |
Every active dispatch is reconciled on every host start (wired into the one recovery method orca serve, orcad and the desktop share): left alone when its terminal is live or the host cannot be asked, failed with termination_reason: 'unknown' and its capability revoked only when the owner says the terminal is gone. |
orca-runtime-reconcile-legacy-worker-terminals-unsupervised-dispatch.test.ts |
| N | dispatch_contexts.dispatched_at was stamped at row creation (a dead duplicate of created_at), the observed exit code was dropped before failDispatch (orca-runtime-subscribe-to-terminal-resize.ts:87-90), and nothing exposed per-attempt wallclock. |
dispatched_at is written on the pending→dispatched edge, exit_code is a column (schema v42), and worker-show --json reports dispatchedAt, completedAt, wallclockMs, exitCode, terminationReason. Follow-up (N2): the schema-skew probe now also registers the v42 exit_code column, so a database already stamped v42 without it is detected and repaired instead of being read as complete. |
worker-dispatch-accounting.test.ts, orchestration-version-skew-migration.test.ts |
| O4 | The execution host's federation observer inspectRemoteAttachment collapsed every showTerminal rejection to missing (federation-attachment-observation.ts:39-42: .catch(() => null) then status: 'missing'), so a transport timeout, a stale local handle or an unclassified throw read as the owner certifying the terminal gone — the word orchestration.federationShow ships to the Run home and that the recovery release path acts on. The local observer's O1/O2 gate never covered this twin (raised by Pullfrog on #20682). |
One shared gate, isOwnerProvenTerminalAbsence (shared/terminal-process-inspection.ts), used by both observers: a resolved null or the owner's own terminal_gone is missing; every other failure is unverifiable with the classifier's reason. releaseRemoteAttachment in recovery mode keeps an unverifiable-with-no-terminal release release_pending (retry after the next inventory) instead of reverting it to retained. Nothing downstream ever settled exited on the old word; the claim itself was the defect. |
federation-attachment-observation.test.ts, federated-worker-release-host-unverifiable-recovery.test.ts |
| show-contact-loss | Remote-runtime terminal show's connected/writable came straight from pty.connected (orca-runtime-build-pty-terminal-summary.ts:34-35, orca-runtime-write-orchestration-pointer-pty.ts:179-180), never checked against the owning SSH target's transport — neither path reads the relay-lost/reconnect state at all. Reproduced against a real VPS: after an iptables-dropped transport, [ssh] Relay channel ... lost; reconnect attempt 1/6 and Keepalive timeout fired while terminal show kept answering connected: true, writable: true with no exitCause for all 17 samples over 90s (odin/proofs/ssh-boundary.2026-09-15T01-39-52-596Z.json phase4). |
While the owning SSH target's registered connection status (getRegisteredSshState) is not connected, connected/writable are forced false and the record carries liveness: { status: 'unverifiable', reason: 'reconnecting' | 'transport_lost' } — never exitCause, never exited; a genuine owner-proven exit (pty.lastExitCause already set) is never overridden. Reuses the existing SSH connection-state registry rather than a second liveness tracker. |
show-contact-loss.test.ts |
Verified, not re-implemented (see odin/VERIFIED.md): nesting-depth enforcement (#16668), durable mutation receipts, capability fencing and journal recovery (#16904, fixes #15180), and the headless recovery sweep that already runs on orca serve and orcad. Odin pins these with tests so they cannot regress silently.
Left open, with the exact plan and cost written down in odin/OPEN.md: the renderer is still a second writer of agent status for remote-runtime panes whose bytes never transit the host.
odin/proof/real-sessions.mjs drives real agent CLIs through Orca's own orchestration worker-start on a headless serve host with an isolated profile. Recorded runs (macOS, this checkout; files under odin/proofs/):
| Phase | Claude | Codex | Grok | Artifact |
|---|---|---|---|---|
Safe default: a fresh profile launches every worker with no bypass flag in its argv (ps captured live command lines, truncated at 200 characters in the cited artifact) |
no bypass; completes because this operator's own Claude config auto-approves | no bypass; stays dispatched, never settles |
no bypass; the worker fails to start | real-sessions.2026-09-14T14-29-05-741Z.json |
Settle: with the operator's per-agent grant recorded in the profile, the worker reports worker_done and the dispatch row settles completed with dispatchedAt, completedAt, wallclockMs |
8.7 s | 4.6 s | not included in the cited artifact | real-sessions.2026-09-14T15-08-32-250Z.json |
| Concurrent: two workers started in parallel both settle | 8.6 s | 5.3 s | — | same file |
Crash: the host is SIGKILLed after worker-start has returned (the send is delivered, the receipt completed, the task unsettled) and restarted on the same profile; replaying the same --retry-request returns the identical dispatch (one row, no second worker); the worker is still dispatched, never falsely exited or completed. The other honest answer, operation_unknown for a receipt still pending at the crash, is pinned by upstream's own unit tests (odin/VERIFIED.md), not by this driver |
pass | pass | failed to start before the crash; the dispatch-count check passes | real-sessions.2026-09-14T14-49-45-377Z.json |
Two things these runs show that a unit test cannot. First, the H1 contract acting on a real profile: the same artifact that shows a settled Claude/Codex run also shows a Codex worker parked on its approval prompt when the profile's grants were written without agentBypassDefaultsReviewed (real-sessions.2026-09-14T15-05-30-764Z.json, kept as evidence). Second, the operator's own agent configuration is outside Odin's contract: the Claude worker completes even in the safe-default phase because this operator's Claude config auto-approves; the argv still carries no flag from Odin.
Linux: every manifest proof (28 residuals and the 4 closed-by-construction entries, at code sha 8a33acda11; artifact odin/proofs/linux-proofs.8a33acda11.txt) reproduces at upstream and closes on Odin inside a node:24-bookworm container, and the twelve process-ownership test files that read a real ps and /proc (PTY process groups, foreground-process batches and fingerprints, process-table snapshots, daemon session reaping, tombstone inspection, worker liveness) pass there. The run is re-derivable: odin/proof/run-proofs-linux.sh clones the committed HEAD into the container and writes odin/proofs/linux-proofs.<sha>.txt (latest: linux-proofs.<<FINAL-SHA>>.txt; the run at 8b0df499bb, when the manifest held 14 residuals, is linux-proofs.8b0df499bb.txt, and the earlier ad-hoc run at 37a8b5489f is linux-proofs.txt). Not covered: Windows hosts, a third agent settling (Grok quota), and Orca's mobile app paired against an Odin host.
| Phase | Result | Artifact |
|---|---|---|
SSH host (odin/proof/ssh-boundary.mjs against a real VPS, claw-vps): a real desktop-mode host boots, seeds an SSH target + repo on disk (the only registration path — there is no CLI/RPC verb for it), and orca host list surfaces it through the real RPC |
pass | ssh-boundary.2026-09-14T21-46-07-872Z.json |
SSH connect: ssh.connect authenticates against the real VPS and drives a real relay deploy end to end — SFTP upload, npm install + native node-pty compile under the VPS's own constrained memory, relay launch, a real accepted client connection, handshake reaching connected — after fixing two real bugs this run found in product code (the upload's path-containment guard now accepts a symlinked project root, src/main/ssh/sftp-upload.ts; a headless/background launch no longer hangs on the macOS Keychain call, src/main/host/electron-secret-store.ts) and working around a third in the driver (dev-mode launches still cannot resolve their own bundled relay path without ORCA_RELAY_PATH) |
pass | same file; full narrative in odin/proofs/ssh-boundary.md |
SSH loss-of-contact matrix (worktree + terminal on the SSH host, transport-drop and relay-SIGKILL variants, reconnect, owner-proven exit), strengthened driver: ok requires the client to actually observe the loss, no sample to ever claim an exit, and terminal wait --for exit to resolve during the outage |
pass at f707829826: transport drop observed on the fifth 5 s sample (terminal show → connected:false, liveness:{status:'unverifiable', reason:'reconnecting'}, no exitCause), terminal wait --for exit resolved {satisfied:false, evidence:'silence'} during both the drop and the relay kill, reconnect re-adopted the same PTY, a real SIGKILL to the shell yielded status:'exited' (out-of-band ps confirmed death; the wire still reports exitCode:0 with cause_unreported, see the narrative), relay relaunched after its kill. The first strengthened run at 8b0df499bb failed this row and exposed show-contact-loss (ssh-boundary.2026-09-15T01-39-52-596Z.json) |
ssh-boundary.2026-09-15T02-28-13-014Z.json |
odin/proofs/ssh-boundary.md has the full diagnosis, including the disk-durable logging technique that pinpointed a hang inside a synchronous OS call that no JS-level timeout could catch (because the event loop itself was frozen), and what narrower items remain open (terminal wait --for exit's immediate-silence verdict, proven only by unit tests, not by this run).
Two independent reviewers were given the same brief (odin/REVIEW_BRIEF.md): review this repository against odin/DIRECTION.md and odin/AGENTS.md, do not rubber-stamp. Four rounds have run. Round one: Codex (codex exec, read-only) returned NOT FINISHED with concrete file:line findings; a Claude review covered the consent and durability sections before its session was rate-limited. Round two, on the fixed tree: Codex again returned NOT FINISHED (its remaining findings are the credential write primitive, the handle-stale classification, the veto ordering, and the contract-level items listed under Deviations); Claude returned FINISHED WITH MATERIAL DEVIATIONS and independently reran all 13 proofs (13/13 reproduce and close), finding one contradiction between two checked-in tests and one unlisted renderer writer. Every material finding from both rounds became a odin(fix-…) commit with its own failing-first proof:
- injected-dispatch recovery had no production caller (wired into the shared recovery method, runtime-level proof);
- the wallclock reader mis-parsed SQLite timestamps outside UTC (34,201,000 ms for a one-second interval in Adelaide; both ends normalised);
- two credential-copy paths bypassed the consent gate (gate moved into the copy primitive);
- two hook checks were still fail-open (
=== trueeverywhere); - exit waits settled on a disconnected PTY and mapped the unverified exit code to
exited; tui-idle results accepted missing evidence; the boolean adapter said satisfied on silence (all removed); - worker observation minted
exitedfrom absence and read every inspection failure as "missing" (now only the owner's not-found answer counts); - widen/narrow of the network listener could race (serialised, consent re-read after a widen);
- profiles that inherited Orca's automatic bypass values kept them (one-shot review migration clears values equal to the YOLO table; a user who chose the same value re-enables it once);
- launch receipts still copied
requestedintoeffectivein two paths (nownullwhen unknown); - sub-agent rows defaulted to done when nothing was observed (now unverifiable);
- the proof runner accepted any nonzero exit as a reproduction (now requires the named assertion at the upstream commit);
- round two: the credential copy could still be reached through retained-pane synchronisation and revocation left the credential in the provenance file (gate moved into
writeRuntimeAuth, provenance deleted on revocation);terminal_handle_stalewas read as owner-proven absence although it describes the client handle graph (only the PTY host'sterminal_goneor a resolved null counts now; the injected-sweep error is returned, not dropped); a retained idle title or ready prompt outranked a fresh first-party working status (the veto is consulted first); two tests written by the original H commit contradicted the H1 review migration (reconciled to the chosen contract);odin/OPEN.mdomitted the command-code title writer (now enumerated).
Round three (brief scope items 13–18, on the tree after v0.1.0: the renderer-writer increments, the SSH boundary run, exit waits on timeout, the Linux proofs, the upstream PRs, and the CI/dependency changes). Both reviewers returned FINISHED WITH MATERIAL DEVIATIONS. Every item became a commit with its own proof; the full list is odin/REVIEW_BRIEF.md item 19, and the commits are:
- operator maintenance that closes no residual was undisclosed — the "Outside the contract" section,
odin/outside-contract.jsonand a drift ratchet that fails on any future change outsideodin/,src/,docs/reference/or the README (d2bdf4e459); the README also stopped claiming "nothing else changed" of a diff that includes a docs-site migration (825c87ae3e); odin/OPEN.md's renderer-writer enumeration was incomplete — everysetAgentStatus(call site is now classified and thetitle-spawn-bell.tslaunch seeds are named (4d7902a545);- a failed status-ownership probe could fail the launch (
3c5b4c2d55, with atc:webfollow-up ined06c27f0b), and the remote-runtime ownership verdict was never re-evaluated after the probe resolved, in either direction (4660dbc895); - the command-code done-settle window existed in two copies — one shared module plus a ratchet (
e7d2138916); - the
safeStoragewindowless guard threw before install and was not platform-scoped — darwin-only, one warning,getSecretStoreOrUnavailable, with the degradation written into deviation 11 anddocs/reference/(f59cb1052b); - an exit wait still rejected on absence instead of resolving the silence verdict (
b705a96191); - the command-code reader-side precedence rule was undisclosed — now deviation 12 (
41366355d7); - four things the tree did not admit to: no cost/token accounting anywhere in the orchestration tree, two adjacent local liveness vocabularies,
terminal_gonecarrying two evidentiary strengths, the survivingstateStartedAtclock comparison, and an M proof file name that did not match the test (bb0101a461, deviations 9–10 and thedocs/reference/ssh-execution-boundary.mdparagraph); - the proof runner mis-parsed
--onlyand wrote per-run debug logs into the tracked proofs tree (42172f4c56); two.after.txtnotes claimed atc:webbaseline that was not true (38907abb67); - the SSH driver's phases 4/6/7 could pass without the client ever observing the loss (
26f11fe34c), and the Linux run had no checked-in runner (1bdcbcce23).
Fixing those surfaced six further residuals, each with its own manifest entry and failing-first proof: I3 (Cursor's launch receipt was never checked against the installed CLI, 61dbafb53c), I4 (a static-catalog fallback was labelled source: 'probe', and probe failures were memoised for the process lifetime, 8b7a7affe7), O3a/O3b (a structured worker's own host-owned unverifiable treated as absent on release; terminal_gone overloaded across four unrelated failures, 382bf626a9), N2 (the schema-skew probe never registered v42's exit_code column, 321f902830), G3 (the credential mirror's no-consent branch still read and persisted the credential; revocation deleted a retained pane's own file, cbd2f06bd8), and show-contact-loss — found against a real VPS, not by inspection, when the strengthened SSH driver ran and terminal show kept answering connected: true through a 90-second transport drop (f707829826).
Round four (brief scope items 19–22: the round-three closures, the residuals found since, the evidence on the tree under review, and the amended upstream PRs). Pullfrog's review of #20682 raised one further residual during this round — the execution host's federation observer minted missing from a thrown showTerminal failure, the twin the local observer's gate never covered — closed by one shared isOwnerProvenTerminalAbsence gate for both observers (54a2be6382, residual O4). Verdict: FINISHED WITH MATERIAL DEVIATIONS.
Findings the reviews raised that are deliberately not changed, with the reason: the liveness projection keeps unattached, missing and identity_changed as wire values beside live / unverifiable / exited because existing tests pin them as distinct client-facing states; orca serve and orcad --bind bind wide by explicit operator command; positive on-screen evidence (an explicit idle marker or ready prompt the agent paints) remains tier-1 evidence.
Orca's full unit suite was run on the merged tree (8,751 files, 81,585 tests) and then every failing file was rerun both here and at the upstream commit. Twenty-nine files were in the failing set: twenty-one failed only on Odin in the first run, of which eighteen were genuine contract pins and are now fixed, and three were build-state or concurrency flakes that pass on re-run; eight fail identically at upstream and are environment-bound (real signed-in Claude CLI, real bash/PTY quirks, network, a release-checkout download, a missing optional package, a stale upstream keepalive test). The final re-run after the fixes reports twenty-one passing, one skipped (no out/cli build), and seven failing — all seven class (c), identical at upstream. The classification with evidence is odin/proofs/full-suite-triage.md. Typecheck is clean on node, cli and web.
Stated plainly, because two independent reviews returned NOT FINISHED against odin/DIRECTION.md's definition of done and these are the items that remain open by decision rather than by oversight:
- Status is not yet single-writer end to end. The main-process store is; the renderer still writes rows for remote-runtime and structured panes whose bytes never transit the host, and it still merges client identity fields into host rows. Closing it needs host-side OSC ingest plus a wire capability gate (
odin/OPEN.md). The renderer is also still the only writer of a pane's very firstworkingrow, seeded from its own launch config before any host observation exists (title-spawn-bell.ts'sapplyInitialAgentStatus,command-code-prompt-status-seed.ts,launch-agent-background-session.ts) — a launch-time seed for local panes exactly as much as remote ones, not one of the four call sites the closing plan covers.odin/OPEN.md's full writer enumeration lists everysetAgentStatus(site with its classification. Odin removed the cross-machine wall-clock adjudication and nothing more. - Settlement keeps two positive-evidence exceptions. An explicit idle marker or ready prompt the agent itself paints counts as observation (a fresh first-party working status now vetoes it), and agents whose only rest signal is their name (grok, copilot, aider, mimo, agy, opencode) settle after the quiescence window. Removing the second would make
tui-idleunusable for those agents (#6011); it is a named trade-off, not the pure "silence is unverifiable" rule. - The wait result is
satisfiedplusevidence, not the literalaccepted | refused | unverifiabletype. The three outcomes are representable and every silence path maps to not-satisfied, but the wire shape is Orca's, kept for compatibility. - Worker observation keeps
unattached,missingandidentity_changedbesidelive / unverifiable / exitedbecause clients depend on them as distinct states. - The launch receipt verifies advertised support, not applied options.
source: 'probe'means the installed CLI listed the model (Claude: and the effort too) and the discovery answer's owncatalogOriginsays the listing came from that live probe, not a static-catalog fallback the executor returns with the samesuccess: trueshape when the CLI exits cleanly but reports no parseable models (I4) — a distinction the receipt used to collapse into a bareresult.successcheck. The probe promise memoised for a worker-launch agent is also evicted on any failed outcome, not just kept for the process lifetime unconditionally, so one transient miss no longer pins every later worker-start for that agent tounverified(I4). For Codex and Cursor, effort is validated against the static catalog, not the probe (effortSource: 'catalog') — Codex'sdebug modelsreports per-model reasoning levels but never listsminimal, which the catalog treats as universal; Cursor's probe derivesthinkingLevelsfrom an id-pattern heuristic that doesn't cover every model the catalog gives a realeffortoption (I3) — trusting the probe in either case would reject a valid selection. Cursor's model is fully probe-verified (source: 'probe'), reusing the samecursor-agent --list-modelsexecutor commit-message generation already uses — no parallel probe was written. Grok has no live probe at this receipt at all: its catalog does not opt into worker launch preferences, so a grok--model/--effortworker-start is rejected before any receipt exists; its model-list probe is wired only at the discovery layer, unreachable from here until that catalog gate opens. Nothing reads back what the launched session actually applied, for any agent. - Sub-agent rows carry their own identity but are still renderer-derived and their synthesized entry state falls back to
donewhere the status type has nounverifiablemember. - Proof coverage is macOS plus a Linux container. Windows process ownership, mixed-version clients, mobile pairing against an Odin host, and a third agent settling (this operator's Grok quota) are not established by the recorded runs. SSH-hosted worktrees are now covered end to end:
odin/proof/ssh-boundary.mjsruns a real desktop-mode host against a real VPS and proves target/repo registration, a realssh.connectrelay deploy reachingconnected, worktree/terminal creation on the SSH host, and the loss-of-contact matrix (transport drop, relaySIGKILL, reconnect, owner-proven exit) — the actual subject ofdocs/reference/ssh-execution-boundary.md. Two real bugs were fixed in product code: the symlinked-worktree upload-root false rejection (src/main/ssh/sftp-upload.ts) and the headless/background launch (ORCA_BACKGROUND_LAUNCH=1, mandatory for every agent-driven proof) hanging forever inside a synchronous macOS Keychain call a windowless process can never get answered (src/main/host/electron-secret-store.ts). A third gap, the dev-mode relay-path resolution, is still worked around in the driver withORCA_RELAY_PATHand remains open because it cannot be reproduced without a live SSH host. Still open:terminal wait --for exit's immediate-silence verdict on real transport loss is proven only by unit tests, not by this run — seeodin/proofs/ssh-boundary.md. - Retained telemetry opt-ins from Orca's automatic enrollment are preserved for pre-existing profiles; only fresh installs are opted out.
- DIRECTION.md's build-order item 5, "cost/resource accounting on the graph," is half delivered. Resource accounting is real: N's
dispatched_at/exit_code/wallclockMsonworker-show --json. Cost/token accounting does not exist anywhere in the orchestration tree — no wired path records what a dispatch spent. Nothing in this repository claims otherwise, but the build-order item itself is not fully met. - Several adjacent liveness-shaped vocabularies exist beside the fixed
live/unverifiable/exitedone, for different local-only questions the SSH boundary contract does not cover. The two disclosed here aredaemon-audit-classifier.ts'spresent/gone/unknown(is the local terminal daemon process itself running) andorca-runtime-get-worktree-ps.ts'slive/dead/unknown(recovering a structured-agent-session TUI owner's local PID after a restart). A round-4 review found at least five more upstream-inherited vocabularies answering other local-only questions (host-live-terminal-probe.ts,workspace-terminal-host-authority.ts,agent-status-capacity-eviction.ts,claude-stream-json-connection.ts,runtime-legacy-worker-terminal-recovery-candidate.ts,pty-listed-session.ts; see~/Dev/odin/odin-work/reviews/round4-opus.md:136-142). None is a synonym for the fixed vocabulary in the sense DIRECTION.md item 4 forbids — none observes a worker's PTY through the relay/SSH boundary — but a reader tracing "what counts as liveness in this codebase" needs the breadth named.docs/reference/ssh-execution-boundary.mdstates the scope explicitly, and names a related finding: the client-facing error stringterminal_goneused to be thrown with multiple evidentiary strengths (a real relay-side tombstone claim vs. local process-registry misses) that no code currently conflates, but that are easy to conflate by inspection alone — see that document's "Distinguishingunverifiablefromexited" section. - The
safeStoragewindowless-launch guard is reached only by launches that setORCA_BACKGROUND_LAUNCHor run E2E-headless — proof drivers, tests, and benchmarks; no production or user-facing launch path sets either. Under that flag, and scoped to macOS (the only platform with a Keychain prompt that can hang with no window to answer it),ElectronSecretStorereports encryption unavailable instead of touchingsafeStorage. That degrades four callers differently, not uniformly: protected settings (opencodeSessionCookie,httpProxyUrl,browserKagiSessionLink) and the SSH PTY owner lease are not persisted; the MiniMax API key/cookie are written in plaintext with a console warning; plugin secrets refuse to read or write; a saved cloud session reads back asdecrypt-failed. The real-world hidden-launch variant of the same hang — Orca started by a login item with a window created but never shown, and no env flag set — is not proven fixed. - A reader-side precedence rule exists for command-code status.
dropsCommandCodeAgentStatus(agent-status-command-code-ownership-filter.ts) drops a host-published command-code row when renderer-local state (foreground process, retained agent, launch config) disagrees about which agent currently owns the pane. Main cannot decide this itself — foreground/retained-agent ownership is renderer-only state it never sees — so the filter stays client-side (odin/OPEN.md). DIRECTION.md item 2's "no reader-side precedence" is not met here; removing it needs main to track pane-level agent ownership itself, which is out of scope for this increment.
Everything above is either in odin/OPEN.md with a plan, or accepted for v1.0.0 as Orca's existing behaviour.
The clusters below touch this repository but close no residual and are not proven by any file
under odin/proof/manifest.json. Each is operator-directed maintenance on the public repo or its
docs site, not contract work; the full file list and upstream 539d4d1f32b4 diff, grouped the same
way, is odin/outside-contract.json, and odin/outside-contract-scope.test.ts fails if a future
change lands outside odin/, src/, docs/reference/, or this file without being added there.
| Cluster | Purpose | Commit range |
|---|---|---|
.claude/agents/github-steward.md |
A repo-maintenance subagent brief for the operator's own triage/CI/security/release workflow. Never merges anything itself. | bd256c7b6f |
| Dependabot + workflow permissions | Dependabot coverage for the four pnpm roots; least-privilege permissions: contents: read on the workflows a security scan flagged. |
9e022c023d..643e28ff98 |
| Docs-site Vercel→Pages migration | stablyai/orca's Vercel project isn't available to this fork; static-export the docs site to GitHub Pages (new export config, static search/OG routes, CNAME/.nojekyll, Odin branding in the shared layout/header/footer). |
6c7b4c5b6e..911f713c8b |
| Docs-site content | Odin branding of existing pages plus a new odin/ section on the public docs site mirroring this README's residual table, real-session runs, and review verdict. |
6c7b4c5b6e..495f5ff97c |
cloud/ and mobile/ dependency bumps |
Lockfile/workspace-override bumps resolving Dependabot alerts inherited from upstream's own lockfiles; no source file in either tree changed. | b3a1a0bc7b |
None of this closes a residual, and none of it is cited by VERIFIED.md, OPEN.md, or the table above. odin/DIRECTION.md:13-17 was added in d2bdf4e459 (the same commit that introduced this section and the drift ratchet) to make the governing scope rule admit this declared operator-maintenance cluster.
Every contract above is offered back to Orca as a single-commit pull request with its failing-first test, rebased onto upstream main and stripped of Odin-only artefacts. Open as of 2026-09-15:
| Residual | Pull request |
|---|---|
| A, A-relay | stablyai/orca#20666 |
| B | stablyai/orca#20679 |
| C (exit-wait subset) | stablyai/orca#20681 |
| O1, O2, O3a, O3b, O4 | stablyai/orca#20682 |
| N | stablyai/orca#20683 |
| M | stablyai/orca#20684 |
| G | stablyai/orca#20689 |
| D | stablyai/orca#20690 |
| E | stablyai/orca#20691 |
| S | stablyai/orca#20692 |
| I | stablyai/orca#20693 |
| K | stablyai/orca#20697 |
Where a PR differs from the Odin commit, the PR body says why: the C PR carries only the exit-wait gate, not the wire evidence field; the M PR includes the O1/O2/O3a classification it depends on. The first PR's review surfaced a real defect in the original diff (an exit replayed synchronously during session construction); it is fixed in both the PR and Odin (adb4b039ae). After Pullfrog's reviews on 2026-09-15, six PRs were amended in place to the fixed contracts, each body carrying a "Review fix" section: #20682 (O3a, O3b and the O4 federation twin that review surfaced; head 28f3d99cd1), #20683 (N2; 62830a5b36), #20684 (O3a plus the returned sweep error; f8cd95c014), #20689 (G3; 5bdd8973f3), #20693 (I3, I4; 2c310acf5d), #20697 (K2; 6c0285b615). #20684's worker-observation.ts differs from #20682's only by the O4 gate extraction, which #20684 does not need.
Each residual is one commit on the odin branch. The commit body names the upstream site, the contract, the judgement calls, and two files under odin/proofs/: <id>.before.txt is the new test failing on the unpatched code, <id>.after.txt is the same test and its neighbours passing after the patch. odin/proof/run-proofs.sh repeats that check mechanically against the pinned upstream commit. odin/proofs/real-sessions.*.json are the recorded runs of real agents through the orchestration surface.
Orca is by Stably AI and Lovecast Inc., MIT. Odin keeps Orca's licence, copyright notice and history; the Odin commits are additive on top of upstream 539d4d1f32. Odin's own briefs are under odin/ (DIRECTION.md, AGENTS.md).
中文 · 日本語 · 한국어 · Español · Français · Português
The AI Orchestrator for 100x builders.
Run Codex, ClaudeCode, OpenCode or Pi side-by-side — each in its own worktree, tracked in one place.
Also in the box:
- Quick open — Search across worktrees, files, agents, commands, and repo context without leaving your flow.
- Account switcher & usage tracking — See Claude and Codex usage and rate-limit resets, and hot-swap accounts without re-logging in.
- Rich repo previews — Preview Markdown, images, PDFs, and repo docs in the workspace.
- Computer Use — Let agents operate desktop apps and visible UI when a workflow needs real interaction.
- Notifications and unread state — Know when an agent finishes or needs attention, then mark threads unread to come back later.
- And many, many more — we ship daily, so this list is perpetually behind. The changelog is the real feature list.
Works with any CLI agent — if it runs in a terminal, it runs in Orca.
Claude Code
Codex
Grok
Cursor
GitHub Copilot
OpenCode
MiMo Code
Amp
OpenClaude
Antigravity
Pi
oh-my-pi
Hermes Agent
Devin
Goose
Auggie
Autohand Code
Charm
Cline
Codebuff
Command Code
Continue
Droid
Kilocode
Kimi
Kiro
Mistral Vibe
Qwen Code
Rovo Dev
+ any CLI agent
- Download from onOrca.dev
- Or grab a build directly: macOS Apple Silicon · macOS Intel · Windows (.exe) · Linux AppImage · All builds
- Running
orca serveon a headless Linux server? See the headless Linux server guide.
Or via a package manager:
# macOS (Homebrew)
brew install --cask stablyai/orca/orca
# Arch Linux (AUR) — or stably-orca-git to build from source
yay -S stably-orca-binPair with your desktop app to monitor and steer your agents from your phone.
- iOS: Download on the App Store or join TestFlight
- Android: Download APK 0.0.48 · Install guide
-
Discord: Join the community on Discord.
-
Twitter / X: Follow @orca_build for updates and announcements.
-
WeChat: Scan to join the Orca community WeChat group 8. Group 8 may be full; if so, scan the Group 9 QR code instead.
-
Feedback & Ideas: We ship fast. Missing something? Request a new feature.
-
Privacy: See the privacy & telemetry docs for what anonymous usage data Orca collects and how to opt out.
-
Show Support: Star this repo to follow along with our daily ships.
Want to contribute or run locally? See our CONTRIBUTING.md guide.
The relay that pairs the mobile app with a desktop host is also in this repository under
cloud/, with a separate pnpm workspace and setup guide.
Windows code signing sponored/provided by SignPath.io, certificate by SignPath Foundation.
Orca is free and open source under the MIT License.












