fix(dashboard): Task Detail's blocking count read the LEGACY lanes (last of the three fan-out surfaces) (#3004)

Third and last of the three surfaces calling the blocker fan-out
wrapper, completing the sweep started in #2990 (Board + Executor bar).

## What was wrong, precisely

The dependent **list** is lane-independent — core pushes `dependentIds`
without consulting lanes — so this section looked broadly right. Two
things beside it are not:

- `overlapBlockedTodoCount`, rendered as **"FN-X is blocking N todo
task(s) via blockedBy overlap"** — counted against the literal `todo`,
so on a renamed board it read **0 while cards were genuinely blocked**.
- the `stale` marker on each blocking dependent — decided against
`terminal`/`review` lanes the operator does not use.

A wrong number sitting beside a right list is the easiest kind to miss,
which is why I checked what the modal actually consumes before deciding
this was worth a PR rather than assuming the whole section was broken.

## Why a prop and not a hook

This was the surface I deferred in #2990 because it had no trait index
in scope. Two options:

- `useBoardWorkflows` inside the modal — rejected. The hook documents
that it does **not** dedupe across consumers: each call installs its own
visibilitychange/focus listeners and its own SSE subscription. That is a
new fetch and subscription per modal open, to answer a question the app
has already answered.
- **Thread the index that already exists** — `App` builds
`footerColumnFlagsByTaskId` for the footer; this forwards it through
`AppModals` as an optional prop. Chosen.

Optional throughout: a card with no entry keeps the documented legacy
fallback, so the remote-node case (where local workflow metadata must
never be applied to foreign ids) and the pre-load window stay
byte-identical.

## Reverted

The new case fails on the rendered text — the modal cannot find `"FN-B
is blocking 2 todo task(s) via blockedBy overlap"`. The pre-existing
legacy-column case above it passes either way, because `todo` satisfies
the literal default; that is exactly why it never caught this.

## Verification

TaskDetailModal.rendering + ExecutorStatusBar + useBlockerFanout **206
passed** · dashboard app suite 11986 passed / 5 skipped (581 files) ·
`pnpm test:gate` 161 + 13 + 487 + 71 · lint · census `--strict` ·
lane-wiring · fnxc-dates · changesets — green.

## One note for whoever owns the FNXC gate

`check-fnxc-future-dates.mjs` **rewrites its baseline as a side effect
and still exits 0**. Today's date roll dropped 183 stamps out of
"future", so any run dirties
`scripts/lib/fnxc-future-dates-baseline.json` in the working tree. It
cost me a stash conflict before I noticed. Not bundled here — it is
repo-wide midnight drift, not this change — but a check that mutates
tracked state on a read is worth a look.
This commit is contained in:
gsxdsm
2026-07-31 00:13:43 -07:00
committed by GitHub
parent d861923355
commit 1de0141ab8
6 changed files with 93 additions and 178 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Task Detail's "is blocking N todo task(s)" now counts your own lane names instead of reading zero.
category: fix
dev: `TaskDetailContent` takes an optional `columnFlagsByTaskId`, forwarded from `App` through `AppModals`; the fan-out useMemo passes it to the wrapper. Omitted, behaviour is byte-identical.

View File

