Files
fusion/scripts
gsxdsm eed8ca55fc batch-dashboard-src: the planner metrics tool froze active runtime on a renamed execution lane (186 → 185) (#2842)
`packages/cli` and the plugin packages are at **zero** lifecycle guards,
so this picks up the nearest unowned work: the `packages/dashboard/src/`
remainder.

## The defect

`activeRuntimeMs` adds the wall-clock since `executionStartedAt` only
while the card is accruing work — the **WIP role** — but it was keyed on
the literal `in-progress`. On a board whose execution lane is renamed,
that live tail was dropped, so `fn_task_planner_get_task_metrics`
reported active time frozen at whatever the last completed segment left
in `cumulativeActiveMs`. The number stayed plausible, which is why
nothing surfaced it.

## The part worth reading: the wiring had no watcher, from either
direction

I wired the producer (`chat.ts` resolves the task's own lanes via
`wipColumnsForTask`) in the same commit, then checked whether that
wiring was actually covered. It was not:

- **Deleting the `wipColumns:` argument left the entire 3830-test
dashboard suite green.** The formatter's own tests inject the set by
hand, so they prove the *guard* and are structurally blind to whether
production fills it.
- **`check-inert-flag-seams.mjs` does not see it either.** It tracks
trailing optional **parameters**; this is a property inside an options
bag. That is a real gap in the checker — every seam expressed as an
options-bag property is currently unguarded. Reported here rather than
fixed, because #2822 and #2830 both already modify that script and a
third change would guarantee a three-way conflict.

So `createTaskPlannerMetricsTool` is exported and a second test drives
it, letting it do its **own** resolution against a renamed board.
Deleting the argument now fails 1 of 2.

## Census

| | before | after |
|---|---|---|
| COLUMN guards | 186 | **185** |
| `packages/dashboard/src/task-planner-chat-metrics.ts` | 1 | **0** |

Baseline re-recorded; `--strict` exits 0.

## Two findings I did NOT act on, deliberately

**1. `github-tracking-state.ts` keeps 2 counted guards and should.**
They are the documented degraded-mode arms of a fully-resolved
classifier (`completeLanes === undefined ? columnId === "done" : ...`).
Marking them `DELIBERATE-LITERAL` would drop the count by
**reclassification rather than conversion** — the exact move the
census's own strict-check warns about. Related: the census reports `0
are trait-fallback branches (already converted)`, yet these are
precisely that shape, so the trait-fallback classifier appears not to
recognise a ternary whose fallback arm is the literal. Worth a look by
whoever owns the census.

**2. Three pre-existing failures in `packages/dashboard/src/__tests__`,
unrelated to this change** — measured identically on `origin/main`
before and after:
- `planning-browser-e2e.test.ts:353`
- `register-model-routes-kimi-k3-supplemental.test.ts:60`
- `routes-tasks-near-duplicate.test.ts:274`

Flagging rather than touching them; per the standing rule they are
quarantine candidates, not appeasement candidates.

## Verification

Dashboard `tsc` clean, `pnpm lint` clean, census `--strict` 0,
`check-inert-flag-seams` 21/21 supplied, changeset lint clean. Targeted
suites: `task-planner-chat-metrics.test.ts` 8/8,
`task-planner-metrics-tool-wip-lanes.test.ts` 2/2.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 15:16:24 -07:00
..