test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests - #14851

Queued
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1
Queued

test(scripts): pin a battery roster floor on 40 more scripts/** self-tests#14851
claude[bot] wants to merge 6 commits into
mainfrom
claude/issue-13799-self-test-roster-floor-b1

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 1, Tier B)

failures.length === 0 was the only success condition in these gates' self-tests, so "every case held" and "the cases never ran" printed the same line. This lands the PR #13487 shape — the one validated on check-doc-authoring.mjs and carried to check-self-test-wired.mjs / check-self-test-workflow-commands.mjs in PR #13797 — on 40 more scripts/** self-tests.

Per file: every existing section opens with battery('NAME'), one registerCase() line goes into the self-test's own assertion helper so every assertion is attributed to the battery most recently opened, and a floor evaluated before the verdict requires the OPENED set to equal the DECLARED set with each battery at or above its own case count. The roster's own size is pinned too, so deleting an entry cannot silence a floor. An assertion that fires with no battery open is filed under (no battery open), which is not a declared name and reds by the same set difference.

⛔ What is pinned is registered NAMES, never a total: a set difference says WHICH battery stopped, a count says only that something did. ⛔ No case was rewritten — the only edits inside each self-test are the roster wiring.

Census, measured not recalled

node scripts/measure-self-test-floor.mjs --json, on the merge base 2d40f9146 and again on this branch:

ROSTERCOUNTNONE
before34158
after434118

Three set-equality assertions, all holding (computed, not eyeballed):

  1. every one of the 40 worklist files reads ROSTER after;
  2. the set of files whose classification CHANGED equals the worklist exactly (symmetric difference empty) — nothing outside the worklist moved;
  3. inside PR Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return #14479's 134 handshake-carrying files, the files still reading NONE are exactly the declared remainder below plus the honoured exclusions — symmetric difference empty, 91 = 86 + 5.

The 40 files floored

filebatteriespinned cases
scripts/check-adr-anchors.mjs6104
scripts/check-agent-test-spelling.mjs1267
scripts/check-aggregator-roster.mjs945
scripts/check-bash32-floor.mjs17153
scripts/check-changeset-no-major.mjs13116
scripts/check-corpus-claim-drift.mjs1694
scripts/check-declared-population-live.mjs216
scripts/check-doc-route-spelling.mjs1150
scripts/check-docs-image-tag.mjs1194
scripts/check-docs-nav-label.mjs925
scripts/check-docs-redirects.mjs548
scripts/check-driver-conformance.mjs1198
scripts/check-driver-memory-census.mjs641
scripts/check-empty-changeset.mjs21118
scripts/check-engine-double-contract.mjs31186
scripts/check-nul-bytes.mjs675
scripts/check-position-name-fold-loaders.mjs415
scripts/check-prerelease-pin-watch.mjs850
scripts/check-published-readme-exports.mjs2382
scripts/check-published-readme-links.mjs10114
scripts/check-query-options-erasure-ratchet.mjs4102
scripts/check-react-page-adapter-contract.mjs851
scripts/check-release-page-status.mjs735
scripts/check-release-section-coverage.mjs950
scripts/check-resume-authority-declared.mjs718
scripts/check-role-word.mjs1187
scripts/check-runtime-services-index.mjs851
scripts/check-sdui-lockstep.mjs535
scripts/check-shard-attestation.mjs15129
scripts/check-single-authz-resolver.mjs859
scripts/check-slot-lookup-ratchet.mjs549
scripts/check-test-source-alias.mjs998
scripts/check-test-typecheck.mts526
scripts/check-verify-stand-in-erasure.mjs324
scripts/check-where-matcher-conformance.mjs339
scripts/check-workflow-status-functions.mjs834
scripts/objectui-changeset-digest.mjs16130
scripts/objectui-range.mjs723
scripts/pr-labels.mjs650
scripts/sync-docs-image-tags.mjs835

383 batteries, 2716 pinned cases.

Two floors are NOT today's count, deliberately

Per the triage ruling: where a battery is one-case-per-row of a list that only ever loses rows, a floor at today's count reddens every legitimate shrink and trains the next author to edit the floor. Both are said in place, over the roster entry:

  • check-adr-anchors.mjsLive tree: green as shipped, red under ablation runs one case per KNOWN_NUMBER_COLLISIONS row (3 today) on top of 20 structural cases; a resolved collision is meant to be deleted and the gate already fails a stale entry. Pinned 21 (20 structural + at least one row audited), not 23.
  • check-single-authz-resolver.mjsEvery exemption carries its reason. runs one case per exemption row (2 today) plus one structural case. Pinned 2, not 3.

Deferred, and why

Tier C — a decision, not a transplant (triage 5478879048; untouched here, returns as its own batch with the reshaping decision made explicitly): the inline top-level blocks scripts/check-regen-pending.mjs, scripts/git-merge-regen.mjs, scripts/setup-git-hooks.mjs; the multi-entry dispatches scripts/check-platform-checklist.mjs, scripts/check-durability-degradation-log-level.mjs; and table-driven self-tests whose natural roster is the table's own rows.

Exclusions honoured (⛔ not edited): the #13798 batch-2 worklist in flight on claude/issue-13798-self-test-handshake-b2 (24 files); scripts/check-i18n-coverage.mjs (PR #14799); scripts/check-i18n-bundles.mjs (reserved for #14008); scripts/pm/dispatch-gates.mjs, scripts/pm/bare-root-worklist.mjs, scripts/check-type-check-coverage.mjs (open PRs #14765 / #14800 / #14805); and every file without the #13798 handshake.

Carve-out, named rather than silent: three handshake-carrying files classify COUNT rather than NONE, so they were never in this card's 155 — scripts/check-refd-timer-probe.mjs, scripts/docs-audit/check-audit-scope.mjs, scripts/measure-stall-guard-headroom.mjs. The census header records the COUNT hits it knew about as hand-checked false positives; these three are unaudited, and are left for a later batch rather than quietly counted as floored.

Remainder of the Tier B surface — 86 files, each with the measured reason it is not in this batch. These are honest transplant blockers, not skips: the transform here is a verbatim one, and each of these needs a decision (name the block-scoped groups, or reshape the report) that belongs in a batch of its own rather than at the end of a long PR.

B1 — no assertion helper inside the self-test body. Every case is written inline, or the helper lives at module scope. A roster here cannot attribute cases without rewriting the cases, which this card forbids. (48 files)

  • scripts/ablation-dist-preflight.mjs
  • scripts/check-adr-links.mjs
  • scripts/check-agent-model-declared.mjs
  • scripts/check-auth-mount-ledger.mjs
  • scripts/check-cli-command-ids.mjs
  • scripts/check-cli-test-child-env.mjs
  • scripts/check-comment-mask-corpus.mjs
  • scripts/check-console-intercept-disarm.mjs
  • scripts/check-cross-package-test-inputs.mjs
  • scripts/check-declaration-mirrors.mjs
  • scripts/check-dispatcher-error-vocabulary.mjs
  • scripts/check-docs-section-name.mjs
  • scripts/check-docs-single-h1.mjs
  • scripts/check-dual-build-cjs-loads.mjs
  • scripts/check-durability-degradation-log-level.mjs
  • scripts/check-entry-guard.mjs
  • scripts/check-examples-live-imports.mjs
  • scripts/check-init-service-contract.mjs
  • scripts/check-kernel-hook-pairs.mjs
  • scripts/check-live-db-isolation.mjs
  • scripts/check-optional-error-sink-contract.mjs
  • scripts/check-org-identifier.mjs
  • scripts/check-override-consistency.mjs
  • scripts/check-parse-guard.mjs
  • scripts/check-partof-closing-keyword.mjs
  • scripts/check-plugin-teardown-shape.mjs
  • scripts/check-published-files.mjs
  • scripts/check-published-list-mirrors.mjs
  • scripts/check-route-envelope.mjs
  • scripts/check-runner-env-posture.mjs
  • scripts/check-sdui-manifest.mjs
  • scripts/check-single-claim-paths.mjs
  • scripts/check-skill-compatibility-version.mjs
  • scripts/check-skill-frame-freshness.mjs
  • scripts/check-skill-frame-sync.mjs
  • scripts/check-tenant-audit-census.mjs
  • scripts/check-watch-hint-literal.mjs
  • scripts/check-widget-option-census.mjs
  • scripts/check-wildcard-fallthrough.mjs
  • scripts/import-prerequisite.mjs
  • scripts/invoked-as.mjs
  • scripts/measure-position-name-fold-census.mjs
  • scripts/measure-test-shard-timings.mjs
  • scripts/partition-test-shards.mjs
  • scripts/publish-smoke-pack.mjs
  • scripts/qa/qa-rollup.mjs
  • scripts/render-release-coverage-anchor.mjs
  • scripts/ts-parse.mjs

B2 — fewer than two named sections. The groups are block-scoped with no banner, so naming them is a judgement per block rather than a transplant. (15 files)

  • scripts/check-console-injection.mjs
  • scripts/check-cross-repo-closer-outcome.mjs
  • scripts/check-docs-locale-catch-all.mjs
  • scripts/check-dts-emitted.mjs
  • scripts/check-error-status-conformance.mjs
  • scripts/check-logger-receiver-detach.mjs
  • scripts/check-merge-queue-triage-outcome.mjs
  • scripts/check-objectql-double-limit.mjs
  • scripts/check-quick-reference-counts.mjs
  • scripts/check-ratchet-remedy-authority.mjs
  • scripts/check-spec-parsed-alias.mjs
  • scripts/check-stack-collection-maps.mjs
  • scripts/check-startup-registry-verdict.mjs
  • scripts/check-tenant-chokepoint.mjs
  • scripts/check-whole-set-label-write.mjs

B3 — the verdict is not reached through a body-level if (SINK…), so there is no single point at which a floor can be evaluated before the verdict without reshaping the report. (11 files)

  • scripts/check-adr-0087-registration.mjs
  • scripts/check-comment-mask-adoption.mjs
  • scripts/check-doc-frontmatter.mjs
  • scripts/check-engine-split-ratio.mjs
  • scripts/check-i18n-stale-fill.mjs
  • scripts/check-required-contexts.mjs
  • scripts/check-section-landing-index.mjs
  • scripts/check-stall-guard-budget.mjs
  • scripts/check-system-context-census.mjs
  • scripts/check-turbo-task-graph.mjs
  • scripts/check-undeclared-dep-imports.mjs

B4 — the self-test entry the census names has no function body this transform can resolve (an aliased or re-exported entry). (9 files)

  • scripts/check-ci-filter-parity.mjs
  • scripts/check-doc-anchors.mjs
  • scripts/check-error-code-casing.mjs
  • scripts/check-keyed-text-bounds.mjs
  • scripts/check-overlay-whitelist-table.mjs
  • scripts/check-pnpm-acquisition.mjs
  • scripts/check-vendor-version-stamps.mjs
  • scripts/js-comment-mask.mjs
  • scripts/release-github-releases.mjs

B5 — the only named sections sit after the verdict site. (2 files)

  • scripts/check-dev-prereqs.mjs
  • scripts/sync-template-versions.mjs

B3 — same as above (failed sink). (1 files)

  • scripts/docs-audit/affected-docs.mjs

Verification

  • Per file: --self-test run before and after; exit codes identical on all 40 (all 0). Floors are the per-battery counts measured by instrumenting the wiring on this tree, not guessed.
  • Ablations, from a COMMITTED implementation, mutation proved on disk and restore proved by an empty git diff HEAD:
    • a battery's cases deleted, array sink (check-sdui-lockstep.mjs) → exit 1;
    • a roster ENTRY deleted (check-sdui-lockstep.mjs) → exit 1, and the run names both halves: "declares 4 batteries, below the pinned 5" and "registered 7 case(s) but is not declared in SELF_TEST_BATTERIES";
    • a battery's cases deleted, counter sink (check-bash32-floor.mjs) → exit 1, "battery 'the table itself' DID NOT RUN — 0 cases registered, 2 pinned".
  • Gates: the 41 families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on this branch, all run, exit codes captured before any pipe. All 41 exit 0 on the merged head 3da3d92.
  • pnpm lint (whole repo, eslint . --no-inline-config): exit 0.
  • Two real findings this caught and fixed, both worth recording:
    • check:ratchet-remedy-authority went red because the first spelling of the ALLOW note put that registry's name and the words "shrink-only" inside anchorFor's window, flipping check-single-authz-resolver.mjs from excluded to unmarked and then MISCLASSIFIED against its CONTROL row. Reworded to state the same fact without the token; green.
    • check:type-check-debt went red because scripts/check-test-typecheck.mts is reached by the root tsc --noEmit and the untyped wiring added 7 raw errors (26 → 33, drifting a frozen DEBT entry upward). Typed; back to the recorded 26.

skip-changeset: scripts/** only, nothing is published from any package.


Generated by Claude Code

`failures.length === 0` was the only success condition in these gates'
self-tests, so "every case held" and "the cases never ran" printed the
same line. Transplants the PR #13487 shape validated on
check-doc-authoring and carried to check-self-test-wired /
check-self-test-workflow-commands in PR #13797: every section opens with
`battery('<name>')`, every assertion is attributed to the battery most
recently opened, and a floor evaluated before the verdict requires the
OPENED set to equal the DECLARED set with each battery at or above its
own case count. The roster's own size is pinned too, so deleting an
entry cannot silence a floor.
Registered NAMES are what is pinned, never a total: a set difference
says WHICH battery stopped, a count says only that something did.
No case was rewritten — the only edits inside each self-test are the
roster wiring (a `battery()` opener per existing section banner, one
`registerCase()` line in the assertion helper, and the floor block
before the verdict). Floors are the per-battery counts measured on this
tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…o ledger-driven batteries
Two batteries register one case per row of a list that is meant to
shrink: `KNOWN_NUMBER_COLLISIONS` in check-adr-anchors (a resolved
collision is deleted, and a stale entry already fails) and `ALLOW` in
check-single-authz-resolver (an exemption that exempts nothing is dead
weight). A floor at today's count would redden every legitimate removal
and train the next author to edit the floor — the one habit these floors
exist to prevent. Pinned instead is the part that does not move with the
list: the structural cases ran AND at least one row was audited, said in
place over each entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
…het-remedy offer
The first spelling put `ALLOW` and the words "shrink-only" inside
`anchorFor`'s window in check-single-authz-resolver, which flipped that
file from `excluded` to `unmarked` under check:ratchet-remedy-authority
(and then MISCLASSIFIED against its CONTROL row). Measured, both
findings; the gate is green again with the same fact stated without the
token. The adr-anchors note is reflowed for readability only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
scripts/check-test-typecheck.mts is the one .mts file in the batch and it
is reached by the root `tsc --noEmit`, so the untyped `battery()` /
`registerCase()` / `floorFailure()` insertions added 7 raw errors and
drifted the frozen DEBT entry for @objectstack/spec-monorepo upward
(26 -> 33, measured). Typing the wiring and widening the roster to
`Readonly<Record<string, number>>` puts the count back at its recorded
26 with check:type-check-debt green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Swfxm6gT9ESmjSS7pqfVw
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@claude

claudeBot commented Sep 3, 2026

Copy link
Copy Markdown
ContributorAuthor

PM note (domain:devx execution seat, session session_01LAwHpn4uVuf4N1geBcD5i3): PR-side CI on 3da3d9225 is red only on Test Core (1/6)packages/clipnpm run test exit 1 (job 100534211626; the log download is refused from this container, the annotations carry the exit code only). This diff is 40 scripts/** self-tests and touches nothing under packages/cli; the shard/package is the #14648 signature, and this head already contains the fix accb9231c7, so it is the post-fix recurrence recorded on #14648. Single permitted non-own re-trigger, spent now:update-branch (a real merge of the current origin/main, no rewrite). If the same shard reds again, the PR parks under the #14648 reading; any other red is real. Review of the content is in progress on #13799.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 06:15
@baozhoutao
baozhoutao added this pull request to the merge queueSep 3, 2026
Any commits made after this event will not be merged.
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / selfTestFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
baozhoutao pushed a commit that referenced this pull request Sep 3, 2026
Batch 1b of #13799: the PR #13487 roster-floor shape transplanted onto the
`scripts/**` self-tests whose assertion sink is NOT a block-bodied helper
inside the self-test body -- a concise arrow, or a module-scope function --
so batch 1 (PR #14851) could not transplant it verbatim.
Per the batch-1 review ruling, the roster machinery lives at MODULE scope
(SELF_TEST_BATTERIES / SELF_TEST_BATTERY_FLOOR / UNATTRIBUTED_BATTERY /
battery() / registerCase() / batteryFloorFailures()), and each file's
existing assertion sink is given a minimal block body that calls
registerCase() and returns the original expression unchanged. No case is
rewritten, none is reordered, and no assertion changes meaning: all 18
self-tests exit with the same code and byte-identical output before and
after.
What is pinned is the registered NAMES, not a total: every existing section
banner opens a battery, every assertion is attributed to the battery most
recently opened, the floor requires the OPENED set to equal the DECLARED set
with each battery at or above its own count, and the roster's own size is
pinned so deleting an entry cannot silence a floor quietly.
None of the introduced helpers is named with a self-test spelling. That is
deliberate and recorded beside them: `check:pm-dispatch-gates` anchors on a
top-level declaration whose NAME spells self-test, and every such name owes a
row in that gate's COMPOUND_ANCHOR_LEDGER. These helpers hold no fixtures to
mask and read no path literal, so the accurate name is the one that says
`battery`.
One battery is pinned at its structural invariant rather than at today's
count, with the reason written over the entry: check-plugin-teardown-shape's
exclusions battery runs exactly one case per DELIBERATELY_EXCLUDED row, and
promoting a name onto the teardown roster is a legitimate edit that shrinks
that list.
Census (`node scripts/measure-self-test-floor.mjs --json`): ROSTER 3 -> 21,
NONE 158 -> 140; the set of files whose class changed equals this worklist
exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k1DVWthZyPS7xi1Q72YpK
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xlskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@claude