Repository navigation
Commit 455229e
fix(pm): dispatch-gates derives the CLI command-id, ADR anchor and error-code provenance gates from the diffs that break them (#31254)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XFw5wfsCwD3s72yDS2BVkmT)_
Fixes #30763
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:`dispatch-gates --commands`
新增两种「按改动内容判定」的门禁派生,并给已有的错误码派生补上一道门禁:改到含 CLI 命令字面量的源码或 CLI 命令文件时派生
`check:cli-command-ids`;改到被 ADR 按符号锚定的文件(或移走/删掉任何被锚定的文件)时派生
`check:adr-symbol-anchors`;改到含错误码字面量的文件时,除原有的词表门禁外再派生
`check:error-code-provenance`。
- 为什么改:这三道门禁在 CI 里每个 PR 都跑,但本地派生清单从不列出它们,开发者报「全绿」后 CI 才红,已各自付过一轮 CI(PR
#30734、#30749、#31214)。
- 风险与回滚:只动 `scripts/pm/` 下的派生工具与其自测,不改任何门禁检查什么,也不动
workflow;最坏情况是多派生一道门禁(多跑几秒)或漏派生(即现状)。回滚即还原本 PR。
- 先看:`scripts/pm/dispatch-gates.mjs` 的 `carriesACliCommandLiteral` 与
`breaksAnAdrAnchor`;`scripts/pm/dispatch-gates.data.mjs` 新增的三条
`CHANGE_KIND_ROWS` 门禁行。
- 两分钟验证:`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack packages/cli/src/commands/migrate/apply.ts
packages/services/service-push/src/push-plugin.ts`,预期输出里有 `pnpm
check:cli-command-ids` 与 `pnpm check:adr-symbol-anchors`(main 上两者都没有)。
- 需要你做的:无,席位落地。
## What changes
Three lint steps run on every PR (`lint.yml`, no `paths:` filter) over a
population no path trigger in `dispatch-gates` reached, so `--commands`
never handed them to a card. Each now reaches a card through a
change-kind row (`CHANGE_KIND_ROWS`), the same channel the vocabulary,
status and durability gates already use:
| Gate | Why it was never derived | Now derived when the diff… |
|---|---|---|
| `check:cli-command-ids` | Its literal population is a `src` path
segment in any package (no subtree spelling covers it); its only
declared root is `scripts/**`. Its command-module duty spells the
commands dir package-relative. | …holds a quoted binary-name literal in
a non-test JS/TS file outside the CLI (content), or touches a CLI
command module or the CLI manifest (path, so a deleted or renamed
command counts). |
| `check:adr-symbol-anchors` | Declared population is `docs/adr/**`
only; an anchor also reds from the anchored file's end. | …edits a file
some ADR anchors by `path#Symbol`, or moves/deletes a file any ADR
anchors. The anchored files are read with the gate's own corpus
registration and the shared extractor (`scripts/symbol-anchors.mjs`),
cross-repo anchors left out. |
| `check:error-code-provenance` | Its only declared literals are the
ledger file, so it sat in the artifact-roster block, outside
`--commands`. | …carries an error-code-shaped value: it joins
`check:dispatcher-error-vocabulary` on the existing `error-code-literal`
row (same stamp sites, population-disjoint verdicts). |
**`check:cli-command-ids`: content, not every diff.** The step is
unconditional in CI, but at about 22 s locally it is not cheap (ADR
anchors ~7 s, provenance ~6 s), so a for-every-diff family was rejected
per the order's precision rule. The literal limb is a net around the
gate's reader, not a copy of it: the gate's module loads `typescript` at
import time and `dispatch-gates` runs in checkouts with no install, so
it is not imported. The self-test holds the net to the gate's own
`binNamesOf` and `literalsOn` in a child process.
## Tests
New self-test cases in `scripts/pm/dispatch-gates.self-test.mjs`:
- **CLI kind:** the PR #30734 shape (a pt-BR fragment opening with the
binary word) and the other limbs through an injected reader; negatives:
a comment-opening line, jsdoc, unquoted prose, `osx`, test files,
`__tests__`, non-JS, CLI source outside its commands dir, no declared
CLI. Live: CLI discovered from its manifest, a command module reached,
discrimination (424 of 7002). Gate-reader parity in a child process:
same binary names, and every file the gate's reader finds a literal in
is inside the net (missed: none). Rendering, whole table, runnable
union, STALE.
- **ADR kind:** symbol-anchored edit/delete hit; file-level-only edit
not a hit, its move/delete a hit; unanchored never. Reader against a
scratch corpus: symbol plus continuation, file-level, cross-repo and
fenced sample left out, empty corpus throws. Live: 150 records, the PR
#30749 file reached, discrimination. Rendering, whole table, runnable
union, STALE.
- **Provenance:** rides the `error-code-literal` row; the #31214 shape
(a scenarios-package constant bound to `VALIDATION_FAILED`) derives it
through the whole table; the section now carries both code gates.
- Census guard: all three are live families.
- One existing pin moved: the inherited-population census row 738 → 744
(the import lines above it).
**Ablation** (one fast-tier run, both guards removed through
`scripts/ablation-replace.mjs`, the first held and the second in run
mode, restore proven: blob == HEAD `098f38af9ac9`, `git diff HEAD`
empty):
- CLI net loses its comment-line skip ⇒ red: "a line that opens as a
comment is not a hit", "…nor a jsdoc line".
- ADR predicate loses its on-disk check ⇒ red: "an edit to a file
anchored only at file level is not a hit".
- Also red, in the "more diagnostics" direction: three whole-table
section-count pins on live i18n / metadata-form / gate-script paths,
because the widened net then fires on comment-only mentions in those
files. The three new pins above are the ones that name the guard; every
other case stayed green (6 of 2021 red).
## Acceptance notes
- **Third reading (#31214), measured at head `813399e1`:** `--commands`
on that PR's 17 paths printed 54 commands and not
`check:error-code-provenance`; the human rendering listed it under
"Artifact rosters" (outside the runnable total). The
`error-code-literal` kind already fired on 5 of the paths
(`scenario-operation-grade.ts` bound `VALIDATION_FAILED_CODE: ErrorCode
= 'VALIDATION_FAILED'`). Same defect class, so fixed here. With this
branch's tool on that tree: 56 commands, `+
check:error-code-provenance`, `+ check:cli-command-ids`. Recall of the
predicate against the gate's own `--report` at fe97d85: 162 of 162 site
files; the gate's any-name constant limb adds 0 files the predicate does
not reach.
- **Census of the class (not fixed here; for one closing card).**
Unconditional `lint.yml` steps over a whole-root population that
`--commands` does not derive for a diff outside their home package
(probe: `packages/qa/scenarios/src/score/scenario-run-grade.ts`):
- Declared WIDE (11), rendered in their own block, never in
`--commands`: `check:init-service-contract`, `check:live-db-isolation`,
`check:meta-type-normalized`, `check:optional-error-sink`,
`check:resume-authority-declared`, `check:route-envelope`,
`check:runner-env-posture`, `check:settings-bind-window`,
`check:startup-registry-verdict`, `check:verify-stand-in`,
`check:wildcard-fallthrough`.
- Artifact-roster families whose gate source walks a whole root and that
no change kind reaches (7): `check:stack-collection-maps`,
`check:authz-resolver`, `check:error-code-casing`,
`check:filter-alias-parity`, `check:tenant-chokepoint`,
`check:object-def-param-keys`, `check:published-readme-exports`. Read
from a walk/`ls-files` signature in each gate's source; population width
not measured per family.
- Roster families a change kind already reaches:
`check:engine-double-contract`, `check:i18n-stale-fill`,
`check:error-status-conformance`, and now `check:error-code-provenance`.
- Type-check lanes are conditional (affected-selected), so outside this
census.
- **Not done here:** making `--commands` emit the roster or wide blocks.
That is a choice for the seat, put in the report as an open question.
- Bounded by the order: no `.github/**` edit, and no change to what any
gate checks.
## Verification
Gate union derived by `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` on this diff (30 families), run on
head `2653b6b1` (after merging `origin/main`), reconciled with `--ran`:
"30 derived famil(ies) accounted for — 30 run, 0 NOT-MEASURED (a DERIVED
zero …)".
<details><summary>30 gates, exit codes captured before any
pipe</summary>
- `node scripts/check-closing-keyword-parity.mjs` (and `--self-test`),
`check-comment-mask-corpus.mjs`, `check-declaration-mirrors.mjs` (and
`--self-test`), `check-self-test-wired.mjs` (and `--self-test`),
`check-self-test-workflow-commands.mjs` (and `--self-test`),
`check-whole-set-label-write.mjs` (and `--self-test`),
`ci/plan-test-core-shards.mjs --self-test`: exit 0 each
- `pnpm check:agent-test-spelling`, `check:bash32-floor`,
`check:ci-filter-parity`, `check:cli-command-ids` (19 s),
`check:cross-package-test-inputs`, `check:declared-population-live`,
`check:driver-memory-census`, `check:entry-guard`,
`check:gitlink-declared`, `check:nul-bytes`, `check:parse-guard`,
`check:pnpm-filter-targets`, `check:pnpm-flag-spellings`,
`check:ratchet-remedy-authority`, `check:refd-timer-probe`,
`check:scripts-symbol-anchors`, `check:watch-hint-literal`: exit 0 each
- `pnpm check:pm-dispatch-gates`: exit 0, "✓ dispatch-gates self-test
(fast tier): 2021 cases pass; 7 slow section(s) deferred."
</details>
- Full battery (`node scripts/pm/dispatch-gates.mjs --self-test`, the
slow tier CI runs on `main` only): on head `2653b6b1`, "✓ dispatch-gates
self-test: 2310 cases pass." (fast 2021 cases in 428 s, slow 289 cases
in 1363 s).
- `pnpm exec eslint --no-inline-config` on the three files: exit 0. No
package touched, so no package `lint`/`test`/`typecheck` is owed.
- CI families are read from this PR's check-runs, not re-run here.
`skip-changeset`: `scripts/pm/**` ships in no package.
---
_Generated by [Claude Code](https://claude.ai/code)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent c09ffc1 commit 455229e
3 files changed
Lines changed: 422 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1062 | 1062 | | |
1063 | 1063 | | |
1064 | 1064 | | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
1065 | 1089 | | |
1066 | 1090 | | |
1067 | 1091 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
456 | 456 | | |
457 | 457 | | |
458 | 458 | | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
459 | 465 | | |
460 | 466 | | |
461 | 467 | | |
| |||
10801 | 10807 | | |
10802 | 10808 | | |
10803 | 10809 | | |
| 10810 | + | |
| 10811 | + | |
| 10812 | + | |
| 10813 | + | |
| 10814 | + | |
| 10815 | + | |
| 10816 | + | |
| 10817 | + | |
| 10818 | + | |
| 10819 | + | |
| 10820 | + | |
| 10821 | + | |
| 10822 | + | |
| 10823 | + | |
| 10824 | + | |
| 10825 | + | |
| 10826 | + | |
| 10827 | + | |
| 10828 | + | |
| 10829 | + | |
| 10830 | + | |
| 10831 | + | |
| 10832 | + | |
| 10833 | + | |
| 10834 | + | |
| 10835 | + | |
| 10836 | + | |
| 10837 | + | |
| 10838 | + | |
| 10839 | + | |
| 10840 | + | |
| 10841 | + | |
| 10842 | + | |
| 10843 | + | |
| 10844 | + | |
| 10845 | + | |
| 10846 | + | |
| 10847 | + | |
| 10848 | + | |
| 10849 | + | |
| 10850 | + | |
| 10851 | + | |
| 10852 | + | |
| 10853 | + | |
| 10854 | + | |
| 10855 | + | |
| 10856 | + | |
| 10857 | + | |
| 10858 | + | |
| 10859 | + | |
| 10860 | + | |
| 10861 | + | |
| 10862 | + | |
| 10863 | + | |
| 10864 | + | |
| 10865 | + | |
| 10866 | + | |
| 10867 | + | |
| 10868 | + | |
| 10869 | + | |
| 10870 | + | |
| 10871 | + | |
| 10872 | + | |
| 10873 | + | |
| 10874 | + | |
| 10875 | + | |
| 10876 | + | |
| 10877 | + | |
| 10878 | + | |
| 10879 | + | |
| 10880 | + | |
| 10881 | + | |
| 10882 | + | |
| 10883 | + | |
| 10884 | + | |
| 10885 | + | |
| 10886 | + | |
| 10887 | + | |
| 10888 | + | |
| 10889 | + | |
| 10890 | + | |
| 10891 | + | |
| 10892 | + | |
| 10893 | + | |
| 10894 | + | |
| 10895 | + | |
| 10896 | + | |
| 10897 | + | |
| 10898 | + | |
| 10899 | + | |
| 10900 | + | |
| 10901 | + | |
| 10902 | + | |
| 10903 | + | |
| 10904 | + | |
| 10905 | + | |
| 10906 | + | |
| 10907 | + | |
| 10908 | + | |
| 10909 | + | |
| 10910 | + | |
| 10911 | + | |
| 10912 | + | |
| 10913 | + | |
| 10914 | + | |
| 10915 | + | |
| 10916 | + | |
| 10917 | + | |
| 10918 | + | |
| 10919 | + | |
| 10920 | + | |
| 10921 | + | |
| 10922 | + | |
| 10923 | + | |
| 10924 | + | |
| 10925 | + | |
| 10926 | + | |
| 10927 | + | |
| 10928 | + | |
| 10929 | + | |
| 10930 | + | |
| 10931 | + | |
| 10932 | + | |
| 10933 | + | |
| 10934 | + | |
| 10935 | + | |
| 10936 | + | |
| 10937 | + | |
| 10938 | + | |
| 10939 | + | |
| 10940 | + | |
| 10941 | + | |
| 10942 | + | |
| 10943 | + | |
| 10944 | + | |
| 10945 | + | |
| 10946 | + | |
| 10947 | + | |
| 10948 | + | |
| 10949 | + | |
| 10950 | + | |
| 10951 | + | |
| 10952 | + | |
| 10953 | + | |
| 10954 | + | |
| 10955 | + | |
| 10956 | + | |
| 10957 | + | |
| 10958 | + | |
| 10959 | + | |
| 10960 | + | |
| 10961 | + | |
| 10962 | + | |
| 10963 | + | |
| 10964 | + | |
| 10965 | + | |
| 10966 | + | |
| 10967 | + | |
| 10968 | + | |
| 10969 | + | |
| 10970 | + | |
| 10971 | + | |
| 10972 | + | |
| 10973 | + | |
| 10974 | + | |
| 10975 | + | |
| 10976 | + | |
| 10977 | + | |
| 10978 | + | |
| 10979 | + | |
| 10980 | + | |
| 10981 | + | |
| 10982 | + | |
| 10983 | + | |
| 10984 | + | |
| 10985 | + | |
| 10986 | + | |
| 10987 | + | |
| 10988 | + | |
| 10989 | + | |
| 10990 | + | |
| 10991 | + | |
| 10992 | + | |
| 10993 | + | |
| 10994 | + | |
| 10995 | + | |
| 10996 | + | |
| 10997 | + | |
| 10998 | + | |
| 10999 | + | |
| 11000 | + | |
| 11001 | + | |
| 11002 | + | |
| 11003 | + | |
10804 | 11004 | | |
10805 | 11005 | | |
10806 | 11006 | | |
| |||
11117 | 11317 | | |
11118 | 11318 | | |
11119 | 11319 | | |
| 11320 | + | |
| 11321 | + | |
11120 | 11322 | | |
11121 | 11323 | | |
11122 | 11324 | | |
| |||
0 commit comments