refactor(coverage): verdict refuses an unstamped coverage directory
Summary
Layer 2 of 3 for #3468. Stack: main ← #3597 ← this PR ← #3598. It adds the reader and makes the
verdict consult it; the four staleness detectors still stand, and #3598 deletes them.
check:coverage-crap --base <ref> scored whatever Istanbul map it found. It now verifies the stamp #3597's
pass left beside those reports first, and refuses before computing anything when there is no stamp, when the
stamp names another commit or another working tree, when the file is not a stamp at all, or when the pass
records a narrowed run. Each is its own typed reason: absent, head, workingTree, unreadable, or the
selection that narrowed it (project, files, test-name, test-ids, shard, tags, unattested).
--all stays report-only and asks none of these questions, because nothing is attributed to a diff there.
The reported vocabulary is derived from the reason table, so a new selection without a sentence is a type
error rather than a silent unreadable.
One hand-written stamp could crash the verdict instead of being refused: runSelection may be any JSON, and
String(value) throws on {toString: null}. The reader tests the type first, pinned by the malformed-record
table.
Validation
pnpm check:affected --run exit 0 (63 checks) at 8e753ea90, foreground, under the gate lock. Evidence
from this head is in the comments: the full stamp, verifyCoverageStamp returning { stamp }, a files
stamp after a one-file pass, and the real check:coverage-crap refusal that map earns.