diff --git a/maps/feature-map/tasks.md b/maps/feature-map/tasks.md index 094f5dd5f11..8716319460c 100644 --- a/maps/feature-map/tasks.md +++ b/maps/feature-map/tasks.md @@ -88,6 +88,8 @@ Use a human/unassigned task to verify persistence without invoking a model. Automated: [task-list helpers](../../ui/src/pages/Issues.test.tsx) cover search URLs, pagination, deduplication, and presentation constants. The suite does not render the page or exercise filtering, grouping, opening a task, and returning; those interactions still need a running-browser check. +Task and inbox rows omit the system interruption labels **Thinking**, **Trying again soon**, and **Retry available**. [Shared row tests](../../ui/src/components/IssueRow.test.tsx) cover working, scheduled-retry, and failed interruptions in both row presentations, including suppression of replacement recovery chips. Task status and other relevant badges remain visible; retry controls remain inside the task conversation. + Manual: Seed human-created, agent-created, scheduled routine, human-initiated chat-channel, and creator-less tasks. Confirm automation is hidden by default, **show agent-created tasks** reveals it, reload preserves the choice, and Clear filters hides it again. Verify list and board search with automation newer than the human results, and expand contextual ancestors/subtasks without promoting unrelated automated roots. Repeat in project task lists. Agent profiles and task-detail subtasks retain complete history. Manual: Filter by status and assignee, change grouping/sort, open a task, and return. Verify the correct records and selected view survive navigation and reload. Include an empty result and a failed request. diff --git a/ui/src/components/IssueRow.test.tsx b/ui/src/components/IssueRow.test.tsx index 6727f3a78f6..852022bda7d 100644 --- a/ui/src/components/IssueRow.test.tsx +++ b/ui/src/components/IssueRow.test.tsx @@ -844,6 +844,31 @@ describe("IssueRow", () => { return snapshot; } + it.each(["working", "retry_scheduled", "failed"] as const)( + "omits %s system interruption feedback without exposing legacy recovery in list rows", + (state) => { + const root = createRoot(container); + const issue = recoveryIssue(at(3 * 60_000)); + issue.interruption = { + intentId: "saved-input", responsibility: "system", state, + nextRetryAt: state === "retry_scheduled" ? at(3 * 60_000) : null, + canRetry: state === "failed", userAction: null, + sourceRunIds: ["run-1"], observedRunId: "run-1", + }; + try { + for (const presentation of ["task", "legacy"] as const) { + act(() => root.render()); + expect(container.textContent).toContain(issue.title); + expect(container.querySelector("[data-inbox-issue-link]")?.getAttribute("href")).toBe("/issues/PAP-1"); + expect(container.textContent).not.toMatch(/Retry available|Thinking|Trying again soon|Recovery in progress/); + expect(container.querySelector("[data-testid='issue-row-recovery-indicator']")).toBeNull(); + } + } finally { + act(() => root.unmount()); + } + }, + ); + it("shows native export activity from the action even without a scheduled retry", () => { const issue = recoveryIssue(at(-5 * 60_000)); Object.assign(issue.activeRecoveryAction!, { diff --git a/ui/src/components/IssueRow.tsx b/ui/src/components/IssueRow.tsx index e2d3b27dcf7..683421bcc4a 100644 --- a/ui/src/components/IssueRow.tsx +++ b/ui/src/components/IssueRow.tsx @@ -221,10 +221,7 @@ export function IssueRow({ // The row already carries the issue's own scheduled retry, so the chip can tell a retry the // scheduler is actually running from one whose due time simply passed. const recoveryIndicator = issue.interruption?.responsibility === "system" && issue.interruption.state !== "resolved" - ? - {issue.interruption.state === "working" ? "Thinking" - : issue.interruption.state === "retry_scheduled" ? "Trying again soon" : "Retry available"} - + ? null : recoveryAction && !requiresExecutionReconciliation(recoveryAction.cause) ? renderRecoveryChip(recoveryAction, selected, { scheduledRetry: issue.scheduledRetry ?? null }) : null;