diff --git a/server/src/__tests__/issues-service.test.ts b/server/src/__tests__/issues-service.test.ts index 2dc65b389f8..5a0022d68ad 100644 --- a/server/src/__tests__/issues-service.test.ts +++ b/server/src/__tests__/issues-service.test.ts @@ -3308,6 +3308,14 @@ describeEmbeddedPostgres("issueService blockers and dependency wake readiness", status: "succeeded", startedAt: new Date("2026-05-23T22:10:00.000Z"), }); + await db.insert(workspaceOperations).values({ + companyId, + executionWorkspaceId, + issueId: null, + phase: "worktree_prepare", + status: "succeeded", + startedAt: new Date("2026-05-23T22:15:00.000Z"), + }); await expect(svc.listWakeableBlockedDependents(blockerId)).resolves.toEqual([ expect.objectContaining({ diff --git a/server/src/services/issues.ts b/server/src/services/issues.ts index 81fb4bbcd96..cfa0a64be89 100644 --- a/server/src/services/issues.ts +++ b/server/src/services/issues.ts @@ -707,30 +707,37 @@ async function listPendingFinalizeBlockerIssueIds( ), ); - const latestByBlockerWorkspace = new Map(); + const latestAttributedByBlockerWorkspace = new Map(); + const latestUnattributedByWorkspace = new Map(); for (const row of rows) { if (!row.executionWorkspaceId) continue; - const keys = row.issueId - ? [`${row.issueId}:${row.executionWorkspaceId}`] - : blockerWorkspacePairs - .filter((pair) => pair.executionWorkspaceId === row.executionWorkspaceId) - .map((pair) => `${pair.blockerIssueId}:${pair.executionWorkspaceId}`); - - for (const key of keys) { + if (row.issueId) { + const key = `${row.issueId}:${row.executionWorkspaceId}`; if (!blockerWorkspaceKeys.has(key)) continue; - const current = latestByBlockerWorkspace.get(key); + const current = latestAttributedByBlockerWorkspace.get(key); if (!current || row.startedAt > current.startedAt) { - latestByBlockerWorkspace.set(key, { + latestAttributedByBlockerWorkspace.set(key, { phase: row.phase, status: row.status, startedAt: row.startedAt, }); } + continue; + } + + const current = latestUnattributedByWorkspace.get(row.executionWorkspaceId); + if (!current || row.startedAt > current.startedAt) { + latestUnattributedByWorkspace.set(row.executionWorkspaceId, { + phase: row.phase, + status: row.status, + startedAt: row.startedAt, + }); } } for (const pair of blockerWorkspacePairs) { - const latest = latestByBlockerWorkspace.get(`${pair.blockerIssueId}:${pair.executionWorkspaceId}`); + const latest = latestAttributedByBlockerWorkspace.get(`${pair.blockerIssueId}:${pair.executionWorkspaceId}`) + ?? latestUnattributedByWorkspace.get(pair.executionWorkspaceId); if (!latest) continue; // no ops recorded -> nothing to finalize for this blocker if (latest.phase === "workspace_finalize" && latest.status === "succeeded") continue; pending.add(pair.blockerIssueId);