Skip to content

feat(orchestration): tell each agent its own orchestration address - #22636

Merged
brennanb2025 merged 51 commits into
mainfrom
brennanb2025/d5-self-address
Oct 2, 2026
Merged

brennanb2025 merged 51 commits into
mainfrom
brennanb2025/d5-self-address

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 13 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1042 $\color{#cf222e}{\Huge{\mathbf{−}}}$​14 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1028
Prod 33 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​393 $\color{#cf222e}{\Huge{\mathbf{−}}}$​44 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​349

ELI5

An agent Orca runs as a chat session can now ask Orca for its own Orca session ID (orca_session_id:<id>), the ID other agents use to message it, and a user can copy a chat's Orca session ID from its menu. Terminal agents see exactly what they see on main.

Before this, a chat agent had no reliable way to learn its own Orca session ID. It guessed: it copied an ID from its environment, or passed --terminal <handle> with a handle that might belong to another pane. A user had no way to copy a chat's Orca session ID at all, so they could not tell another agent where to send messages for that chat. And a dispatched worker running as a chat session was never told its own ID.

What Changed

Scope

This PR changes four places an agent or user sees:

  • orca status (text and --json): a chat caller gets its Orca session ID (caller.orcaSessionId, and an orcaSessionId: text line). A terminal caller gets exactly main's output.
  • The orchestration guide gains one line: "ORCA status --json shows your Orca session ID as caller.orcaSessionId when you have one."
  • A dispatched worker's instructions (the "preamble" Orca sends a worker when it starts a task) name each party by its kind. A worker that is a chat session is told "Your Orca session ID is: …". A coordinator that is a session is "Your coordinator's Orca session ID is: …". Terminals keep main's "Your coordinator's terminal handle is: …".
  • A structured chat tab's right-click menu gains Copy Orca Session ID, with a tooltip saying what the ID is.

It also fixes two places where a chat that was /cleared was shown its new session's ID instead of the Orca session ID it keeps across /clear: the dispatch-show --preamble preview, and the error for sending to a provider's own session ID. And it rewords agent-facing refusals that called this ID an "address" or a bare "session id".

Not affected:

  • Terminal agents. Their orca status output, their worker preamble under a terminal coordinator, and their check, send and ask are exactly main's.
  • How mail is stored. Every agent keeps the mailbox key it has on main, and no data is migrated.
  • Dispatching a task to a chat is still refused (session_chat_not_dispatchable). Making a chat a dispatch target is the stacked PR feat(orchestration): a native chat can be a dispatch worker, like a terminal agent #22972.
  • How long a blocking check --wait or ask waits. A chat waits exactly as long as a terminal agent, as on main.

What this changes for you

Situation Before After
A chat agent needs its own ID to give to another agent No way to ask; it guessed from its environment or a flag orca status --json returns caller: { orcaSessionId: "orca_session_id:<id>", live: true }, resolved by Orca
A human runs orca status in a chat agent's shell Readiness lines only Plus orcaSessionId: orca_session_id:<id>, or orcaSessionId: none (refused: <code>) if Orca will not act as that session
A human runs orca status in a terminal agent's shell Readiness lines only Unchanged
A worker running as a chat session starts a task Told its coordinator's "terminal handle" and its task ID only Also told "Your Orca session ID is: orca_session_id:", and its commands use that ID
A worker's coordinator is a chat "Your coordinator's terminal handle is: orca_session_id:" "Your coordinator's Orca session ID is: orca_session_id:"
A terminal worker under a terminal coordinator main's preamble Byte-for-byte the same
A user wants another agent to message a chat Only Copy Session ID, which copies the provider's own ID and changes on /clear Copy Orca Session ID copies the ID Orca routes to, which /clear keeps. Tooltip: "Orca's ID for this chat, separate from the agent CLI's own session ID. Agents use it to refer to each other through Orca." Toasts: "Orca session ID copied" / "Unable to copy Orca session ID"
A /cleared chat previews a dispatch or someone sends to its provider ID Named its new session's ID Names the Orca session ID the chat kept

Mechanism

  • orchestration.callerShow (new, read-only, no params). Orca's host already works out who is calling on every orchestration request, from the session ID the CLI sends in its request envelope. callerShow returns that answer as orca_session_id:<id>, where the ID is the first session of the chat's /clear chain. For anyone who is not a session it answers null. A session Orca will not act as (not running, another host, a provider's own ID) gets the same refusal every orchestration command gets.
  • orca status calls callerShow (10 second limit) only when the process carries an Orca session ID (ORCA_AGENT_SESSION_ID) and the runtime is reachable. A terminal agent makes no extra call, so its text and JSON are exactly main's. An older host that lacks the method, or any failure, leaves caller out; the exit code is unchanged.
  • The guide (skill-guides/orchestration.md, bundled into the CLI) gains exactly that one line. Nothing in the guide is chat-specific. orca status help gains a note about caller.orcaSessionId, and the run-use, run-current and check summaries no longer say the caller is a terminal.
  • The worker preamble (preamble.ts) picks each identity line by the party's kind: a value spelled orca_session_id: gets the Orca session ID wording, anything else keeps main's terminal-handle wording and no self line. Every path that builds a preamble (dispatch, dispatch --dry-run, dispatch-show, worker-start) names each party the same way: a session by its Orca session ID (its /clear root's), anything else by its handle.
  • A structured worker's commands in its preamble (--from, --terminal) use its Orca session ID, matching its self line. The host binds that ID to the worker's own mailbox, so its mail is stored exactly as on main.
  • The provider-ID refusal (session-recipient.ts) names the /clear chain's first session instead of the current one.
  • Copy Orca Session ID (NativeChatCopyOrcaSessionIdMenuItem.tsx, wired in use-structured-native-chat-pane-commands.ts) asks the host that owns the chat (orchestration.sessionAddress, new) for the Orca session ID when the item is selected, because only the host's session records know a chat's /clear history. Against a host that predates the method it copies orca_session_id:<current id>. Any other failure shows the error toast; the copy never claims a success it did not have. The tooltip uses the existing menu-item tooltip pattern and the shadcn tooltip primitive. New strings, with real translations, are in all six locales.

Why

Why ask the host instead of reading the environment in the CLI. The CLI can read the session ID it was started with, but not whether Orca will act as that session (a released session, another host, a provider's own ID), and not a chat's /clear history. The host already decides this for every command, so status reports that decision rather than a guess.

Why terminal agents are left exactly as on main. Terminal agents do not have an Orca session ID yet. Showing a terminal handle under a new name, or under a neutral word, would teach agents a name that changes when terminals move to Orca session IDs. So a terminal caller's status and a terminal worker's preamble stay exactly as they are.

Why a new method instead of a field on status.get. status.get is the readiness probe. It is called without an orchestration envelope (the 1 second local probe, the version check, remote status), so it cannot see who is calling. It would also make every readiness probe read session records and turn a refused session into a failed readiness check.

Why a structured worker's mail stays under its handle. A structured worker (a worker that runs as a chat session) has its mail stored under the handle Orca minted for it. Rewriting that handle to the Orca session ID wherever an agent reads mail would need a change at every read site, and any site that missed it would show the other spelling. Moving storage to Orca session IDs is its own change. Until then the worker is told its Orca session ID, which routes to the same mailbox.

Why chats get no special wait limit. We considered capping how long a chat's check --wait and ask block, on the theory that the chat provider's shell tool would kill a long command. Neither provider does: default Codex's command tool returns output after a few seconds and keeps the command running, and Claude Code moves a Bash command that passes its timeout to the background. Terminal agents run the same tools with no cap. A cap would only have made a chat coordinator re-run check every few seconds. So a chat waits exactly as a terminal agent does.

Why the menu item resolves at click time, and why its own label. A /clear changes the chat's current session but not its Orca session ID, so reading it on click uses the current /clear history. In Orca's UI "Session ID" already means the provider's own ID, so this gets its own item, and the tooltip says how the two differ; Copy Session ID is unchanged.

Deviations

  • Intended (confirmed): a terminal worker whose coordinator is a chat sees "Your coordinator's Orca session ID is: orca_session_id:" instead of main's line. On main that line prints the chat's orca_session_id: value under "Your coordinator's terminal handle is:", which calls an Orca session ID a terminal handle. Every other line of that preamble is main's.
  • Intended: Copy Orca Session ID is on structured chat tabs only. A chat shown inside a terminal pane is that terminal's agent, which keeps Copy Terminal ID.
  • Intended: against a host without orchestration.sessionAddress, the menu copies orca_session_id:<current id>. Safe because such a host routes that ID to the same chat.
  • Intended: the run-use, run-current and check help summaries say "coordinator" or "this agent" instead of "terminal", for every agent. They stay accurate for terminal agents.
  • Temporary: a structured worker is told its Orca session ID, but check rows, receipts, reply hints and worker-list still show its structworker_ handle, because its mail is stored under that handle. Messages to either reach it. Follow-up: store mail by Orca session ID, after which every surface shows the Orca session ID.
  • Temporary: dispatch and worker-start name the parties after the dispatch row is written (and, for worker-start, after the worker launches). This cannot fail on any input that reaches it today. Follow-up: work the names out before writing the dispatch row.
  • Temporary: the orca status help note says caller is omitted when the agent is not an Orca session, but does not mention caller.refusal for a session Orca refuses. Follow-up: add it to the note.
  • Temporary: the menu's RPC is still named orchestration.sessionAddress although it now returns { orcaSessionId }. Only the renderer calls it, and it is unreleased. Follow-up: rename it before release, or accept the name.
  • Temporary (already on main, not caused by this PR): in a development build, a structured worker's preamble can name the orca CLI instead of orca-dev unless the coordinator's CLI identified itself as a dev build. Follow-up: use the CLI name the structured message lane uses.
  • Temporary: if the chat host is not running when Copy Orca Session ID is selected, orchestration.sessionAddress answers the current session's ID instead of the /clear chain's first one. Hard to reach, because a visible chat has already started that host. Follow-up: start the host first and refuse if it cannot.
  • Temporary: resolving a terminal caller once on the host for every command, as sessions already are, is deferred. It no longer affects orca status, which shows nothing for terminal agents.

Merge order

Base is main. The stacked PR #22972 (a chat as a dispatch assignee) must be restacked onto this PR's final head before it merges: it used the wait cap and the worker-renaming helper this PR no longer has, and it must follow the Orca session ID wording.

Linked Issue

None — part of the structured chat orchestration program. Base is main.

Visual Proof

Live Electron QA of this head, 1ce4007929, on a separate Mac (M4Air): a dev build with an isolated home and profile, a hidden window and CDP screenshots. The QA driver was Codex. The agents inside the app are structured Claude chats and a Claude terminal worker.

A chat's right-click menu shows Copy Orca Session ID, with its tooltip

Chat right-click menu with Copy Orca Session ID hovered and its tooltip open

Selecting it shows the success toast

Toast reading Orca session ID copied

The copied value is orca_session_id:<id>. Here it is pasted into the composer, and the chat's own orca status --json reports the same value

Copied value orca_session_id:claude_15647270_… pasted into the chat composer

The chat runs orca status --json: caller.orcaSessionId equals the copied value, live true

A chat worker's instructions, from a terminal coordinator: main's coordinator line plus "Your Orca session ID is: orca_session_id:…"

Chat worker preamble showing the coordinator's terminal handle, the task ID and Your Orca session ID is: orca_session_id:…

A terminal worker's instructions match main. The text the worker received is byte-identical to main's preamble rendered for the same inputs. The identity lines ("Your coordinator's terminal handle is: term_…", with no Orca session ID line) had scrolled off the top of the pane. The end of the same preamble is shown here, with every command using the terminal handle.

Terminal worker pane: the end of main's preamble, with commands using the term_ handle, and READY

Terminal menus are unchanged: Copy Terminal ID is still there, and there is no Copy Orca Session ID. This PR changes no terminal-pane files.

Terminal pane right-click menu with Copy Terminal ID and no Copy Orca Session ID

Terminal tab right-click menu with no Copy Orca Session ID

The two screenshots below come from an earlier head, fd0c2a12bd. The behavior they show is unchanged here.

A chat's check --wait is not capped. With Claude Code's default 120 second Bash timeout, Claude moved the command to the background at 120 s instead of killing it; the wait kept running, a message sent at 150 s arrived once, and the chat picked it up on its own. In a second run, where Claude chose a 240 s tool timeout, the message arrived at about 165 s, also exactly once.

Chat wait moved to the background at 120 s and still received the message

Chat's blocking check receives a message at about 165 s

Testing

Checks at 1ce4007929 (main merged at 8b76683b400):

  • Typecheck (tc:node, tc:cli, tc:web) passes.
  • 113 test files, 1217 tests pass, 4 skipped: every test file this PR adds or changes, plus preamble.test.ts and its snapshot, all of rpc/methods/orchestration/, the CLI session-caller tests, the guide tests in config/scripts/, and NativeChatStructuredSession. A wider run at 88383118d60 (all of src/main/runtime/orchestration, rpc/methods/orchestration, every rpc/orchestration-*.test.ts, the CLI orchestration tests and the structured chat tests) passed: 293 files, 2673 tests.
  • oxlint (full), the anti-slop rules on changed files, check:code-quality:changed and check:react-doctor:changed are clean.
  • verify:rpc-params-catalog, verify:bundled-skill-guides, verify:skill-bundle-manifest and all five verify:localization-* scripts pass.

New and changed tests:

  • preamble.test.ts: the identity lines for each pairing of kinds. The snapshot of a terminal worker under a terminal coordinator is main's snapshot, unchanged.
  • agent-facing-parity.test.ts: a chat worker's preamble equals a terminal worker's apart from its identity lines; the chat message-pointer text matches the terminal one in packaged and dev builds; the guide has no chat-only text and grows by one line. A guard checks that the guide and its references, every preamble pairing, and the refusals that name a session never call the Orca session ID an "address".
  • src/cli/orca-session-id-wording.test.ts: the same guard over CLI help, specs and orca status text.
  • status-caller.test.ts: a chat caller's orcaSessionId field and text line; a terminal agent, a pane key alone and a plain shell print main's status and make no extra call; a refused session; an older host.
  • orchestration-caller-show.test.ts: callerShow for a chat, a structured worker (whose preamble names its Orca session ID while its mail stays under its handle), a /cleared chat, a released session, a provider ID, a paired client, a terminal agent and no identity.
  • orchestration-worker-mode-opacity.test.ts: a structured worker is taught a terminal worker's text apart from its identity lines, and a structured worker's sub-worker is told its coordinator's Orca session ID.
  • orchestration-party-addressing.test.ts: orchestration.sessionAddress answers the Orca session ID for a chat and a worker; a /cleared chat's dispatch-show preview and provider-ID refusal name the Orca session ID it kept.
  • use-native-chat-context-menu.test.tsx: the label, the exact tooltip text, both toasts, and the copied value.
  • use-structured-native-chat-pane-commands.test.tsx: on a structured chat tab the item appears, and selecting it asks orchestration.sessionAddress with the tab's host and session ID.
  • orchestration-check-wait-session.test.ts: a chat's check --wait reaches the host's waiter with the full budget it asked for.

Ablations (each change undone, then its tests re-run; all 12 went red):

  • The terminal coordinator line given the new wording: 3 preamble tests fail, including main's snapshot.
  • No self line for a session worker: 4 tests fail.
  • A structured worker named by its handle in worker-start: 2 tests fail.
  • Previews naming parties by raw handle: 3 tests fail.
  • orca status asking the host for a terminal agent: 3 tests fail.
  • callerShow answering the mailbox handle: 1 fails. sessionAddress answering a worker's handle: 1 fails.
  • "address" put back into a refusal: the guard fails. "address" put back into the orca status help: the CLI guard fails.
  • Tooltip text changed, toast changed, menu wiring removed: 1 test fails each.

A separate fresh review of this head also checked:

  • Both merges of main have no hand-resolved conflicts.
  • A terminal worker's preamble is byte-identical to main's over 24 input combinations, comparing against a copy of main's preamble.ts.
  • A structured worker that names itself by its Orca session ID settles worker_done, heartbeats, asks and checks exactly as it does by its handle.
  • No agent-read text calls this ID an "address".
  • The translations are real and the old keys are gone.
  • It ran its own 4 ablations, which all went red.

Not verified: keyboard focus showing the tooltip in the running app; Linux, Windows and SSH by hand; Codex chats live (the Codex wait behavior comes from Codex's source and from real Orca Codex session logs).

  • I manually tested these changes locally (live Electron QA on a separate Mac, see Visual Proof)
  • Automated tests added/updated, or explained why not below

AI Disclosure

Review

  • orca status makes one extra local call, bounded at 10 seconds, only for a process that carries an Orca session ID and only when the runtime is reachable.
  • Mixed versions: a new CLI against an older host omits caller; an older CLI never calls the new method; a new app against an older host copies orca_session_id:<current id>.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Security: callerShow only reports the identity the caller already presented, and a session claim from another host is refused as before. Cross-platform: no platform-specific code. SSH/remote: the menu asks the host that owns the chat, and a session claim from a paired client is refused as for every orchestration command. Mobile: no mobile change. Performance: one bounded local call per orca status for a chat agent, and one host call per menu selection.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • orca status --json reports caller — new read-only orchestration.callerShow RPC answers from the dispatch entry's resolved session (session:<id>, live: true) or probes the envelope's terminal handle, else null; 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_COMMAND instead of orca-dev/orca.
  • Guide, help text, and bundled skill guide — "Your address" section, a non-waiting chat-coordinator loop, and the ORCA_CLI_COMMAND forms; run-use/run-current/check summaries 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.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 force-pushed the brennanb2025/d4-coordinator-delivery branch from ca9b471 to 6abb9d9 Compare September 24, 2026 10:26
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d5-self-address branch from 47e84ab to e1c897b Compare September 24, 2026 10:32

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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_COMMAND resolution into the shared skill stub — the invocation guidance left the always-loaded orchestration kernel for skill-stubs/_shared/cli-resolution.md, which now covers chat sessions beside WSL and gives the POSIX and PowerShell forms; every skills/*/SKILL.md projection, both skill bundle manifests, and src/cli/bundled-skill-guides.ts were regenerated.
  • Relocated the chat-coordinator loop and address details to references — references/coordinator-loop.md now owns the non-waiting loop and /clear note, references/messaging-and-gates.md the address details, while the kernel keeps one pointer line each for the caller's address, the environment-resolved check caller, and the chat coordinator (kernel measured at 201 lines, budget 202).
  • Repinned the kernel contract tests — asserts the environment-resolved check caller and Never name another agent with --from/--terminal, requires the preamble's own check command, and rejects the old check --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.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 force-pushed the brennanb2025/d4-coordinator-delivery branch from 6abb9d9 to a32a526 Compare September 24, 2026 10:59
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d5-self-address branch from e1c897b to 5c6cc5f Compare September 24, 2026 11:00
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d4-coordinator-delivery branch from a32a526 to e1e205d Compare September 24, 2026 11:59
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d5-self-address branch from 5c6cc5f to 8117ac5 Compare September 24, 2026 12:03
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d4-coordinator-delivery branch from e1e205d to 55692e7 Compare September 24, 2026 12:34
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d5-self-address branch from 8117ac5 to e4c584c Compare September 24, 2026 12:34

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (e4c584cf01), six commits landed, all addressing the architecture review of the orchestration-address feature:

  • Refuse a blocking check --wait from a chat — the host now rejects wait: true from a native lease with wait_requires_terminal (effectsApplied: false) before any waiter registers, naming the turn-loop recovery in the message; a tui-held session may still block. The code was added to the structured-runtime passthrough set.
  • Resolve orca status's caller with the verbs' ladder, host-side — callerShow now probes the carried handle, then remints through the pane key, and only then reports the stale handle as live: false; the CLI always asks, so a pane-key-only process resolves too.
  • Show a structured worker as session:<id> on every read — withAgentVisibleAddresses re-spells from_handle/to_handle in check rows and formatted banners, and the coordinator address in preambles goes through the same codec. Only reads are re-spelled: stored keys and send receipts keep the handle the settlement path matches.
  • Teach a chat worker the turn loop and pin parity at the contract — the structured-worker preamble asks with a 5s budget, never a blocking wait, uses the turn loop for sub-dispatch and post-worker_done, and emits check --terminal session:<id>; the mode-parity test now pins sections, verbs, flags, and lifecycle ids rather than bytes.
  • Tests updated — db threaded to preamble delivery, a terminal-view waiter in the consumer-fencing test, and the Run id read through the fixture's checked accessor.

I read the range-diff and the full-diff production sections end to end. The host and CLI terminal ladders stay equivalent for the stale-handle / pane-remint cases (resolveTerminalPane only throws terminal_not_found, mapped to "no remint"), runtimeKind matches the delivery-view discriminator, the session refusal codes are in the passthrough set, and reads-only re-spelling leaves lifecycle-reconciliation matching intact. The parity test guards against vacuity (asserts 8 commands, no minted handle, the sub-dispatch section).

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (4927a2d3d1), one commit landed (ee5a52fc07), the last of the architecture-review follow-ups for this feature:

  • Added orchestration.sessionAddress — a read-only RPC returning the session:<id> a chat's conversation is reached at, derived host-side through sessionOrchestrationIdentity; it refuses an id that is not an Orca session id and is registered in RPC_PARAMS_BY_METHOD (method count 42 → 43).
  • Made Copy Orchestration Address resolve at copy time — the menu item now takes a () => Promise<string | null> resolver that asks the host instead of a renderer-formatted session:<live id>, falling back to the live id only on a method_not_found host and surfacing any other failure as an error toast.
  • Corrected the guide's /clear wording — coordinator-loop.md and messaging-and-gates.md now say a chat's address survives /clear (it names the conversation) while caller.sessionId becomes the new session; bundled-skill-guides.ts regenerated.

I read the incremental range-diff and the full-diff production sections end to end. sessionAddress and callerShow share a single derivation, so the copied address equals the address the session acts as; the only swallowed failure in the renderer resolver is method_not_found, and the menu item's visibility gating is unchanged. The four delta suites pass at this head (52 tests), verify:bundled-skill-guides and verify:rpc-params-catalog exit 0, and pnpm tc:node / tc:web are clean. Prior reviews carry no inline threads, so nothing needed retiring.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new commit is sound, but the branch now conflicts with its advanced base and cannot merge.

Reviewed changes

Since the prior pullfrog review (ee5a52fc07), one commit landed (5602038dcb), the read-side half of the stack's /clear lineage work:

  • Re-spelled a structured worker by its conversation actor — agentVisibleOrchestrationAddress now returns sessionOrchestrationIdentity(worker.sessionId, db).actor instead of formatting session:<live id> directly, so the address an agent reads for a worker comes from the same derivation the caller resolver binds. On the merge-base this is behavior-identical; the lineage-aware divergence only appears once the base carries #22631.

⚠️ The branch conflicts with its base in the file this commit changes

brennanb2025/d4-coordinator-delivery has advanced from 55692e7e6b to e79d321f (#22631), which rewrote structured-session-mail-address.ts around the /clear lineage. This branch still carries the pre-lineage version of that file, so merging produces a content conflict there — GitHub reports the PR as CONFLICTING. The branch needs a rebase onto (or merge of) the current base, and the resolution must keep this commit's delegation (agentVisibleOrchestrationAddress deriving the actor through sessionOrchestrationIdentity(...).actor) on top of #22631's lineage-aware sessionOrchestrationIdentity.

Technical details
# Rebase `d5-self-address` onto the lineage-aware `d4-coordinator-delivery`

## Affected sites
- `src/main/runtime/orchestration/structured-session-mail-address.ts` — content conflict in the import block: the base adds `getStructuredAgentSessionHost` and `readAgentSessionRecordStore`, this branch adds `resolveStructuredWorkerIdentity` and `MessageRow`.
- `src/main/runtime/rpc/orchestration-session-caller.ts` — auto-merges, but re-check the `sessionOrchestrationIdentity` call shape after the rebase (the base gives it a third `store` parameter).

## Required outcome
- The rebased branch builds and typechecks against the current base.
- `agentVisibleOrchestrationAddress` still returns `sessionOrchestrationIdentity(worker.sessionId, db).actor`, which on the lineage-aware base resolves to the conversation's root session.

## Verification
- `git merge-tree --write-tree HEAD origin/brennanb2025/d4-coordinator-delivery` reports a single content conflict in `structured-session-mail-address.ts`; `orchestration-session-caller.ts` auto-merges.

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 force-pushed the brennanb2025/d4-coordinator-delivery branch from e79d321 to 92ecd41 Compare September 24, 2026 22:11
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d5-self-address branch from 5602038 to 4a8f01f Compare September 24, 2026 23:26

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (5602038dcb), the branch was rebased onto the current lineage-aware base and two test-only commits landed. The prior review's merge blocker is resolved.

  • Rebased onto the lineage-aware d4-coordinator-delivery (92ecd41040) — git merge-tree HEAD origin/brennanb2025/d4-coordinator-delivery is clean. structured-session-mail-address.ts now carries the base's /clear lineage code, and this branch's agentVisibleOrchestrationAddress keeps its delegation through sessionOrchestrationIdentity(worker.sessionId, db).actor, so a structured worker reads as its conversation's root.
  • Pinned the cleared-chat copy assertion to the exact address — the orchestration-caller-show case now asserts shown.address === ACTOR_X for both the predecessor and its cleared successor rather than toMatch(/^session:/), so it fails if the lineage walk regresses to the live id.
  • Completed the mode-opacity fixture's record store — the partial store gained listRecords: () => [] (each session its own root), the listing structuredSessionLineage reads during a sub-worker start.

I read the incremental range (5602038dcb..4a8f01f7d6), the touched production files end to end, and the other sessionOrchestrationIdentity call sites (each passes a store or relies on the default readAgentSessionRecordStore()). orchestration-caller-show.test.ts (10) and orchestration-worker-mode-opacity.test.ts (4) run green at this head. No prior inline threads needed retiring.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (4a8f01f7d6), the branch was rebased onto the advanced base 34d9401a80, a test-only commit landed, and one new substantive commit refactored the self-address surfaces onto the base's renamed types:

  • Rebased onto the lineage-aware base 34d9401a80 — the base now exposes a session's address as a bare branded OrcaSessionId (sessionOrchestrationIdentity(...).orcaSessionId, formatted by formatOrcaSessionAddress) in shared/orca-session-address.ts, with the prefix split into the leaf orca-session-address-prefix.ts so CLI entries stay off the codec's zod graph. These files are base-authored; the PR consumes them.
  • callerShow and sessionAddress format the root session:<id> — callerShow's session branch reports formatOrcaSessionAddress(orchestrationCaller.orcaSessionId); sessionAddress validates with isOrcaSessionId and then formats sessionOrchestrationIdentity(params.sessionId).orcaSessionId, keeping the copied address equal to the address the session acts as.
  • Agent-visible worker spelling uses the conversation root — agentVisibleOrchestrationAddress derives formatOrcaSessionAddress(sessionOrchestrationIdentity(worker.sessionId, db).orcaSessionId) behind an isOrcaSessionId guard, so mailbox reads show a structured worker as its lineage-root session address while stored keys and receipts keep the handle.
  • CLI and renderer resolve via the one exported constant / guard — the status refusal line, the check caller label and the dispatch preamble spell session: from ORCA_SESSION_ADDRESS_PREFIX; the renderer resolver and NativeChatStructuredSession swap sessionOrchestrationActor for isOrcaSessionId; the copy fallback formats formatOrcaSessionAddress(sessionId).

I read the new commit's diff and each of its eight files at HEAD, and read the base commit 34d9401a80 diff to confirm the rename semantics being adapted to. Grep shows no remaining sessionOrchestrationActor / formatOrchestrationActor / .actor / coordinator_actor usage in src, and no stale "actor" wording in the guide/help/spec files. At this head the ten affected suites (90 tests) pass, and pnpm tc:node, tc:cli and tc:web are clean. Prior pullfrog reviews carry no inline threads, so nothing needed retiring; the earlier merge-conflict blocker is resolved.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (2c4fcb4107), one substantive commit landed (18baf737ba), the last architecture-review follow-up for the self-address feature:

  • orchestration.sessionAddress now resolves through the one party resolver — the handler swaps sessionOrchestrationIdentity(...).orcaSessionId for resolveOrcaSessionParty(...).orcaSessionId, so a session's reported/copied address is derived by the same hook that binds a verb acting as that session. A non-Orca id still refuses with unknown; a recorded worker whose identity the host lost now refuses with notLive instead of formatting a stale address. ORCHESTRATION_TARGET_PARAM classifies sessionAddress.sessionId as a target (that map is read only by the party-naming contract tests, so there is no runtime routing change).
  • check --wait is refused for every session caller, workers included — the runtimeKind === 'native' discriminator is removed from both OrchestrationSessionCaller and resolveOrchestrationSessionCaller, so the gate is now simply "the request carries a session caller". The old "a session held by its terminal view runs in a PTY and may still wait" carve-out was dead: production never writes a tui lease (the terminal handoff is removed; tui is decoded only from older-build records and normalized), so every structured session runs turn by turn. Terminal agents still block normally, and the refusal stays in the structured-runtime passthrough set.
  • Tests and guides follow the contract change — a structured-worker refusal case replaces the deleted terminal-view waiter test in orchestration-check-wait-session.test.ts; the consumer_fenced-while-waiting case in orchestration-session-coordinator.test.ts is deleted because a session can no longer register a waiter (that fencing path remains covered by the dispatch/legacy fencing suites); PARTY_NAMING_FIELDS grows to include sessionId; coordinator-loop.md drops the terminal-view wording and messaging-and-gates.md records that a chat is reachable by send but refused as a Dispatch assignee.

I read the commit's raw diff and each touched file at HEAD, confirmed resolveOrcaSessionParty derives the same lineage root the previous path did, and confirmed no production writer produces a tui lease. At this head the five delta suites pass (101 tests), config/scripts/orchestration-skill-guidance.test.mjs passes (29), pnpm tc:node/tc:cli/tc:web are clean, and verify:bundled-skill-guides / verify:skill-bundle-manifest exit 0. Prior pullfrog reviews carry no inline threads, so nothing needed retiring.

ℹ️ The PR description's Architecture review §1 still describes the superseded check --wait gate

The code now refuses check --wait from any session caller, but the description's "Architecture review" item 1 still says the session caller "carries its lease's runtimeKind" and that "a session held by its terminal view runs in a PTY and may still wait". A reviewer reading the description alone would infer the opposite of the shipped behavior; the commit message states the new contract, so only the PR body needs the correction.

Technical details
# Align the PR description with the final `check --wait` contract

## Affected sites
- PR body, "Architecture review" item 1 — claims `runtimeKind` is carried and a terminal-view session may wait; both were removed by `18baf737ba`.

## Required outcome
- Item 1 states that `orchestration.check` refuses `wait: true` for any session caller (a `consumer_fenced`/`stable_pane_required`-style fail-closed gate with the turn-loop recovery), and that only a terminal agent, which carries no session id, may block.

## Open questions for the human
- None — this is a description edit only, no code change.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 force-pushed the brennanb2025/d5-self-address branch from 18baf73 to cad7778 Compare September 25, 2026 21:59

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — a couple of minor suggestions inline.

Reviewed changes

Since the prior pullfrog review (18baf737ba, rebased to b1554f7f7f), seven commits landed that swap two of the prior architecture-review mechanisms and simplify the agent-facing surface:

  • Replaced the session check --wait refusal with a host-side cap — session-caller-wait-cap.ts caps a structured session's blocking check --wait/ask to 6 s (Codex) or 100 s (Claude) and leaves a terminal caller uncapped; wait_requires_terminal and its passthrough entry are removed, and the consumer-fenced waiter test is restored now that sessions register waiters again.
  • Unified the worker preamble — one text for both modes, differing only by the address line; the chat-specific 5 s ask, turn-loop wording, "end your turn", and the ORCA_CLI_COMMAND invocation were deleted.
  • Made orca status's caller opaque — dropped kind and sessionId from the address and refusal shapes, and removed the chat-specific check spec notes plus the root-help address/ORCA_CLI_COMMAND lines.
  • Dropped every chat-specific instruction from the guide — the kernel and references name the address once and carry no session:<id>, /clear, or ORCA_CLI_COMMAND text; agent-facing-parity.test.ts pins chat↔terminal parity for the preamble, pointer, and guide.
  • i18n — the Copy Orchestration Address strings moved to the head of the native-chat block; no behavior change.

ℹ️ The PR description documents a design these commits replaced

The body still describes the intermediate design. §4 says the worker preamble invokes the CLI through structuredSessionCliInvocation ("$ORCA_CLI_COMMAND"), Architecture review item 1 describes the runtimeKind carve-out, and Notes lists wait_requires_terminal and a caller.sessionId. None of that ships: the preamble teaches bare orca, every session caller is capped, and the caller shape is opaque. "What works end to end" leans on the Codex ORCA_CLI_COMMAND result, so a reviewer reading the body alone would infer the opposite of the merged behavior. Please rewrite the affected sections (or restore the documented behavior).

Technical details
# Reconcile the PR body with the final shipped design

## Affected sites
- PR body §4 ("The worker preamble") — claims `structuredSessionCliInvocation` / `ORCA_CLI_COMMAND`; the final `deliver-worker-dispatch-preamble.ts` passes `runtime.getTerminalOrchestrationCliCommand(terminalHandle)`, and `preamble.ts` renders `orca`/`orca-dev`/`orca-ide`.
- PR body "Architecture review" items 1–2 — describe the `runtimeKind` carve-out and the contract-parity preamble; both were replaced by the wait cap and byte-parity.
- PR body "Notes" — lists `wait_requires_terminal` (removed from `errors.ts`) and `caller.sessionId` (removed from the caller shape).
- PR body "New tests" / "Ablations" — still enumerate the deleted chat-ask and refusal mechanisms.

## Required outcome
- The body describes the shipped mechanisms: a host-side cap for a session caller's blocking `check --wait`/`ask` (not a refusal), one preamble differing only by the address, and an opaque `caller`.

## Open questions for the human
- Was dropping the `ORCA_CLI_COMMAND` invocation from the preamble intentional? It matches the base branch (the final diff vs base does not contain it), but the skill stub added here (`skill-stubs/_shared/cli-resolution.md`) still tells chat sessions a bare `orca` can reach a different Orca.

ℹ️ Nitpicks

  • orca status's text refusal now prints caller: none (refused: <code>). null already means "no identity", so none for a session that carried an id but was refused reads as the opposite; refused (<code>) keeps the two distinguishable.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

…only

No mount passes both terminal-pane actions and an orchestration address: a
chat shown inside a terminal pane is that terminal's agent, copied by its
terminal ID. Drop the unreachable terminal-pane placement and its tests.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (7b7c90b), four commits landed on the branch (now merged onto main at e2b6a4c), simplifying the agent-facing address model back toward main's:

  • Removed the session-caller wait cap — session-caller-wait-cap.ts and its check/ask call sites are deleted, so a chat's blocking call waits the budget asked for like a terminal's; the prior inline thread is retired.
  • Made every agent's address its mailbox address — callerShow, sessionAddress, and the worker preamble now report mailboxAddressOf (a terminal/worker handle, or a chat's session:<lineage root>); the read-side agentVisibleOrchestrationAddress/withAgentVisibleAddresses re-spelling layer is gone, and dispatch previews spell the coordinator through the party resolver.
  • Reverted the check caller label to the CLI's environment — orchestrationCallerLabel is synchronous again (handle or injectedSessionAddress()), dropping the per-check host round trip.
  • Restricted Copy Orchestration Address to chat tabs — the unreachable terminal-pane placement and its tests are removed.

I read the incremental range-diff and each touched file at HEAD, and confirmed the mailboxAddressOf derivation yields the same address bindDeclaredCaller rewrites a caller param to. The changed suites pass at this head (orchestration-caller-show, orchestration-check-wait-session, orchestration-worker-mode-opacity, agent-facing-parity, orchestration-party-cli-address, orchestration-party-addressing, preamble; 74 tests), and pnpm tc:node/tc:cli/tc:web are clean. The prior inline thread on session-caller-wait-cap.ts:12-13 is addressed by the deletion and resolved.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

…n check reads

After a window reload a terminal agent keeps ORCA_TERMINAL_HANDLE=term_old while
its pane is reminted as term_new. callerShow reminted and advertised term_new,
but check, send and ask act as the carried handle and never remint, so mail
sent to the advertised address was never read by that agent. callerShow now
answers the carried handle with its liveness, and null for a pane key alone,
from which the mailbox verbs have no identity. Resolving terminal callers once
on the host for every verb is a separate follow-up.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (e2b6a4c27a), one commit (55ab34d55c) reversed the terminal ladder in orchestration.callerShow:

  • orca status now answers the carried handle instead of the pane remint — resolveTerminalCaller returns { address: ORCA_TERMINAL_HANDLE, live: resolveTerminalIdentity(handle).live } (live or not), and null when only a pane key is present; resolvePaneHandle (runtime.resolveTerminalPane) is deleted. The new rationale holds: these are the handles the mailbox verbs (check, send, ask) act as, which the CLI resolves from the environment without reminting — only the coordinator verbs (resolveCoordinatorTerminalHandle, validateEnvHandle: true) remint through terminal.resolvePane.
  • Tests updated to prove the advertised mailbox is read — the stale-handle case now inserts mail to the advertised handle and reads it through the real orchestration.check, asserting count: 1; a new case pins pane-key-only to null, and status-caller.test.ts flips that expectation accordingly.

I read the incremental range-diff and the touched files at HEAD, and traced the CLI's mailbox-verb caller resolution to confirm the coherence claim. The delta suites pass at this head (17 tests), and pnpm tc:node / tc:cli are clean. The sole prior inline thread (session-caller-wait-cap.ts:12-13) is already resolved.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

…mpt repro, and trim round-one leftovers

The reliability repro's fake worker parsed "Your coordinator's terminal handle
is:", which the preamble now spells "Your coordinator's address is:", so it
silently skipped worker_done; it accepts both. Dispatch and its dry-run go back
to main's coordinator line (their `from` is already bound at the entry); only
dispatch-show, whose `from` is unbound, resolves it. Also drops a stale
status-caller comment, trims the wait test to its one uncapped-wait case, and
reverts comment-only churn in the worker opacity test.
The guide grows by the one caller.address line; the parity test bounds the
kernel at main's length plus that line instead of forcing a reword.
…ion Address

Renders the pane-commands hook as a structured chat tab and selects the item:
it asks orchestration.sessionAddress with the tab's target and session id.
Also corrects the menu item's comment to what it copies.
Conflict in locales/en.json resolved as a JSON 3-way merge keeping both
sides' keys.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (55ab34d55c), three authored commits plus a merge of origin/main landed:

  • Reverted the dispatch and dry-run coordinator line to main's spelling — orchestration.dispatch and its --dry-run preview now pass params.from ?? 'coordinator' directly, because the dispatch entry already binds a session caller's from to its address (bindDeclaredCaller, keyed off ORCHESTRATION_CALLER_PARAM); only dispatchShow, whose from is not a caller param and so is unbound, still resolves through resolveOrchestrationParty. The revert is behavior-identical for every reachable caller, since a raw terminal or worker handle resolves to itself.
  • Restored the guide's worker obligation 1 to main's wording — the kernel now grows only by the single caller.address line; the parity test bounds it at 197 + 1 = 198 lines and the guide is 198. bundled-skill-guides.ts regenerated, and the verify:bundled-skill-guides gate passes.
  • Added a renderer test for the chat-tab menu action — renders useStructuredNativeChatPaneCommands as a structured chat tab and selects Copy Orchestration Address, asserting it asks the tab's host (orchestration.sessionAddress with the tab target and session id). The item is pinned to the chat-tab mount, matching useNativeChatContextMenu's showTerminalPaneActions === false gate. Also corrected the menu item's comment and taught the long-prompt repro to read the renamed coordinator line.

I verified the dispatch binding claim by tracing bindDeclaredCaller/bindDeclaredSessionAddress, confirmed the CLI's mailbox verbs (check/send/ask) send the carried handle while only coordinator verbs remint, and ran the eight touched suites (50 tests, pass), pnpm tc:node/tc:cli (clean), verify:bundled-skill-guides (exit 0), and oxlint on the changed files (0 findings).

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

bundled-skill-guides.ts conflicted (generated); regenerated from the merged
skill-guides sources. Main dropped the dispatch capability from the preamble
params (#23994) and added a guide line, so the parity test stops passing a
capability and bounds the kernel at main's new length plus the address line.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (fd0c2a12bd), the branch merged origin/main (3047353017) and adapted to two upstream changes; the PR's own feature content is unchanged.

  • Regenerated the bundled skill guide — origin/main added a line to skill-guides/orchestration.md; src/cli/bundled-skill-guides.ts was regenerated from the merged sources and the parity test's kernel bound moved to 198 + 1, matching the guide's 199 lines exactly under its <= assertion.
  • Dropped the dispatch capability from the preamble params — upstream removed the dispatch capability (#23994), so PreambleParams no longer declares dispatchCapability and the parity fixture stops passing one.
  • No other PR-authored content moved: the incremental range-diff is limited to these mechanical adaptations, so no feature behavior changed.

I read the incremental range-diff and the full raw diff end to end, and confirmed at HEAD that the merge preserved the PR's own changes. pnpm tc:node, tc:cli and tc:web are clean; verify:bundled-skill-guides exits 0; the parity/preamble/worker-mode-opacity suites (36), the caller-show/session-caller/party-addressing/status-caller suites (90), and the skill-guidance contract test (29) all pass. No open pullfrog review threads needed retiring.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: ready for your decision (not merged)

The problem. An agent running in Orca had no reliable way to learn its own orchestration address, the name other agents use to message it. It guessed from its environment or passed --terminal <handle>, which could name a stale handle or the wrong pane. A user had no way to copy a chat's address to hand to another agent.

What changes for you. orca status --json now shows every agent its own address as caller.address: session:<id> for a chat (the address it keeps across /clear), its handle for a terminal agent or a structured worker. The guide gains one line saying so. A worker's instructions state its own address and its coordinator's. A chat's right-click menu gains Copy Orchestration Address. A chat agent and a terminal agent run the same commands and wait the same way; only the address value differs.

Fixed during this review (head d7cd45d5e69; the PR is now 41 files, +1269/−36 against main, down from 57 files, +1722/−103):

  • The chat wait cap is removed. The PR capped a chat's check --wait and ask at 6 s for Codex and 100 s for Claude, assuming each provider kills a long shell command. Neither does. Default Codex's command tool yields and keeps the command running, and Claude Code moves a timed-out command to the background. So the cap only made a Codex chat coordinator re-run check every 6 s. Live QA confirms that a Claude chat's wait survives the 120 s Bash timeout and delivers the message exactly once.
  • One address per agent. The PR showed a structured worker as session:<id> by rewriting its stored structworker_… handle on some read paths. Other paths (its own send receipts, inbox, the dispatch previews) still showed the handle, so the same worker appeared under two names. Now every surface reports the address its mail is stored under, and the rewriting layer is deleted.
  • After a window reload, orca status advertised the pane's new terminal handle, while the agent's own check, send and ask still read the old one, so mail sent to the advertised address was never read. orca status now reports the handle those commands act as, with live from Orca's liveness check.
  • Smaller fixes:
    • A menu placement that no mount could ever render (a chat inside a terminal pane) is removed.
    • check no longer makes an extra host call just to print a label.
    • The guide differs from main by exactly one line.
    • A reliability-gate tool that parsed the renamed preamble line (tests/tools/repro-orchestration-long-prompt.mjs) is fixed.
    • A test now pins that the menu item is wired onto real chat tabs.

Deferred (all P3; none blocks):

  • Host-side terminal caller resolution for every command. After a window reload, orca status reports the carried handle as not live while the coordinator commands switch to the pane's new handle.
  • Storing mail by session id, after which structured workers could be session:<id> everywhere at once.
  • In a dev build, a structured worker's preamble can name orca instead of orca-dev. This is already on main.
  • Copy Orchestration Address with no chat host running: if the host that owns chat sessions isn't running, it can copy the chat's current id instead of its pre-/clear address. Hard to reach, because an open chat starts that host.
  • The SSH fallback orca status (used only when the host CLI cannot launch) omits caller.
  • dispatch-show --preamble --from session:<lost worker> now errors instead of echoing from back.
  • Menu placement: the menu item sits in the chat body's right-click menu (next to Copy and Paste), not the tab's menu.
  • Test gaps: two tests don't reach far enough. The check for chat-only guide text reads only the main guide file, not its reference files. The comparison test's stand-in host always answers orca, so it can't catch a dev build naming the wrong CLI.

QA observations that are not this PR's (already on main, noted for follow-up):

  • A chat that wakes itself after a background task shows no prompt bubble.
  • Plain check output omits the message body.
  • delivered_at stays null after a check --wait consumes a message.
  • The sidebar chat row disappears after /clear until the next turn.
  • A structured worker's tab is labelled "Claude Chat", like the user's own chat.

Verified:

  • Three review rounds (host, agent-facing text, renderer), an architecture challenge, a narrow check of the last fixes, and the readiness checklist. The checklist found no P0–P2 issues.
  • Typecheck (node, web, cli), 84 test files / 1005 tests, full lint and the verify scripts at 46ffb53c35. CI passes at d7cd45d5e69.
  • Live Electron QA on a separate Mac at fd0c2a12bd (screenshots in the PR body):
    • the menu copies the address, and the same address after /clear;
    • a chat's and a terminal's orca status report their own addresses;
    • a chat's uncapped wait survives Claude's 120 s timeout and delivers exactly once;
    • a structured worker's preamble, its orca status and the copy action all show one handle.
  • Grok was out of quota, so a Claude Opus agent drove the QA.

Not verified:

  • Codex chats live (the Codex behaviour comes from Codex's source and real Orca Codex session logs).
  • Linux, Windows and SSH by hand.
  • The later main merges were not re-run live; they don't touch the covered code.

Stacked #22972 must be restacked onto this head. It uses the removed cap and address-rewriting helpers.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — a few stale address-spelling references inline.

Reviewed changes

Since the prior pullfrog review (5370575704 @ 46ffb53c35), the branch merged origin/main (which renamed the orchestration address prefix session: → orca_session_id:) and added one test commit that follows the rename:

  • Merged main's address-prefix rename — ORCA_SESSION_ADDRESS_PREFIX is now orca_session_id: and the old session: spelling is retired and refused. The PR's producer and consumer paths already read the shared constant (session-recipient.ts, caller-show.ts, status-caller.ts, structured-session-orchestration-address.ts, agent-session-caller-env.ts), so no production change was required.
  • Aligned the two test expectations to the new spelling — status-caller.test.ts and orchestration-party-addressing.test.ts now expect orca_session_id:<id> and the "Orca session ID" refusal wording.

I read the incremental range-diff, the full PR diff, and the touched producer files at HEAD; ran the two delta suites plus the caller-show, session-caller, parity, mode-opacity, check-wait, structured-address and native-chat menu suites (111 tests, pass), and verify:rpc-params-catalog / verify:bundled-skill-guides exit 0. The delta has no PR-authored behavior change; the leftovers below are the only concrete items. The sole prior inline thread (session-caller-wait-cap.ts) is resolved.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

…terminal agents as main has them

Terminal agents keep main's exact wording: a terminal worker's preamble is
byte-identical to main's, and orca status prints nothing new for them. A
session is named by its Orca session ID (orca_session_id:<id>, its /clear
root's): a structured worker's preamble says "Your Orca session ID is: …"
and its commands use that ID, and a session coordinator is "Your
coordinator's Orca session ID is: …". orca status shows a session caller's
`caller.orcaSessionId`; callerShow answers null for anyone else. The chat
tab menu item becomes "Copy Orca Session ID" with a tooltip saying what the
ID is, and its toasts match. No agent-read text calls this ID an address.
A structured worker's mail is still keyed by its minted handle.
…from a CLI test

The node project cannot compile src/cli, so the guard over CLI help, specs
and status text moves to src/cli; both halves share one pattern. Also brings
two comments and the long-prompt repro's coordinator-line regex to the Orca
session ID wording.
… primitive's typography

Drops a restyle the design-system gate refuses on TooltipContent, keeps
"Agent" untranslated in the Japanese tooltip as that catalog does, and types
the test's tooltip mock without an assertion.
Comment on lines +27 to +29
return undefined
}
try {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Terminal caller address disappears When a terminal agent runs orca status --json, this early return omits caller because the agent has no injected session ID. Terminal agents therefore lose the way to discover and share their own orchestration handle, which the previous implementation reported along with its live state.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (5383701470 @ 01669930e4), three authored commits and two origin/main merges landed, renaming the agent's self-identity from an "orchestration address" to an "Orca session ID" and narrowing the feature to sessions:

  • orca status is now session-only — orchestration.callerShow dropped its terminal branch (and the runtime/evidence plumbing) and returns { caller: { orcaSessionId, live: true } } for a session or null otherwise; the CLI returns undefined without asking the host when the environment carries no ORCA_AGENT_SESSION_ID, so a terminal agent's status output is byte-identical to main.
  • Renamed the shared shapes — OrchestrationCallerSession{orcaSessionId,live}, CliStatusCaller without null, and orchestration.sessionAddress returning { orcaSessionId }; the human-readable status line key is now orcaSessionId:.
  • Preamble naming is kind-aware — dispatchIdentityLines names a session by "Your coordinator's Orca session ID is:" / "Your Orca session ID is:" and leaves a terminal on main's wording with no self line; the new orcaSessionIdOrHandle resolves the coordinator in dispatch, dry-run, dispatchShow and worker preamble delivery, while a structured worker's mail stays keyed by its minted handle.
  • Menu rename — NativeChatCopyOrcaSessionIdMenuItem (with a tooltip and six-locale strings) and resolveStructuredSessionOrcaSessionId replace the address-named versions.
  • Wording guard — a new CLI test and parity block assert agent-read text (help, specs, status, guide/references, preambles, refusals) never calls the Orca session ID an "address".

I read the incremental range-diff and the full production sections at HEAD, and traced the session-caller binding (bindDeclaredCaller, resolveDeclaredCallerParty), mailboxAddressOf, and canonicalOrcaSessionId to confirm the orca status, sessionAddress, preamble and menu all agree. The 61 host/CLI delta tests and 12 renderer delta tests pass; tc:cli/tc:node/tc:web, verify:bundled-skill-guides, verify:rpc-params-catalog, verify:localization-catalogs and verify:skill-bundle-manifest all exit 0. The three prior inline nitpicks (stale session:<id> spellings) are addressed by the rename and were retired.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025

brennanb2025 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Review status after the Orca session ID wording change: ready for your decision (not merged; live QA passed)

The problem. A chat agent had no reliable way to learn its own Orca session ID, the ID other agents use to message it. A user had no way to copy it. Before this change, the PR called that ID an "address" and showed terminal agents a new caller line, which went against the plan: every agent will eventually be called by its Orca session ID (orca_session_id:<id>), and terminal agents haven't moved yet.

What changes for you (head 1ce4007929, 46 files, +1435/−58; CI passes and the branch merges cleanly):

  • Chat agents: orca status --json shows a chat its own caller.orcaSessionId (orca_session_id:<id>), plus an orcaSessionId: text line. That ID is the one /clear keeps.
  • Terminal agents: orca status is exactly main's.
  • Worker instructions:
    • A worker running as a chat session is told "Your Orca session ID is: …".
    • A coordinator that is a session is named "Your coordinator's Orca session ID is: …"; a terminal coordinator keeps main's "terminal handle" line.
    • A terminal worker under a terminal coordinator gets main's instructions byte for byte.
  • Chat tab menu: Copy Orca Session ID, with the tooltip "Orca's ID for this chat, separate from agent CLIs' own session IDs. Agents use it to refer to each other through Orca." and the toasts "Orca session ID copied" / "Unable to copy Orca session ID". Translated in all six languages.
  • Wording: nothing agents read calls this ID an "address" or a bare "session ID".

Needs your eye:

  • A terminal worker whose coordinator is a chat now reads "Your coordinator's Orca session ID is: orca_session_id:…". The spec says terminal workers keep main's text, but main would print "Your coordinator's terminal handle is: orca_session_id:…", which calls an Orca session ID a terminal handle. Only that one line differs from main, and a fresh reviewer agreed the spec's naming rule requires it.
  • Known trade-off: a structured worker is told, and uses, orca_session_id:<id>, but its mail is still stored under its structworker_… handle. So check rows, receipts and worker lists still show the handle. Messages to either reach it, and its task completion and heartbeats settle correctly (verified by tests). This lasts until mail is stored by Orca session ID.
  • Help summaries: run-use, run-current and check now say "caller" instead of main's "terminal" for every agent. This changed earlier in this PR.

Deferred (P3):

  • On dispatch and worker start, the IDs are looked up after the dispatch record is created; this cannot fail today.
  • The orca status help says caller is omitted without an Orca session ID, but a refused session still prints its refusal.
  • The renderer-only method is still named orchestration.sessionAddress. It is unreleased, so renaming it is free now.
  • Earlier items: host-side terminal caller resolution; mail stored by Orca session ID; the dev-build CLI name, already on main; the menu item sits in the chat body's menu, not the tab's.

Verified:

  • The fixer implemented the change and ran 12 ablations, each of which failed its test.
  • Typechecks pass for node, cli and web, as do the wide (2,673 tests) and targeted (1,217 tests) runs, lint and all the verify scripts.
  • A fresh review found no P0–P2 issues. It confirmed:
    • a terminal worker's preamble is identical to main's across 24 input combinations;
    • a terminal agent's orca status is main's;
    • its own search found no "address" wording left for this ID;
    • the menu strings and translations are exact;
    • a structured worker using orca_session_id: in its commands still completes, sends heartbeats and asks correctly.

Live QA (passed, at 1ce4007929): Codex drove a dev build of this head on a separate Mac (M4Air), with an isolated home and profile and a hidden window. It used the Mac's existing Codex login, no credentials were copied, and the real ~/.codex/hooks.json and config.toml hashed identical before and after. Results (screenshots are embedded in the PR body):

  • A chat's right-click menu shows Copy Orca Session ID, with the exact tooltip.
  • Selecting it shows "Orca session ID copied".
  • It copies orca_session_id:claude_15647270_…, which equals the chat's own orca status --json caller.orcaSessionId.
  • A chat worker started by a terminal coordinator is told "Your coordinator's terminal handle is: term_…" and "Your Orca session ID is: orca_session_id:…".
  • A terminal worker received main's preamble byte for byte, with no Orca session ID line.
  • The terminal pane and tab menus are unchanged: Copy Terminal ID is still there, and there is no Copy Orca Session ID.

Not verified: keyboard focus showing the tooltip; Linux, Windows and SSH by hand; Codex chats as the product under test.

QA notes, not caused by this PR:

  • In a dev build, a structured worker's preamble says orca while a terminal worker's says orca-dev. This is already on main and deferred.
  • worker-stop on a terminal worker answered user_owned, not stopped. Not investigated.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Since the prior pullfrog review (1ce4007929 @ #5385918505), one authored commit landed:

  • Corrected the Orca session ID tooltip to the singular — NativeChatCopyOrcaSessionIdMenuItem's default tooltip string, the use-native-chat-context-menu assertion, and the en/es/fr catalogs now read "separate from the agent CLI's own session ID"; the ja/ko/zh strings already used the singular, so all six catalogs now agree. No behavior change.

use-native-chat-context-menu.test.tsx passes (7 tests) at this head. All three prior inline threads (stale session:<id> spellings) are resolved, so nothing needed retiring.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025
brennanb2025 merged commit 6e7e964 into main Oct 2, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant