Repository navigation
Commit e0d6317
Run seven lint gates through their root check:* alias instead of a copied command (#26409)
<!-- claude-projects-attribution: {"github_login":"os-steve"} -->
_Requested by **Steve** · [project
thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi95YovdFSHTxz132KjPG4TAa)_
Part of #26086
Part of #26091
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:`lint.yml` 里 7 个门禁步骤原来把根 `package.json` 别名的命令逐字抄了一遍,现在直接跑 `pnpm
check:NAME`。另外 `check-system-context-census` 的自测原来钉的是内联两行,现在改钉别名。
- 为什么改:两份一样的命令迟早会漂移。这 7 处今天一字不差,改成别名后 `package.json` 就是唯一定义。卡上说 16
处,实测只有 9 处逐字相同;另外 2 处所在的 job 有意不装 pnpm,所以不动。其余调用的参数和别名本来就不一样,CI
实跑的是内联那份,逐条写在 Acceptance notes。
- 风险与回滚:行为不变。两个 lane 都已装好 pnpm,而且各自已经在跑 36 和 42 个 `pnpm check:*` 步骤;pnpm
会原样透传退出码(本地测过 exit 3)。回滚就是 revert 这个 PR。
- 先看:`.github/workflows/lint.yml` 的 7 处 hunk,以及
`scripts/check-system-context-census.mjs` 的 WIRING 小节。
- 两分钟验证:本地逐个跑这 7 个 `pnpm check:NAME`,7 个都是 exit 0;再跑 `node
scripts/check-system-context-census.mjs --self-test`。
- 需要你做的:这是 Tier H(改 `.github/workflows/**`),需要
GOVERNED_APPROVERS(os-zhuang 或 hotlong)批准。两张卡这里都只写 Part of:#26086 的其余 17
段主体还在等 Steve 的决策卡;#26091 还剩 4 个别名没有调用方,外加一个 `--self-test`,见下文。
## What changes
Seven `lint.yml` gate steps spelled out, byte for byte, the command
their root `package.json` alias holds. They now run the alias:
| Lane | Step | Was | Now |
|---|---|---|---|
| `lint-repo-tooling` | Docs anchors resolve to real headings | `node
scripts/check-system-context-census.mjs --self-test` then `node
scripts/check-system-context-census.mjs` | `pnpm
check:system-context-census` |
| `lint-repo-tooling` | Published src imports only declared workspace
deps | the two `check-undeclared-dep-imports.mjs` legs | `pnpm
check:undeclared-dep-imports` |
| `lint-repo-tooling` | Keyed text-family columns declare their bound |
the two `check-keyed-text-bounds.mjs` legs | `pnpm
check:keyed-text-bounds` |
| `lint-repo-tooling` | Platform-object tenancy census matches the tree
| the two `check-platform-object-tenancy-census.mjs` legs | `pnpm
check:platform-object-tenancy-census` |
| `lint-ci-engine` | Declared registry log level | `node … --self-test
&& node …` | `pnpm check:registry-log-declared` |
| `lint-ci-engine` | Declared REST fault-log level | `node … --self-test
&& node …` | `pnpm check:rest-log-declared` |
| `lint-ci-engine` | Declared REST fault-log level — observers | `node …
--self-test && node …` | `pnpm check:rest-log-spy-declared` |
- **Same command, same order, same exit code.** Each alias value equals
the removed lines joined with `&&`. The census below compares them as
parsed strings, not by eye. A two-line `run: |` block under the default
`bash -e` already stopped at the first failing leg, so `&&` changes
nothing. `pnpm` passes the child's exit code through (checked locally
with a script that exits 3). Each step keeps its `id:` and
`continue-on-error: true`, so the lane verdict reads it as before.
- **pnpm is already there.** Both lanes run `Setup pnpm` and `Install
dependencies` before their gates, and they already run 42
(`lint-repo-tooling`) and 36 (`lint-ci-engine`) `pnpm check:*` steps.
- **One pin moves with it.** `check-system-context-census.mjs
--self-test` asserted that `lint.yml` contains the two literal `node
scripts/check-system-context-census.mjs` lines. It now asserts that
`lint.yml` runs `pnpm check:system-context-census`, and that the root
alias is exactly `node scripts/check-system-context-census.mjs
--self-test && node scripts/check-system-context-census.mjs`. The
guarantee is the same: both legs are scheduled, and the step's battery
has one more check. Negative control: with the `lint.yml` line removed,
the self-test fails on `WIRING: lint.yml invokes this gate through its
root alias`. Its docblock's two sentences about the pin now say "through
the alias".
- **Two comment literals were made false by these steps and are
corrected.** They are the "Invoked as `node` rather than through a `pnpm
check:*` alias" pointers above the census and undeclared-dep-imports
steps. No other workflow prose changes. The `GATE INVOCATION IDIOM` note
at the top of `lint.yml` still holds: it says the direct form is a
choice, not a fence, and most steps still take it.
## Tests
- All seven aliases, run locally as CI will run them (`pnpm -s
check:NAME`): seven exit 0.
- `node scripts/check-system-context-census.mjs --self-test`: all cases
pass. The negative control above turns it red with one FAIL line.
- The step census was re-run on this branch. Steps whose inlined `node
scripts/…` lines exactly equal a root `check:*` alias: 9 before, 2
after. The 2 left are the no-pnpm jobs below.
- `grep -c 'pnpm run check:\|pnpm check:' .github/workflows/*.yml`,
summed: 216 on `main`, 223 here (+7).
Derived gate families: `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` gives 56 commands. **All 56 exit 0**,
and `--ran ran.list` gives `56 derived famil(ies) accounted for — 56
run, 0 NOT-MEASURED`. CI runs the rest.
<details><summary>Gate results (exit code, command, seconds)</summary>
```
0 node scripts/check-aggregator-roster.mjs 0s
0 node scripts/check-aggregator-roster.mjs --self-test 2s
0 node scripts/check-ci-filter-parity.mjs 0s
0 node scripts/check-closing-keyword-parity.mjs 11s
0 node scripts/check-closing-keyword-parity.mjs --self-test 5s
0 node scripts/check-comment-mask-corpus.mjs 187s
0 node scripts/check-declaration-mirrors.mjs 1s
0 node scripts/check-declaration-mirrors.mjs --self-test 0s
0 node scripts/check-merged-branch-reaper-outcome.mjs 0s
0 node scripts/check-merged-branch-reaper-outcome.mjs --self-test 0s
0 node scripts/check-scripts-symbol-anchors.mjs 3s
0 node scripts/check-scripts-symbol-anchors.mjs --self-test 4s
0 node scripts/check-self-test-wired.mjs 2s
0 node scripts/check-self-test-wired.mjs --self-test 5s
0 node scripts/check-self-test-workflow-commands.mjs 118s
0 node scripts/check-self-test-workflow-commands.mjs --self-test 4s
0 node scripts/check-step-collectors.mjs 0s
0 node scripts/check-step-collectors.mjs --self-test 6s
0 node scripts/check-whole-set-label-write.mjs 2s
0 node scripts/check-whole-set-label-write.mjs --self-test 0s
0 node scripts/ci/scheduled-full-run.mjs --self-test 0s
0 node scripts/docs-audit/check-drift-comment.mjs 1s
0 node scripts/pm/bare-root-worklist.mjs --self-test 30s
0 node scripts/pm/ci-failure.mjs --self-test 0s
0 pnpm check:agent-test-spelling 3s
0 pnpm check:bash32-floor 2s
0 pnpm check:cli-command-ids 19s
0 pnpm check:cross-package-test-inputs 33s
0 pnpm check:declared-population-live 36s
0 pnpm check:driver-memory-census 5s
0 pnpm check:entry-guard 38s
0 pnpm check:gitlink-declared 1s
0 pnpm check:node-version 1s
0 pnpm check:nul-bytes 5s
0 pnpm check:parse-guard 3s
0 pnpm check:pm-dispatch-gates 393s
0 pnpm check:pm-expected-skips 6s
0 pnpm check:pm-governed-merges 9s
0 pnpm check:pm-post-stamped 1s
0 pnpm check:pm-record-recognisers 4s
0 pnpm check:pnpm-acquisition 1s
0 pnpm check:pnpm-filter-targets 3s
0 pnpm check:pnpm-flag-spellings 5s
0 pnpm check:ratchet-remedy-authority 4s
0 pnpm check:refd-timer-probe 22s
0 pnpm check:required-contexts 3s
0 pnpm check:select-gate-families 5s
0 pnpm check:shard-attestation 2s
0 pnpm check:stall-guard-budget 2s
0 pnpm check:stall-guard-headroom 4s
0 pnpm check:system-context-census 6s
0 pnpm check:type-check-coverage 6s
0 pnpm check:type-check-debt 388s
0 pnpm check:watch-hint-literal 7s
0 pnpm check:workflow-status-functions 1s
0 pnpm check:workflow-step-name-quoting 1s
```
</details>
## Acceptance notes
**#26086 counted 16 inlined commands. 9 steps match an alias exactly.**
The census reads every `run:` step and finds its non-comment lines that
invoke a `scripts/` file that some root `check:*` alias also invokes. It
then compares those lines, joined with `&&`, against the alias value. It
finds 9 exact matches and 46 partial ones. The partial ones are mostly
different invocations of the same script, not copies of the alias, so CI
is enforcing the inline form. This is the "which one CI actually
enforced" answer the card asks for:
| Where | Alias | What CI runs (enforced) vs. the alias | Status |
|---|---|---|---|
| `check-links.yml` · Check ADR cross-links | `check:adr-links` |
identical; the job deliberately has no setup-node, corepack or install
(its own comment explains why), so there is no pnpm to call | stays
`node` |
| `board-snapshot.yml` · The tool's own cases |
`check:pm-board-snapshot` | identical; the job deliberately runs no
`pnpm install` and sets up no pnpm (its own comment) | stays `node` |
| `pr-automation.yml` changeset-check (3 steps) |
`check:empty-changeset`, `check:adr-0087-registration`,
`check:changeset-gate-self-tests` | CI runs each gate with `--base
"$MERGE_BASE"`; the aliases run it against the default base | CI's form
is the enforced one; stays |
| `lint.yml` symbol-anchor collector + 3 scan steps |
`check:adr-symbol-anchors`, `check:scripts-symbol-anchors`,
`check:spec-docblock-symbol-anchors` | CI runs every leg, but split: the
self-tests through one `run_self_test` collector, the scans as separate
steps | same legs, different grouping; stays |
| `lint.yml` · dev-prereqs, skill-frame freshness | `check:dev-prereqs`,
`check:skill-frame-freshness` | CI runs the self-test half only ("never
the scan", per the step names); the aliases also run the scan | CI's
form is the enforced one; stays |
| `half-state-patrol.yml` · Sweep the closed cards |
`check:pm-closed-card-sweep` | CI runs the self-test with its output
sent to a log, then the sweep with mode and provenance arguments | stays
|
| `ci.yml` (stall guard, shard attestation) | `check:stall-guard`,
`check:shard-attestation` | CI runs the tools in `--log` / `--emit` /
`--verify` modes; the aliases are their self-tests | different commands;
stays |
| `cut-rc.yml` (3 gates, release bodies) | the changeset gates,
`check:release-body` | `--base "$SNAPSHOT_SHA"` forms | file is deleted
by #26196; not touched |
| other single partial rows | `check:closing-target-claim`,
`check:partof-closing-keyword`, `check:docs-audit-scope`,
`check:pm-fleet-write-*`, `check:issue-citations` | CI runs the gate;
the alias is its self-test (or vice versa), so neither is a copy of the
other | stays |
So the drift the card describes, two copies of one command, existed in 9
places. 7 are removed here. The other 2 are in jobs built to run without
pnpm.
**#26091 Wanted 2 is partly done here.** Root `check:*` aliases with no
caller in any workflow, hook, `scripts/` file or other `package.json`
script: 11 on `main`, 4 after this PR. The 4 are
`check:adr-symbol-anchors`, `check:scripts-symbol-anchors`,
`check:spec-docblock-symbol-anchors` and `check:pm-closed-card-sweep`,
and the row above says why each step is split. Calling the alias there
would rerun the self-tests that the collector already runs. Deleting the
alias would remove the local one-command form. Its claim rules out both
("no gate removed or added"), so they are reported, not changed. The
card's other leftover, a `--self-test` for
`scripts/check-changeset-fixed.mjs`, is not in this claim. Both are why
this PR is `Part of #26091`.
## Verification
```sh
for a in system-context-census undeclared-dep-imports keyed-text-bounds platform-object-tenancy-census registry-log-declared rest-log-declared rest-log-spy-declared; do pnpm -s check:$a > /dev/null; echo "$? check:$a"; done
node scripts/check-system-context-census.mjs --self-test
```
Tier H (`.github/workflows/**`): draft until a GOVERNED_APPROVERS
approval (os-zhuang, hotlong).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01ADHkmQq9EYQdTQwmRutQTS)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01ADHkmQq9EYQdTQwmRutQTS
Co-authored-by: Claude <noreply@anthropic.com>1 parent 96f1258 commit e0d6317
2 files changed
Lines changed: 27 additions & 23 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
631 | 631 | | |
632 | 632 | | |
633 | 633 | | |
634 | | - | |
635 | | - | |
| 634 | + | |
| 635 | + | |
636 | 636 | | |
637 | 637 | | |
638 | 638 | | |
639 | 639 | | |
640 | 640 | | |
641 | | - | |
642 | | - | |
| 641 | + | |
643 | 642 | | |
644 | 643 | | |
645 | 644 | | |
| |||
908 | 907 | | |
909 | 908 | | |
910 | 909 | | |
911 | | - | |
912 | | - | |
| 910 | + | |
| 911 | + | |
913 | 912 | | |
914 | 913 | | |
915 | 914 | | |
916 | 915 | | |
917 | | - | |
918 | | - | |
919 | | - | |
| 916 | + | |
920 | 917 | | |
921 | 918 | | |
922 | 919 | | |
923 | 920 | | |
924 | 921 | | |
925 | 922 | | |
926 | | - | |
927 | | - | |
928 | | - | |
| 923 | + | |
929 | 924 | | |
930 | 925 | | |
931 | 926 | | |
| |||
1968 | 1963 | | |
1969 | 1964 | | |
1970 | 1965 | | |
1971 | | - | |
1972 | | - | |
1973 | | - | |
| 1966 | + | |
1974 | 1967 | | |
1975 | 1968 | | |
1976 | 1969 | | |
| |||
3593 | 3586 | | |
3594 | 3587 | | |
3595 | 3588 | | |
3596 | | - | |
| 3589 | + | |
3597 | 3590 | | |
3598 | 3591 | | |
3599 | 3592 | | |
| |||
3608 | 3601 | | |
3609 | 3602 | | |
3610 | 3603 | | |
3611 | | - | |
| 3604 | + | |
3612 | 3605 | | |
3613 | 3606 | | |
3614 | 3607 | | |
| |||
3623 | 3616 | | |
3624 | 3617 | | |
3625 | 3618 | | |
3626 | | - | |
| 3619 | + | |
3627 | 3620 | | |
3628 | 3621 | | |
3629 | 3622 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
207 | 207 | | |
208 | 208 | | |
209 | 209 | | |
210 | | - | |
| 210 | + | |
211 | 211 | | |
212 | 212 | | |
213 | 213 | | |
214 | 214 | | |
215 | 215 | | |
216 | | - | |
| 216 | + | |
217 | 217 | | |
218 | 218 | | |
219 | 219 | | |
| |||
2305 | 2305 | | |
2306 | 2306 | | |
2307 | 2307 | | |
| 2308 | + | |
2308 | 2309 | | |
2309 | | - | |
2310 | | - | |
| 2310 | + | |
| 2311 | + | |
| 2312 | + | |
| 2313 | + | |
| 2314 | + | |
| 2315 | + | |
| 2316 | + | |
| 2317 | + | |
| 2318 | + | |
| 2319 | + | |
| 2320 | + | |
| 2321 | + | |
| 2322 | + | |
2311 | 2323 | | |
2312 | | - | |
2313 | 2324 | | |
2314 | 2325 | | |
2315 | 2326 | | |
| |||
0 commit comments