feat(FN-3954): blocker staleness fanout and escalation for tasks

Merges FN-3954: adds a blocker fanout system where task staleness automatically escalates to upstream blocking tasks, with a new `blocker-fanout` core module, dashboard hooks wiring that surfaces escalation status on the board and executor status bar, and a new settings toggle to disable escalation.

Fusion-Task-Id: FN-3954
This commit is contained in:
Fusion
2026-05-10 19:47:07 -07:00
committed by gsxdsm
parent 0c5c47933a
commit 2aec3474b0
24 changed files with 411 additions and 143 deletions

View File

@@ -414,6 +414,7 @@ function areTaskCardPropsEqual(previous: TaskCardProps, next: TaskCardProps): bo
previous.fanout?.totalCount === next.fanout?.totalCount &&
previous.fanout?.activeTodoCount === next.fanout?.activeTodoCount &&
previous.fanout?.isHighFanout === next.fanout?.isHighFanout &&
previous.fanout?.escalation?.blockingAgeMs === next.fanout?.escalation?.blockingAgeMs &&
areTaskDependenciesEqual(previous.fanout?.dependentIds ?? [], next.fanout?.dependentIds ?? []) &&
areTaskDependenciesEqual(previous.fanout?.staleBlockedByDependentIds ?? [], next.fanout?.staleBlockedByDependentIds ?? []) &&
previousTask.id === nextTask.id &&
@@ -1648,12 +1649,12 @@ function TaskCardComponent({
)}
{fanout && fanout.totalCount > 0 && (
<span
className={`card-fanout-badge${fanout.staleBlockedByDependentIds.length > 0 ? " card-fanout-badge--stale" : ""}${fanout.isHighFanout ? " card-fanout-badge--high-impact" : ""}`}
data-tooltip={`Blocking ${fanout.totalCount} active task(s); ${fanout.activeTodoCount} waiting in todo${fanout.isHighFanout ? ` (high fan-out threshold: ${HIGH_FANOUT_BLOCKER_TODO_THRESHOLD})` : ""}`}
className={`card-fanout-badge${fanout.staleBlockedByDependentIds.length > 0 ? " card-fanout-badge--stale" : ""}${fanout.isHighFanout ? " card-fanout-badge--high-impact" : ""}${fanout.escalation ? " card-fanout-badge--escalated" : ""}`}
data-tooltip={`Blocking ${fanout.totalCount} active task(s); ${fanout.activeTodoCount} waiting in todo${fanout.isHighFanout ? ` (high fan-out threshold: ${HIGH_FANOUT_BLOCKER_TODO_THRESHOLD})` : ""}${fanout.escalation ? ` · escalated after ${Math.floor(fanout.escalation.blockingAgeMs / 60000)}m in blocking column` : ""}`}
>
<GitBranch size={12} style={{ verticalAlign: "middle" }} />
<span>
{fanout.isHighFanout ? "High fan-out" : "Blocks"}{" "}
{fanout.escalation ? "Escalated" : fanout.isHighFanout ? "High fan-out" : "Blocks"}{" "}
<span className="card-fanout-count">{fanout.totalCount}</span>
{fanout.isHighFanout ? ` (${fanout.activeTodoCount} todo)` : ""}
{fanout.staleBlockedByDependentIds.length > 0 ? ` (${fanout.staleBlockedByDependentIds.length} stale)` : ""}