From cc3a18cd910d8e8a8ae68bc983fa9cf477d75f80 Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Tue, 8 Sep 2026 16:04:11 -0700 Subject: [PATCH] propagate native session identity through CLI orchestration --- .../handlers/orchestration/gate-handlers.ts | 19 ++++++++++---- .../handlers/orchestration/task-handlers.ts | 25 +++++++++++++------ .../orchestration/terminal-identity.ts | 9 +++++++ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/cli/handlers/orchestration/gate-handlers.ts b/src/cli/handlers/orchestration/gate-handlers.ts index f9ec4c6583f..280b09a4ac4 100644 --- a/src/cli/handlers/orchestration/gate-handlers.ts +++ b/src/cli/handlers/orchestration/gate-handlers.ts @@ -2,7 +2,7 @@ import type { CommandHandler } from '../../dispatch' import { printResult } from '../../format' import { getOptionalJsonFlag, getOptionalStringFlag, getRequiredStringFlag } from '../../flags' import { callOrchestrationMutation } from './mutation-request' -import { resolveCoordinatorTerminalHandle } from './terminal-identity' +import { orchestrationSessionPayload, resolveCoordinatorTerminalHandle } from './terminal-identity' export const ORCHESTRATION_GATE_HANDLERS: Record = { 'orchestration gate-create': async ({ flags, client, cwd, json }) => { @@ -13,7 +13,9 @@ export const ORCHESTRATION_GATE_HANDLERS: Record = { question: getRequiredStringFlag(flags, 'question'), options: getOptionalJsonFlag(flags, 'options'), // Why: gates are Run-scoped, so the coordinator handle is the authorized caller identity. - from: await resolveCoordinatorTerminalHandle(flags, cwd, client) + ...(orchestrationSessionPayload().agentSessionId + ? orchestrationSessionPayload() + : { from: await resolveCoordinatorTerminalHandle(flags, cwd, client) }) }) printResult( result, @@ -29,7 +31,9 @@ export const ORCHESTRATION_GATE_HANDLERS: Record = { }>(client, flags, 'orchestration.gateResolve', { id: getRequiredStringFlag(flags, 'id'), resolution: getRequiredStringFlag(flags, 'resolution'), - from: await resolveCoordinatorTerminalHandle(flags, cwd, client) + ...(orchestrationSessionPayload().agentSessionId + ? orchestrationSessionPayload() + : { from: await resolveCoordinatorTerminalHandle(flags, cwd, client) }) }) printResult(result, json, (value) => `Gate ${value.gate.id} resolved: ${value.gate.resolution}`) }, @@ -37,7 +41,11 @@ export const ORCHESTRATION_GATE_HANDLERS: Record = { 'orchestration gate-list': async ({ flags, client, cwd, json }) => { const run = getOptionalStringFlag(flags, 'run') // Why: named runs remain inspectable without a pane; only implicit runs resolve identity. - const from = run ? undefined : await resolveCoordinatorTerminalHandle(flags, cwd, client) + const session = orchestrationSessionPayload() + const from = + run || session.agentSessionId + ? undefined + : await resolveCoordinatorTerminalHandle(flags, cwd, client) const result = await client.call<{ gates: { id: string; task_id: string; question: string; status: string }[] count: number @@ -46,7 +54,8 @@ export const ORCHESTRATION_GATE_HANDLERS: Record = { task: getOptionalStringFlag(flags, 'task'), status: getOptionalStringFlag(flags, 'status'), run, - from + from, + ...session }) printResult(result, json, (value) => { if (value.gates.length === 0) { diff --git a/src/cli/handlers/orchestration/task-handlers.ts b/src/cli/handlers/orchestration/task-handlers.ts index c4c943261e8..5e6b7c435dd 100644 --- a/src/cli/handlers/orchestration/task-handlers.ts +++ b/src/cli/handlers/orchestration/task-handlers.ts @@ -4,7 +4,7 @@ import { getOptionalStringFlag, getRequiredStringFlag } from '../../flags' import { RuntimeClientError } from '../../runtime-client' import { abbreviateOrchestrationTasks } from '../../../shared/orchestration-task-summary' import { callOrchestrationMutation } from './mutation-request' -import { resolveCoordinatorTerminalHandle } from './terminal-identity' +import { orchestrationSessionPayload, resolveCoordinatorTerminalHandle } from './terminal-identity' const TASK_STATUS_VALUES = [ 'pending', @@ -17,7 +17,10 @@ const TASK_STATUS_VALUES = [ export const ORCHESTRATION_TASK_HANDLERS: Record = { 'orchestration task-create': async ({ flags, client, cwd, json }) => { - const callerTerminalHandle = await resolveCoordinatorTerminalHandle(flags, cwd, client) + const session = orchestrationSessionPayload() + const callerTerminalHandle = session.agentSessionId + ? undefined + : await resolveCoordinatorTerminalHandle(flags, cwd, client) const result = await callOrchestrationMutation<{ task: { id: string; status: string } }>( client, flags, @@ -29,7 +32,8 @@ export const ORCHESTRATION_TASK_HANDLERS: Record = { deps: getOptionalStringFlag(flags, 'deps'), parent: getOptionalStringFlag(flags, 'parent'), run: getOptionalStringFlag(flags, 'run'), - callerTerminalHandle + callerTerminalHandle, + ...session } ) printResult(result, json, (r) => `Created ${r.task.id} [${r.task.status}]`) @@ -38,9 +42,11 @@ export const ORCHESTRATION_TASK_HANDLERS: Record = { 'orchestration task-list': async ({ flags, client, cwd, json }) => { const brief = flags.has('brief') const run = getOptionalStringFlag(flags, 'run') - const callerTerminalHandle = run - ? undefined - : await resolveCoordinatorTerminalHandle(flags, cwd, client) + const session = orchestrationSessionPayload() + const callerTerminalHandle = + run || session.agentSessionId + ? undefined + : await resolveCoordinatorTerminalHandle(flags, cwd, client) const result = await client.call<{ tasks: { id: string @@ -60,7 +66,8 @@ export const ORCHESTRATION_TASK_HANDLERS: Record = { ready: flags.has('ready') ? true : undefined, brief: brief ? true : undefined, run, - callerTerminalHandle + callerTerminalHandle, + ...session }) // Why: only older runtimes (no spec_truncated) skip server-side abbreviation and need this client-side fallback. const needsClientAbbreviation = @@ -106,7 +113,9 @@ export const ORCHESTRATION_TASK_HANDLERS: Record = { status, result: getOptionalStringFlag(flags, 'result'), run: getOptionalStringFlag(flags, 'run'), - callerTerminalHandle: await resolveCoordinatorTerminalHandle(flags, cwd, client) + ...(orchestrationSessionPayload().agentSessionId + ? orchestrationSessionPayload() + : { callerTerminalHandle: await resolveCoordinatorTerminalHandle(flags, cwd, client) }) } ) printResult(result, json, (r) => `Updated ${r.task.id} -> ${r.task.status}`) diff --git a/src/cli/handlers/orchestration/terminal-identity.ts b/src/cli/handlers/orchestration/terminal-identity.ts index 9b998489229..10d6c5abf58 100644 --- a/src/cli/handlers/orchestration/terminal-identity.ts +++ b/src/cli/handlers/orchestration/terminal-identity.ts @@ -59,6 +59,15 @@ export function resolveOrchestrationRuntimeFence(): string | undefined { return value && value.length > 0 ? value : undefined } +export function orchestrationSessionPayload(): { + agentSessionId?: string + runtimeFence?: number +} { + const agentSessionId = resolveOrchestrationAgentSessionId() + const fence = resolveOrchestrationRuntimeFence() + return agentSessionId && fence ? { agentSessionId, runtimeFence: Number(fence) } : {} +} + /** * Whether the handle this process was born with still names a live identity. *