From e0431071048bc136bc7bacb4fe69bb3abf91de1d Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Sat, 5 Sep 2026 01:26:09 -0700 Subject: [PATCH] fix(orchestration): redrive resumed run by stable pane --- .../orchestration/mailbox-delivery-target.ts | 12 +++-- .../mailbox-statusless-codex-delivery.test.ts | 49 +++++++++++++++++-- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/main/runtime/orchestration/mailbox-delivery-target.ts b/src/main/runtime/orchestration/mailbox-delivery-target.ts index 3e47b020ff0..b8ba47614c1 100644 --- a/src/main/runtime/orchestration/mailbox-delivery-target.ts +++ b/src/main/runtime/orchestration/mailbox-delivery-target.ts @@ -22,15 +22,17 @@ export class OrchestrationMailboxDeliveryTarget { const db = this.deps.getDb() const runId = handle.startsWith('run:') ? handle.slice('run:'.length) : '' const dispatchId = handle.startsWith('dispatch:') ? handle.slice('dispatch:'.length) : '' + const run = runId ? db?.getRun(runId) : undefined const dispatch = dispatchId ? db?.getDispatchContextById?.(dispatchId) : undefined const remote = dispatchId && !dispatch ? db?.getRemoteDispatchAttachment?.(dispatchId) : undefined - const paneKey = dispatch?.assignee_pane_key ?? remote?.pane_key + const paneKey = run?.coordinator_pane_key ?? dispatch?.assignee_pane_key ?? remote?.pane_key + const paneHandle = paneKey ? this.deps.getTerminalHandleForPaneKey(paneKey) : null const ownerHandle = runId - ? db?.getRun(runId)?.coordinator_handle - : ((paneKey ? this.deps.getTerminalHandleForPaneKey(paneKey) : null) ?? - dispatch?.assignee_handle ?? - remote?.terminal_handle) + ? paneHandle && this.deps.hasTerminalHandle(paneHandle) + ? paneHandle + : run?.coordinator_handle + : (paneHandle ?? dispatch?.assignee_handle ?? remote?.terminal_handle) return ownerHandle && this.deps.hasTerminalHandle(ownerHandle) ? ownerHandle : null } diff --git a/src/main/runtime/orchestration/mailbox-statusless-codex-delivery.test.ts b/src/main/runtime/orchestration/mailbox-statusless-codex-delivery.test.ts index a355e08baab..a5028deb83e 100644 --- a/src/main/runtime/orchestration/mailbox-statusless-codex-delivery.test.ts +++ b/src/main/runtime/orchestration/mailbox-statusless-codex-delivery.test.ts @@ -1,13 +1,15 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { InMemoryOrchestrationMessages, deferred } from '../orca-runtime-test-fixtures.spec' import type { OrchestrationDb } from './db' -import type { OrchestrationMailboxDeliveryTarget } from './mailbox-delivery-target' +import { OrchestrationMailboxDeliveryTarget } from './mailbox-delivery-target' import type { OrchestrationMailboxLeaf, OrchestrationMailboxOwner } from './mailbox-owner' import { OrchestrationMailboxPointerDelivery } from './mailbox-pointer-delivery' import type { SubmitStatuslessCodexPointer } from './mailbox-statusless-codex-submit' const MAILBOX = 'run:run-1' const TERMINAL_HANDLE = 'term-1' +const STALE_TERMINAL_HANDLE = 'term-slept' +const PANE_KEY = 'tab-1:leaf-1' function statuslessLeaf(): OrchestrationMailboxLeaf { return { @@ -25,6 +27,7 @@ function makeHarness( proveStatuslessCodexIdle: (terminalHandle: string, ptyId: string) => Promise, options: { withMessage?: boolean + useRemintedRunTarget?: boolean submitStatuslessCodexPointer?: SubmitStatuslessCodexPointer } = {} ) { @@ -34,17 +37,34 @@ function makeHarness( if (options.withMessage !== false) { db.insertMessage({ from: 'term-sender', to: MAILBOX, subject: 'wake work' }) } + if (options.useRemintedRunTarget) { + db.setRun({ + id: 'run-1', + coordinator_handle: STALE_TERMINAL_HANDLE, + coordinator_pane_key: PANE_KEY + }) + } const writePty = vi.fn().mockReturnValue(true) let delivery: OrchestrationMailboxPointerDelivery const redriveMailbox = vi.fn((mailboxHandle: string) => { delivery.deliverForHandle(mailboxHandle) }) + const deliveryTarget = options.useRemintedRunTarget + ? new OrchestrationMailboxDeliveryTarget({ + getDb: () => db as unknown as OrchestrationDb, + getTerminalHandleForPaneKey: (paneKey) => (paneKey === PANE_KEY ? TERMINAL_HANDLE : null), + hasTerminalHandle: (handle) => handle === TERMINAL_HANDLE, + canProbePtyLiveness: () => false, + controllerKnowsPtyIsLive: () => false, + isLeafPtyProvenAbsent: () => Promise.resolve(false) + }) + : ({ + resolveTerminalHandle: () => TERMINAL_HANDLE, + deferForAbsenceProbe: () => false + } as unknown as OrchestrationMailboxDeliveryTarget) delivery = new OrchestrationMailboxPointerDelivery({ mailboxOwner: { resolve: () => MAILBOX } as unknown as OrchestrationMailboxOwner, - deliveryTarget: { - resolveTerminalHandle: () => TERMINAL_HANDLE, - deferForAbsenceProbe: () => false - } as unknown as OrchestrationMailboxDeliveryTarget, + deliveryTarget, getDb: () => db as unknown as OrchestrationDb, getLeaf: () => leaf, getLeafKey: (tabId, leafId) => `${tabId}:${leafId}`, @@ -259,6 +279,25 @@ describe('statusless Codex mailbox pointer delivery', () => { expect(harness.db.getUnreadMessages(MAILBOX)[0]?.delivered_at).toEqual(expect.any(String)) }) + it('redrives a resumed run through its stable pane after the terminal handle remints', async () => { + const submitStatuslessCodexPointer = vi + .fn() + .mockRejectedValueOnce(new Error('foreground_not_ready')) + .mockResolvedValueOnce() + const harness = makeHarness(() => Promise.resolve('pty-1:incarnation-1'), { + submitStatuslessCodexPointer, + useRemintedRunTarget: true + }) + + harness.delivery.deliverForHandle(TERMINAL_HANDLE) + await vi.waitFor(() => expect(submitStatuslessCodexPointer).toHaveBeenCalledTimes(1)) + await vi.advanceTimersByTimeAsync(1_000) + await vi.waitFor(() => expect(submitStatuslessCodexPointer).toHaveBeenCalledTimes(2)) + + expect(harness.redriveMailbox).toHaveBeenCalledWith(MAILBOX, undefined) + expect(harness.db.getUnreadMessages(MAILBOX)[0]?.delivered_at).toEqual(expect.any(String)) + }) + it('bounds a permanent structured submission failure to one retry', async () => { const submitStatuslessCodexPointer = vi .fn()