## The pattern
Four review findings dispatched to me in a single day were the **same
defect**: a guard converted to role resolution while the function it
*feeds* still filters on the literal. The resolved guard admits a custom
column, the literal collaborator rejects it, and **nothing errors** —
the endpoint returns `repaired: 0` and reads as converted.
| PR | resolved side | literal collaborator |
|---|---|---|
| #2700 | review guard | `reconcileInReviewBranchRebind` filters `===
"in-review"` |
| #2700 | retry guard | `isInReviewMissingWorktreeSessionStartFailure`
likewise |
| #2698 | role-aware tabs | reconciliation effects still compare
`"done"` / `"in-review"` |
| #2688 | role-derived flags | memos and a `useState` capture keyed on
the stale value |
Since opening this I have been handed **two more** of the identical
shape (#2701, #2702). It is not a coincidence; it is what a conversion
phase produces by default.
## What this adds
A file where **both vocabularies are live** is where that can happen, so
the census now names those files.
**Measured: 23 of 134 guard-bearing files, holding 311 of 686 guards** —
and the top of the list is exactly where the findings landed:
```
MIXED-VOCABULARY files (a role resolver AND legacy literals): 23, holding 311 guards
110 packages/engine/src/self-healing.ts
57 packages/engine/src/executor.ts
26 packages/engine/src/scheduler.ts
20 packages/dashboard/src/routes/register-task-workflow-routes.ts
```
## Report-only, deliberately
A partially converted file is the **expected** state during a conversion
phase. Gating this would punish correct in-progress work and would be
routed around within a day. What it buys is that a reviewer of a listed
file knows to check the collaborators of anything converted — which is
what this repo's **Surface Enumeration** rule already requires, and what
each of those PRs missed.
The rule exists. The fleet work order does not mention it, so reviewers
are catching these one site at a time.
## Verification
Five tests, both directions: flags a mixed file; does **not** flag a
fully literal one (or the entire backlog lights up and the signal
carries no information); does **not** flag a fully converted one; does
not match a resolver name inside a longer identifier (the
`hold`-inside-`threshold` trap from #2677); survives an unreadable file.
**Mutation: dropping the resolver condition fails 2 of 38.**
The helper lives in the **lib**, not the CLI — importing the CLI
executes it and calls `process.exit`, so nothing defined there is
reachable from a test. I found that by trying.
38 census tests green · `--strict` and `--compare` exit 0 · lint clean ·
gate green (487 + 158 + 10 + 71). **No census numbers change.**