test(scripts): give six more self-tests a battery roster and floor (#13799 batch 3) - #15156
Merged
Merged
Conversation
Part of #13799 (batch 3). The concise-arrow sink `t` gets a block body so it can call registerCase(); 12 batteries / 150 cases pinned. Case count before == after (150), measured against the branch point. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 3). The module-level `assert` keeps its semantics (print and exit 1 on the first failure); a thin in-body `check()` wrapper attributes each case to the open battery and defers to it. 4 batteries / 23 cases pinned, and the floor reports through that same `assert`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 3). Same thin in-body `check()` wrapper over the module-level `assert`; 8 batteries / 22 cases pinned. Gate mode still green on the tree (298 fragment links across 409 sources). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 3). Third of the module-level-`assert` trio, same thin in-body wrapper; 10 batteries / 16 cases pinned. Its verdict line prints a LITERAL "10 cases" that tracks nothing and undercounts the 16 assertions the body actually runs — left as found (the card's scope is the floor, and the handshake stays exactly as landed), recorded instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 3). The 7 inline `failures.push(...)` sites now route through one block-bodied `expect()` that registers the case whether it holds or not; message text is unchanged. 2 batteries / 59 cases, the first hoisted because cases run before the first banner. The count reconciles against the tables: 21 + 12 + 4 and 12 + 6 + 3 + 1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 3). The 6 inline `failed += 1` sites route through one block-bodied `check()` that keeps both the ✓ and ✗ branches verbatim and counts the case either way. 3 batteries / 36 cases, the first hoisted (10 + 3 + 12 + 1 run before the first banner). Not a repo sweep: with no args it prints usage and exits 2, unchanged from the branch point. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
baozhoutao
marked this pull request as ready for review
September 4, 2026 04:22
baozhoutao
enabled auto-merge
September 4, 2026 04:22
baozhoutao
pushed a commit
that referenced
this pull request
Sep 4, 2026
…y roster `cases` with no failing entry was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line. Batch 6b of the roster-floor transplant, two shapes at once: - the sink repair PR #15156 landed: the concise arrow `const t = (name, ok, detail) => cases.push(...)` gains a block body and registers the case before recording it. `cases.push` receives exactly the arguments it always did -- no case is rewritten, reordered or re-judged. - the single hoisted battery PR #15217 landed: this file carries no named section banner, so it declares ONE battery opened at the top of the self-test body, floor at the measured count (12), and pins the roster's own size at 1. No comment is promoted to a section head. A breach files into the self-test's own `cases` sink, so the existing verdict reds on it with no verdict line rewritten; the #13798 handshake is untouched. Cases before == after: 12 == 12, measured on runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
baozhoutao
pushed a commit
that referenced
this pull request
Sep 4, 2026
…-test `cases.filter((c) => !c.cond)` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Class-1 sink repair, the PR #15156 shape: the concise-arrow `ok` sink gains a block body that calls `registerCase()` before the unchanged `cases.push`. No assertion condition is inverted or rewritten. Class-2 roster, the PR #15217 shape: ONE battery hoisted to the top of the self-test body, floor at the measured 23, `SELF_TEST_BATTERIES` size pinned at 1. No comment was promoted to a section head. Case count before == after, measured by pinning the roster to an unreachable value and reading the breach line: 23. `--self-test` stdout and stderr are byte-identical to the base tree's, exit 0 on both. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
baozhoutao
pushed a commit
that referenced
this pull request
Sep 4, 2026
…attery roster `failed === 0` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line. Batch 6b, two shapes at once: - the sink repair PR #15156 landed: the 12 inline `cases.push({...})` sites route through ONE block-bodied in-body helper, `addCase`, which registers the case and then performs the identical push. The case object is passed through untouched and the loop that runs the cases is not touched at all -- no case is rewritten, reordered or re-judged. - the single hoisted battery PR #15217 landed: this file carries no named section banner (its `--- n/m: ... ---` comments label fixtures, not sections), so it declares ONE battery opened at the top of the self-test body, floor at the measured count (12), roster size pinned at 1. No comment is promoted to a section head. A breach files into the self-test's own `failed` counter, so the existing verdict reds on it with no verdict line rewritten; the #13798 handshake is untouched. Normal mode stays green on the tree. Cases before == after: 12 == 12, measured on runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
baozhoutao
pushed a commit
that referenced
this pull request
Sep 4, 2026
`cases.filter((c) => !c.ok)` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Class-1 sink repair, the PR #15156 shape: the concise-arrow `t` sink gains a block body that calls `registerCase()` before the unchanged `cases.push`. No assertion condition is inverted or rewritten. Class-2 roster, the PR #15217 shape: ONE battery hoisted to the top of the self-test body, floor at the measured 20, `SELF_TEST_BATTERIES` size pinned at 1. The file's single named section banner is NOT split on, and no comment was promoted to a section head. Case count before == after, measured by pinning the roster to an unreachable value and reading the breach line: 20 — which agrees with the count the existing verdict line prints. `--self-test` stdout and stderr are byte-identical to the base tree's, exit 0 on both. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
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 3, the class-1-ONLY deferrals from PR #15003's table).
PR #13487's roster-and-floor shape, exactly as batches 1/1b/1c/2 landed it (PRs #14851, #14872, #14896, #15003), transplanted onto the files whose only recorded defect in #15003's table was the assertion-sink shape while the banner count and the body-level verdict site already qualified. 39 batteries / 306 cases pinned across 6 files. The seventh candidate is deferred with a measured reason rather than forced.
Per file, and nothing else:
SELF_TEST_BATTERIESroster of names with a per-battery floor,SELF_TEST_BATTERY_FLOORpinning the roster's own size, andUNATTRIBUTED_BATTERY, placed after the import block;battery('BANNER TEXT')at each existing section banner, named verbatim from the banner with its marker stripped;registerCase()at the head of the one in-body assertion helper this PR gives each file — which is the whole of the class-1 work;⛔ No case is rewritten, none reordered, no assertion changes meaning. ⛔ No TOTAL is pinned.
What "class-1" cost per file, since that was the deferral reason
The three sink shapes in #15003's table needed three different — and each strictly local — repairs:
assertcheck-adr-links,check-doc-anchors,check-kernel-hook-pairscheck(cond, message)that registers the case and then defers to the existingassert, whose semantics (print,process.exit(1)on the first failure) are untouched. Call sites change by one token:assert(becomescheck(.check-published-files(7 sites),ablation-dist-preflight(6 sites)tpm/check-clause2-carrierst, so it can holdregisterCase().In the inline-sink pair the failure-message template is now evaluated eagerly rather than only on the failing branch. Every one of those templates interpolates values already computed on the line above, so this is free of side effects; it is recorded because it is the one place where the diff is not a pure re-routing.
The floor, and case count before == after
Both numbers are measured on a run, not derived from the diff.
beforeforcheck-clause2-carriersis the count its own verdict line already printed; forablation-dist-preflightit is the✓lines the base run prints, one per case; for the other four the base file was instrumented with a counter at the point each case is evaluated, run, and then restored — restore proven bygit hash-objectequalling the HEAD blob and by an emptygit diff HEAD, not by the exit code of the restore command.beforewas readscripts/ablation-dist-preflight.mjs✓lines on the base runscripts/check-adr-links.mjsassertscripts/check-doc-anchors.mjsassertscripts/check-kernel-hook-pairs.mjsassertscripts/check-published-files.mjsscripts/pm/check-clause2-carriers.mjsTwo files run cases before their first banner (
ablation-dist-preflight,check-published-files); their first battery is opened at the top of the body and that banner then carries no second opener — the PR #13487 precedent's own shape, as batches 1b and 2 did it.check-published-files's 59 reconciles against its own tables independently of the instrument: 21 pattern + 12 classification + 4 population-declaration for the first battery, and 12exportsverdict + 6 (theFix:-line loop skips the 6 rows expected to pass) + 3 census-floor + 1 shared enumerator for the second.The card's own instrument agrees
node scripts/measure-self-test-floor.mjs, which the card names as the thing to re-measure with rather than re-derive:ebb082204+6, and the six new roster entries are exactly this PR's six files.
Ablation: each floor was made to fail, on the battery it names
Per file: the first declared battery's opener is renamed so that battery registers nothing, the self-test is run, and it must exit non-zero naming that battery. Then restore, and it must be green again. Both legs are proven on disk — the mutation by counting the injected marker, the restore by
git hash-objectagainst the HEAD blob plus an emptygit diff HEADand a zero residual-marker count — never by an editor's or agit checkout's exit code, and every script carries atrap ... EXIT INT TERMrestore.These are
.mjsscripts executed directly from source: nodist/and noexportsresolution stands between the edit and the run, so the rebuild leg the ablation contract requires for package-resolved subjects does not apply here. Recorded rather than skipped silently.ablation-dist-preflight.mjswhole-tree accounting: the pure tablecheck-adr-links.mjsDiscrimination: verbatim link shapes are invisible; prose ones are not.check-doc-anchors.mjsSlug parity with the renderer, on the two shapes that actually broke.check-kernel-hook-pairs.mjsA hook pinned on both sides passes.check-published-files.mjsthe dispatch-gates declaration (#10542)pm/check-clause2-carriers.mjsthe declaration reader: the fixed spelling, and everything that is not⭐ The one behavioural hazard #15003 measured, measured again here
#15003 deferred
scripts/pm/dispatch-gates.mjsbecause its self-test reads its own source and four battery names carrying path-shaped text were read by its own path-population extractor as declared populations — a change of meaning, not a no-op.This batch adds new string literals to six files that dispatch-gates reads as gate sources, so the same extractor could have read a battery name as a watch hint. It does not.
extractWatchHintswas run over all six files on both trees:ablation-dist-preflight.mjs[][]check-adr-links.mjs["docs/adr"]["docs/adr"]check-doc-anchors.mjs["content/**","README.md/**","ARCHITECTURE.md/**"]check-kernel-hook-pairs.mjs["packages/core/src"]["packages/core/src"]check-published-files.mjspm/check-clause2-carriers.mjs[][]Byte-identical on every file.
check:pm-dispatch-gates(1343 cases) andcheck:declared-population-liveare both green on the branch, which is the same finding reached the other way.Deferred (1), with the measurement
scripts/partition-test-shards.mjsthrowat every site, and only 22 are the uniform single-lineif (cond) throw new Error(msg);. The other 14 are multi-line, several nested insideforloops and closures. Routing them through a helper means inverting the failure condition by hand at each site — and a mis-scoped or dropped!yields an assertion that still registers its case, still prints nothing, and still passes, so the floor being installed cannot see it. That is a rewrite of every assertion rather than the "route without changing assertion semantics" the shape asks for, so it is deferred rather than improvised past. The route a later batch can take without inverting anything: a thunk helper,const check = (fn) => { registerCase(); fn(); };, wrapping each site's existingif (...) throw ...verbatim — no condition is touched, at the cost of reindenting the 14 multi-line blocks.⛔ Untouched by construction, per the dispatch:
scripts/pm/dispatch-gates.mjs(still DEFERRED, reason above),scripts/pm/check-half-states.mjs(~17 kloc, the analyzer cannot resolve its body), every class-2 / class-3 file in #15003's table, and the files held by other live cards.Shrink-only ledgers: scanned, one worth naming
Every battery whose cases come off a module-level list was enumerated and each list read, per the card's "a floor is not always the measured count":
CONVENTION_ILLUSTRATIVE_TARGETS(check-adr-links, 3 rows feeding 6 of battery 3's 8 cases) is a pin of three strings that ADR-0046 must keep containing — the file's own header says so. It grows or holds; it is not a baseline that legitimate work shortens. Named here because it is the one floor in this batch that moves with a list at all.KNOWN_DEAD_TARGETS(check-adr-links) is shrink-only, and is exactly the case the card warns about — so note what it drives: one structural case (no entry has outlived its excuse), not one per row. It is currently[], and shrinking it cannot move that count. This is the card's own remedy — pin the part that does not move with the list — arrived at without needing to deviate.ROOT_DIR_WATCH_HINTS,FORBIDDEN,EXPORTS_CENSUS_FLOOR(check-published-files) andCLAUSE2_VALUES(check-clause2-carriers) are registers and closed sets that grow or are pinned by an adjacent assertion; none is shrink-only.Verification
Every exit code captured by redirect before any pipe; each gate's own verdict line read rather than a bare
$?. Run on6bddfc959, the final commit of this branch.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack→ 27 commands, all 27 run, all exit 0.check:pm-dispatch-gates(exit 0, 5m39s, 1343 cases),check-self-test-wired+--self-test,check-self-test-workflow-commands+--self-test,check:declared-population-live,check:ratchet-remedy-authority,check:nul-bytes— all exit 0.--self-testand its normal gate run against the live tree.check-adr-links(599 destinations resolve) andcheck-doc-anchors(298 fragment links across 409 sources) arelint.ymlgates and are green on the tree.ablation-dist-preflightis a per-invocation tool, not a repo sweep: with no arguments it prints usage and exits 2, unchanged from the branch point.packages/qa/dogfood/test/multi-package-artifact.dogfood.test.ts,packages/plugins/plugin-auth/src/rate-limit-storage-isolation.test.ts) exercises it — both are prose references in comments. Each script's--self-testis its own suite, and all six ran.grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'): no match.check:nul-bytesgreen (8238 files scanned).skip-changeset:scripts/**publishes from no package, the same call PR #15003 made for the identical surface.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code