From ce9ecd9d1b3a3ffd64d5680cf5270166fba3f6a7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 5 Sep 2026 14:21:43 +1000 Subject: [PATCH] fix(server): keep old failures from waking snoozed V2 threads --- .../ThreadSettlementService.test.ts | 25 ++++++++++++++++++- .../ThreadSettlementService.ts | 4 ++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/server/src/orchestration-v2/ThreadSettlementService.test.ts b/apps/server/src/orchestration-v2/ThreadSettlementService.test.ts index cbca5b3066d8..aa1032642091 100644 --- a/apps/server/src/orchestration-v2/ThreadSettlementService.test.ts +++ b/apps/server/src/orchestration-v2/ThreadSettlementService.test.ts @@ -130,13 +130,36 @@ describe("isAutoSettlementCandidate", () => { snoozedAt: at(-60 * 60 * 1_000), }); expect(isAutoSettlementCandidate(snoozed, NOW_MS)).toBe(false); - expect(isAutoSettlementCandidate(shell({ ...snoozed, status: "failed" }), NOW_MS)).toBe(true); + expect( + isAutoSettlementCandidate( + shell({ ...snoozed, status: "failed", latestRunCompletedAt: at(-30 * 60 * 1_000) }), + NOW_MS, + ), + ).toBe(true); expect( isAutoSettlementCandidate( shell({ ...snoozed, latestRunCompletedAt: at(-30 * 60 * 1_000) }), NOW_MS, ), ).toBe(true); + expect( + isAutoSettlementCandidate( + shell({ ...snoozed, status: "failed", latestRunCompletedAt: at(-2 * 60 * 60 * 1_000) }), + NOW_MS, + ), + ).toBe(false); + expect( + isAutoSettlementCandidate( + shell({ ...snoozed, status: "failed", latestRunCompletedAt: snoozed.snoozedAt }), + NOW_MS, + ), + ).toBe(false); + expect( + isAutoSettlementCandidate( + shell({ ...snoozed, status: "failed", latestRunCompletedAt: null }), + NOW_MS, + ), + ).toBe(false); // Expired snooze is no longer a park. expect(isAutoSettlementCandidate(shell({ ...snoozed, snoozedUntil: at(-1) }), NOW_MS)).toBe( true, diff --git a/apps/server/src/orchestration-v2/ThreadSettlementService.ts b/apps/server/src/orchestration-v2/ThreadSettlementService.ts index ebe13f0d2b5f..5222fd2a72aa 100644 --- a/apps/server/src/orchestration-v2/ThreadSettlementService.ts +++ b/apps/server/src/orchestration-v2/ThreadSettlementService.ts @@ -112,7 +112,9 @@ export function isAutoSettlementCandidate( // one still parked on its wake time keeps its stronger statement. const snoozedAtMs = toMillis(thread.snoozedAt); const completedAtMs = toMillis(thread.latestRunCompletedAt); - const wokeOnError = thread.status === "failed"; + const wokeOnError = + thread.status === "failed" && + (snoozedAtMs === null || (completedAtMs !== null && completedAtMs > snoozedAtMs)); const wokeOnCompletion = snoozedAtMs !== null && completedAtMs !== null && completedAtMs > snoozedAtMs; return wokeOnError || wokeOnCompletion;