Skip to content

Commit aea3443

Browse files
skills(os-dev, pm-dispatch): every PR opens with a six-line 维护者速读; the seat's 席位核对 precedes pr_ready/enqueue; H69 patrols a summons that ran ahead of it (#26327)
Fixes #26155 Clause-②: no Metadata-protocol: none ## 维护者速读 改了什么:每个 PR 正文现在都以这块六行速读开头(受管与否都带),其后英文节序固定、门禁日志折进可展开块;席位在你被请审之前先把自己的核对贴到当前 head;巡查多一行报告态 H69,点名「已请审、席位核对却没跟上 head」的 Tier H PR。 为什么改:你的原话「看一下现在的pr写的内容,我总感觉对我审核的人帮助不大,是否需要更新skills」→「立卡」;立卡实测 35 个 open PR 首节名不统一、中文只在 6 个受管草稿里、其中 4 个没有席位终稿。 风险与回滚:只改两份规则文本与一行报告态巡查,不改任何门禁判定、不动复核清单;出错时你看到的是 PR 正文形状不对或 H69 多报一行,不阻塞任何落地。回滚 = revert 本 PR 的一个 commit。 先看:`.claude/agents/os-dev.md`(新五行是模板本体;退掉的三行去向见 Acceptance notes)→ `.claude/skills/pm-dispatch/SKILL.md`(① 行:席位核对先于 `pr_ready`/入队)→ `scripts/pm/check-half-states.mjs`(风险 hunk = `h69SeatRecordBehindHead` 里 head 日期与记录时间的比较)。 两分钟验证:`node scripts/pm/check-half-states.mjs --self-test`,预期末行含 `H69 seat record before governed review 66/40`;`pnpm check:pm-skill-ratchet`,预期 `os-dev.md is 404 lines (ceiling 404; headroom 0)`。 需要你做的:确认或改这六个标签——这块就是模板本体,它的形状在本 PR 上由你定;落地由席位走 Tier S 契约复核,不需要你点合并。 ## What changes **`.claude/agents/os-dev.md` — 404 → 404 lines (ceiling 404).** Lines 288–289 (the governed-only `## 维护者速读(草稿)` with 五段 including 席位意见) become five rule lines, now 285–289: the block on every PR right after the two declaration lines; the six labels verbatim and in order; the `先看` and `两分钟验证` sub-rules; `需要你做的` = exactly one action, `无,席位落地` on a non-governed PR; and the fixed English section order (What changes / Tests / Acceptance notes / Verification) with every log reading folded into a details/summary block. Three lines retired to pay for them, each to a home it already had: - old 273 (push with `-u`, back off on network failure, pre-push refuses card trailers) → rule 1 lines 30 and 32, and base line 285 (now 282: no card trailer on a commit); - old 275 (after the PR opens, merge `main` only on a conflict, a main-red or a dequeue, then the scoped re-check) → AGENTS.md Multi-agent discipline §10, which states it verbatim; - old 284 (the three safe spellings beside a card number: `is not addressed here`, `out of scope:`, `remains open`) → the keyword rule directly above it (base 282–283, now 280–281, 「让它们远离其它卡号」) and review-checklist.md:10 安全拼法 (卡号旁零动词). **`.claude/skills/pm-dispatch/SKILL.md` — 319 → 319 lines (ceiling 319); four lines rewritten in place, no new line.** ① (188): the seat's record is on the PR before `pr_ready` (Tier H) and before enqueue (Tier S), pinned to the head — the single home of the Wanted-2 precondition; `两层同欠` is carried by naming both triggers, `卡只留指针行` by execution-duties.md:184 and the pointer spelling on 190. 192: the six labels. 193: the dev's block on every PR, no 席位意见 line. 194: the seat corrects the six lines and adds the 席位意见 line. **`scripts/pm/check-half-states.mjs` — H69, report-only (35,243 → 35,593 lines).** Population = H48's (governed, Tier H, open, drafts in) narrowed to a pending request from a `GOVERNED_APPROVERS` account; it fires when no comment whose line begins `## 席位核对` is newer than the head's committer date. It reuses the thread H48 buys and adds ONE commit read per PR that carries a record at all — a PR with no record is judged without that read, an unread head date is UNJUDGED, never clean. A sibling of H43, not a widening: H43 asks who was asked, H69 whether the record preceded the asking, and the two remedies differ. Coverage pair `seatRecordCandidates`/`seatRecordJudged`, summary clause `Seat records (H69)`, band `state`, a 66-case battery pinned at 40. H48's hint text and fixture follow the renamed dev heading: the body section is now `## 维护者速读`, the same heading as the comment marker, H48 still reads comments only, and a new case proves the fixture carries that heading so the pin is not vacuous. **Not touched.** `references/review-checklist.md` (card ⛔ 3). `references/landing-operations.md`: its Tier S enqueue line — the order's candidate home — no longer exists on `origin/main` (#26210 retired it), and the surviving line 60 sits at 115 bytes with no room for a fold, so the precondition has one home. No open PR body was rewritten. AGENTS.md untouched. ## Tests - `node scripts/pm/check-half-states.mjs --self-test` on `b04d9371`: exit 0 — `✓ check-half-states self-test: 5030 cases pass. Batteries: … H69 seat record before governed review 66/40`. The pair the card pins is `H69: approver requested, record OLDER than the head -> finding` and `H69: approver requested, record NEWER than the head -> clean`, with the controls beside them: no record needs no head read; an unread head date is UNJUDGED; a non-approver or assign-only request does not fire; Tier S stands down; a new push after a fresh record re-opens the state; H43/H48 adjacency. - No ablation: the diff changes rule text and a patrol script, not a tested runtime behaviour (os-dev.md: 配置、脚本、workflow、文档 ⛔ 不消融). ## Acceptance notes - **Premise — relay request timing (measured; it shapes the wording).** `fleet-write/execute.mjs` requests `GOVERNED_APPROVERS` at `pr_create` AND at `pr_ready` on a Tier H hit (its battery name at execute.mjs:1046; AGENTS.md Prime Directive 14 calls the draft-time request a summons). So the precondition cannot bind the create-time request; SKILL.md ① binds `pr_ready` and enqueue, and H69 reads the pending request as the summons it is — a fresh Tier H draft fires until the seat's record lands on its head, which is the measured shape (4 of 6 governed drafts on the filing day). - **Premise — the details/summary fold (unmeasured until this PR).** 0 of 28 open and 0 of 100 recently closed PR bodies carried a details tag (REST `GET /pulls`, read 2026-10-26T20:25Z); platform-readings.md records the write-side sanitizer deleting unknown tag shapes and says nothing about this element. This PR's own `## Verification` is the measurement: if the folds below render, the rule line stands; if they were stripped, the seat has the reading and the fold needs a different spelling. - **Ruling A on #25919 (comment 6386217274) answers 404** — NOT MEASURED, evidence destroyed. The card's quotation of it (「规范核心与事故史分家」) and the surviving ruling 6407900763 on that card point the same way, and nothing here depends on it. - **Recognisers re-grepped before and after** (`速读|五段|席位意见|Acceptance notes|维护者速读|席位核对` over `.claude/**` and `scripts/pm/*.mjs`): none is keyed on `(草稿)` or `五段`. `MAINTAINER_BRIEF_MARKER` (H48) reads comments only and is unchanged; `fleet-roster.mjs` reads `## 席位核对` plus ACCEPT, unchanged; `check-governed-merges.mjs`, `check-governed-queue-guard.mjs` and `dispatch-gates.mjs` say "a final 维护者速读" in prose, still true; `post-stamped.mjs`'s `席位意见` opener belongs to the decision-analysis frame, unrelated; `references/decision-analysis.md:13` keeps its one-line governed-draft summary — the seat's decision-box line, not the PR brief. - **Tier.** The only governed paths are `.claude/**` → Tier S: this PR stays draft; the seat's independent `CONTRACT_REVIEW_TIER` review and the queue are the landing. The dev did not ready, arm or enqueue it. `skip-changeset` rides `pr_create`'s labels: `.claude/**` and `scripts/pm/**` publish nothing. - **Out of scope, not filed:** none. The `os-dev.md:292` token-count clause (「姊妹门禁定义 token 计数后同报 token」) names a gate that does not exist; noted as a candidate for the next compression, not retired here. ## Verification <details><summary>Required gates — all green on b04d937, exit codes captured before any pipe</summary> | command | exit | verdict line | |:--|:--|:--| | `node scripts/pm/check-half-states.mjs --self-test` | 0 | `✓ check-half-states self-test: 5030 cases pass. Batteries: … H69 seat record before governed review 66/40.` | | `pnpm check:pm-skill-ratchet` | 0 | `✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 404 lines (ceiling 404; headroom 0).` · `.claude/skills/pm-dispatch/SKILL.md is 319 lines (ceiling 319; headroom 0).` | | `pnpm check:pm-skill-id-lint` | 0 | `✓ check-skill-id-lint: 104 file(s) clean (pattern /#[0-9]{3,}/g).` | | `pnpm check:skill-frame-sync` | 0 | `✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent` | | `pnpm check:skill-frame-freshness` | 0 | `✓ check-skill-frame-freshness: the decision frame in this tree is current with origin/main (fetched just now).` | </details> <details><summary>Derived families — `dispatch-gates --commands --repo objectstack-ai/objectstack` on b04d937: 52 commands, 51 exit 0 on the first pass, the one exit 3 reran green after a build</summary> Derivation header: `gate list derived from the tree of 'objectstack-ai/objectstack' at commit b04d937`. Runner: each command via `bash -c`, exit code captured before any pipe. | command | exit | wall | |:--|:--|:--| | `node scripts/check-ci-filter-parity.mjs` | 0 | 0s | | `node scripts/check-closing-keyword-parity.mjs` | 0 | 3s | | `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | 5s | | `node scripts/check-comment-mask-corpus.mjs` | 0 | 185s | | `node scripts/check-declaration-mirrors.mjs` | 0 | 0s | | `node scripts/check-declaration-mirrors.mjs --self-test` | 0 | 0s | | `node scripts/check-issue-citations.mjs` | 0 | 1s | | `node scripts/check-scripts-symbol-anchors.mjs` | 0 | 4s | | `node scripts/check-scripts-symbol-anchors.mjs --self-test` | 0 | 4s | | `node scripts/check-self-test-wired.mjs` | 0 | 2s | | `node scripts/check-self-test-wired.mjs --self-test` | 0 | 5s | | `node scripts/check-self-test-workflow-commands.mjs` | 0 | 121s | | `node scripts/check-self-test-workflow-commands.mjs --self-test` | 0 | 4s | | `node scripts/check-whole-set-label-write.mjs` | 0 | 2s | | `node scripts/check-whole-set-label-write.mjs --self-test` | 0 | 0s | | `node scripts/ci/scheduled-full-run.mjs --self-test` | 0 | 1s | | `node scripts/pm/bare-root-worklist.mjs --self-test` | 0 | 32s | | `node scripts/pm/board-snapshot.mjs --self-test` | 0 | 0s | | `node scripts/pm/check-governed-queue-guard.mjs --self-test` | 0 | 0s | | `node scripts/pm/check-harness-current.mjs --self-test` | 0 | 8s | | `node scripts/pm/sweep-closed-cards.mjs --self-test` | 0 | 0s | | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` | 3 | 2s | | `pnpm check:agent-model-declared` | 0 | 1s | | `pnpm check:agent-test-spelling` | 0 | 3s | | `pnpm check:bash32-floor` | 0 | 2s | | `pnpm check:cli-command-ids` | 0 | 18s | | `pnpm check:closing-target-claim` | 0 | 1s | | `pnpm check:commit-card-trailers` | 0 | 1s | | `pnpm check:cross-package-test-inputs` | 0 | 35s | | `pnpm check:doc-authoring` | 0 | 7s | | `pnpm check:driver-memory-census` | 0 | 5s | | `pnpm check:entry-guard` | 0 | 40s | | `pnpm check:gitlink-declared` | 0 | 2s | | `pnpm check:issue-citations` | 0 | 7s | | `pnpm check:nul-bytes` | 0 | 5s | | `pnpm check:parse-guard` | 0 | 3s | | `pnpm check:partof-closing-keyword` | 0 | 1s | | `pnpm check:pm-dispatch-gates` | 0 | 413s | | `pnpm check:pm-expected-skips` | 0 | 6s | | `pnpm check:pm-governed-merges` | 0 | 10s | | `pnpm check:pm-governed-prose` | 0 | 1s | | `pnpm check:pm-half-states` | 0 | 3s | | `pnpm check:pm-post-stamped` | 0 | 1s | | `pnpm check:pm-skill-id-lint` | 0 | 1s | | `pnpm check:pm-skill-ratchet` | 0 | 1s | | `pnpm check:pnpm-filter-targets` | 0 | 3s | | `pnpm check:pnpm-flag-spellings` | 0 | 5s | | `pnpm check:ratchet-remedy-authority` | 0 | 4s | | `pnpm check:refd-timer-probe` | 0 | 24s | | `pnpm check:single-claim-paths` | 0 | 1s | | `pnpm check:skill-frame-sync` | 0 | 1s | | `pnpm check:watch-hint-literal` | 0 | 6s | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` exit 3 on the first pass = the gate's own PREREQUISITE refusal (`@objectstack/formula` and `@objectstack/lint` unbuilt; "Nothing was measured"). Rerun after `pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` under the verify lock: exit 0. `--ran` reconciliation: ✓ dispatch-gates --ran: 52 derived famil(ies) accounted for — 52 run, 0 NOT-MEASURED (a DERIVED zero — all 52 recorded an exit code and none of them is 3). The derivation before the runs was clean; the `--ran` reconciliation run printed a STALE TREE warning: the branch base is `f00cbe36` and `origin/main` had moved 5 commits by then; the two files the tool names as stale are the `scripts/sdui-manifest.sources/core.json` and `react.json` hash sentinels for `ui/packages/core` and `ui/packages/react`, which no changed path touches, and the derived set was 52 commands both times. `main` is not merged before the PR opens (AGENTS.md: merge `main` only on a conflict, a main-red or a dequeue). </details> <details><summary>Hook self-tests and the local-only freshness gate (outside the derivation, run on b04d937)</summary> | command | exit | wall | |:--|:--|:--| | `bash .claude/hooks/guard-main-checkout-bash.selftest.sh` | 0 | 7s | | `bash .claude/hooks/guard-main-checkout.selftest.sh` | 0 | 5s | | `bash .claude/hooks/guard-process-kill.selftest.sh` | 0 | 1s | | `bash .claude/hooks/guard-shared-stash.selftest.sh` | 0 | 2s | | `bash .claude/hooks/guard-tree-enum.selftest.sh` | 0 | 1s | | `bash .claude/hooks/session-start-fleet.selftest.sh` | 0 | 1s | | `pnpm check:skill-frame-freshness` | 0 | 3s | </details> <details><summary>Line budget — bytes of every touched rule line (cap 120)</summary> | file:line | before | after | |:--|:--|:--| | os-dev.md:273 (retired) | 115 B | — | | os-dev.md:275 (retired) | 87 B | — | | os-dev.md:284 (retired) | 84 B | — | | os-dev.md:288 → 285 | 114 B | 108 B | | os-dev.md:289 → 286 | 118 B | 98 B | | os-dev.md (new) 287 | — | 115 B | | os-dev.md (new) 288 | — | 95 B | | os-dev.md (new) 289 | — | 114 B | | SKILL.md:188 | 116 B | 114 B | | SKILL.md:192 | 116 B | 104 B | | SKILL.md:193 | 111 B | 107 B | | SKILL.md:194 | 115 B | 118 B | os-dev.md 404 → 404 lines; SKILL.md 319 → 319 lines; check-half-states.mjs 35,243 → 35,593 lines (no ceiling). </details> Co-authored-by: Claude <noreply@anthropic.com>
1 parent 583b024 commit aea3443

