Skip to content

Commit 782fc29

Browse files
os-zhuangclaude
andauthored
docs(pm-dispatch): 探活入例行、报告丢失直接验收、座位行自查等五处协议更新 (#5597)
* docs(pm-dispatch): 探活入例行、报告丢失直接验收、座位行自查等五处协议更新 2026-08-05 实测教训回写(维护者指示): 1. step 6 新增「探活」固定动作:完成通知在宿主进程重启下会静默丢失—— 三个在飞 dev 死亡数小时无任何信号;每轮巡检对无产出的 dev 发状态 询问,「no active task; resumed from transcript」回包即当场复活。 2. step 6 新增「报告丢失直接验收」兜底:PR 全绿 + agent 确认死亡/静默 ≥2h + 报告未达 ⇒ 直接按 PR 对照 origin/main 验收(#5550/#5556 先例)。 3. 座位表协议新增「每轮核对自己的正文行」:协议升级迁移状态可把在任 PM 记成待认领,叠加惰性回收条款即误回收风险(spec 座位当日实例)。 4. worktree 接手协议前置 SendMessage 复活路径(更便宜、保全上下文), 接手协议降为 resume 不可用时的后备。 5. step 7 新增两条评审判据:验收判据本身可被 dev 用测量证伪(#5452 字面 grep 归零判据不成立,改钉配平不变量);tests/docs-only PR 走 skip-changeset 标签且 rerun 无效需新 labeled 事件(#5497/#5502)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D * docs(pm-dispatch): skip-changeset 条目随 #5625 更新 —— 闸门已实时读标签,教训改记为「载荷 vs 现状」通病标本 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8dbd2a8 commit 782fc29

1 file changed

Lines changed: 55 additions & 5 deletions

File tree

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

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ issues that collide on shared files — and「谁来分诊」原本是每个 PM
346346
—— Routine 座位查调度器(`last_fired` / `next_run`),会话座位查它最近一条
347347
产出评论的时间戳,**>24h 无产出即可回收**(编辑该行 + 一条审计评论)。子树/
348348
批次里在飞的认领仍按认领协议由原认领者跟完。
349+
- **每轮巡检核对自己的正文行。** 协议或表格结构升级会迁移状态:2026-08-05
350+
spec 座位的在任 PM(接管时按升级前惯例只发过登记评论)在正文表格化迁移后
351+
被记为「⏳ 待认领 / 前任已收官」—— 而上一条的惰性回收会把这个错位变成
352+
误回收,别的会话也可能照着「待认领」真来接管。自查一行的成本是零;发现
353+
不符,当场改行 + 审计评论,不等冲突发生。这与「从 labels 重建状态」同源:
354+
正文行也是状态,读它、修它,不靠记忆。
349355
- **epic 委托不在座位表登记** —— `pm:epic` 父单正文自带会话与领地,
350356
`label:pm:epic` 即全量索引(见「Epic 子树车道」)。座位表只记常设座位,一件
351357
事只记一处。
@@ -987,8 +993,11 @@ disobedience.
987993

988994
`/compact`, and any host-level interruption of the PM session, kills running
989995
subagents together with their pending tool calls — #4700 and #4775 both died on
990-
the same second. **The agent is not resumable; its worktree, branch and commits
991-
are intact.** Never re-run the original dispatch prompt over that state: a fresh
996+
the same second. **先试 SendMessage 复活,再谈接手**:对已死 agent 发一条消息,
997+
宿主会「从 transcript 恢复」—— 带着它全部上下文接着干,worktree、分支、提交
998+
都还在(2026-08-05 三个死 agent 全部由此复活并各自收尾,见 step 6 探活)。
999+
仅当 resume 不可用(跨会话接手、transcript 丢失)时才走下面的 worktree 接手
1000+
协议。Never re-run the original dispatch prompt over that state: a fresh
9921001
agent that follows it will try to create the worktree that already exists, or
9931002
redo work already committed. Dispatch a **new** agent with these four additions
9941003
instead:
@@ -1093,9 +1102,26 @@ connector grant 只能传递调用会话自身持有的,CCR 平台注入的 gith
10931102

10941103
### 6. Collect
10951104

1096-
**Subagent mode:** wait for the background task notifications — do not poll,
1097-
do not fabricate a pending agent's result. A dev that dies or returns
1098-
malformed output counts as `status: "blocked"` with its raw output attached.
1105+
**Subagent mode:** wait for the background task notifications — do not poll
1106+
for *results*, do not fabricate a pending agent's result. A dev that dies or
1107+
returns malformed output counts as `status: "blocked"` with its raw output
1108+
attached.
1109+
1110+
**探活是每轮巡检的固定动作 —— 完成通知不可靠,它的缺席什么都不证明。**
1111+
下面的停摆纠偏处理「带任务中状态的通知到了」;这一条处理更隐蔽的另一半:
1112+
**通知根本不来**。宿主进程重启会把运行中的 subagent 连同其完成通知一起
1113+
静默杀掉 —— 2026-08-05 实测,五个「在飞」dev 里三个(#5050/#5515/#5483)
1114+
已死数小时,批次视图仍显示 5/5,实际吞吐 2/5,零信号。规程三条:
1115+
1116+
- 每次巡检(定时器唤醒、轮间隙)对**每个已派发且尚无远程分支/PR**
1117+
dev 发一次状态询问(SendMessage,措辞「回一段简报后继续干活」,不改变
1118+
任务);派发后 ~45 分钟无任何远程产出即到探活门槛。
1119+
- 两种回包都有价值:活着 → 拿到进度与阻塞点;**「no active task; resumed
1120+
from transcript」→ agent 生前已死,这次询问本身就是复活** —— 从其
1121+
transcript 带全部上下文恢复,比 worktree 接手协议(step 5)便宜得多,
1122+
优先用它;resume 不可用时才走接手协议。
1123+
- 判据永远取正向证据(远程分支、PR、报告、探活回包),⛔ 绝不把「还没
1124+
收到失败通知」读作「还在跑」。
10991125

11001126
**A stalled subagent is this half's most common failure, and it never
11011127
self-heals.** When a dev stops mid-task reasoning that "a background watcher will
@@ -1142,6 +1168,14 @@ dispatch 由下一轮按同一判据处置(~2h 无报告即 `blocked`),`delete_t
11421168
Routine 的取舍是:凡验证管线可能超过一个 fire 的活,**一开始就走 `mode:cloud`**,
11431169
把恢复权交给下一轮的 GitHub 读数,而不是赌它能在本轮内被唤醒。
11441170

1171+
**报告丢失 ≠ 验收停摆(直接验收兜底)。** dev 的 JSON 报告是证据来源之一,
1172+
不是验收的先决条件 —— 状态模型第一句就是「所有状态在 GitHub」。同时满足
1173+
(a) draft PR 已存在且 CI 全绿、(b) 探活确认 agent 已死或 ≥2h 无任何推送、
1174+
(c) 报告未达 —— 则 PM 直接按 PR 验收:逐文件核对 diff 与认领申报的文件面,
1175+
对照 `origin/main` 复核 PR 正文的前提声明与验证叙述,step 7 其余判据不变
1176+
(2026-08-05 的 #5550/#5556 即此路径落地并合并)。顺序保护:agent 可能还
1177+
活着时**先探活、后翻 ready** —— 抢先翻会与它的收尾推送竞态。
1178+
11451179
### 7. Review each report
11461180

11471181
You are the reviewer of record. For each report, verify against GitHub — not
@@ -1187,6 +1221,22 @@ against the report's own claims:
11871221
correction belongs in the PR/issue comments so the next reader inherits the
11881222
corrected premise, and a wrong premise still sitting in an issue body gets
11891223
its own follow-up issue rather than being silently dropped.
1224+
- **验收判据本身也是前提的一部分,可被 dev 证伪。** #5452 的 issue 把验收写成
1225+
「某条字面 grep 归零」,dev 实测证明该 pattern 修前修后命中数不变(修好的
1226+
正确输出同样匹配它),于是改钉真不变量(行内代码跨度花括号配平)做门禁,
1227+
并因此多抓出 2 处 issue 的 grep 天然看不见的同根因缺陷。评审姿势:dev
1228+
测量推翻字面判据、换上等价或更强的不变量门禁 = 好运行,照 ACCEPT;但推翻
1229+
过程必须写在 PR 正文里,且新判据要附在 main 语料上的实测信噪比(误报为零
1230+
的证据),否则按 REWORK 要证据。
1231+
- **Tests/docs-only PR 走 `skip-changeset` 标签,不走空 changeset**(空
1232+
changeset 滞留发布,#4898)。标签由 PM 在验收时打。历史坑(#5497/#5502
1233+
实测):该闸曾从**事件载荷**读标签,rerun 重放旧载荷看不见新标签,得靠
1234+
「摘掉再打回」制造新 labeled 事件 —— **#5625(#5580)已根治**,闸门改为
1235+
实时读 PR 标签,rerun 即翻绿。留此一条是因为它是一类通病的标本:**任何
1236+
从事件载荷而非现状读判据的闸,rerun 都复现旧世界** —— 撞上同形状的红,
1237+
先查该闸读的是载荷还是现状,再决定是补事件还是改闸。
1238+
边界:改动若含读者可见的生成产物(如参考文档),dev 选 changeset 而非
1239+
标签是对的 —— 以 PR 正文说明的理由为准,两条路都有效,别来回改。
11901240
- **`+0/-0` in a PR diff is not proof of an empty file.** git renders a file
11911241
as binary — zero added, zero removed — as soon as it contains a NUL byte.
11921242
#4870's 347-line test file showed `+0/-0` and was briefly misread as an

0 commit comments

Comments
 (0)