Fourth unowned finding picked up after both batch PRs (#2783 core, #2785
engine) merged without addressing their reports. Completes the
`isNearDuplicateCanonicalInactive` seam alongside #2823, which fixed the
sixth (core) site.
## The defect
All five engine call sites — `self-healing.ts` ×2, `triage.ts` ×3 —
called the predicate without the canonical's resolved column flags, so
it fell back to the legacy `done`/`archived` ids. A canonical resting in
a renamed complete column (`shipped`) read as **still active**, so every
*"the canonical is inactive, so clear the marker"* branch failed to
fire.
The user-visible result is precisely the stranding FN-8356 was written
to remove: a card keeps its **"Needs your decision"** duplicate badge
pointing at work that shipped days ago, and no decision can resolve it —
the detail banner deliberately offers none for an inactive canonical.
## Measured
With the fix reverted, exactly one case flips:
```
✓ clears the FN-8353-shaped hidden decision for every inactive canonical state
× renamed vocabulary: clears the decision for a canonical resting in a RENAMED complete column
✓ renamed vocabulary: leaves the decision alone while the canonical is still in the WIP lane
✓ leaves active canonical decisions, user pauses, unrelated reasons, non-marker sources untouched
Tests 1 failed | 3 passed (4)
```
With it: `Tests 4 passed (4)`.
## Wiring is proven separately from behaviour
A behaviour test on one call site says nothing about the other four —
that is the failure this whole lane keeps re-finding, so I did not rely
on it.
With #2822's barrel-import fix applied locally, the seam gate's
staleness check **fails both engine allow-list entries as "now
supplied"** — it can no longer find an omitting call site in either
file. That is the proof for all five.
Consequence worth flagging: **when the second of #2822 / this PR lands,
the two engine entries in #2822 must be deleted.** CI fails until they
are, by design — the exemption cannot outlive its fix.
## Both negatives included
A canonical still in the WIP lane must **not** have its decision
cleared, under each vocabulary. Resolving real flags must not degrade
into "every column is terminal", which would dismiss a duplicate
decision the operator has not made yet.
## Design note
The helper is module-private in each file rather than shared.
`findColumn` is already duplicated exactly this way in
`hold-release.ts`, `merge-trait.ts`, and `workflow-capacity.ts` —
following the established shape beat adding a cross-module abstraction
for a bug fix.
## Verification
`pnpm test:gate` green · 27 triage suites / 387 tests green · engine
`tsc` 0 · lint 0 · changeset included.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>