fleet: live-agent-count.ts 6 → 0 — the no-enrichment fallback, marked not converted (#2762)

Unclaimed file, no overlap with any open fleet PR. Previous PR (#2756)
is merged, so this is my one open PR.

## Census

| | before | after |
|---|---|---|
| backlog | 447 | **441** |
| reviewed | 38 | 44 |
| this file | 6 | **0** |

`--strict` exit 0, baseline re-recorded in the same commit.

## Why marked, not converted

All six literals sit after a `??` or a `flags ? … :`. Each is reached
**only** when the caller supplied no trait flags and no enriched shape —
precisely the case `enrichRunningAgentTaskShape` (takes the IR) and
`enrichRunningAgentTaskShapeFromFlags` (takes board flags) exist to
remove. There is nothing to resolve from there, so the choice is not
convert-vs-literal; it is **known legacy answer vs a different guess.**

**And the guess is not neutral.** Running and Waiting are *complements*
over the same rows:

```ts
isWaitingAgentTask = !running && (columnIsIntakeOrHold ?? isLegacyPreImplementationColumn(column))
```

A card matching neither arm is reported as **neither running nor
waiting**, so the footer's queued total silently under-reports it.
Guessing "not WIP" or "not review" loses cards from the count; the
legacy id at least matches every pre-rename board. That is why this file
already carries a `DELIBERATE-LITERAL` marker above
`isLegacyPreImplementationColumn` with the same argument — this PR
extends it to the three functions holding the remaining fallbacks
(`enrichRunningAgentTaskShapeFromFlags`, `terminalKind`,
`isRunningAgentTask`).

**The fix for a renamed board is at the CALLER** — pass flags, or use
the IR-taking enricher. Noted at the site.

## Pattern note for the fleet

This is the third file I have taken where `N → 0` is reached by marking
rather than converting, and they share a shape worth naming: **a literal
after `??` or in the `else` of a `flags ?` ternary is a degraded-mode
answer, not an unconverted guard.** The trait path is already there and
already correct; the literal is what runs when the trait path has no
input. Deleting it does not remove a decision — it substitutes a
different one, silently, in exactly the states where nobody is looking
(first paint, un-enriched callers, pre-rename data).

## Verification

Core typecheck clean · `live-agent-count.test.ts` 11/11 · `--strict`
exit 0 · comments only, no behavior change.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-30 08:57:52 -07:00
committed by GitHub
parent 6386be6626
commit 3092c9c2bb
2 changed files with 32 additions and 1 deletions

View File

@@ -108,6 +108,22 @@ export function enrichRunningAgentTaskShape<T extends RunningAgentTaskShape>(tas
}
/** Attach the same traits from dashboard board-column flags without loading an IR. */
/*
FNXC:ConcurrencyIndicators 2026-07-30-03:40 DELIBERATE-LITERAL: the no-enrichment fallback only.
Every literal below sits after a `??` or a `flags ? … :` — it is reached ONLY when the caller
supplied no trait flags and no enriched shape, which is the case the enrichers exist to remove.
There is nothing to resolve from in that state, so converting is not possible; the choice is only
between the known legacy answer and a different guess.
That choice is not neutral here. Running and Waiting are COMPLEMENTS over the same rows, so a card
matching neither arm is reported as neither running nor waiting and the footer's queued total
silently under-reports it. Guessing "not WIP" or "not review" is therefore worse than the legacy id,
which at least matches every pre-rename board.
The fix for a renamed board is at the CALLER — pass flags, or use `enrichRunningAgentTaskShape`,
which takes the IR and resolves every role by trait. Same reasoning as the marker above
`isLegacyPreImplementationColumn`, which this file already records.
*/
export function enrichRunningAgentTaskShapeFromFlags<T extends RunningAgentTaskShape>(task: T, flags?: Pick<TraitFlags, "complete" | "archived" | "intake" | "hold" | "countsTowardWip" | "mergeOrchestration" | "mergeBlocker">): T & Required<Pick<RunningAgentTaskShape, "columnTerminalKind" | "columnIsIntakeOrHold" | "columnCountsTowardWip" | "columnIsReviewOrMerge">> {
return {
...task,
@@ -137,6 +153,12 @@ function hasLiveWorkflowStepLease(task: RunningAgentTaskShape): boolean {
return task.workflowStepResults?.some((result) => result.status === "pending") === true;
}
/*
FNXC:ConcurrencyIndicators 2026-07-30-03:40 DELIBERATE-LITERAL: the no-enrichment fallback only.
Full rationale at the first marker of this name above (enrichRunningAgentTaskShapeFromFlags): these
legacy-id literals are the flag-less fallback the enrichers exist to remove; converting here would
guess, and a wrong guess under-reports the queued total. Fix at the CALLER by passing flags/IR.
*/
function terminalKind(task: RunningAgentTaskShape): ColumnTerminalKind {
// Legacy literals are intentionally fixture-only degradation when workflow IR is unavailable.
return task.columnTerminalKind ?? (task.column === "done" ? "complete" : task.column === "archived" ? "archived" : "none");
@@ -150,6 +172,12 @@ function terminalKind(task: RunningAgentTaskShape): ColumnTerminalKind {
* A live `pending` workflow-step lease (e.g. an in-flight Code Review gate)
* counts in any non-terminal column, since gate sessions run with null status.
*/
/*
FNXC:ConcurrencyIndicators 2026-07-30-03:40 DELIBERATE-LITERAL: the no-enrichment fallback only.
Full rationale at the first marker of this name above (enrichRunningAgentTaskShapeFromFlags): these
legacy-id literals are the flag-less fallback the enrichers exist to remove; converting here would
guess, and a wrong guess under-reports the queued total. Fix at the CALLER by passing flags/IR.
*/
export function isRunningAgentTask(task: RunningAgentTaskShape): boolean {
if (task.paused || task.userPaused || terminalKind(task) !== "none") return false;
if (task.status === "planning") return true;

View File

@@ -8,7 +8,6 @@
"packages/core/src/task-store/async-comments-attachments.ts": 9,
"packages/dashboard/app/components/TaskContextMenu.tsx": 9,
"packages/dashboard/app/components/Column.tsx": 7,
"packages/core/src/live-agent-count.ts": 6,
"packages/core/src/task-merge.ts": 6,
"packages/dashboard/app/components/ListView.tsx": 6,
"packages/dashboard/src/routes/register-task-workflow-routes.ts": 5,
@@ -125,6 +124,8 @@
},
"deliberateByFile": {
"packages/dashboard/src/reliability-metrics.ts\u0000in-review": 4,
"packages/core/src/live-agent-count.ts\u0000in-progress": 2,
"packages/core/src/live-agent-count.ts\u0000in-review": 2,
"packages/dashboard/app/components/TaskCard.tsx\u0000triage": 2,
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000triage": 2,
"packages/engine/src/scheduler.ts\u0000in-progress": 2,
@@ -135,6 +136,8 @@
"packages/cli/src/commands/task.ts\u0000done": 1,
"packages/cli/src/extension.ts\u0000archived": 1,
"packages/cli/src/extension.ts\u0000done": 1,
"packages/core/src/live-agent-count.ts\u0000archived": 1,
"packages/core/src/live-agent-count.ts\u0000done": 1,
"packages/core/src/task-store/task-store-helpers.ts\u0000in-progress": 1,
"packages/core/src/task-store/task-store-helpers.ts\u0000todo": 1,
"packages/dashboard/app/components/command-center/MissionControlPanel.tsx\u0000done": 1,