Skip to content

Commit c5d4634

Browse files
pm-dispatch(review): a PR reaches a human only after the seat's ACCEPT and a same-head contract PASS: no seat assignee at the draft open, the approver request is the seat's hand-off, a PR landed owing a review is re-reviewed with findings filed as cards (#27385)
Fixes #27345 Fixes #27363 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:把「PR 推给人审」的时点改为 **席位 ACCEPT + 现 head 契约复核 PASS 俱在案之后**:请审成为席位的交棒动作(中继 `pr_request_reviewers`;作者是审批人时 `assign`),dev 开 draft PR 不再带 `assignees`,中继 `pr_create` 不再在开 PR 那一刻请审;落地时仍欠复核的 PR 在落地 head 上复审,发现逐条立新卡;巡查 H43 只在交棒已到期而无人被请时才报。 - 为什么改:您的 GitHub 指派清单被没人复核过的 draft 填满,请审在席位审完之前就发出(「这个是技能的bug,应该是开发完了你审核通过才会推送给我审核」);三张 PR 在 PASS 之前或缺席时就被推到您面前并挂了 auto-merge(「没有完成复审就推送给我审核了」)。 - 风险与回滚:只改技能文本、中继表的一个标记位(`pr_create` 的 `governedReview`)与一条只报不拦的巡查行;不新增门禁、不碰 workflow。回滚 = revert 本 PR 的三个 commit;中继 `pr_ready` 仍保留受管请审兜底(Tier H 的 ready 本就在批准之后),Tier H 的批准与合并仍是您的点击。 - 先看:① `scripts/pm/fleet-write/ops.mjs` 的 `pr_create` 行(`governedReview: true` 移除)与头部「The governed-review follow-up」节;② `.claude/skills/pm-dispatch/SKILL.md` L198–201(规则唯一一份);③ `scripts/pm/check-half-states.mjs` 的 `h43HandoffReading` 与 `h43GovernedReviewRequestGap`(新的 `handoff` 门;unread 不判、before 不报、due 才报)。 - 两分钟验证:`node scripts/pm/fleet-write/execute.mjs --self-test && node scripts/pm/check-half-states.mjs --self-test`,预期尾行 `209 cases pass across 20 batteries` 与 `5066 cases pass … H43 hand-off timing 89/80`;本 PR 自身就是首个样本:draft 开出时 `assignees` 与 `requested_reviewers` 皆空(见 Verification 的回读)。 - 需要你做的:无,席位落地(路径面 `.claude/**` + `scripts/pm/**`,Tier S:席位跑契约复审,PASS 后 ready → 入队)。 ## What changes The two cards are one rule at two points, so the rule is written once — SKILL.md 〈路径分叉〉 ③ — and the other files point at it: a PR reaches a human only when development is done AND the seat's ACCEPT (`## 席位核对`) AND, where clause ② applies (every governed path is the review's `rules` face, so on every governed PR), a `## Contract review` PASS on the CURRENT head are on the PR; then, and only for Tier H, the seat requests review from `GOVERNED_APPROVERS` (`os-zhuang`, `hotlong`). The seat's own account is never assigned to or requested on a PR; a Tier S PR goes to no human; a head that moves after the PASS goes back to waiting. ### Card 27345 — the same-head PASS gates the ask, and a PR that landed owing a review is re-reviewed - `.claude/skills/pm-dispatch/SKILL.md` 〈路径分叉〉 L198–201, rewritten in place (four lines, same count): ③ the request IS the seat's hand-off after ACCEPT + same-head PASS, through `pr_request_reviewers`; the author-is-approver fallback stays (`assign` the author, request the others; never the seat's own account; Tier S hands off to nobody); `pr_create`/`pr_ready` request and assign nobody, a head that moves after the PASS goes back to waiting, an off-relay PR has the seat read its reviewers and assignees itself; the 速读 「需要你做的」 line that asks for approval names the PASS comment id and its `Head-sha`, and with no PASS says "contract review owed" and does not ask. - `references/contract-review.md` L47 (was L49): the two pre-landing checks now gate the request and the ask as well — ① a same-head, same-shape, at-tier PASS on the current head. New L52–53 (item 2): a PR that lands while still owing a review is re-reviewed on its landed head by the lane seat or by triage under the gap rule (a)(b)(c); a FAIL is not repaired on the closed PR — each must-fix is filed as a NEW card citing the record, graded on its own; a revert only for a main red (p0, main-red 约定①) or a security boundary. Paid by folding the two wrapped pairs L34–35 (`Local-runs:`) and L43–44 (`--brief-template`) into one line each — every clause kept; the script path is spelled in full on L33 already. - `references/landing-operations.md` L12: PASS ⇒ Tier S ready + auto-merge, Tier H hands off per SKILL.md ③; L13 points at the post-landing rule. Paid by deleting old L54, whose content (a contract-review-PASS PR arrives at the landing window already ready and armed) is L12's own statement. - `references/lanes/director.md` L57: five checks in order before a governed PR waits for a human — seat record, 速读, same-head PASS, `pr_request_reviewers`, green head. ### Card 27363 — no seat assignee at the draft open; the approver request is the seat's hand-off - `.claude/agents/os-dev.md` L37/L60: a dev's `pr_create` carries no `assignees` (labels only — `skip-changeset` still rides the create); a human sees the PR at the seat's hand-off. - `references/execution-duties.md` L63: 「PR assignee = 卡的」 and the takeover swap are gone; the in-flight-PR reader is `head:claude/` open PRs plus the card their body names (`Fixes`/`Part of`) — no PR assignee anywhere in it. The card's assignee and the `Claim:` `Branch:` still own the work. - `references/dispatch-runbook.md` 〈卡线程〉 L140 (item 4): a project thread does not perform the harness's post-create assign / request-review step; the request is the seat's hand-off — citing 「审核通过才会推送给我审核」. Paid by deleting old L136, whose three clauses (p1 first; the project-wide cap is the maintainer's; queue when full) are `coordinator.md` 三 L23–L25 verbatim, which the deleted line itself pointed at. - `scripts/pm/fleet-write/ops.mjs`: `governedReview: true` leaves the `pr_create` row — the draft open summons nobody; `GOVERNED_REVIEW_OPS` derives to `['pr_ready']`. The `assignees` leg stays optional on the row for the author-is-approver fallback and other callers; a dev simply stops sending it. **Hypothesis 1 measured:** the relay already has `pr_request_reviewers` (ops.mjs L1050: `pull` required, `reviewers`/`team_reviewers` with `atLeastOne`), so the hand-off is ONE seat stroke after ACCEPT + PASS; `pr_ready` keeps its follow-up as a backstop — a Tier H pull is readied only after an approver approved it, so there it costs zero writes when the hand-off was made and names the one approver still uncovered when it was not. Header sections rewritten accordingly (the maintainer's words quoted once). - `scripts/pm/fleet-write/execute.mjs` / `validate.mjs`: headers and self-tests pin the derived op list as `pr_ready` alone and that a `pr_create` on a Tier H diff reads no file list, re-reads no pull or reviews, sends no request and no assignee (an approver-authored pull included), and that a create answering no number owes no follow-up (the stroke no longer fails on its account). The governed battery's create-side runs became `pr_ready` runs; three create NEGATIVE pins replace them (pin 29 → 30). - `scripts/pm/check-half-states.mjs` H43 (item 5): before judging 「asked neither approver」 the row reads the PR's own issue-comment thread — H48's fetch class, cached so H48/H69 pay nothing — for the seat's ACCEPT (`SEAT_RECORD_MARKER` + `seatRecordAccepts`, seat-record.mjs) and a `## Contract review` naming the current head whose verdict word is PASS (`latestContractReviewOnHead`, widened with `verdict`; `contractReviewVerdictOf` is the one reader of the word, three measured dialects). Three states: unread ⇒ UNJUDGED (quiet, disclosed), before ⇒ not a half state (quiet), due ⇒ the existing coverage judgment. Only DUE buys the submitted-review page. Summary clause and two count keys (`governedHandoffRead`, `governedHandoffDue`) disclose the reading; drafts still neither fire nor silence it. Bound stated in the header: the PR thread is the one thread read — a PASS on the card alone reads as BEFORE (under-report only); the ACCEPT's freshness against the head stays H69's question. H69's header and sentence stopped saying 「the relay summons at `pr_create`」 (made false by this PR; its self-test pin moved with it). - **Hypothesis 2 measured** (patrols reading PR assignees as ownership): none. `check-handover.mjs` (a) reads CARD assignees and puts pull requests out of its population (its self-test pins it); `check-half-states.mjs` reads a PR's `assignees` only as H43's approver-coverage fallback, kept on purpose (the fallback assigns an approver, never a seat). `project-forms.md` L31–32: the ledger is labels + the card's assignee + `Claim:` + `head:claude/` PRs — already assignee-free on the PR side, no edit. - **Hypothesis 3**: confirmed with one adjustment — `locateReviewOfRecord` itself is not called: it requires BOTH threads (PR and card) or answers `unreadable`, and reads no verdict word; H43 reuses its building blocks (`latestContractReviewOnHead`, the one head-sha recogniser `record-recognisers.mjs` imports) and adds the verdict word beside them. - **Hypothesis 4**: the `Regen-provenance` pair (contract-review L50–51) does not compress under 120 B; the `Local-runs:` and `--brief-template` pairs do, so they paid; landing-operations L7–8 kept, old L54 paid instead. ## Line budget — every `.claude` file at its ceiling (headroom 0, prose ≤120 B) ### .claude/skills/pm-dispatch/SKILL.md — 319 → 319 lines - L198 (107 B) `- ③ 中继 ˋpr_createˋ/ˋpr_readyˋ 命中 Tier H 即向 ˋGOVERNED_APPROVERSˋ 中未请/派/审者请审。` - L199 (117 B) `- 作者是审批人 ⇒ 指派它、请其余(请它必 422),否则请全员;速读只点非作者审批人去批。` - L200 (119 B) `- 脱中继开的 PR 无 run 行:交速读前席位恒自读 ˋrequested_reviewersˋ/ˋassigneesˋ,⛔ 不只看 run 行。` - L201 (115 B) `- 缺口经中继 ˋpr_request_reviewersˋ/ˋassignˋ 补,⛔ 不碰 draft 位;ACCEPT 与轮报点名脱中继作者。` + L198 (117 B) `- ③ 请审 = 席位交棒:ACCEPT 与现 head 同形 PASS 俱在案后,中继 ˋpr_request_reviewersˋ 请审批人。` + L199 (120 B) `- 作者是审批人 ⇒ ˋassignˋ 它、请其余(请它必 422);⛔ 永不派/请席位自身账号;Tier S 不交人。` + L200 (119 B) `- ˋpr_createˋ/ˋpr_readyˋ 不请审不指派;PASS 后 head 移 ⇒ 回等复核;脱中继 PR 自读请审人与指派。` + L201 (118 B) `- 速读「需要你做的」求批点名 PASS 评论 id+ˋHead-shaˋ;无 PASS ⇒ 写 contract review owed 不求批。` ### .claude/agents/os-dev.md — 402 → 402 lines - L37 (118 B) ` - 恒不写卡的 assignee(空也开工,报 ˋsummaryˋ);PR assignee = 卡的:ˋpr_createˋ 带 ˋassignees: [LOGIN]ˋ。` + L37 (114 B) ` - 恒不写卡的 assignee(空也开工,报 ˋsummaryˋ);PR ⛔ 不带 ˋassigneesˋ,人经席位交棒才见 PR。` - L60 (104 B) ` - 写预算三笔:ˋgit pushˋ、ˋpr_createˋ(draft,含 assignee 与 labels)、ˋos-dev-reportˋ 评论。` + L60 (111 B) ` - 写预算三笔:ˋgit pushˋ、ˋpr_createˋ(draft,含 labels、⛔ 无 assignees)、ˋos-dev-reportˋ 评论。` ### .claude/skills/pm-dispatch/references/execution-duties.md — 188 → 188 lines - L63 (118 B) `- 卡 assignee 归 PM,dev 恒不写;PR assignee = 卡的,接管 ② 同笔换;读者 ˋis:pr is:open assignee:LOGINˋ。` + L63 (119 B) `- 卡 assignee 归 PM,dev 恒不写;PR ⛔ 不派席位账号;在飞 PR 读 ˋhead:claude/ˋ 开 PR 正文点名的卡。` ### .claude/skills/pm-dispatch/references/contract-review.md — 60 → 60 lines - L34 (88 B) `- 同形另带 ˋLocal-runs:ˋ 行:ˋnoneˋ,或 ˋprobe — REASONˋ 具名唯一本地探针;` - L35 (42 B) ` 有行必校,缺行旧记录不改判。` + L34 (119 B) `- 同形带 ˋLocal-runs:ˋ 行:ˋnoneˋ 或 ˋprobe — REASONˋ 具名唯一探针;有行必校,缺行旧记录不改判。` - L43 (77 B) `- 简报从 ˋnode scripts/pm/record-recognisers.mjs --brief-templateˋ 起稿:` - L44 (54 B) ` 只读条款与输入集内建,⛔ 不删 ⛔ 行。` + L42 (113 B) `- 简报从 ˋrecord-recognisers.mjs --brief-templateˋ 起稿:只读条款与输入集内建,⛔ 不删 ⛔ 行。` - L49 (115 B) `- 落地前检两条,过则 Tier S 入队、Tier H 等人批:① 达档条款②复核 PASS 在案(同形记录)。` + L47 (117 B) `- 请审/求批与落地前检两条,过则 Tier S 入队、Tier H 等人批:① 现 head 同形达档 PASS 在案。` + L52 (115 B) `- 落地时仍欠复核的 PR 在落地 head 复审,车道席或分诊按 (a)(b)(c) 接;FAIL ⛔ 不修已关 PR。` + L53 (120 B) `- 每条 must-fix 引该记录立新卡、按发现定级;回退仅限主干红(p0,main-red 约定①)或安全边界。` ### .claude/skills/pm-dispatch/references/landing-operations.md — 101 → 101 lines - L12 (74 B) `- PASS ⇒ ready、auto-merge;FAIL ⇒ 补丁轮;⛔ 免复核不放行。` + L12 (118 B) `- PASS ⇒ Tier S ready、auto-merge;Tier H 经 SKILL.md ③ 交棒请审;FAIL ⇒ 补丁轮;⛔ 免复核不放行。` + L13 (114 B) `- 落地后才见欠复核 ⇒ 按 ˋcontract-review.mdˋ 复审落地 head、发现立新卡,⛔ 不修已关 PR。` - L54 (104 B) `- 契约复核 PASS 落地的 PR 到窗口时已 ready 且 auto-merge 在挂,见 ˋcontract-review.mdˋ。` ### .claude/skills/pm-dispatch/references/lanes/director.md — 86 → 86 lines - L57 (117 B) `- 受管 PR 待人批前核四件:席位记录、维护者速读、中继 ˋpr_request_reviewersˋ 请审、绿 head。` + L57 (117 B) `- 受管 PR 待人批前核五件:席位记录、速读、现 head PASS、ˋpr_request_reviewersˋ 请审、绿 head。` ### .claude/skills/pm-dispatch/references/dispatch-runbook.md — 245 → 245 lines - L136 (116 B) `- coordinator 按优先级开线程,p1 先;全项目上限由维护者按项目定(ˋcoordinator.mdˋ),满即排队。` + L140 (119 B) `- 线程 ⛔ 不做 harness 开 PR 后指派/请审:「审核通过才会推送给我审核」,请审是席位交棒。` ## Tests <details><summary>Self-tests, before (origin/main 28872e6) → after (50118ff), exits captured before any pipe</summary> | suite | before | after | |:--|:--|:--| | `fleet-write/validate.mjs --self-test` | 216 cases / 13 batteries, exit 0 | 216 / 13, exit 0 (pin content changed, count unchanged) | | `fleet-write/execute.mjs --self-test` | 208 / 20, exit 0 | 209 / 20, exit 0 (governed battery 29 → 30) | | `fleet-write/dispatch.mjs --self-test` | 265 / 24, exit 0 | 265 / 24, exit 0 (unchanged file; imports the new table) | | `check-half-states.mjs --self-test` | 5034 cases, exit 0 | 5066 cases, exit 0; new battery `H43 hand-off timing 89/80` (57 legacy coverage cases driven with the hand-off DUE + 32 timing cases) | | `record-recognisers.mjs --self-test` | 297, exit 0 | 297, exit 0 | | `check-owed-reviews.mjs --self-test` | 49 / 8, exit 0 | 49 / 8, exit 0 | | `check-governed-queue-guard.mjs --self-test` | 401, exit 0 | 401, exit 0 | | `check-handover.mjs` / `fleet-roster.mjs` / `seat-record.mjs` / `check-governed-merges.mjs --self-test` | 46 / 78 / ok / 537 | unchanged, exit 0 | </details> <details><summary>Ablations — one per changed script, committed state first, restore hash-proven by scripts/ablation-replace.mjs (blob == HEAD, git diff HEAD empty), whole tree clean after</summary> Expected direction for every leg: turn red (常态). Observed: 1. `ops.mjs` — `governedReview: true` planted back on `pr_create` (anchor hit 1 → 0, blob 2abc597 → f52678f1, restored to 2abc597). `validate.mjs --self-test` exit 1 with the named pin red: 「the governed-review follow-up runs after exactly pr_ready … 1 of 216 case(s) failed」. `execute.mjs --self-test` exit 1 by a TypeError at L1303 (the requests battery's `pr_create` + `issue_create` stroke stopped after the create — the re-enabled follow-up asked for `GET …/pulls/9/files`, which the fixtures no longer prime — so the second write never happened): red by crash at the first create-side case the mutation reaches, before the ⭐ negative pin itself was evaluated. - A first attempt of this leg was a NO-OP and is recorded as such: the replacement text re-contained the anchor, the tool refused (anchor count 1 → 1, not the declared drop), the child never ran, nothing was written. Re-anchored on the row's unique comment line and re-run as above. 2. `execute.mjs` — the follow-up forced to run after `pr_create` again (`action.op === 'pr_create' ||`). `execute.mjs --self-test` exit 1, same TypeError at L1303 for the same reason (a follow-up after the create), red by crash. Restored to ddd1bfa == HEAD. 3. `check-half-states.mjs` — the hand-off gate `if (handoff?.state !== 'due') return null;` deleted. `--self-test` exit 1 by a TypeError at `h43GovernedReviewRequestGap` (`handoff.record` on an undefined hand-off, reached from the 「an UNREAD thread is UNJUDGED」 pin): red by crash at exactly the pin the gate protects. Restored to f5c5c23 == HEAD. 4. `check-half-states.mjs` — `contractReviewVerdictOf` answering `PASS` for every explicit `VERDICT:` line. `--self-test` exit 1 with 6 named ✗ cases, among them 「a FAIL on the current head is BEFORE (got "due,PASS", want "before,FAIL")」, 「the newest PASS on the head decides, and a FAIL after it withdraws the hand-off」, 「`**VERDICT: PASS**` reads PASS, and FAIL reads FAIL」, 「the explicit VERDICT line wins over prose」. Restored to f5c5c23 == HEAD. 5. `check-half-states.mjs` (3b, the non-crash reading of leg 3) — the gate narrowed to `unread`/`undefined` only, so BEFORE is no longer quiet. `--self-test` exit 1 with ONE named ✗ case out of 5066: 「H43 row: ⛔ BEFORE the hand-off, nobody asked is NOT a half state — quiet」 (it got the finding sentence, wanted null); every DUE case stayed green, so the mutation moved exactly the predicate the card asks for. Restored to f5c5c23 == HEAD; `git status --porcelain` empty after every leg. </details> ## Acceptance notes - `AGENTS.md` (Tier H, outside this dispatch's file list and not edited here) still says in 〈Multi-agent working discipline〉 「the PR's assignee mirrors the card's, set by the executor at pr_create」 — contradicted by os-dev.md L37 after this PR. One sentence to retire; it needs the maintainer's hand on a Tier H file. carrier: the seat (`domain:skills#2`) files it or hands it to triage; noted here, not filed by the dev. - Card 26617 is untouched and stays `pm:on-hold`: its shape 1 (the approver request moves off `pr_create`) is implemented here; triage decides its disposition after landing. - PRs already in flight with a person assigned are not unassigned here (card 27363 item 6). - The claude.ai project-harness step itself is outside this repo; only the thread line (dispatch-runbook.md L140) tells a thread not to perform it. - In-file adjacency edited: H69's header and sentence in `check-half-states.mjs` claimed the relay summons at `pr_create`; this PR makes that false, so the two spots (and the one self-test pin on the words) now describe the hand-off. No row semantics changed for H69. - `latestContractReviewOnHead` now returns `verdict` beside `id` and `sha` (additive; `record-recognisers.mjs` does not import it). - This PR is the first to follow the rule it writes: its `pr_create` carried no `assignees` while os-dev.md L37 on `main` still said to send one — the seat ruled the omission for this PR on both claims. - Not run locally: `test:repo` (CI's `Test Core`), the lint sweep, dogfood (no `!` in the title, no `(narrowing)` arm); every CI family is read from the PR's check-runs by the seat. - No `.github/workflows/**` line was needed; no new gate, script or workflow. ## Verification Local subset = the derived union, run on the final head `50118ffc` (`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`, no paths, change set from the merge base `28872e68`; 11 paths, +461/−199 lines, under the 3000-line threshold). 67 families, every exit captured before any pipe (`cmd > log 2>&1; status=$?`), reconciled with `--ran`: **67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN** (`✓ dispatch-gates --ran: 67 derived famil(ies) accounted for`). One family first answered exit 3 (`check:doc-formula-expressions`, PREREQUISITE NOT MET — its `dist/` inputs were not built in this worktree); after `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` under the shared verify lock (`VERDICT command-exit 0 · held the lock 2s · waited 0s`, a full cache replay) it was re-run and answered exit 0. Non-zero exits remaining in the record: 0. <details><summary>The 67 commands and their exits (the `--ran` record)</summary> ```text node scripts/check-closing-keyword-parity.mjs :: exit 0 node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 node scripts/check-comment-mask-corpus.mjs :: exit 0 node scripts/check-declaration-mirrors.mjs :: exit 0 node scripts/check-declaration-mirrors.mjs --self-test :: exit 0 node scripts/check-issue-citations.mjs :: exit 0 node scripts/check-platform-checklist-watchdog.mjs :: exit 0 node scripts/check-platform-checklist-watchdog.mjs --self-test :: exit 0 node scripts/check-release-section-coverage.mjs :: exit 0 node scripts/check-release-section-coverage.mjs --strict :: exit 0 node scripts/check-self-test-wired.mjs :: exit 0 node scripts/check-self-test-wired.mjs --self-test :: exit 0 node scripts/check-self-test-workflow-commands.mjs :: exit 0 node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0 node scripts/check-whole-set-label-write.mjs :: exit 0 node scripts/check-whole-set-label-write.mjs --self-test :: exit 0 node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0 node scripts/ci/scheduled-full-run.mjs --self-test :: exit 0 node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0 node scripts/pm/board-snapshot.mjs --self-test :: exit 0 node scripts/pm/check-governed-queue-guard.mjs --self-test :: exit 0 node scripts/pm/check-harness-current.mjs --self-test :: exit 0 node scripts/pm/sweep-closed-cards.mjs --self-test :: exit 0 node scripts/render-release-coverage-anchor.mjs --self-test :: exit 0 pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 pnpm check:agent-model-declared :: exit 0 pnpm check:agent-test-spelling :: exit 0 pnpm check:bash32-floor :: exit 0 pnpm check:ci-filter-parity :: exit 0 pnpm check:cli-command-ids :: exit 0 pnpm check:closing-target-claim :: exit 0 pnpm check:commit-card-trailers :: exit 0 pnpm check:cross-package-test-inputs :: exit 0 pnpm check:doc-authoring :: exit 0 pnpm check:driver-memory-census :: exit 0 pnpm check:entry-guard :: exit 0 pnpm check:gitlink-declared :: exit 0 pnpm check:issue-citations :: exit 0 pnpm check:nul-bytes :: exit 0 pnpm check:parse-guard :: exit 0 pnpm check:partof-closing-keyword :: exit 0 pnpm check:platform-checklist :: exit 0 pnpm check:pm-close-cards :: exit 0 pnpm check:pm-dispatch-gates :: exit 0 pnpm check:pm-expected-skips :: exit 0 pnpm check:pm-fleet-write-dispatch :: exit 0 pnpm check:pm-fleet-write-execute :: exit 0 pnpm check:pm-fleet-write-validate :: exit 0 pnpm check:pm-governed-merges :: exit 0 pnpm check:pm-governed-prose :: exit 0 pnpm check:pm-half-states :: exit 0 pnpm check:pm-issue-create :: exit 0 pnpm check:pm-issue-transfer :: exit 0 pnpm check:pm-label-write :: exit 0 pnpm check:pm-post-stamped :: exit 0 pnpm check:pm-record-recognisers :: exit 0 pnpm check:pm-skill-id-lint :: exit 0 pnpm check:pm-skill-ratchet :: exit 0 pnpm check:pm-write-pace :: exit 0 pnpm check:pnpm-filter-targets :: exit 0 pnpm check:pnpm-flag-spellings :: exit 0 pnpm check:ratchet-remedy-authority :: exit 0 pnpm check:refd-timer-probe :: exit 0 pnpm check:scripts-symbol-anchors :: exit 0 pnpm check:single-claim-paths :: exit 0 pnpm check:skill-frame-sync :: exit 0 pnpm check:watch-hint-literal :: exit 0 ``` </details> Local-only readings (CI runs their `--self-test` only): `check:pm-skill-ratchet` — every ceilinged file at its landed count (SKILL.md 319/319 with the widest-row pin 341 B untouched; os-dev.md 402/402; execution-duties 188/188; contract-review 60/60; landing-operations 101/101; director 86/86; dispatch-runbook 245/245), every edited line ≤120 B; `check:pm-skill-id-lint` 105 files clean; `check:nul-bytes` clean over 22172 files; `check:dev-prereqs` / `check:skill-frame-freshness` not applicable (no `packages/spec` or four-axis frame edit; the frame's md5 at L242–262 is unchanged, `abff5f852c8fd09b79ec0623439aa4f0`). CI families (`Lint & Repo Gates`, `TypeScript Type Check`, `Test Core` incl. `test:repo`, `Governed Surface Queue Guard`, the UI four) are read from this PR's check-runs by the seat; nothing of them was re-run locally beyond the derived subset above. This PR's own open through the relay carried no `assignees` key; the stroke's `--json` read-back (assignees and requested reviewers as the platform lists them) is quoted in the os-dev report comment on card 27345. --- _Generated by [Claude Code](https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg)_ --------- Co-authored-by: objectstack-fleet[bot] <noreply@anthropic.com>
1 parent 9f57dcc commit c5d4634

11 files changed

Lines changed: 461 additions & 199 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ model: opus
3434
- 同批 agents 共用一个 scratchpad 目录,自然命名的文件会被彼此静默覆盖。
3535
2. **卡 assignee 归 PM。** 派发原子对已把它设好;共享身份下该字段答不了是谁。
3636
- 你的身份位是认领评论里的分支;仓 CLAUDE.md 的 claim-first 已由 PM 的认领满足。
37-
- 恒不写卡的 assignee(空也开工,报 `summary`);PR assignee = 卡的:`pr_create` 带 `assignees: [LOGIN]`。
37+
- 恒不写卡的 assignee(空也开工,报 `summary`);PR ⛔ 不带 `assignees`,人经席位交棒才见 PR。
3838
- 发现与他人在途工作重复,停下报 `blocked`。
3939
- PR 上不是你设置的状态属于另一个 actor:⛔ 永不去纠正;疑问进报告,挡住报 blocked。
4040
- 回退他人的操作(尤其 ready 翻转)永不轮到你;把意外写进 `summary`。
@@ -57,7 +57,7 @@ model: opus
5757
- 写工具自读所需变量;⛔ 永不打印环境变量的值,转录是 AGENTS.md 禁落令牌的日志行。
5858
- 拼法不限于 `env`、`printenv`、`set`、`export -p`、`echo $VAR`、`cat /proc/*/environ`。
5959
- 判存在只用不印值形式 `[ -n "${X+x}" ] && echo set`;已印出 ⇒ `deviations` 只点名变量名。
60-
- 写预算三笔:`git push`、`pr_create`(draft,含 assignee 与 labels)、`os-dev-report` 评论。
60+
- 写预算三笔:`git push`、`pr_create`(draft,含 labels、⛔ 无 assignees)、`os-dev-report` 评论。
6161
- 卡与线程只走 payload 档(公开仓单卡网页内嵌 JSON,拼写住 platform-readings)或单卡 REST 读。
6262
- 三类发现进报告交席位代立,不 `POST /issues`、⛔ 不静默弃报;PM 去重读数当既有事实用。
6363
- PR 正文 dev 只写一次,在开 PR 那一笔,⛔ 不 `PATCH`;事后要改的报告点名改法,席位代写。

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,10 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
195195
- PR 上的标签 = 待维护者审阅,不入六态;与请审同为等人批清单,随获批或撤回判决离开。
196196
- 批准判定单源 = 队列守卫常量 `GOVERNED_APPROVERS`:授权账户 APPROVED 即算,⛔ 不卡 `commit_id`。
197197
- 批准后再推亦不过期;席位落地 = 过落地前检、清标、ready、auto-merge,踢出/变基同法。
198-
- ③ 中继 `pr_create`/`pr_ready` 命中 Tier H 即向 `GOVERNED_APPROVERS` 中未请/派/审者请审。
199-
- 作者是审批人 ⇒ 指派它、请其余(请它必 422),否则请全员;速读只点非作者审批人去批。
200-
- 脱中继开的 PR 无 run 行:交速读前席位恒自读 `requested_reviewers`/`assignees`,⛔ 不只看 run 行。
201-
- 缺口经中继 `pr_request_reviewers`/`assign` 补,⛔ 不碰 draft 位;ACCEPT 与轮报点名脱中继作者。
198+
- ③ 请审 = 席位交棒:ACCEPT 与现 head 同形 PASS 俱在案后,中继 `pr_request_reviewers` 请审批人。
199+
- 作者是审批人 ⇒ `assign` 它、请其余(请它必 422);⛔ 永不派/请席位自身账号;Tier S 不交人。
200+
- `pr_create` 不请不派;`pr_ready` 只补交棒漏;PASS 后 head 移 ⇒ 回等复核;脱中继 PR 自读请/派。
201+
- 速读「需要你做的」求批点名 PASS 评论 id+`Head-sha`;无 PASS ⇒ 写 contract review owed 不求批。
202202
- ④ 轮次报告单列 awaiting a human merge。
203203
- skills 车道自有 PR:纯代码面如 `scripts/pm/` 由本席按达档自审(清单不减)后落地。
204204
- 受管面两层:Tier S = `.claude/**` 全树,余皆 Tier H 等人批;S 经达档复核 PASS 后 ready → 入队。

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,26 @@
3131
独立性对、PASS/FAIL。
3232
- 同形含首行 `Served-tier:`:值写该面所定档的常量名 `CONTRACT_REVIEW_TIER` 或 `TIER_DEFAULT`;
3333
无此行不成裁决;模板 `node scripts/pm/record-recognisers.mjs --template`,申报面加 `--face declaration`。
34-
- 同形另带 `Local-runs:` 行:`none`,或 `probe — REASON` 具名唯一本地探针;
35-
有行必校,缺行旧记录不改判。
34+
- 同形带 `Local-runs:` 行:`none` 或 `probe — REASON` 具名唯一探针;有行必校,缺行旧记录不改判。
3635
- ① derived judgments 逐项:diff 引出的接受集与公开面变化逐条点名判对错。
3736
- ② semver 定级与 changeset 声明一致;③ 边界旗:dev 挂旗与 `open_questions` 逐旗答复或升级。
3837
- ④ 设计判断欠 schema、governed 规则文本、收窄三面,spec、skills、ADR 皆已在内 ⛔ 不另立面:
3938
逐 `hits` 文件判改动对所引代码与验收场景是否成立,ADR 另判首个消费者与执行计划;
4039
被引代码读而不审;①–④ 合称完整复核,余面同形无 ④,⛔ 无第二条记录。
4140
- 实质 head 各欠一轮完整复核;只落发现的 commit 由同一复核者 delta 复核;无 must-fix 即止。
4241
- 另记作者:PR `user.login` 非 `objectstack-fleet[bot]` ⇒ ③ 注点名该 login(脱中继写),落地前读。
43-
- 简报从 `node scripts/pm/record-recognisers.mjs --brief-template` 起稿:
44-
只读条款与输入集内建,⛔ 不删 ⛔ 行。
42+
- 简报从 `record-recognisers.mjs --brief-template` 起稿:只读条款与输入集内建,⛔ 不删 ⛔ 行。
4543
- 隔离复核子代理暂存全写按所审 PR 命名的 `<scratchpad>/pr-<n>/`,⛔ 不读非本轮自写的暂存。
4644
- 独立性对:`Implemented-by:`/`Reviewed-by:` 取值同见 `--template`;子代理记采纳它的席位。
4745
- ④ 恒由起草者之外的 agent 达档跑,起草已达档不免;喂入同上,⛔ 不喂起草者的结论。
4846
- 轮次报告设复审清单专节,与呈裁清单同为强制审计。
49-
- 落地前检两条,过则 Tier S 入队、Tier H 等人批:① 达档条款②复核 PASS 在案(同形记录)。
47+
- 请审/求批与落地前检两条,过则 Tier S 入队、Tier H 等人批:① 现 head 同形达档 PASS 在案。
5048
- 例外:纯重生成或只动上列散文面的 head 后移原记录继续管;判据机读已提交树;
5149
PR 落 `Regen-provenance:` 行。
5250
- ② PR check 全绿,⛔ 非 required 子集;例外:merge-base 同签名的红不计、按设计而红见 SKILL.md。
5351
- 签名 = 失败步 + 首错行,读 base check runs 的 API ⛔ 不凭口述;主干红止血立单不变。
52+
- 落地时仍欠复核的 PR 在落地 head 复审,车道席或分诊按 (a)(b)(c) 接;FAIL ⛔ 不修已关 PR。
53+
- 每条 must-fix 引该记录立新卡、按发现定级;回退仅限主干红(p0,main-red 约定①)或安全边界。
5454

5555
## 等复核标记 `needs:contract-review`
5656

‎.claude/skills/pm-dispatch/references/dispatch-runbook.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,11 @@
133133
- 披露纪律卡(私密细节不得离开席位会话)也留席内,认领写明;卡线程照计 `batch`。
134134
- 项目的 coordinator 跨席位统一调度卡线程;每席一个线程跑 PM 循环,卡线程即 dev。
135135
- 席位随时把候选卡交 coordinator,附优先级、派发令全文与建议 effort,⛔ 不等自己的槽位。
136-
- coordinator 按优先级开线程,p1 先;全项目上限由维护者按项目定(`coordinator.md`),满即排队。
137136
- 卡线程交回即释放槽位,席位当即告知 coordinator;审核期开着不占槽,REWORK 补丁轮再占一槽。
138137
- 档位与 effort 席位自推导 ⛔ 不等维护者原话:`--tier` 过路径,MANDATORY 即绑;effort 按难度。
139138
- 派发令写两者与推导(`--tier` 行或难度读数),协调者照令开线程;常设原话有则作 `reason:`。
140139
- 席位留认领文本/派发令/契约复核/ACCEPT/落地;线程实施、开 draft PR、驱动 CI 与可合并。
140+
- 线程 ⛔ 不做 harness 开 PR 后指派/请审:「审核通过才会推送给我审核」,请审是席位交棒。
141141
- 派发令由 coordinator 写进线程开场消息,`Writes:` 行逐字在内,⛔ 不落共享目录;卡上留指针。
142142
- coordinator 开线程即读线程分支交席位(读不到则线程自报);⛔ 线程不认领、不写 assignee。
143143
- 席位写 assignee+`pm:dispatched`+带该 `Branch:` 的认领;线程核对最新认领指向本分支方开工。

‎.claude/skills/pm-dispatch/references/execution-duties.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
## 认领(先认领后动工)
6161

6262
- 归属 = session ID,⛔ 不认作者字段;`Account:` 派生自 assignee,不等即半态、持卡席下笔补正。
63-
- 卡 assignee 归 PM,dev 恒不写;PR assignee = 卡的,接管 ② 同笔换;读者 `is:pr is:open assignee:LOGIN`。
63+
- 卡 assignee 归 PM,dev 恒不写;PR ⛔ 不派席位账号;在飞 PR 读 `head:claude/` 开 PR 正文点名的卡。
6464
- 部分落地(PR 带 `Refs #N (item k)`,⛔ 不 `Fixes`)即释放:合入同笔回 `pm:queue` + 清 assignee。
6565
- 同笔 `Release:` 行点名已落项与余项;余项整树归他席 ⇒ 点名该席改标,拆分加 `pm:retriage`。
6666
- 派发前按序执行原子对:① Assign @me,并把 `pm:dispatched` 与摘 `pm:queue` 放进同一次标签写入。

‎.claude/skills/pm-dispatch/references/landing-operations.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
- 路径肢 = diff 触及契约面 `packages/spec/src/**` 非测试,含 error-code-ledger、`*.zod.ts` 契约 schema。
1010
- 声明肢 = 认领评论声明 `Clause-②: yes`,与路径无关;错误的 `no` 是可审计的假申报。
1111
- 子代理起不来 ⇒ 复核缺席,PR 带 `needs:contract-review` 留 draft 队列外;旁路仅维护者逐次亲审
12-
- PASS ⇒ ready、auto-merge;FAIL ⇒ 补丁轮;⛔ 免复核不放行。
12+
- PASS ⇒ Tier S ready、auto-merge;Tier H 经 SKILL.md ③ 交棒请审;FAIL ⇒ 补丁轮;⛔ 免复核不放行。
13+
- 落地后才见欠复核 ⇒ 按 `contract-review.md` 复审落地 head、发现立新卡,⛔ 不修已关 PR。
1314
- DELIBERATE CORRECTION 红(`check-empty-changeset`)⛔ 不等维护者;确认件皆须点名每个被改 note:
1415
- diff 只改 release 文字或注释者:派发席 ACCEPT 确认,逐句引改前与改后,免第二次同 head 复核。
1516
- 其余(含改代码)照全套:同 head 达档复核 PASS 记录即确认,记录逐句判改写句。
@@ -51,7 +52,6 @@
5152
- undraft 撞 429 ⇒ 落地入等 `resets at` 态:该刻记卡,到点一次重试;⛔ 不报阻塞、不自定节奏。
5253
- 落地遭分类器拒 ⇒ 停手、报维护者、卡上记命令与拒因;⛔ 不换拼法、不退回 ccr 绕过。
5354
- 落地评论 = 两个读数的探针表 + 一行状态变更(摘标/关卡/收口),⛔ 不复述 `## 席位核对`。
54-
- 契约复核 PASS 落地的 PR 到窗口时已 ready 且 auto-merge 在挂,见 `contract-review.md`。
5555
- 转 ready/入队前跑 `check-governed-merges.mjs --pr N`:受管面照两层;>3000 行(含生成物)照 Tier H。
5656
- ⛔ 两层不由席位批准;清标即落地同受此闸,漏判会被队列守卫在 merge group 里拒收。
5757
- 再读 `mergeable_state`:`dirty` ⇒ 先 merge `origin/main` 再挂;生成物在面上按 A 的固定序。

‎.claude/skills/pm-dispatch/references/lanes/director.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
- 入箱勤务:校验/补全四棱块、速读与 `Prior rulings on this card:` 行;入箱同笔现读前提。
5555
- 线程有 `Ruling:`/RULED 的卡再入箱,该行逐 id 各一句变化;缺行 ⇒ 拒入,`pm:retriage` 回立卡者。
5656
- 一次只开一批:维护者对批 N 回字(一字即可)后,新到才合成批 N+1;续批至清零才收工。
57-
- 受管 PR 待人批前核四件:席位记录、维护者速读、中继 `pr_request_reviewers` 请审、绿 head。
57+
- 受管 PR 待人批前核五件:席位记录、速读、现 head PASS、`pr_request_reviewers` 请审、绿 head。
5858
- 缺件即补;⛔ 不入批、不求聊天「同意」;批准与合并恒是维护者的点击,⛔ 不代。
5959
- 呈报前逐卡逐仓重跑 `git grep -n -iE 'TERMS' origin/main -- AGENTS.md docs/adr packages/spec/src`。
6060
- 以协议为准:消费面对齐协议 ⇒ 荐对齐呈批,协议没有的能力荐删;⛔ 不自裁。

0 commit comments

Comments
 (0)