Skip to content

Commit 41ff021

Browse files
claude[bot]claude
andauthored
docs(agents): the contract-review carrier is the seat's to hang; --pair PR-NUMBER is the only spelling (#18250)
Fixes #18181 ## What changed Three lines across two governed rules-layer files; line counts unchanged (os-dev.md 403/403, SKILL.md 812/812), every edited line at or under the 120-byte cap, no re-wrap anywhere, and the decision-frame block SKILL.md :734–:755 untouched (md5 `3327d02c56f8a0eca88569dad2270f32` before and after). **`.claude/agents/os-dev.md` :287** — the line the card names, re-derived on `b3b43b6` (the card body's `:288` had drifted; the filer's correction comment 5664488072 gives :287): ```diff -- 认领写 `Clause-②: yes` ⇒ 开 PR 同笔挂 `needs:contract-review`,报告附 `--pair N` 退出码。 +- `needs:contract-review` 归席位,⛔ 不挂不摘不等;报 PR 上有无与 `--pair PR-NUMBER` 退出码作读数。 ``` The dev no longer hangs the carrier. It never hangs, removes or waits for `needs:contract-review`; it reports whether the label is present on the PR and the `--pair PR-NUMBER` exit code — as a reading, not as a gate it must clear. **`.claude/agents/os-dev.md` :301** — the neighbouring `skip-changeset` label-write rule (mechanism assumption A2, same file surface, same class — an additive label write the container may refuse): ```diff -- 被拒 ⇒ 停下报 `blocked` 点名端点与状态码,⛔ 不换 MCP 写道;写后必做对比式读回。 +- 被拒 ⇒ 报端点与状态码、席位代挂,⛔ 不报 `blocked`、不走 MCP;写后必做对比式读回。 ``` One rule now covers both carriers: a refused additive label write is reported with endpoint and status and the seat hangs the label; the dev never reports `blocked` for it and never switches to an MCP write. **`.claude/skills/pm-dispatch/SKILL.md` :646** — the one `--pair N` token (REGION claim: this line only): ```diff -- `Clause-②: yes` 认领同笔在卡上挂标;PR 开出即读 `check-clause2-carriers --pair N` 为 0 再请审。 +- `Clause-②: yes` 认领同笔卡上挂标;PR 开出读 `check-clause2-carriers --pair PR-NUMBER` 为 0 再请审。 ``` `--pair PR-NUMBER` is now the only spelling in the three governed files (contract-review.md :42 already spelled it so). ## Why Direction A of the card's grading (comment 5673619664), executed as ruled: the `needs:contract-review` carrier is the PM seat's to hang — on the card at the claim and on the PR when the PR appears — which is what every seat already does; the dev never blocks on a label write; `--pair PR-NUMBER` becomes the only spelling. Option B (granting the dev container the label write) is a permissions widening and was ruled not this card. The two defects the card and its correction measured: a dev that obeyed :287 literally was refused the additive label write by its container's write classifier on two independent objectui runs, while an objectstack dev could write it — per container, unknowable in advance; and `--pair N` bound `N` to the nearest referent, the card, while the script takes a PR number and answers a card number with exit 2 (UNJUDGED), which a naive capture reads as a red gate. ## Mechanism readings - **A1** — :287 is the line on `b3b43b6` (108 B; the card's :288 is the `skills/**` line). Replaced as above. Under the byte cap the `Clause-②: yes` trigger did not fit, so the rule is now unconditional: on every PR the dev hangs nothing, removes nothing, waits for nothing, and reports carrier presence plus the `--pair PR-NUMBER` exit code. That superset is deliberate — `--pair` also carries the widening-tell row, which only fires on a `Clause-②: no` claim, so a reading on every PR is worth more than one on `yes` claims alone. - **A2** — measured on the text: :301's `被拒 ⇒ 停下报 blocked` is the same container-refusal class one line over, and nothing about `skip-changeset` requires the dev to block on it: CI's changeset gate reads the label, the dev's report says whether it landed, and the seat can hang it on that report. So one rule covers both carriers and :301 changed as above; :299 (the label is your step, hang it as soon as the PR opens) and :300 (additive endpoint) stay — the dev still attempts the write. The live half of the measurement is this PR's own `skip-changeset` write; its outcome (landed, or the endpoint and status of the refusal) is in the `os-dev-report` comment on the card, not here, because the PR body is written before the label write and is not re-sent. - **A3** — `git grep -n -- '--pair N\b' -- '.claude/**' 'scripts/pm/**'`: before 6 hits (os-dev.md :287, SKILL.md :646, and 4 in `scripts/pm/**`); after 4 hits, all outside the claimed surface: `check-clause2-carriers.mjs` :24 and :490 (docblocks), :4947 (a self-test title), and `check-widening-tells.mjs` :492 (docblock). In the three governed files the count is 0. Lit control `--pair PR-NUMBER`: 1 before (contract-review.md :42), 3 after (:42, os-dev.md :287, SKILL.md :646). The script docblocks bind `N` to a PR number in their own text (:11 spells `--pair 13910 # ONE PR`), so the ambiguity is not live there; noted below, not edited. - **A4** — measured from the sibling checkout on this container: `cd /home/user/objectui && PM_SWEEP_REPO=objectstack-ai/objectui node ../objectstack/scripts/pm/check-clause2-carriers.mjs --pair 9552` exits 0 with the provenance line `every row below is read from objectstack-ai/objectui (source: PM_SWEEP_REPO)` and the verdict `PR #9552 / card #6910 — the clause-② declaration is readable in the fixed spelling and both carriers agree` (token present, 3 reads served; the proxy re-exec happened by itself). A control on objectui#9495 (no longer open) exits 2 — UNJUDGED, with the board still retargeted. So the invocation works from a sibling checkout. The byte cap leaves no room on :287 for the invocation (the line stands at 119 B), so the line carries only the flag spelling; the script header (:20–:24) already spells the sibling invocation and every run prints the board it read, which is the remedy text the ruling asks to keep in the script. ## Gates Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; change set from the merge base): 18 families on `a2cbbef0`, re-derived on the merged head `0c934967` (merge base `68fea8bc`) — identical list. All 18 run in the foreground on `0c934967`, exit codes captured by redirect before any pipe, all 0: `check-closing-keyword-parity` (+ `--self-test`) · `check-comment-mask-corpus` · `check-governed-queue-guard --self-test` · `check:doc-formula-expressions` (lint pkg) · `check:agent-model-declared` · `check:agent-test-spelling` · `check:commit-card-trailers` · `check:doc-authoring` · `check:driver-memory-census` · `check:nul-bytes` · `check:pm-governed-merges` · `check:pm-governed-prose` · `check:pm-skill-id-lint` · `check:pm-skill-ratchet` · `check:refd-timer-probe` · `check:skill-frame-sync` · `check:watch-hint-literal` Reconciliation on `0c934967`: `✓ dispatch-gates --ran: 18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code and none of them is 3)`. Verdict lines: `✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0)` · `✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0)` · `✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model` · `✓ check-skill-id-lint: 27 file(s) clean` · `✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent`. `check:doc-formula-expressions` first answered exit 3 (PREREQUISITE NOT MET — `@objectstack/formula` and `@objectstack/lint` unbuilt in a fresh worktree); prerequisite built under the verify lock (`turbo run build --filter=@objectstack/formula --filter=@objectstack/lint`, VERDICT command-exit 0), rebuilt again after the merge, then the gate exits 0. The exit 3 is not a measurement and is not counted as one. Not run locally, by design: the 11 wide-population families and the whole-repo `pnpm lint` sweep belong to CI. Control-byte self-scan on both edited files: no hits. ## Line budget | file | before | after | ceiling | edited lines (bytes) | | --- | --- | --- | --- | --- | | `.claude/agents/os-dev.md` | 403 | 403 | 403 | :287 108→119 · :301 110→114 | | `.claude/skills/pm-dispatch/SKILL.md` | 812 | 812 | 812 | :646 116→118 | Paid by density in place; no line merged or split. ## Deviations, declared 1. SKILL.md :646: the token swap alone (`N` → `PR-NUMBER`, +8 B) puts the line at 124 B, over the 120-byte cap. Two characters were dropped on the same line (`在`, `即`), content unchanged, landing at 118 B. Still inside the one-line REGION claim. 2. os-dev.md :287: the `Clause-②: yes` trigger is gone for the byte cap; the rule is unconditional (see A1). If the seat wants the trigger back, the price is the `作读数` tail or the `不等` limb. 3. os-dev.md :287 does not spell the objectui invocation (A4); the line names the flag, the script header names the sibling form. 4. os-dev.md :301 edited under A2 (inside the file surface and the card's class). objectui's copy and the dispatch-order template are untouched. 5. `skip-changeset`: nothing published moves — `.claude/**` is on the fast path (no package `files[]` ships it). 6. `origin/main` merged at `68fea8bc` (one spec commit, nothing on this surface) before opening; #18242 remains open on SKILL.md :172–:185 — disjoint from :646. ## Acceptance notes - **To file (class b, for the seat — dedupe words: `needs:contract-review`, `PR 创建者`, `同笔挂`, SKILL.md, direction A):** SKILL.md :645 still reads 「`needs:contract-review`(恒英文)由 PR 创建者随可复审契约增量同笔挂:draft PR,或先到的报告。」 For a dev-created PR the creator is the dev, which direction A says never hangs it. Outside this card's REGION claim (:646 only), so not edited here; it sits on the SKILL.md chain the seat owns. - noted, not filed: 4 `--pair N` spellings remain in `scripts/pm/**` docblocks and one self-test title (listed under A3); each is next to text that binds N to a PR number. 承接者:无. - noted, not filed: os-dev.md :300's 「可达性按会话探,先探后用」 is redundant with the new :301 — the write attempt is the probe. Left as is; deleting it frees bytes, not a line. 承接者:无. - Observed on this PR after opening: the labels present are reported in the `os-dev-report` comment with a read-back; under one shared identity the author field says nothing about who hung what. ## 维护者速读(草稿) **改了什么**:改了两个受管规则文件里的三行,行数不变。开发 agent 定义(os-dev.md)一行:`needs:contract-review` 这个标签归席位挂,开发 agent 不挂、不摘、不等,只在报告里写 PR 上有没有它、以及 `--pair PR-NUMBER` 的退出码,作读数。另一行:加法写标签被容器拒绝时,报端点与状态码、由席位代挂,不再报 `blocked`、不走 MCP。PM 技能(SKILL.md)一个 token:`--pair N` 改成 `--pair PR-NUMBER`。 **为什么改**:两次独立实测里,开发 agent 的容器拒绝写标签,而规则要求它开 PR 同笔挂——照做就失败、如实报告又像抗命。分诊裁定 A 向:载体由席位挂(认领时挂卡、PR 出现时挂 PR),开发 agent 只报所见。同一行的 `N` 让人绑到卡号,脚本要的是 PR 号,给卡号返回 exit 2(未判),会被当红灯读;`PR-NUMBER` 是唯一拼写。 **风险与代价(含回滚)**:行数与上限不变,每行 ≤120 字节,决策框架块未动。风险是开发 agent 不再自己挂载体,若席位漏挂,条款② PR 的载体会缺失——但席位侧已经是现行做法,且开发 agent 报告的 `--pair` 读数会暴露缺失。回滚 = revert 本 PR,无其他副作用。 **席位意见**: **你要做的**:审阅上面三行措辞(尤其 :287 去掉了 `Clause-②: yes` 触发词、改为对每个 PR 都成立);同意即给授权批准,由席位落地;不同意请指出要保留的措辞。 --- _Generated by [Claude Code](https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1297178 commit 41ff021

