Skip to content
Closed
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
64 changes: 32 additions & 32 deletions .claude/skills/pm-dispatch/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -135,9 +135,8 @@ UI 创建并勾 GitHub 连接器、UI 钉模型(会话内 create_trigger 的Rout
证据的零实现停手是好产出,不当返工计)。**裁决明令的动作实施中测出对向事实** ⇒ 照裁决字面执
行、被打断行为的 pin 反转为拒绝 pin(不是删除)、⛔ 同 PR 不做任何 promote/回退、冲突立
成 `needs-user-decision` 卡、该 PR 不挂 auto-merge 留异议窗口。
- **spec 改动的 fixture triage 必须跑消费包测试**(A 包的改动可让 B 包的 fixture 反着断言
,spec 范围内任何 sweep 都看不见)—— 动契约面的派发令点名消费包测试清单,报告要有各消费包真实
读数。
- **spec 改动的 fixture triage 必须跑消费包测试**(A 包的改动可让 B 包的 fixture 反着断言,
spec 内的 sweep 看不见)—— 动契约面的派发令点名消费包测试清单,报告要各消费包真实读数。

## 多仓协调(五条规则)

Expand DownExpand Up@@ -319,17 +318,19 @@ UI 创建并勾 GitHub 连接器、UI 钉模型(会话内 create_trigger 的Rout

### 候选与批次

**整车道一次读全,本地求交**(维护者 2026-08-11 接受):`list_issues` 带 `labels: [domain:X]` +
最小字段一次拿回全车道 open 集,各状态本地求交 —— 按单一 pm 状态切片的查询看不见其它状态,是结
构性盲区。候选 = open、未 assign、无`needs-user-decision`;已排队父单的 open sub-issue 自动是
候选(`pm:epic` 父单的子树除外)。**每张候选读全文 + 全部评论**(裁决落在评论区,跳过评论就是跳
**每轮整车道重读、一次读全,本地求交**(维护者 2026-08-11 接受):`list_issues` 带
`labels: [domain:X]` + 最小字段一次拿回全车道 open 集,各状态本地求交 —— 单一 pm 状态切片的查
询看不见其它状态;⛔ 不拿上轮/检查点清单当派发输入(实测两次漏卡)。候选 = open、未 assign、
无`needs-user-decision`;已排队父单的 open sub-issue 自动是候选(`pm:epic` 父单的子树除外)。**每张候选读全文 + 全部评论**(裁决落在评论区,跳过评论就是跳
过裁决;评论还可能记着一半工作已交付);**派发前做 stale-premise check**(issue 描述的是立单当天
的仓 —— `git log --oneline -20 -- <paths>` 花几分钟,不查则赔一次 agent-run)。

**批次独立性。** 一批内任两单不得可能碰同一个包/registry/barrel/spec schema;拿不准就串行。**同
文件单跨轮硬串行;延后不是搁置**(被延后那一刻就把已知的坑记到该 issue 上)。**维护者明示豁免同
文件串行时,替代纪律四条**(豁免的是排队,不是防撞):① 文件面申报到**区域**级(函数/段落);② 开
PR 前合一次 main;③ 兄弟卡落地后再合一次;④ 冲突交合并队列仲裁,⛔ PM 不手动排序;豁免不外溢。**
文件串行时,替代纪律四条**(豁免的是排队,不是防撞):① 文件面申报到**区域**级(函数/段落),同一
热文件并发编写者设上限;② 开 PR 前合一次 main;③ 兄弟卡落地后再合一次;④ 冲突交合并队列仲裁,
⛔ PM 不手动排序;豁免不外溢,防的是并发**编写者**不防队列里的成品 PR —— 前一 dev 会话一结束即
可派下一张同文件卡,⛔ 不等其 PR 落地。**
阻塞解除后给延后单重新定价**:派发前一单时带必答项「你的改动让 #X 变简单/变难/变得不必要还是无
影响?」,派发后一单前用这个回答重读它的选项与成本,⛔ 不沿用立单时那份(前后单共用同一契约或数
据表示时适用)。
Expand DownExpand Up@@ -411,7 +412,8 @@ dev 侧推分支要早 —— 远程分支是在飞工作最硬的证据。**Sta
- **翻转公开语义的裁决随卡带全仓 pin 清扫**,两句缺一不可(全仓一轮翻完;翻转后的pin 断言新语义
的实质,真非法形状的拒收断言逐字保留 —— 丢第二句就退化成「全仓删光」)。**条件性标准条款命中
判据才抄**:多实现面 ⇒ 共享一致性覆盖;拒收用例 ⇒ `code`+`status` 最低断言;过滤/谓词语
义 ⇒ 编译面清单逐面申报(⛔ 静默略过)。
义 ⇒ 编译面清单逐面申报(⛔ 静默略过);测试进 type-check 债包 ⇒ 点名
`check:type-check-debt`(债包 `pnpm typecheck` 结构性全绿)。
- **Premise-first 写明**:issue 正文是线索不是规格;`premise_still_valid: false` +无 PR 是合法
且常常有价值的交付 —— 派发词预设 issue 为真,就把好运行变成表面抗命。

Expand All@@ -424,11 +426,12 @@ Model tiering 显式传参);S 级但不机械(判断面在设计不在门禁)按

**云卡四课**(细则见 `references/dispatch-runbook.md`;一次性云卡用 `create_session`,⛔ 不用
create_trigger+fire —— 维护者 2026-08-07 拍板,trigger 流只留给定时/重复型):① 授权面随
source 不随环境;② 派发词必带**自驱条款**;③ 交付通道 = dev 自开 draft PR + 终报以 issue 评论
交付;④ **云卡 draft PR 一存在立即 `subscribe_pr_activity` —— 硬步骤**。云会话 `SendMessage`
not-reachable 是设计非故障(维护者 2026-08-11 裁定),⛔ 不复测。**接手中断的 dev**:先试
SendMessage 复活,resume 不可用才走接手协议 —— ⛔ 不重跑原派发词;worktree 不新建;逐 hunk 读
既有工作再决定;验证完整重跑;assignee/认领评论/分支全不动(既有认领的延续,不是新认领)。
source 不随环境,且 **push 授权 ≠ GitHub API 可达** —— App 未接通的 org 里 dev 推得了分支、开
不了 PR 读不了 issue:完整令随 prompt 携带 + 发布失败回落条款,回落协议见 runbook;② 派发词必
带**自驱条款**;③ 交付通道 = dev 自开 draft PR + 终报以 issue 评论交付;④ **云卡 draft PR 一
存在立即 `subscribe_pr_activity` —— 硬步骤**。云会话 `SendMessage` not-reachable 是设计非故障
(维护者 2026-08-11 裁定),⛔ 不复测。**接手中断的 dev**:先试 SendMessage 复活,不可用才走接手
协议(四条增量见 runbook;既有认领的延续不是新认领,⛔ 不重跑原派发词)。

### 收集

Expand All@@ -453,15 +456,14 @@ SendMessage 复活,resume 不可用才走接手协议 —— ⛔ 不重跑原派

**失报与停摆的处置(细则见 `references/dispatch-runbook.md`)。** 三条原则:

- **停摆永不自愈**:携带任务中途状态的完成通知本身就是停摆信号,立刻 SendMessage 附前台执行姿
态句,⛔ 不等任何静默阈值(阈值是给「没有回答」的);复位走梯度,每次比上一次更具体,第三次停摆
判 unreliable 按接手协议重派。这里是消费侧兜底,⛔ 不能写成「派发词写全了就可以不探」。
- **停摆永不自愈**:携带任务中途状态的完成通知就是停摆信号,立刻 SendMessage 附前台执行姿态句
,⛔ 不等静默阈值(阈值是给「没有回答」的);复位走梯度、逐次更具体,第三次停摆判 unreliable 按
接手协议重派。这里是消费侧兜底,⛔ 不能写成「派发词写全了就可以不探」。
- **通知重放先算身份再读内容**:去重三元组 `(issue, 分支, PR head sha)`,与已验收那份相同 ⇒ 记
「重放」即结束,⛔ 不重新验收不重复 ACCEPT;⛔ 到达不读作「还活着」,不到达也不读作「已死」。
- **直接验收兜底(报告丢失 ≠ 验收停摆)**:(a) draft PR 在且 CI 全绿 + (b) 探活确认已死
或 ≥2h 无推送 + (c) 报告未达 ⇒ 直接按 PR 验收(逐文件核对 diff 与申报文件面,对
照 `origin/main` 复核前提与验证叙述,复核判据不减);先探活后翻 ready。舰队级死因(全账号断粮)
下取 (a)+(c) 照常收口,PR body 就是报告。
或 ≥2h 无推送 + (c) 报告未达 ⇒ 直接按 PR 验收(复核判据不减,细则见 runbook);先探活后翻
ready;舰队级死因(全账号断粮)下取 (a)+(c) 照常收口,PR body 就是报告。

### 复核

Expand DownExpand Up@@ -499,10 +501,9 @@ You are the reviewer of record —— **对 GitHub 核验,不对报告的自述
**入队与落地(细则见 `references/landing-operations.md`,落地窗口查阅)。** 原则:

- **碰生成物的 PR,入队前先同步 + 整体重生成** —— os-regen 驱动会零冲突标记地**静默丢掉一侧改
动**,只有重生成才暴露;四步序已机械化(`bash scripts/pm/os-regen-merge.sh`:**先 commit
merge 再重生成**,顺序防锚点静默倒退与`gen:openapi` 假红两个陷阱);重生成后断言兄弟单条目与
上一单**实现体**仍在;清单当场读 `grep os-regen .gitattributes` ⛔ 不抄进派发令当常量;⛔ 禁
止为凑相等手改锚点文件,⛔ 不得要求 `baseRev == merge-base`(允许滞后)。
动**,只有重生成才暴露;四步序已机械化(`bash scripts/pm/os-regen-merge.sh`,**先 commit
merge 再重生成**,顺序陷阱见 landing-operations);重生成后断言兄弟单条目与上一单**实现体**仍
在;清单当场读 `grep os-regen .gitattributes` ⛔ 不抄进派发令当常量;⛔ 禁止为凑相等手改锚点。
- **跟到 MERGED 为止;入队后的看护归队列管家。** 车道 PM 管验收、首次入队(ACCEPT 后挂 6–9 分
钟 flip 定点核门禁 job 结论,绿即转 ready + 挂 auto-merge —— CI success webhook 不可靠,
⛔ 不坐等不忙轮询)、确认 MERGED(两个读数);落地窗口给关键 PR 挂`subscribe_pr_activity`(
Expand DownExpand Up@@ -562,13 +563,12 @@ blockers**(三仓 `target:<major>`之和,归零 = 三张板都空)。
是否应该设置一个1小时的定时以监测时间窗口已经解锁」)。检测读数、盲区与恢复 playbook 细则
见 `references/platform-readings.md`;常驻原则:

- **检测**:`ccusage blocks` 给窗口边界与燃烧率,但只有单容器视野、估成本不估套餐余量(没有任何
面向 agent 的接口暴露账号级剩余额度);**权威的墙信号是失败本身**——撞墙报文里的重置时刻在那
一刻可得、事前查不到,把它记下来。
- **跨墙定时器**:拿到重置时刻 ⇒ 一发定点(reset + 缓冲)优先;没有 ⇒ 挂每小时cron Routine,⛔ **
不用 send_later 链** —— send_later 是 run-once、fire 后自禁用(平台文档),投进死窗口的那一发
是否被重试未实测且文档未承诺,按保守设计一次性链条可能断在它存在的意义上;第一枪成功
的 fire 跑恢复后**删除 cron**(幸存 cron 是孤儿定时器)。fired 文本照定时器写法纪律。
- **检测**:`ccusage blocks` 给窗口边界与燃烧率,但单容器视野、估成本不估套餐余量;**权威的墙
信号是失败本身** —— 撞墙报文里的重置时刻在那一刻可得、事前查不到,把它记下来。
- **跨墙定时器**:拿到重置时刻 ⇒ 一发定点(reset + 缓冲)优先;没有 ⇒ 挂每小时 cron Routine,
⛔ **不用 send_later 链**(run-once、fire 后自禁用,一次性链条可能恰好断在断粮窗口里 —— 论证
见事实表);第一枪成功的 fire 跑恢复后**删除 cron**(幸存 cron 是孤儿定时器)。fired 文本照定
时器写法纪律。
- **恢复 playbook 链的是既有规则**:逐个探在飞云卡 → 直接验收兜底或 transcript 复活→ 重挂常规
巡检 → 照常跑轮;draft-PR-early 契约守住时零信息丢失。

Expand Down
38 changes: 38 additions & 0 deletions .claude/skills/pm-dispatch/references/dispatch-runbook.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -38,6 +38,36 @@ branch-early、draft-PR 时点报告、transcript 复活与 worktree 接手协
roster —— `ListAgents` 列不到、`SendMessage` 直投 not-reachable 是设计而非故障(维
护者 2026-08-11 裁定:事件驱动架构即长期方案),⛔ 不复测 roster 路径。

## 云 dev 的 GitHub API 不可达 —— 发布回落协议

**push 授权 ≠ API 可达,两者独立失败**:org 未接通 Claude GitHub App 时,
`create_session` 云 dev 推分支一切正常,而 PR/评论/issue 的每一次 API 调用都被
org 策略拦下。失败**安静且昂贵**:dev 把活干完、发布不出去、停在 need_input 等
人 —— 实测一班六张云卡中五张:分支照推、dev 侧开不出 PR,其中一张在 need_input
空等近两小时;**最早一张(~05:25Z)自己开出了 PR、立了卡,~08:00Z 起的派发全部
403** —— 可达性是**班中翻转**的,不是从未配置,诊断先问「什么时候变的」,不问
「有没有配过」。API 不可达期间,四条硬规则:

- **完整派发令随 prompt 携带;issue 评论照发,但只作公共存档**。「⛔ 不整段粘贴
issue 正文」的前提是 dev 读得到 GitHub —— API 不可达时前提不成立,prompt 是唯
一送达通道(实测 dev 报 comment text unreadable 后原地停摆)。
- **每张云卡派发令带发布失败回落条款**:开不出 PR ⇒ ⛔ 不循环重试、⛔ 不丢弃 ——
完整 PR 正文、完整 `<!-- os-dev-report -->`、本应立的卡的完整文本,全部放进最
后一条会话消息,并写明哪些自己发成功了。
- **PM 代开 PR 时,changeset 从 dev 分支的 diff 读**:`git diff
origin/main...FETCH_HEAD -- .changeset/`;⛔ 不用 `git ls-tree .changeset/ |
head -1` —— 它给的是字母序第一个**存量** changeset,曾对两条不同分支给出一模一
样的无关文本。
- **`get_session` 的状态不是完成度**:`review_ready` / `need_input` 只说明 dev
停了,不说明有东西可复核 —— 分支(`ls-remote`)与 PR 独立核验。

整套回落是 API 不可达期间的代偿,不是长期方案 —— **修复是 org 管理员把 Claude
GitHub App 接到 org 上**,读到本节的维护者优先做接通,不维护绕行。两个边界:①
**存量会话不继承新接通的 App**(实测:接通后长命容器的 API 读写仍 403,报文明说
not enabled for this session;git push 照常)—— 接通后新建的会话才拿到,别拿旧容
器的 403 判「接通没生效」;② 本节在 App 接通期间**休眠不删除** —— 可达性在一班
之内翻转过一次,再见 403 先认这个形状。

## 接手中断的 dev(worktree 接手协议)

先试 SendMessage 复活(从 transcript 带全部上下文恢复),resume 不可用才接手。⛔
Expand DownExpand Up@@ -129,6 +159,14 @@ SendMessage 附执行姿态句(「前台(阻塞)同步执行全部步骤,中途
重验后逐面抄进派发令**(⛔ 不凭记忆),并带:「每一面都必须在 PR 正文有一个结
论:已改 / 本就合规(证据)/ 明确不在范围(理由);⛔ 静默略过 —— 评审把没提到
的面读作漏掉的面」。防的不是做错,是做对了一部分然后以为做完了。
- 往带 type-check DEBT/EXEMPT 台账的包新增/改写测试文件 ⇒ 派发令点名 `pnpm
check:type-check-debt`,并要求**先 build 依赖闭包**(不建则 exit 1 是
missing-module 级联,不是台账读数)—— 这类包把自己的测试排除在 tsconfig 之外
,有的连 `typecheck` 脚本都没有,`pnpm typecheck` 全绿的同时测试层照样漂移
(一班之内三张 PR 撞同一道门)。⛔ 两个反模式一并写进派发令:不许抬台账数字放
行本 PR 自己新增的文件 —— 那是给自己开的许可条;不许 `--lower` 别的包的 ℹ 信
息行。这道门的价钱花得值:实测一张 PR 的三条「类型错误」里两条是真实 API 误用
(必填参数缺失),vitest 永远测不出来。
- **Premise-first 写明**:issue 正文是线索不是规格,先对 origin/main 验前提;
`premise_still_valid: false` + 无 PR 是合法且常常有价值的交付 —— 派发词预设
issue 为真,就把好运行变成表面抗命。
15 changes: 11 additions & 4 deletions .claude/skills/pm-dispatch/references/platform-readings.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,13 +43,20 @@
一气完成);重试对齐整点(REST core 整点重置)优于指数退避,⛔ 绝不忙轮询。
search 与 core 是独立配额,一侧打满另一侧可作退路;REST core 在共享身份下同样
会打满 ——「走 REST」≠「不限量」。
- **MCP 参数两陷阱**:`list_issues` 多标签过滤是 **OR** 不是 AND(要 AND 走 REST
search 的 `label:a label:b`,或本地求交);`issue_write` 的 `labels` 是**整组替
换**不是追加 —— 不先读现值合并再写,会静默剥掉别的标签(状态机丢位);真追加走
REST `POST /issues/{n}/labels`;写后照标签纪律回读。
- **MCP 参数三陷阱**:`list_issues` 多标签过滤是 **OR** 不是 AND,并集的
`totalCount` 读起来与队列深度一模一样,⛔ 不当队列读数 —— 探一个标签、`pm:*` 本
地数(要 AND 走 REST search 的 `label:a label:b`,或本地求交);`issue_write`
的 `labels` 是**整组替换**不是追加 —— 不先读现值合并再写,会静默剥掉别的标签
(状态机丢位);真追加走 REST `POST /issues/{n}/labels`;**新立卡的 labels 同样
会静默丢**,落成无 `pm:*` 的卡对每一张 sweep 都不可见 —— 立卡与改标签同样适用
「写后回读」。

## 读数陷阱

- **已合并的分支被自动删除,⛔ 不能当分支探针的阳性对照**:拿它作对照得到空输出,
读起来像「探针工作正常、只是分支还没出现」,实际什么都没证明。可用的对照要**此
刻确认存在**:`git ls-remote --heads origin 'claude/*' | wc -l`(在飞车队恒
>0),或一个当前 open 的 PR head。
- **读数四坑**:`cd X && cmd` 会短路(路径不存在时命令在当前仓继续执行,产出假读
数)—— 跨仓一律 `git -C <path>`;`git grep -c <pat> | wc -l` 数的是文件数不是命
中数;裸名 grep 被幸存家族当子串命中 —— 退役核验带引号精确名,更硬的判据是查声
Expand Down
Loading