3 files changed

Lines changed: 370 additions & 20 deletions

File tree

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,7 @@ model: opus
270270
- driver/kernel 启动路径同此;那时跑 `--project integration` 并在报告里说明,否则写已声明给 CI。
271271
- 层是测出来的,不是列出来的:spawn CLI 或启动 driver 的测试按 `packages/cli/vitest-tiers.ts` 落。
272272
- 分区 pin `test/vitest-tiers-partition.test.ts` 在某个测试文件两层皆无或皆有时变红。
273-
- 用 `git push -u origin claude/issue-<n>-<slug>` 推上去,网络失败退避重试;pre-push 拒卡片 trailer。
274273
- Draft PR 指向 `main`,正文首行 `Fixes #<n>`;合并不应关卡时用 `Part of #<n>`,并说明留下哪一半。
275-
- PR 开出后合 main 只因冲突、main 致 CI 红、出队,后只跑 §10 复检。
276274
- 全量 dogfood 只在终 head 跑一次,仅当标题带 `!` 或 `Clause-②:` 带 `(narrowing)` 臂(yes/no 皆算)。
277275
- 命令同 CI:按 ① 建闭包,锁下 `pnpm --filter @objectstack/dogfood test`;⛔ 无 `OS_TEST_SHARD`、无路径。
278276
- 红 = 本改动的后果(陈旧 fixture)同 PR 修,余照报;⛔ 永不跳过或收窄;计数记 `dogfood_battery`。
@@ -281,12 +279,14 @@ model: opus
281279
- ⛔ 永不 `Fixes` 一张还在决策箱的卡:合并会静默关掉它,而收件箱过滤只读 open。
282280
- ⛔ 不写否定式的关单句,它照样关掉点名的卡:解析器无视否定,只匹配关键词 + `#<n>`。
283281
- 关键词是 `fix/fixes/fixed/close/closes/closed` 与 `resolve/resolves/resolved`;让它们远离其它卡号。
284-
- 写 `#<n> is not addressed here`、`out of scope: #<n>` 或 `#<n> remains open`。
285282
- 卡片关系只在 PR 正文声明一次:commit ⛔ 不带卡片 trailer,其 trailer pair 一律 model-free。
286283
- harness 归属提醒凭其优先级句让位本文件;harness 自写含模型名 trailer 只报,⛔ 不仿不改史。
287284
- 受管路径全在 `.claude/**` 者 Tier S,达档复核 PASS 在案即由席位入队落地;余皆 Tier H 等人批。
288-
- 受管面 PR 正文带 `## 维护者速读(草稿)` 节,中文、业务角度,席位意见留空;两层同欠。
289-
- 五段固定:改了什么/为什么改/风险与代价(含回滚)/席位意见/你要做的;席位定稿成评论。
285+
- 两声明行后 `## 维护者速读` 六行,受管与否都带,中文、业务角度,不写席位意见。
286+
- 六行固定:改了什么/为什么改/风险与回滚/先看/两分钟验证/需要你做的。
287+
- 先看 ≤3 文件按风险排,点名风险 hunk;两分钟验证 = 一条命令或一次点击,写预期所见。
288+
- 需要你做的恰一个动作,非受管面写「无,席位落地」;席位定稿成评论。
289+
- 英文节序:What changes/Tests/Acceptance notes/Verification;日志读数每子题折进 details/summary 块。
290290
- 触 `skills/**`(对外发布的技能包)的 diff:PR 正文报两个读数,并默认拒绝小功能大扩写。
291291
- 两个读数缺一不可:被改文件的整文件 before/after,与整包 before/after(全部 SKILL.md 之和)。
292292
- 行数为准,姊妹门禁定义 token 计数后同报 token。

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
185185
- 另含 `ui/docs/adr/**`+`ui/.claude/**`+`ui/skills/**`+`ui/AGENTS.md`+`ui/CLAUDE.md`+`ui/.github/workflows/**`。
186186
- 路径面命中 Tier H ⇒ ACCEPT 换终局四件套,混合 diff ⛔ 不按比例判;要拆让 dev 单独开 PR。
187187
- 改动 >3000 行(含生成物)同换终局四件套,⛔ 无 Tier S 例外;读数 = PR additions+deletions。
188-
- ① 席位记录一条落 PR,两层同欠:Tier H 置顶速读五段,其下 `## 席位核对`;卡只留指针行。
188+
- ① 席位记录落 PR 先于 `pr_ready`/入队且钉 head:速读六行+席位意见,其下 `## 席位核对`。
189189
- ② PR 悬着等人批,同笔挂 `needs-user-decision`;人工直合即审核记录,授权批准 ⇒ 席位落地。
190190
- 指针 `ACCEPT → PR #n comment <id>`;技能面 hunk 复核随面定档:席未达档起隔离达档复核。
191191
- 核对六项(席位读此):形态/前提实测/门禁 check-runs/接受的偏差/范围外去向/落地条款。
192-
- 速读五段固定:改了什么/为什么改/风险与代价(含回滚)/席位意见/你要做的(一个动作)。
193-
- 草稿归 dev:受管面 PR 正文带 `## 维护者速读(草稿)`,中文、业务角度,席位意见留空。
194-
- 终稿 = 席位对照自己读的 diff 校正草稿、填席位意见,置顶席位记录;维护者只读评论。
192+
- 速读六行固定:改了什么/为什么改/风险与回滚/先看/两分钟验证/需要你做的。
193+
- 草稿归 dev:每个 PR 正文带 `## 维护者速读` 六行,中文、业务角度,不写席位意见。
194+
- 终稿 = 席位对照自己读的 diff 校正六行、加席位意见行,置顶席位记录;维护者只读评论。
195195
- PR 上的标签 = 待维护者审阅,不入六态;与请审同为等人批清单,随获批或撤回判决离开。
196196
- 批准判定单源 = 队列守卫常量 `GOVERNED_APPROVERS`:授权账户 APPROVED 即算,⛔ 不卡 `commit_id`。
197197
- 批准后再推亦不过期;席位落地 = 过落地前检、清标、ready、auto-merge,踢出/变基同法。

0 commit comments

Comments
 (0)