From 39b94d0e7ab2e64ffda525c92c592b10fe40b5a2 Mon Sep 17 00:00:00 2001 From: Nicky Leach Date: Wed, 22 Jul 2026 14:00:36 -0700 Subject: [PATCH] fix(test): gate interaction-continuation retry barrier on terminal write (#10049) --- .../__tests__/heartbeat-process-recovery.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/server/src/__tests__/heartbeat-process-recovery.test.ts b/server/src/__tests__/heartbeat-process-recovery.test.ts index 1432021f91..49008825b4 100644 --- a/server/src/__tests__/heartbeat-process-recovery.test.ts +++ b/server/src/__tests__/heartbeat-process-recovery.test.ts @@ -2211,7 +2211,21 @@ describeEmbeddedPostgres("heartbeat orphaned process recovery", () => { .select() .from(heartbeatRuns) .where(eq(heartbeatRuns.agentId, agentId)); - return rows.length >= 2 ? rows : null; + if (rows.length < 2) return null; + // Gate on the *terminal* write of the background recovery, not the + // intermediate retry-run commit. recordPlanApprovalResumeFailureRetry + // writes the system comment first and updates the interaction + // result.resumeFailure last (heartbeat.ts:5627 then :5632), so once + // resumeFailure.status is observed the comment + issue update are also + // committed and every assertion below is race-free. + const interactionRow = await db + .select({ result: issueThreadInteractions.result }) + .from(issueThreadInteractions) + .where(eq(issueThreadInteractions.id, interactionId)) + .then((interactionRows) => interactionRows[0] ?? null); + const result = interactionRow?.result ?? null; + const resumeFailure = result && "resumeFailure" in result ? result.resumeFailure : null; + return resumeFailure?.status === "retrying" ? rows : null; }); expect(runs).toHaveLength(2);