Skip to content

Commit 43e928d

Browse files
feat(gates): check:self-test-wired audits every root alias that declares a --self-test (#21351) (#21366)
Fixes #21351 Clause-②: no ## What changes `scripts/check-self-test-wired.mjs` gains the population source triage directed (comment 5947041331): every root `package.json` alias whose expansion carries `--self-test`. The existing gate is widened to its stated purpose. No gate is added and no workflow is edited. - **Membership** (`collectAliasDeclarations`). A root alias is a member when its expansion self-tests a script. The expansion goes through the same `expandAlias` the workflow half already uses, so `pnpm ALIAS` chains count. A root alias is also a member when its own text has a right-bounded `--self-test` that the anchor cannot attribute to a script path. The roster is computed inside `collectPopulation` from the one parse of `package.json` that the workflow extraction already does. `package.json` is not read a second time. - **Verdict** (`auditAliasPopulation`). For each member, every script its expansion self-tests must be run with `--self-test` by some workflow step or composite action. That can happen by path, through this alias, or through any alias a step names. An existing `SELF_TEST_RUN_OTHERWISE` row also counts. When neither holds, the gate reports `[alias-self-test-not-run] pnpm ALIAS`, which names the alias and the unrun script(s). A literal the anchor cannot attribute is reported as `[alias-self-test-unattributed]`. - **Allowlist** (`SELF_TEST_ALIASES_OUTSIDE_CI`, rows of `{ alias, why }`, in the gate's own file). The list is **empty**: no alias qualifies, because all 170 are wired. `auditAliasAllowlist` reports a row as red in four cases: - it has no reason; - its alias no longer exists; - its alias's expansion no longer carries `--self-test`; - a workflow now runs every self-test the alias declares. The remedy text refuses the allowlist as a way to clear a finding. Judging whether a row is legitimate is marked ⛔ MAINTAINER-ONLY, following the existing ledger's wording. - **Floor.** `refusalFor` refuses a reading whose alias roster is empty or absent ("the alias reader is broken"). This is the last arm, so the sibling gate's refusal pins still hit the arms they hit before. - ⛔ **`population` is unchanged.** That export means "the self-tests CI runs", and `check-self-test-workflow-commands.mjs` spawns every member of it. An alias that CI does not run has no place in that sweep. The sibling's scope line still reads 232. ## Measured: objectstack `main` 23365ea (base) against this head 98d23b3 **Roster.** 170 root aliases carry `--self-test`, and for every one of them each self-tested script is run with the flag by a workflow step: - 153 aliases are named by a workflow directly. - For the other 17, the script's self-test is run by path or through another alias. For example, `check:adr-links` is not named, but `check-links.yml` runs `node scripts/check-adr-links.mjs --self-test`. - No alias is unwired and no literal is unattributable, so the allowlist is empty. - No current alias turned red, so no workflow edit is needed. **Probes.** These are production runs of the gate on scratch copies of `scripts/`, `.github/workflows`, `.github/actions` and `package.json`. Only the gate file differs between the two columns: base blob c36931a against head blob 89cf1f5. | tree | base gate | this gate | |---|---|---| | unmodified | exit 0 | exit 0 | | plus alias `check:pm-probe-unwired` = `node scripts/pm/measurement-claim-triage.mjs --self-test`, named by no step | exit 0 | exit 1, `[alias-self-test-not-run] pnpm check:pm-probe-unwired` | | `lint.yml` step `Issue-transfer door self-test` (`pnpm check:pm-issue-transfer`) deleted | exit 0 | exit 1, `[alias-self-test-not-run] pnpm check:pm-issue-transfer` | ## Pins The new battery `declared alias population` has 22 cases. The battery registry floor goes from 11 to 12. - **Deleting the only step that runs an alias goes red and names the alias.** This is pinned two ways: - on pure inputs; - end to end through `collectPopulation` on a fixture tree. That case also asserts that the old named-population audit stays silent on the same tree, so the hole and the repair are in one case. - **An allowlisted alias stays green.** The row excuses only its own alias: a second alias that declares the same script still goes red. - **The current roster passes.** This is the production run on this tree, which exits 0. `lint.yml` runs it on every PR. A self-test cannot hold a tree verdict. - **Stale allowlist rows go red:** a row for an alias that is gone, one whose expansion lost `--self-test`, one whose self-tests a workflow now runs, and one with no reason. - **Crediting routes stay green:** an alias a step names, a chain alias a step names, a script self-tested by path, and a script with a `SELF_TEST_RUN_OTHERWISE` row. - **Partial wiring still goes red.** A step running the script without the flag goes red. A two-script alias with one script unrun names exactly that one. - **Membership:** chain aliases are members; `--self-test-extra` is not the flag. - **Unattributable literals go red:** `node scripts/l.mjs --json --self-test` reports the alias as unattributed, while the attributed spelling beside it does not. - **`the exported population` battery:** it gains the empty and absent roster refusal, and its floor goes from 8 to 9. - **Composite-action fixture:** its `package.json` now carries one self-test alias, because the shared reading refuses a tree that has none. No step names that alias, so both of the battery's controls are unchanged. ## Ablation Both legs ran on the committed state 98d23b3 through `scripts/ablation-replace.mjs`. For each leg: - the anchor went from 1 hit to 0; - the blob changed; - the restore was proven: the blob equals the HEAD blob 89cf1f5 and `git diff HEAD` is empty. | leg | mutation | `--self-test` | production, this tree | production, deleted-step tree | |---|---|---|---|---| | verdict | `const unrun = scripts.filter(...)` becomes `const unrun = []` | exit 1 (5 cases, including the deleted-step pin) | exit 0 | exit 0 | | membership | the roster's membership condition becomes `false` | exit 1 (11 cases) | exit 1, refused: alias reader is broken | exit 1, refused | The first leg is the reason this matters. With the verdict ablated, production on this tree and on the deleted-step tree are both green. `--self-test` is therefore the only instrument for this rule, and `lint.yml` runs it with the flag. ## Gates (head 98d23b3; patch round 2 at `03d397c714`: 57 derived, 57 run, all exit 0, reported in `5948256806`) Derivation: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands`, with no paths. It gives 29 commands, set-equal to the seat's lead. All 29 exit 0: - `check-ci-filter-parity` (run only, not edited) - `check-closing-keyword-parity`, production and `--self-test` - `check-comment-mask-corpus` - `check-declaration-mirrors`, both modes - `check-scripts-symbol-anchors`, both modes - `check-self-test-wired`, both modes - `check-self-test-workflow-commands`, both modes, population 232 - `check-whole-set-label-write`, both modes - `pm/bare-root-worklist --self-test` - `pnpm check:` agent-test-spelling, bash32-floor, cli-command-ids, cross-package-test-inputs, driver-memory-census, entry-guard, gitlink-declared, nul-bytes, parse-guard, pm-dispatch-gates, pnpm-filter-targets, ratchet-remedy-authority, refd-timer-probe, watch-hint-literal `check:ratchet-remedy-authority` still classifies this file as `refused`, with no live offer. The counts are the same as on base: 15 marked, 5 refused. No package is touched, so no build closure, package tests or typecheck are owed. The changeset is skipped because the change is under the repo-root `scripts/`: the root package is private and nothing is published. ## Acceptance notes - **Four passages this change made false are corrected in this PR** (patch round 2, `03d397c714`, comments only; the seat's ruling on the dev's open question, per `5948256806`). They are three `lint.yml` comment blocks (the `Issue-transfer door self-test` step, the stale-`finding` sweep step, and the import-prerequisite module step) and the `scripts/check-system-context-census.mjs` header paragraph. Each now states the declared-alias population. A probe backs each sentence: deleting the stale-finding step, or both census invocations, now reds. No step, `run:` line or code moved: `yaml.parse` of the two `lint.yml` versions is deep-equal, and the census script's comment-masked code is identical. (Seat edit.) - **Scope is the root `package.json`, as the card set it.** An alias in a package's own `package.json` is outside this population. --- _Generated by [Claude Code](https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 11905a4 commit 43e928d

3 files changed

Lines changed: 453 additions & 28 deletions

File tree

‎.github/workflows/lint.yml‎

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -563,12 +563,14 @@ jobs:
563563
# agent typed the command by hand.
564564
#
565565
# ⛔ NOT a hole in `check:self-test-wired`, whose green is correct by its
566-
# own definition: its population is the scripts CI RUNS, and this file is a
567-
# MODULE no workflow can invoke, so it sat in that gate's remainder by
568-
# construction. The blast radius and the population rule point in opposite
569-
# directions here: the file with the largest inheritance surface in the
570-
# farm is the one shape the wiring gate cannot see. Naming it in this step
571-
# is what moves it INTO that population (161 -> 162 scripts CI runs that
566+
# own definition: its population is the scripts CI RUNS plus, since
567+
# #21351, the scripts a root `package.json` alias self-tests, and this
568+
# file is a MODULE no workflow can invoke and no alias names, so it sat in
569+
# that gate's remainder by construction. The blast radius and the
570+
# population rule point in opposite directions here: the file with the
571+
# largest inheritance surface in the farm is the one shape the wiring gate
572+
# cannot see. Naming it in this step is what moves it INTO that population
573+
# (161 -> 162 scripts CI runs that
572574
# ship a `--self-test`), and it is the smaller of the two remedies — the
573575
# other being to widen the gate to a transitive closure, which #14007
574576
# explicitly does not ask for. ⛔ It is also not a licence to sweep the
@@ -1545,11 +1547,12 @@ jobs:
15451547
# just as green, and a wrong transfer is a write against a shared board,
15461548
# not a report.
15471549
#
1548-
# ⛔ `check:self-test-wired` does not hold this step. No other workflow
1549-
# names this script, and that gate's population is the scripts a
1550-
# workflow names, so deleting this step drops the script back out of it
1551-
# with every gate still green — the same hole the stale-`finding` sweep
1552-
# step below records, which only the step itself closes.
1550+
# `check:self-test-wired` holds this step through the declared alias. No
1551+
# other workflow names this script, but since #21351 that gate's
1552+
# population includes every root `package.json` alias whose expansion
1553+
# carries `--self-test`, so deleting this step reds it with
1554+
# `[alias-self-test-not-run] pnpm check:pm-issue-transfer`. The
1555+
# stale-`finding` sweep step below is held the same way.
15531556
- name: Issue-transfer door self-test
15541557
run: pnpm check:pm-issue-transfer
15551558

@@ -1584,9 +1587,12 @@ jobs:
15841587
#
15851588
# Until this step existed the instrument was UNFIRED: the tool shipped a
15861589
# 91-case `--self-test` that nothing in CI ran, which is the second half
1587-
# of the pair `check:self-test-wired` exists for (a script is IN its
1588-
# population only once a workflow names it, so an unwired tool's self-test
1589-
# is not a hole the gate can see — it is a hole only this step closes).
1590+
# of the pair `check:self-test-wired` exists for. A script was then IN
1591+
# that gate's population only once a workflow named it, so the unwired
1592+
# self-test was a hole only this step could close. Since #21351 the gate
1593+
# also reads every root `package.json` alias whose expansion carries
1594+
# `--self-test`, so it holds this step through `check:pm-stale-finding`:
1595+
# deleting the step reds `[alias-self-test-not-run]`.
15901596
#
15911597
# What the self-test instruments is the set of rules a clean tree cannot
15921598
# exercise: the screen's ungraded verdict, which is the ONE thing the

0 commit comments

Comments
 (0)