From 83a0f1fd523b5e99a1dc94b114e229b3b1c5173b Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 19 Apr 2026 03:22:10 +0100 Subject: [PATCH] test: share subagent cleanup decision fixture --- src/agents/subagent-registry-cleanup.test.ts | 52 +++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/agents/subagent-registry-cleanup.test.ts b/src/agents/subagent-registry-cleanup.test.ts index 474421bc08e..c816503b9e0 100644 --- a/src/agents/subagent-registry-cleanup.test.ts +++ b/src/agents/subagent-registry-cleanup.test.ts @@ -19,60 +19,57 @@ function makeEntry(overrides: Partial = {}): SubagentRunRecor describe("resolveDeferredCleanupDecision", () => { const now = 2_000; - it("defers completion-message cleanup while descendants are still pending", () => { - const decision = resolveDeferredCleanupDecision({ - entry: makeEntry({ expectsCompletionMessage: true }), + function resolveDecision( + overrides: Pick< + Parameters[0], + "activeDescendantRuns" | "entry" + > & + Partial< + Pick[0], "resolveAnnounceRetryDelayMs"> + >, + ) { + return resolveDeferredCleanupDecision({ now, - activeDescendantRuns: 2, announceExpiryMs: 5 * 60_000, announceCompletionHardExpiryMs: 30 * 60_000, maxAnnounceRetryCount: 3, deferDescendantDelayMs: 1_000, resolveAnnounceRetryDelayMs: () => 2_000, + ...overrides, + }); + } + + it("defers completion-message cleanup while descendants are still pending", () => { + const decision = resolveDecision({ + entry: makeEntry({ expectsCompletionMessage: true }), + activeDescendantRuns: 2, }); expect(decision).toEqual({ kind: "defer-descendants", delayMs: 1_000 }); }); it("hard-expires completion-message cleanup when descendants never settle", () => { - const decision = resolveDeferredCleanupDecision({ + const decision = resolveDecision({ entry: makeEntry({ expectsCompletionMessage: true, endedAt: now - (30 * 60_000 + 1) }), - now, activeDescendantRuns: 1, - announceExpiryMs: 5 * 60_000, - announceCompletionHardExpiryMs: 30 * 60_000, - maxAnnounceRetryCount: 3, - deferDescendantDelayMs: 1_000, - resolveAnnounceRetryDelayMs: () => 2_000, }); expect(decision).toEqual({ kind: "give-up", reason: "expiry" }); }); it("keeps regular expiry behavior for non-completion flows", () => { - const decision = resolveDeferredCleanupDecision({ + const decision = resolveDecision({ entry: makeEntry({ expectsCompletionMessage: false, endedAt: now - (5 * 60_000 + 1) }), - now, activeDescendantRuns: 0, - announceExpiryMs: 5 * 60_000, - announceCompletionHardExpiryMs: 30 * 60_000, - maxAnnounceRetryCount: 3, - deferDescendantDelayMs: 1_000, - resolveAnnounceRetryDelayMs: () => 2_000, }); expect(decision).toEqual({ kind: "give-up", reason: "expiry", retryCount: 1 }); }); it("uses retry backoff for completion-message flows once descendants are settled", () => { - const decision = resolveDeferredCleanupDecision({ + const decision = resolveDecision({ entry: makeEntry({ expectsCompletionMessage: true, announceRetryCount: 1 }), - now, activeDescendantRuns: 0, - announceExpiryMs: 5 * 60_000, - announceCompletionHardExpiryMs: 30 * 60_000, - maxAnnounceRetryCount: 3, - deferDescendantDelayMs: 1_000, resolveAnnounceRetryDelayMs: (retryCount) => retryCount * 1_000, }); @@ -80,14 +77,9 @@ describe("resolveDeferredCleanupDecision", () => { }); it("uses retry backoff for non-completion flows so cleanup can settle after announce failures", () => { - const decision = resolveDeferredCleanupDecision({ + const decision = resolveDecision({ entry: makeEntry({ expectsCompletionMessage: false, announceRetryCount: 1 }), - now, activeDescendantRuns: 0, - announceExpiryMs: 5 * 60_000, - announceCompletionHardExpiryMs: 30 * 60_000, - maxAnnounceRetryCount: 3, - deferDescendantDelayMs: 1_000, resolveAnnounceRetryDelayMs: (retryCount) => retryCount * 1_000, });