Skip to content

Commit 1f6bc5a

Browse files
pm-dispatch(main-red): knock the seats whose PRs were held for main to turn green (#29941)
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} --> _Requested by **Yibo Wang** · [project thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwBUyArWn6eHL33NNgvdpkwiW)_ Fixes #29445 ## 维护者速读 - **改了什么:** 车道因 main 红停放的 PR 在正文写一行 `Waits-on: main-red #n`;锚卡关闭时分诊(缺则总监)找出所有带这行的 open PR,逐个敲其席位信箱新键 `Notify: main-green · anchor #n · PR #m`;收到的席位合 main、删这行、照 §C 继续落地。 - **为什么改:** 您的原话:「这个应该立卡写入 skills:如果到时候发现有哪个 PR 确实因为这次红被挡住(比如有车道把 PR 停下来等 main 绿),我会敲对应车道的邮箱,让它继续推进。」此前没有任何一步告诉停等的车道可以继续。 - **风险与回滚:** 只改 pm-dispatch 规则文本与信箱门铃词表,无门禁、标签、状态或巡查行;回滚即 revert 本 PR。三份规则文件各抬行数上限 1 行,均引本卡原话为裁决记录。 - **先看:** `scripts/pm/record-recognisers.mjs`(新键一行 + 读取器 + 自测 pin),`references/triage-duties.md`(敲门两行、删一行重复判据),`scripts/pm/check-skill-line-ratchet.mjs`(三处上限各 +1 的注释)。 - **两分钟验证:** `node scripts/pm/record-recognisers.mjs --mailbox-keys | grep -A1 main-green` 应打印新键及其行;`--self-test` 应报 363 cases pass。 - **需要你做的:** 无,席位落地(Tier S:仅 `.claude/**` 与 `scripts/pm/**`)。 Clause-②: no Metadata-protocol: none ## What changes Four edits, one PR, as the card's Change 1–4 ask: 1. **Mark the hold** — `references/landing-operations.md` §C: the release-condition line now reads "依赖 PR 或锚卡修复合入; 因 main 红停放者加行首 `Waits-on: main-red #n`" (folded into the existing line at zero lines; 120 B against the 120-byte cap). 2. **Knock on close** — `references/triage-duties.md`, beside the main-red anchor duties: when an anchor card closes, in the same round triage reads the open PRs whose body carries a line-leading `Waits-on: main-red #n` and rings each one's seat once with `Notify: main-green`; the worked example follows (anchor #N closes ⇒ PRs #a and #b each get one knock; the count goes into the round record; the director takes the duty when triage is absent). 3. **The doorbell key** — `scripts/pm/record-recognisers.mjs`: `MAILBOX_KEYS` gains `Notify: main-green · anchor #n · PR #m` (17 → 18 keys) with its reader (anchor + PR, both in `numbers`); `--mailbox-keys` prints it; `references/project-forms.md` 〈信箱 PR〉 names it in the scenario list, which the self-test pins against the table in both directions. 4. **The receiving seat** — `references/landing-operations.md` §C, one new line: on `Notify: main-green` the seat merges `origin/main` (relay `pr_update_branch`), drops the `Waits-on:` line and resumes as §C's last step says. No new gate, label, state or patrol row. `check-half-states.mjs` H72 reads the table only through `mailboxEvents`, so it needed no change and its self-test passes. ### Line ratchet (`scripts/pm/check-skill-line-ratchet.mjs`) Every file named here sat at its ceiling with every neighbouring line at 113–120 B, so folding bought only Change 1. Deletion paid one line: `triage-duties.md`'s Clause-② boundary test, which `execution-duties.md` already states (its `Clause-②:` line and its narrowing line). The remainder is three ordinary ruled raises of **+1 each**, the ruling of record being the maintainer's verbatim word quoted on #29445 (filing gate ③, a task the maintainer set directly), copied into each CEILINGS row comment: | file | lines before → after | ceiling before → after | paid by | | --- | --- | --- | --- | | `references/landing-operations.md` | 101 → 102 | 101 → 102 | ruled raise +1, recorded under the CROSS_FILE_MOVES destination's `ruledRaises` (the gate still reads the move as +32 against −500) | | `references/triage-duties.md` | 99 → 100 | 99 → 100 | +2 lines, −1 duplicate deleted, ruled raise +1 (this file is a source of the `lanes/director.md` move: that move now reads +15 against −20, still paid) | | `references/project-forms.md` | 58 → 59 | 58 → 59 | ruled raise +1 | `record-recognisers.mjs`: doorbell battery floor 41 → 42, roster pin seventeen → eighteen; the pin refuses the misspelt keys `maingreen`, `main-grean`, `green` and `Request: main-green`, and reads the anchor alone, a bare `#m`, `PR none`, a bare anchor number, a trailing reason and the verbatim template as unreadable. ## Tests - `node scripts/pm/record-recognisers.mjs --self-test` — exit 0, `363 cases pass` (was 362 on the base). - `pnpm check:pm-record-recognisers` (record-recognisers, check-owed-reviews, mailbox-open, fleet-roster self-tests) — exit 0. - `pnpm check:pm-skill-ratchet` — exit 0; prints the landing-operations move as `+32 (69→102, less 1 line of ordinary ruled raise)` and the director move as `+15 (70→86, less 1) against a net source decrease of 20`. - `pnpm check:pm-skill-id-lint` — exit 0, 109 files clean. - `node scripts/pm/check-half-states.mjs --self-test` — exit 0, 5161 cases. - The three families above re-run on the committed head `6be5c8c8` — all exit 0. ## Acceptance notes - `node scripts/pm/record-recognisers.mjs --mailbox-keys` lists `Notify: main-green · anchor #n · PR #m` with its row (sender triage or the director; receiver the seat of each held PR; when the anchor closes). - The worked example is in `triage-duties.md`'s edited text. - Not done here (out of scope, no card filed): nothing mechanical reads `Waits-on:` lines — the knock is a seat's reading of open PR bodies, as the card asks (「这是一个门铃和两行文字」). - Changeset: none — `.claude/**` and `scripts/pm/**` publish nothing; `skip-changeset` declared on the create. ## Verification <details><summary>dispatch-gates: 40 derived, 40 run, 0 NOT-MEASURED (working tree identical to 6be5c8c)</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 40 families for the 5-file diff; every command ran in the worktree with its exit captured before any pipe and reconciled with `--ran`: `40 derived famil(ies) accounted for — 40 run, 0 NOT-MEASURED`. One family, `pnpm --filter @objectstack/lint run check:doc-formula-expressions`, first exited 3 (PREREQUISITE NOT MET: `@objectstack/formula` and `@objectstack/lint` not built); after `pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` it exited 0, and that reading is the one reconciled. </details> Base: `origin/main` at `21510bba` — unchanged since the branch was cut, so no merge was needed before opening. --- _Generated by [Claude Code](https://claude.ai/code/session_01WGufzjF3PXfVhah6UuSDYG)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2ec4f43 commit 1f6bc5a

5 files changed

Lines changed: 75 additions & 7 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@
8686
## C. 依赖前棒才能转绿的 PR:draft 停放 + 签名级预期红清单
8787

8888
- 这种 PR 停在 draft,正文写精确的预期红清单:逐条失败测试名 + 报错签名。
89-
- 正文同写解除条件:点名所依赖的那张 PR 合入。
89+
- 正文同写解除条件:依赖 PR 或锚卡修复合入;因 main 红停放者加行首 `Waits-on: main-red #n`。
9090
- 每个 CI-failure 事件与清单比对:签名匹配静默跳过,新签名才是真问题。
9191
- 依赖合入后:末轮同步走中继 `pr_update_branch`(`rest-channel.md`)→ 红清零 → 转 ready → 入队。
92+
- 收 `Notify: main-green` 即照上行合 `origin/main`、删 `Waits-on:` 行,续走 §C 落地。
9293

9394
## D. 串行接力:多个已实现 PR 全碰生成物时,一次只放行一个
9495

‎.claude/skills/pm-dispatch/references/project-forms.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
- 车道→复审席或兄弟席同交接行 `Request: contract-review`;反向随记录 `Notify: contract-review`。
4141
- 任一席→分诊:p0 嫌疑、main 红、确定性队列红 `Request: urgent-triage`。
4242
- 立锚卡者→分诊(缺则总监)`Request: main-red`,→破坏 PR 的席与锚卡车道 `Notify: main-red`。
43+
- 锚卡关闭:分诊(缺则总监)→正文带 `Waits-on: main-red #n` 的每张 open PR 之席 `Notify: main-green`。
4344
- 车道→分诊问卡去留路由定级 `Request: triage`;反向 p0/p1 发版阻塞定入 `Notify: release-blocker`。
4445
- 移卡入队者→车道:p0/p1 `Blocked-by` 关闭 `Notify: unblocked`;记裁决席→被改席 `Notify: ruling`。
4546
- 席→兄弟席或他车道:认领文件面相交或须先落 `Notify: serial`,先落者落地 `Notify: landed`。

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
- 每轮读上份轮次记录 fire 以来全部 main push、schedule 与队列结论,⛔ 不只读最新一跑。
2424
- 窗内无锚红当轮立锚卡、照首触定级,转绿照立并点名承修卡;逾 90 分钟无记录记明断档。
2525
- main-red 锚卡由席位先立先派,首触事后补作记录级:可改域,⛔ 不改动作,在飞照补。
26+
- 锚卡关闭同轮:读正文行首 `Waits-on: main-red #n` 的 open PR,一 PR 一敲其席 `Notify: main-green`。
27+
- 例:锚 #N 关 ⇒ 带 `Waits-on: main-red #N` 的 PR #a、#b 各一敲;计数进轮次记录;缺分诊归总监。
2628
- 主干全量红与确定性队列红首触定 p0(锚卡、根因卡、full-run 卡);flake 锚卡判确定性才升。
2729
- 车道席自分诊:本车道卡挡自有在飞(认领卡/PR/落地/拆分链)且证据清楚,方可首触定 p1/p2。
2830
- 证据 = 卡上引具名失败 check/run、复现读数或 pin 测试;记录照分诊格式贴卡,请分诊复审。
@@ -93,7 +95,6 @@
9395
- 例外一:`platform-readings.md` 增量抬上限到落地行数,免决策卡,记 `ruledRaises` 引常设裁决。
9496
- 例外二:AGENTS.md 报告态翻转,须①不删门不跳测;②同笔附两红 run 入下批待决;③否即翻回。
9597
- 条件:席位验收评论逐条核实、去重计数(候选/落地/已有/拒收)、一事一行、不计重排。
96-
- 机械边界测试(条款②判据):改动扩大接受集或公开面 ⇒ 是;拉回已声明契约 ⇒ 否。
9798
- 回翻条款:实施中发现契约终究要动 ⇒ dev 停手,卡回决策箱,⛔ 永不静默重裁。
9899
- 请示纪律:方向性授权覆盖整条执行链一并做完,⛔ 不逐项回问。
99100
- 推送维护者只照 `lanes/triage.md` 推送清单;中间状态与限流/重试细节只进座位贴和触发器。

