fix(dashboard): one queued badge family — map raw 'queued', fold queued-to-plan into the status badge
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
7
.changeset/one-queued-badge-family.md
Normal file
7
.changeset/one-queued-badge-family.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
summary: One queued badge family — scheduler-queued cards read "Queued", and Queued to plan is the same badge as Planning.
|
||||||
|
category: fix
|
||||||
|
dev: Raw status "queued" no longer renders the lowercase engine token; the standalone queued-to-plan pill is removed and folds into the main status badge span (same classes/tooltip, testid preserved), so a card can never show two queued labels.
|
||||||
@@ -3392,7 +3392,15 @@ function TaskCardComponent({
|
|||||||
? t("tasks.needsInput", "Needs input")
|
? t("tasks.needsInput", "Needs input")
|
||||||
: isTransientPlannerActive
|
: isTransientPlannerActive
|
||||||
? t("tasks.statusPlanning", "Planning")
|
? t("tasks.statusPlanning", "Planning")
|
||||||
: getTaskStatusLabel(visualStatus ?? "", t, showOptionalGateBadge ? undefined : getRunningWorkflowStepLabel(task), { idle: !isAgentActive, overlapBlockedBy: task.overlapBlockedBy ?? null });
|
/*
|
||||||
|
FNXC:TaskStatusBadge 2026-08-01-03:20 (operator: ONE queued badge family, no dupes):
|
||||||
|
Queued-to-plan renders through THIS badge now — same span, same family as Planning —
|
||||||
|
instead of the standalone `queued-to-plan` pill it used to be (removed below). One card,
|
||||||
|
one badge; the muted modifier class and testid survive on this span.
|
||||||
|
*/
|
||||||
|
: showQueuedToPlanBadge
|
||||||
|
? t("tasks.queuedToPlan", "Queued to plan")
|
||||||
|
: getTaskStatusLabel(visualStatus ?? "", t, showOptionalGateBadge ? undefined : getRunningWorkflowStepLabel(task), { idle: !isAgentActive, overlapBlockedBy: task.overlapBlockedBy ?? null });
|
||||||
const hasCardMetaBadges = showPriorityBadge
|
const hasCardMetaBadges = showPriorityBadge
|
||||||
|| task.executionMode === "fast"
|
|| task.executionMode === "fast"
|
||||||
// FNXC:PlannerOversight 2026-07-04-00:00: the oversight badge is opt-in
|
// FNXC:PlannerOversight 2026-07-04-00:00: the oversight badge is opt-in
|
||||||
@@ -3536,9 +3544,9 @@ function TaskCardComponent({
|
|||||||
: pausedByAgent ? t("tasks.pausedByAgent", "paused by agent") : t("tasks.paused", "paused")}
|
: pausedByAgent ? t("tasks.pausedByAgent", "paused by agent") : t("tasks.paused", "paused")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{showStatusBadge && (
|
{(showStatusBadge || showQueuedToPlanBadge) && (
|
||||||
<span
|
<span
|
||||||
className={`card-status-badge card-status-badge--${task.column}${isAwaitingApproval ? " awaiting-approval" : ""}${isPlanReviewReplanCapApproval ? " awaiting-approval--plan-review-replan-cap" : ""}${isAwaitingInput ? " awaiting-input" : ""}${isAgentActive ? " pulsing" : ""}${isFailed ? " failed" : ""}${isStuck ? " stuck" : ""}`}
|
className={`card-status-badge card-status-badge--${task.column}${showQueuedToPlanBadge ? " queued-to-plan" : ""}${isAwaitingApproval ? " awaiting-approval" : ""}${isPlanReviewReplanCapApproval ? " awaiting-approval--plan-review-replan-cap" : ""}${isAwaitingInput ? " awaiting-input" : ""}${isAgentActive ? " pulsing" : ""}${isFailed ? " failed" : ""}${isStuck ? " stuck" : ""}`}
|
||||||
title={
|
title={
|
||||||
isPlanReviewReplanCapApproval
|
isPlanReviewReplanCapApproval
|
||||||
? t(
|
? t(
|
||||||
@@ -3560,6 +3568,11 @@ function TaskCardComponent({
|
|||||||
idle Revising card explains itself. Gated on !isAgentActive so a genuinely
|
idle Revising card explains itself. Gated on !isAgentActive so a genuinely
|
||||||
running revise cycle keeps no misleading "waiting" text.
|
running revise cycle keeps no misleading "waiting" text.
|
||||||
*/
|
*/
|
||||||
|
: showQueuedToPlanBadge
|
||||||
|
? t(
|
||||||
|
"tasks.queuedToPlanTitle",
|
||||||
|
"Waiting for a planning slot — planning starts when an agent slot frees up",
|
||||||
|
)
|
||||||
: task.status === "needs-replan" && !isAgentActive
|
: task.status === "needs-replan" && !isAgentActive
|
||||||
? t(
|
? t(
|
||||||
"tasks.needsReplanQueuedTitle",
|
"tasks.needsReplanQueuedTitle",
|
||||||
@@ -3568,7 +3581,7 @@ function TaskCardComponent({
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
aria-label={isTransientPlannerActive ? t("tasks.statusPlanning", "Planning") : undefined}
|
aria-label={isTransientPlannerActive ? t("tasks.statusPlanning", "Planning") : undefined}
|
||||||
data-testid={isAwaitingApproval ? `card-awaiting-approval-${task.id}` : undefined}
|
data-testid={isAwaitingApproval ? `card-awaiting-approval-${task.id}` : showQueuedToPlanBadge ? `card-queued-to-plan-${task.id}` : undefined}
|
||||||
data-awaiting-approval-reason={isAwaitingApproval ? (task.awaitingApprovalReason ?? "manual") : undefined}
|
data-awaiting-approval-reason={isAwaitingApproval ? (task.awaitingApprovalReason ?? "manual") : undefined}
|
||||||
>
|
>
|
||||||
{statusBadgeLabel}
|
{statusBadgeLabel}
|
||||||
@@ -3624,18 +3637,6 @@ function TaskCardComponent({
|
|||||||
find. Names the surviving dimension only. Worktrees can also be the binding gate, but only when
|
find. Names the surviving dimension only. Worktrees can also be the binding gate, but only when
|
||||||
the operator has worktree limiting on, so it is not stated unconditionally here.
|
the operator has worktree limiting on, so it is not stated unconditionally here.
|
||||||
*/}
|
*/}
|
||||||
{showQueuedToPlanBadge && (
|
|
||||||
<span
|
|
||||||
className="card-status-badge card-status-badge--todo queued-to-plan"
|
|
||||||
data-testid={`card-queued-to-plan-${task.id}`}
|
|
||||||
title={t(
|
|
||||||
"tasks.queuedToPlanTitle",
|
|
||||||
"Waiting for a planning slot — planning starts when an agent slot frees up",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{t("tasks.queuedToPlan", "Queued to plan")}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{hasInReviewStall && stallCopy && (
|
{hasInReviewStall && stallCopy && (
|
||||||
<span
|
<span
|
||||||
className={`card-status-badge card-status-badge--in-review in-review-stall in-review-stall--${stallCopy.code}`}
|
className={`card-status-badge card-status-badge--in-review in-review-stall in-review-stall--${stallCopy.code}`}
|
||||||
|
|||||||
@@ -74,6 +74,14 @@ export function getTaskStatusBadgeLabel(
|
|||||||
return t("tasks.statusQueuedBehind", "Queued behind {{taskId}}", { taskId: context.overlapBlockedBy });
|
return t("tasks.statusQueuedBehind", "Queued behind {{taskId}}", { taskId: context.overlapBlockedBy });
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
FNXC:TaskStatusBadge 2026-08-01-03:20 (operator: one queued family, like the planning badge):
|
||||||
|
Raw "queued" (scheduler capacity/dependency marker) previously fell through to the verbatim
|
||||||
|
lowercase engine token. Map it so every queued state reads as the same badge family.
|
||||||
|
*/
|
||||||
|
if (status === "queued") {
|
||||||
|
return t("tasks.statusQueued", "Queued");
|
||||||
|
}
|
||||||
|
/*
|
||||||
FNXC:TaskStatusBadge 2026-07-26-14:05:
|
FNXC:TaskStatusBadge 2026-07-26-14:05:
|
||||||
"planning" is an engine token, not operator copy, and it was only ever hidden because U12's
|
"planning" is an engine token, not operator copy, and it was only ever hidden because U12's
|
||||||
workflow-step override happened to cover the same cards. Now that the Plan Review gate has its own
|
workflow-step override happened to cover the same cards. Now that the Plan Review gate has its own
|
||||||
|
|||||||
Reference in New Issue
Block a user