diff --git a/ui/src/pages/IssueDetail.test.tsx b/ui/src/pages/IssueDetail.test.tsx index 3b52e52addd..7fbd28e217e 100644 --- a/ui/src/pages/IssueDetail.test.tsx +++ b/ui/src/pages/IssueDetail.test.tsx @@ -524,9 +524,9 @@ function createPausePreview(): IssueTreeControlPreview { generatedAt: new Date("2026-04-21T00:00:00.000Z"), releasePolicy: { strategy: "manual" }, totals: { - totalIssues: 2, + totalIssues: 3, affectedIssues: 2, - skippedIssues: 0, + skippedIssues: 1, activeRuns: 1, queuedRuns: 0, affectedAgents: 0, @@ -563,8 +563,39 @@ function createPausePreview(): IssueTreeControlPreview { skipped: false, skipReason: null, }, + { + id: "child-2", + identifier: "PAP-3", + title: "Completed child", + status: "done", + parentId: "issue-1", + depth: 1, + assigneeAgentId: null, + assigneeUserId: null, + activeRun: null, + activeHoldIds: [], + action: "pause", + skipped: true, + skipReason: "terminal_status", + }, + ], + skippedIssues: [ + { + id: "child-2", + identifier: "PAP-3", + title: "Completed child", + status: "done", + parentId: "issue-1", + depth: 1, + assigneeAgentId: null, + assigneeUserId: null, + activeRun: null, + activeHoldIds: [], + action: "pause", + skipped: true, + skipReason: "terminal_status", + }, ], - skippedIssues: [], activeRuns: [], affectedAgents: [], warnings: [], @@ -953,6 +984,8 @@ describe("IssueDetail", () => { expect(container.textContent).not.toContain("Status breakdown"); expect(container.textContent).not.toContain("Active runs cancelled"); expect(container.textContent).toContain("Paused child"); + expect(container.textContent).toContain("Completed child"); + expect(container.textContent).toContain("Complete"); const pauseApplyButton = Array.from(container.querySelectorAll("button")) .find((button) => button.textContent?.trim() === "Pause and stop work"); diff --git a/ui/src/pages/IssueDetail.tsx b/ui/src/pages/IssueDetail.tsx index f37b06a6618..a6e1830034c 100644 --- a/ui/src/pages/IssueDetail.tsx +++ b/ui/src/pages/IssueDetail.tsx @@ -2564,6 +2564,16 @@ export function IssueDetail() { () => (treeControlPreview?.issues ?? []).filter((candidate) => !candidate.skipped), [treeControlPreview], ); + const treePreviewDisplayIssues = useMemo( + () => { + const previewIssues = treeControlPreview?.issues ?? []; + if (treeControlMode !== "pause") { + return previewIssues.filter((candidate) => !candidate.skipped); + } + return previewIssues.filter((candidate) => !candidate.skipped || candidate.skipReason === "terminal_status"); + }, + [treeControlMode, treeControlPreview], + ); const activePauseHold = treeControlState?.activePauseHold ?? null; const activeRootPauseHoldsForDisplay = useMemo( () => activePauseHold?.isRoot === true ? activeRootPauseHolds : [], @@ -2656,7 +2666,7 @@ export function IssueDetail() { : treeControlMode === "restore" ? `Restore ${previewAffectedIssueCount} issues` : "Resume subtree"; - const treePreviewAffectedIssueRows = treePreviewAffectedIssues.map((candidate) => ({ + const treePreviewAffectedIssueRows = treePreviewDisplayIssues.map((candidate) => ({ candidate, issue: { ...issue, @@ -3527,13 +3537,19 @@ export function IssueDetail() { {candidate.identifier ?? candidate.id.slice(0, 8)} {candidate.title} + {candidate.skipped && candidate.skipReason === "terminal_status" ? ( + Complete + ) : null} ))}