From 2a8c0ca513a0b10e496dd674feefb35e5ce8f0bb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Jul 2026 01:19:32 -0400 Subject: [PATCH] refactor(agents): consolidate subagent lifecycle regression tests (#114326) --- .../subagent-registry-lifecycle.test.ts | 686 ++++-------------- src/agents/subagent-registry.test.ts | 261 ++----- 2 files changed, 203 insertions(+), 744 deletions(-) diff --git a/src/agents/subagent-registry-lifecycle.test.ts b/src/agents/subagent-registry-lifecycle.test.ts index 4aef89686edf..e7298b033dbc 100644 --- a/src/agents/subagent-registry-lifecycle.test.ts +++ b/src/agents/subagent-registry-lifecycle.test.ts @@ -26,6 +26,8 @@ import type { SubagentRunRecord } from "./subagent-registry.types.js"; import { createStructuredOutputTool } from "./tools/structured-output-tool.js"; type LifecycleControllerParams = Parameters[0]; +type LifecycleController = ReturnType; +type SubagentCompletionParams = Parameters[0]; function waitForLifecycleState(assertion: () => T | Promise): Promise { return vi.waitFor(assertion, { interval: 1 }); @@ -229,6 +231,21 @@ function createLifecycleController({ return createSubagentRegistryLifecycleController(params); } +function completeRun( + controller: LifecycleController, + entry: SubagentRunRecord, + overrides: Omit, "runId"> = {}, +) { + return controller.completeSubagentRun({ + runId: entry.runId, + endedAt: 4_000, + outcome: { status: "ok" }, + reason: SUBAGENT_ENDED_REASON_COMPLETE, + triggerCleanup: false, + ...overrides, + }); +} + async function runNoReplyMirrorScenario(params: { timestamp: number; text?: string; @@ -338,13 +355,7 @@ describe("subagent registry lifecycle hardening", () => { ); const controller = createLifecycleController({ entry, runSubagentAnnounceFlow }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect( @@ -378,13 +389,7 @@ describe("subagent registry lifecycle hardening", () => { }); const controller = createLifecycleController({ entry, runs }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(releaseDelete).toBeTypeOf("function")); expect(getActiveGatewayRootWorkCount()).toBe(1); @@ -414,13 +419,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(releaseBrowserCleanup).toBeTypeOf("function")); markGatewayRestartDraining(); releaseBrowserCleanup?.(); @@ -457,15 +456,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry, runs, persist, persistOrThrow, warn }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry)).resolves.toBeUndefined(); expect(warn).toHaveBeenCalledTimes(1); expect(persistOrThrow).toHaveBeenCalledTimes(1); @@ -497,15 +488,7 @@ describe("subagent registry lifecycle hardening", () => { }); const controller = createLifecycleController({ entry, persistOrThrow }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }), - ).rejects.toThrow("registry store boom"); + await expect(completeRun(controller, entry)).rejects.toThrow("registry store boom"); expect(entry).toEqual(original); expect(taskExecutorMocks.completeTaskRunByRunId).not.toHaveBeenCalled(); @@ -523,13 +506,7 @@ describe("subagent registry lifecycle hardening", () => { }), ), }); - const providerCompletion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + const providerCompletion = completeRun(controller, entry); await waitForLifecycleState(() => expect(finishCapture).toBeTypeOf("function")); const interruptedRecovery = controller.completeSubagentRun({ runId: entry.runId, @@ -563,13 +540,7 @@ describe("subagent registry lifecycle hardening", () => { }); const recovered = structuredClone(entry); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 4_001 }); expect(markSubagentRunPausedAfterYield({ entry, endedAt: 4_002 })).toBe(false); expect(entry).toEqual(recovered); @@ -775,15 +746,9 @@ describe("subagent registry lifecycle hardening", () => { }), }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }), - ).rejects.toThrow("subagent task projection did not finalize"); + await expect(completeRun(controller, entry, { endedAt: 4_001 })).rejects.toThrow( + "subagent task projection did not finalize", + ); expect(entry).toEqual(original); expect(persistOrThrow).not.toHaveBeenCalled(); @@ -815,13 +780,7 @@ describe("subagent registry lifecycle hardening", () => { }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 4_001 }); expect(taskExecutorMocks.completeTaskRunByRunId.mock.invocationCallOrder[0]).toBeLessThan( persistOrThrow.mock.invocationCallOrder[0]!, @@ -976,13 +935,7 @@ describe("subagent registry lifecycle hardening", () => { }); expect(entry.completion).toMatchObject({ resultText: null }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 4_001 }); expect(captureSubagentCompletionReply).toHaveBeenCalledOnce(); expect(entry.completion?.resultText).toBe( @@ -1017,11 +970,9 @@ describe("subagent registry lifecycle hardening", () => { }); expect(entry.completion).toMatchObject({ resultText: null }); - await controller.completeSubagentRun({ - runId: entry.runId, + await completeRun(controller, entry, { endedAt: 4_001, outcome: { status: "timeout" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, triggerCleanup: false, }); @@ -1051,13 +1002,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply, }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 4_001 }); expect(captureSubagentCompletionReply).not.toHaveBeenCalled(); expect(entry.completion).toMatchObject({ @@ -1084,13 +1029,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply, }); - const success = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + const success = completeRun(controller, entry); await waitForLifecycleState(() => expect(captureSubagentCompletionReply).toHaveBeenCalledOnce(), ); @@ -1138,13 +1077,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply: vi.fn(async () => "premature terminal reply"), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); expect(runSubagentAnnounceFlow).toHaveBeenCalledOnce(); expect(entry.cleanupHandled).toBe(true); @@ -1182,13 +1115,7 @@ describe("subagent registry lifecycle hardening", () => { }); const controller = createLifecycleController({ entry, runs }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(entry.deleteCleanupDispatchedAt).toBeTypeOf("number")); expect(markSubagentRunPausedAfterYield({ entry, endedAt: 4_001 })).toBe(false); @@ -1212,13 +1139,7 @@ describe("subagent registry lifecycle hardening", () => { ); const controller = createLifecycleController({ entry, runs, runSubagentAnnounceFlow }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(entry.deleteCleanupDispatchedAt).toBeTypeOf("number")); expect(markSubagentRunPausedAfterYield({ entry, endedAt: 4_001 })).toBe(false); @@ -1243,13 +1164,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply, }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(captureSubagentCompletionReply).toHaveBeenCalledOnce(), ); @@ -1294,13 +1209,7 @@ describe("subagent registry lifecycle hardening", () => { await waitForLifecycleState(() => expect(helperMocks.persistSubagentSessionTiming).toHaveBeenCalledOnce(), ); - const success = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const success = completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); await waitForLifecycleState(() => expect(helperMocks.persistSubagentSessionTiming).toHaveBeenCalledTimes(2), ); @@ -1342,13 +1251,7 @@ describe("subagent registry lifecycle hardening", () => { emitSubagentEndedHookForRun, }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); await waitForLifecycleState(() => expect(entry.cleanupCompletedAt).toBeTypeOf("number")); expect(runSubagentAnnounceFlow).not.toHaveBeenCalled(); @@ -1480,13 +1383,7 @@ describe("subagent registry lifecycle hardening", () => { }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); expect(entry).toMatchObject({ endedAt: 4_000, @@ -1509,13 +1406,7 @@ describe("subagent registry lifecycle hardening", () => { const original = structuredClone(entry); const controller = createLifecycleController({ entry }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); expect(entry).toEqual(original); expect(taskExecutorMocks.completeTaskRunByRunId).not.toHaveBeenCalled(); @@ -1536,13 +1427,7 @@ describe("subagent registry lifecycle hardening", () => { resolveSubagentTask: () => ({ lookup: "unavailable" }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); expect(entry).toMatchObject({ endedAt: 4_000, @@ -1569,13 +1454,7 @@ describe("subagent registry lifecycle hardening", () => { resolveSubagentTask: () => ({ lookup: "unavailable" }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 4_001 }); expect(entry).toMatchObject({ endedAt: 4_001, @@ -1606,15 +1485,9 @@ describe("subagent registry lifecycle hardening", () => { }), }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }), - ).rejects.toThrow("registry store boom"); + await expect(completeRun(controller, entry, { endedAt: 4_001 })).rejects.toThrow( + "registry store boom", + ); expect(entry).toEqual(original); expect(taskExecutorMocks.completeTaskRunByRunId).toHaveBeenCalledTimes(1); @@ -1652,13 +1525,7 @@ describe("subagent registry lifecycle hardening", () => { }), }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); await waitForLifecycleState(() => expect(captureSubagentCompletionReply).toHaveBeenCalled()); expect(entry).toMatchObject({ endedAt: 4_000, @@ -1720,13 +1587,7 @@ describe("subagent registry lifecycle hardening", () => { ); cancellationStable = true; - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_001, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { endedAt: 4_001, triggerCleanup: true }); finishSessionTiming?.(); await killed; @@ -1760,13 +1621,7 @@ describe("subagent registry lifecycle hardening", () => { }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 3_999, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 3_999 }); expect(entry).toMatchObject({ endedAt: 3_999, @@ -1871,13 +1726,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 3_999, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { endedAt: 3_999, triggerCleanup: true }); expect(retireSupersededRun).toHaveBeenCalledWith(entry.runId, entry); expect(runs.has(entry.runId)).toBe(false); @@ -1934,13 +1783,7 @@ describe("subagent registry lifecycle hardening", () => { retireSupersededRun, }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 3_999, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry, { endedAt: 3_999 }); expect(resolveSubagentTask).toHaveBeenCalledTimes(2); expect(observedSupersededAt).toEqual([5_000, 5_000]); @@ -1971,13 +1814,7 @@ describe("subagent registry lifecycle hardening", () => { }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => { expect(taskExecutorMocks.setDetachedTaskDeliveryStatusByRunId).toHaveBeenCalledWith({ @@ -2001,13 +1838,7 @@ describe("subagent registry lifecycle hardening", () => { resolveSubagentTask: () => ({ lookup: "unavailable" }), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry); expect(taskExecutorMocks.completeTaskRunByRunId).toHaveBeenCalledWith( expect.objectContaining({ @@ -2037,13 +1868,7 @@ describe("subagent registry lifecycle hardening", () => { retireSupersededRun, }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(captureSubagentCompletionReply).toHaveBeenCalled()); const newer = createRunEntry({ runId: "run-2", createdAt: 5_000, startedAt: 5_000 }); runs.set(newer.runId, newer); @@ -2073,13 +1898,7 @@ describe("subagent registry lifecycle hardening", () => { }); const controller = createLifecycleController({ entry, runs, retireSupersededRun }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(helperMocks.persistSubagentSessionTiming).toHaveBeenCalledOnce(), ); @@ -2105,13 +1924,7 @@ describe("subagent registry lifecycle hardening", () => { }); const controller = createLifecycleController({ entry }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); + await completeRun(controller, entry); expectFields(firstCallArg(taskExecutorMocks.completeTaskRunByRunId), { runId: entry.runId, @@ -2121,173 +1934,68 @@ describe("subagent registry lifecycle hardening", () => { }); }); - it("marks required progress-only completions blocked without failing the task", async () => { - const entry = createRunEntry({ - expectsCompletionMessage: true, - }); - - const controller = createLifecycleController({ - entry, - captureSubagentCompletionReply: vi.fn(async () => "I'll inspect the repo now."), - }); - - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); - - expectFields(firstCallArg(taskExecutorMocks.completeTaskRunByRunId), { - runId: entry.runId, - runtime: "subagent", - sessionKey: entry.childSessionKey, - progressSummary: "I'll inspect the repo now.", + it.each([ + { + name: "marks required progress-only completions blocked without failing the task", + reply: "I'll inspect the repo now.", terminalOutcome: "blocked", terminalSummary: "Required completion ended with progress-only text, not a final deliverable.", - }); - expect(taskExecutorMocks.failTaskRunByRunId).not.toHaveBeenCalled(); - }); - - it("marks missing required completions blocked while preserving real final reports", async () => { - const missingEntry = createRunEntry({ - expectsCompletionMessage: true, - }); - await createLifecycleController({ - entry: missingEntry, - captureSubagentCompletionReply: vi.fn(async () => undefined), - }).completeSubagentRun({ - runId: missingEntry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); - - expectFields(firstCallArg(taskExecutorMocks.completeTaskRunByRunId), { - runId: missingEntry.runId, + }, + { + name: "marks missing required completions blocked", + reply: undefined, terminalOutcome: "blocked", terminalSummary: "Required completion did not produce a final deliverable.", - }); - - taskExecutorMocks.completeTaskRunByRunId.mockClear(); - const finalEntry = createRunEntry({ - runId: "run-final", - expectsCompletionMessage: true, - }); - await createLifecycleController({ - entry: finalEntry, - captureSubagentCompletionReply: vi.fn( - async () => "Fixed the crash and verified the regression tests pass.", - ), - }).completeSubagentRun({ - runId: finalEntry.runId, - endedAt: 5_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); - - const finalArg = firstCallArg(taskExecutorMocks.completeTaskRunByRunId); - expectFields(finalArg, { - runId: finalEntry.runId, - runtime: "subagent", - sessionKey: finalEntry.childSessionKey, - progressSummary: "Fixed the crash and verified the regression tests pass.", + }, + { + name: "preserves real final completion reports", + reply: "Fixed the crash and verified the regression tests pass.", + terminalOutcome: undefined, terminalSummary: null, - }); - expect(finalArg.terminalOutcome).toBeUndefined(); - }); - - it("keeps required completions successful when final output follows progress text", async () => { - const entry = createRunEntry({ - expectsCompletionMessage: true, - }); - - await createLifecycleController({ - entry, - captureSubagentCompletionReply: vi.fn( - async () => "I'll inspect the repo now. The crash is a missing null check in src/foo.ts.", - ), - }).completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); - - const finalArg = firstCallArg(taskExecutorMocks.completeTaskRunByRunId); - expectFields(finalArg, { - runId: entry.runId, - runtime: "subagent", - sessionKey: entry.childSessionKey, - progressSummary: - "I'll inspect the repo now. The crash is a missing null check in src/foo.ts.", + }, + { + name: "keeps required completions successful when final output follows progress text", + reply: "I'll inspect the repo now. The crash is a missing null check in src/foo.ts.", + terminalOutcome: undefined, terminalSummary: null, - }); - expect(finalArg.terminalOutcome).toBeUndefined(); - }); - - it("keeps required completions successful when final output follows a separator", async () => { - const entry = createRunEntry({ - expectsCompletionMessage: true, - }); - - await createLifecycleController({ - entry, - captureSubagentCompletionReply: vi.fn( - async () => "I'll inspect the repo now - the crash is a missing null check in src/foo.ts.", - ), - }).completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); - - const finalArg = firstCallArg(taskExecutorMocks.completeTaskRunByRunId); - expectFields(finalArg, { - runId: entry.runId, - runtime: "subagent", - sessionKey: entry.childSessionKey, - progressSummary: - "I'll inspect the repo now - the crash is a missing null check in src/foo.ts.", + }, + { + name: "keeps required completions successful when final output follows a separator", + reply: "I'll inspect the repo now - the crash is a missing null check in src/foo.ts.", + terminalOutcome: undefined, terminalSummary: null, - }); - expect(finalArg.terminalOutcome).toBeUndefined(); - }); - - it("keeps required completions blocked when progress text only adds follow-up planning", async () => { - const entry = createRunEntry({ - expectsCompletionMessage: true, - }); - - await createLifecycleController({ - entry, - captureSubagentCompletionReply: vi.fn( - async () => "I'll inspect the repo now. Then I'll run tests and report back.", - ), - }).completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }); - - expectFields(firstCallArg(taskExecutorMocks.completeTaskRunByRunId), { - runId: entry.runId, - runtime: "subagent", - sessionKey: entry.childSessionKey, - progressSummary: "I'll inspect the repo now. Then I'll run tests and report back.", + }, + { + name: "keeps required completions blocked when progress text only adds follow-up planning", + reply: "I'll inspect the repo now. Then I'll run tests and report back.", terminalOutcome: "blocked", terminalSummary: "Required completion ended with progress-only text, not a final deliverable.", + }, + ])("$name", async ({ reply, terminalOutcome, terminalSummary }) => { + const entry = createRunEntry({ expectsCompletionMessage: true }); + await createLifecycleController({ + entry, + captureSubagentCompletionReply: vi.fn(async () => reply), + }).completeSubagentRun({ + runId: entry.runId, + endedAt: 4_000, + outcome: { status: "ok" }, + reason: SUBAGENT_ENDED_REASON_COMPLETE, + triggerCleanup: false, }); + + const finalArg = firstCallArg(taskExecutorMocks.completeTaskRunByRunId); + expectFields(finalArg, { + runId: entry.runId, + runtime: "subagent", + sessionKey: entry.childSessionKey, + ...(reply === undefined ? {} : { progressSummary: reply }), + terminalSummary, + }); + expect(finalArg.terminalOutcome).toBe(terminalOutcome); + expect(taskExecutorMocks.failTaskRunByRunId).not.toHaveBeenCalled(); }); it("does not reject cleanup give-up when task delivery status update throws", async () => { @@ -2339,15 +2047,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry, persist, runSubagentAnnounceFlow }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); const browserCleanupArg = firstCallArg( browserLifecycleCleanupMocks.cleanupBrowserSessionsForLifecycleEnd, @@ -2379,15 +2079,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry, persist, runSubagentAnnounceFlow }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); await waitForLifecycleState(() => expect(entry.delivery?.announcedAt).toBe(12_300)); expect(entry.delivery?.enqueuedAt).toBe(4_100); @@ -2423,13 +2115,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(getActiveGatewayRootWorkCount()).toBe(0)); const newer = createRunEntry({ runId: "run-2", @@ -2469,15 +2155,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry, persist, runSubagentAnnounceFlow }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); await waitForLifecycleState(() => expect(entry.cleanupCompletedAt).toBeTypeOf("number")); expect(entry.delivery?.status).toBe("delivered"); @@ -2509,15 +2187,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply: vi.fn(async () => "raw collector result"), }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); const browserCleanupArg = firstCallArg( browserLifecycleCleanupMocks.cleanupBrowserSessionsForLifecycleEnd, @@ -2549,13 +2219,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply: vi.fn(async () => "raw collector result"), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(entry.cleanupCompletedAt).toBeTypeOf("number")); await waitForLifecycleState(() => @@ -2650,13 +2314,7 @@ describe("subagent registry lifecycle hardening", () => { captureSubagentCompletionReply: vi.fn(async () => "raw collector result"), }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(entry.cleanupCompletedAt).toBeTypeOf("number")); expect(entry.collectorCompletion).toEqual({ @@ -2682,15 +2340,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); await waitForLifecycleState(() => expect(gatewayMocks.callGateway).toHaveBeenCalledWith({ @@ -2773,15 +2423,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); const retireArg = findCallArg( bundleMcpRuntimeMocks.retireSessionMcpRuntimeForSessionKey, @@ -2804,15 +2446,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); expect(bundleMcpRuntimeMocks.retireSessionMcpRuntimeForSessionKey).not.toHaveBeenCalled(); }); @@ -2828,11 +2462,9 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry, persist, runSubagentAnnounceFlow }); await expect( - controller.completeSubagentRun({ - runId: entry.runId, + completeRun(controller, entry, { endedAt: 4_250, outcome: { status: "timeout" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, triggerCleanup: true, }), ).resolves.toBeUndefined(); @@ -2863,15 +2495,7 @@ describe("subagent registry lifecycle hardening", () => { const controller = createLifecycleController({ entry, persistOrThrow }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_250, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { endedAt: 4_250 })).resolves.toBeUndefined(); expect(entry.outcome).toEqual({ status: "ok", @@ -2894,15 +2518,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow: vi.fn(async () => false), }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: false, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry)).resolves.toBeUndefined(); expect(captureSubagentCompletionReply).toHaveBeenCalledWith(entry.childSessionKey, { waitForReply: false, @@ -2964,15 +2580,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); expect(runSubagentAnnounceFlow).not.toHaveBeenCalled(); expect(typeof entry.cleanupCompletedAt).toBe("number"); @@ -2999,15 +2607,7 @@ describe("subagent registry lifecycle hardening", () => { emitSubagentEndedHookForRun, }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); expect(emitSubagentEndedHookForRun).toHaveBeenCalledTimes(1); expect(emitSubagentEndedHookForRun).toHaveBeenCalledWith({ @@ -3043,13 +2643,7 @@ describe("subagent registry lifecycle hardening", () => { emitSubagentEndedHookForRun, }); - const completion = controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + const completion = completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(emitSubagentEndedHookForRun).toHaveBeenCalled()); runs.set( "run-2", @@ -3223,15 +2817,7 @@ describe("subagent registry lifecycle hardening", () => { warn, }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); expect(warn).toHaveBeenCalledTimes(1); const [warning, warningFields] = firstCall(warn); @@ -3295,15 +2881,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); expectFields(firstCallArg(taskExecutorMocks.setDetachedTaskDeliveryStatusByRunId), { runId: entry.runId, @@ -3464,15 +3042,7 @@ describe("subagent registry lifecycle hardening", () => { runSubagentAnnounceFlow, }); - await expect( - controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }), - ).resolves.toBeUndefined(); + await expect(completeRun(controller, entry, { triggerCleanup: true })).resolves.toBeUndefined(); expect( browserLifecycleCleanupMocks.cleanupBrowserSessionsForLifecycleEnd, @@ -3797,13 +3367,7 @@ describe("requester settle wake trigger", () => { runSubagentAnnounceFlow, }); - await controller.completeSubagentRun({ - runId: entry.runId, - endedAt: 4_000, - outcome: { status: "ok" }, - reason: SUBAGENT_ENDED_REASON_COMPLETE, - triggerCleanup: true, - }); + await completeRun(controller, entry, { triggerCleanup: true }); await waitForLifecycleState(() => expect(settleWake).toHaveBeenCalledTimes(1)); // The no-wake decision completed, but the spawning turn can still yield. diff --git a/src/agents/subagent-registry.test.ts b/src/agents/subagent-registry.test.ts index 5e4438fc448c..2a335a8175e1 100644 --- a/src/agents/subagent-registry.test.ts +++ b/src/agents/subagent-registry.test.ts @@ -1603,115 +1603,67 @@ describe("subagent registry seam flow", () => { }); }); - it("keeps explicit run timeout terminal when late lifecycle success arrives", async () => { - const startedAt = Date.now(); - mockGatewayMethods(mocks.callGateway, { - "agent.wait": { status: "timeout" }, - }); - mocks.loadSessionStore.mockReturnValue( - createSessionStore({ - updatedAt: startedAt, - status: "running", - }), - ); - - mod.registerSubagentRun({ + it.each([ + { + name: "keeps explicit run timeout terminal when late lifecycle success arrives", runId: "run-timeout-late-lifecycle-ok", task: "timeout should stay terminal", - runTimeoutSeconds: 1, - }); - - await vi.advanceTimersByTimeAsync(10_000); - await waitForFast(() => { - const completedRun = findRequesterRun("run-timeout-late-lifecycle-ok"); - expect(completedRun?.endedAt).toBe(startedAt + 1_000); - expect(completedRun?.outcome?.status).toBe("timeout"); - }); - - const lifecycleHandler = getLifecycleHandler(); - - lifecycleHandler?.({ - runId: "run-timeout-late-lifecycle-ok", - stream: "lifecycle", - data: { - phase: "end", - endedAt: startedAt + 2_000, - }, - }); - - await waitForFast(() => { - const run = findRequesterRun("run-timeout-late-lifecycle-ok"); - expect(run?.endedAt).toBe(startedAt + 1_000); - expectRecordFields( - run?.outcome, - { - status: "timeout", - startedAt, - endedAt: startedAt + 1_000, - elapsedMs: 1_000, - }, - "late lifecycle timeout outcome", - ); - }); - await waitForFast(() => { - expect(mocks.runSubagentAnnounceFlow).toHaveBeenCalledTimes(1); - }); - }); - - it("keeps published explicit timeout stable when pre-deadline lifecycle success arrives late", async () => { - const startedAt = Date.now(); - mockGatewayMethods(mocks.callGateway, { - "agent.wait": { status: "timeout" }, - }); - mocks.loadSessionStore.mockReturnValue( - createSessionStore({ - updatedAt: startedAt, - status: "running", - }), - ); - - mod.registerSubagentRun({ + eventStartedAfterMs: undefined, + eventEndedAfterMs: 2_000, + expectCapturedReply: false, + }, + { + name: "keeps published explicit timeout stable when pre-deadline lifecycle success arrives late", runId: "run-timeout-late-lifecycle-predeadline-ok", task: "published timeout should stay stable", - runTimeoutSeconds: 1, - }); + eventStartedAfterMs: 10, + eventEndedAfterMs: 500, + expectCapturedReply: true, + }, + ])( + "$name", + async ({ runId, task, eventStartedAfterMs, eventEndedAfterMs, expectCapturedReply }) => { + const startedAt = Date.now(); + mockGatewayMethods(mocks.callGateway, { "agent.wait": { status: "timeout" } }); + mocks.loadSessionStore.mockReturnValue( + createSessionStore({ updatedAt: startedAt, status: "running" }), + ); + mod.registerSubagentRun({ runId, task, runTimeoutSeconds: 1 }); - await vi.advanceTimersByTimeAsync(5_000); - await waitForFast(() => { - const completedRun = findRequesterRun("run-timeout-late-lifecycle-predeadline-ok"); - expect(completedRun?.endedAt).toBe(startedAt + 1_000); - expect(completedRun?.outcome?.status).toBe("timeout"); - }); - - const lifecycleHandler = getLifecycleHandler(); - - lifecycleHandler?.({ - runId: "run-timeout-late-lifecycle-predeadline-ok", - stream: "lifecycle", - data: { - phase: "end", - startedAt: startedAt + 10, - endedAt: startedAt + 500, - }, - }); - - await waitForFast(() => { - const run = findRequesterRun("run-timeout-late-lifecycle-predeadline-ok"); - expect(run?.endedAt).toBe(startedAt + 1_000); - expectRecordFields( - run?.outcome, - { + await vi.advanceTimersByTimeAsync(5_000); + await waitForFast(() => { + expect(findRequesterRun(runId)).toMatchObject({ + endedAt: startedAt + 1_000, + outcome: { status: "timeout" }, + }); + }); + getLifecycleHandler()({ + runId, + stream: "lifecycle", + data: { + phase: "end", + ...(eventStartedAfterMs === undefined + ? {} + : { startedAt: startedAt + eventStartedAfterMs }), + endedAt: startedAt + eventEndedAfterMs, + }, + }); + await waitForFast(() => { + const run = findRequesterRun(runId); + expect(run?.endedAt).toBe(startedAt + 1_000); + expectRecordFields(run?.outcome, { status: "timeout", startedAt, endedAt: startedAt + 1_000, elapsedMs: 1_000, - }, - "stable published timeout outcome", - ); - }); - expect(mocks.runSubagentAnnounceFlow).toHaveBeenCalledTimes(1); - expect(mocks.captureSubagentCompletionReply).toHaveBeenCalledTimes(1); - }); + }); + expect(mocks.runSubagentAnnounceFlow).toHaveBeenCalledTimes(1); + }); + if (expectCapturedReply) { + expect(mocks.captureSubagentCompletionReply).toHaveBeenCalledTimes(1); + } + }, + ); it("converts first lifecycle success after the explicit run deadline into timeout", async () => { const startedAt = Date.now(); @@ -1923,65 +1875,25 @@ describe("subagent registry seam flow", () => { }); }); - it("allows non-explicit published timeouts to be corrected by lifecycle success", async () => { - const startedAt = Date.parse("2026-03-24T11:59:00Z"); - mod.registerSubagentRun({ + it.each([ + { + name: "allows non-explicit published timeouts to be corrected by lifecycle success", runId: "run-non-explicit-timeout-corrected", task: "non-explicit timeout remains correctable", - }); - const run = mod.getSubagentRunByChildSessionKey("agent:main:subagent:child"); - expect(run).not.toBeNull(); - Object.assign(run ?? {}, { - startedAt, - sessionStartedAt: startedAt, - endedAt: startedAt + 30_000, - outcome: { - status: "timeout", - startedAt, - endedAt: startedAt + 30_000, - elapsedMs: 30_000, - }, - delivery: { - status: "delivered", - announcedAt: startedAt + 30_000, - deliveredAt: startedAt + 30_000, - }, - }); - - const lifecycleHandler = getLifecycleHandler(); - - lifecycleHandler?.({ - runId: "run-non-explicit-timeout-corrected", - stream: "lifecycle", - data: { - phase: "end", - startedAt, - endedAt: startedAt + 35_000, - }, - }); - - await waitForFast(() => { - const correctedRun = findRequesterRun("run-non-explicit-timeout-corrected"); - expect(correctedRun?.endedAt).toBe(startedAt + 35_000); - expectRecordFields( - correctedRun?.outcome, - { - status: "ok", - startedAt, - endedAt: startedAt + 35_000, - elapsedMs: 35_000, - }, - "non-explicit published timeout corrected outcome", - ); - }); - }); - - it("allows pre-deadline lifecycle timeouts to be corrected by lifecycle success", async () => { - const startedAt = Date.parse("2026-03-24T11:59:00Z"); - mod.registerSubagentRun({ + runTimeoutSeconds: undefined, + }, + { + name: "allows pre-deadline lifecycle timeouts to be corrected by lifecycle success", runId: "run-predeadline-timeout-corrected", task: "pre-deadline timeout remains correctable", runTimeoutSeconds: 60, + }, + ])("$name", async ({ runId, task, runTimeoutSeconds }) => { + const startedAt = Date.parse("2026-03-24T11:59:00Z"); + mod.registerSubagentRun({ + runId, + task, + ...(runTimeoutSeconds === undefined ? {} : { runTimeoutSeconds }), }); const run = mod.getSubagentRunByChildSessionKey("agent:main:subagent:child"); expect(run).not.toBeNull(); @@ -1989,44 +1901,27 @@ describe("subagent registry seam flow", () => { startedAt, sessionStartedAt: startedAt, endedAt: startedAt + 30_000, - outcome: { - status: "timeout", - startedAt, - endedAt: startedAt + 30_000, - elapsedMs: 30_000, - }, + outcome: { status: "timeout", startedAt, endedAt: startedAt + 30_000, elapsedMs: 30_000 }, delivery: { status: "delivered", announcedAt: startedAt + 30_000, deliveredAt: startedAt + 30_000, }, }); - - const lifecycleHandler = getLifecycleHandler(); - - lifecycleHandler?.({ - runId: "run-predeadline-timeout-corrected", + getLifecycleHandler()({ + runId, stream: "lifecycle", - data: { - phase: "end", + data: { phase: "end", startedAt, endedAt: startedAt + 35_000 }, + }); + await waitForFast(() => { + const correctedRun = findRequesterRun(runId); + expect(correctedRun?.endedAt).toBe(startedAt + 35_000); + expectRecordFields(correctedRun?.outcome, { + status: "ok", startedAt, endedAt: startedAt + 35_000, - }, - }); - - await waitForFast(() => { - const correctedRun = findRequesterRun("run-predeadline-timeout-corrected"); - expect(correctedRun?.endedAt).toBe(startedAt + 35_000); - expectRecordFields( - correctedRun?.outcome, - { - status: "ok", - startedAt, - endedAt: startedAt + 35_000, - elapsedMs: 35_000, - }, - "pre-deadline published timeout corrected outcome", - ); + elapsedMs: 35_000, + }); }); });