Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .claude/skills/pm-dispatch/references/dispatch-runbook.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,7 +68,13 @@ branch-early、draft-PR 时点报告、transcript 复活与 worktree 接手协
`fire_trigger` + 用后即 `delete_trigger`);巡检退为兜底心跳,每轮先核订阅已覆盖哪
些面、只补盲区(会话停摆、未开 PR 的分支、姊妹仓动静)。CCR 云会话不注册跨会话消息
roster —— `ListAgents` 列不到、`SendMessage` 直投 not-reachable 是设计而非故障(维
护者 2026-08-11 裁定:事件驱动架构即长期方案),⛔ 不复测 roster 路径。
护者 2026-08-11 裁定:事件驱动架构即长期方案),⛔ 不复测 roster 路径。会话句柄同
时是**账号作用域**的:`get_session` / `archive_session` / 绑会话的 poke 触发器,对
另一个账号建的会话一律答 `not found`,且该回答与「会话从不存在」在响应里不可区分
—— **⛔ 永不把它读作死亡信号**(误判死会招来往可能还活着的 worktree 里塞第二个
agent);实测另一账号读作 `not found` 的会话,其 PM 在数十分钟前刚读到它
RUNNING。跨账号接班时前任的会话三条路都不可达,活性判定只能走 GitHub 上的产出读
数;draft-PR 时点交报的契约正是为此存在 —— 报告落在卡上,无需探活即可收口。

## subagent 批(`mode:subagent`)派发前置:先快进本地检出

