diff --git a/server/src/__tests__/heartbeat-process-recovery.test.ts b/server/src/__tests__/heartbeat-process-recovery.test.ts index 9a0fcc4aae1..ea28277702d 100644 --- a/server/src/__tests__/heartbeat-process-recovery.test.ts +++ b/server/src/__tests__/heartbeat-process-recovery.test.ts @@ -4539,6 +4539,9 @@ describeEmbeddedPostgres("heartbeat orphaned process recovery", () => { expect(result.orphanBlockersAssigned).toBe(0); + const repeatResult = await heartbeat.reconcileStrandedAssignedIssues(); + expect(repeatResult.orphanBlockersAssigned).toBe(0); + const blocker = await db .select() .from(issues) @@ -4547,6 +4550,7 @@ describeEmbeddedPostgres("heartbeat orphaned process recovery", () => { expect(blocker?.assigneeAgentId).toBeNull(); const comments = await db.select().from(issueComments).where(eq(issueComments.issueId, blockerIssueId)); + expect(comments).toHaveLength(1); expect(comments[0]?.body).toContain("Board-Owned Blocker"); expect(comments[0]?.body).toContain("responsibleUserId"); diff --git a/server/src/services/recovery/service.ts b/server/src/services/recovery/service.ts index c1cd7a536ed..1d112f7ef4f 100644 --- a/server/src/services/recovery/service.ts +++ b/server/src/services/recovery/service.ts @@ -969,6 +969,18 @@ export function recoveryService(db: Db, deps: { enqueueWakeup: RecoveryWakeup }) const relations = await issuesSvc.getRelationSummaries(candidate.id); const blockingLinks = formatIssueLinksForComment(relations.blocks); if (candidate.responsibleUserId != null) { + const lastComment = await db + .select({ body: issueComments.body }) + .from(issueComments) + .where(eq(issueComments.issueId, candidate.id)) + .orderBy(desc(issueComments.createdAt), desc(issueComments.id)) + .limit(1) + .then((rows) => rows[0] ?? null); + if (lastComment?.body.includes("Board-Owned Blocker")) { + skipped += 1; + continue; + } + await issuesSvc.addComment( candidate.id, [