tooling(scripts): row batteries for four table-driven self-tests (#13799 batch 7b) - #15286
Merged
Merged
Conversation
`failed === 0` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Recipe A, as the batch 7 pilot (PR #15271) settled it for the table-driven class: each of the 14 rows of the literal `cases` table is a declared battery under its own label verbatim, floor 1, and `registerCase(name)` is the first statement of the driving loop body. The roster is a LITERAL the table is checked against — never derived from it — and its own size is pinned at 14, which is also half of the duplicate-label refusal. No assertion condition touched, no control flow rewritten, no comment promoted to a section head, verdict handshake unchanged. The red-run line becomes `N failure(s) (cases and floor)` because floor breaches report into the same sink; the green line is byte-identical to main's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…-test `failed === 0` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Recipe A, as the batch 7 pilot (PR #15271) settled it: each of the 18 rows of the literal `cases` table is a declared battery under its own `label` verbatim, floor 1, roster size pinned at 18. `registerCase(c.label)` is the FIRST statement of the driving loop body — ahead of the `try` whose `catch` ends in `continue` and ahead of the two guards that do the same, because the floor asserts REACH and a registration behind a guard reintroduces the inversion. Scope stated in place: the four discovery-block assertions below the loop are not rows of the table (the verdict has always printed 18 rows, not the 22 assertions that run), so they are left exactly as they are. No assertion condition touched, no control flow rewritten, no comment promoted to a section head, verdict handshake unchanged. Red-run line becomes `N failure(s) (cases and floor)`; the green line is byte-identical to main's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…self-test `failures === 0` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Recipe A, as the batch 7 pilot (PR #15271) settled it: each of the 18 rows of the literal `cases` table is a declared battery under its own `name` verbatim, floor 1, roster size pinned at 18, and `registerCase(c.name)` is the first statement of the driving loop body. Scope stated in place: the eight `expectRoot(...)` assertions of the dead-root reverse proof below the loop are not rows of the table — the verdict line has always counted the 18 analysis rows and named that proof separately — so they are left exactly as they are. No assertion condition touched, no control flow rewritten, no comment promoted to a section head, verdict handshake unchanged. Red-run line becomes `N failure(s) (cases and floor)`; the green line is byte-identical to main's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
`failed === 0` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Recipe A, as the batch 7 pilot (PR #15271) settled it: each of the 23 rows of the literal mask/strip `cases` table is a declared battery under its own label verbatim, floor 1, roster size pinned at 23, and `registerCase(name)` is the first statement of the driving loop body. Scope stated in place: the twelve `interpolation`-view assertions below the corpus loop are NOT a second literal table — their rows exist only because an `x(...)` call pushed them onto `extra` at runtime, so a roster taken from that loop would be DERIVED and a deleted call would delete its own floor. They are left exactly as they are and the verdict keeps counting them separately. This module is a LIBRARY the gates import, so the change is proved from the consumer side too: six importers' `--self-test` runs (comment-mask-corpus, comment-mask-adoption, error-code-casing, entry-guard, declaration-mirrors, watch-hint-literal) are byte-identical to the base tree's on both streams and green in normal mode on the edited tree. No assertion condition touched, no control flow rewritten, no comment promoted to a section head, verdict handshake unchanged. Red-run line becomes `N failure(s) (cases and floor)`; the green line is byte-identical to main's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Contributor
Author
|
Out-of-scope finding filed while landing this batch, unassigned and Generated by Claude Code |
This was referenced Sep 4, 2026
baozhoutao
marked this pull request as ready for review
September 4, 2026 09:06
baozhoutao
enabled auto-merge
September 4, 2026 09:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #13799
Batch 7b of the assertion-floor card: four table-driven
scripts/**self-tests, under recipe A exactly as the batch 7 pilot (PR #15271, ACCEPT5537827823) settled it. Every file hadfailures === 0as its ONLY success condition, so "every case held" and "the cases never ran" printed the same line. Four files floored, nothing deferred.All evidence below was produced at the final commit
5dfa45644, against an installed base worktree at the dispatch pinorigin/main=4dd5041bd.Rows to batteries to floors
scripts/pm/check-skill-id-lint.mjsscripts/check-agent-model-declared.mjsscripts/check-startup-registry-verdict.mjsexpectRoot(...)assertions of the dead-root reverse proofscripts/js-comment-mask.mjsinterpolation-view assertions pushed ontoextraat runtimeRecipe A, per file: battery name = the row label verbatim, no prefix;
registerCase(label)is the FIRST statement of the driving loop body; the roster is a LITERAL the table is checked against, never derived from it; floors, not equalities; the roster's own size pinned at the row count; the red-run line becomesN failure(s) (cases and floor)and the green line is byte-identical tomain's.check-agent-model-declared's driving loop carries threecontinues (one in acatch), so registration sits ahead of thetry— per Q1 of the pilot ACCEPT, the floor asserts REACH, and a registration behind a guard reintroduces the very inversion the recipe exists to avoid.Two "not a row" scope calls, both written into the file. They are not deferrals — the tables themselves are fully floored:
check-agent-model-declared/check-startup-registry-verdict: those assertions are written inline one at a time below the loop, and each file's verdict line has always counted the table's rows separately from them.js-comment-mask: theinterpolationsection is not a second literal table. Its rows exist only because anx(...)call pushed them ontoextraat runtime, so a roster taken from that loop would be DERIVED — a deleted call would silently delete its own floor, the one defect this shape exists to prevent. Flooring it needs a literal roster of its own and is not a table-row question.Roster ⇄ table cross-check
Roster keys printed against the labels the loop actually registered, per file: 14 / 18 / 18 / 23, symmetric difference EMPTY in all four. Both halves of the duplicate refusal are in place: a duplicate ROSTER key collapses and trips the size pin, a duplicate TABLE label is named by the cross-check.
Ablations — 16 legs, 4 per file, all from the committed implementation
registerCase()call removedThe third leg is where the row count is measured on runs rather than read off the source, and it agrees with the roster size in every file.
No rebuild leg is owed: these are plain
.mjsscripts executed directly from source, with nodiston the resolution path. Every mutation was proved on disk before the run (occurrence counts of the removed and injected text, plus byte deltas — never an editor's exit code), and every restore is proved by HEAD-blob hash equality plus an emptygit diff HEAD; each leg ran under atrap ... EXIT INT TERMwith absolute paths.Both modes vs the base worktree
For all four files,
--self-testand normal mode: stdout and stderr byte-identical to the base tree's, exit code identical (0 on both;js-comment-mask's no-argument usage path is 2 on both).js-comment-maskis a library — the importer proofSix importers,
--self-teston both trees:check-comment-mask-corpus,check-comment-mask-adoption,check-error-code-casing,check-entry-guard,check-declaration-mirrors,check-watch-hint-literal— all exit 0, stdout and stderr byte-identical base vs branch. The same six also run green in normal mode on the edited tree, which is the real consumption path.Census and hints
node scripts/measure-self-test-floor.mjs --json: NONE 35 to 31, ROSTER 132 to 136, COUNT unchanged at 2. The movers are exactly the four files of this batch — symmetric difference against the worklist EMPTY, and no file newly reads NONE.extractWatchHintsoutput is identical on both trees for all four files, andcheck:watch-hint-literalis green.Gates
The derived family for this diff —
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 30 commands, derived at5dfa45644— plus the always-runs tail. All green, exit codes captured by redirect before any pipe.Two of the thirty first came back NOT MEASURED on a fresh worktree rather than red —
check:doc-formula-expressions(exit 3) andcheck:browser-reachable-entries— both refusing because the packages they read compiled output from were not built. Neither is a finding and neither can be reached by this diff; both were re-run green after building@objectstack/spec,@objectstack/formulaand@objectstack/lintthrough the shared verify lock. Also green:check:pm-dispatch-gates,check-self-test-wired(both modes),check-self-test-workflow-commands(both modes),check:declared-population-live,check:ratchet-remedy-authority,check:watch-hint-literal,check:nul-bytes.Control-byte scan clean over every edited file and every posted body.
Invariants
⛔ No assertion condition touched. ⛔ No control flow rewritten. ⛔ No comment promoted to a section head. The verdict handshake is untouched in each file, in each file's own spelling (sentinel return in
check-skill-id-lintandjs-comment-mask, theselfTestReachedVerdictflag incheck-agent-model-declared, flag plus exit code incheck-startup-registry-verdict). The only four deleted lines in the whole diff are the four red-run verdict lines; everything else is additive.skip-changeset: no package publishes anything from this diff.Generated by Claude Code
Generated by Claude Code