‎scripts/pm/check-skill-line-ratchet.mjs‎

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,17 @@ export const CEILINGS = new Map([
12251225
// verbatim out of SKILL.md, whose ceiling fell 819 → 319 in the same PR; +32
12261226
// against a net source decrease of 500. Landed count, headroom 0, same
12271227
// convention.
1228-
['.claude/skills/pm-dispatch/references/landing-operations.md', 101],
1228+
// Raised 101 → 102 by the main-green doorbell — an ORDINARY raise on a
1229+
// CROSS_FILE_MOVES destination, recorded under that entry's `ruledRaises`
1230+
// below, ⛔ not a second move. The text is §C's resume line: a seat that
1231+
// receives `Notify: main-green` merges `origin/main` through the relay's
1232+
// `pr_update_branch`, drops its `Waits-on:` line and resumes landing as §C's
1233+
// last step says; the hold line itself (`Waits-on: main-red #n`) folded into
1234+
// §C's existing release-condition line at zero lines. Ruling of record: the
1235+
// main-red resume card (#29445, filing gate ③, a task the maintainer set
1236+
// directly), maintainer verbatim and untranslated: 「这个应该立卡写入 skills:如果到时候发现有哪个 PR 确实因为这次红被挡住(比如有车道把 PR 停下来等 main 绿),我会敲对应车道的邮箱,让它继续推进。」
1237+
// Measured delta +1 (101 → 102); landed count, headroom 0.
1238+
['.claude/skills/pm-dispatch/references/landing-operations.md', 102],
12291239
// Release-aftercare duties — what a lane PM still owes AFTER a tagged release
12301240
// rolls to production, which the landing window (ends at MERGED) never
12311241
// covered: post-roll placement/latency reading with the waker-bias re-draw
@@ -1362,7 +1372,20 @@ export const CEILINGS = new Map([
13621372
// 94-95 each merged after deleting what contract-review.md and AGENTS.md
13631373
// already state, and the reporting pair 101-102 replaced by one pointer to the
13641374
// push list in lanes/triage.md. Landed count, headroom 0, same convention.
1365-
['.claude/skills/pm-dispatch/references/triage-duties.md', 99],
1375+
// Raised 99 → 100 by the main-green doorbell — an ORDINARY raise, ⛔ not a
1376+
// cross-file move. The text is two lines beside the main-red anchor duties:
1377+
// when an anchor card closes, triage (the director when triage is absent)
1378+
// reads the open PRs whose body carries a line-leading `Waits-on: main-red
1379+
// #n`, rings each one's seat once with `Notify: main-green` in the same
1380+
// round and counts them in the round record, with the worked example (anchor
1381+
// #N closes ⇒ PRs #a and #b each get one knock). One line was paid by
1382+
// deleting the Clause-② boundary test that execution-duties.md already states
1383+
// (its `Clause-②` line and its narrowing line), so the net is +1. Ruling of
1384+
// record: the main-red resume card (#29445, filing gate ③, a task the
1385+
// maintainer set directly), maintainer verbatim and untranslated:
1386+
// 「这个应该立卡写入 skills:如果到时候发现有哪个 PR 确实因为这次红被挡住(比如有车道把 PR 停下来等 main 绿),我会敲对应车道的邮箱,让它继续推进。」
1387+
// Measured delta +1 (99 → 100); landed count, headroom 0.
1388+
['.claude/skills/pm-dispatch/references/triage-duties.md', 100],
13661389
// execution-duties.md, raised 183 → 185 by the split-off-card ruling — an
13671390
// ORDINARY raise, ⛔ not a cross-file move (card #23579). The text is two rule
13681391
// lines beside the derived-sub-issue rules in 〈候选与批次〉: a queued card found
@@ -1470,7 +1493,18 @@ export const CEILINGS = new Map([
14701493
// 6595244387 (the rate) and 6595840476. The key row and the record/rate
14711494
// line are the two lines the ruling orders; the 不敲 line was rewritten in
14721495
// place. Measured delta +2 (56 → 58 lines); landed count, headroom 0.
1473-
['.claude/skills/pm-dispatch/references/project-forms.md', 58],
1496+
// Raised 58 → 59 by the main-green doorbell — an ORDINARY raise, ⛔ not a
1497+
// cross-file move. The text is one 〈信箱 PR〉 scenario row: when a main-red
1498+
// anchor card closes, triage (the director when triage is absent) rings the
1499+
// seat of every open PR whose body carries `Waits-on: main-red #n` with
1500+
// `Notify: main-green`; the key's full spelling lives in
1501+
// `record-recognisers.mjs` MAILBOX_KEYS, which the self-test pins against this
1502+
// section both ways, so the row cannot be folded into a neighbour (each sits
1503+
// at 113–120 B against the 120-byte cap). Ruling of record: the main-red
1504+
// resume card (#29445, filing gate ③, a task the maintainer set directly),
1505+
// maintainer verbatim and untranslated: 「这个应该立卡写入 skills:如果到时候发现有哪个 PR 确实因为这次红被挡住(比如有车道把 PR 停下来等 main 绿),我会敲对应车道的邮箱,让它继续推进。」
1506+
// Measured delta +1 (58 → 59); landed count, headroom 0.
1507+
['.claude/skills/pm-dispatch/references/project-forms.md', 59],
14741508
// The app-vs-platform boundary — the deciding question (could this be written
14751509
// from the metadata alone, with no knowledge of this company?), the publication
14761510
// test (one consumer is a use, two is a contract) and the two anti-patterns.
@@ -2289,6 +2323,17 @@ export const CROSS_FILE_MOVES = new Map([
22892323
ruling: '入队与落地 consolidation into landing-operations.md under the principle-only cut of SKILL.md, authorised by #14685 item 5 (comment 5520452691)',
22902324
was: 69,
22912325
sources: [['.claude/skills/pm-dispatch/SKILL.md', 819]],
2326+
ruledRaises: [
2327+
{
2328+
// Quoted beside this entry's ceiling above. Copied from there, not paraphrased.
2329+
ruling:
2330+
'the main-green resume line on `.claude/skills/pm-dispatch/references/landing-operations.md` §C'
2331+
+ ' — the main-red resume card (#29445, filing gate ③, a task the maintainer set directly),'
2332+
+ ' maintainer verbatim and untranslated: 「这个应该立卡写入 skills:如果到时候发现有哪个 PR 确实因为这次红被挡住(比如有车道把 PR 停下来等 main 绿),我会敲对应车道的邮箱,让它继续推进。」',
2333+
date: '2026-11-03',
2334+
delta: 1,
2335+
},
2336+
],
22922337
},
22932338
],
22942339
// The thin triage seat (maintainer's word 2026-10-23, verbatim and

0 commit comments

Comments
 (0)