Skip to content

test(scripts): give 13 more self-tests a battery roster and floor - #15003

Merged
baozhoutao merged 5 commits into
mainfrom
claude/issue-13799-batch2-roster-floor
Sep 3, 2026
Merged

test(scripts): give 13 more self-tests a battery roster and floor#15003
baozhoutao merged 5 commits into
mainfrom
claude/issue-13799-batch2-roster-floor

Conversation

@claude

@claude claude Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of #13799 (batch 2, Tier B — the batch-1 shape).

PR #13487's roster-and-floor shape, exactly as batches 1/1b/1c landed it (PRs #14851, #14872, #14896), transplanted onto the scripts/** self-tests that already carry that shape. 123 batteries / 973 cases pinned across 13 files.

Per file, and nothing else:

  • a module-level frozen SELF_TEST_BATTERIES roster of names with a per-battery floor, SELF_TEST_BATTERY_FLOOR pinning the roster's own size, and UNATTRIBUTED_BATTERY, placed after the import block;
  • battery('BANNER TEXT') at each existing section banner, named verbatim from the banner;
  • one registerCase() at the head of the existing in-body assertion helper;
  • the floor evaluated immediately before the existing verdict site, its messages entering the file's own failure sink so the report the file already prints carries them.

⛔ No case is rewritten, none reordered, no assertion changes meaning. ⛔ No TOTAL is pinned.

The population, re-derived on a fresh tree

Triage's rule (5478879048) — 「#13798 first, per file」 — makes this batch the unfloored set that already has the handshake, not what remains: a floor on a handshake-less file cannot fire, because the floor never runs either.

reading PM parking note 5527609175 measured here on 5bc2f272
files defining a selfTest (.mjs/.mts) 173 175
with a verdict handshake (union of the three landed spellings) 160 160
with a roster floor (SELF_TEST_BATTERIES) 92 92
⇒ dispatchable (handshake ✓, roster ✗) 69 69
⇒ blocked by #13798 (no handshake) 12 14

69 + 14 = 83 = 175 − 92, reconciled. The dispatchable set matches at 69; the whole delta sits inside the blocked set, which this batch excludes by construction (two extra files define a selfTest and carry no handshake: check-adr-symbol-anchors.mjs, symbol-anchors.mjs).

The file surface: 13 floored, 56 deferred with a measured reason

The batch-1 criterion, measured on all three halves: a block-bodied in-body assertion helper, at least two named section banners at statement position (innermost open bracket a brace, never a square bracket or a paren), and a body-level verdict site. 13 of the 69 qualify.

