Found while landing #13885 (PR #13982), which moved scripts/check-type-check-coverage.mjs's eleven refusals from exit 1 to exit 3. Filed rather than folded in: it is a different file, a different gate family, and — unlike that card — the current behaviour here is deliberate and argued in the source, so it is a decision to re-open rather than a defect to repair.
Measured at 92d273fe8
scripts/import-prerequisite.mjs is the shared frame for "can this gate load the package it imports?". Twenty-plus root gates import requireDependency / requireDefaultExport from it. It prints a PREREQUISITE NOT MET banner whose closing paragraph every importer inherits verbatim — and it exits 1:
exportfunctionreportPrerequisiteNotMet(importerUrl,verdict,measures){console.error(prerequisiteNotMetText(importerUrl,verdict,measures));process.exit(1);}and the inherited advisory says so in words:
(Exit code 1 — capture it BEFORE any pipe:
The reasoning is stated at requireDependency, and it is not a throwaway:
Exits 1, the code every real verdict uses: any wrapper treating non-zero as failure keeps behaving identically, and a second failure code would be a new contract nobody asked for. The reading a caller MUST be able to make is not in the code — it is in the printed text, which says nothing was measured.
Why it is worth re-deciding rather than leaving
Three other gates in the same lint family answer the same words with 3, and one of them says the split exists precisely because prose is not what an exit-code reader reads:
So the repo now says PREREQUISITE NOT MET in two exit codes, and the one that says 1 is the one inherited by the most gates. A reader or a gate-reconciling agent that learns "3 means nothing was measured" from three gates will read the twenty-plus that use this frame exactly backwards.
The counter-argument in the source is real and should be weighed, not brushed aside: no consumer today distinguishes 1 from 3 (every CI step treats any non-zero as failure), so the change buys nothing mechanical and costs a contract change. The 2026-08-07 meta-criterion — one operation with two implementations and inconsistent behaviour, the governed side wins — points the other way. That is a judgement, which is why this is a card and not a patch.
Deliberately not claimed
Generated by Claude Code
Generated by Claude Code
Found while landing #13885 (PR #13982), which moved
scripts/check-type-check-coverage.mjs's eleven refusals from exit 1 to exit 3. Filed rather than folded in: it is a different file, a different gate family, and — unlike that card — the current behaviour here is deliberate and argued in the source, so it is a decision to re-open rather than a defect to repair.Measured at
92d273fe8scripts/import-prerequisite.mjsis the shared frame for "can this gate load the package it imports?". Twenty-plus root gates importrequireDependency/requireDefaultExportfrom it. It prints aPREREQUISITE NOT METbanner whose closing paragraph every importer inherits verbatim — and it exits 1:and the inherited advisory says so in words:
The reasoning is stated at
requireDependency, and it is not a throwaway:Why it is worth re-deciding rather than leaving
Three other gates in the same lint family answer the same words with 3, and one of them says the split exists precisely because prose is not what an exit-code reader reads:
scripts/check-test-completeness.mjs—EXIT_PREREQUISITE_NOT_MET = 3, with a header arguing the class at length.scripts/check-dual-build-cjs-loads.mjs—EXIT_PREREQ = 3for "reads built output, tree has nodist/".scripts/check-type-check-coverage.mjs— 3 as of PR Answer every check-type-check-coverage refusal with exit 3, not a finding's 1 #13982.So the repo now says
PREREQUISITE NOT METin two exit codes, and the one that says 1 is the one inherited by the most gates. A reader or a gate-reconciling agent that learns "3 means nothing was measured" from three gates will read the twenty-plus that use this frame exactly backwards.The counter-argument in the source is real and should be weighed, not brushed aside: no consumer today distinguishes 1 from 3 (every CI step treats any non-zero as failure), so the change buys nothing mechanical and costs a contract change. The 2026-08-07 meta-criterion — one operation with two implementations and inconsistent behaviour, the governed side wins — points the other way. That is a judgement, which is why this is a card and not a patch.
Deliberately not claimed
Generated by Claude Code
Generated by Claude Code