@@ -2199,6 +2199,7 @@ function AppInner() {
<AppModals
projectId={currentProject?.id}
tasks={tasks}
columnFlagsByTaskId={footerColumnFlagsByTaskId}
projects={projects}
currentProject={currentProject}
addToast={addToast}

View File

@@ -7,6 +7,7 @@ import type { UseTaskHandlersResult } from "../hooks/useTaskHandlers";
import type { Toast, ToastType } from "../hooks/useToast";
import { ModalErrorBoundary } from "./ErrorBoundary";
import { TaskDetailModal } from "./TaskDetailModal";
import type { BlockerFanoutColumnFlags } from "../hooks/useBlockerFanout";
import { GitHubImportModal } from "./GitHubImportModal";
import { SubtaskBreakdownModal } from "./SubtaskBreakdownModal";
import { ScriptsModal } from "./ScriptsModal";
@@ -42,6 +43,8 @@ function prefetchSettingsModal() {
interface AppModalsProps {
projectId?: string;
tasks: Task[];
/* Per-task lifecycle traits, forwarded to Task Detail's blocker fan-out. */
columnFlagsByTaskId?: ReadonlyMap<string, BlockerFanoutColumnFlags>;
projects: ProjectInfo[];
currentProject: ProjectInfo | null;
addToast: (message: string, type?: ToastType) => void;
@@ -103,6 +106,7 @@ interface AppModalsProps {
export function AppModals({
projectId,
tasks,
columnFlagsByTaskId,
projects,
currentProject,
addToast,
@@ -320,6 +324,7 @@ export function AppModals({
task={detailTask}
projectId={projectId}
tasks={tasks}
columnFlagsByTaskId={columnFlagsByTaskId}
onClose={closeDetailWithNav}
onOpenDetail={openDetailTaskWithNav}
mobileHeaderMode={modalManager.detailTaskOrigin === "list-mobile" ? "back" : "close"}

View File

@@ -72,7 +72,7 @@ import type { SessionTerminalMode, SessionTerminalPosture } from "./SessionTermi
import { usePluginUiSlots } from "../hooks/usePluginUiSlots";
import { appendTokenQuery } from "../auth";
import { extractDependencyDeleteConflict, extractLineageDeleteConflict } from "../utils/taskDelete";
import { MAX_AUTO_MERGE_RETRIES, computeBlockerFanoutMap } from "../hooks/useBlockerFanout";
import { MAX_AUTO_MERGE_RETRIES, computeBlockerFanoutMap, type BlockerFanoutColumnFlags } from "../hooks/useBlockerFanout";
import { resolveEffectiveGithubRepoDefault } from "./githubTracking";
import type { TFunction } from "i18next";
import { linkifyFilePaths, linkifyReactChildren } from "../utils/filePathLinkify";
@@ -363,6 +363,8 @@ export interface TaskDetailModalProps {
task: Task | TaskDetail;
projectId?: string;
tasks?: Task[];
/* Per-task lifecycle traits for the blocker fan-out; see the useMemo that consumes it. */
columnFlagsByTaskId?: ReadonlyMap<string, BlockerFanoutColumnFlags>;
onClose: () => void;
onOpenDetail: (task: Task | TaskDetail) => void; // For clicking dependencies
onMoveTask: (id: string, column: Column, optionsOrPosition?: { preserveProgress?: boolean } | number) => Promise<Task>;
@@ -722,6 +724,7 @@ export function TaskDetailContent({
task,
projectId,
tasks = [],
columnFlagsByTaskId,
onOpenDetail,
onMoveTask,
onDeleteTask,
@@ -3700,7 +3703,21 @@ export function TaskDetailContent({
return bNum - aNum;
});
const blockerFanoutMap = useMemo(() => computeBlockerFanoutMap(tasks), [tasks]);
/*
FNXC:WorkflowResolvedColumns 2026-07-30-23:20 (third fan-out surface):
Without resolved traits this classified against `todo`/`in-review`/`done`, so on a renamed board
the "blocking N todo task(s)" line counted zero and the `stale` marker on each blocking dependent
was decided against lanes the operator does not use. The dependent LIST itself is lane-independent
(core pushes `dependentIds` unconditionally), which is why the modal still looked broadly right —
only the count and the staleness were wrong.
Optional: a card with no entry keeps the documented legacy fallback, so the remote-node case and
the pre-load window are byte-identical.
*/
const blockerFanoutMap = useMemo(
() => computeBlockerFanoutMap(tasks, columnFlagsByTaskId ? { columnFlagsByTaskId } : {}),
[tasks, columnFlagsByTaskId],
);
const blockingEntry = blockerFanoutMap.get(task.id);
const blockingDependents = useMemo(() => {
if (!blockingEntry) return [] as Array<{ id: string; label: string; stale: boolean }>;

View File

@@ -1021,6 +1021,42 @@ describe("TaskDetailModal", () => {
expect(screen.getByText("File scope overlap blocker: FN-OVER (stale)")).toBeInTheDocument();
});
it("counts the overlap blockedBy summary using the board's OWN lane names", () => {
/*
FNXC:WorkflowResolvedColumns 2026-07-30-23:35:
The case below renamed and nothing else. Without resolved traits the count is taken against the
literal `todo`, which no card is in, so this line read "blocking 0 todo task(s)" while two cards
were in fact blocked. The dependent LIST stayed correct throughout (core builds it without
consulting lanes), which is what made the wrong number easy to miss.
*/
const tasks = [
makeTask({ id: "FN-B", column: "building" }),
makeTask({ id: "FN-1", column: "drafting", blockedBy: "FN-B" }),
makeTask({ id: "FN-2", column: "drafting", blockedBy: "FN-B" }),
];
const columnFlagsByTaskId = new Map(tasks.map((task) => [
task.id,
task.column === "building" ? { countsTowardWip: true } : { hold: true },
]));
render(
<TaskDetailModal
initialTab="definition"
task={makeTask({ id: "FN-B", column: "building" })}
tasks={tasks}
columnFlagsByTaskId={columnFlagsByTaskId}
onClose={noop}
onMoveTask={noopMove}
onDeleteTask={noopDelete}
onMergeTask={noopMerge}
onOpenDetail={noopOpenDetail}
addToast={noop}
/>,
);
expect(screen.getByText("FN-B is blocking 2 todo task(s) via blockedBy overlap")).toBeInTheDocument();
});
it("shows overlap blockedBy summary in Blocking section", () => {
render(
<TaskDetailModal

View File

@@ -1,245 +1,94 @@
{
"packages/cli/src/__tests__/cli-active-count-lanes.test.ts": 5,
"packages/cli/src/__tests__/pr-create-review-lane-resolved.test.ts": 1,
"packages/cli/src/__tests__/task-retry-renamed-review.pg.test.ts": 2,
"packages/cli/src/commands/__tests__/task.test.ts": 1,
"packages/cli/src/commands/dashboard.ts": 1,
"packages/cli/src/commands/task.ts": 8,
"packages/cli/src/commands/task.ts": 6,
"packages/cli/src/extension.ts": 3,
"packages/core/src/__tests__/analytics-timing-roles-resolved.test.ts": 1,
"packages/core/src/__tests__/archive-all-done-lane.test.ts": 1,
"packages/core/src/__tests__/archived-column-gate-parity.test.ts": 3,
"packages/core/src/__tests__/assigned-agent-archived-lanes.test.ts": 1,
"packages/core/src/__tests__/blocker-fanout.test.ts": 2,
"packages/core/src/__tests__/display-ranking-roles-resolved.test.ts": 1,
"packages/core/src/__tests__/duplicate-terminal-roles-resolved.test.ts": 1,
"packages/core/src/__tests__/eval-automation-complete-lane.test.ts": 1,
"packages/core/src/__tests__/intake-duplicate-terminal-lanes.test.ts": 1,
"packages/core/src/__tests__/legacy-auto-merge-stamp-review-lanes.test.ts": 1,
"packages/core/src/__tests__/merge-path-lanes-resolved.test.ts": 2,
"packages/core/src/__tests__/postgres/archived-document-lanes.pg.test.ts": 1,
"packages/core/src/__tests__/postgres/dependency-satisfied-renamed-board.pg.test.ts": 2,
"packages/core/src/__tests__/postgres/mission-store.pg.test.ts": 1,
"packages/core/src/__tests__/postgres/near-duplicate-clear-renamed-terminal.pg.test.ts": 2,
"packages/core/src/__tests__/postgres/store-archive-reads.pg.test.ts": 1,
"packages/core/src/__tests__/postgres/sync-workflow-ir-is-always-default.pg.test.ts": 1,
"packages/core/src/__tests__/postgres/task-dependency-mutation.pg.test.ts": 2,
"packages/core/src/__tests__/project-lane-vocabulary.test.ts": 1,
"packages/core/src/__tests__/postgres/task-dependency-mutation.pg.test.ts": 1,
"packages/core/src/__tests__/pure-lifecycle-predicates.test.ts": 3,
"packages/core/src/__tests__/reads-age-staleness-lane-hydration.test.ts": 1,
"packages/core/src/__tests__/renamed-lanes-staleness-and-blockers.test.ts": 2,
"packages/core/src/__tests__/reopen-semantics-by-role.test.ts": 1,
"packages/core/src/__tests__/store-overlap-repair-lanes-resolved.test.ts": 1,
"packages/core/src/__tests__/sync-workflow-ir-callsite-allowlist.test.ts": 2,
"packages/core/src/__tests__/task-age-staleness.test.ts": 1,
"packages/core/src/__tests__/task-merge-lanes-resolved.test.ts": 1,
"packages/core/src/__tests__/task-update-lanes-resolved.test.ts": 1,
"packages/core/src/__tests__/unarchive-target-lanes.test.ts": 1,
"packages/core/src/__tests__/workflow-ir-resolver.test.ts": 1,
"packages/core/src/__tests__/workflow-lifecycle-traits.test.ts": 3,
"packages/core/src/agent-store.ts": 2,
"packages/core/src/assigned-task-ranking.ts": 1,
"packages/core/src/async-chat-store.ts": 4,
"packages/core/src/async-mission-store-queries.ts": 3,
"packages/core/src/async-mission-store.ts": 2,
"packages/core/src/blocker-fanout.ts": 5,
"packages/core/src/async-mission-store-queries.ts": 1,
"packages/core/src/async-mission-store.ts": 1,
"packages/core/src/blocker-fanout.ts": 1,
"packages/core/src/chat-store.ts": 1,
"packages/core/src/command-center-live.ts": 1,
"packages/core/src/default-workflow-hooks.ts": 1,
"packages/core/src/duplicate-detection.ts": 1,
"packages/core/src/duplicate-intake.ts": 2,
"packages/core/src/eval-automation.ts": 1,
"packages/core/src/index.gate.ts": 1,
"packages/core/src/live-agent-count.ts": 1,
"packages/core/src/mobile-nav-primary-items.ts": 1,
"packages/core/src/near-duplicate-canonical.ts": 1,
"packages/core/src/postgres/migrations/0000_initial.sql": 1,
"packages/core/src/postgres/migrations/0029_planning_active_timing.sql": 1,
"packages/core/src/postgres/migrations/0035_fn_8543_mission_lineage_stop.sql": 1,
"packages/core/src/postgres/migrations/0036_chat_session_tags.sql": 2,
"packages/core/src/project-lane-vocabulary.ts": 3,
"packages/core/src/project-lane-vocabulary.ts": 1,
"packages/core/src/settings-schema.ts": 2,
"packages/core/src/store.ts": 9,
"packages/core/src/task-age-staleness.ts": 1,
"packages/core/src/task-merge.ts": 3,
"packages/core/src/task-priority.ts": 2,
"packages/core/src/store.ts": 2,
"packages/core/src/task-store/archive-lifecycle-2.ts": 2,
"packages/core/src/task-store/async-comments-attachments.ts": 1,
"packages/core/src/task-store/async-merge-coordination.ts": 2,
"packages/core/src/task-store/branch-and-pr-entities.ts": 3,
"packages/core/src/task-store/branch-group-ops.ts": 1,
"packages/core/src/task-store/comments-ops.ts": 2,
"packages/core/src/task-store/lifecycle-ops.ts": 2,
"packages/core/src/task-store/merge-queue-ops-2.ts": 4,
"packages/core/src/task-store/moves.ts": 2,
"packages/core/src/task-store/project-store-ops.ts": 1,
"packages/core/src/task-store/task-artifacts-ops.ts": 6,
"packages/core/src/task-store/task-creation.ts": 2,
"packages/core/src/task-store/task-id-integrity.ts": 1,
"packages/core/src/task-store/task-mutation-ops.ts": 1,
"packages/core/src/task-store/task-store-helpers.ts": 3,
"packages/core/src/task-store/task-update.ts": 5,
"packages/core/src/task-store/update-task-deps.ts": 7,
"packages/core/src/task-store/workflow-definitions.ts": 1,
"packages/core/src/task-store/workflow-integrity.ts": 1,
"packages/core/src/task-symbol-resolution.ts": 1,
"packages/core/src/task-timing.ts": 2,
"packages/core/src/team-analytics.ts": 1,
"packages/core/src/types/merge-queue.ts": 1,
"packages/core/src/workflow-analytics.ts": 1,
"packages/core/src/workflow-ir-resolver.ts": 3,
"packages/core/src/workflow-lifecycle-traits.ts": 2,
"packages/core/src/task-store/task-store-helpers.ts": 2,
"packages/core/src/task-store/task-update.ts": 1,
"packages/core/src/task-store/update-task-deps.ts": 5,
"packages/core/src/task-timing.ts": 1,
"packages/core/src/workflow-ir-resolver.ts": 2,
"packages/dashboard/app/App.tsx": 3,
"packages/dashboard/app/components/AgentDetailView.css": 1,
"packages/dashboard/app/components/ChatView.css": 2,
"packages/dashboard/app/components/PendingAttachmentPreviews.css": 1,
"packages/dashboard/app/components/TaskCard.tsx": 2,
"packages/dashboard/app/components/TaskDetailModal.css": 1,
"packages/dashboard/app/components/TaskReviewTab.tsx": 1,
"packages/dashboard/app/components/__tests__/AgentDetailView.mobile-scroll.test.tsx": 1,
"packages/dashboard/app/components/__tests__/AgentListModal.test.tsx": 1,
"packages/dashboard/app/components/__tests__/ListView.test.tsx": 1,
"packages/dashboard/app/components/__tests__/SubtaskBreakdownModal.test.tsx": 1,
"packages/dashboard/app/components/__tests__/TaskCard.test.tsx": 5,
"packages/dashboard/app/components/__tests__/TaskDetailModal.definition-actions.test.tsx": 1,
"packages/dashboard/app/components/__tests__/TaskDetailModal.models-progress-workflow.test.tsx": 1,
"packages/dashboard/app/components/__tests__/TaskReviewTab.test.tsx": 2,
"packages/dashboard/app/components/command-center/MissionControlPanel.tsx": 1,
"packages/dashboard/app/components/taskSorting.ts": 1,
"packages/dashboard/app/hooks/__tests__/useSessionFiles.test.ts": 1,
"packages/dashboard/app/hooks/useSessionFiles.ts": 2,
"packages/dashboard/app/styles.css": 1,
"packages/dashboard/app/utils/__tests__/appLifecycle.test.ts": 1,
"packages/dashboard/app/utils/__tests__/taskProgress.test.ts": 1,
"packages/dashboard/app/utils/__tests__/taskTiming.test.ts": 1,
"packages/dashboard/app/utils/appLifecycle.ts": 1,
"packages/dashboard/app/utils/prFeedback.ts": 1,
"packages/dashboard/app/utils/taskProgress.ts": 1,
"packages/dashboard/app/utils/taskTiming.ts": 1,
"packages/dashboard/src/__tests__/agent-task-link-terminal-lanes.test.ts": 1,
"packages/dashboard/src/__tests__/ai-session-diagnostics.test.ts": 1,
"packages/dashboard/src/__tests__/board-workflows.test.ts": 1,
"packages/dashboard/src/__tests__/chat.test.ts": 1,
"packages/dashboard/src/__tests__/command-center-analytics-column-flags.test.ts": 1,
"packages/dashboard/src/__tests__/devserver-manager.test.ts": 1,
"packages/dashboard/src/__tests__/devserver-preview-detect.test.ts": 1,
"packages/dashboard/src/__tests__/github-tracking-comments.test.ts": 1,
"packages/dashboard/src/__tests__/github-tracking-reconciler.test.ts": 2,
"packages/dashboard/src/__tests__/github-tracking-renamed-board.test.ts": 3,
"packages/dashboard/src/__tests__/github-tracking-state.test.ts": 1,
"packages/dashboard/src/__tests__/gitlab-parity-inventory-documentation.test.ts": 1,
"packages/dashboard/src/__tests__/gitlab-tracking-comments.test.ts": 1,
"packages/dashboard/src/__tests__/issue-image-attachments.test.ts": 1,
"packages/dashboard/src/__tests__/register-git-github.review-lanes.test.ts": 1,
"packages/dashboard/src/__tests__/register-signal-routes.test.ts": 1,
"packages/dashboard/src/__tests__/reliability-metrics.test.ts": 1,
"packages/dashboard/src/__tests__/routes-github.test.ts": 4,
"packages/dashboard/src/__tests__/routes-pull-requests.test.ts": 1,
"packages/dashboard/src/__tests__/routes-tasks.test.ts": 1,
"packages/dashboard/src/__tests__/sse.test.ts": 1,
"packages/dashboard/src/__tests__/task-lifecycle-lanes.test.ts": 1,
"packages/dashboard/src/github-tracking-reconciler.ts": 3,
"packages/dashboard/src/github-tracking-state.ts": 2,
"packages/dashboard/src/project-store-resolver.ts": 1,
"packages/dashboard/src/routes/__tests__/register-task-workflow-routes.move-bypassguards.test.ts": 2,
"packages/dashboard/src/routes/__tests__/register-task-workflow-routes.resolved-review-column.test.ts": 5,
"packages/dashboard/src/routes/register-command-center-routes.ts": 2,
"packages/dashboard/src/routes/register-git-github.ts": 1,
"packages/dashboard/src/routes/register-project-routes.ts": 2,
"packages/dashboard/src/routes/register-system-maintenance-routes.ts": 1,
"packages/dashboard/src/routes/register-task-workflow-routes.ts": 11,
"packages/dashboard/src/routes.ts": 3,
"packages/dashboard/vitest.config.ts": 2,
"packages/engine/src/__tests__/_workflow-vocabulary-fixture.ts": 1,
"packages/engine/src/__tests__/agent-assignment.test.ts": 2,
"packages/engine/src/__tests__/agent-tools-intake-column.test.ts": 1,
"packages/engine/src/__tests__/auto-heal-review-lane-callsite-audit.test.ts": 1,
"packages/engine/src/__tests__/backlog-pressure-reporter.test.ts": 1,
"packages/engine/src/__tests__/builtin-workflows-lifecycle.test.ts": 3,
"packages/dashboard/src/routes/__tests__/register-task-workflow-routes.resolved-review-column.test.ts": 4,
"packages/dashboard/src/routes/register-task-workflow-routes.ts": 4,
"packages/dashboard/vitest.config.ts": 1,
"packages/engine/src/__tests__/census-query-role-split.test.ts": 1,
"packages/engine/src/__tests__/census-reclassification-message.test.ts": 1,
"packages/engine/src/__tests__/ephemeral-worker-manager.test.ts": 2,
"packages/engine/src/__tests__/eval-followups.test.ts": 1,
"packages/engine/src/__tests__/executor-fast-mode-workflows.test.ts": 1,
"packages/engine/src/__tests__/executor-graph-failure-lanes-resolved.test.ts": 7,
"packages/engine/src/__tests__/executor-planner-lanes-resolved.test.ts": 1,
"packages/engine/src/__tests__/executor-resume-query-lanes.test.ts": 1,
"packages/engine/src/__tests__/executor-stale-spec-active-lanes.test.ts": 2,
"packages/engine/src/__tests__/executor-user-cancel.test.ts": 1,
"packages/engine/src/__tests__/executor-stale-spec-active-lanes.test.ts": 1,
"packages/engine/src/__tests__/heartbeat-terminal-lane.test.ts": 1,
"packages/engine/src/__tests__/lifecycle-column-census-ast.test.ts": 1,
"packages/engine/src/__tests__/lifecycle-column-census.test.ts": 2,
"packages/engine/src/__tests__/logger-mock-completeness.test.ts": 1,
"packages/engine/src/__tests__/notification-service.test.ts": 2,
"packages/engine/src/__tests__/plan-approval-hold-invariant.test.ts": 1,
"packages/engine/src/__tests__/planner-lanes-async-resolution.test.ts": 1,
"packages/engine/src/__tests__/planner-overseer.test.ts": 1,
"packages/engine/src/__tests__/lifecycle-column-census.test.ts": 1,
"packages/engine/src/__tests__/planning-continuation-terminal-lanes.test.ts": 1,
"packages/engine/src/__tests__/project-engine-merge-lane-resolved.test.ts": 2,
"packages/engine/src/__tests__/restart-recovery-coordinator.test.ts": 2,
"packages/engine/src/__tests__/review-handoff-lane.test.ts": 1,
"packages/engine/src/__tests__/scheduler-fanout-escalation-lanes.test.ts": 2,
"packages/engine/src/__tests__/scheduler-load-lane-union.test.ts": 2,
"packages/engine/src/__tests__/self-blocked-dependency-deadlock.pg.test.ts": 1,
"packages/engine/src/__tests__/self-healing-db-corruption.test.ts": 1,
"packages/engine/src/__tests__/stale-task-reporter.test.ts": 1,
"packages/engine/src/__tests__/task-completion-dependency-lanes.test.ts": 1,
"packages/engine/src/__tests__/transition-pending-recovery-deadlock.pg.test.ts": 2,
"packages/engine/src/__tests__/unwired-lane-parameter-guard.test.ts": 4,
"packages/engine/src/__tests__/usage-limit-detector.test.ts": 3,
"packages/engine/src/__tests__/workflow-file-scope-lease-caller-gap-live-e2e.pg.test.ts": 1,
"packages/engine/src/__tests__/workflow-graph-optional-step-fix.test.ts": 3,
"packages/engine/src/__tests__/workflow-ir-provenance-live-e2e.pg.test.ts": 2,
"packages/engine/src/__tests__/workflow-optional-role-param-caller-audit-live-e2e.pg.test.ts": 1,
"packages/engine/src/__tests__/workflow-planning-continuation-terminal-gap-live-e2e.pg.test.ts": 1,
"packages/engine/src/__tests__/workflow-settings-fallback-alignment.test.ts": 1,
"packages/engine/src/__tests__/workflow-sweep-sentinel-task-id-live-e2e.pg.test.ts": 1,
"packages/engine/src/__tests__/workflow-sync-selection-blast-radius-live-e2e.pg.test.ts": 2,
"packages/engine/src/__tests__/workflow-terminal-node-sync-resolution-live-e2e.pg.test.ts": 1,
"packages/engine/src/__tests__/workflow-timing-trait-live-e2e.pg.test.ts": 1,
"packages/engine/src/__tests__/workflow-unarchive-target-live-e2e.pg.test.ts": 1,
"packages/engine/src/agent-assignment.ts": 2,
"packages/engine/src/agent-heartbeat.ts": 2,
"packages/engine/src/agent-session-helpers.ts": 2,
"packages/engine/src/agent-tools.ts": 1,
"packages/engine/src/auto-merge-finalization.ts": 1,
"packages/engine/src/backlog-pressure-reporter.ts": 1,
"packages/engine/src/concurrency.ts": 5,
"packages/engine/src/ephemeral-worker-manager.ts": 2,
"packages/engine/src/eval-followups.ts": 2,
"packages/engine/src/ipc/__tests__/ipc-host.test.ts": 1,
"packages/engine/src/ipc/__tests__/ipc-worker.test.ts": 1,
"packages/engine/src/concurrency.ts": 4,
"packages/engine/src/merger.ts": 2,
"packages/engine/src/mission-feature-sync.ts": 2,
"packages/engine/src/mission-symbol-admission.ts": 2,
"packages/engine/src/notification/notification-service.ts": 3,
"packages/engine/src/mission-symbol-admission.ts": 1,
"packages/engine/src/pi.ts": 3,
"packages/engine/src/planner-lane-resolution.ts": 1,
"packages/engine/src/planner-overseer.ts": 1,
"packages/engine/src/project-engine.ts": 11,
"packages/engine/src/replan-target.ts": 4,
"packages/engine/src/restart-recovery-coordinator.ts": 4,
"packages/engine/src/runtime-primitives.ts": 1,
"packages/engine/src/project-engine.ts": 8,
"packages/engine/src/restart-recovery-coordinator.ts": 1,
"packages/engine/src/runtime-resolution.ts": 1,
"packages/engine/src/runtimes/__tests__/child-process-worker.test.ts": 3,
"packages/engine/src/runtimes/in-process-runtime.ts": 4,
"packages/engine/src/scheduler.ts": 9,
"packages/engine/src/stale-task-reporter.ts": 2,
"packages/engine/src/task-completion.ts": 1,
"packages/engine/src/triage.ts": 9,
"packages/engine/src/usage-limit-detector.ts": 5,
"packages/engine/src/workflow-node-handlers.ts": 1,
"packages/engine/src/workflow-work-processor.ts": 2,
"packages/engine/src/workflow-work-scheduler.ts": 1,
"packages/engine/src/worktree-pool.ts": 1,
"packages/engine/vitest.config.ts": 1,
"scripts/__tests__/check-inert-flag-seams.test.mjs": 1,
"scripts/check-fnxc-future-dates.mjs": 3,
"scripts/check-inert-flag-seams.mjs": 2,
"scripts/check-sql-column-literals.mjs": 1,
"packages/engine/src/scheduler.ts": 3,
"packages/engine/src/triage.ts": 6,
"packages/engine/src/workflow-work-processor.ts": 1,
"scripts/lib/lifecycle-column-census-ast.mjs": 3,
"scripts/lib/unwired-lane-parameter.mjs": 3,
"scripts/lifecycle-column-census.mjs": 12,
"scripts/lifecycle-column-census.mjs": 3,
"docs/dashboard-guide.md": 3,
"docs/testing.md": 1,
"docs/workflow-steps.md": 1