Skip to content

Commit 572c33a

Browse files
baozhoutaoclaude
andauthored
Pin COMPOUND_ANCHOR_LEDGER's docblock counts to the table (#17391)
* fix(dev-tools): pin COMPOUND_ANCHOR_LEDGER's docblock counts to the table The docblock above COMPOUND_ANCHOR_LEDGER stated the table's total/genuine/ accidental composition in prose, and the prose had drifted from the table twice (22/15/7 -> 25/17/8 -> 29/19/10) without anything going red. Corrected the prose to the re-measured counts and added a --self-test block that reads the docblock's own stated numbers back out of this module's source, computes the real counts from COMPOUND_ANCHOR_LEDGER itself, and asserts they agree -- so a row added without updating the docblock reds there instead of drifting further unnoticed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU * fix(dev-tools): pin the ledger's distinct-spellings count too Review on #17391 flagged that "26 distinct spellings" is derivable from COMPOUND_ANCHOR_LEDGER the same way TOTAL/GENUINE/ACCIDENTAL are, and was left unpinned in the same paragraph the other three were just fixed in. Added a fourth --self-test assertion, same shape: read the docblock's "over N distinct spellings" clause out of this module's own source, compare against a fresh Set-based count from the ledger. Verified the leg-2 probe (a row added without touching the prose) still reds with this pin present, and that duplicating an existing row's name (no new spelling) correctly leaves this new pin green while TOTAL/GENUINE still catch the row count. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent a54ecaa commit 572c33a

1 file changed

Lines changed: 112 additions & 21 deletions

File tree

‎scripts/pm/dispatch-gates.mjs‎

