Repository navigation
Commit 04a3148
pm-dispatch: one seat record per governed PR; the card keeps a pointer; the landing comment is the probe table; the director ledger is one block per summon (#23422)
Fixes #23381
Clause-②: no
Text-only charter change on four pm-dispatch files, under the
maintainer's 「同意」 (2026-10-14, chat) on the director seat's proposal,
quoted verbatim on the card: 「席位产物合并。ACCEPT 和速读终稿合成 PR
上一条记录,卡上只留指针;落地记录保持探针表;台账只在每场收工写一块。」 and 「立卡你决定,不需要我同意」. Dispatched by
the `domain:skills` seat (claim comment 6163070718); the dev leaves no
claim of its own. Base `b5b1bf7277` = `origin/main` at dispatch; head
`a19252d363`.
Cards named here with no closing verb beside them: #23379 and #23380
(landed as b5b1bf7 and 5656c56 — out of scope here), #23352,
#23389, #23396, #23405 (in flight; their files are not touched here),
#23414 (landed — out of scope here).
## 维护者速读(草稿)
**改了什么**:席位在每张受管 PR 上只写一条记录。Tier H 的 PR 把五段「维护者速读」放在最上面,下面紧跟 `##
席位核对`(形态 / 前提实测 / 门禁 check-runs / 接受的偏差 / 范围外去向 / 落地条款);Tier S 的 PR 只有
`## 席位核对`。卡上只留一行指针,指向 PR 上那条评论。落地时卡上的评论只剩两个读数的探针表加一行状态变更,不再复述
ACCEPT。总监席的摘要台账每场收工写一块,不再每落地一张写一块。四个文件、十五行改动,没有代码、脚本或门禁改动。
**为什么改**:您在 2026-10-14 同意了总监席的方案 6。今天每张卡落地要留五到六段席位散文(认领、dev 报告、卡上的
ACCEPT、PR 上的速读终稿、落地记录、台账块),ACCEPT 的内容在终稿和台账里各被复述一遍。您只读 PR
上的速读;席位需要的是门禁并集、偏差和落地条款,不是散文。合成一条记录后,您读的东西不变,席位少写三段,卡上少一段大评论。
**风险与代价(含回滚)**:机器读的东西一样没动——合并队列守卫和落地前检读的是 PR 上的 `## Contract review`
记录,不是席位的 ACCEPT 段落(`record-recognisers.mjs` 的自测把席位 ACCEPT 段落钉为「不是记录」,本
PR 的 head 上该自测 312 例全过)。代价是三处本 PR 不能碰的旧句子会过时(`execution-duties.md:179`
的「issue 英文短评论」,两个脚本里打印的「ACCEPT on the card」补救文案),已在下方 Acceptance notes
点名,由持有那些文件的在飞 PR 承接。另有一个未实测的平台读数:`platform-readings.md:426` 记的「ACCEPT
照过」没有说明是在卡上还是 PR 上测的,而新形态把 ACCEPT 写到 PR 线程——首次落地时席位需要实测一次。回滚 = revert
这一个 commit,四个文件回到 `b5b1bf7277` 的字节。
**席位意见**:(留空,由席位填写)
**你要做的(一个动作)**:读完速读后,若同意,批准(或直接合并)这张 draft PR;`.claude/**` 按登记表是 Tier
S,席位会按 `check-governed-merges.mjs --pr` 的读数走对应的落地路。
## What changed, line by line
Every edited or deleted line, before and after. Line numbers are the
file's at `b5b1bf7277` (before) and at `a19252d363` (after). Placeholder
note: the file spells the comment-id placeholder in angle brackets
(`comment` followed by `id` in angle brackets); it is written as
`comment ID` below because GitHub strips the angle-bracket form from
bodies.
### `.claude/skills/pm-dispatch/SKILL.md` 〈路径分叉〉 — 319 → 319 lines
The dispatch named the surface as L187–193; on `b5b1bf7277` the ① line
is L188 (L187 is the 3000-line (`改动 over 3000 行`) rule, untouched). Six
lines (L188–193) became seven (L188–194); the seventh is paid by
deleting old L202, the queued pull-back line, whose content is AGENTS.md
Prime Directive #14 「Already armed or queued when you read this? Disable
auto-merge AND convert it back to draft … ask the maintainer at once to
remove a queued PR by hand — then confirm from the remote …」 (plus
`references/platform-readings.md:44` 「出队按队列 ref 阳性探针答不在队向」). AGENTS.md
outranks this skill, so nothing is lost.
Before (L188–193):
```text
- ① 复核结论照常写在 issue 上;技能面 hunk 须由契约复审档的席复核,档外席先交 skills 席。
- ② PR 留给维护者看得见地悬着;终局两条:人工直合即审核记录;授权批准 ⇒ 席位落地。
- 看得见 = ACCEPT 同笔挂 `needs-user-decision` + 贴终稿「维护者速读」评论;①仍是审核记录。
- 速读五段固定:改了什么/为什么改/风险与代价(含回滚)/席位意见/你要做的(一个动作)。
- 草稿归 dev:受管面 PR 正文带 `## 维护者速读(草稿)`,中文、业务角度,席位意见留空。
- 终稿 = 席位对照自己读的 diff 校正草稿、填席位意见后贴评论;维护者只读评论。
```
After (L188–194; the 速读五段 and 草稿归 dev lines are byte-identical):
```text
- ① 席位记录一条落 PR,两层同欠:Tier H 置顶速读五段,其下 `## 席位核对`;卡只留指针行。
- ② PR 悬着等人批,同笔挂 `needs-user-decision`;人工直合即审核记录,授权批准 ⇒ 席位落地。
- 指针 `ACCEPT → PR #n comment ID`;技能面 hunk 须由契约复审档的席复核,档外席先交 skills 席。
- 核对六项(席位读此):形态/前提实测/门禁 check-runs/接受的偏差/范围外去向/落地条款。
- 速读五段固定:改了什么/为什么改/风险与代价(含回滚)/席位意见/你要做的(一个动作)。
- 草稿归 dev:受管面 PR 正文带 `## 维护者速读(草稿)`,中文、业务角度,席位意见留空。
- 终稿 = 席位对照自己读的 diff 校正草稿、填席位意见,置顶席位记录;维护者只读评论。
```
Deleted (old L202), paid for the seventh line above:
```text
- 已入队 ⇒ 转 draft 并 disable,即请维护者手动出队(席位无实测手段);出队以阳性探针答。
```
What each change carries: ① is the merged record (change 1 of the card)
— one seat record on the PR, owed by both tiers, 速读 on top for Tier H,
`## 席位核对` below, the card keeps a pointer line. ② keeps its two
terminals and absorbs the label clause that the deleted 看得见 line carried
(`needs-user-decision` is applied in the same stroke as the record). The
指针 line spells the pointer and keeps ①'s second clause (skills-face
hunks are reviewed at the contract-review tier; an off-tier seat hands
to the skills seat) unchanged. The 核对六项 line names the six items of `##
席位核对` and says seats read that section. The 终稿 line now places the
corrected 速读 at the top of the seat record instead of a separate
comment. Dropped without a home needed: 「复核结论照常写在 issue 上」 (no longer
true), 「贴终稿「维护者速读」评论」 (replaced by the one record), 「①仍是审核记录」 (① now
names the record itself). Untouched by the card's fence: L95, L108, the
four-axis block L241–261 (md5 `abff5f852c8fd09b79ec0623439aa4f0` before
and after).
### `.claude/skills/pm-dispatch/references/landing-operations.md` — 101
→ 101 lines
Inserted after L55 (「确认 MERGED 要两个读数:每轮同时读队列分支与 `origin/main`。」), change
2 of the card:
```text
- 落地评论 = 两个读数的探针表 + 一行状态变更(摘标/关卡/收口),⛔ 不复述 `## 席位核对`。
```
Deleted (old L57), to pay for it:
```text
- 窗口自身权责不变:跟到 MERGED、踢出处置、落地后对账。
```
Its three duties are each stated in the same file already: 跟到 MERGED —
section B's heading 「跟到 MERGED 为止;入队后的看护归车道 PM 落地窗口」 and L49 「车道 PM
的权责三件:验收(复核清单)、首次入队、确认 MERGED」; 踢出处置 — L27 「红/踢出处置在同一落地窗口内做」; 落地后对账 —
L73 「每次合并后重拉一次车道盘点与预期状态对账,⛔ 不留给下轮巡检」. The rider added no duty the
section lacked. Re-read for truth, unchanged: L3 and L50 (ACCEPT as the
event that opens the window), L15 (the dispatching seat's ACCEPT
confirms a text-only DELIBERATE CORRECTION — a content rule that holds
wherever the ACCEPT is written), L26 (落地记账 on the seat post — the
execution seat's own list; the card's change 3 is the director's summon
ledger, a different ledger).
### `.claude/skills/pm-dispatch/references/lanes/director.md` — 65 → 66
lines (ceiling 72)
Inserted after L36 (「到合并 = 推进到就绪并点名等待,⛔ 不代维护者合并。」) in 职责一, change 3 of
the card:
```text
- 摘要台账每场收工一块,⛔ 不逐落地写块;一次落地的记录 = PR 席位记录 + 落地探针表。
```
It does not restate SKILL.md L236 「一条裁决已记录的权威载体 =
总监席每场收工的摘要台账(卡、权威、方向、状态转移)」 — the four items stay there; this line adds
only the cadence (one block per summon end, never one per landing) and
what a landing's record is.
### `.claude/skills/pm-dispatch/references/seat-lifecycle.md` L33 — 96 →
96 lines
Before:
```text
- 写侧刷新点 = 轮次边界;中途状态由卡上 claim/ACCEPT 评论承载。
```
After:
```text
- 写侧刷新点 = 轮次边界;中途状态由卡上 claim 评论与指针行、PR 上 `## 席位核对` 承载。
```
## Restatement scan
`grep -n 'ACCEPT\|终稿\|速读'` over `.claude/skills/pm-dispatch/**` and
`.claude/agents/os-dev.md` on `a19252d363`. Verdict: still true / stale.
Action: edited here / out of surface, reported.
| file:line | sentence (abridged) | verdict | action |
|:--|:--|:--|:--|
| SKILL.md:86 | index row 「执行席落地窗口(ACCEPT 之后至 MERGED)」 | still true
(ACCEPT as the event) | none |
| SKILL.md:95 | 「中文只留四通道(维护者速读、…)」 | still true | none (fenced out by
the card) |
| SKILL.md:182 | 「**ACCEPT 之后的路径分叉**」 | still true (and the
governed-prose anchor) | none |
| SKILL.md:186 | 「路径面命中 Tier H ⇒ ACCEPT 换终局四件套」 | still true | none |
| SKILL.md:188 / 190 / 194 | ① / 指针 / 终稿 | rewritten | edited here |
| SKILL.md:192 / 193 | 速读五段 / 草稿归 dev | still true | none
(byte-identical) |
| SKILL.md:274 | 「每场召唤把带席内 ACCEPT 的受管草稿呈为一批」 | still true | none |
| SKILL.md:283 | 「ACCEPT 逐条一行 `filed #N`/…」 | still true (content rule)
| none |
| references/contract-review.md:10, :37 | the ACCEPT names the sentences
it checked; the review-wait label is applied at ACCEPT on the PR | still
true | out of surface (PR #23389 holds the file) |
| references/decision-analysis.md:16 | 「…速读住 PR」 | still true (now as
the top of the seat record) | none |
| references/execution-duties.md:179 | 「判决 ACCEPT:issue 英文短评论,核对清单结论 +
抽查读数 + 偏差,链接 PR,⛔ 不复述其叙事。」 | **stale** — for a governed PR the ACCEPT is
now the PR's `## 席位核对`; the card gets a pointer | out of surface (PR
#23389 holds the file), reported below with a replacement sentence |
| references/filing-gate.md:17; triage-duties.md:38, :39, :51;
lanes/director.md:45 | the decision card's 「维护者速读」 | still true (a
different 速读: the decision card's) | none |
| references/landing-operations.md:3, :15, :50 | ACCEPT as the event /
the text-only confirmation | still true | none (re-read, see above) |
| references/platform-readings.md:426 | 「…同会话派发 PR 上 PASS 拒
`[Self-Approval]`,建卡、ACCEPT 照过」 | still true as recorded, but the
reading does not say on which thread the ACCEPT passed | out of surface
(#23377 owns the file), reported below |
| references/review-checklist.md:14, :19, :42, :70, :72, :76, :77 | the
seven ACCEPT sentences | still true — each names the ACCEPT as a verdict
or its content, none its location | none |
| references/seat-lifecycle.md:33 | 「中途状态由卡上 claim/ACCEPT 评论承载」 | was
stale | edited here |
| references/seat-post-protocol.md:38 | 「已 ACCEPT 待队列 PR」 | still true |
none |
| lanes/director.md:35, :50 | 「非受管 code PR 绿加 ACCEPT 即入队落地」 / 「有席内
ACCEPT 者呈一批」 | still true | none |
| lanes/ui.md:38 | 「散文面归 ACCEPT」 | still true | none |
| .claude/agents/os-dev.md:287, :334 | the dev's 速读 draft in the PR
body; a missing report blocks ACCEPT | still true | none |
## Recogniser reading (from the tree, not the card)
- `scripts/pm/record-recognisers.mjs`: `REVIEW_OF_RECORD_THREADS` = the
PR thread and the card thread; `REVIEW_OF_RECORD_LOCATION` derives to
"the PR or its card". `locateReviewOfRecord` accepts only a comment
whose body carries the `## Contract review` heading marker and the head
sha, newest first; its self-test (L1063–1064) builds a seat ACCEPT
paragraph (bold first line, head, `Reviewed-by:`, no heading) and pins
it `absent` — 「a seat's ACCEPT paragraph … is NOT a record」. Nothing
this PR changes is read by it.
- `scripts/pm/check-half-states.mjs` H36: `h36AcceptedOrArmed(pr)` is
`pr.draft === false || pr.auto_merge != null` — the PR's ready/armed
state, never ACCEPT text.
- `scripts/pm/check-governed-merges.mjs --pr`: reads the register tier
and the size; its printed remedy says "ACCEPT on the card" (stale prose,
see Acceptance notes), but no reading depends on an ACCEPT comment.
- `node scripts/pm/check-governed-queue-guard.mjs --self-test` on
`a19252d363`: exit 0, 「312 cases pass」.
## Gates (exit codes captured before any pipe; head `a19252d363`)
`node scripts/pm/dispatch-gates.mjs --commands` derived 20 families for
this diff (4 paths, +8/−7). Recorded as `cmd :: exit N` and reconciled
with `--ran`: 「20 derived famil(ies) accounted for — 20 run, 0
NOT-MEASURED」 (exit 0) — see the note on the one family that first
refused.
| command | exit |
|:--|:--|
| `pnpm check:pm-skill-ratchet` | 0 — SKILL.md 319/319,
landing-operations.md 101/101, lanes/director.md 66/72,
seat-lifecycle.md 96/96; every changed line ≤ 120 bytes (max 119) |
| `pnpm check:pm-skill-id-lint` | 0 — 87 files clean |
| `pnpm check:pm-governed-prose` | 0 — both regions name all 7
registered surfaces, claim no others (the 〈路径分叉〉 anchors are intact) |
| `pnpm check:skill-frame-sync` | 0 — the one frame copy coherent;
four-axis block md5 unchanged |
| `pnpm check:nul-bytes` | 0; plus `grep -naP` for C0/DEL bytes over the
four files: no hit |
| `node scripts/pm/check-governed-queue-guard.mjs --self-test` | 0 — 312
cases |
| `node scripts/check-closing-keyword-parity.mjs` and `--self-test` | 0,
0 |
| `node scripts/check-comment-mask-corpus.mjs` | 0 |
| `node scripts/pm/check-harness-current.mjs --self-test` | 0 |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
0 — after the `@objectstack/formula` + `@objectstack/lint` build taken
under `os-verify-lock.sh` (VERDICT command-exit 0); 22 record-scoped
formula examples across 474 files judged clean |
| `pnpm check:agent-test-spelling` | 0 |
| `pnpm check:cross-package-test-inputs` | 0 |
| `pnpm check:doc-authoring` | 0 |
| `pnpm check:driver-memory-census` | 0 |
| `pnpm check:gitlink-declared` | 0 |
| `pnpm check:pm-expected-skips` | 0 |
| `pnpm check:pm-governed-merges` | 0 |
| `pnpm check:refd-timer-probe` | 0 |
| `pnpm check:watch-hint-literal` | 0 |
The first sweep ran before `pnpm install` in the worktree: seven
families answered exit 3 (PREREQUISITE NOT MET, 「Fix: pnpm install」) and
one `ERR_MODULE_NOT_FOUND`; those were not measurements and were re-run
after the install. `check:doc-formula-expressions` then still refused
(「`@objectstack/formula` is not built」), so its build (`turbo run build
--filter=@objectstack/formula --filter=@objectstack/lint`) was taken
under `scripts/pm/os-verify-lock.sh` and the gate re-run. The farm
(`pnpm lint`, `pnpm test`, builds) is CI's: read off this PR's
check-runs. No ablation: text-only diff.
## Acceptance notes
- **Stale out of surface, reported, not edited** —
`references/execution-duties.md:179` 「判决 ACCEPT:issue 英文短评论,核对清单结论 +
抽查读数 + 偏差,链接 PR,⛔ 不复述其叙事。」 goes stale under this card. Replacement
sentence I would write (118 bytes): 「判决 ACCEPT = PR 上 `## 席位核对`
评论:核对清单结论 + 抽查读数 + 偏差,⛔ 不复述其叙事;卡留一行指针。」 — it unifies the location for
every PR. Whether non-governed code PRs' ACCEPT also moves is the one
scope question the ruling's words leave open (they name the ACCEPT and
the 速读终稿 pair); this PR writes SKILL.md's rule for both governed tiers,
as dispatched. Carrier: PR #23389 holds `execution-duties.md`.
- **Stale printed remedies in scripts, out of surface** —
`scripts/pm/check-governed-merges.mjs:220` and `:1865`,
`scripts/pm/check-governed-queue-guard.mjs:1964` print 「ACCEPT on the
card, `needs-user-decision` on the PR, a final 维护者速读」 as the Tier H
terminal. Prose only; no reading depends on it. Carrier: PR #23389 holds
`scripts/pm/**`.
- **Unmeasured platform premise** —
`references/platform-readings.md:426` records that the harness
classifier refuses a PASS on a same-session PR as `[Self-Approval]`
while 「建卡、ACCEPT 照过」, without saying on which thread the passing ACCEPT
was written. The new shape writes the ACCEPT (`## 席位核对`) on the PR
thread, the same thread where the PASS was refused. The seat should take
that reading on the first landing under this rule and record it;
carrier: #23377 (queued) owns `platform-readings.md`.
- **Dispatch line numbers** — the dispatch and claim name SKILL.md
L187–193; on `b5b1bf7277` the ① line is L188 and L187 is the 3000-line
(`改动 over 3000 行`) rule, which is untouched. The deletion that pays for
the seventh line (old L202) is outside L188–193 but inside 〈路径分叉〉 and
inside the same file, as the dispatch's 「paid by a same-file deletion
named with the sentence that restates it」 allows; it is declared here
and in the report's `deviations`.
- **Tier at landing** — the card says Tier H; the register
(`GOVERNED_SURFACES`) carries `.claude/**` as Tier S.
`check-governed-merges.mjs --pr` decides at landing; the PR is a draft
either way.
- **Changeset** — `.claude/**` ships in no package: `skip-changeset`
applied via `label-write.mjs` after the PR opened (see the report for
the write's result).
- **Local verification scope** — the derived families above and the two
self-tests; `pnpm lint` / `pnpm test` / builds are CI's and were not run
locally.
---
_Generated by [Claude
Code](https://claude.ai/code/session_013zGKMG1cRedVzWtqGGGZW9)_
Co-authored-by: objectstack-fleet[bot] <332303061+objectstack-fleet[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>1 parent 4f81f31 commit 04a3148
4 files changed
Lines changed: 8 additions & 7 deletions
File tree
- .claude/skills/pm-dispatch
- references
- lanes
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
185 | 185 | | |
186 | 186 | | |
187 | 187 | | |
188 | | - | |
189 | | - | |
190 | | - | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
191 | 192 | | |
192 | 193 | | |
193 | | - | |
| 194 | + | |
194 | 195 | | |
195 | 196 | | |
196 | 197 | | |
| |||
199 | 200 | | |
200 | 201 | | |
201 | 202 | | |
202 | | - | |
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| 56 | + | |
56 | 57 | | |
57 | | - | |
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
0 commit comments