Skip to content

Commit fe8e5b3

Browse files
committed
test(scripts): floor measure-position-name-fold-census' self-test on a registered battery
The 13 `if (...) problems.push(...)` assertion sites in `selfTest()` are each wrapped verbatim in the `check(() => { ... })` thunk PR #15198 landed. The sink here is FAILURE-ONLY, so routing `problems.push` itself through `registerCase()` would have inverted the floor rather than installing it: a green run would register nothing and the battery would read DID NOT RUN. Zero named banners, so one hoisted battery, floored at the 24 registrations measured on a run (four of the thirteen sites sit inside loops: 9 + 4 + 4 + 2 + 5). The floor lives inside the `!quiet` branch. `main()` gates the PRODUCTION census on `selfTest({ quiet: true })`, which prints no verdict and so makes no claim for a floor to guard; evaluating it there would let a roster edit change what a census run outputs. Both production modes are byte-identical to the base tree. One site stays outside the roster and says so in place: the `catch` arm of the AUDIT_CONTROLS loop ends in `continue`, illegal inside the thunk's arrow function, and rewriting that control flow is exactly what the verbatim rule forbids. Its sibling in the same loop body is floored, so a loop that stops running still reds. Part of #13799 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
1 parent de6303c commit fe8e5b3

1 file changed

Lines changed: 193 additions & 52 deletions

File tree

‎scripts/measure-position-name-fold-census.mjs‎

