Closes the last of the five findings I reported to batch-core (#2783),
which merged without them. This one I held back twice on purpose; the
reason is now resolved.
## The dead code
`evaluateMergeBlockerGuard` had **exactly one reference in the repo: its
own declaration.** Never called, never re-exported from
`index.ts`/`index.gate.ts`, never registered as a trait hook. Its
`lifecycleColumns` conversion was applied to dead code, and the census
counted it as progress.
## Why I would not delete it earlier, and what changed
I twice declined this, because no production `"guard"` trait hook is
registered anywhere in the codebase — the only
`registerTraitHookImpl(..., "guard", ...)` is in a test. If a
registration had been dropped, that would be a real product bug and this
function would be its evidence, so deleting it would have destroyed the
breadcrumb.
**It is not missing.** Merge blocking is enforced inline in
`task-store/moves.ts` (~645 and ~821) via `getTaskMergeBlocker`, gated
on the **resolved trait flags** (`toFacts.flags.complete` +
`fromFacts.flags.mergeBlocker`) rather than on column ids — a better
implementation than the one being deleted. The logic moved; this
function, and a file-header line crediting a never-existent
`evaluateDefaultWorkflowGuards` reader, were left behind.
The header now records where the guard actually lives, so the next
person does not repeat the investigation I just did.
Also removed: `GuardVerdict` (its return type, used nowhere else) and
the orphaned `getTaskMergeBlocker` import — the latter caught by lint,
not by me.
## The gap this exposed
The allow-list staleness check only fired for a seam the scan still
**finds** — it asks *"is this site supplied now?"*. Delete the
declaration and the name is never iterated, so its entry sits in the
list forever, exempting nothing and misreporting what is tolerated.
I found this by deleting the function and watching the gate stay
**silent** about its leftover entry.
**Measured:** an `ALLOWED` entry naming a non-existent seam now fails
with `no such seam declared any more; remove its ALLOWED entry`;
removing the probe returns exit 0. The failure header is reworded, since
"the sites are supplied now" no longer covers both reasons.
This is the fourth blind spot closed in this check, and like the others
it was found by exercising the gate rather than reading it.
## Verification
`pnpm test:gate` green · `tsc -p packages/core` 0 · lint 0 · gate now
reports **20** seams (was 21 — the drop is this deletion).
No changeset: deleting unreachable internal code with no exported
surface is behaviour-preserving.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>