You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
scripts/pm/check-governed-merges.mjs runs its --self-test at module scope — a second instance of #9757's class, now with a real importer that it can mask #9839
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:
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:
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.
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.
Triage first-touch grading (triage seat, session session_01JEhkB6ShK2HHDzozy7Qwgz): promoted to pm:queue · domain:devx confirmed (scripts/pm/) · type Bug — the module's header offers GOVERNED_SURFACES as a live, load-bearing import, and importing it under --self-test violates that import contract (side effects up to process.exit(1)).
Premises verified on origin/main @ 07bfd31cb: the unguarded dispatch sits at scripts/pm/check-governed-merges.mjs:1009-1011 (if (process.argv.includes('--self-test')) { selfTest(); }), while the main() dispatch at :810 IS guarded (invokedDirectly && …) — so the guard variable the fix needs already exists in the file. The live importer's workaround is at scripts/pm/check-governed-prose.mjs:87-90 (argv filtered around the dynamic import and restored), whose own comment says it should be deleted when the guard lands.
Scope: gate the :1009 dispatch with the existing invokedDirectly (direct node … --self-test, the form pnpm check:pm-governed-merges uses, keeps working), then delete the consumer workaround. Not held under #9757 (open class parent, no PR in flight): the producer-side fix is mechanical, the masking path is live today, and Prime-Directive fix-at-the-producer applies — but the PR should note it will adopt whatever guard spelling #9757 later standardizes. No open PR touches this file. Size/model suggestion: S, opus.
PM: FIXED upstream by PR #9897 — verified, closing.
This card reports that scripts/pm/check-governed-merges.mjs runs its --self-test at module scope, so importing the module fires its assertions inside the importer's own self-test.
Fixed. PR #9897 (#9777) added the guard as a declared in-place fix — its dev created the exposure by importing the module for proxyRearmPlan, found the correct shape already pinned by line 810 of that same file, and applied it. Verified on current origin/main:
1009: // `invokedDirectly` for the same reason line 810 carries it: this module is
1012: // assertions inside the importer's own `--self-test`, printing a second
1016: if (invokedDirectly && process.argv.includes('--self-test')) {
1017: selfTest();
The comment records why, citing the in-file precedent — so the next reader does not re-litigate it.
Closing. Not dispatched, no work owed.
⚠️ Note for the queue: this is the third card of mine closed today as already-fixed rather than dispatched (#9677, #9596, this one). I now re-derive dispatchability from the tree before claiming, not from the card's age — a card filed against a moving repo is a claim about a past commit.
Activity
scripts/pm/dispatch-gates.mjsdispatches its CLI at module top level, so the re-exports its header offers cannot be imported —importruns the tool andprocess.exit(2)s the importer #9757os-warren commentedon Aug 19, 2026
Triage first-touch grading (triage seat, session
session_01JEhkB6ShK2HHDzozy7Qwgz): promoted topm:queue·domain:devxconfirmed (scripts/pm/) · type Bug — the module's header offersGOVERNED_SURFACESas a live, load-bearing import, and importing it under--self-testviolates that import contract (side effects up toprocess.exit(1)).Premises verified on
origin/main@07bfd31cb: the unguarded dispatch sits atscripts/pm/check-governed-merges.mjs:1009-1011(if (process.argv.includes('--self-test')) { selfTest(); }), while themain()dispatch at:810IS guarded (invokedDirectly && …) — so the guard variable the fix needs already exists in the file. The live importer's workaround is atscripts/pm/check-governed-prose.mjs:87-90(argv filtered around the dynamic import and restored), whose own comment says it should be deleted when the guard lands.Scope: gate the
:1009dispatch with the existinginvokedDirectly(directnode … --self-test, the formpnpm check:pm-governed-mergesuses, keeps working), then delete the consumer workaround. Not held under #9757 (open class parent, no PR in flight): the producer-side fix is mechanical, the masking path is live today, and Prime-Directive fix-at-the-producer applies — but the PR should note it will adopt whatever guard spelling #9757 later standardizes. No open PR touches this file. Size/model suggestion: S, opus.Generated by Claude Code
claude commentedon Aug 19, 2026
PM: FIXED upstream by PR #9897 — verified, closing.
This card reports that
scripts/pm/check-governed-merges.mjsruns its--self-testat module scope, so importing the module fires its assertions inside the importer's own self-test.Fixed. PR #9897 (#9777) added the guard as a declared in-place fix — its dev created the exposure by importing the module for
proxyRearmPlan, found the correct shape already pinned by line 810 of that same file, and applied it. Verified on currentorigin/main:The comment records why, citing the in-file precedent — so the next reader does not re-litigate it.
Closing. Not dispatched, no work owed.
Generated by Claude Code