2 files changed

Lines changed: 4 additions & 4 deletions

File tree

‎.claude/agents/os-dev.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ model: opus
284284
- 受管面(见 AGENTS.md)PR 正文带 `## 维护者速读(草稿)` 节,中文、业务角度,席位意见留空。
285285
- 五段固定:改了什么/为什么改/风险与代价(含回滚)/席位意见/你要做的;席位定稿成评论。
286286
- 正文以 session-URL 形式的署名页脚收尾(见字节与 sanitizer 纪律节)。
287-
- 认领写 `Clause-②: yes` ⇒ 开 PR 同笔挂 `needs:contract-review`,报告附 `--pair N` 退出码。
287+
- `needs:contract-review` 归席位,⛔ 不挂不摘不等;报 PR 上有无与 `--pair PR-NUMBER` 退出码作读数。
288288
- 触 `skills/**`(对外发布的技能包)的 diff:PR 正文报两个读数,并默认拒绝小功能大扩写。
289289
- 两个读数缺一不可:被改文件的整文件 before/after,与整包 before/after(全部 SKILL.md 之和)。
290290
- 行数为准,姊妹门禁定义 token 计数后同报 token。
@@ -298,7 +298,7 @@ model: opus
298298
- 其余实测:构建后 grep `files[]` 所列路径找符号,带正控;符号零命中、正控命中 ⇒ 不发布。
299299
- 本仓库:标签是真实机制,打标签是你的步骤、不是 CI 的,PR 一开出就打。
300300
- 写入首选加法端点(REST `POST .../issues/<n>/labels`,不碰已有标签);可达性按会话探,先探后用。
301-
- 被拒 ⇒ 停下报 `blocked` 点名端点与状态码,⛔ 不换 MCP 写道;写后必做对比式读回。
301+
- 被拒 ⇒ 报端点与状态码、席位代挂,⛔ 不报 `blocked`、不走 MCP;写后必做对比式读回。
302302
- 读回 diff 现集对 union(读集, 目标):union 有而回读缺 = 被剥的并发标签,重挂并写进报告。
303303
- 读回只检测剥除防不了,门语义标签被剥恰成绿灯;加法写同样必要不充分。
304304
- size-labeler 的整组 PUT 会抹掉正确的加法写;收尾一律读回、清单进报告;标签没了就重挂。

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,8 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
642642
- PASS ⇒ 同席剥标并引记录、ready、auto-merge;FAIL ⇒ 补丁轮;⛔ 免复核不放行。
643643
- 真正设计分叉照旧进决策箱,席内复核 ⛔ 不替代维护者裁定。
644644
- 外部评审链降为可选事后审计,非放行前提。
645-
- `needs:contract-review`(恒英文)由 PR 创建者随可复审契约增量同笔挂:draft PR,或先到的报告。
646-
- `Clause-②: yes` 认领同笔在卡上挂标;PR 开出即读 `check-clause2-carriers --pair N` 为 0 再请审。
645+
- `needs:contract-review`(恒英文)由席位同笔挂:PR 一现即挂 PR;报告先到则先挂卡。
646+
- `Clause-②: yes` 认领同笔卡上挂标;PR 开出读 `check-clause2-carriers --pair PR-NUMBER` 为 0 再请审。
647647
- 挂标后复核完成前短暂停靠;⛔ 不前瞻预挂。
648648
- 席内复核的适用面、载体纪律、资格与归属、降档保险丝见 `references/contract-review.md`。
649649
- 碰生成物的 PR 入队前先同步 + 整体重生成:四步序 `bash scripts/pm/os-regen-merge.sh`。

0 commit comments

Comments
 (0)