Address recovery review cleanup notes

This commit is contained in:
Dotta committed 2026-05-10 00:15:26 -05:00
1 parent ff19cf66b1
commit 48d95bd237
2 files changed
+55 -32

No files matched your search

+33 -14
View File
@@ -422,11 +422,11 @@ type RecoveryActionsLister = {
) => Promise<Map<string, NonNullable<IssueRelationIssueSummary["activeRecoveryAction"]>>>;
};
async function annotateRelationSummariesWithRecoveryActions(
async function relationRecoveryActionMap(
recoveryActionsSvc: RecoveryActionsLister,
companyId: string,
relations: { blockedBy: IssueRelationIssueSummary[]; blocks: IssueRelationIssueSummary[] },
) {
): Promise<Map<string, NonNullable<IssueRelationIssueSummary["activeRecoveryAction"]>>> {
const candidates: IssueRelationIssueSummary[] = [];
const visit = (summary: IssueRelationIssueSummary) => {
candidates.push(summary);
@@ -436,13 +436,24 @@ async function annotateRelationSummariesWithRecoveryActions(
};
for (const blocker of relations.blockedBy) visit(blocker);
for (const blocking of relations.blocks) visit(blocking);
if (candidates.length === 0) return;
if (candidates.length === 0) return new Map();
const ids = [...new Set(candidates.map((summary) => summary.id))];
const map = await recoveryActionsSvc.listActiveForIssues(companyId, ids);
for (const summary of candidates) {
const action = map.get(summary.id) ?? null;
if (action) summary.activeRecoveryAction = action;
}
return recoveryActionsSvc.listActiveForIssues(companyId, ids);
}
function withRecoveryActionsOnRelationSummaries(
relations: { blockedBy: IssueRelationIssueSummary[]; blocks: IssueRelationIssueSummary[] },
recoveryActionByIssueId: Map<string, NonNullable<IssueRelationIssueSummary["activeRecoveryAction"]>>,
) {
const augment = (summary: IssueRelationIssueSummary): IssueRelationIssueSummary => ({
...summary,
activeRecoveryAction: recoveryActionByIssueId.get(summary.id) ?? summary.activeRecoveryAction ?? null,
terminalBlockers: summary.terminalBlockers?.map(augment),
});
return {
blockedBy: relations.blockedBy.map(augment),
blocks: relations.blocks.map(augment),
};
}
const ACTIVE_REVIEW_APPROVAL_STATUSES = new Set(["pending", "revision_requested"]);
@@ -1599,11 +1610,15 @@ export function issueRoutes(
currentExecutionWorkspacePromise,
recoveryActionsSvc.getActiveForIssue(issue.companyId, issue.id),
]);
await annotateRelationSummariesWithRecoveryActions(
const recoveryActionsByRelationIssue = await relationRecoveryActionMap(
recoveryActionsSvc,
issue.companyId,
relations,
);
const relationsWithRecoveryActions = withRecoveryActionsOnRelationSummaries(
relations,
recoveryActionsByRelationIssue,
);
res.json({
issue: {
@@ -1621,8 +1636,8 @@ export function issueRoutes(
projectId: issue.projectId,
goalId: goal?.id ?? issue.goalId,
parentId: issue.parentId,
blockedBy: relations.blockedBy,
blocks: relations.blocks,
blockedBy: relationsWithRecoveryActions.blockedBy,
blocks: relationsWithRecoveryActions.blocks,
assigneeAgentId: issue.assigneeAgentId,
assigneeUserId: issue.assigneeUserId,
originKind: issue.originKind,
@@ -1713,11 +1728,15 @@ export function issueRoutes(
svc.getCurrentScheduledRetry(issue.id),
recoveryActionsSvc.getActiveForIssue(issue.companyId, issue.id),
]);
await annotateRelationSummariesWithRecoveryActions(
const recoveryActionsByRelationIssue = await relationRecoveryActionMap(
recoveryActionsSvc,
issue.companyId,
relations,
);
const relationsWithRecoveryActions = withRecoveryActionsOnRelationSummaries(
relations,
recoveryActionsByRelationIssue,
);
const mentionedProjects = mentionedProjectIds.length > 0
? await projectsSvc.listByIds(issue.companyId, mentionedProjectIds)
: [];
@@ -1734,8 +1753,8 @@ export function issueRoutes(
successfulRunHandoff: successfulRunHandoffStates.get(issue.id) ?? null,
scheduledRetry,
activeRecoveryAction,
blockedBy: relations.blockedBy,
blocks: relations.blocks,
blockedBy: relationsWithRecoveryActions.blockedBy,
blocks: relationsWithRecoveryActions.blocks,
relatedWork: referenceSummary,
referencedIssueIdentifiers: referenceSummary.outbound.map((item) => item.issue.identifier ?? item.issue.id),
...documentPayload,
+22 -18
View File
@@ -2193,7 +2193,7 @@ export function recoveryService(db: Db, deps: { enqueueWakeup: RecoveryWakeup })
}
async function collectIssueGraphLivenessFindings() {
const issueRows = await db
const issueRowsPromise = Promise.resolve(db
.select({
id: issues.id,
companyId: issues.companyId,
@@ -2218,10 +2218,10 @@ export function recoveryService(db: Db, deps: { enqueueWakeup: RecoveryWakeup })
isNull(issues.hiddenAt),
notInArray(issues.originKind, [RECOVERY_ORIGIN_KINDS.issueGraphLivenessEscalation]),
),
);
const issueIdsUnderAnalysis = issueRows.map((row) => row.id);
));
const [
issueRows,
relationRows,
agentRows,
activeRunRows,
@@ -2232,6 +2232,7 @@ export function recoveryService(db: Db, deps: { enqueueWakeup: RecoveryWakeup })
recoveryIssueRows,
recoveryActionRows,
] = await Promise.all([
issueRowsPromise,
db
.select({
companyId: issueRelations.companyId,
@@ -2321,21 +2322,24 @@ export function recoveryService(db: Db, deps: { enqueueWakeup: RecoveryWakeup })
notInArray(issues.status, ["done", "cancelled"]),
),
),
issueIdsUnderAnalysis.length === 0
? Promise.resolve([])
: db
.select({
companyId: issueRecoveryActions.companyId,
issueId: issueRecoveryActions.sourceIssueId,
status: issueRecoveryActions.status,
})
.from(issueRecoveryActions)
.where(
and(
inArray(issueRecoveryActions.status, ["active", "escalated"]),
inArray(issueRecoveryActions.sourceIssueId, issueIdsUnderAnalysis),
),
),
issueRowsPromise.then((rows) => {
const issueIdsUnderAnalysis = rows.map((row) => row.id);
return issueIdsUnderAnalysis.length === 0
? []
: db
.select({
companyId: issueRecoveryActions.companyId,
issueId: issueRecoveryActions.sourceIssueId,
status: issueRecoveryActions.status,
})
.from(issueRecoveryActions)
.where(
and(
inArray(issueRecoveryActions.status, ["active", "escalated"]),
inArray(issueRecoveryActions.sourceIssueId, issueIdsUnderAnalysis),
),
);
}),
]);
const openRecoveryIssues = recoveryIssueRows.flatMap((row) => {