Ruling (maintainer, 2026-09-18, live chat, verbatim and untranslated):
不需要 AI 不能自审契约改动 这种
and, on the disposition proposed for the checker:
同意你的建议
So this is not "fix the checker" — the rule itself is withdrawn: there is no longer a requirement that a contract-affecting change be reviewed by a seat other than the one that wrote it. What goes with it is the machinery built to enforce that rule.
What made the case — measured on main, not recalled
| measurement |
value |
Is scripts/pm/check-clause2-carriers.mjs in any CI workflow? |
No — zero hits across .github/workflows/ |
| Its size |
9,132 lines / 619 KB |
| Code that actually imports it |
2 files, one symbol: readClause2Line, imported by scripts/check-changeset-no-major.mjs and scripts/check-adr-0087-registration.mjs |
| Are those two in CI? |
Yes — lint.yml, pr-automation.yml, cut-rc.yml, release.yml |
So CI depends on roughly forty lines of that file and runs none of the rest.
Two failure modes were also measured live on PR #18420, and both are about the instrument rather than the diff:
- It cannot judge a PR whose branch was not named by PM dispatch.
CLAIM_BRANCH_SHAPE is /claude\/issue-\d+-[A-Za-z0-9][A-Za-z0-9._-]*/g; a session-assigned branch (claude/zealous-mendel-o0o6aq) parses to zero branches, the claim cannot be resolved, and --pair exits 2 (UNJUDGED) — which by its own rules is ⛔ never "clean". Systematic, not a one-off.
- Its "review of record on the head" limb self-invalidates on every base merge. Sync the branch with
main and the recorded verdict names a superseded head.
Scope — what comes out, what must NOT
Out:
- The rule text in
.claude/skills/pm-dispatch/SKILL.md (clause ② in 〈入队与落地〉 and the landing pre-check item ②; hits at lines ~76, 152, 338, 474-477, 512-522, 635-646, 672, 766 at time of filing).
.claude/skills/pm-dispatch/references/contract-review.md in full (60 lines), plus the mentions in references/platform-readings.md.
- The
needs:contract-review gate label and its hang/clear discipline.
- In
scripts/pm/check-clause2-carriers.mjs: the C4 (independence pair), C6 (review of record) and C7 (Served-tier:) rows, and the --pair landing pre-check role.
Must survive — measure before deleting anything:
readClause2Line and the Clause-②: yes | no declaration line itself: the two CI gates above read it for semver level and ADR-0087 disposition, which is a different job from who reviewed the diff. Extract it to a small module (~40 lines) so those gates stop hanging off a 9k-line file.
CONTRACT_REVIEW_TIER in scripts/pm/dispatch-gates.mjs: it also mandates a model tier for path-based clause ① work (the pm-dispatch skill surfaces, the published skills/** catalog). Only its review role retires.
- ⚠️
needs:contract-review is named in packages/spec/src/api/error-code-ledger.zod.ts and its generated reference page — a published surface. Measure what that row does before touching it; removing a published ledger row is its own decision, not a rider on this one.
- Whatever
check-half-states.mjs, check-governed-queue-guard.mjs, check-widening-tells.mjs, check-label-desc-cap.mjs, check-skill-line-ratchet.mjs and ensure-pm-labels.sh do with the label — each needs its own reading; several only name it in prose.
If the hazard is still wanted later
The thing the rule guarded against is an AI seat approving its own contract change and queueing it. If that is ever wanted again, the cheap form is GitHub's own required reviews / CODEOWNERS — platform-enforced, zero lines of comment archaeology — rather than a checker that is not in CI and reads two lines out of a comment body. Recorded here so a later reader knows the alternative was considered and not merely forgotten.
Sequencing
Dedup terms
clause-② · needs:contract-review · check-clause2-carriers · contract-review.md · independence pair SELF-REVIEW
Ruling (maintainer, 2026-09-18, live chat, verbatim and untranslated):
and, on the disposition proposed for the checker:
So this is not "fix the checker" — the rule itself is withdrawn: there is no longer a requirement that a contract-affecting change be reviewed by a seat other than the one that wrote it. What goes with it is the machinery built to enforce that rule.
What made the case — measured on
main, not recalledscripts/pm/check-clause2-carriers.mjsin any CI workflow?.github/workflows/readClause2Line, imported byscripts/check-changeset-no-major.mjsandscripts/check-adr-0087-registration.mjslint.yml,pr-automation.yml,cut-rc.yml,release.ymlSo CI depends on roughly forty lines of that file and runs none of the rest.
Two failure modes were also measured live on PR #18420, and both are about the instrument rather than the diff:
CLAIM_BRANCH_SHAPEis/claude\/issue-\d+-[A-Za-z0-9][A-Za-z0-9._-]*/g; a session-assigned branch (claude/zealous-mendel-o0o6aq) parses to zero branches, the claim cannot be resolved, and--pairexits 2 (UNJUDGED) — which by its own rules is ⛔ never "clean". Systematic, not a one-off.mainand the recorded verdict names a superseded head.Scope — what comes out, what must NOT
Out:
.claude/skills/pm-dispatch/SKILL.md(clause ② in 〈入队与落地〉 and the landing pre-check item ②; hits at lines ~76, 152, 338, 474-477, 512-522, 635-646, 672, 766 at time of filing)..claude/skills/pm-dispatch/references/contract-review.mdin full (60 lines), plus the mentions inreferences/platform-readings.md.needs:contract-reviewgate label and its hang/clear discipline.scripts/pm/check-clause2-carriers.mjs: the C4 (independence pair), C6 (review of record) and C7 (Served-tier:) rows, and the--pairlanding pre-check role.Must survive — measure before deleting anything:
readClause2Lineand theClause-②: yes | nodeclaration line itself: the two CI gates above read it for semver level and ADR-0087 disposition, which is a different job from who reviewed the diff. Extract it to a small module (~40 lines) so those gates stop hanging off a 9k-line file.CONTRACT_REVIEW_TIERinscripts/pm/dispatch-gates.mjs: it also mandates a model tier for path-based clause ① work (the pm-dispatch skill surfaces, the publishedskills/**catalog). Only its review role retires.needs:contract-reviewis named inpackages/spec/src/api/error-code-ledger.zod.tsand its generated reference page — a published surface. Measure what that row does before touching it; removing a published ledger row is its own decision, not a rider on this one.check-half-states.mjs,check-governed-queue-guard.mjs,check-widening-tells.mjs,check-label-desc-cap.mjs,check-skill-line-ratchet.mjsandensure-pm-labels.shdo with the label — each needs its own reading; several only name it in prose.If the hazard is still wanted later
The thing the rule guarded against is an AI seat approving its own contract change and queueing it. If that is ever wanted again, the cheap form is GitHub's own required reviews / CODEOWNERS — platform-enforced, zero lines of comment archaeology — rather than a checker that is not in CI and reads two lines out of a comment body. Recorded here so a later reader knows the alternative was considered and not merely forgotten.
Sequencing
.claude/**,skills/**): the authoring seat never self-queues this one.groupruns package-authored scheduled work without a declaration, owning each run's writes per record #18420.readClause2Lineand prove the four CI workflows still green first, then remove the rule text and the gate role, then the label.Dedup terms
clause-②·needs:contract-review·check-clause2-carriers·contract-review.md·independence pair SELF-REVIEW