**Consolidation branch for u11/u7.** Supersedes #2624. Contents changed
substantially while it sat unmerged — this body reflects what is
actually in it now.
## Measured with the authoritative census, not grep
`node scripts/lifecycle-column-census.mjs` — **triage guards 11 → 10.**
## 1. A real defect in merged code: a hold column is only a planner lane
if it precedes implementation
Found by greptile on #2616, verified by me, fixed here at the source
because that PR cannot land.
`resolveLifecycleColumns` returns `hold` as the **first** hold-trait
column in declared order, with no positional constraint relative to wip
(`workflow-lifecycle-traits.ts`: `hold:
first(LIFECYCLE_ROLE_FLAGS.hold)`). A workflow using a hold trait for a
**mid-pipeline wait** — a pause after implementation starts — therefore
had that column returned as its planner lane, and
`reconcileMissionFeatureState` demoted the feature to `triaged`. The
mission board reported started work as not-yet-started: silent, and
wrong in the direction that makes a roadmap lie.
This is my defect, introduced in #2610.
**Why it survived:** every lineage anyone has tested puts the hold *in
front* of wip, so the default and Ideas boards are unaffected and no
existing test could see it.
**The fix is positional, with a deliberate asymmetry.** A hold column
counts only when it appears before wip in declared order. When wip
cannot be located the hold is left **out** rather than guessed —
including it wrongly demotes live work on the roadmap, while excluding
it wrongly costs only a `triaged` transition the next reconcile
re-applies.
Mutation-verified: dropping the positional test fails the mid-pipeline
case and nothing else.
## 2. MissionControlPanel funnel aliases
Assessed and **deliberately not trait-converted**. These are heuristic
*name aliases* for a canonical SDLC stage — the matcher already accepts
`signal`/`backlog`/`ready`/`shipped` because it buckets arbitrary
boards, with an `other` fallback. Post-#2515 a default board's planning
cards sit in `todo` and count at the Todo stage, leaving Planning at
zero: the funnel reporting where cards *are*, not a guard that stopped
firing. Hoisted to a named set so it stops reading as unconverted.
This is the **DISPLAY-ALIAS** class the census still lacks — receiver
*is* a column id, purpose is presentation rather than a lifecycle
decision. `DocumentsView`'s status dot is the other one. Without that
bucket a ratchet will keep demanding conversions that make the product
worse.
## What I dropped, because main's version was better
The original #2624 carried a `TaskContextMenu` conversion. #2626 landed
`isPureIntakeColumn` — intake **without** hold — while mine treated any
intake-flagged column as intake. That's wrong for a **merged Planning
column**: it carries both traits, cards there wait for capacity and have
real actions, so I would have suppressed the menu where it belongs — a
new regression in place of the one I was fixing. Theirs is correct. Mine
is gone, along with its now-invalid test and a helper nothing else used.
## Verification
- merge gate green (482 + 132 + 10), engine tsc clean, dashboard tsc
clean, lint clean
- 7 planner-lane tests green, mutation-verified
No changeset: `@fusion/engine` and `@fusion/dashboard` are private.
🤖 Generated with [Claude Code](https://claude.com/claude-code)