Skip to content

Commit 3d38cc7

Browse files
committed
fix(scripts): scope the "is the guard wired" assertions to update()'s own body
The self-test's wiring cases scanned the WHOLE FILE for `judgeRecordability({ head:`, which matched the battery's own test code. An ablation proved the consequence: deleting the generator's call to the judge left the self-test GREEN at exit 0 — the assertion was pinning itself, and the battery it claimed to protect was a phantom check. Scoped to a slice of `update()`'s own body, with the slice bounds asserted so a rename cannot make the case vacuously green instead. The stamp case is scoped the same way, for the same reason. Also stops the off-pin case from crashing when the guard is ablated: reading `[0].includes(...)` off an empty array threw a TypeError where a named failure belongs, so the self-test redded for the right reason with the wrong words. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
1 parent 15ea1b1 commit 3d38cc7

1 file changed

Lines changed: 22 additions & 17 deletions

File tree

‎scripts/check-sdui-lockstep.mjs‎

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -841,10 +841,14 @@ export function selfTest() {
841841
'a checkout one commit off the pin is refused, not recorded',
842842
recKinds(judgeRecordability({ head: PIN_B, livePin: PIN_A })) === 'head-off-pin',
843843
);
844+
// `?? ''` rather than `[0].includes(...)`: with the guard ablated the array is
845+
// EMPTY, and an uncaught TypeError there is a crash where a named failure
846+
// belongs — the self-test would red for the right reason with the wrong words.
847+
const offPinText = judgeRecordability({ head: PIN_B, livePin: PIN_A })[0] ?? '';
844848
check(
845849
'the refusal names BOTH revisions, so the operator can see which way to move',
846-
judgeRecordability({ head: PIN_B, livePin: PIN_A })[0].includes(PIN_B.slice(0, 12))
847-
&& judgeRecordability({ head: PIN_B, livePin: PIN_A })[0].includes(PIN_A.slice(0, 12)),
850+
offPinText.includes(PIN_B.slice(0, 12)) && offPinText.includes(PIN_A.slice(0, 12)),
851+
offPinText || '(no finding at all)',
848852
);
849853
// Absence and malformation are loud here too, and they are DISTINGUISHED: a
850854
// pin that cannot be compared must not read as a checkout off the pin.
@@ -910,27 +914,28 @@ export function selfTest() {
910914
'the plain literal is still spelled too, so the file the gate opens is named as written',
911915
inCode.includes(`'${PIN_FILE}'`),
912916
);
913-
// The guard is only worth anything if `--update` actually consults it. A
914-
// `judgeRecordability` that nothing calls is a phantom check: every case above
915-
// stays green while the generator records from any tree it likes.
917+
// ⚠️ The two cases below are scoped to `update()`'s OWN BODY, never to the
918+
// whole file. Measured: a whole-file scan for `judgeRecordability({ head:`
919+
// matches the battery above, so deleting the generator's call left the
920+
// self-test GREEN — the assertion was pinning its own test code. Every
921+
// "is it wired" case has that shape; the slice is what makes it real.
922+
const updateOpen = inCode.indexOf('\nfunction update() {');
923+
const updateClose = inCode.indexOf('\n}\n', updateOpen);
916924
check(
917-
'the generator CALLS the recordability judge, so the cases above are not phantom',
918-
/judgeRecordability\(\{\s*head:/.test(inCode),
925+
"the generator's body is still addressable, so the cases below are not vacuous",
926+
updateOpen !== -1 && updateClose > updateOpen && updateClose - updateOpen > 1000,
927+
`open ${updateOpen}, close ${updateClose}`,
919928
);
920-
// Scoped to the record literal itself — a whole-file scan for the forbidden
921-
// spelling would match THIS assertion's own pattern and never be able to pass.
922-
// The bounds are asserted, so a rename cannot make the case vacuously green.
923-
const recordOpen = inCode.indexOf('\n const record = {');
924-
const recordClose = inCode.indexOf('\n writeFileSync(join(ROOT, RECORD_FILE)');
929+
const updateSrc = inCode.slice(updateOpen, updateClose);
930+
// A `judgeRecordability` nothing calls is a phantom check: every case in the
931+
// battery above stays green while the generator records from any tree it likes.
925932
check(
926-
"the generator's record literal is still addressable, so the case below is not vacuous",
927-
recordOpen !== -1 && recordClose > recordOpen,
928-
`open ${recordOpen}, close ${recordClose}`,
933+
'the generator CALLS the recordability judge, so that battery is not phantom',
934+
/judgeRecordability\(/.test(updateSrc),
929935
);
930-
const recordLiteral = inCode.slice(recordOpen, recordClose);
931936
check(
932937
'and it stamps `recordedAgainstPin` from the value it compared, not from a second read',
933-
/recordedAgainstPin: livePin,/.test(recordLiteral) && !/readFileSync/.test(recordLiteral),
938+
/recordedAgainstPin: livePin,/.test(updateSrc) && !/recordedAgainstPin: readFileSync/.test(updateSrc),
934939
);
935940

936941
// ── The floor: every declared battery RAN, and ran its cases (#13489) ───

0 commit comments

Comments
 (0)