fix(FN-4168): surface stalled-review reason inline on task cards
Fusion-Task-Id: FN-4168 Fusion-Task-Lineage: 781ffc66-cb1c-42b9-85e1-e5cbe0655863
This commit is contained in:
@@ -162,6 +162,16 @@
|
||||
border: var(--btn-border-width) solid color-mix(in srgb, var(--color-warning) 30%, transparent);
|
||||
}
|
||||
|
||||
.card-stalled-review-reason {
|
||||
margin-top: var(--space-xs);
|
||||
font-size: 0.6875rem;
|
||||
line-height: 1.4;
|
||||
color: var(--text-muted);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.card-status-badge.paused {
|
||||
background: var(--status-done-bg-deep);
|
||||
color: var(--text-muted);
|
||||
@@ -1183,6 +1193,10 @@
|
||||
padding: 1px 6px;
|
||||
}
|
||||
|
||||
.card-stalled-review-reason {
|
||||
font-size: 0.625rem;
|
||||
}
|
||||
|
||||
.card-mission-badge {
|
||||
max-width: 80px;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -467,6 +467,11 @@ function areTaskCardPropsEqual(previous: TaskCardProps, next: TaskCardProps): bo
|
||||
previousTask.sourceAgentId === nextTask.sourceAgentId &&
|
||||
previousTask.sourceMetadata?.issueUrl === nextTask.sourceMetadata?.issueUrl &&
|
||||
previousTask.sourceMetadata?.agentName === nextTask.sourceMetadata?.agentName &&
|
||||
previousTask.stalledReview?.reason === nextTask.stalledReview?.reason &&
|
||||
previousTask.stalledReview?.heuristic === nextTask.stalledReview?.heuristic &&
|
||||
previousTask.stalledReview?.matchCount === nextTask.stalledReview?.matchCount &&
|
||||
previousTask.stalledReview?.firstMatchAt === nextTask.stalledReview?.firstMatchAt &&
|
||||
previousTask.stalledReview?.lastMatchAt === nextTask.stalledReview?.lastMatchAt &&
|
||||
areAttachmentsEqual(previousTask.attachments, nextTask.attachments) &&
|
||||
areCommentsEqual(previousTask.comments, nextTask.comments) &&
|
||||
areTaskDependenciesEqual(previousTask.dependencies, nextTask.dependencies) &&
|
||||
@@ -746,6 +751,7 @@ function TaskCardComponent({
|
||||
const showPriorityBadge = normalizedPriority !== DEFAULT_TASK_PRIORITY;
|
||||
const isStuck = isTaskStuck(task, taskStuckTimeoutMs, lastFetchTimeMs);
|
||||
const stalledReview = getStalledReviewSignal(task);
|
||||
const showStalledReview = Boolean(stalledReview && task.column === "in-review" && !isPaused);
|
||||
const isAwaitingApproval = task.column === "triage" && task.status === "awaiting-approval";
|
||||
const isArchived = task.column === "archived";
|
||||
const isAgentActive = !globalPaused && !queued && !isFailed && !isPaused && !isStuck && !isAwaitingApproval && (task.column === "in-progress" || ACTIVE_STATUSES.has(task.status as string));
|
||||
@@ -1394,7 +1400,7 @@ function TaskCardComponent({
|
||||
Stuck
|
||||
</span>
|
||||
)}
|
||||
{stalledReview && task.column === "in-review" && !isPaused && (
|
||||
{showStalledReview && stalledReview && (
|
||||
<span
|
||||
className="card-status-badge card-status-badge--in-review stalled-review"
|
||||
title={stalledReview.reason}
|
||||
@@ -1555,6 +1561,11 @@ function TaskCardComponent({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{showStalledReview && stalledReview && (
|
||||
<div className="card-stalled-review-reason" title={stalledReview.reason}>
|
||||
{stalledReview.reason}
|
||||
</div>
|
||||
)}
|
||||
{isFailed && task.error && (
|
||||
<div className="card-error" title={task.error}>
|
||||
<span className="card-error-icon">⚠</span>
|
||||
|
||||
@@ -176,7 +176,7 @@ describe("TaskCard", () => {
|
||||
expect(container.querySelector(".card-status-badge")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders stalled badge with reason tooltip when stalledReview is set", () => {
|
||||
it("renders stalled badge with visible reason when stalledReview is set", () => {
|
||||
render(
|
||||
<TaskCard
|
||||
task={makeTask({
|
||||
@@ -197,6 +197,7 @@ describe("TaskCard", () => {
|
||||
|
||||
const stalledBadge = screen.getByText("Stalled");
|
||||
expect(stalledBadge.getAttribute("title")).toContain("Re-enqueued for merge 3 times");
|
||||
expect(screen.getByText("Re-enqueued for merge 3 times in the last 60 minutes without leaving in-review")).toBeDefined();
|
||||
});
|
||||
|
||||
it("does not render stalled badge when stalledReview is undefined", () => {
|
||||
@@ -213,6 +214,7 @@ describe("TaskCard", () => {
|
||||
);
|
||||
|
||||
expect(screen.queryByText("Stalled")).toBeNull();
|
||||
expect(screen.queryByText(/Re-enqueued for merge/)).toBeNull();
|
||||
});
|
||||
|
||||
it("shows paused by agent label when pausedByAgentId is set", () => {
|
||||
|
||||
Reference in New Issue
Block a user