Expand Down
7 changes: 7 additions & 0 deletions .claude/skills/pm-dispatch/references/landing-operations.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,6 +45,13 @@ auto-merge 的顺序不可反(转回 draft 会同时掉 auto-merge 与队列成
⛔ 不拆成「下轮巡检再摘」。同刻顺手读一次相关卡的 `closed_by_pull_requests`,确认没
有别的卡被正文里的闭合关键词误关(事实表见平台读数)。

**每次合并后重拉一次车道盘点,与预期状态对账** —— 也是落地动作的一步,⛔ 不留给下
轮巡检:取 open 卡清单,对照「本次合并应关哪些、不应关哪些」的预期 diff 一遍;预期
之外从 open 消失的卡,就是被 PR 正文闭合关键词静默误关的卡(`completed` 状态对一切
只看 open 的过滤与巡检隐身,不主动 diff 永远看不见)。与上一段互补而不互替:
`closed_by_pull_requests` 是逐卡核对、要先知道读哪张;盘点对账不需要先验名单,实测
里抓住静默误关的正是这一步。

**落地窗口给关键 PR 挂 `subscribe_pr_activity`**(会话型座位专用;Routine 座位每
fire 新会话收不到,维持轮询):

Expand Down
28 changes: 27 additions & 1 deletion .claude/skills/pm-dispatch/references/platform-readings.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,6 +20,12 @@
- **PR 转回 draft 会同时掉 auto-merge 与队列成员资格,且不自动恢复**;转正后必须
重新挂。反方向同理:要真踢出队列,只有转 draft —— `disable_pr_auto_merge` 单独
调用**不解除队列成员资格**,PR 照样落地。
- **`enable_pr_auto_merge` 一律显式传 `mergeMethod: "SQUASH"`**:不传时静默退回
被禁的 merge-commit 方式 —— 等于无操作。但**回显在两个方向都不可靠**:实测队列
路径上回显为空(`method: `)而 timeline 的入队事件照发、PR 照落地;也实测显式
传 SQUASH 后回显 `MERGE`(参数被治理 `main` 的合并队列侧改写,落地历史仍是每
PR 一提交)。⇒ 权威信号只有队列成员资格的 timeline 事件与最终 MERGED 状态,
⛔ 不拿回显当任何方向的证据,也不读 `auto_merge` 字段。
- `enable_pr_auto_merge` 的空字段返回(`method: , enabled at `)对「入没入队」零区
分度,签名本身不构成任何方向的证据。序列:① 先验队列分支(给条目 ~20–30s 建
出);② 分支在 ⇒ 结束,⛔ 不翻转;③ 等待后仍缺席**且队列已见 churn**(更新的条
Expand All@@ -32,6 +38,9 @@
件反射式重投。第三种签名:本 PR 名下**没有任何** `merge_group` run 且批次同伴的
run 全部 `success` = 队列重建的连带取消,不是红 —— 带签名读数收据重投一次(收据
留在 PR 上),⛔ 无收据不重投;同一 PR 第二次被踢移交队列管家。
- **实测吞吐参数两则**:合并队列落地延迟 ≈ 每 PR 15–30 分钟且串行 —— 多 PR 在队
时按此估算落地窗口,⛔ 不据「还没落」提前判异常;单容器重验证(build+test)并
发甜点 ≈3 —— 排批时按它定同容器重验证卡的并发上限,再高互相争用、再低闲置。

## API 配额

Expand All@@ -47,6 +56,17 @@
search 的 `label:a label:b`,或本地求交);`issue_write` 的 `labels` 是**整组替
换**不是追加 —— 不先读现值合并再写,会静默剥掉别的标签(状态机丢位);真追加走
REST `POST /issues/{n}/labels`;写后照标签纪律回读。
- **`list_issues` 永不返回 assignees**(`fields` 枚举无此成员;不传 `fields` 响应
里同样没有)—— 已认领卡与空闲卡在响应里逐字节相同,车道清单因此**回答不了**
「哪张能认领」这个它被用来回答的问题,失效完全静默、长得就像成功。清单只是
**候选名单**:每一条在认领前都必须过一次完整 `issue_read`(它才返回
`assignees`),⛔ 不把 `list_issues` 结果当候选集直接认领。
- **MCP `issue_read` 的 body 是 HTML 实体转义过的**(撇号/引号/尖括号成实体),而
comments 原样返回。⇒ MCP 座位做 body 往返(读 → 改 → `issue_write` 整体写回)不
安全:写回的是转义实体,或凭猜反转义 —— 长正文围栏里的箭头等显示编码不可靠逆
转,且同一套工具里无从对账真原文。机器可 grep 的行(`Blocked-by:` 一类)可能因
此落在评论首行而非 body —— 解锁扫描必须连评论一起扫(`in:comments`);确要改写
body,先经 REST 取原始 body 对账再写。

## 读数陷阱

Expand All@@ -59,6 +79,10 @@
- `rerun_failed_jobs` 复用原 run 的提交与合并 ref,不拿新 main 重算 —— 红因是基上
缺一个已合修复时重跑无效,只能推提交(`git merge origin/main`);判别:修复的合
并时间晚于 run 创建时间即是。
- **同一 head 上轻量兄弟 workflow `success` + 重量级载体 `cancelled`,是普通取代
的预期签名,不是选择性失败**:兄弟 run 秒级跑完,载体要 10–15 分钟,新推送的
cancel-in-progress 窗口只罩得住后者。见到它先比对 run 的 `head_sha` 与 PR 当前
head(取代必有新 head),而不是开「为什么只取消了它」的调查。
- **CI 红了先取完整日志归档再下结论**:「completeness check 绿」只断言没有
worker 静默死,≠ 测试通过;并发输出的「相邻」≠「因果」(先查 `turbo.json` 依赖
边);⛔ 不只看 tail。公开发出的诊断被推翻时,更正发在同样公开的位置,据它开的
Expand DownExpand Up@@ -90,7 +114,9 @@
面的否定词** ——「nothing here fixes #N」在合并时照关 #N,而写这句话的动机恰恰是声
明不修;好实践(读了兄弟卡、显式划界)反而制造了失效。安全写法:把号码放在没有关
键词打头的位置 —— `#N is not addressed here` / `out of scope: #N` /
`#N remains open`。
`#N remains open`。实测的解析边界三条:关键词只绑**同一行**的 `#N`;动名词
(closing/fixing)不是关键词,散文里出现不触发;行内反引号里的关键词不触发
(code span 实测不建闭合链接;围栏块未独立实测,按同规则对待但留待复测)。
- **PR body 与 squash commit message 是两个独立解析源**:commit message 只有
`Fixes` 首行、看起来干净,不代表 body 干净 —— 只查 commit 会漏。误关的卡以
`completed` 状态对一切「只看 open」的过滤与巡检隐身,没有任何机械守卫覆盖这条路
Expand Down
17 changes: 17 additions & 0 deletions .claude/skills/pm-dispatch/references/review-checklist.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,15 @@
`Part of #<n>`,否则合并会静默关掉一张正躺在决策箱里的卡,而
`needs-user-decision` 的收件箱过滤只看 open issue —— 卡一关,待裁问题就此无人可
见。翻 ready 之前亲核首行,别只信报告。
-**`Part of` PR 翻 ready 前,再扫一遍正文的闭合关键词形状**:GitHub 的闭合关键词
解析器把 `close/fix/resolve` 及其变位(⛔ 动名词 closing/fixing 不在内)绑定到
**同一行**`#N`,并无视周围全部散文 —— 否定、情态、警告一律被忽略,为**防止**
误关而写的那句(「应当由 PM 另行关某卡」)恰恰就是执行误关的那句。写侧纪律:
⛔ 永不把闭合关键词放在另一张 open 卡编号旁;安全写法是让编号不被关键词打头
(「`#N` is not addressed here」/「out of scope: `#N`」),或把关键词放进反引号
(实测:行内 code span 不触发;围栏未独立实测)。半状态巡查器带一条 report-only
的「`Part of` 与闭合关键词绑定同一编号」矛盾检测,但它只巡开着的 PR —— 翻
ready 前的这一扫是唯一挡在合并前面的人工步骤。
-**`Part of` 收口的卡不会自动关,`pm:dispatched` 必须手工摘**:`Fixes` 卡由
GitHub 关闭时标签随卡一起离开在飞视图;`Part of` 卡合并后仍然开着,标签留在原
地,于是 `label:pm:dispatched is:open` 把一张没有 dev、没有分支、没有任何在飞物
Expand DownExpand Up@@ -37,6 +46,14 @@
`conclusion` 已为 `success`(门禁族跑在其内),⛔ 不因报告写了「本地绿」跳过。收
敛期转红走补丁轮(SendMessage 续派原 dev —— 那是这笔交换已付过的价钱,不是
REWORK 的理由;红着合并才是)。重量级卡可在派发令显式写「本单等 CI」。
-**每个门禁读数先钉到 PR 的当前 head**:先读 PR 的 `head.sha`,再比对 run 的
`head_sha` —— 不一致的 run 是关于一个死提交的读数,绿与红**双向都不入账**:旧
head 的绿会把「新推送未验」读成「消费者干净」,旧 head 的红会把当前 head 已修
掉的缺陷重新挂回 PR。
-**被取代 head 上的 run 永不重跑**:非当前 head 上的 `cancelled` 结论零动作 ——
新推送自带全套 run。重跑烧掉一整个重量级周期,还能忠实复现一个已被当前 head 修
掉的缺陷、给绿 PR 挂上假红;实测两次误重跑都源于读到 `cancelled` 没先比对
head。
-**收益穿过必经边界之后还在吗?** 判据(不是每单都做):价值主张依赖某个下游组件
如实转发(HTTP 错误信封、序列化、日志汇聚、跨进程传输)⇒ 至少端到端验一次收益在
边界之后仍然存在 —— 精心写的拒收正文可能被 4xx 直通层整条替换,缺口在清单里不在
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,7 +57,11 @@
任会话 ID、注销时间、队列快照、**热文件串行队**、跨车道备忘);⑤ 审计评论存档
(接任指引:`/pm-dispatch 接手` + 先读座位贴);⑥ `list_triggers` 清点本会话全
部自设定时器,逐个清理**或随移交物转交**(绑着移交中 PR 的定时器随 PR 转交,不
清);⑦ 向维护者交最终报告 —— **不含 SKILL 更新建议清单**(该固定产物已退役,维护
清);⑥ʹ 本座位派出的 dev 会话由**离任 PM 自己**逐个 `archive_session` —— 会话句
柄是账号作用域的,换账号的接任者对它们一律 `not found`(细则见
`dispatch-runbook.md`),归档义务**不可移交**;确须留跑的会话在座位贴里点名、写
明「归档不随交接转移」,⛔ 不把它留在接任者的欠账清单上 —— 那是一条接任者做不到
的待办;⑦ 向维护者交最终报告 —— **不含 SKILL 更新建议清单**(该固定产物已退役,维护
者 2026-08-12 裁定;零建议是好班次)。任期观察只可按三类上报:① 原则错/缺(不变量
级,罕见)→ 经专题通道给 skills 席;② 可机械化项(提议门禁或脚本,⛔ 永不散文)→
正常立卡;③ 平台事实变化 → `references/` 事实表改一行。三类都以 `finding` 入
Expand Down
Loading