Lines changed: 193 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -693,75 +693,167 @@ const AUDIT_CONTROLS = [
693693
// handshake is a flag rather than a returned sentinel.
694694
let selfTestReachedVerdict = false;
695695

696+
// -- The self-test's own battery roster and floor (#13489) ------------------
697+
//
698+
// Reaching the verdict used to be this self-test's ONLY success condition, so
699+
// "every control held" and "the controls never ran" printed the same line.
700+
// Closed the way PR #13487 validated on check-doc-authoring: what is pinned is
701+
// the registered NAMES, not a number.
702+
//
703+
// This file's assertion sites are `if (...) problems.push(...)` -- a
704+
// FAILURE-ONLY sink. Routing `problems.push` itself through `registerCase()`
705+
// would register a case only when a control FAILS: a fully green run would
706+
// register 0 and the battery would read DID NOT RUN, the floor inverted rather
707+
// than installed. So the sites are counted by the `check(() => { ... })` THUNK
708+
// PR #15198 measured: the existing `if (...) problems.push(...)` is carried in
709+
// VERBATIM, no condition is touched, and registration happens whether or not
710+
// the site fires.
711+
//
712+
// This file declares ONE battery, opened at the top of the self-test body: it
713+
// carries ZERO named section banners, fewer than the two the sectioning
714+
// criterion needs, and a comment is NOT promoted to a section head. The hoisted
715+
// single battery is the shape PR #14896, PR #15003 and PR #15217 landed.
716+
//
717+
// ⭐ ONE site stays OUTSIDE the roster, deliberately: the `catch` arm of the
718+
// AUDIT_CONTROLS loop (`audit control threw: ...`) ends in `continue`, which is
719+
// illegal inside the thunk's arrow function. Wrapping it would mean rewriting
720+
// that control flow -- exactly what the verbatim rule forbids. Its sibling in
721+
// the same loop body, `if (!ac.expect(result))`, IS floored, so a loop that
722+
// stops running still reds. This is the residue recipe A's non-table
723+
// assertions carry too (PR #15286's `extra` call).
724+
//
725+
// The count is a FLOOR, not an equality -- adding controls is ordinary work and
726+
// must not red. A battery BELOW its floor means cases stopped running; the
727+
// remedy is to find what stopped registering, never to lower the number. Four
728+
// of the thirteen floored sites sit inside `for` loops, so the count is the
729+
// number of times a site is REACHED on a run, measured on a run.
730+
const SELF_TEST_BATTERIES = Object.freeze({
731+
'measure-position-name-fold-census self-test': 24,
732+
});
733+
734+
// DELETING an entry silences that battery's floor exactly as effectively as
735+
// zeroing it, so the roster's own size is pinned too.
736+
const SELF_TEST_BATTERY_FLOOR = 1;
737+
738+
// The key an assertion is filed under when no battery is open. It is not a
739+
// declared battery, so it reds by the same set difference rather than silently
740+
// inflating whichever battery happened to run last.
741+
const UNATTRIBUTED_BATTERY = '(no battery open)';
742+
696743
function selfTest({ quiet = false } = {}) {
744+
// The battery ledger this self-test's floor is evaluated against (#13489).
745+
// `battery()` opens a battery; every site below is attributed to the one most
746+
// recently opened, so a section that stops running stops registering and
747+
// names ITSELF at the floor rather than going quiet.
748+
const batterySeen = new Map();
749+
let openBattery = null;
750+
const battery = (name) => {
751+
openBattery = name;
752+
};
753+
const registerCase = () => {
754+
const b = openBattery ?? UNATTRIBUTED_BATTERY;
755+
batterySeen.set(b, (batterySeen.get(b) ?? 0) + 1);
756+
};
757+
battery('measure-position-name-fold-census self-test');
758+
// The thunk: it registers the case and then runs the existing site VERBATIM,
759+
// so no control's condition is inverted or rewritten and the `problems` sink
760+
// keeps its own semantics.
761+
const check = (fn) => {
762+
registerCase();
763+
fn();
764+
};
697765
const problems = [];
698766
const c = census();
699767

700768
for (const name of CONTROLS.builtinPositions) {
701-
if (!c.positions.has(name)) {
702-
problems.push(`parse-integrity: built-in POSITION \`${name}\` was not found. The scanner has drifted`
703-
+ ' off the declaration shape; every number below it would be an under-count.');
704-
}
769+
check(() => {
770+
if (!c.positions.has(name)) {
771+
problems.push(`parse-integrity: built-in POSITION \`${name}\` was not found. The scanner has drifted`
772+
+ ' off the declaration shape; every number below it would be an under-count.');
773+
}
774+
});
705775
}
706776
for (const name of CONTROLS.builtinPermissionSets) {
707-
if (!c.permissionSets.has(name)) {
708-
problems.push(`parse-integrity: built-in PERMISSION SET \`${name}\` was not found. Same failure, other axis.`);
709-
}
777+
check(() => {
778+
if (!c.permissionSets.has(name)) {
779+
problems.push(`parse-integrity: built-in PERMISSION SET \`${name}\` was not found. Same failure, other axis.`);
780+
}
781+
});
710782
}
711783

712784
const a = CONTROLS.junctionAnchor;
713-
if (!c.bindings.some((b) => b.position === a.position && b.set === a.set)) {
714-
problems.push(`positive control (junction) NOT classified as a junction binding: `
715-
+ `${a.position} -> ${a.set}\n ${a.why}`);
716-
}
717-
if (c.nameFolds.some((f) => f.name === a.position)) {
718-
problems.push(`positive control (junction) was reported as a NAME-DEPENDENCY: ${a.position}\n ${a.why}`);
719-
}
785+
check(() => {
786+
if (!c.bindings.some((b) => b.position === a.position && b.set === a.set)) {
787+
problems.push(`positive control (junction) NOT classified as a junction binding: `
788+
+ `${a.position} -> ${a.set}\n ${a.why}`);
789+
}
790+
});
791+
check(() => {
792+
if (c.nameFolds.some((f) => f.name === a.position)) {
793+
problems.push(`positive control (junction) was reported as a NAME-DEPENDENCY: ${a.position}\n ${a.why}`);
794+
}
795+
});
720796

721797
const b = CONTROLS.nameFoldAnchor;
722798
const fold = c.nameFolds.find((f) => f.name === b.name);
723-
if (!fold) {
724-
problems.push(`positive control (name-fold) NOT detected: ${b.name}\n ${b.why}`);
725-
} else if (!fold.permissionSets.some((s) => s.kind === 'artifact')) {
726-
problems.push(`positive control (name-fold) ${b.name} was detected, but its permission-set half is not`
727-
+ ' the composed artifact -- the control is passing for the wrong reason.');
728-
}
799+
check(() => {
800+
if (!fold) {
801+
problems.push(`positive control (name-fold) NOT detected: ${b.name}\n ${b.why}`);
802+
} else if (!fold.permissionSets.some((s) => s.kind === 'artifact')) {
803+
problems.push(`positive control (name-fold) ${b.name} was detected, but its permission-set half is not`
804+
+ ' the composed artifact -- the control is passing for the wrong reason.');
805+
}
806+
});
729807

730808
const n = CONTROLS.negative;
731-
if (c.nameFolds.some((f) => f.name === n.position)) {
732-
problems.push(`negative control reported as a name-fold: ${n.position}\n ${n.why}`);
733-
}
734-
if (!c.bindings.some((x) => x.position === n.position && x.set === n.set)) {
735-
problems.push(`negative control ${n.position} -> ${n.set} was not seen as a junction binding at all;`
736-
+ ' the binder scan is blind, so every junction-bound pair would be misfiled as unbound.');
737-
}
809+
check(() => {
810+
if (c.nameFolds.some((f) => f.name === n.position)) {
811+
problems.push(`negative control reported as a name-fold: ${n.position}\n ${n.why}`);
812+
}
813+
});
814+
check(() => {
815+
if (!c.bindings.some((x) => x.position === n.position && x.set === n.set)) {
816+
problems.push(`negative control ${n.position} -> ${n.set} was not seen as a junction binding at all;`
817+
+ ' the binder scan is blind, so every junction-bound pair would be misfiled as unbound.');
818+
}
819+
});
738820

739821
const sb = CONTROLS.secondBinder;
740-
if (!c.bindings.some((x) => x.position === sb.position && x.set === sb.set)) {
741-
problems.push(`second-binder control missed: \`${sb.position} -> ${sb.set}\` is a junction binding declared by`
742-
+ ' a binder whose list is NOT named POSITION_PERMISSION_SET_BINDINGS. The scan is recognising one app\'s'
743-
+ ' spelling again, so other apps\' junction rows are invisible and their positions read as inert.');
744-
}
745-
if (c.inert.some((i) => i.name === sb.position)) {
746-
problems.push(`second-binder control: \`${sb.position}\` was reported INERT while a binder binds it.`);
747-
}
748-
if (!c.nameFolds.some((f) => f.name === 'sales_manager')) {
749-
problems.push('a position junction-bound to a DIFFERENT set must still count as a name-fold on its own name'
750-
+ ' (sales_manager is bound to crm_sales_user and still folds onto the HotCRM `sales_manager` set).'
751-
+ ' Losing this would tell 要点 2 the pair is already governed.');
752-
}
822+
check(() => {
823+
if (!c.bindings.some((x) => x.position === sb.position && x.set === sb.set)) {
824+
problems.push(`second-binder control missed: \`${sb.position} -> ${sb.set}\` is a junction binding declared by`
825+
+ ' a binder whose list is NOT named POSITION_PERMISSION_SET_BINDINGS. The scan is recognising one app\'s'
826+
+ ' spelling again, so other apps\' junction rows are invisible and their positions read as inert.');
827+
}
828+
});
829+
check(() => {
830+
if (c.inert.some((i) => i.name === sb.position)) {
831+
problems.push(`second-binder control: \`${sb.position}\` was reported INERT while a binder binds it.`);
832+
}
833+
});
834+
check(() => {
835+
if (!c.nameFolds.some((f) => f.name === 'sales_manager')) {
836+
problems.push('a position junction-bound to a DIFFERENT set must still count as a name-fold on its own name'
837+
+ ' (sales_manager is bound to crm_sales_user and still folds onto the HotCRM `sales_manager` set).'
838+
+ ' Losing this would tell 要点 2 the pair is already governed.');
839+
}
840+
});
753841

754842
const bleed = CONTROLS.isDefaultBleed;
755-
if (!c.bindings.some((x) => x.position === 'everyone' && x.set === bleed.bound)) {
756-
problems.push(`regression control: \`${bleed.bound}\` declares \`isDefault: true\` and must appear as an`
757-
+ ' `everyone` auto-bind. It does not, so the isDefault scan has stopped seeing declarations it owns.');
758-
}
759-
for (const set of bleed.unbound) {
760-
if (c.bindings.some((x) => x.position === 'everyone' && x.set === set)) {
761-
problems.push(`regression control fired again: \`everyone -> ${set}\` was reported as a junction binding,`
762-
+ ` but ${set} declares no \`isDefault\`. The isDefault look-ahead is reading past the declaration's own`
763-
+ ' object literal again -- see CONTROLS.isDefaultBleed.');
843+
check(() => {
844+
if (!c.bindings.some((x) => x.position === 'everyone' && x.set === bleed.bound)) {
845+
problems.push(`regression control: \`${bleed.bound}\` declares \`isDefault: true\` and must appear as an`
846+
+ ' `everyone` auto-bind. It does not, so the isDefault scan has stopped seeing declarations it owns.');
764847
}
848+
});
849+
for (const set of bleed.unbound) {
850+
check(() => {
851+
if (c.bindings.some((x) => x.position === 'everyone' && x.set === set)) {
852+
problems.push(`regression control fired again: \`everyone -> ${set}\` was reported as a junction binding,`
853+
+ ` but ${set} declares no \`isDefault\`. The isDefault look-ahead is reading past the declaration's own`
854+
+ ' object literal again -- see CONTROLS.isDefaultBleed.');
855+
}
856+
});
765857
}
766858

767859
for (const ac of AUDIT_CONTROLS) {
@@ -772,9 +864,11 @@ function selfTest({ quiet = false } = {}) {
772864
problems.push(`audit control threw: ${ac.label} -- ${e?.message}`);
773865
continue;
774866
}
775-
if (!ac.expect(result)) {
776-
problems.push(`audit control FAILED: ${ac.label}\n got: ${JSON.stringify(result)}`);
777-
}
867+
check(() => {
868+
if (!ac.expect(result)) {
869+
problems.push(`audit control FAILED: ${ac.label}\n got: ${JSON.stringify(result)}`);
870+
}
871+
});
778872
}
779873

780874
if (problems.length > 0) {
@@ -783,6 +877,53 @@ function selfTest({ quiet = false } = {}) {
783877
return 1;
784878
}
785879
if (!quiet) {
880+
// -- The floor: the declared battery RAN, and ran its cases (#13489) ----
881+
//
882+
// Evaluated after every site has had its chance and BEFORE the verdict, so
883+
// the success line below can only be printed by a run in which the set of
884+
// batteries that registered cases EQUALS the set declared.
885+
//
886+
// ⭐ It lives INSIDE the `!quiet` branch on purpose. `main()` gates the
887+
// PRODUCTION path on `selfTest({ quiet: true })`, which prints no verdict
888+
// and therefore makes no claim for a floor to guard; evaluating the floor
889+
// there would let a roster edit change what a census run outputs. The floor
890+
// belongs to the `--self-test` verdict, which is the line that would
891+
// otherwise claim controls hold that never ran.
892+
//
893+
// It reports in this file's own idiom -- a stderr block and a non-zero
894+
// return -- and returns BEFORE `selfTestReachedVerdict` is set, so a breach
895+
// reds through the #13798 handshake as well as through the exit code.
896+
const floorFailures = [];
897+
const declaredBatteries = Object.keys(SELF_TEST_BATTERIES);
898+
if (declaredBatteries.length < SELF_TEST_BATTERY_FLOOR) {
899+
floorFailures.push(
900+
`SELF_TEST_BATTERIES declares ${declaredBatteries.length} batteries, below the pinned `
901+
+ `${SELF_TEST_BATTERY_FLOOR} -- a battery deleted from the roster takes its own floor with it.`,
902+
);
903+
}
904+
for (const [name, count] of batterySeen) {
905+
if (declaredBatteries.includes(name)) continue;
906+
floorFailures.push(
907+
`self-test battery "${name}" registered ${count} case(s) but is not declared in `
908+
+ 'SELF_TEST_BATTERIES -- a case attributed to no declared battery is one nothing floors.',
909+
);
910+
}
911+
for (const name of declaredBatteries) {
912+
const count = batterySeen.get(name) ?? 0;
913+
if (count >= SELF_TEST_BATTERIES[name]) continue;
914+
floorFailures.push(
915+
count === 0
916+
? `self-test battery "${name}" DID NOT RUN -- 0 cases registered, ${SELF_TEST_BATTERIES[name]} pinned. `
917+
+ 'The verdict below would have claimed those controls hold.'
918+
: `self-test battery "${name}" registered ${count} case(s), below its pinned floor of `
919+
+ `${SELF_TEST_BATTERIES[name]} -- cases that used to run no longer do.`,
920+
);
921+
}
922+
if (floorFailures.length > 0) {
923+
process.stderr.write(`x measure-position-name-fold-census self-test floor (${floorFailures.length} breach(es))\n\n${
924+
floorFailures.map((f) => ` - ${f}`).join('\n\n')}\n\n A battery at or below its floor means cases STOPPED RUNNING -- the battery is the bug, not the number. Find what stopped registering (an early return, a deleted block, a guard that now skips) and restore it.\n\n`);
925+
return 1;
926+
}
786927
process.stdout.write(
787928
`✓ measure-position-name-fold-census self-test: junction anchor (${a.position} -> ${a.set}) classified as`
788929
+ ` a junction binding and absent from the name-dependency list; name-fold anchor (${b.name}) detected`

0 commit comments

Comments
 (0)