Repository navigation
Commit 628e55d
pm: retire the needs:contract-review label from the tree (ruling B step ③) (#19737)
Part of #19061
## 维护者速读(草稿)
**改了什么**:按裁决记录 5770886272(B 字母,第 ③ 步)把 `needs:contract-review`
标签从代码树里退役。`ensure-pm-labels.sh` 不再创建它;队列守卫
`check-governed-queue-guard.mjs` 的标签腿(退出码 6/7、标签读取、载体判定与渲染、#17040
电池)整段删除;`check-half-states.mjs`
里围绕该标签巡查的五行(H31/H35/H51/H53/H61)连同扫描点、汇总句、计数键、分带登记与自测一起删除,仓库级
issue-event 窗口读取随之消失;`check-changeset-no-major.mjs` 只读 PR 正文的
`Clause-②:` 行,标签载体轴与对 `check-half-states.mjs` 的 import
删除;`.claude/**`、`AGENTS.md`、两个 workflow 注释里叫 agent
去挂/读/等这个标签、`--pair`、双载体或降档保险丝的句子改成只认 `## Contract review` 记录。每个受管 PR
一条记录的契约原样保留。
**为什么改**:维护者原话「不需要 AI 不能自审契约改动 这种」与「我们系统开发了太多无用的门禁,反而在浪费时间」;裁决 B 把三层(标签
+ `--pair` + 记录)收成一层,只留记录给队列守卫读。第 ① 步(抽出 `readClause2Line`)和第 ②
步(规则文本)已落地;这是最后一步。
**风险与代价(含回滚)**:队列守卫少一条腿,`groupExitCode` 变成两腿(governed → size),退出码 6/7
从登记表移除;半态巡查少五个家族(自测 5170 → 4897 例,`gate` 分带保留但暂无成员);changeset
门禁不再把标签当声明载体,以后没写 `Clause-②:` 行的 PR 读作未声明。回滚 = revert 本 PR
的四个提交(每类一个提交,可单独回退)。⛔ GitHub 上的标签对象本 PR 不删,由席位在合并后、确认没有开着的卡或 PR
还挂着它时移除。一处残留:`check-clause2-carriers.mjs` 把该标签常量改为文件内局部常量——它的 `--pair`
扫描已被裁决退役、无人运行,但队列守卫仍懒加载它的记录识别器与
`--template`,所以文件还不能删;把识别器抽成小模块后整文件连同这个常量一起删,是下一步(见下方 Remainder)。
**席位意见**:**建议批准并合并。** 这是裁决
5770886272(B)的最后一步,做的是「减」:标签的创建者、读者、巡查行、changeset 门禁的标签载体轴和九处叫 agent
去挂/读/等标签的句子全部退休,净 −2650 行;裁决要保留的东西一样没少 —— 队列守卫仍先看授权批准、再看 `## Contract
review` 记录(席位在头上逐段核过守卫的两腿与半态巡查保留的记录读取器),`AGENTS.md` :275–:281 把 Tier S
写成只认记录。四个自测(279 / 4897 / 339 / 1140
例)与十二个门禁族在席位工作树上重跑全绿。一处残留是量出来的而非选的:`check-clause2-carriers.mjs`
还不能删,因为队列守卫懒加载它的六个记录识别器与 `--template`;dev
给它留了本文件内的退休常量并禁止新引用。席位把「抽出识别器、整文件删除」定为 #19061 的第 ④ 步(合并后由 `Release:`
记在卡上,不另立卡),所以本 PR 首行是 `Part of`。合并后席位删除 GitHub 上的标签对象、关闭因它而起的
objectui#9867,并放行压在这些文件后面的 #19146 / #19129 ② / #19244 ② ③。复核记录:PR 评论
5779366929(PASS,在席按服务档渲染);ACCEPT 在卡 #19061。CI 读数:33 latest-per-name
check runs — 24 success, 9 skipped, 0 in progress, 0 other (the seat's
read at 00:13 UTC of this date; the lint-and-repo-gates job success)。
**你要做的**:本 PR 是 Tier H(`AGENTS.md` 在登记表上),草稿状态由您手动合并;合并后席位移除 GitHub
标签对象,并为「抽出记录识别器、删除 `check-clause2-carriers.mjs`」立单。
## Summary
Ruling record 5770886272 on #19061 (letter B), step ③: the
`needs:contract-review` label leaves the tree. Every mechanism that
created, read, hung, cleared or expected it is retired; the one `##
Contract review` record per governed PR — the thing the queue guard
reads to release `.claude/**` in the merge group — stays exactly as it
was. `Part of` rather than `Fixes`: one measured remainder is named
below.
## Per-path disposition (18 label sites on the base, plus the prose
riders)
| path | class | what changed |
|---|---|---|
| `scripts/pm/ensure-pm-labels.sh` | CODE | the `needs:contract-review`
row (comment block + `gh label create`) removed; the pointer in the
`repo:*` block reworded. The GitHub label object is NOT deleted here. |
| `scripts/pm/check-governed-queue-guard.mjs` | CODE | the carrier leg
retired: `EXIT_REFUSED_CARRIER` (6) and
`EXIT_REFUSED_CARRIER_UNREADABLE` (7), `CONTRACT_REVIEW_LABEL`,
`CARRIER_LEG_NAME`, `carrierVerdict`, `runCarrierGuard`,
`renderCarrierVerdict`, `makeLabelReader`, the main-dispatch call, the
exit table rows, the header's SECOND-leg section; `groupExitCode` is
two-legged (governed, size); `carrierPullsInGroup` (still read by the
size leg) renamed `queuedPullsInGroup`; the module-eval-cycle
explanation moved onto the surviving `REVIEW_OF_RECORD_LOCATION` mirror;
the `#17040` battery (39 cases) removed, floor 24 → 23, its enumeration
cases and the two zero-cost-clear scoping pins re-homed in the `#19036`
size battery; the Tier S prescriptions stop naming `--pair N`. |
| `scripts/pm/check-half-states.mjs` | CODE | H31 (carrier split), H35
(gate-label removal events, with `GATE_SEMANTIC_LABELS`,
`isGateSemanticLabel`, the event-window constants and
`listRecentIssueEvents`), H51 (verdict without label stroke), H53
(carrier without increment) and H61 (landed carrier) removed: rows,
sweep sites, summary clauses and count keys, band entries and self-test
sections; `CONTRACT_REVIEW_LABEL` removed. KEPT: `bindingClosesCard`,
the record readers (`CONTRACT_REVIEW_HEADING_MARKER`, `H51_SHA_MIN_HEX`,
`H51_SHA_SPAN`, `contractReviewHeadMatch`, `latestContractReviewOnHead`)
with their pins re-homed under a "record readers" section. The `#13947`
ledger fixtures move from H31 to a `stall` family (H12); the `gate` band
stays declared, rank 0, with no live member; the H52 reservation pin now
asserts the spent number is never re-used. |
| `scripts/check-changeset-no-major.mjs` | CODE | the label carrier axis
retired: `declarationFromPullRequest` reads the `Clause-②:` body line
only (no `labels` read, no `carrier` field), `judgeLevel`/`renderLevel`
drop `carrier`/`carrierUnread` and every sentence that named the label;
the `check-half-states.mjs` import goes (the gate's first-party closure
is now `clause2-line.mjs` alone); the `#17229` battery (25 cases)
removed, floor 20 → 19; the payload-snapshot docblock rewritten around
the body. |
| `scripts/pm/check-clause2-carriers.mjs` | CODE (remainder) | NOT
deleted — measured: `check-governed-queue-guard.mjs` lazily imports six
record recognisers from it (`locateReviewOfRecord`,
`deliveredCardNumber`, `servedTierStands`, `isModelIdentifierToken`,
`REVIEW_OF_RECORD_THREADS`, `REVIEW_OF_RECORD_LOCATION`) and
`contract-review.md` points at its `--template`, so the ruling's
deletion precondition ("nothing but the extracted module is imported")
does not hold on this base. Its two imports of the retired symbols
become a LOCAL `CONTRACT_REVIEW_LABEL` / `isGateSemanticLabel`,
docblocked as retired and import-forbidden; nothing else in it moves.
This is the one CODE site still spelling the label. |
| `scripts/pm/check-widening-tells.mjs` | PROSE in code | no label leg;
the design-note sentence reworded ("a review-gate label"); the dated
2026-09-16 census line at :673 is HISTORY and stays. |
| `scripts/pm/check-label-desc-cap.mjs` | PROSE in code | the
97-char/101-byte specimen sentence stops naming the label; the self-test
keeps the description string as a fixture (renamed case). Floor
`MIN_DESCRIPTIONS` 12 vs 38 found — untouched. |
| `scripts/pm/check-skill-line-ratchet.mjs` | HISTORY + rows | the two
raise-provenance comments naming the label stay (they explain past
ceilings); rows lowered: `os-dev.md` 403 → 402, `state-machine.md` 42 →
41 (`AGENTS.md` stays 1116 — the paragraph re-wrapped to the same
count). |
| `scripts/pm/dispatch-gates.mjs` | PROSE in code | the
`CONTRACT_REVIEW_TIER` docblock no longer names the re-review sub-round,
the fuse or the label bullets; the rulebook pointer goes to
`references/contract-review.md`. |
| `scripts/pm/clause2-line.mjs` | PROSE in code | the "STEP ① … nothing
else has landed yet" paragraph rewritten to the landed state; the
provenance sentence at :11 and the measured incident at :307 stay. |
| `scripts/pm/check-governed-merges.mjs` | CODE strings | Tier S landing
prose and the `--test` rendering stop prescribing `--pair N`; two
self-test pins flipped to assert its absence; the mirror docblock points
at `REVIEW_OF_RECORD_LOCATION`. |
| `scripts/pm/post-stamped.mjs` | CODE string | the near-miss row stops
prescribing `--pair`. |
| `.github/workflows/lint.yml` | PROSE | the desc-cap specimen comment
and the clause-② self-test step comment (the step itself stays: it keeps
the recognisers loadable). |
| `.github/workflows/pr-automation.yml` | PROSE | the WHICH LEVEL prose
names the one carrier left. |
| `.claude/agents/os-dev.md` :303 | PROSE | line deleted. |
| `.claude/skills/pm-dispatch/SKILL.md` :769 | PROSE | 三职 = 契约复核记录事后审计 …
|
| `references/lanes/director.md` :27/:31/:33/:35 | PROSE | duty one
audits the records; 落地前检③ → ②; handoff by `pm:*` label, record stays on
PR or card. |
| `references/lanes/ui.md` :38 | PROSE | record-only contract, pointer
to `../contract-review.md`. |
| `references/state-machine.md` :8/:10 | PROSE | H29/H30 authority; the
card-side-first line deleted. |
| `references/dispatch-runbook.md` :161 | PROSE | 独立性件 → 达档复核记录. |
| `references/platform-readings.md` :26 | PROSE | the label row
generalised to the still-true `mergeable_state: blocked` reading. |
| `references/contract-review.md` :13/:19 | PROSE (unchanged) | the
`--template` pointers stay valid because the script stays; they follow
the file at the extraction step. |
| `AGENTS.md` :278 | PROSE | Prime Directive #14 Tier S: the `--pair N`
clause removed, paragraph re-wrapped at the 120-byte budget. |
| `.changeset/console-87af769e9a3e.md`, `docs/adr/0131-…`,
`docs/audits/**` | HISTORY | untouched. |
## What stays, on purpose
- One `## Contract review` record per governed PR, `Served-tier:` line,
the queue guard's Tier S leg and its lazy import of the recognisers —
ruling B, not A.
- `CONTRACT_REVIEW_TIER` in `dispatch-gates.mjs` (path-mandate role) and
`readClause2Line` in `clause2-line.mjs` (step ①).
- The GitHub label object: the seat removes it after MERGED once no open
card or PR carries it.
## Remainder (why `Part of`)
`check-clause2-carriers.mjs` still spells the label in a local constant
because its deletion — the ruling's own end state for the file — waits
on extracting the six record recognisers and `--template` into a module
the queue guard can lazily import (a sibling of step ①, roughly the
2,700-3,000 to 4,300 line band of that file plus its record batteries).
Retiring the C1/C3/gate-history rows inside a file that is slated for
deletion would rewire the retired `--pair` sweep for nothing. The seat
files that extraction as its own card; with it the last label site goes
and `objectui#9867` falls moot.
## Tests
All on the merged head `8671754c9` (base `106d4c8dd`, `origin/main`
`342808cf5` merged clean, no file overlap), exits captured before any
pipe:
- `node scripts/pm/check-governed-queue-guard.mjs --self-test` — exit 0
— `✓ check-governed-queue-guard self-test: 279 cases pass`
- `node scripts/pm/check-half-states.mjs --self-test` — exit 0 — `✓
check-half-states self-test: 4897 cases pass` (5170 before; batteries
H66 182/172 and H67 152/142 each lost one cross-family pin)
- `node scripts/check-changeset-no-major.mjs --self-test` — exit 0 —
`339 assertions`; `--base origin/main` exit 0 (level axis NOT APPLICABLE
with no `pull_request`)
- `node scripts/pm/check-clause2-carriers.mjs --self-test` — exit 0 —
`1140 cases pass`
- `pnpm check:pm-governed-merges` exit 0 · `pnpm check:pm-post-stamped`
596 cases · `pnpm check:pm-dispatch-gates` 1905 cases (748 s) · `pnpm
check:pm-widening-tells` 525 cases · `pnpm check:pm-label-desc-cap`
self-test + gate (38 descriptions, all ≤100) · `pnpm
check:pm-skill-ratchet` exit 0 (`total ceilings down 9 lines`) · `pnpm
check:pm-skill-id-lint` 30 files clean · `pnpm check:pm-governed-prose`
6/6 surfaces · `pnpm check:nul-bytes` 9231 files clean · `pnpm
check:commit-card-trailers` 5 commits clean
- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` derives 84 commands (identical before and after the merge);
`--ran` reconciled — run locally: 80 of them; declared to CI: `pnpm
--filter @objectstack/lint run check:doc-formula-expressions` (needs the
package build), `pnpm check:partof-closing-keyword` (reads the PR body),
`pnpm check:pm-expected-skips` (reads the board); `pnpm
check:type-check-debt` exit 3 = PREREQUISITE NOT MET (needs the packages
build closure; this diff touches no package) — NOT MEASURED.
- Narrowed lint: `pnpm exec eslint --no-inline-config --format json`
over the 11 touched `.mjs` files — exit 0, 11 files, 0 errors, 0
warnings. Population read from `eslint.config.mjs` (the
`**/*.{ts,…,mjs,cjs}` block); the config never enables type-aware
linting (`eslint.config.mjs` :326-:328, "no `parserOptions.project`, no
typed `@typescript-eslint` rules for ANY file"), so this diff moves no
untouched file's verdict; the whole-repo `pnpm lint` is CI's run.
- `node scripts/pm/check-harness-current.mjs`: STALE before and after —
it compares the shared checkout's HEAD with `origin/main`, which this
branch does not move.
- `node scripts/pm/check-governed-merges.mjs --pr N`: run after the PR
exists (expected GOVERNED, Tier H via `AGENTS.md`); reported on the
card.
## Deviations
- `check-clause2-carriers.mjs` keeps a local retired-label constant (see
Remainder) — the one departure from "the label retired from the tree",
measured and named rather than forced.
- `pnpm check:type-check-debt` not measured locally (build
prerequisite); `pnpm install --frozen-lockfile && pnpm build` after the
merge was not run because this diff touches no package and every gate
run here reads scripts, workflows or `.claude/**`.
## Acceptance notes
- class: b · `scripts/pm/check-widening-tells.mjs` still describes
`--pair`'s C5 row as its live consumer (:85, :241, :1338) — that
consumer is retired by ruling B; the gate's own self-test is what CI
runs. Not touched here (not the label); carrier: the extraction card
above. Dedupe words: widening-tells --pair C5 consumer retired.
- `scripts/pm/check-expected-skips.mjs` :118 still names
`check-clause2-carriers.mjs` as the read ladder it mirrors — true while
the file exists; follows the extraction.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Wnstp2kTth7sGXfr8fXypc)_
---
_Generated by [Claude Code](https://claude.ai/code)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 3f9e2ea commit 628e55d
22 files changed
Lines changed: 405 additions & 3055 deletions
File tree
- .claude
- agents
- skills/pm-dispatch
- references
- lanes
- .github/workflows
- scripts
- pm
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
301 | 301 | | |
302 | 302 | | |
303 | 303 | | |
304 | | - | |
305 | 304 | | |
306 | 305 | | |
307 | 306 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
766 | 766 | | |
767 | 767 | | |
768 | 768 | | |
769 | | - | |
| 769 | + | |
770 | 770 | | |
771 | 771 | | |
772 | 772 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
161 | | - | |
| 161 | + | |
162 | 162 | | |
163 | 163 | | |
164 | 164 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | | - | |
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
916 | 916 | | |
917 | 917 | | |
918 | 918 | | |
919 | | - | |
920 | | - | |
921 | | - | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
922 | 922 | | |
923 | 923 | | |
924 | 924 | | |
| |||
1254 | 1254 | | |
1255 | 1255 | | |
1256 | 1256 | | |
1257 | | - | |
1258 | | - | |
1259 | | - | |
1260 | | - | |
1261 | | - | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
1262 | 1262 | | |
1263 | 1263 | | |
1264 | | - | |
1265 | | - | |
1266 | | - | |
| 1264 | + | |
| 1265 | + | |
1267 | 1266 | | |
1268 | 1267 | | |
1269 | 1268 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
784 | 784 | | |
785 | 785 | | |
786 | 786 | | |
787 | | - | |
788 | | - | |
| 787 | + | |
| 788 | + | |
789 | 789 | | |
790 | 790 | | |
791 | 791 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
278 | | - | |
279 | | - | |
280 | | - | |
281 | | - | |
282 | | - | |
283 | | - | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
284 | 284 | | |
285 | 285 | | |
286 | 286 | | |
| |||
0 commit comments