Skip to content

Commit 99e3c06

Browse files
committed
test: the wiring permission assertions must read executable lines only
Found by this gate's own ablation sweep. Revoking `contents: read` from the guard workflow -- which would kill the job in its checkout step, before the gate judges anything -- left the self-test GREEN, because the comment explaining why that scope is needed contains those same two words and the assertion scanned the whole file. A phantom check: green because of the prose describing the thing it was meant to verify. Both permission assertions now scan the comment-stripped workflow, as the package-manager assertion beside them already did, and the ablation reddens with the string still present in the file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
1 parent cd4084d commit 99e3c06

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

scripts/check-single-claim-paths.mjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,19 +501,27 @@ function selfTest() {
501501
// loses an activity type is not a weaker gate, it is a silent one.
502502
const wiringPath = join(ROOT, WIRING_WORKFLOW);
503503
const wiring = existsSync(wiringPath) ? readFileSync(wiringPath, 'utf8') : '';
504+
const wiringLines = wiring.split('\n').filter((line) => !/^\s*#/.test(line)).join('\n');
504505
t('the wiring workflow exists', wiring !== '', true);
505506
t('the wiring workflow runs this script', wiring.includes('node scripts/check-single-claim-paths.mjs'), true);
506507
t('the wiring passes the PR number (the wired-ness witness)', /PR_NUMBER:/.test(wiring), true);
507508
t('the wiring passes a token, without which no file list can be read', /GITHUB_TOKEN:/.test(wiring), true);
508509
for (const activity of ['opened', 'reopened', 'edited', 'synchronize']) {
509510
t(`the wiring subscribes to '${activity}' (a collision only exists while both PRs are open)`, new RegExp(`types:\\s*\\[[^\\]]*\\b${activity}\\b[^\\]]*\\]`).test(wiring), true);
510511
}
511-
t('the wiring can read pull requests', /pull-requests:\s*read/.test(wiring), true);
512+
// Both permission assertions read the COMMENT-STRIPPED workflow, and that
513+
// is not tidiness — it is a hole this file's own ablation sweep found. The
514+
// header comment above the permissions block has to be able to say the
515+
// words contents read to explain why the scope is there, and a naive scan
516+
// of the whole file therefore passed with the real grant DELETED: a phantom
517+
// check, green because of the prose describing it. Only executable lines
518+
// are scanned.
519+
t('the wiring can read pull requests', /pull-requests:\s*read/.test(wiringLines), true);
512520
// Naming a permissions block sets every unlisted scope to none, and this
513521
// job checks the repo out to reach this script. Without the contents scope
514522
// it dies in checkout, before judging anything.
515-
t('the wiring can read contents, which its checkout step requires', /contents:\s*read/.test(wiring), true);
516-
t('the guard job invokes no package manager (it needs node and nothing else)', /\b(pnpm|corepack|yarn|npm)\b/.test(wiring.split('\n').filter((l) => !/^\s*#/.test(l)).join('\n')), false);
523+
t('the wiring can read contents, which its checkout step requires', /contents:\s*read/.test(wiringLines), true);
524+
t('the guard job invokes no package manager (it needs node and nothing else)', /\b(pnpm|corepack|yarn|npm)\b/.test(wiringLines), false);
517525

518526
// --- The older gate must still be there, unweakened. This gate ADDS a
519527
// second question; it does not replace the card-keyed one.

0 commit comments

Comments
 (0)