feat(orchestration): tell each agent its own orchestration address - #22636
brennanb2025 wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
orca status --jsonreportscaller— new read-onlyorchestration.callerShowRPC answers from the dispatch entry's resolved session (session:<id>,live: true) or probes the envelope's terminal handle, elsenull; CLI maps session refusals to{live:false, refusal}and omits the field on an older host.- Worker preamble names the worker's own address — terminal handle, or
session:<id>plus a reach sentence for a structured worker, whose commands now invoke"$ORCA_CLI_COMMAND"/& $env:ORCA_CLI_COMMANDinstead oforca-dev/orca. - Guide, help text, and bundled skill guide — "Your address" section, a non-waiting chat-coordinator loop, and the
ORCA_CLI_COMMANDforms;run-use/run-current/checksummaries de-terminalized. - Copy Orchestration Address menu action — copies
session:<id>from a structured chat in both mounts, with success/failure toasts and translations in six locales.
I verified the host handler's context members (orchestrationCaller.actor/sessionId, orchestrationCompatibilityEvidence) are populated for every orchestration.* session claim, that the refusal codes the CLI keys on match the ones the resolver emits, that no production parser depends on the relabelled coordinator line, and that the bundled guide is regenerated in sync. The changed suites (preamble, deliver-worker-dispatch-preamble, status-caller, orchestration-caller-show) pass locally (48 tests). Wire changes are additive and the mode-parity normalizer is not vacuous.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
ca9b471 to
6abb9d9
Compare
47e84ab to
e1c897b
Compare
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
The branch was rebased since the prior pullfrog review (47e84abbdaf6, 6 commits). The only commit new this run is e1c897b980, a guide-contract fix plus regenerated artifacts:
- Moved
ORCA_CLI_COMMANDresolution into the shared skill stub — the invocation guidance left the always-loaded orchestration kernel forskill-stubs/_shared/cli-resolution.md, which now covers chat sessions beside WSL and gives the POSIX and PowerShell forms; everyskills/*/SKILL.mdprojection, both skill bundle manifests, andsrc/cli/bundled-skill-guides.tswere regenerated. - Relocated the chat-coordinator loop and address details to references —
references/coordinator-loop.mdnow owns the non-waiting loop and/clearnote,references/messaging-and-gates.mdthe address details, while the kernel keeps one pointer line each for the caller's address, the environment-resolvedcheckcaller, and the chat coordinator (kernel measured at 201 lines, budget 202). - Repinned the kernel contract tests — asserts the environment-resolved
checkcaller andNever name another agent with --from/--terminal, requires the preamble's owncheckcommand, and rejects the oldcheck --terminal <your_handle>shape from #21097.
I read the full raw diff end to end. Production source is untouched by e1c897b980; the change is documentation, test contracts, and regenerated artifacts. config/scripts/orchestration-skill-guidance.test.mjs passes (29/29), and pnpm verify:bundled-skill-guides, verify:skill-bundle-manifest, and verify:rpc-params-catalog all exit 0 at this head, so the regenerated block is in sync. No threads from the prior review needed retiring.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
6abb9d9 to
a32a526
Compare
e1c897b to
5c6cc5f
Compare
a32a526 to
e1e205d
Compare
5c6cc5f to
8117ac5
Compare
…address in orca status orca status --json gains a caller block: the calling agent's address as the host resolved it from the identity its environment carries. A structured session is session:<id>; a terminal agent is its handle, with whether the host still knows it. A session the host refuses reports that refusal instead. The host answers through a new read-only orchestration.callerShow, so the session claim runs through the same dispatch-entry resolver every verb uses. An older host leaves caller unresolved. The help footer and the run/check specs stop describing identity only in terminal terms.
…tors a non-waiting loop The orchestration guide now states that a chat session's address is session:<id> (never the provider's id), that orca status --json reports it, and that no caller flag should name another agent. A consuming check no longer tells every caller to name itself with --terminal. A chat coordinator starts its wave, ends the turn, and on each turn Orca starts for new mail runs a non-waiting check and ack; it never blocks in check --wait. The guide also names ORCA_CLI_COMMAND as the executable in chat sessions.
…t's context menu Copies session:<id>, the Orca-minted address other agents message the chat by. The existing Copy Session ID still copies the provider's id and is left as is; the new action is labelled so the two cannot be confused. Strings are added to every locale catalog.
…on address The worker preamble names the coordinator's address rather than a terminal handle, and states the worker's own address. A structured worker is told it is session:<id>, that its coordinator reaches it there or at its dispatch mailbox, and that mail arriving while it is idle starts a new turn. Its commands invoke the CLI through ORCA_CLI_COMMAND in its own shell's form, the same rendering the pointer turn uses, because a bare orca in a login shell can reach a different Orca.
…and PowerShell A chat session's shell reads the variable as "$ORCA_CLI_COMMAND" in a POSIX shell (Git Bash included) and as & $env:ORCA_CLI_COMMAND in PowerShell, the same two forms the pointer turn and worker preamble render. The chat coordinator loop now runs the check its pointer turn names.
…rca moves its Runs
…the orchestration kernel in budget The guide-contract tests own two rules this PR broke: only the shared skill stub may describe how to resolve the CLI, and the always-loaded orchestration kernel stays within 202 lines. The ORCA_CLI_COMMAND text moves to the stub's resolver block, which now covers chat sessions and login shells beside WSL and gives the POSIX and PowerShell forms; every skill projection and the bundle manifest are regenerated. The kernel keeps one line each for the caller's address, the environment-resolved check caller and the chat coordinator's non-waiting loop; the loop steps and the address details move to the coordinator-loop and messaging references. The two kernel pins now assert the new check contract and refuse the old --terminal <your_handle> shape.
e1e205d to
55692e7
Compare
8117ac5 to
e4c584c
Compare

ELI5
Every agent Orca runs now knows its own orchestration address, and so does the user.
orca status --jsongains acallerfield. Orca's host fills it in from the identity already in the agent's environment. A chat getssession:<id>; a terminal agent gets its terminal handle.orca --helpsay what that address is and how to use it. A chat coordinator is told to start its workers and end its turn, instead of blocking incheck --wait. Orca wakes it when results arrive.session:<id>, so a user can hand that address to another agent. The existing Copy Session ID is unchanged and still copies the provider's id.Merge order
Last PR of the structured-chat orchestration stack. Merge in this order: #22522 → #22555 → #22568 → #22631 → this PR. The PR base is
brennanb2025/d4-coordinator-delivery(head6abb9d9f1f).What works end to end
Proven live in the running app, on an isolated dev profile under
ORCA_BACKGROUND_LAUNCH=1, driven over CDP with a hidden window.Claude: a real structured Claude chat ran
"$ORCA_CLI_COMMAND" status --jsonand got backcaller: { kind: "session", address: "session:claude_c69e…", live: true }. It then loaded the guide with"$ORCA_CLI_COMMAND" skills get orchestrationand was asked to supervise one worker by following the guide's chat-coordinator section. With no further user input, it:check --wait");--waitand processed theworker_done;--ack;--terminal-state reclaimable).The worker's journal shows the new preamble:
Your orchestration address is: session:ad834dda-…, the coordinator'ssession:address, and every command written as"$ORCA_CLI_COMMAND" orchestration …. The worker sentworker_donewith exactly that command.Codex: a real structured Codex chat ran the same
status --jsonand gotcaller.address = session:codex_e234…. The same run also shows why the guide namesORCA_CLI_COMMAND. In Codex's shell,command -v orcaresolved to the user's global/usr/local/bin/orca, while"$ORCA_CLI_COMMAND"was this app's CLI. The full Codex coordinator loop was proven in #22631; it was not re-run here.Terminal agent:
orca status --jsonin an Orca terminal reportedcaller: { kind: "terminal", address: "term_d338…", live: true }. That is the same handle as itsORCA_TERMINAL_HANDLE.Menu: the chat's context menu shows Copy Orchestration Address. Selecting it put
session:claude_c69e8529_0241_438c_b5e3_2764dc07c72don the clipboard and showed the "Orchestration address copied" toast. The rig saved the clipboard first and restored it afterwards.What Changed
1.
orca status --jsonreports the caller's address, as the host resolved itorchestration.callerShow, takes no params. It answers from what the dispatch entry already resolved:{ kind: 'session', address: 'session:<id>', sessionId, live: true };resolveTerminalIdentityprobe, which returns{ kind: 'terminal', address, live };null.session:<id>, not itsstructworker_handle. The worker also keeps its handle, butsession:<id>is the one address that reaches every kind of session (feat(orchestration): deliver worker results to a structured chat coordinator #22631).orca statuscalls it only when the runtime is reachable and the process carries an identity. Nothing names the caller in params: the CLI's orchestration envelope carriesORCA_AGENT_SESSION_IDand the terminal evidence, exactly as it does for every verb.{ kind: 'session', sessionId, live: false, refusal: { code, message } }. The codes are the existingsession_caller_*codes (not live, provider id, host boundary, unknown).calleris left out, so a missing field means "not resolved".caller: nullmeans "this process has no orchestration identity".caller:line.2. The orchestration guide, its references, and the shared skill stub
The always-loaded kernel (
skill-guides/orchestration.md) stays within its 202-line budget. It gains five lines, and the detail lives in the references it already routes to.caller.addressinORCA status --json(session:<id>in a chat, your handle in a terminal); never name another agent with--from/--terminal;checkno longer tells every caller to name itself with--terminal <handle>, the instruction shape behind fix(orchestration): stop the sender-terminal refusal recommending another pane's handle #21097. It takes its caller from the environment in a chat or Orca terminal; elsewhere you pass your own--terminal <handle>. A worker uses its preamble's owncheckcommand;check --wait, and the coordinator-loop reference is routed for chat coordination.references/coordinator-loop.md: the chat-coordinator loop. Start the wave and end the turn. On each turn Orca starts for new mail, run thecheckthat turn names, without--wait. Process it,--ack, and end the turn again. After/clear, Orca moves the Runs to the new session (feat(orchestration): deliver worker results to a structured chat coordinator #22631).references/messaging-and-gates.md:session:<id>addresses;callerlive: falseandnullmean;/cleargives a new address, and a send to the old one is refused with the new one named;checkcaller rule.skill-stubs/_shared/cli-resolution.md): the only place allowed to describe CLI resolution. ItsORCA_CLI_COMMANDsentence said "for managed WSL sessions"; it now also covers chat sessions whose login shells (Codex's among them) can put a differentorcafirst on PATH, and gives both forms:"$ORCA_CLI_COMMAND"in a POSIX shell (Git Bash included),& $env:ORCA_CLI_COMMANDin PowerShell. Regenerated with the repo's generators:skills/*/SKILL.mdprojections;src/cli/bundled-skill-guides.ts;resources/skills/current-manifest.jsonand the unreleased rows ofsnapshot-registry.json.3.
orca --helpand the CLI specsORCA_CLI_COMMANDin both shell families.statusspec notes thecallerfield.run-use,run-currentandcheckstop describing the caller as a terminal.4. The worker preamble
Your coordinator's terminal handle is:becomesYour coordinator's address is:, because a coordinator may be a chat.session:<id>;dispatch:<id>;ORCA_CLI_COMMAND.structuredSessionCliInvocation({ platform, provider }), the same rendering the pointer turn uses. A Codex worker on Windows gets& $env:ORCA_CLI_COMMAND; everyone else gets"$ORCA_CLI_COMMAND". This replacesorca-dev/orca, which a login shell can resolve to a different Orca.5. Copy Orchestration Address
session:<id>, derived with the shared actor codec (formatOrchestrationActor), and toasts success or failure.en.jsonand hand-added to es, fr, ja, ko and zh.Why
The mechanism: Orca already resolves a caller's identity on the host, once, at the dispatch entry (#22555). The agent just had no way to see the answer. So the agents guessed, and the old guide told them to pass
--terminal <handle>, which is how #21097 happened.callerShowreturns the result of that same resolution rather than adding a second resolver. Putting it inorca status, which the guide's supervised loop already runs first, means a coordinator that follows the guide sees its address with no new step.Alternatives rejected:
callerintostatus.get.status.getis the runtime-readiness probe. It is called without an orchestration envelope (the 1s local probe, the contract check, remote status), and the session resolver only runs fororchestration.*requests. Every readiness probe would pay a session-record read, and a refused session would turn a readiness check into an error.ORCA_AGENT_SESSION_IDfrom the CLI. That does not prove the host will act as that session (a released lease, a provider id, another host), and the brief requires the answer to be host-resolved.Deviations, stated plainly:
caller.live: falsereports a stale handle and does not remint it. The coordinator verbs remint throughORCA_PANE_KEY;statusonly reports.Linked Issue
None — part of the structured chat status/orchestration program. Stacked on #22631.
Visual Proof
Live dev app, hidden window, CDP screenshots.
Chat context menu: before / after
After selecting it (the clipboard held
session:claude_c69e8529_0241_438c_b5e3_2764dc07c72d):orca status --jsoncaller, from a Claude chat, a Codex chat and a terminal agentA Claude chat coordinating one worker by following the guide: it ends its turn, receives the pointer turn, checks without waiting, releases the worker and acks
The "before" shot is the same running app with this PR's three renderer files set back to the base commit (vite HMR), then restored.
Testing
New tests
orchestration-caller-show.test.tsruns through the real dispatcher and session-caller harness:session:<id>even when it carries a terminal view's pane evidence;session:<id>, not its handle;null.status-caller.test.tsruns the realorca statushandler and the real CLI client over a real Unix socket:live: false;callerout;preamble.test.ts:session:<id>and the reach sentence;deliver-worker-dispatch-preamble.test.ts:& $env:ORCA_CLI_COMMANDand a Claude worker gets"$ORCA_CLI_COMMAND";orca.use-native-chat-context-menu.test.tsx:session:<id>in both mount modes;Ablations: 12 mechanisms, each deleted or neutralized. Each replacement was asserted to match exactly once, run against the 6 reachable test files (61 tests), then restored from HEAD. All were re-run at this head, and every one went red:
statusnever resolves the callerThe first run of "invocation ignores the provider" was green, because the suite ran only on macOS, where both providers render the same form. A test that stubs
process.platformtowin32was added, and the ablation then went red.Guide-contract pins (in
config/scripts), each ablated by restoring the old text in the kernel:check --terminal <your_handle>: 4 red;checkcaller sentence: 3 red;ORCA_CLI_COMMANDline restated in the kernel: 4 red.The address that the structured chat component passes to the menu (
NativeChatStructuredSession) has no unit test. It is proven live: the before shot drops it, and the after shot copies the real session id.The
config/scriptsguide-contract tests are green at this head: the guide keeps theORCAplaceholder (executable resolution lives in the shared skill stub, whose text now covers chat sessions as well as WSL), the kernel stays inside its line budget, and the caller pins assert the new environment-resolved contract.Suites (
env -u ORCA_STRUCTURED_SESSION -u ORCA_AGENT_SESSION_ID … npx vitest run --config config/vitest.config.ts):config/scripts,src/cli,src/main/runtime/orchestration,src/main/runtime/rpc,src/renderer/src/components/native-chat, the actor codec and the coordinator-mail integration suite ran at this head: 1,001 files / 9,480 tests, 9,153 passed, 321 skipped, 6 failed. None of the 6 comes from this PR:build-native-for-platformandorchestration-all-start-versions-migration.pnpm installor shell environment:patched-dependencies-frozen-install(×2) andskill-recipe-shell.Checks
pnpm tc:node,tc:cliandtc:webare clean.check:code-quality:changed: 0 findings. A fullpnpm exec oxlintreports 0 errors, andoxfmt --checkis clean on the changed files.verify:bundled-skill-guides,verify:skill-bundle-manifest,verify:rpc-params-catalogand the fourverify:localization-*gates pass.pnpm-lock.yamlis absent from the range. No documentation files are added; every guide, reference, stub and skill file edited is already tracked.AI Disclosure
Review
statusrather than a field onstatus.get; see Why.session:<id>, although its sends still carry--from <structworker handle>, which the host maps to the same session.Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
method_not_found, socalleris left out.calleris an optional field in CLI output only.--environment): a session claim from a paired client is refused by refactor(orchestration): resolve every caller to one orchestration actor #22555.statusthen reports the refusal (session_caller_host_boundary) instead of an address. A terminal handle from another host probes as not live.statustherefore reports its terminal handle, ornull.statusmakes one extra RPC, and only when the process carries an identity. For a session it costs one record read. Resolving the caller may bring up the agent-session host, so thecallerShowcall runs under its own 10s budget instead of the 1s readiness probe's; a process with no identity, or an unreachable runtime, never pays it.orchestration-cli-subprocess.test.tsis skipped unless a builtout/cliexists. On this machine its keepalive case fails (checkanswersstable_pane_requiredfor itsterm_nobodycaller). It fails even with a freshly built CLI underenv -i, keeping onlyHOME,PATHandTMPDIR, and it fails identically on a clean export of feat(orchestration): deliver worker results to a structured chat coordinator #22631's head6abb9d9f1f. The review of this PR ran it 3/3 green in another shell and attributed my failure to the test spreadingprocess.envinto the spawned CLI. Myenv -irun does not support that explanation, so the cause is machine-specific and still unknown. It is not tied to this branch.Not verified
[orchestration] could not wake a structured session for its mail { error: 'provider close unproven' }, and no pointer turn arrived. The feat(orchestration): deliver worker results to a structured chat coordinator #22631 implementer traced it to the Claude adapter onmain: the adapter keeps an evicted session indexed when it cannot prove the provider closed, so every later resume fails. It is reported to the orchestrator and is not changed here. After an app restart, the pending mail was delivered on restore, and the chat ran the guide's loop (check, reply,--ack). Codex and non-evicted coordinators are not affected.status; the full loop was proven in feat(orchestration): deliver worker results to a structured chat coordinator #22631.& $env:ORCA_CLI_COMMAND) is unit-tested only. There is no Windows host.