mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 02:26:12 +02:00
fix: cover recovery-owned blocker attention
This commit is contained in:
1 parent
dc39ac4b25
commit
6db67c2da6
2 files changed
+37
-2
No files matched your search
@@ -3487,6 +3487,12 @@ describeEmbeddedPostgres("issueService blockers and dependency wake readiness",
|
||||
const updated = await svc.update(issueId, { status: "blocked" });
|
||||
|
||||
expect(updated?.status).toBe("blocked");
|
||||
const [listed] = await svc.list(companyId, { status: "blocked" });
|
||||
expect(listed?.blockerAttention).toMatchObject({
|
||||
state: "covered",
|
||||
reason: null,
|
||||
unresolvedBlockerCount: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("auto-routes a blocked issue to todo when its final blocker edge is deleted", async () => {
|
||||
|
||||
@@ -1649,7 +1649,7 @@ type IssueBlockerAttentionInputNode =
|
||||
IssueBlockerAttentionNode,
|
||||
"id" | "companyId" | "parentId" | "identifier" | "title" | "status" | "assigneeAgentId" | "assigneeUserId"
|
||||
>
|
||||
& { executionRunId?: string | null; description?: string | null };
|
||||
& { executionRunId?: string | null; description?: string | null; originKind?: string | null };
|
||||
|
||||
type IssueBlockerAttentionEdge = {
|
||||
issueId: string;
|
||||
@@ -2045,6 +2045,31 @@ async function listIssueBlockerAttentionMap(
|
||||
}
|
||||
if (roots.length === 0) return attentionMap;
|
||||
|
||||
const rootIds = roots.map((root) => root.id);
|
||||
const recoveryOwnedIssueIds = new Set<string>();
|
||||
for (const chunk of chunkList(rootIds, ISSUE_LIST_RELATED_QUERY_CHUNK_SIZE)) {
|
||||
const recoveryRows = await dbOrTx
|
||||
.select({
|
||||
sourceIssueId: issueRecoveryActions.sourceIssueId,
|
||||
recoveryIssueId: issueRecoveryActions.recoveryIssueId,
|
||||
})
|
||||
.from(issueRecoveryActions)
|
||||
.where(
|
||||
and(
|
||||
eq(issueRecoveryActions.companyId, companyId),
|
||||
inArray(issueRecoveryActions.status, ["active", "escalated"]),
|
||||
or(
|
||||
inArray(issueRecoveryActions.sourceIssueId, chunk),
|
||||
inArray(issueRecoveryActions.recoveryIssueId, chunk),
|
||||
),
|
||||
),
|
||||
);
|
||||
for (const row of recoveryRows) {
|
||||
if (row.sourceIssueId) recoveryOwnedIssueIds.add(row.sourceIssueId);
|
||||
if (row.recoveryIssueId) recoveryOwnedIssueIds.add(row.recoveryIssueId);
|
||||
}
|
||||
}
|
||||
|
||||
const nodesById = new Map<string, IssueBlockerAttentionNode>();
|
||||
const edgesByIssueId = new Map<string, IssueBlockerAttentionEdge[]>();
|
||||
for (const root of roots) nodesById.set(root.id, { ...root });
|
||||
@@ -2360,7 +2385,11 @@ async function listIssueBlockerAttentionMap(
|
||||
for (const root of roots) {
|
||||
const topLevelEdges = (edgesByIssueId.get(root.id) ?? []).filter((edge) => nodesById.get(edge.blockerIssueId)?.status !== "done");
|
||||
if (topLevelEdges.length === 0) {
|
||||
if (externalWaitFromDescription(root.description ?? null)) {
|
||||
if (
|
||||
externalWaitFromDescription(root.description ?? null) ||
|
||||
recoveryOwnedIssueIds.has(root.id) ||
|
||||
(isStrandedIssueRecoveryOriginKind(root.originKind) && Boolean(root.assigneeAgentId))
|
||||
) {
|
||||
attentionMap.set(root.id, createIssueBlockerAttention({ state: "covered" }));
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user