Skip to content

fix(scripts): move check-ci-filter-parity's self-test fixtures inside selfTest() - #11631

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-10841-self-test-fixture-fabrication
Aug 24, 2026
Merged

fix(scripts): move check-ci-filter-parity's self-test fixtures inside selfTest()#11631
os-steve merged 1 commit into
mainfrom
claude/issue-10841-self-test-fixture-fabrication

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#10841

scripts/check-ci-filter-parity.mjs kept its self-test fixture apparatus at module
scope: the REAL_TEST_IF condition constant, the fixtureWorkflow builder, and the
table declaration-table helper. All three are used only by selfTest() — every
call site is inside it — but dispatch-gates.mjs blanks self-test bodies before
scanning a gate's module body for the path literals it reads, so a fixture helper
hoisted out of that body escapes the blanking and its fixture globs are read as the
gate's declared population.

This moves the three declarations inside selfTest(). No behaviour change: same
fixtures, same 39 assertions, same real run. Triage's remedy 1, taken at its widest
sensible boundary — the whole fixture apparatus rather than just the two defaults —
so the site is closed for the class and not only for the two instances. Remedy 3
(teaching maskSelfTests about module-scope self-test-only constants) is a
scripts/pm/dispatch-gates.mjs change and is untouched here.

Premise re-verified on today's tree

The card was measured on 2026-08-21 at PR #10801's merged ref. Re-derived here on
origin/main3637731e2 — 152 families today, up from the 150 quoted in dispatch,
after dispatch-gates.mjs gained import-following (#11512) and the --self-test
invocation matcher (#11554):

#11554's rule — a self-test family follows no import — does not reach this site. That
rule decides which modules a family inherits hints from; this leak is a literal in
the gate's own module body, which every family scans directly. Same species, one level
in.

Price

Census over all 6511 tracked files against all 152 families, using the derivation's own
coveringKey per (family, file):

beforeafter
families discovered152152
families with at least one pair134134
total (gate, file) pairs6673361407
  • pairs lost: 5326 — every one of them this single family's
  • pairs gained: 0
  • pairs re-attributed (pair survives, covering key or via changes): 0

Gain and re-attribution are counted separately, per the standard #11512 and #11554 were
held to. There is no re-attribution here at all.

The genuine hints did not shrink

The family's hint set goes from four entries to one:

dropped: packages/** scripts/** @objectstack/probe
added: (none)

All three are self-test fixtures. @objectstack/probe is the fixture declaration
table's package name; it was already inert for matching (no tracked path under it) and
contributed 0 of the 5326. It falls out of the same move and is reported for
completeness, not counted as gain.

The gate's real population is asserted rather than eyeballed — its surviving pairs are
exactly two, enumerated in full:

.github/workflows/ci.yml ⇢ gate source '.github/workflows/ci.yml'
scripts/check-ci-filter-parity.mjs ⇢ gate script (identity)

That is the whole of what the gate opens: readFileSync(join(root, CI_WORKFLOW)) in
main() and list(), plus CROSS_PACKAGE_TEST_INPUTS imported from the sibling gate.
The census compared the hint set of every family, not just this one, precisely
because a lead that stops appearing looks exactly like a lead that was never earned: no
other family moved in either direction.

Non-vacuity, both directions

Reverse-verified from the committed fix by restoring the pre-fix file out of
origin/main, under a trap ... EXIT INT TERM restore. The mutation was proven on
disk — sha256 changed, and the fixtureWorkflow declaration anchor moved from column 0
to column 2 and back — and the restore proven byte-identical (sha256 equal to the fixed
file, git status clean for the path):

derivation inputmutated (pre-fix)restored (fix)
packages/core/src/index.tsMATCHED via gate source packages/**absent
scripts/check-nul-bytes.mjsMATCHED via gate source scripts/**absent
.github/workflows/ci.ymlMATCHED via gate source .github/workflows/ci.ymlMATCHED, same key

No rebuild leg applies here: dispatch-gates.mjs reads this gate with readFileSync
on the source path, never through a package exports map or a dist/ artifact, so
there is no build step standing between the edit and the measurement.

Gates

Derived union for this diff — node scripts/pm/dispatch-gates.mjs with no paths, so
the change set comes from the merge base rather than from a hand-written list — run at
head f30da6d0e (the final commit), exit codes captured before any pipe:

gateexitits own verdict line
pnpm check:cross-package-test-inputs0green
pnpm check:entry-guard0✓ check:entry-guard: 142 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0green
pnpm check:pnpm-filter-targets0green
node scripts/check-ci-filter-parity.mjs0OK: all 95 declared cross-package glob(s) (80 unique) are covered by core or crosspkg
node scripts/check-ci-filter-parity.mjs --self-test0✓ check-ci-filter-parity --self-test: 39 assertions
node scripts/check-cross-package-test-inputs.mjs0green

Plus the two standing families: pnpm check:nul-bytes (0 — check-nul-bytes: OK (scanned 6506 text file(s) ... no raw ASCII control bytes)) and
pnpm check:pm-dispatch-gates (0 — ✓ dispatch-gates self-test: 579 cases pass.),
the latter because this change is measured by that tool.

Run through scripts/pm/os-verify-lock.sh; its verdict line was
VERDICT command-exit 0 · held the lock 66s · waited 0s.

No changeset

scripts/ only — a dev-tooling gate that is not published and releases nothing, so this
PR carries the skip-changeset label instead of a changeset file.

Generated by Claude Code


Generated by Claude Code

…elfTest()
The fixture builder, its condition constant and its declaration-table helper
sat at module scope while being used only by selfTest(). dispatch-gates.mjs
blanks self-test BODIES before scanning a gate's module body for the path
literals it reads, so a module-scope fixture helper escapes that blanking and
its fixture globs are read as the gate's declared population.
The two subtree globs the core/crosspkg defaults spell put this gate in the
MATCHED column for 5326 tracked files it never opens. Its real population is
.github/workflows/ci.yml and its own source.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026
@os-steve
os-steve marked this pull request as ready for review August 24, 2026 10:16
@os-steve
os-steve added this pull request to the merge queueAug 24, 2026
Merged via the queue into main with commit 8d2c95dAug 24, 2026
32 checks passed
@os-steve
os-steve deleted the claude/issue-10841-self-test-fixture-fabrication branch August 24, 2026 10:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

2 participants

@os-steve@claude