Measured while implementing #9525 (the governed-surface prose pin). Not repaired there: different defect class, and #9757 already owns the class plus the "pick one guard spelling" cleanup. Filed unassigned, severity for triage.
Facts
scripts/pm/check-governed-merges.mjs ends with an unguarded, argv-reading dispatch at module scope:
if(process.argv.includes('--self-test')){selfTest();}selfTest() calls process.exit(1) on failure. There is no entry-point guard, so the branch is taken by any importer whose own argv contains --self-test — the flag every sibling gate in this family uses, by convention (check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-governed-merges itself all spell it that way in package.json).
Measured on origin/main at 152bff8fc, from the first real importer (scripts/pm/check-governed-prose.mjs, which imports GOVERNED_SURFACES) before the workaround went in:
✓ check-governed-merges --self-test: 77 assertions (the unified governed predicate + near misses, ...)
✓ check-governed-prose self-test: 24 cases pass.
Two self-tests ran; only one was asked for.
Why it matters — the masking direction
The noise is cosmetic. The consequence is not: on the failure path the imported module calls process.exit(1)during the import, before a single case of the importer's own self-test reports. The importer's gate would then go red under another script's name, with the importer's own result never produced. That is the silent-success shape's mirror — a gate whose verdict is replaced by a neighbour's — and it is reachable in exactly the situation where the importer's self-test matters most.
Unlike #9757 this module is not merely unimportable in principle: GOVERNED_SURFACES is the register the whole governed-surface regime reads, so importing it is the correct and intended thing to do, and #9525 now does. The re-export is live and load-bearing.
Current state — worked around, not fixed
scripts/pm/check-governed-prose.mjs withholds the flag for the duration of the import:
constrealArgv=process.argv;process.argv=realArgv.filter((arg)=>arg!=='--self-test');const{GOVERNED_SURFACES}=awaitimport('./check-governed-merges.mjs');process.argv=realArgv;That is a consumer-side accommodation for a producer-side defect — the shape Prime Directive #12 says to fix at the producer. It is documented in place with this issue's reasoning, and it should be deleted when the guard lands.
Relation to #9757
Same class, sibling file. #9757 records the defect in scripts/pm/dispatch-gates.mjs, names the precedent (#6566 → PR #6695 on check-adr-0087-registration.mjs), and already carries the "the tree spells this guard four different ways" cleanup. This is a fifth spelling site and a fifth file; whoever settles the spelling there should sweep this one in the same pass. Filed as a sub-issue of #9757 rather than standalone for that reason.
Dedupe
search_issues for "check-governed-merges.mjs self-test runs on import entry-point guard argv" returns #9757 (open, the class), #6566/#8528/#9651 (closed, other scripts), and no card about this file's import semantics.
Generated by Claude Code
Measured while implementing #9525 (the governed-surface prose pin). Not repaired there: different defect class, and #9757 already owns the class plus the "pick one guard spelling" cleanup. Filed unassigned, severity for triage.
Facts
scripts/pm/check-governed-merges.mjsends with an unguarded, argv-reading dispatch at module scope:selfTest()callsprocess.exit(1)on failure. There is no entry-point guard, so the branch is taken by any importer whose own argv contains--self-test— the flag every sibling gate in this family uses, by convention (check:pm-skill-ratchet,check:pm-skill-id-lint,check:pm-governed-mergesitself all spell it that way inpackage.json).Measured on
origin/mainat152bff8fc, from the first real importer (scripts/pm/check-governed-prose.mjs, which importsGOVERNED_SURFACES) before the workaround went in:Two self-tests ran; only one was asked for.
Why it matters — the masking direction
The noise is cosmetic. The consequence is not: on the failure path the imported module calls
process.exit(1)during the import, before a single case of the importer's own self-test reports. The importer's gate would then go red under another script's name, with the importer's own result never produced. That is the silent-success shape's mirror — a gate whose verdict is replaced by a neighbour's — and it is reachable in exactly the situation where the importer's self-test matters most.Unlike #9757 this module is not merely unimportable in principle:
GOVERNED_SURFACESis the register the whole governed-surface regime reads, so importing it is the correct and intended thing to do, and #9525 now does. The re-export is live and load-bearing.Current state — worked around, not fixed
scripts/pm/check-governed-prose.mjswithholds the flag for the duration of the import:That is a consumer-side accommodation for a producer-side defect — the shape Prime Directive #12 says to fix at the producer. It is documented in place with this issue's reasoning, and it should be deleted when the guard lands.
Relation to #9757
Same class, sibling file. #9757 records the defect in
scripts/pm/dispatch-gates.mjs, names the precedent (#6566 → PR #6695 oncheck-adr-0087-registration.mjs), and already carries the "the tree spells this guard four different ways" cleanup. This is a fifth spelling site and a fifth file; whoever settles the spelling there should sweep this one in the same pass. Filed as a sub-issue of #9757 rather than standalone for that reason.Dedupe
search_issuesfor "check-governed-merges.mjs self-test runs on import entry-point guard argv" returns #9757 (open, the class), #6566/#8528/#9651 (closed, other scripts), and no card about this file's import semantics.Generated by Claude Code