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
Commit 66cbfa6
Browse filesBrowse the repository at this point in the historyBrowse files
feat(gates): give the closing-keyword parity gate a --body pre-flight mode (#17552)
* feat(gates): give the closing-keyword parity gate a --body mode
There was no runnable instrument a PR author could point at a body to
prove its closing keywords before the PR exists. The one grammar this
repo grades for agreement is spelled three times and every spelling is
private to its own file, so the only enforcement that reads a body is
the blocking gate that fires after the body is written.
This gate already builds the three shipped parsers as real RegExps from
the shipped bytes. `--body <FILE|->` runs exactly those over one body
and prints every hit with the parser id and its reference scope. No
fourth spelling is introduced -- a transcribed grammar is the defect the
sweep exists to catch, and it would go red on one.
Exit register, documented in the header: 0 when no registered parser
binds anything, 2 when at least one binds (the report, not a failure),
1 when the instrument did not run -- no path, an unreadable input, or a
parser that could not be extracted.
The case it exists for is a sentence written to prevent a close that
arms one, because no parser reads negation. Six new self-test cases
cover it: the negation body, a `Part of` body, the colon spelling on a
qualified reference, and two end-to-end drives of the mode through a
real process (a file and stdin) that grade the exit code.
Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK
Co-authored-by: Claude <noreply@anthropic.com>
* fix(gates): drive the body-mode self-test against THIS file, not the cwd's copy
The two end-to-end cases spawned `join(root, SELF)`, and `root` comes from
`repoRoot()` — the cwd. Launched from a sibling checkout the battery
therefore spawned THAT tree's copy of the script and graded a file nobody
had edited: measured, it reported `got 3` (the dependency-prerequisite
exit of an uninstalled sibling) instead of the exit register under test.
A harness that verified the wrong subject has verified nothing. The child
is now `fileURLToPath(import.meta.url)`, so the process under test is the
process that is running.
Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK
Co-authored-by: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: scripts/check-closing-keyword-parity.mjs
+159-1Lines changed: 159 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,7 @@
7
7
* node scripts/check-closing-keyword-parity.mjs # judge the shipped parsers
8
8
* node scripts/check-closing-keyword-parity.mjs --self-test # prove the battery can go red
9
9
* node scripts/check-closing-keyword-parity.mjs --list # the registry
10
+
* node scripts/check-closing-keyword-parity.mjs --body FILE # what binds in ONE body ("-" reads stdin)
10
11
*
11
12
* ## The seam
12
13
*
@@ -51,6 +52,40 @@
51
52
* and those differences are asserted too, so that a widening of the separator
52
53
* cannot quietly widen the scope with it.
53
54
*
55
+
* ## The body mode -- the same three parsers, one body
56
+
*
57
+
* `--body FILE` (or `-` for stdin) asks a different question of the SAME
58
+
* parsers: not "do the three agree" but "which of them binds what in THIS
59
+
* text". It is a pre-flight instrument for a PR body, runnable BEFORE the PR
60
+
* exists -- otherwise the only enforcement that reads a body is the blocking
61
+
* gate behind partof-closing-keyword-guard.yml, which fires after the body is
62
+
* already written.
63
+
*
64
+
* It adds NO grammar. It calls `loadParsers()` and runs whatever that returns,
65
+
* because a fourth spelling transcribed into a body checker is precisely the
66
+
* defect the sweep below exists to catch. Nor does it collapse the answer: the
67
+
* three differ on purpose in REFERENCE SCOPE, so a bare reference binding in
68
+
* two of them and not the third IS the answer, per parser, not noise.
69
+
*
70
+
* The case it exists for is prose written to PREVENT a close that arms one.
71
+
* A sentence of the shape `Merging this must not <verb> #N` binds in every
72
+
* parser scoped to the bare form, because none of them reads negation -- and
73
+
* neither does GitHub's own parser (the #10241 specimen below was closed out of
74
+
* a sentence saying it was not). The safe spelling is zero verbs beside the
75
+
* number. This mode makes that visible; it decides nothing and blocks nothing.
76
+
*
77
+
* Exit register -- three answers, deliberately distinct:
78
+
*
79
+
* 0 No registered parser binds anything in the body.
80
+
* 2 At least one parser binds. NOT a failure: it is the report, and the
81
+
* caller decides. It is 2 and not 1 because 1 already means this gate
82
+
* could not do its job, and "your body declares a close" must never read
83
+
* as "the instrument broke".
84
+
* 1 The instrument did not run: no path given, an unreadable file, or a
85
+
* parser that could not be extracted -- #4690 again, a harness that could
86
+
* not find its subject has verified nothing. Never a quiet zero-hit
87
+
* answer.
88
+
*
54
89
* ## What is asserted
55
90
*
56
91
* 1. EXTRACTION. Every registered parser is found in the shipped bytes. A
@@ -98,8 +133,10 @@
98
133
// dispatch-gates: whole-tree-population -- the sweep reads every tracked file (node_modules and dist aside) hunting the closing-keyword grammar, so a card adding prose or a workflow anywhere implicates it; the literals below are the parsers it grades.
console.error(`\ncheck-closing-keyword-parity --body: ${broken.length} of ${parsers.length} parser(s) could not be extracted, so ${where} was NOT fully read:\n`);
console.log(`check-closing-keyword-parity --body: OK (no registered parser binds a closing declaration in ${where}; ${parsers.length} parsers consulted).`);
433
+
return0;
434
+
}
435
+
constids=newSet(hits.map((h)=>h.id));
436
+
console.log(
437
+
`\ncheck-closing-keyword-parity --body: ${hits.length} closing declaration(s) in ${where}, `
438
+
+`bound by ${ids.size} of ${parsers.length} registered parser(s). Merging a PR with this body acts on them; `
439
+
+'the safe spelling for a reference you do NOT want acted on is zero verbs beside the number.',
440
+
);
441
+
return2;
442
+
}
443
+
346
444
functionrun(){
347
445
constroot=repoRoot();
348
446
constparsers=loadParsers(root);
@@ -472,6 +570,65 @@ function selfTest() {
472
570
'X7: a registered file that stopped carrying the grammar is caught',
473
571
);
474
572
573
+
// 5. The BODY MODE, on the fixtures sections 2-4 already grade. The
574
+
// references come from `REFS` and the refusals from `SCOPES`, so a case
575
+
// here cannot drift away from what this file asserts about the same three
576
+
// parsers -- and each expectation is the parser SET, because the per-parser
577
+
// scope split is the answer the mode exists to show.
assert(hit.status===2,`X11: \`--body FILE\` exits 2 on the negation body, got ${hit.status}`);
624
+
assert(hit.out.includes('h7-partof-closing-keyword'),`X11: the exit-2 report names the parser that binds, got: ${hit.out.trim()||'nothing'}`);
625
+
626
+
constclean=drive(['--body','-'],`Part of ${REFS.bare}`);
627
+
assert(clean.status===0,`X12: \`--body -\` exits 0 on a body that declares no close, got ${clean.status}`);
628
+
}finally{
629
+
rmSync(dir,{recursive: true,force: true});
630
+
}
631
+
475
632
if(failures.length===0){
476
633
console.log(`✓ check-closing-keyword-parity --self-test: ${checked} assertions, ${MUTATIONS.length} mutations of the shipped parsers each driven to red.`);
0 commit comments