Lines changed: 112 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,18 +4172,21 @@ const BARE_ENTRY_POINT_NAME = 'selfTest';
41724172
*
41734173
* ## The census, re-derived on this tree
41744174
*
4175-
* 209 code-position matches over the tracked JS/TS corpus. 187 are the bare
4176-
* `selfTest`; the remaining 22 carry compound names over 21 distinct spellings,
4177-
* and they are the rows below. Fifteen are genuine self-test batteries — the
4178-
* anchor firing on them is the anchor working. SEVEN are production code:
4175+
* 252 code-position matches over the tracked JS/TS corpus. 223 are the bare
4176+
* `selfTest`; the remaining 29 carry compound names over 26 distinct spellings,
4177+
* and they are the rows below. Nineteen are genuine self-test batteries — the
4178+
* anchor firing on them is the anchor working. TEN are production code:
41794179
*
4180-
* scripts/check-self-test-wired.mjs carriesSelfTest
4180+
* scripts/check-self-test-wired.mjs carriesSelfTest
41814181
* scripts/check-self-test-workflow-commands.mjs runSelfTest
4182-
* scripts/check-step-collectors.mjs selfTestTargets
4183-
* scripts/check-step-collectors.mjs selfTestDiscoveries
4184-
* scripts/measure-self-test-floor.mjs selfTestDefs
4185-
* scripts/pm/dispatch-gates.mjs selfTestOnlyCallables
4186-
* scripts/pm/dispatch-gates.mjs maskSelfTests
4182+
* scripts/check-step-collectors.mjs selfTestTargets
4183+
* scripts/check-step-collectors.mjs selfTestDiscoveries
4184+
* scripts/measure-durability-swallow-family.mjs selfTestMode
4185+
* scripts/measure-self-test-floor.mjs selfTestDefs
4186+
* scripts/pm/dispatch-gates.mjs selfTestOnlyCallables
4187+
* scripts/pm/dispatch-gates.mjs maskSelfTests
4188+
* scripts/pm/dispatch-gates.mjs selfTestCaseLines
4189+
* scripts/pm/dispatch-gates.mjs selfTestOnlyInvocation
41874190
*
41884191
* Every one of them is a gate that REASONS ABOUT self-tests, which is why they
41894192
* cluster: a tool that finds, spawns, counts or masks other scripts' self-tests
@@ -4192,16 +4195,17 @@ const BARE_ENTRY_POINT_NAME = 'selfTest';
41924195
*
41934196
* ## What it costs today: nothing, MEASURED, and that is the whole point
41944197
*
4195-
* Neutralising each of the seven one at a time and re-extracting moves no hint
4196-
* in any of the four files. The claim is therefore live rather than recalled —
4198+
* Neutralising each of the ten one at a time and re-extracting moves no hint
4199+
* in any of the six files. The claim is therefore live rather than recalled —
41974200
* and it is exactly the kind of claim that stops being true without anything
41984201
* going red, which is what the pin in this module's self-test exists to catch.
41994202
*
4200-
* The same measurement over the fifteen genuine rows is NOT zero, and that
4201-
* asymmetry is what makes the classification load-bearing rather than
4202-
* decorative: `fixtureSelfTest` drops `packages/spec/spec-changes.json` and
4203-
* `prePushIsArmedSelfTest` drops `.githooks/pre-push`, both fixture paths in
4204-
* `scripts/check-regen-pending.mjs`, both correctly refused. So "no
4203+
* The same measurement, redone over the table's current nineteen genuine rows,
4204+
* is still NOT zero, and that asymmetry is what makes the classification
4205+
* load-bearing rather than decorative: `fixtureSelfTest` drops
4206+
* `packages/spec/spec-changes.json` and `prePushIsArmedSelfTest` drops
4207+
* `.githooks/pre-push`, both fixture paths in `scripts/check-regen-pending.mjs`,
4208+
* both correctly refused. So "no
42054209
* compound-name match may contribute a hint" is FALSE as a blanket invariant;
42064210
* the invariant holds only over the accidental half, and only a classification
42074211
* can name that half.
@@ -4219,14 +4223,14 @@ const BARE_ENTRY_POINT_NAME = 'selfTest';
42194223
* that excludes the accidental one also unmasks a real self-test battery and
42204224
* readmits its fixture paths as hints — the fabricated-lead family this
42214225
* whole masker exists to refuse, traded for a silence that costs nothing.
4222-
* - **Special-casing this module's own path fixes two rows of seven.** The
4223-
* other five live in three other files, so the objection that a rename
4226+
* - **Special-casing this module's own path fixes four rows of ten.** The
4227+
* other six live in five other files, so the objection that a rename
42244228
* "fixes one instance and leaves the class" applies to it too, one file
42254229
* wider — and it would make the tool's self-scan differ from every other
42264230
* scan, which is a hazard of its own.
42274231
*
4228-
* ⇒ What ships is neither. The anchor keeps firing on all 22, the mask keeps
4229-
* blanking all 22, and the cost of the seven accidental ones is MEASURED on
4232+
* ⇒ What ships is neither. The anchor keeps firing on all 29, the mask keeps
4233+
* blanking all 29, and the cost of the ten accidental ones is MEASURED on
42304234
* every run instead of asserted in prose. Silence was the defect; the remedy is
42314235
* noise on the day it starts costing something.
42324236
*
@@ -4239,6 +4243,13 @@ const BARE_ENTRY_POINT_NAME = 'selfTest';
42394243
* measures, and keeps measuring, that masking it costs no hint. ⛔ Do not
42404244
* "repair" a red by renaming the function to dodge the anchor: the row is the
42414245
* record, and the next accidental name is the one nobody will notice.
4246+
*
4247+
* The TOTAL / GENUINE / ACCIDENTAL counts stated above are pinned the same
4248+
* way (#15310): `--self-test` computes them fresh from this table and checks
4249+
* the docblock's own prose against that computation, never against a second
4250+
* hand-typed constant. Prose that drifts from the table reds there, instead
4251+
* of drifting further unnoticed the way it had — twice — by the time #15310
4252+
* measured it.
42424253
*/
42434254
const COMPOUND_ANCHOR_LEDGER = [
42444255
['packages/lint/scripts/check-doc-formula-expressions.mjs', 'specSelfTest', false],
@@ -15508,6 +15519,86 @@ function selfTest() {
1550815519
t('…and so is the reachability helper beside it', names.includes('selfTestOnlyCallables'));
1550915520
}
1551015521

15522+
// #15310 — the docblock above states this table's TOTAL / GENUINE /
15523+
// ACCIDENTAL composition in prose, and prose does not move when a row is
15524+
// added: three integers that agree with EACH OTHER while jointly
15525+
// disagreeing with the table is exactly the shape that let this drift twice
15526+
// without ever looking wrong. The declared numbers are read out of this
15527+
// module's own docblock text, never re-typed as a second constant here, and
15528+
// checked against a count taken fresh from COMPOUND_ANCHOR_LEDGER itself —
15529+
// so a row added without touching the docblock reds here, and an edit to
15530+
// any unrelated line changes neither side and stays green.
15531+
{
15532+
const ownSource = readFileSync(nodePath.join(ROOT, 'scripts/pm/dispatch-gates.mjs'), 'utf8');
15533+
const ledgerAt = ownSource.indexOf('const COMPOUND_ANCHOR_LEDGER = [');
15534+
const before = ledgerAt < 0 ? '' : ownSource.slice(0, ledgerAt);
15535+
const blockStart = before.lastIndexOf('/**');
15536+
const blockEnd = before.lastIndexOf('*/');
15537+
// Line-wrapped JSDoc prose carries a `\n * ` between words that happen to
15538+
// fall on a line break — flattened to single spaces so a future rewrap of
15539+
// this paragraph cannot itself make a true reading look false.
15540+
const prose =
15541+
blockStart < 0 || blockEnd < 0
15542+
? ''
15543+
: ownSource
15544+
.slice(blockStart, blockEnd)
15545+
.replace(/\n[ \t]*\*[ \t]?/g, ' ')
15546+
.replace(/[ \t]+/g, ' ');
15547+
15548+
const total = COMPOUND_ANCHOR_LEDGER.length;
15549+
const genuine = COMPOUND_ANCHOR_LEDGER.filter(([, , accidental]) => !accidental).length;
15550+
const accidental = COMPOUND_ANCHOR_LEDGER.length - genuine;
15551+
const distinctSpellings = new Set(COMPOUND_ANCHOR_LEDGER.map(([, name]) => name)).size;
15552+
15553+
// Only as wide as the words this docblock actually spells; extending it is
15554+
// a deliberate edit, not silent tolerance for a new spelling.
15555+
const NUMBER_WORDS = {
15556+
zero: 0, one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9,
15557+
ten: 10, eleven: 11, twelve: 12, thirteen: 13, fourteen: 14, fifteen: 15, sixteen: 16,
15558+
seventeen: 17, eighteen: 18, nineteen: 19, twenty: 20,
15559+
};
15560+
const asCount = (word) => (/^\d+$/.test(word) ? Number(word) : NUMBER_WORDS[String(word).toLowerCase()]);
15561+
15562+
const remaining = prose.match(/the remaining (\d+) carry compound names/);
15563+
const allFiring = prose.match(/keeps firing on all (\d+), the mask keeps blanking all (\d+)/);
15564+
const genuineLine = prose.match(/([A-Za-z]+) are genuine self-test batteries/);
15565+
const accidentalLine = prose.match(/([A-Za-z]+) are production code:/);
15566+
const spellingsLine = prose.match(/over (\d+) distinct spellings/);
15567+
15568+
t(
15569+
'the docblock\'s TOTAL row count — "the remaining N carry compound names" and both "all N" claims — ' +
15570+
`agrees with the table (table: ${total}; declared: ` +
15571+
`${remaining ? remaining[1] : '<not found>'}/${allFiring ? allFiring[1] : '<not found>'}/` +
15572+
`${allFiring ? allFiring[2] : '<not found>'})`,
15573+
remaining !== null
15574+
&& allFiring !== null
15575+
&& Number(remaining[1]) === total
15576+
&& Number(allFiring[1]) === total
15577+
&& Number(allFiring[2]) === total,
15578+
);
15579+
t(
15580+
"the docblock's GENUINE count (\"N are genuine self-test batteries\") agrees with the table " +
15581+
`(table: ${genuine}; declared: ${genuineLine ? genuineLine[1] : '<not found>'})`,
15582+
genuineLine !== null && asCount(genuineLine[1]) === genuine,
15583+
);
15584+
t(
15585+
"the docblock's ACCIDENTAL count (\"N are production code:\") agrees with the table " +
15586+
`(table: ${accidental}; declared: ${accidentalLine ? accidentalLine[1] : '<not found>'})`,
15587+
accidentalLine !== null && asCount(accidentalLine[1]) === accidental,
15588+
);
15589+
// Distinct NAMES, not rows: `runSelfTest` is a genuine entry point in one
15590+
// file and an accidental one in another, so it is one spelling occupying
15591+
// two rows — the same reason COMPOUND_ANCHOR_KEYS has to carry the file in
15592+
// its key. This is derivable from the table exactly like the three above,
15593+
// so it is pinned the same way rather than left as the one clause in this
15594+
// paragraph a future row could still drift without going red.
15595+
t(
15596+
"the docblock's distinct-spellings count (\"over N distinct spellings\") agrees with the table " +
15597+
`(table: ${distinctSpellings}; declared: ${spellingsLine ? spellingsLine[1] : '<not found>'})`,
15598+
spellingsLine !== null && Number(spellingsLine[1]) === distinctSpellings,
15599+
);
15600+
}
15601+
1551115602
// A population DECLARED for this very scanner is referenced by no executing
1551215603
// code — being unreferenced is what such a declaration IS. Extending the mask
1551315604
// to value declarations was implemented and REFUSED on this evidence: over

0 commit comments

Comments
 (0)