A named section banner carries a marker — a horizontal rule, a box, or an enumerator (// 1. name, // G1: name). An unmarked comment explains the next statement; ⛔ promoting one to a section head is a judgement per comment, which this transplant does not make.

The instrument used to classify all 69 was cross-validated against PR #14896's 15 measured drops: it reproduces every one of them (two differ by a single banner, 0 vs 1, both far below the floor of 2).

Floored (13)

file batteries cases
scripts/check-filter-alias-parity.mjs 7 18
scripts/check-i18n-bundles.mjs 4 (first battery hoisted) 77
scripts/check-i18n-coverage.mjs 4 (first battery hoisted) 71
scripts/check-page-declaration-shape.mjs 8 19
scripts/check-skill-identifier-liveness.mjs 10 75
scripts/check-type-source-resolution.mjs 11 79
scripts/docs-audit/check-audit-scope.mjs 2 (first battery hoisted) 26
scripts/measure-stall-guard-headroom.mjs 15 35
scripts/pm/check-governed-merges.mjs 22 243
scripts/pm/check-governed-prose.mjs 6 28
scripts/pm/check-governed-queue-guard.mjs 17 129
scripts/pm/ci-failure.mjs 14 136
scripts/pm/git-history.mjs 3 37

Three files run cases before their first banner (check-i18n-bundles, check-i18n-coverage, docs-audit/check-audit-scope); their first battery is opened at the top of the body and that banner then carries no second opener — the PR #13487 precedent's own shape, as batch 1b did it. Banners that registered no case are not declared as batteries and get no opener: a battery is a section that actually runs cases. That applies to exactly one banner in this batch (measure-stall-guard-headroom, 16 banners → 15 batteries).

⭐ Two of the 13 read as already-floored and were not

docs-audit/check-audit-scope.mjs prints ✓ check-audit-scope self-test: ${total} cases pass. and measure-stall-guard-headroom.mjs prints ${checked} assertion(s) passed. — both derive a case count and print it, and nothing compares either. If a case array shrinks, the printed number shrinks with it and the gate stays green. Both now carry a real roster floor. (The pair the card names by identifier, typecheck-configs.mjs and check-comment-mask-corpus.mjs, is not in the floored set — both are class-1/class-2 and appear in the table below.)

Deferred (56) — left for a later batch rather than improvised

file measured reason
scripts/ablation-dist-preflight.mjs class-1 — no single in-body assertion helper: the failed sink is written at 6 inline site(s).
scripts/check-adr-links.mjs class-1 — assertions go through a module-level assert, so the self-test body holds no block-bodied assertion helper.
scripts/check-agent-model-declared.mjs class-1 — no single in-body assertion helper: the failed sink is written at 7 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-comment-mask-corpus.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-console-intercept-disarm.mjs class-1 — no single in-body assertion helper: the failures sink is written at 2 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-declaration-mirrors.mjs carried forward from PR #14896, re-confirmed here: class-1 concise-arrow sink const ok = (label, cond) => cases.push({ label, cond });, no block body for registerCase(). (Also 0 named section banners.)
scripts/check-doc-anchors.mjs class-1 — assertions go through a module-level assert, so the self-test body holds no block-bodied assertion helper.
scripts/check-docs-single-h1.mjs class-1 concise-arrow sink t — no block body to hold registerCase(); class-2 — 1 named section banner(s) in the body, below the two the criterion needs.
scripts/check-dts-emitted.mjs carried forward from PR #14896, re-confirmed: 0 named section banners in the self-test body (needs 2).
scripts/check-durability-degradation-log-level.mjs Tier C by the card: a multi-entry dispatch combining several self-test callees. Excluded by construction. (Also 0 named section banners in the body.)
scripts/check-error-code-casing.mjs class-1 — no single in-body assertion helper: the failed sink is written at 3 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-examples-live-imports.mjs class-1 — no single in-body assertion helper: the failed sink is written at 1 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-exported-any-returns.mts class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-kernel-hook-pairs.mjs class-1 — assertions go through a module-level assert, so the self-test body holds no block-bodied assertion helper.
scripts/check-logger-receiver-detach.mjs carried forward from PR #14896, re-confirmed: below the two named section banners the criterion needs (this instrument reads 0, b1c read 1; both below the floor).
scripts/check-meta-type-normalized.mjs class-1 — no single in-body assertion helper: the problems sink is written at 4 inline site(s); class-2 — 1 named section banner(s) in the body, below the two the criterion needs.
scripts/check-objectql-double-limit.mjs carried forward from PR #14896, re-confirmed: 1 named section banner, below the two the criterion needs.
scripts/check-optional-error-sink-contract.mjs class-1 — no single in-body assertion helper: the failures sink is written at 7 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-org-identifier.mjs class-1 — no single in-body assertion helper: the failed sink is written at 2 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-osv-exemptions.mjs class-3 — no body-level verdict site, so there is no place inside the body to evaluate a floor before the verdict; class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-override-consistency.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-platform-checklist.mjs Tier C by the card: a multi-entry dispatch combining several self-test callees, so there is no single selfTest body to floor. Excluded by construction.
scripts/check-pnpm-acquisition.mjs class-1 concise-arrow sink t — no block body to hold registerCase(); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-published-files.mjs class-1 — no single in-body assertion helper: the failures sink is written at 7 inline site(s).
scripts/check-refd-timer-probe.mjs class-1 — no single in-body assertion helper: the failed sink is written at 5 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-sdui-manifest.mjs class-1 — no single in-body assertion helper: the failures sink is written at 1 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-skill-compatibility-version.mjs carried forward from PR #14896, re-confirmed: 1 named section banner, below two; and no block-bodied in-body assertion helper (the failed sink is written at 7 inline sites).
scripts/check-skill-frame-freshness.mjs carried forward from PR #14896, re-confirmed: no in-body assertion helper at all — cases is pushed at 12 separate inline sites, so there is no single block body for registerCase().
scripts/check-skill-frame-sync.mjs class-1 — no single in-body assertion helper: the failed sink is written at 5 inline site(s); class-2 — 1 named section banner(s) in the body, below the two the criterion needs.
scripts/check-skills-token-ratchet.mjs class-1 — no single in-body assertion helper: the failed sink is written at 1 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/check-spec-parsed-alias.mjs carried forward from PR #14896, re-confirmed: no named section banner in the self-test body — its comments label individual cases, not sections.
scripts/check-stack-collection-maps.mjs carried forward from PR #14896, re-confirmed: 0 named section banners in the self-test body.
scripts/check-startup-registry-verdict.mjs carried forward from PR #14896, re-confirmed: 1 named section banner, below the two the criterion needs.
scripts/check-tenant-chokepoint.mjs carried forward from PR #14896, re-confirmed: 0 named section banners — three unmarked prose comments head its blocks, and promoting one to a section head is a judgement per comment this transplant does not make.
scripts/check-test-completeness.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 1 named section banner(s) in the body, below the two the criterion needs.
scripts/check-turbo-task-graph.mjs carried forward from PR #14896, re-confirmed: class-3 — no body-level verdict site (selfTest() returns a failures array; the verdict is printed by a separate runSelfTest()). Also 0 named section banners.
scripts/check-whole-set-label-write.mjs carried forward from PR #14896, re-confirmed: below the two named section banners the criterion needs (this instrument reads 0, b1c read 1).
scripts/check-widget-option-census.mjs class-1 — no single in-body assertion helper: the failed sink is written at 5 inline site(s); class-2 — 1 named section banner(s) in the body, below the two the criterion needs.
scripts/check-wildcard-fallthrough.mjs carried forward from PR #14896, re-confirmed: 0 named section banners — four unmarked prose comments head its blocks.
scripts/check-workspace-manifest-cycles.mjs class-3 — no body-level verdict site, so there is no place inside the body to evaluate a floor before the verdict.
scripts/checklist-select.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/js-comment-mask.mjs carried forward from PR #14896, re-confirmed: 0 named section banners in the self-test body.
scripts/measure-position-name-fold-census.mjs class-3 — no body-level verdict site, so there is no place inside the body to evaluate a floor before the verdict; class-1 — no single in-body assertion helper: the problems sink is written at 15 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/measure-test-shard-timings.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/partition-test-shards.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict).
scripts/pm/check-clause2-carriers.mjs class-1 concise-arrow sink t — no block body to hold registerCase().
scripts/pm/check-half-states.mjs class-1 concise-arrow sink — const t = (name, actual, expected) => cases.push([name, actual, expected]); (L11941) has no block body to hold registerCase(). (The analyzer could not resolve this file's body automatically either: js-comment-mask.mjs mis-scans it at ~17 kloc and blanks the function keyword, so the reading above is by hand.)
scripts/pm/check-label-desc-cap.mjs class-2 — 1 named section banner(s) in the body, below the two the criterion needs.
scripts/pm/check-skill-id-lint.mjs class-1 — no single in-body assertion helper: the failed sink is written at 1 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/pm/check-skill-line-ratchet.mjs class-1 — no single in-body assertion helper: the failed sink is written at 1 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/pm/dispatch-gates.mjs shape ✓, behaviour ✗ — measured, not guessed. 74 banners / 73 live batteries / 1288 cases, and the transplant renders cleanly, but this self-test READS ITS OWN SOURCE: with the roster in place node scripts/pm/dispatch-gates.mjs --self-test prints declare 26 literal(s) where the base tree prints 23, and 3116 tracked files where the base prints 2992. Four battery names carry path-shaped text (e.g. The scripts/** blind spot, closed at the source (#10784)) and the gate's own path-population extractor reads them as declared populations. That is a change of meaning, not a no-op, so it is deferred rather than improvised past. (Its self-test also costs ~288 s per run, twice per verification.)
scripts/pm/release-rehearsal-clone.mjs class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/publish-smoke-pack.mjs carried forward from PR #14896, re-confirmed: no comment at statement position in the self-test body at all, so no section banner.
scripts/render-release-coverage-anchor.mjs class-1 — no in-body assertion sink at all (bare throw / table-driven verdict); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/run-with-stall-guard.mjs class-2 — 0 named section banner(s) in the body, below the two the criterion needs.
scripts/typecheck-configs.mjs class-3 — no body-level verdict site, so there is no place inside the body to evaluate a floor before the verdict; class-1 — no single in-body assertion helper: the failures sink is written at 2 inline site(s); class-2 — 0 named section banner(s) in the body, below the two the criterion needs.

Shrink-only ledgers: scanned, none found in this batch

Every battery that drives its cases off a module-level constant was enumerated inside the 13 self-test bodies and each underlying list read: FAILURE_BRANCHES (check-i18n-coverage), WORKSPACE_PARENT_GLOBS (check-type-source-resolution), REPLAYS and GOVERNED_SURFACES (check-governed-merges), PROSE_SURFACES (check-governed-prose), GOVERNED_SURFACES, GOVERNED_APPROVERS, REPLAYS and GENERATED_SURFACE_EXCEPTIONS (check-governed-queue-guard). None is shrink-only:

  • REPLAYS is a set of incident replays and only grows; GOVERNED_SURFACES, PROSE_SURFACES and GENERATED_SURFACE_EXCEPTIONS are registers that grow as surfaces and generators are governed;
  • FAILURE_BRANCHES is the gate's own branch set, whose length the verdict line already prints;
  • GOVERNED_APPROVERS is a pinned two-account set — the assertion immediately above the loop is the-authorized-set-is-exactly-the-ruled-two-accounts, so an edit to it already reds by design and the floor adds no new friction.

So no floor in this batch moves with a list a legitimate edit shortens.

Evidence

Behaviour is unchanged, per file

For all 13: node FILE --self-test before and after, exit code captured by redirect before any pipe. 13/13 exit 0 both sides, with stdout and stderr byte-identical on every one (compared in full, not sampled). The two check:i18n* readings are from the tree after pnpm install and a workspace build; without the build both gates exit 3 on a missing-CLI prerequisite, which is container state, not a verdict.

Census

node scripts/measure-self-test-floor.mjs --json:

base 5bc2f272 this branch dc3e2815
ROSTER 91 104
COUNT 4 2
NONE 72 61

Three set assertions, computed in python, not read by eye:

  1. every one of the 13 worklist files reads ROSTER after — True; before, 11 read NONE and 2 read COUNT (the instrument's own high-recall "candidate to read" class, which its header says is not a verdict — both were hand-read and are the false floors described above);
  2. the set of files whose class changed equals the worklist exactly (symmetric difference empty) — True;
  3. git diff --name-only equals the worklist exactly — True.

Ablations — four, each from the committed implementation

Each leg carries a trap … EXIT INT TERM restore on absolute paths. The mutation is proved on disk by an anchored count and git hash-object against the HEAD blob (an empty hash is read as FAILURE, not as "nothing to compare"), and the restore by an empty git diff HEAD — never by an exit code. The anchor is required to match exactly one line or the leg aborts. No dist is on the resolution path of any of these four files, so no rebuild leg applies.

  1. A battery's cases deletedscripts/pm/check-governed-prose.mjs, the 3 cases under battery('codeSpansIn') (5575ba248f4b0d32). Exit 0 → 1: self-test battery "codeSpansIn" DID NOT RUN — 0 cases registered, 3 pinned. The verdict below would have claimed those cases hold.
  2. A roster entry deletedscripts/docs-audit/check-audit-scope.mjs, the 'the injection contract (#13591)': 1, row (anchored count 1 → 0; 60debd41db15d005). Exit 0 → 1, naming both halves: SELF_TEST_BATTERIES declares 1 batteries, below the pinned 2 and battery "the injection contract ([finding] Adding a NEW hand-written page under content/docs/ makes a PR human-merge-only — always, and invisibly until the gate runs #13591)" registered 1 case(s) but is not declared in SELF_TEST_BATTERIES.
  3. The introduced registerCase() removed from the sink helperscripts/check-filter-alias-parity.mjs (anchored count 1 → 0; f54a07e3568fd046). Exit 0 → 1 with every original case still passing: all 7 batteries report DID NOT RUN, so the file's own green verdict is exactly what the floor refuses.
  4. One battery() opener deletedscripts/check-page-declaration-shape.mjs, battery('Comment masking, both directions'); (anchored count 1 → 0; 00b6c350deb47921). Exit 0 → 1: battery "Comment masking, both directions" DID NOT RUN — 0 cases registered, 3 pinned.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack from this worktree after the edits (no paths passed; the script reads the change set from git — 13 paths). 38 commands derived + node scripts/pm/check-governed-queue-guard.mjs --self-test (that gate's self-test runs from governed-surface-guard.yml, not lint.yml, so the lint-derived list does not name it) + pnpm check:declared-population-live = 40 run. Every exit code captured by redirect before any pipe.

  • 39 RAN-PASS (exit 0) of the 40, including check:pm-dispatch-gates (exit 0, dispatch-gates self-test: 1288 cases pass), check:declared-population-live (exit 0), check:ratchet-remedy-authority (exit 0) and check:nul-bytes (exit 0).
  • check-test-completenessexit 3, NOT MEASURED by the gate's own instruction (PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named). Not a pass and not a red.
  • Three first-pass readings that were container state, all cleared and re-run green: check-engine-split-ratio exit 2 (this clone is shallow … a ratio derived here would be real, plausible and WRONG) → 0 after git fetch --shallow-since=2026-05-29 origin main; check:i18n and check:i18n-coverage exit 3 (PREREQUISITE NOT MET — the workspace CLI is not built, with both --self-test halves already printing their ✓ line) → 0 each after pnpm exec turbo run build --filter=./packages/* --filter=./packages/*/* under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, held 453s). Neither is a verdict about this diff, and neither was read as a pass before it was re-run.
  • pnpm lint (whole repo, eslint . --no-inline-config) — exit 0 on dc3e2815, 82 s. No narrowing claimed.
  • Control-byte scan over the 13 changed files (grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]') — no hits; check:nul-bytes exit 0.

The build left the tracked tree unchanged (git status --porcelain empty).

scripts/** publishes nothing ⇒ skip-changeset.

Post-merge: origin/main merged in, one conflict resolved (2026-09-03)

PR evicted from the merge queue at 17:59:29Z on a merge conflict, not a test failure (mergeable_state: dirty; its own CI was green on dc3e2815 and no merge-group build ever ran). Resolved by a real merge commit — ⛔ no rebase, no amend, no force-push.

Exactly one file conflicted: scripts/pm/check-governed-merges.mjs, changed on main by 5d4d55aec "tooling(pm): govern hotcrm in check-governed-merges (#14867) (#14987)". The other 12 are untouched by the merge (git diff --stat dc3e2815 HEAD over the 13 lists that one file and nothing else).

Both sides kept. The hunk was my battery('multi-repo scope (#9619)'); opener against main's replacement of four-governed-repos-declared with five-governed-repos-declared plus a new hotcrm-is-a-governed-repo-with-its-slug (#14867) assertion. The resolution keeps the opener and both of main's assertions; nothing of main's hotcrm governance is dropped, and no floor is loosened. Main's added comment is unmarked prose explaining the next statement, ⛔ not promoted to a section head, so the file gains no battery.

The battery numbers moved, and were re-read rather than assumed. A probe run over the merged file (dump inserted, mutation proved by git hash-object, restored to an empty git diff HEAD) reports:

  • declared set equals opened set — 22 / 22, symmetric difference empty;
  • exactly one battery moved: multi-repo scope (#9619) 15 → 17 (main's one-assertion-becomes-two, plus one more case the new register row adds through that section's own loop); total 243 → 245, matching the file's own 245 assertions verdict line;
  • that entry's floor was re-read to 17. Every other floor is unchanged, and SELF_TEST_BATTERY_FLOOR stays 22.

Re-verified on the merge result 8d6d40e6:

  • Behaviour byte-identical, measured in place rather than from a copy: origin/main's own version of the file swapped into the worktree (7486320e8f1afdf2, proved equal to the origin/main blob), run, then restored to an empty git diff HEAD. Both sides exit 0 with stdout and stderr byte-identical. ⚠️ A first reading of this file exited 1 with the battery below its floor; that was the fresh worktree having no node_modules, so the real-generator battery could not run — container state, not a case deletion, and it cleared to exit 0 after pnpm install. It is recorded rather than quietly re-run.
  • A fifth ablation leg, on the merged file: main's own assert('five-governed-repos-declared', …) line deleted (anchored count 1 → 0, 0585ed5acee9dfa2). Exit 0 → 1: self-test battery "multi-repo scope (check-governed-merges cannot answer its own question where it is actually run: sibling repos are out of scope, and merged_by is UNRESOLVED without a token #9619)" registered 16 case(s), below its pinned floor of 17. Restored to an empty git diff HEAD. So the re-read floor is load-bearing over main's change, not merely satisfied by it.
  • Gates re-derived and re-run on 8d6d40e6 — the derived family is byte-identical to the pre-merge one (38 commands), and the same 40 ran with the same result: 39 RAN-PASS, 1 NOT MEASURED (check-test-completeness exit 3). check:pm-governed-merges exit 0; check:pm-dispatch-gates exit 0 (1288 cases). The two check:i18n* gates again needed the workspace build in this fresh worktree (exit 3, both --self-test halves green) and were 0 each after it, under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, held 425s).
  • pnpm lint whole repo — exit 0 on 8d6d40e6, 79 s. Control-byte scan clean; build left the tracked tree unchanged.
  • git diff --stat origin/main HEAD -- scripts/ is still exactly the 13 files, 1365 insertions / 1 deletion — the same net shape as before the merge, now purely additive over current main.

⛔ Left as a draft with no auto-merge armed, per the coordinator.


🤖 Generated with Claude Code

https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk


Generated by Claude Code

Part of #13799 (batch 2, Tier B — the batch-1 shape).

PR #13487's roster-and-floor shape as batches 1/1b/1c landed it, transplanted
onto four `scripts/**` self-tests that already carry that shape.

⛔ No case is rewritten, none reordered, no assertion changes meaning.
⛔ No TOTAL is pinned — the roster pins registered NAMES.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 2, Tier B — the batch-1 shape).

⛔ No case is rewritten, none reordered, no assertion changes meaning.
⛔ No TOTAL is pinned — the roster pins registered NAMES.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Part of #13799 (batch 2, Tier B — the batch-1 shape).

⛔ No case is rewritten, none reordered, no assertion changes meaning.
⛔ No TOTAL is pinned — the roster pins registered NAMES.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 15725f3eeb58eea0a3779cd095e88f757fa086a8packageMentionDocs.

@baozhoutao
baozhoutao marked this pull request as ready for review September 3, 2026 17:24
@baozhoutao
baozhoutao requested a review from hotlong as a code owner September 3, 2026 17:24
@baozhoutao
baozhoutao enabled auto-merge September 3, 2026 17:24
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Sep 3, 2026
# Conflicts:
#	scripts/pm/check-governed-merges.mjs
…merge

`origin/main`'s #14867 change (`hotcrm` added to `GOVERNED_REPOS`) grows the
`multi-repo scope (#9619)` battery from 15 cases to 17: one assertion becomes
two, and the new register row adds one more through the section's own loop.
Re-read from a probe run rather than assumed — the declared set still equals
the opened set (22/22), and the file's self-test output stays byte-identical
to `origin/main`'s version of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit 8a96e66 Sep 3, 2026
35 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13799-batch2-roster-floor branch September 3, 2026 19:22
baozhoutao pushed a commit that referenced this pull request Sep 4, 2026
… hoisted battery (#13799)

The self-test decided success by `failures.length === 0` alone, so "every case
held" and "the cases never ran" printed the same line. It carries no named
section banner, and a comment is not promoted to a section head, so it declares
ONE battery opened at the top of the body -- the hoisted shape PRs #14896 and
#15003 landed for exactly this case.

Floor 8, measured rather than transcribed: the roster was probed with a
deliberately unreachable pin and the floor's own report named the registered
count. Behaviour is unchanged -- `--self-test` stdout and stderr are
byte-identical against origin/main, exit 0 both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>
baozhoutao pushed a commit that referenced this pull request Sep 4, 2026
…e-limit self-tests (#13799)

Both decided success by `failures.length === 0` alone. Neither carries the two
named section banners the sectioning criterion needs, and a comment is not
promoted to a section head, so each declares ONE battery opened at the top of
its self-test body -- the hoisted shape PRs #14896 and #15003 landed.

Floors 47 and 47, measured by probing the roster with an unreachable pin and
reading the count the floor's own report names. `--self-test` stdout and stderr
are byte-identical against origin/main for both, exit 0 on both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>
baozhoutao pushed a commit that referenced this pull request Sep 4, 2026
…tered battery

The 22 bare `if (...) throw ...` assertions in `selfTest()` are each wrapped
verbatim in the `check(() => { ... })` thunk PR #15198 landed: the condition is
carried in untouched, so no `!` can be dropped while the case still registers
and still passes. Zero named section banners, so one hoisted battery (the
PR #14896 / #15003 / #15217 shape), floored at the measured 22 with the roster's
own size pinned at 1. The floor throws, matching this file's own sink, and is
evaluated before the verdict so the success line can only be printed by a run
that actually ran its cases.

Part of #13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 9, 2026
…isted battery each (objectstack-ai#13799 batch 5) (objectstack-ai#15217)

* tooling(scripts): floor the check-dts-emitted self-test with a single hoisted battery (objectstack-ai#13799)

The self-test decided success by `failures.length === 0` alone, so "every case
held" and "the cases never ran" printed the same line. It carries no named
section banner, and a comment is not promoted to a section head, so it declares
ONE battery opened at the top of the body -- the hoisted shape PRs objectstack-ai#14896 and
objectstack-ai#15003 landed for exactly this case.

Floor 8, measured rather than transcribed: the roster was probed with a
deliberately unreachable pin and the floor's own report named the registered
count. Behaviour is unchanged -- `--self-test` stdout and stderr are
byte-identical against origin/main, exit 0 both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>

* tooling(scripts): floor the logger-receiver-detach and objectql-double-limit self-tests (objectstack-ai#13799)

Both decided success by `failures.length === 0` alone. Neither carries the two
named section banners the sectioning criterion needs, and a comment is not
promoted to a section head, so each declares ONE battery opened at the top of
its self-test body -- the hoisted shape PRs objectstack-ai#14896 and objectstack-ai#15003 landed.

Floors 47 and 47, measured by probing the roster with an unreachable pin and
reading the count the floor's own report names. `--self-test` stdout and stderr
are byte-identical against origin/main for both, exit 0 on both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>

* tooling(scripts): floor the spec-parsed-alias and stack-collection-maps self-tests (objectstack-ai#13799)

check-spec-parsed-alias decided success by `failures.length === 0` alone.
check-stack-collection-maps already COUNTED its assertions and printed the
number -- but nothing compared it, so a case block that stopped running shrank
the printed count and the gate stayed green: evidence, not proof.

Neither carries the two named section banners the sectioning criterion needs,
and a comment is not promoted to a section head, so each declares ONE battery
opened at the top of its self-test body.

Both floors measured at 18. The two hand-written verdict counts agree with the
registered count on this tree (`18 assertions passed`, `18 assertions over
synthetic sources`), so neither had drifted. `--self-test` stdout and stderr are
byte-identical against origin/main for both, exit 0 on both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>

* tooling(scripts): floor the tenant-chokepoint and label-desc-cap self-tests (objectstack-ai#13799)

Both decided success by their sink alone (`failures.length === 0`, `failed === 0`),
so "every case held" and "the cases never ran" printed the same line.
tenant-chokepoint's blocks are headed by unmarked prose and label-desc-cap
carries one banner, below the two the sectioning criterion needs; a comment is
not promoted to a section head and a lone banner is not split, so each declares
ONE battery opened at the top of its self-test body.

label-desc-cap's sink is a counter rather than a list, so its floor prints the
breach and folds it into `failed` -- the same refusal in that file's own idiom.

Floors 17 and 44, measured by probing the roster with an unreachable pin.
`--self-test` stdout and stderr are byte-identical against origin/main for both,
exit 0 on both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>

* tooling(scripts): floor the whole-set-label-write and wildcard-fallthrough self-tests (objectstack-ai#13799)

Neither carries the two named section banners the sectioning criterion needs, so
each declares ONE battery opened at the top of its self-test body. Floors 41 and
18, measured by probing the roster with an unreachable pin.

whole-set-label-write registers from `expect()` only. Its two trailing ledger
loops walk WHOLE_SET_ACTIONS and ALLOWLIST and push straight to `failures`; they
are left unregistered ON PURPOSE, because ALLOWLIST is meant to shrink and a
floor that moved with it would red every legitimate removal -- the one habit
these floors exist to prevent. The comment above the roster says so in place.

wildcard-fallthrough refuses in place rather than collecting, so its floor
refuses in place too. ⚠️ Its verdict prints a TRANSCRIBED `17 cases` while the
body has 18 assert call sites and registers 18 -- the literal had already
drifted one low. It is left untouched so this change stays a pure no-op on
output, and filed separately; the floor is what makes the drift harmless.

`--self-test` stdout and stderr are byte-identical against origin/main for both,
exit 0 on both sides.

Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 9, 2026
…ecipe-A self-tests (objectstack-ai#15307)

* test(scripts): floor measure-test-shard-timings' self-test on a registered battery

The 22 bare `if (...) throw ...` assertions in `selfTest()` are each wrapped
verbatim in the `check(() => { ... })` thunk PR objectstack-ai#15198 landed: the condition is
carried in untouched, so no `!` can be dropped while the case still registers
and still passes. Zero named section banners, so one hoisted battery (the
PR objectstack-ai#14896 / objectstack-ai#15003 / objectstack-ai#15217 shape), floored at the measured 22 with the roster's
own size pinned at 1. The floor throws, matching this file's own sink, and is
evaluated before the verdict so the success line can only be printed by a run
that actually ran its cases.

Part of objectstack-ai#13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* test(scripts): floor measure-position-name-fold-census' self-test on a registered battery

The 13 `if (...) problems.push(...)` assertion sites in `selfTest()` are each
wrapped verbatim in the `check(() => { ... })` thunk PR objectstack-ai#15198 landed. The sink
here is FAILURE-ONLY, so routing `problems.push` itself through `registerCase()`
would have inverted the floor rather than installing it: a green run would
register nothing and the battery would read DID NOT RUN. Zero named banners, so
one hoisted battery, floored at the 24 registrations measured on a run (four of
the thirteen sites sit inside loops: 9 + 4 + 4 + 2 + 5).

The floor lives inside the `!quiet` branch. `main()` gates the PRODUCTION census
on `selfTest({ quiet: true })`, which prints no verdict and so makes no claim for
a floor to guard; evaluating it there would let a roster edit change what a
census run outputs. Both production modes are byte-identical to the base tree.

One site stays outside the roster and says so in place: the `catch` arm of the
AUDIT_CONTROLS loop ends in `continue`, illegal inside the thunk's arrow
function, and rewriting that control flow is exactly what the verbatim rule
forbids. Its sibling in the same loop body is floored, so a loop that stops
running still reds.

Part of objectstack-ai#13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* test(scripts): floor check-override-consistency's self-test on its table rows

Recipe A as the pilot PR objectstack-ai#15271 settled it: each of the 17 row labels of the
literal `cases` table is a declared battery with a floor of 1, `registerCase(name)`
is the first statement of the driving loop body, and the roster is a LITERAL the
table is cross-checked against so a deleted or renamed row names ITSELF rather
than deleting its own floor. Roster size pinned at 17; duplicate labels are
refused from both sides. The three `// --- ... ---` comments inside the array are
grouping rules, not section heads.

The boolean `passed` becomes a `failures` counter so the red line can carry the
recipe's wording, `N failure(s) (cases and floor)`; no assertion condition is
touched and the green line is byte-identical to the base tree's.

Part of objectstack-ai#13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* test(scripts): floor check-skill-line-ratchet's self-test on all 155 table rows

Recipe A per the pilot PR objectstack-ai#15271: every row label is a declared battery with a
floor of 1, `registerCase(name)` is the first statement of the driving loop,
the roster is a LITERAL cross-checked against the table, size pinned at 155.
The only deleted line is the red-run verdict, reworded to the recipe's
`N failure(s) (cases and floor)`; the green line stays byte-identical.

The batch-8 census flagged this table's four `...(() => { ... })()` spreads as an
IIFE-produced block whose rows could not take a literal roster key. Measured, that
premise does not hold here: each IIFE is a SCOPING device that declares local
fixture consts and then returns an array of LITERAL [label, actual, expected]
rows. No label is a template string or computed, and no row comes from a
map/push/loop. Three independent readings agree on 155 -- labels extracted from
source, literal row starts, and the `cases.length` the green line prints on a run
-- so ALL 155 rows are floored with no residue, rather than the partition the row
anticipated.

Part of objectstack-ai#13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants