**Rebased. The census claim in my original title was overtaken — this is
now a correction, not a conversion.**
## Census: 0 before, 0 after
#3261 got there first, by **recording** the fallback rather than
converting it. Its `DELIBERATE` reasoning is correct and I kept it
verbatim.
## What this corrects
That note says:
> Recorded rather than converted because **there is nothing to convert
TO**.
There is. **`isTerminalColumnRole` in core is this predicate, term for
term** — verified against `column-roles.ts` rather than assumed:
| | hand-rolled | `isTerminalColumnRole` |
|---|---|---|
| flags present | `flags.complete === true \|\| flags.archived === true`
| same, via the two role helpers |
| flags undefined | `columnId === "done" \|\| columnId === "archived"` |
same, via `LEGACY_COMPLETE/ARCHIVED_COLUMN_ID` |
And the helper's own doc names this exact case — it exists *"because the
pattern `column !== \"done\" && column !== \"archived\"` is the single
most repeated shape in the backlog"* and *"keeps callers from
re-deriving it and from accidentally dropping one half."*
**The rest of #3261's argument stands and is preserved.** The
undefined-flags arm is a **live** path, and treating an unreadable
workflow as non-terminal would count a finished card's retained worktree
against live capacity. That reasoning is about the *fallback's
existence*, not about *where the predicate lives* — and the shared
helper carries the identical fallback.
Second time in this file: `isWipColumnTask` two lines up records that it
was itself once *"a hand-rolled copy of `isWipColumnRole`"*. That's an
argument for the helper being easy to miss, not for anyone being
careless.
## Coverage, stated rather than implied
**Blinding this predicate to `false` leaves all 22 scheduler suites
green (365 tests)** — the capacity logic it feeds has no behavioural
coverage at all.
The added test pins the **lane vocabulary** (both renamed terminal
lanes, the non-terminal lanes, the legacy fallback). It does **not** pin
the capacity arithmetic, which stays unguarded and belongs to that
gate's owner. Under-counting is the dangerous direction: the commit
adding the gate reports `maxWorktrees=4` with **a fifth worktree
admitted**.
## Verification
- 23 scheduler suites — **368 green**; `tsc` clean
- Census 0 → 0; DELIBERATE count unchanged at 148; inert ratchet green
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>