diff --git a/src/main/runtime/orchestration/db.ts b/src/main/runtime/orchestration/db.ts index 173681e3e47..b6a8f3e3dab 100644 --- a/src/main/runtime/orchestration/db.ts +++ b/src/main/runtime/orchestration/db.ts @@ -7500,7 +7500,9 @@ export class OrchestrationDb { ) { return true } - return params.handle === dispatch.assignee_handle && !params.paneKey + return ( + params.handle === dispatch.assignee_handle && (!params.paneKey || !dispatch.assignee_pane_key) + ) } private findActiveDispatchForAssignee( diff --git a/src/main/runtime/rpc/methods/orchestration-send-dispatch-authority.test.ts b/src/main/runtime/rpc/methods/orchestration-send-dispatch-authority.test.ts index 484e29ad100..f08ce857a23 100644 --- a/src/main/runtime/rpc/methods/orchestration-send-dispatch-authority.test.ts +++ b/src/main/runtime/rpc/methods/orchestration-send-dispatch-authority.test.ts @@ -89,4 +89,30 @@ describe('orchestration.send Dispatch authority', () => { expect(db.getTask(task.id)?.status).toBe('dispatched') expect(db.getDispatchContextById(dispatch.id)?.status).toBe('dispatched') }) + + it.each(['escalation', 'decision_gate'] as const)( + 'accepts a matching legacy sender with a newly observed pane for %s', + async (type) => { + setup() + const task = db.createTask({ spec: 'legacy owned assignment' }) + db.createDispatchContext(task.id, 'term_legacy') + vi.mocked(runtime.getTerminalPaneKey).mockImplementation((handle) => + handle === 'term_legacy' ? 'tab_legacy:leaf_legacy' : harness.coordinatorPaneKey + ) + + const result = (await send({ + from: 'term_legacy', + type, + subject: 'Legitimate legacy control', + payload: JSON.stringify({ + taskId: task.id, + ...(type === 'decision_gate' ? { question: 'Proceed?' } : {}) + }) + })) as { message: { type: string }; lifecycle?: { action: string } } + + expect(result.message.type).toBe(type) + expect(result.lifecycle).toBeUndefined() + expect(db.getTask(task.id)?.status).toBe('dispatched') + } + ) })