Skip to content

Commit 1047fe1

Browse files
authored
governed: tier the register — Tier H stays human/approved, Tier S (.claude/**) lands on a contract-tier review of record (#19144)
1 parent 4d1d9d9 commit 1047fe1

8 files changed

Lines changed: 446 additions & 173 deletions

File tree

‎.claude/skills/pm-dispatch/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,8 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
621621
- ④ 轮次报告单列 awaiting a human merge。
622622
- 已入队才读到本条 ⇒ 转 draft 与 disable 都做;出队以阳性探针答,ref 缺席只旁证。
623623
- skills 车道自有 PR:纯代码面如 `scripts/pm/` 由本席按达档自审(清单不减)后落地。
624-
- 受管面两层:事实层仅本技能 `references/`,其余为规则层(含发布 `skills/**` 与 SKILL.md)。
625-
- 规则层四件套等人批;事实层 PR(受管路径全在该目录)经席内达档复核后 ready → 入队。
624+
- 受管面两层:Tier H(规则层)= `AGENTS.md`+`CLAUDE.md`+`docs/adr/**`+`docs/NORTH-STAR.md`+发布 `skills/**`。
625+
- Tier S = `.claude/**` 全树;Tier H 四件套等人批;Tier S 经席内达档复核 PASS 在案后 ready → 入队。
626626
- 路径面干净的才转 ready → 入队;队列是唯一被认可的落地路径,⛔ 永不队列外合并。
627627
- 入队资格:每 check 绿或预期 skip,⛔ 非必查子集;名单 check-expected-skips.mjs 只判 objectstack。
628628
- 非必查红是真缺陷或坏门,归 PM 入队前处置;第三种按设计而红,三条全立才可带红入队:

‎.claude/skills/pm-dispatch/references/contract-review.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
- 放宽 tell 由 `scripts/pm/check-widening-tells.mjs` 判,`no` 撞新键/成员/导出/登记即拒,附 file:line。
4444
- ③ PR check 全绿,⛔ 非 required 子集;例外:merge-base 同签名的红不计、按设计而红见 SKILL.md。
4545
- 签名 = 失败步 + 首错行,读 base check runs 的 API ⛔ 不凭口述;主干红止血立单不变。
46-
- 规则层等维护者的字;受管路径全在 `.claude/skills/pm-dispatch/references/` 者达档过本三条入队。
46+
- Tier H(规则层)等维护者的字;受管路径全在 Tier S 面(`.claude/**`)者达档过本三条入队。
4747

4848
## 降档保险丝(机读)
4949

‎.claude/skills/pm-dispatch/references/core-rules.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
- 停摆永不自愈,按梯度复位、三次即判不可靠重派;报告丢失时按草稿 PR 直接验收。
120120
- 复核对 GitHub 核验 ⛔ 不对自述核验,逐项过清单并亲核形态、范围与整包价值密度。
121121
- CI 收敛读数只属于复核侧;判决三种:验收落卡、返工最多两轮、升级走决策通道。
122-
- 验收后取路径面,命中规则层即分叉 ⛔ 不翻正式不入队;`references/` 席内达档复核后入队。
122+
- 验收后取路径面,命中规则层即分叉 ⛔ 不翻正式不入队;Tier S 席内达档复核 PASS 后入队。
123123
- 受管面 PR 留 draft 并向两个授权批准账户请审;契约卡无同形复核记录 PASS ⛔ 禁止入队。
124124
- 入队资格是每一个检查全绿 ⛔ 不是必查子集;碰生成物的 PR 入队前先同步再重生成。
125125
- 唯一例外:源码自述 pushed 上按设计而红、不跑 `merge_group`、评论记明门与因,三条全立。

‎AGENTS.md‎

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -252,40 +252,40 @@ localStorage / auth gotchas.
252252
When a cloud decision's **mechanism half** governs open code here, this repo carries its own ADR — own number, a
253253
`## Provenance` section naming the cloud record and its date, the commercial half left in cloud — and the cloud
254254
record gains a one-line pointer. Files never move between registries and numbers are never reassigned.
255-
14. **⛔ A governed surface is confirmed and merged by the maintainer, by hand — or confirmed by an authorized
256-
approval and then landed by the owning seat; before that approval no AI seat merges, queues, or arms auto-merge on a
257-
PR whose diff touches one.** The governed surfaces are `docs/adr/**`, `.claude/**` (agents, hooks and settings —
258-
not only skills), `skills/**`, `AGENTS.md`, `CLAUDE.md` and `docs/NORTH-STAR.md` — the file you are reading is
259-
one — and a mixed diff is governed whole on a single path hit. The register is the `GOVERNED_SURFACES` table in
260-
`scripts/pm/check-governed-merges.mjs`; adding a surface is an edit *there*, never here, and `pnpm
261-
check:pm-governed-prose` reds per-PR when this paragraph names fewer surfaces than the register — or more. When it
262-
reds, name the surface here.
255+
14. **⛔ A governed surface lands only the way its tier allows — Tier H by the maintainer's hand or by an authorized
256+
approval, Tier S by the owning seat on a contract-tier review of record; before that record no AI seat merges,
257+
queues, or arms auto-merge on a PR whose diff touches one.** The governed surfaces are `docs/adr/**`,
258+
`docs/NORTH-STAR.md`, `.claude/**` (agents, hooks and settings — not only skills), `skills/**`, `AGENTS.md` and
259+
`CLAUDE.md` — the file you are reading is one — and a mixed diff is governed whole on a single path hit. The
260+
register is the `GOVERNED_SURFACES` table in `scripts/pm/check-governed-merges.mjs`, each row carrying its tier;
261+
adding a surface is an edit *there*, never here, and `pnpm check:pm-governed-prose` reds per-PR when this
262+
paragraph names fewer surfaces than the register — or more. When it reds, name the surface here.
263263

264264
**Authoring stays open to every seat** — drafting, pushing, opening and revising the PR. What is reserved is the
265265
**landing**: on a PR whose diff touches a governed surface ⛔ never merge, ⛔ never queue, ⛔ never arm
266266
auto-merge, ⛔ never flip it out of draft to make any of those possible — judged on the PR's **file list**, not
267267
its description; a **mixed diff is not a proportion question**, one path hit is enough; to land the rest, split off
268-
the governed files. **Those four lift only for an authorized APPROVED review** — by an account in
269-
`GOVERNED_APPROVERS` (`scripts/pm/check-governed-queue-guard.mjs`), on ANY commit and not dismissed. That word is
270-
spent once per PR: the OWNING seat then lands it, later pushes included, re-queuing after an ejection or a rebase on
271-
its own pre-landing check; this gate does not re-review it. Hand-authored governed content needs that approval; a PR
272-
whose only governed paths are register rows the queue leg regenerates byte-exact clears with zero approvals — an
273-
uncertified recompute, drift or a hand-authored sibling keeps it governed. Unapproved, no seat lands it: the
274-
ending is that approval, then the owning seat. **Landing is tiered**: a PR whose governed paths all lie under
275-
`.claude/skills/pm-dispatch/references/` lands through the queue after the skills seat's contract-tier review; every
276-
other governed path is the rules layer and waits for the maintainer's word, which the director seat requests as ONE
277-
batch of at most five rows — the approval stays the maintainer's click. ⛔ **No agent seat submits an approving
278-
review on a governed-surface PR, under any account** — an authorized account is agent-operated too; "CI is green"
279-
carries no information about a governance change.
268+
the governed files. **The landing is tiered by the register; one Tier H path makes the whole PR Tier H.** **Tier H**
269+
(人合: `docs/adr/**`, `docs/NORTH-STAR.md`, `skills/**`, `AGENTS.md`, `CLAUDE.md`): those four lift only for an
270+
authorized APPROVED review by an account in `GOVERNED_APPROVERS`, on ANY commit and not dismissed; that word is
271+
spent once per PR — the OWNING seat then lands it, later pushes included; the director seat requests the word as
272+
ONE batch of at most five rows, and the click stays the maintainer's. **Tier S** (席内达档复核落地: all of
273+
`.claude/**`): those four lift once the PR thread or its card carries a `## Contract review` record for the PR's
274+
current head with `Served-tier: CONTRACT_REVIEW_TIER` and a PASS verdict, `check-clause2-carriers.mjs --pair N`
275+
reads 0 and every check is green — the owning seat then lands it through the queue; the post-merge audit is the
276+
compensating control. A PR whose only governed paths are register rows the queue leg regenerates byte-exact clears
277+
with zero approvals — an uncertified recompute, drift or a hand-authored sibling keeps it governed. ⛔ **No agent
278+
seat submits an approving review on a governed-surface PR, under any account** — an authorized account is
279+
agent-operated too; "CI is green" carries no information about a governance change.
280280

281281
**Already armed or queued when you read this?** Convert it back to **draft** AND disable auto-merge — draft is
282282
what removes queue membership, disabling alone drops only the arming — then confirm from the remote that it is in
283283
neither the queue nor `origin/main`. **Draft is no barrier by itself — the barrier is this directive**, and a
284-
spent approval IS the review record, ⛔ not a relaxation. Behind it: the queue guard refuses an unpinned governed
285-
diff; CODEOWNERS routes review requests for `docs/adr/` only, so nothing summons the maintainer on the other four;
286-
the post-merge audit (`scripts/pm/check-governed-merges.mjs`) lists every governed-surface merge with its approver
287-
and merger — a merger the maintainer does not recognise, or any agent approval, is a seat violation, filed and
288-
rolled back. The rule has no exception for a seat to judge.
284+
spent approval or a standing record IS the review record, ⛔ not a relaxation. Behind it: the queue guard refuses a
285+
governed diff without its tier's record; CODEOWNERS routes review requests for `docs/adr/` only, so nothing summons
286+
the maintainer on the other Tier H surfaces; the post-merge audit (`scripts/pm/check-governed-merges.mjs`) lists
287+
every governed-surface merge with its approver and merger — a merger the maintainer does not recognise, any agent
288+
approval, or a Tier S merge without a PASS record is a seat violation, filed and rolled back. No seat judges this.
289289

290290
15. **⛔ A version release is performed by the maintainer, by hand — no AI seat publishes, tags, cuts a Release, or
291291
triggers a release workflow, and none merges the Version Packages PR.** A rule that binds every seat lives here,
@@ -797,7 +797,7 @@ working in its domain — browse the directory, never a hand-written list here:
797797
- `.claude/skills/` — repo-internal agent playbooks; every entry must carry
798798
`metadata.internal: true`.
799799

800-
⛔ **Both roots are governed surfaces** — human-merge only, or **Prime Directive #14**'s pinned-approval path.
800+
⛔ **Both roots are governed surfaces** — `skills/` is Tier H, `.claude/skills/` Tier S (**Prime Directive #14**).
801801

802802
---
803803

@@ -1059,8 +1059,8 @@ Both non-handshake shapes, and how to classify and probe your own:
10591059
§7: never straight to `main`; never arm a PR that isn't green yet). A finished task
10601060
= a merged PR, not a dirty working tree. ⛔ **Except a diff touching a governed
10611061
surface** (Prime Directive #14 names them — more than ADRs): push it, open the PR, and stop
1062-
there; landing waits for the maintainer's word. For that class, a finished task = a PR
1063-
left visibly awaiting that word.
1062+
there; landing waits for its tier's record — the maintainer's word, or a seat's contract-tier
1063+
review. For that class, a finished task = a PR left visibly awaiting that record.
10641064
3. **Add a changeset for anything that publishes.** Feature, functional improvement or fix — run `pnpm changeset`
10651065
(or add a `.changeset/*.md` entry) describing it before committing. A bug fix in a released package takes a
10661066
**`patch`** changeset — never none, and ⛔ never `skip-changeset`: that label is for a diff that publishes

‎scripts/pm/check-clause2-carriers.mjs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8132,11 +8132,17 @@ export async function selfTest() {
81328132
created_at: '2026-09-16T10:00:00Z',
81338133
body: contractReviewRecordLines({ headSha: PIN_HEAD, reviewedBy: 'session_01PINSEAT' }).join('\n'),
81348134
};
8135+
// A Tier S path (the register's `.claude/**` row since #19133; the fact layer
8136+
// under it was the whole tier under #18020). The control below asks the
8137+
// register, so a row moving tiers reddens here instead of silently driving
8138+
// the approval leg.
8139+
const TIER_S_PATH = '.claude/skills/pm-dispatch/references/contract-review.md';
8140+
t('⛔ CONTROL: the fixture path is Tier S under the register, so the record leg is the one being driven', GUARD.governedTierFor([TIER_S_PATH]) === GUARD.TIER_S);
81358141
const pinRun = async (where) => {
81368142
const threadsRead = [];
81378143
const verdict = await GUARD.runGuard({
81388144
event: GUARD.EVENT_MERGE_GROUP,
8139-
rows: [{ sha: 'e'.repeat(40), subject: `x (#${PIN_PR})`, pr: PIN_PR, paths: [`${GUARD.REFERENCES_TIER_PREFIX}contract-review.md`] }],
8145+
rows: [{ sha: 'e'.repeat(40), subject: `x (#${PIN_PR})`, pr: PIN_PR, paths: [TIER_S_PATH] }],
81408146
fetchReviews: async () => [],
81418147
fetchPull: async () => ({ sha: PIN_HEAD, body: `Fixes #${PIN_CARD}`, headRef: `claude/issue-${PIN_CARD}-x` }),
81428148
fetchComments: async (n) => {

0 commit comments

Comments
 (0)