Skip to content

Commit fbecffe

Browse files
claude[bot]claude
andauthored
test(scripts): batch 7 pilot — floor check-sdui-manifest on its own table row labels (#15271)
* test(scripts): floor check-sdui-manifest's table-driven self-test on its own row labels Batch 7 pilot for the assertion-floor card: the first of the ten table-driven `scripts/**` self-tests, whose natural roster is the table's own named rows rather than sections. `failures === 0` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line. The sink here (`failures++`) writes only on failure, so routing it through `registerCase()` would invert the floor rather than install it: a fully green run would register nothing. So each row label in the literal `cases` table becomes a declared battery with a floor of 1, and `registerCase(name)` is the first statement of the driving loop body — attributing the case to the row actually being run. The roster is a LITERAL the table is checked against, never derived from it: a derived roster lets a deleted row delete its own floor. The roster's own size is pinned, which is also what refuses a duplicate row label at declaration time; a table cross-check names which label collided. No assertion condition touched, no control flow rewritten, the verdict handshake kept as landed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk * test(scripts): keep check-sdui-manifest's green self-test line byte-identical The floor's evidence is the refusal, not the success line, so the green-tree stdout stays exactly as landed. The failure line keeps its corrected wording — floor breaches are counted in the same sink as case failures, so "N case(s) failed" would have been inaccurate — but that line is only reachable on a red run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent ee434a3 commit fbecffe

1 file changed

Lines changed: 107 additions & 1 deletion

File tree

scripts/check-sdui-manifest.mjs

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,49 @@ export function checkTree(root) {
144144
// as one that passed (#13798).
145145
const SELF_TEST_VERDICT = 'check-sdui-manifest self-test reached its verdict';
146146

147+
// ── The self-test's own battery roster and floor (#13489) ──────────────────
148+
//
149+
// `failures === 0` used to be this self-test's ONLY success condition, so "every
150+
// case held" and "the cases never ran" printed the same line. Closed the PR
151+
// #13487 way: what is pinned is the registered NAMES, not a number.
152+
//
153+
// This self-test is TABLE-DRIVEN — one literal `cases` table, one loop over it,
154+
// and a sink (`failures++`) that writes only when a case FAILS. Routing THAT
155+
// sink through `registerCase()` would register a case only when it fails: a
156+
// fully green run would register 0 and every battery would read DID NOT RUN, the
157+
// floor inverted rather than installed. So the roster is the table's own rows.
158+
// Each row LABEL is a declared battery, verbatim, with a floor of 1, and
159+
// `registerCase(name)` is the first statement of the driving loop body — so the
160+
// case is attributed to the row actually being run, whatever that row asserts
161+
// afterwards. There is no `battery()` opener: for a table-driven self-test the
162+
// ROW is the battery, so attribution is the loop variable rather than a
163+
// most-recently-opened section.
164+
//
165+
// ⛔ A pinned TOTAL is not the repair, and neither is a roster DERIVED from the
166+
// table: `cases.length` moves with the table, so a deleted row would delete its
167+
// own floor. The roster below is a LITERAL the table is checked against, which
168+
// is what lets a deleted or renamed row name ITSELF in the refusal.
169+
//
170+
// The counts are a FLOOR, not an equality — a row that grows into several
171+
// registrations must not red. 1 is the honest floor for a table row: the loop
172+
// reaches it exactly once per run.
173+
const SELF_TEST_BATTERIES = Object.freeze({
174+
'green fixture passes': 1,
175+
'missing artefact is RED': 1,
176+
'hand-edited artefact (hash mismatch) is RED': 1,
177+
'moved pin is RED': 1,
178+
'empty components is RED': 1,
179+
'missing record is RED': 1,
180+
});
181+
182+
// DELETING an entry silences that battery's floor exactly as effectively as
183+
// zeroing it, so the roster's own size is pinned too. This pin is also half of
184+
// the duplicate-label refusal: two rows sharing a label collapse to ONE key in
185+
// the literal above, so the roster falls below this number; the table
186+
// cross-check in the floor block is the other half, and names WHICH label
187+
// collided.
188+
const SELF_TEST_BATTERY_FLOOR = 6;
189+
147190
function selfTest() {
148191
const mk = (mutate) => {
149192
const root = mkdtempSync(join(tmpdir(), 'sdui-manifest-check-'));
@@ -187,8 +230,15 @@ function selfTest() {
187230
['missing record is RED', mk((r) => rmSync(join(r, 'scripts', 'sdui-manifest.record.json'))), 1],
188231
];
189232

233+
// The ledger this self-test's floor is evaluated against (#13489).
234+
const batterySeen = new Map();
235+
const registerCase = (name) => {
236+
batterySeen.set(name, (batterySeen.get(name) ?? 0) + 1);
237+
};
238+
190239
let failures = 0;
191240
for (const [name, root, want] of cases) {
241+
registerCase(name);
192242
const problems = checkTree(root);
193243
const got = problems.length ? 1 : 0;
194244
if (got !== want) {
@@ -197,8 +247,64 @@ function selfTest() {
197247
for (const p of problems) console.error(` ${p}`);
198248
}
199249
}
250+
// ── The floor: every declared row RAN, and ran its case (#13489) ───────
251+
//
252+
// Evaluated after every row has had its chance and BEFORE the verdict, so the
253+
// success line below can only be printed by a run in which the set of rows
254+
// that registered EQUALS the set declared. A set difference names WHICH row
255+
// stopped; a count says only that something did.
256+
const floorFailure = (message) => {
257+
console.error(`✗ self-test floor: ${message}`);
258+
failures++;
259+
};
260+
const declaredBatteries = Object.keys(SELF_TEST_BATTERIES);
261+
let floorBreached = false;
262+
if (declaredBatteries.length < SELF_TEST_BATTERY_FLOOR) {
263+
floorBreached = true;
264+
floorFailure(
265+
`SELF_TEST_BATTERIES declares ${declaredBatteries.length} batteries, below the pinned ` +
266+
`${SELF_TEST_BATTERY_FLOOR} — a battery deleted from the roster takes its own floor with it.`,
267+
);
268+
}
269+
const rowLabels = cases.map(([name]) => name);
270+
const duplicated = [...new Set(rowLabels.filter((name, i) => rowLabels.indexOf(name) !== i))];
271+
if (duplicated.length > 0) {
272+
floorBreached = true;
273+
floorFailure(
274+
`the cases table uses ${duplicated.map((n) => JSON.stringify(n)).join(', ')} as a row label more than once — ` +
275+
'two rows sharing a label are ONE battery, so the second can stop running while the first keeps the floor met.',
276+
);
277+
}
278+
for (const [name, count] of batterySeen) {
279+
if (declaredBatteries.includes(name)) continue;
280+
floorBreached = true;
281+
floorFailure(
282+
`self-test battery "${name}" registered ${count} case(s) but is not declared in ` +
283+
'SELF_TEST_BATTERIES — a case attributed to no declared battery is one nothing floors.',
284+
);
285+
}
286+
for (const name of declaredBatteries) {
287+
const count = batterySeen.get(name) ?? 0;
288+
if (count >= SELF_TEST_BATTERIES[name]) continue;
289+
floorBreached = true;
290+
floorFailure(
291+
count === 0
292+
? `self-test battery "${name}" DID NOT RUN — 0 cases registered, ${SELF_TEST_BATTERIES[name]} pinned. ` +
293+
'The verdict below would have claimed that case holds.'
294+
: `self-test battery "${name}" registered ${count} case(s), below its pinned floor of ` +
295+
`${SELF_TEST_BATTERIES[name]} — cases that used to run no longer do.`,
296+
);
297+
}
298+
if (floorBreached) {
299+
floorFailure(
300+
'A battery at or below its floor means cases STOPPED RUNNING — the battery is the bug, not the ' +
301+
'number. Find what stopped registering (a deleted row, a renamed label, a loop that no longer ' +
302+
'reaches it) and restore it.',
303+
);
304+
}
305+
200306
if (failures) {
201-
console.error(`✗ check-sdui-manifest self-test: ${failures} case(s) failed.`);
307+
console.error(`✗ check-sdui-manifest self-test: ${failures} failure(s) (cases and floor).`);
202308
process.exit(1);
203309
}
204310
console.log(`✓ check-sdui-manifest self-test: ${cases.length} cases behave (green passes; absence, tamper, moved pin, emptiness are RED).`);

0 commit comments

Comments
 (0)