From a5bf307cbca9e3a0d10a9fc4e3f5e89ee957f10b Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Sat, 5 Sep 2026 14:35:26 -0700 Subject: [PATCH] fix(orchestration): stop claiming a structured worker was checked for a prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit worker-show reported observation.agentWait: null for every structured worker. The field's own contract says null means Orca looked and found no wait, and absent means it never looked — and nothing looks here: a structured worker parks on a journal question item, which no terminal prompt scan can see. So null was a false negative on the one field a coordinator is explicitly told to read, and it was mode-dependent: the same worker as a PTY would have reported the wait. Absent is both the honest value and a state a PTY worker already reaches (an older host, an unreadable pane, a probe that did not answer), so it discloses nothing about which mode ran. --- .../orchestration-worker-mode-opacity.test.ts | 21 +++++++++++++++++++ .../orchestration-worker-observation.ts | 8 +++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/main/runtime/rpc/methods/orchestration-worker-mode-opacity.test.ts b/src/main/runtime/rpc/methods/orchestration-worker-mode-opacity.test.ts index 0412043d072..e7cd8c24da0 100644 --- a/src/main/runtime/rpc/methods/orchestration-worker-mode-opacity.test.ts +++ b/src/main/runtime/rpc/methods/orchestration-worker-mode-opacity.test.ts @@ -22,6 +22,7 @@ import { } from '../../structured-worker-identity' import { ORCHESTRATION_METHODS } from './orchestration' import { readStructuredWorkerOutput } from './orchestration-structured-worker-lifecycle' +import { inspectWorkerTerminal } from './orchestration-worker-observation' const WORKTREE = 'repo::wt' const STRUCTURED_HANDLE = 'structworker_worker' @@ -257,4 +258,24 @@ describe('a worker cannot tell which mode it is running in', () => { expect(read).toThrow(/--source auto or --source transcript/) expect(read).not.toThrow(/structured/i) }) + + it('never claims a structured worker was checked for a human-answerable prompt', async () => { + installStructuredCoordinator(STRUCTURED_HANDLE, 'sess_worker') + vi.spyOn(runtime, 'showTerminal').mockResolvedValue({ + handle: 'term_coord', + worktreeId: WORKTREE, + status: 'running' + } as never) + const started = await startWorker({ + settings: STRUCTURED_DEFAULT, + from: 'term_coord', + coordinatorPaneKey + }) + + const observation = await inspectWorkerTerminal(runtime, db, started.dispatchId) + + // Absent, not null: null is the contract's "looked and found none", and a journal question is + // invisible to every prompt scan, so null would be a false negative a coordinator acts on. + expect('agentWait' in observation).toBe(false) + }) }) diff --git a/src/main/runtime/rpc/methods/orchestration-worker-observation.ts b/src/main/runtime/rpc/methods/orchestration-worker-observation.ts index fb0529d6fd9..369857c8e81 100644 --- a/src/main/runtime/rpc/methods/orchestration-worker-observation.ts +++ b/src/main/runtime/rpc/methods/orchestration-worker-observation.ts @@ -35,6 +35,11 @@ export async function inspectWorkerTerminal( if (structured) { // Exactness is the recorded pane and lineage, which the runtime getters answer from the // structured registry; there is no terminal to show. + // + // `agentWait` is deliberately ABSENT rather than null. Null is the contract's "Orca looked and + // found no wait", and nothing here looks: a structured worker parks on a journal question item, + // which no terminal prompt scan can see. Reporting null would tell a coordinator the worker is + // not waiting, which is the one thing the field's own documentation forbids inferring. const exact = db.isDispatchProcessCurrent({ dispatchId, paneKey: structured.paneKey, @@ -45,8 +50,7 @@ export async function inspectWorkerTerminal( terminal: null, exact, status: exact ? observation.status : 'identity_changed', - ...(exact && observation.reason ? { reason: observation.reason } : {}), - agentWait: null + ...(exact && observation.reason ? { reason: observation.reason } : {}) } } const terminal = await runtime.showTerminal(terminalHandle).catch(() => null)