Skip to content

feat(orchestration): let a structured chat run orchestration as itself - #22568

Open
brennanb2025 wants to merge 11 commits into
brennanb2025/d2-caller-resolverfrom
brennanb2025/d3-cli-injection
Open

brennanb2025 wants to merge 11 commits into
brennanb2025/d2-caller-resolverfrom
brennanb2025/d3-cli-injection

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 23, 2026

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 19 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1056 $\color{#cf222e}{\Huge{\mathbf{−}}}$​166 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​890
Prod 32 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​363 $\color{#cf222e}{\Huge{\mathbf{−}}}$​126 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​237

ELI5

A native chat now knows its own orchestration name. Orca gives every chat an id; this PR puts that id in the environment of everything the chat runs, and teaches the orca CLI to send it. So when a chat runs orca orchestration run-create or check, it acts as itself, instead of refusing or (worse) guessing another pane's terminal and eating that pane's mail. If the chat passes --from/--terminal naming someone else, the CLI refuses before sending anything. Terminal agents behave exactly as before.

What Changed

Third PR of the structured-chat orchestration stack, stacked on #22555. Supersedes #19648 (not closed here).

1. The id is injected into every structured session's child

  • structuredSessionChildIdentityEnv (renamed from structuredWorkerChildIdentityEnv, since it now covers every structured session) sets ORCA_AGENT_SESSION_ID to the Orca-minted session id. Both native launches build their env here:
    • native Claude: claude-structured-launch-resolution.ts;
    • native Codex: codex-structured-child-environment.ts.
  • Terminal view (the native → TUI handoff): ensureAgentSession passes the id in the terminal's spawn env when it runs under handoff authority (withStructuredSessionTerminalViewEnv).
    • It is not put in agentEnv, because the launch config persists. A later relaunch from it would replay the id without the handoff that binds the terminal to the session.
  • No fence travels with the id.
  • A structured worker keeps the structworker_ handle it was minted. For orchestration the id wins and the host maps it back to that handle (refactor(orchestration): resolve every caller to one orchestration actor #22555), so the worker still has one identity.
  • The host-boundary caveat is recorded where the id is injected: identity by session id assumes one machine and one user.

2. An ordinary chat can now reach the Orca CLI, by absolute path

  • On main, only a dispatched worker got ORCA_CLI_COMMAND and the PATH entry for this app's CLI. An ordinary chat inherited the ambient PATH. Its orca therefore resolved only if the user had installed the CLI globally, and on packaged Linux bare orca is GNOME's screen reader.
  • Every structured session now gets the same prependOrcaCliDirToChildPath treatment a PTY agent gets:
    • dev: userData/cli/bin;
    • packaged macOS/Windows: the bundled resources/bin;
    • packaged Linux: the bare-orca shim.
  • ORCA_CLI_COMMAND is the absolute launcher in that directory. prependOrcaCliDirToChildPath now returns the path:
    • dev: orca-dev (orca-dev.cmd on Windows);
    • packaged macOS: resources/bin/orca;
    • packaged Windows: resources/bin/orca.exe, the native launcher, because orca.cmd refuses message bodies;
    • packaged Linux: the shim's orca.
    • This was found by the live coordinator run in feat(orchestration): deliver worker results to a structured chat coordinator #22631. Codex runs every command as /bin/zsh -lc. The login profile (macOS path_helper, a user's .zprofile) rebuilds PATH and puts a global install ahead of the prepended directory. On the test machine bare orca became an older global CLI, which refused (safely, on the identity-less marker).
    • An agent resolves the CLI from ORCA_CLI_COMMAND first (the existing skill contract). An absolute path survives any shell's startup files, on every platform.
    • The PATH prepend stays, so bare orca still works in shells that read no profile.
  • Alternatives rejected:
    • Codex's shell_environment_policy.set.PATH is re-exported only when Codex wraps a command with its shell snapshot. When no snapshot applies (for example a cwd that differs from the snapshot's), the command runs as zsh -lc and the profile reorders PATH again.
    • allow_login_shell = false would drop every login-profile variable except PATH, which is all Orca hydrates.
    • A startup-file wrapper for non-interactive login shells has no bash equivalent, and none on Windows.
  • Remaining limit: a bare orca typed inside a login shell still resolves by the user's PATH. An older global Orca there refuses on the marker. A same-version or newer global CLI runs itself; which runtime it reaches was not verified.

3. One CLI precedence rule, in one place

  • resolveOrchestrationTerminalHandle (and resolveCoordinatorTerminalHandle) now check the injected id first. When it is present, the caller is the session:
    • they return undefined, so no caller param is sent;
    • nothing is resolved or guessed;
    • the envelope's orchestrationCompatibilityEvidence.agentSessionId carries the id, and the host binds the caller.
  • The caller flag is checked before any request:
    • a caller flag may restate the session: session:<id>, the bare id, or a structured worker's own structworker_ handle (the acceptance set refactor(orchestration): resolve every caller to one orchestration actor #22555's host uses);
    • any other value is refused with consumer_fenced: "This command runs as agent session <id>, so --from <x> would act as a different caller. Drop --from: … No request was sent." That includes the terminal view's own pane handle.
  • Because the rule lives in the shared resolver, all 16 CLI verbs whose request names its caller get it: run-create, run-use, run-current, check, send, reply, ask, dispatch, gate-create, gate-resolve, gate-list, task-create, task-list, task-update, worker-start, worker-list.
    • reply and worker-list, which fix: route native chat orchestration by agent session identity #19648 left guessing, are covered with no per-handler code.
    • gate-list --run and task-list --run need no caller and skip the resolver. They still run the conflict check (refuseConflictingSessionCaller), so a conflicting --from is refused there too, never dropped. Terminal callers on that branch are unchanged.
  • A session never presents a pane as its identity: check sends no terminalPaneKey and send sends no senderPaneKey under a session.
  • dispatch-show --preamble: its --from only fills the preview text and names no caller, so it passes through unfenced. A flagless preview under a session writes the address the real dispatch writes: session:<id>, or a worker's handle.
  • The envelope reads the id from the CLI's own environment only (createOrchestrationCompatibilityEnvelope). The SSH paths build evidence from a remote shell's environment, where a session id can never name a session on this host.
  • Host refusals (session_caller_*, refactor(orchestration): resolve every caller to one orchestration actor #22555) pass through verbatim, including the worker-without-identity refusal. worker-list does not widen one into an unscoped listing: the list call is refused the same way.

4. Where the id is stripped

  • SSH: buildHostCliEnv deletes ORCA_AGENT_SESSION_ID (and the marker) from the host env it spreads into a remote command's CLI. A remote command never claims a local session. REMOTE_CONTEXT_ENV_VARS already never forwarded it from the remote side.
  • Inherited PTY env: an Orca launched inside a structured session inherits that session's id, and every pane would present it as its caller.
    • It is stripped through the existing "inherited agent-session stamps" mechanism, which already strips Claude's child-session stamps: main computes envToDelete for keys the caller did not set explicitly.
    • That list covers the local provider, the daemon (including an older relocated daemon) and the SSH relay.
    • A terminal view's explicit id is kept.
  • WSL: a terminal view running in a WSL shell carries the id into the guest (ORCA_AGENT_SESSION_ID/u in WSLENV), beside the WSL host stamp. refactor(orchestration): resolve every caller to one orchestration actor #22555 then refuses the claim, naming the host boundary. Without it, the pane handle would silently become that chat's caller inside WSL.

5. The ORCA_STRUCTURED_SESSION marker
Kept, and still written beside the id.

  • A current CLI checks the id first, so a session that has an id is never treated as identity-less. A test sets both and checks that check acts as the session.
  • The marker is written for a CLI that predates the id: one a chat can reach through a global install when a shell rc resets PATH.
  • The reader keeps main's refusal and wording for the opposite case: a child of a host that predates injection, which has the marker and no id.
  • A marker inherited by a PTY or by the SSH passthrough is stripped along with the id.

Other

  • STRUCTURED_WORKER_HANDLE_PREFIX / isStructuredWorkerHandle moved to src/shared/structured-worker-handle.ts so the CLI uses the same definition. Main re-exports it, and the D1 actor codec uses it instead of its own literal.
  • A vitest setup file removes ORCA_AGENT_SESSION_ID and ORCA_STRUCTURED_SESSION inherited from whoever runs the suite. Without it, 37 existing CLI tests flip branch when the suite is run from a structured chat (measured by setting the id in the runner's env with and without the file).

Why

Ported from #19648 unchanged in intent:

  • the TUI handoff injection site (now in spawn env, not the persisted agentEnv);
  • the WSLENV entry for the id;
  • injecting the id for every session in the one env builder both providers call;
  • per handler: check suppresses the pane key under a session, and its output names the session; send's lifecycle guard accepts the id; ask's timed-out resume command omits --from for a session.

Changed from #19648:

Why the rule lives in the resolver: every verb that names a caller already asks resolveOrchestrationTerminalHandle. Putting the id check there means a verb cannot forget it, and the enumerated test below proves no verb guesses.

Linked Issue

None — part of the structured chat status/orchestration program. Supersedes #19648; stacked on #22555.

Visual Proof

N/A — no UI change. The change is child-process environment and CLI identity; see Testing for what was and was not run end to end.

Testing

  • I manually tested these changes locally (no Electron end-to-end run; see Not verified)
  • Automated tests added/updated

New and updated tests

  • src/cli/orchestration-session-caller-cli.test.ts, per verb, for the 16 caller-naming verbs, with the env of a chat in terminal view (id + its pane handle + pane key, and a sibling for the guess to find):
    • flagless acts as the session: no caller param, no pane key, no getTerminalHandle, no terminal.* RPC;
    • a conflicting flag is refused with consumer_fenced and zero RPCs, including the terminal view's own pane handle;
    • session:<id> and the bare id are accepted.
  • Real login shells: a temp HOME whose .zprofile and .bash_profile put a stand-in global orca first.
    • Under -lc, bare orca resolves to the global. This is the positive control: the profile really reorders PATH.
    • "$ORCA_CLI_COMMAND" resolves to this app's launcher.
    • Under a profile-less -c, bare orca stays on this app's CLI.
    • Both files are skipped on Windows.
    • Where each arm runs:
      • The bash arm (structured-session-cli-login-shell.test.ts) runs in every lane.
      • The zsh arm (structured-session-cli-login-shell.live-shell.test.ts) runs in the real-shell lane, which installs zsh. It is registered in pr.yml and excluded in unit-tests.yml. The ordinary Linux unit lane has no /bin/zsh, which is why it failed there with ENOENT.
    • The lane guard's real-zsh detector (pr-workflow-parallelism.test.mjs) now also matches a zsh spawned through the ProcessSpec program: field, which is how this test escaped it. Removing either the lane entry or the new detector branch turns the guard red.
  • Enumerated population with a positive control: all 30 CLI orchestration verbs run once.
    • With no identity, 17 guess a terminal (the 16 above plus dispatch-show --preamble). This proves the harness can see a guess.
    • With the id, 0 guess.
  • Also pinned there:
    • a structured worker restates its own handle but not another's;
    • a worker's worker_done is sent as the session;
    • id + old marker is never identity-less;
    • marker-only keeps main's refusal with no --from advice;
    • a terminal agent is unchanged;
    • the ask resume omits --from;
    • the dispatch-show preview address;
    • host refusals surface verbatim from check/run-current/worker-list, and JSON keeps orcaSessionId;
    • the envelope, including the WSL stamp beside the id.
  • Env propagation:
    • Claude: the resolver names the child by the Orca id over an overlay's id, and the spawned child (real scripted CLI) gets the session's id over one inherited by Orca itself;
    • Codex: builder output, plus a spawned real node child answering with its own env: id, ORCA_CLI_COMMAND, CLI dir first on PATH;
    • terminal view: ensureAgentSession under handoff passes the id in spawn env and not in launchConfig.agentEnv, and a plain resume has none;
    • PTY: an inherited id is stripped on local and daemon spawns, an explicit one is kept, and the SSH spawn's envToDelete includes it;
    • WSL: WSLENV carries ORCA_AGENT_SESSION_ID/u beside the host stamp;
    • SSH: buildHostCliEnv drops the host's id and never takes the remote's;
    • the env builder: chat and worker on packaged Linux/macOS/Windows and dev.

Ablations: 19 mechanisms, each deleted or reverted, each red. All 19 were re-run at head c0767e101a against the 14 reachable test files (358 tests). The CLI-rule rows (80/33/33) are unchanged. The harness asserts that each replacement matched exactly once.

Ablated mechanism Red tests
The CLI does not check the injected id first 80 (every per-verb case, the enumerated population, the worker, the preview)
A conflicting caller flag is not refused 33 (both refusal cases × 15 flag-carrying verbs, the worker's other handle, and the --run listings' flag)
The session's own spellings are not accepted 33 (both spellings × 15 verbs, the worker's own handle, and the --run listings' restated flag)
The envelope carries no id 2
check sends the terminal view's pane key 1
send sends the terminal view's pane key 1
The lifecycle send guard ignores the id 1
The ask resume command names --from 1
The dispatch-show preview ignores the session 1
The structured child gets no id 8 (Claude resolver, Codex builder and adapter, the spawned Codex child, the builder)
CLI reachability for workers only (main's behavior) 13 (every chat platform case, the Claude resolver, Codex, the spawned child, the login-shell cases)
The terminal view is spawned without the id 1
An inherited id is not stripped from PTY env 3 (local, daemon, SSH envToDelete)
The id is not passed into WSL 1
The SSH passthrough keeps the host's id 1
The marker is no longer written 4
ORCA_CLI_COMMAND is the bare name orca again 17 (every env assertion including the worker spawn env, plus the real zsh -lc and bash -lc cases)
gate-list --run drops a conflicting --from 1
task-list --run drops a conflicting --from 1

Separately, with the vitest setup file removed and ORCA_AGENT_SESSION_ID set in the runner's env, 37 of 61 tests in five existing CLI orchestration files go red. With the file present, all 61 pass.

Suites run at 2a688ed73a (env -u ORCA_STRUCTURED_SESSION npx vitest run --config config/vitest.config.ts src/main src/cli src/shared src/relay config/scripts):

  • 5,363 files / 54,512 tests: 53,778 passed, 708 skipped, 1 expected failure, and 25 failures. None is caused by this PR:
  • pnpm tc:node, tc:cli and tc:web are clean.
  • check-changed-code-quality: 0 findings. oxlint and oxfmt --check on the changed files are clean. audit:anti-slop is clean.
  • pnpm-lock.yaml is absent from every commit in the range, and no documentation files are added.

AI Disclosure

Review

  • Precedence in the shared resolver rather than per handler: does any caller-naming verb bypass resolveOrchestrationTerminalHandle? The enumerated test says no for all 30 verbs.
  • Refusing the terminal view's own pane handle as --from: consistent with the host, which refuses it too.
  • The marker decision (§5).

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

Can an ordinary structured chat run the CLI?

  • Before: only through a global install (/usr/local/bin/orca on this machine). On packaged Linux bare orca is not Orca at all.
  • After: yes on dev, packaged macOS, packaged Windows and packaged Linux, through the same PATH entry a PTY agent gets. This is unit-tested per platform, not run on a packaged build.
  • WSL: a native structured session never runs in WSL (the host scope excludes it). A terminal view in a WSL shell is refused by the host as cross-host.

Host boundaries:

Folder workspaces: unaffected; the id carries no workspace.

Mobile: no mobile code changed; mobile never sends a session claim. Mobile tests were not run.

Mixed versions:

  • New CLI + pre-refactor(orchestration): resolve every caller to one orchestration actor #22555 host. The host ignores the field, and the CLI sends no caller param. Nothing guesses a sibling, but only run-create/run-use/run-current fail their schema. The rest fall back to placeholder attribution on that host:
    • send and ask fall back to the sender unknown;
    • gates and dispatch fall back to the coordinator coordinator;
    • reply is attributed to the original message's recipient (params.from ?? original.to_handle, message-methods.ts on main);
    • a consuming check gets stable_pane_required.
  • The omit choice. Sending an explicit session:<id> would avoid those fallbacks, at the cost of writing a stray session: string as a terminal handle on an old host. I chose to omit.
  • Why the pairing is unlikely in practice: the id is injected only by a host that has this change, into its own children, whose PATH puts that host's CLI first. The launcher also binds that CLI to the host's userData.
  • Old CLI in a new chat: it reads no id and sees no handle, so it refuses on the marker, which is kept for exactly this case. It never guesses.

Not verified:

  • No Electron end-to-end run. No real structured chat ran orca orchestration … through the built CLI against a live app; the next PR in the stack carries the full end-to-end acceptance.
  • Packaged builds were not run (the PATH treatment and launcher paths are unit-tested per platform).
  • The login-shell fix was not re-proved live in the feat(orchestration): deliver worker results to a structured chat coordinator #22631 rig; that PR carries the live Codex coordinator run after it rebases.
  • Windows and PowerShell: the absolute orca.exe path is unit-tested only.
  • Orca's own terminal agents (PTY) run login shells too and are not changed here. Their orca still resolves by the profile's PATH order; that behavior predates this PR.
  • Windows, Linux, WSL and mobile were not run; all runs were on macOS.
  • The real-binary Claude tests (claude-structured-real-cli.test.ts, claude-tui-resume-real-binary.integration.test.ts) fail here identically at refactor(orchestration): resolve every caller to one orchestration actor #22555's head. They drive the installed claude binary.

@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 — one minor correctness edge inline.

Reviewed changes

  • Session id injected into every structured child. structuredWorkerChildIdentityEnv becomes structuredSessionChildIdentityEnv, setting ORCA_AGENT_SESSION_ID plus the CLI PATH entry for chats and workers alike; both native providers (Claude resolver, Codex builder) build their child env here.
  • Terminal view carries the same id. ensureAgentSession passes the id in spawn env via withStructuredSessionTerminalViewEnv, deliberately not in the persisted launchConfig.agentEnv.
  • CLI acts as the session. The shared resolver returns undefined when the injected id names the caller and refuses a conflicting caller flag with consumer_fenced before any request; all 16 caller-naming verbs inherit the rule, with a per-verb and a 30-verb enumerated test.
  • Envelope and stripping. The id rides orchestrationCompatibilityEvidence.agentSessionId; SSH host-CLI passthrough, inherited PTY env (local/daemon/relay), and WSL are handled, and the shared structworker_ handle helpers move to src/shared.
  • Tests. Per-verb and enumerated CLI coverage plus env-propagation tests spanning native Claude/Codex (including a spawned real child), terminal view, WSL, PTY inheritance, and SSH.

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

return undefined
}
const ownHandle = process.env.ORCA_TERMINAL_HANDLE
return isStructuredWorkerHandle(ownHandle) ? ownHandle : `session:${sessionId}`

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.

A structured worker running in terminal view carries the PTY pane handle in ORCA_TERMINAL_HANDLE, not the minted structworker_ handle (only the native chat child gets that), so this returns session:<id> rather than the worker's handle. The host binds that worker's caller to its structworker_ handle, so a flagless dispatch-show --preamble previews different coordinator text than the real dispatch writes, and --from <own structworker_ handle> is refused here even though the host accepts it. Low impact since session:<id> is a valid alias in both places, but it diverges from the PR's stated "a worker's handle" invariant, and the tests only cover a native-chat worker.

Technical details
# `injectedSessionAddress` mis-names a worker's terminal view

## Affected sites
- `src/cli/handlers/orchestration/terminal-identity.ts:211` — derives the address from `ORCA_TERMINAL_HANDLE`; a terminal view's value is the PTY pane handle.
- `src/cli/handlers/orchestration/dispatch-handlers.ts:49` — uses `injectedSessionAddress()` for the preview's coordinator text.
- `src/main/runtime/rpc/orchestration-session-caller.ts:121-125` — the host prefers `worker.handle` for `caller.address`, so real dispatch text and the accepted `--from` set include the `structworker_` handle.
- `src/main/runtime/orca-runtime-get-agent-session-execution-namespace.ts:178` — terminal view gets only the id, so the worker handle never reaches the CLI there.

## Required outcome
- The flagless address a session presents should equal the address the host binds. Either deliver the worker handle to the terminal view (a dedicated env var the CLI reads) or state that `session:<id>` is the canonical flagless address for a session in terminal view.

## Open questions for the human
- Is a dispatched worker ever handed off to terminal view in practice? If not, this is unreachable and only the docs/claim need adjusting.

@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 in this delta. The run-scoped caller-flag gap for gate-list/task-list is closed cleanly, with tests that fail against the previous code. The one open thread from the prior review — injectedSessionAddress() for a worker in terminal view — is untouched by these commits and remains open.

Reviewed changes

  • Added refuseConflictingSessionCaller to terminal-identity.ts. A session still validates the caller flag on a --run-scoped listing: it throws consumer_fenced before any RPC when --from names another actor, and returns undefined otherwise.
  • Routed gate-list --run and task-list --run through it. Both previously short-circuited to undefined when --run was present, so a conflicting --from on the run-scoped path was silently dropped instead of refused. They now match every other caller-naming verb.
  • Pinned the run-scoped rule. A per-command test asserts the flagless path sends no caller param, that another actor's handle is refused with consumer_fenced and zero RPCs, and that the session's own session:<id> spelling is accepted.

Pullfrog  | Fix it ➔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 structured-session-cli-login-shell.test.ts hardcodes /bin/zsh, which the default Linux unit-test shards do not have installed, so it will fail the required Unit-tests check. Verified locally: 2 of its 3 cases exit with spawn /bin/zsh ENOENT.

Reviewed changes

  • Named this app's CLI by absolute path. prependOrcaCliDirToChildPath now returns the launcher, and structuredSessionChildIdentityEnv sets ORCA_CLI_COMMAND to it (dev orca-dev, packaged resources/bin/orca / orca.exe, packaged Linux shim) instead of the literal 'orca', falling back only when there is no app environment.
  • Added a real-login-shell test. structured-session-cli-login-shell.test.ts sets a temp HOME whose profile prepends a stand-in global orca, then asserts bare orca resolves to the global and "$ORCA_CLI_COMMAND" resolves to this app for zsh -lc and bash -lc.
  • Updated env expectations. Claude, Codex, and identity-env tests now expect the absolute dev launcher.

The ORCA_CLI_COMMAND value is intentionally kept to the bare-name union when sent on the wire (resolveCompatibilityCliCommand, schema in orchestration-params.ts:45,125), while the locally printed resume commands use the absolute path and are quoted by renderCommand — both correct. The prior review's open injectedSessionAddress() thread is untouched by this commit.

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

Comment thread src/main/runtime/structured-session-cli-login-shell.test.ts Outdated

@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

  • Split the login-shell suite by shell. The zsh arm moved to a new structured-session-cli-login-shell.live-shell.test.ts; structured-session-cli-login-shell.test.ts keeps only the bash arm, so it no longer spawns a shell the ordinary unit lane lacks.
  • Extracted the shared setup. structured-session-login-shell-test-harness.ts holds the temp HOME, the stand-in global orca stubs, and the structuredSessionChildIdentityEnv wiring, consumed by both suites.
  • Wired the zsh arm into the real-shell lane. pr.yml adds the new file to the shell-contracts job and unit-tests.yml adds it to the shard --exclude list, so the required Unit-tests check no longer runs it.
  • Taught the lane guard to see a program-field zsh. realZshUsage in config/scripts/pr-workflow-parallelism.test.mjs gained a program:\s*['"](?:\/(?:usr\/)?bin\/)?zsh['"] alternative, and the new file joined shellContractFiles — the mechanism that let the test escape the zsh-install lane.

Verified locally on the zsh-less runner: the lane guard passes (19/19), the bash arm passes (2/2), and the new live-shell file fails only when run directly outside the exclude.

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

@brennanb2025
brennanb2025 force-pushed the brennanb2025/d2-caller-resolver branch from 22f54f2 to 3ace023 Compare September 24, 2026 10:59
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d3-cli-injection branch from 2d9dc67 to fef6854 Compare September 24, 2026 10:59
…ren and let the CLI act as it

Every structured session's child (native Claude, native Codex, and the terminal
view) carries ORCA_AGENT_SESSION_ID and reaches the Orca CLI. The CLI sends the id
in the orchestration envelope; when present it is the caller, and a caller flag
naming anyone else is refused before any request. The id is stripped from
inherited PTY env and from the SSH host-CLI passthrough, and crosses into WSL so
the host can refuse the cross-host claim.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d2-caller-resolver branch from 3ace023 to f771efd Compare September 24, 2026 11:58
…ve Codex, the terminal view, WSL, PTY inheritance and SSH
…verb that names its caller

Adds the per-verb table (flagless acts as the session; a conflicting --from or
--terminal is refused before any request; the session's own spellings are
accepted), the enumerated guess population with its positive control, the
structured worker's own handle, the identity-less refusal for an older child,
the unchanged terminal agent, and the envelope. dispatch-show's --from only fills
preview text, so it passes through unfenced and a session's flagless preview
names the address the real dispatch writes.
…LIs that predate it

A CLI older than the id, reached through a global install when a shell rc resets
PATH, would otherwise guess a sibling's terminal in a chat that no longer carries
the marker. It refuses on the marker instead; a current CLI checks the id first,
so the marker never makes a session with an id identity-less.
…-list scoped by --run

A --run listing needs no caller, so both handlers skipped the resolver and a
--from naming another actor was dropped silently under a session. The conflict
check now runs on that branch too; terminal callers are unchanged.
…ured session's login shells

A provider can run each command in a login shell: Codex runs zsh -lc, and the
profile rebuilds PATH, putting a global install (possibly an older Orca) ahead of
the directory Orca prepended. ORCA_CLI_COMMAND, which an agent resolves the CLI
from first, is now the absolute launcher in that directory (the native launcher
on Windows), so no shell's startup files can swap it. The PATH prepend stays for
shells that read no profile. Found by the live coordinator run of the next PR.
…ne that installs zsh

The ordinary Linux unit lane has no /bin/zsh, so the zsh arm failed there with
ENOENT. It moves to a live-shell file registered in the shell-contracts lane; the
bash arm keeps running in every lane. The lane guard's detector now also sees a
zsh spawned through the ProcessSpec program field, which is how this test
escaped it.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/d3-cli-injection branch from fef6854 to 3af56b1 Compare September 24, 2026 11:58

This branch has not been deployed

No deployments
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