dispatch-pipeline

star 0

三段式调度 SOP(主 agent 不写代码、全程委派 subagent)。触发——用户提了写代码需求(新功能 / 修 bug / 改 UI / 重构 / 加 feature / 加测试等会落地 Edit/Write/NotebookEdit 的任务);主 agent 检测到代码需求后第一步就 Skill 加载本 SOP,再调度 planner → 用户拍板 → generator → executor → PASS/FAIL(FAIL 自动重调 generator 最多 3 次)。含并行模式 2B/3B/3C/5、§8/§9 写权限边界、失败循环 4A/4B、review-fix 子循环、文档同步收尾。不触发——纯问答 / 解释代码 / 找文件 / 查状态 / 改 meta 配置(rule、memory、hook、settings)/ 用户明确 bypass(你直接改 / 跳过 planner)。

LuoYangcan By LuoYangcan schedule Updated 6/10/2026

name: dispatch-pipeline description: 三段式调度 SOP(主 agent 不写代码、全程委派 subagent)。触发——用户提了写代码需求(新功能 / 修 bug / 改 UI / 重构 / 加 feature / 加测试等会落地 Edit/Write/NotebookEdit 的任务);主 agent 检测到代码需求后第一步就 Skill 加载本 SOP,再调度 planner → 用户拍板 → generator → executor → PASS/FAIL(FAIL 自动重调 generator 最多 3 次)。含并行模式 2B/3B/3C/5、§8/§9 写权限边界、失败循环 4A/4B、review-fix 子循环、文档同步收尾。不触发——纯问答 / 解释代码 / 找文件 / 查状态 / 改 meta 配置(rule、memory、hook、settings)/ 用户明确 bypass(你直接改 / 跳过 planner)。

三段式调度(主 agent 不写代码)

收到写代码需求时(新功能 / 修 bug / 改 UI / 重构 / 加 feature 等会落地 Edit / Write / NotebookEdit 的任务),主 agent 不亲自落地。唯一动作是调度 Agent 工具下三个 subagent

用户需求
  ↓
主 agent: 判断 + 建 worktree(如需要)
  ↓
[planner subagent] —— 独立 context、写 .specs/<slug>.md
  ↓
主 agent: 把 spec 路径告诉用户、AskUserQuestion 问「是否开始实现」
  ↓ 用户拍板「开始」
[generator subagent] —— 独立 context、按 spec 写代码 + 跑编译
  ↓
主 agent: 报告 generator 结果 + AskUserQuestion 问「下一步」
  ↓ 用户拍板「进 executor」(或先「起模拟器看一下」→ 主 agent simctl install/launch → 再 AskUserQuestion)
[executor subagent] —— 独立 context、跑硬验收(spec/build/lint/AMD/UI/硬约束)
  ↓ verdict==PASS
[executor 内嵌 Step 6.5] —— PASS 后跑一次外部 reviewer subagent(Opus 4.8 extended thinking,~5-10 分钟)
  ↓
主 agent: 报告 verdict==PASS + 展示 review 报告摘要 + AskUserQuestion 问「review 怎么处理」
  ↓
[review-fix 子循环(按需)] —— 用户挑修 → generator 按 Step 2.1 append AMD 再修 + 自己跑编译 → 直接进 P4(不再跑 executor,省 token)
  ↓
主 agent: AskUserQuestion 问「是否总结+更新文档」 → 按用户选择执行 → 等下一步指令

verdict==FAIL 路径(本session 内部 generator 实现):主 agent 把 issues 整理给 generator 重写(最多 3 次)
verdict==FAIL 路径(外部 generator 实现):主 agent 停下 AskUserQuestion 让用户选「内部 generator(Claude) / Codex / 暂停」(阶段 4A,不自动重调)
3 次都失败 → 报给用户拍板

并行模式扩展:spec 第 2 节并行分组里有多个 parallel-N 组时,阶段 2 / 3 走「并行模式」—— 见下方 2B / 3B / 3C / 阶段 5 子节。串行模式(只有 serial 组 / 写「全部串行」)按上图原流程跑。判别由 planner 在 spec 里标注、用户在阶段 1 末尾审 spec 时拍板,主 agent 自己判断是否并行。

🔁 review 在并行模式下的处理:3B 各组 executor 都传 run_review_subagent: false(单组不跑 review);review 只在 3C 合并 + 阶段 5 最终 executor 跑一次。

触发

满足任一条件即按本 rule 走:

  • 用户提了写代码需求(含修 bug / 改 UI / 重构 / 加 feature / 加测试)
  • 用户的需求会落地 Edit / Write / NotebookEdit

不触发(主 agent 仍按默认行为做):

  • 纯问答 / 解释代码 / 找文件 / 查状态
  • 改 rule / 改 memory / 改 hook / 改 settings.json(这些是 meta 配置,主 agent 自己改)
  • 改 spec 文件本身(这是 planner 的活,主 agent 直接调 planner,不走 generator)
  • /openpr / /review / /pr-review 等 slash command 内部流程
  • 用户明确说「这个简单的你直接改」「跳过 planner」「不用 executor」—— 必须用户显式说才能跳;主 agent 不能自己判断「这个简单」

Codex 工具映射(Desktop / CLI)

Codex(Desktop / CLI)里没有字面量 Skill(...) / Agent(...) / AskUserQuestion 工具时,按下面映射执行,不把工具名差异当作跳过 pipeline 的理由:

  • Skill(dispatch-pipeline):Read 本 SKILL.md 全文;后续按本 SOP 执行。
  • Agent({ subagent_type: "<role>", prompt: "..." }):优先用当前会话已暴露的 subagent 工具;若有 multi_agent_v1.spawn_agent 就调 multi_agent_v1.spawn_agent({ agent_type: "<role>", message: "..." });若工具尚未加载且有 tool_search,先搜 multi-agent 再调。<role>planner / generator / executor / ui-reviewer
  • run_in_background: true / 并行 Agent:同一轮发起多个 spawn_agent;需要结果时用 multi_agent_v1.wait_agent 等待。
  • AskUserQuestion:若有 request_user_input / AskUserQuestion 等用户输入工具就用;否则在主对话直接停下问用户,等明确回复后再进入下一阶段。
  • 写代码请求命中本 skill 时,视作用户已显式授权本 pipeline 使用 planner / generator / executor delegation;除非用户明确 bypass(「你直接改」「跳过 planner」「不用 executor」)。
  • 无任何等价 subagent 工具时:不要主 agent 自己写代码;报告「当前 Codex 会话没有 multi-agent/subagent 工具」,让用户选择直接改 / 暂停 / 换可用会话。

主 agent 的具体调度动作

阶段 0: 前置

  • 收到需求 → 判断是否新话题 → 如需要按 ~/.claude/rules/use-worktree.md 建 worktree
  • 已经在 worktree 里 → 跳过

阶段 1: 调 planner

Agent({
  description: "<需求一句话> — 规划 spec",
  subagent_type: "planner",
  prompt: """
    用户原始需求(原话):
    <贴用户原话>

    Worktree slug: <当前 slug>
    Worktree 绝对路径: <pwd>

    按 ~/.claude/agents/planner.md 的 SOP 工作,最终产出 .specs/<slug>.md。
  """
})

planner 返回后:

  1. Read 一下 .specs/<slug>.md 自己看一眼(确认 planner 没写空 / 没写错路径)
  2. 外部 URL 一致性 grep 自检(防 planner 瞎填 file id 类错误):扫主索引 §4 / §1 里出现的所有 https://... URL(重点:figma.com / notion.so / linear.app / docs.google.com 等用户参考资料)、对每条 URL 取file id 段(如 figma 的 /design/<fileKey>/、notion 的 /page-<id> 末段、linear 的 <team>-<num>),跑:
    for fid in $FILE_IDS; do grep -q "$fid" <用户原始 prompt 文本/对话日志>; done
    
    任何 file id 在用户原话中不存在 → 立即报给用户「spec §4 出现了你没给过的 URL/ID <X>,可能是 planner 瞎填,要不要让 planner 修?」,给 AskUserQuestion 选项「调 planner 修 / 我自己 Edit 改 / 保留(确实是合理的衍生)」。这一步是 B+C 防呆机制的 C 环节(planner 端 figma get_metadata 验证是 B 环节)。注意:用户原话里只有 URL 时按 file id 段精确匹配;只有提到产品 / 项目名时不算(不要把 "某产品名" 当作 URL 验证依据)
  3. spec 文件路径 + planner 返回的关键摘要 + planner 返回的 decisions 四子段摘要(直接转述 planner 给的「自作主张 / 存疑 / 隐含偏差 / 借鉴 pattern」各一句话,空段标「无」;不要只甩路径,让用户当场就能看到 planner 做了哪些判断)+ .specs/<slug>/decisions.md 路径(附在摘要后,供用户 Read 全文核对)展示给用户
  4. 用 AskUserQuestion 停下问,至少给这几个选项:
    • 开始实现(调 generator)
    • 我先看 spec,等我说开始
    • 改 spec / 改方向(重新调 planner)
    • 不用 generator,我自己改 / 跳过

硬约束

planner 返回后,主 agent 的下一个 tool call 只能是以下之一:

  • Read(读 spec 自检)
  • AskUserQuestion(向用户拍板)
  • Bash(只读命令,如 git status 看 worktree 状态)

绝对不能Agent(subagent_type="generator")。哪怕 spec 看起来无懈可击、用户原始需求看起来已经 ready-to-code,也不准自动进入阶段 2。

用户回复必须是明确同意词才能调 generator:「开始 / 开 / ok 开始 / 干 / go / 实现吧 / 没问题开始」之类。

用户回复模糊(「嗯」「让我看看」「先放着」「再想想」)→ 继续等,不要把模糊回复脑补成同意。

阶段 1.5: 用户决策后必须调 planner 同步 spec(强制闸口)

硬约束:用户对 spec 给出实质决策后,该决策必须由 planner 写进 spec 文件,且在主 agent 进入下一步之前完成(下一步 = 调 generator / 交接外部 generator / 起模拟器 / 收尾 / 等下一条指令)。绝不允许只用自然语言回一句「明白」就略过落 spec。

顺序:决策先聊清楚、再落 spec——不要抢在回复用户前盲目同步一个半成品决策。判断决策是否「聊清楚」:用户给了明确、可执行、无歧义的内容(不是反问 / 模糊 / 还在比选项)。聊清楚的当轮就落 spec,别拖到忘。

⚠️ 「落 spec」与「谁写代码」解耦:用户选「我自己改 / 用外部 generator / 跳过 generator」只改变实现归属,不豁免决策内容落 spec。外部 generator 唯一的需求输入就是 spec —— 你不调内部 generator,反而让落 spec 更必须、不是更不必须。这条岔路上最容易漏,每次走到它都要回头确认决策内容已进 spec(§1-6 / §9 AMD)。

触发(任一即触发):

  • 用户回复明确同意词(「开始 / 开 / ok 开始 / 干 / go / 实现吧 / 没问题开始」)→ planner 把"用户已确认 spec、授权进入实现阶段"追加到更新日志
  • 用户回复「改 spec / 改方向 / 加 / 减 X」→ planner 落地调整(这本来就要调 planner)
  • 用户回复「不用 generator,我自己改 / 用外部 generator / 跳过」→ planner 把"用户决定跳过内部 generator 阶段"追加到更新日志,记下范围。注意:若同一轮里用户还夹带了实质决策内容(如「不需要标题」「改成 X」),那条决策内容也要一并落 spec(§1-6 或 §9 AMD)——别因为用户说了「我自己改」就连决策内容一起漏掉。这是历史上反复漏的点。

不触发

  • 用户回复模糊(「嗯」「让我看看」「先放着」「再想想」)→ 继续等用户进一步指令,不调 planner
  • 用户回复「我先看 spec,等我说开始」→ 等用户后续给实质决策再调

调 planner 同步的 prompt 模板:

Agent({
  description: "<需求一句话> — 同步用户决策",
  subagent_type: "planner",
  model: <见下方「模型选择」表>,
  prompt: """
    场景:用户决策同步(dispatch-pipeline 阶段 1.5)

    Worktree slug: <slug>
    Worktree 绝对路径: <pwd>
    Spec 文件绝对路径: <pwd>/.specs/<slug>.md

    用户在 AskUserQuestion 里挑的选项:<原选项标签>
    用户回复原话:<贴用户原话>
    决策含义(主 agent 摘要的一句话):<例:用户确认 spec、授权进入实现阶段 / 用户要求把 X 加进硬约束 / 用户决定跳过 generator>

    按 ~/.claude/agents/planner.md 的"二次调用:用户决策同步"场景 SOP 工作。
  """
})

模型选择model 参数 override planner.md frontmatter 默认 opus):

用户回复类型 model
简单确认词(「开始 / 开 / ok 开始 / 干 / go / 实现吧 / 没问题开始 / 没问题 / 没意见」) haiku
append AMD(机械转写指令成 §9 子文件 + 轻量判断是否撞 §1-6) sonnet
真·实质决策(改硬约束 / 改 scope / 拆任务 / 改测试用例 / 「跳过 generator」/ 带具体内容的指令) 不传(默认 opus)

拿不准 → 不传(走 opus)。

planner 同步完返回后,主 agent 再次 Read 一遍 .specs/<slug>.md 确认改动落地,然后才进入下一步(阶段 2 调 generator / 等用户进一步指令 / 其他分支)。

自检 checklist(每次准备调 generator 前过一遍)

  • 我的上一个 tool call 是 planner 返回?→ 如果是,下一步绝不能直接调 generator
  • 我向用户展示了 spec 路径 + 摘要?
  • 我用 AskUserQuestion 问过用户「是否开始实现」?
  • 用户给了明确同意词?(不是「嗯」「ok」之外的模糊词)
  • 我已经在用户决策后调 planner 同步进 spec、并 Read 确认了?(阶段 1.5 强制闸口)
  • 5 项全部 ✅ → 才能 invoke generator

通用闸口(不止「调 generator 前」):任何时候准备回复用户并进入下一步(含交接外部 generator / 起模拟器 / 收尾 / 等指令)之前,若本轮用户给过实质决策,先问自己「这条决策的内容进 spec 了吗(§1-6 或 §9 AMD)?」没进就先调 planner 落,再回复。外部 generator 路径不过上面的 generator checklist,唯一防漏点就是这条通用闸口。

阶段 2: 调 generator(用户说「开始」之后)

前提:阶段 1.5 已经跑过 —— 用户决策已经由 planner 同步进 .specs/<slug>.md。如果还没跑,回去补,不要继续往下。

Step 0: 选模式

主 agent 读 spec 第 2 节「并行分组」表:

  • 表里有多个 parallel-N 组 → 走 2B 并行模式
  • 表里只有 serial 组 / 写「全部串行」 / 表为空 → 走 2A 串行模式

2A: 串行模式(默认)

Agent({
  description: "<需求一句话> — 实现",
  subagent_type: "generator",
  prompt: """
    Worktree slug: <slug>
    Worktree 绝对路径: <pwd>
    要执行的子任务范围: <全部 | 子任务 ID 列表>

    .specs/<slug>.md 是你的需求圣经。
    按 ~/.claude/agents/generator.md 的 SOP 工作。
  """
})

generator 返回有两种情况:

  • 正常完成进入阶段 2.5(用户拍板 checkpoint),不要直接进入阶段 3。
  • 带「需要 planner 更新 spec」标注 → generator 返回的结构化结论里会有 needs_planner_update: true + feedback_file(指向 .specs/<slug>-feedback.md)+ feedback_iter(本轮 iter 编号)+ feedback_summary。主 agent:
    1. Read 看一眼 feedback_file 自检(确认 generator 真的写了文件、文件里有对应 iter 章节、不是空 placeholder)
    2. feedback_summary + feedback 文件路径展示给用户,让用户先有上下文(不要贴整份 feedback)
    3. 调 planner 走「场景 B:generator 反馈更新」,prompt 里必须带:feedback 文件绝对路径、本轮 iter 编号、spec 文件绝对路径。不要在 prompt 里复述 feedback 内容 —— planner 会自己 Read 文件
    4. planner 改完 spec → 主 agent Read 一下 spec 末尾「更新日志」确认改动落地 → 再问用户「spec 更新了,要看一眼再继续吗?」
    5. 用户同意 → 重新调 generator 继续(generator 下一轮启动会自己 Read spec 看 planner 改了什么)

2B: 并行模式(spec 标注多个 parallel-N 组时)

对每个 parallel-N 组 + serial 组(如有)各开一个 sub-worktree,让 generator 在里面独立干活。parallel-N 组之间并行;serial 组内的子任务由该组的 generator 顺序串行跑。

Step 1: 给每组建 sub-worktree
cd <主 worktree 绝对路径>   # .worktrees/<slug>/
mkdir -p .subworktrees

# 每个 parallel-N 组 + serial 组(如非空)各建一个
# GROUPS 来自 spec 第 2 节并行分组表的「组 ID」列
for group in $GROUPS; do
  git worktree add .subworktrees/$group -b <type/scope-slug>--$group HEAD
done

每个 sub-worktree 还要按 ~/.claude/rules/use-worktree.md 的 step 5-7 复制 <project-specific> 的 gitignored 本地配置 / 锁文件 / 跑初始化命令(例:Local.xcconfig.env.localPackage.resolvedyarn.lock、生成 xcodeproj、npm install 等)—— 没这些 build 会失败。

不要在每个 sub-worktree 都打开 IDE / workspace —— 多开 N 个窗口浪费。sub-worktree 只跑命令行 build,主 worktree 的 IDE 窗口留给用户审改动。

Step 2: 同一个 message 里发起 N 个并行 generator

关键:所有 generator 调用必须放进同一个 assistant message 的多个 Agent tool calls 里 + 每个都带 run_in_background: true,否则会变串行(系统会一个跑完再跑下一个)。

Agent({
  description: "<需求> — parallel-1",
  subagent_type: "generator",
  run_in_background: true,
  prompt: """
    Worktree slug: <主 slug>--parallel-1
    Worktree 绝对路径: <主 worktree>/.subworktrees/parallel-1
    Spec 文件绝对路径: <主 worktree>/.specs/<slug>.md   ← 注意是主 worktree(.specs/ 是 .gitignore,sub-worktree 没有)
    要执行的子任务范围: <spec 第 2 节并行分组表里 parallel-1 组的 task ID 列表>
    并行模式: 是
    
    重要约束:
    - 你只改本组分配的子任务对应的文件 —— 其他 parallel-* 组同时在改别的文件,撞了就互相覆盖
    - 不改 spec 第 1-7 节
    - 不动主 worktree(你的 cwd 是 sub-worktree)
    
    按 ~/.claude/agents/generator.md 的 SOP 工作。
  """
})
Agent({...parallel-2...}, run_in_background: true)
Agent({...serial...}, run_in_background: true)
Step 3: 等所有组完成

主 agent 在所有并发 Agent call 都返回前不要继续往下 —— 后台 Agent 完成时系统会通知。等齐再进入阶段 3B。

单组异常处理

任一组 generator 返回「需要 planner 更新 spec」标注(结构化结论里 needs_planner_update: true):

  1. 让其他正在跑的组继续跑完(结果暂存到 sub-worktree,不丢弃)
  2. 该组的 feedback 文件写在该组自己的 sub-worktree 下(路径形如 <sub-worktree>/.specs/<sub-slug>-feedback.md),不在主 worktree。Read 一下确认文件存在 + iter 章节落地
  3. 调 planner,prompt 里带:feedback 文件绝对路径(在 sub-worktree 下)、本轮 iter 编号、spec 文件绝对路径(在主 worktree 下,因为 .specs/ gitignored、sub-worktree 没有 spec)。planner 改 spec 主文件、不修 sub-worktree 的 feedback 文件
  4. spec 更新后 → 用户拍板 → 主 agent 决定下一步:
    • 该组单独重做(其他组结果保留;重做时 generator 在 sub-worktree 内继续读主 worktree 的 spec)
    • 整组重新分组(如果 planner 重划了)→ 清理所有 sub-worktree 重来

阶段 2.5: generator 完成后的用户拍板 checkpoint

generator 完成后自动进 executor。主 agent 必须停下来 AskUserQuestion 问用户下一步——给 generator 改动一个"先让用户看"的机会、避免用户没确认就闯进硬验收。

代码 review 在最终 PASS 后跑一次:正常路径由 executor 在 verdict==PASS 后内嵌跑(详见 ~/.claude/agents/executor.md Step 6.5)。但最终 PASS 可能经 lint 快速路径 / 外部 generator / 跳过 executor 到达,绕过 executor 的 PASS 流程、内嵌 review 不触发 —— 所以由主 agent 在 Step P2 保底:到达最终 PASS 时检查「本轮 review 跑过没」,没跑就主 agent 跑一次(同 /review 的 review subagent),跑过就不重复(不双跑)。review 与 verdict 解耦,retry 期间不重复 review。bypass:用户主动跑 /review/codex:review slash command 任何时候都可以,不是默认流程的一部分。

Step 0: 触发条件

闸口只在主路径 generator 第一次返回 success 时触发:

  • ✅ 触发:阶段 2A 串行模式的 generator 返回 success;阶段 2B 并行模式所有组 generator 都返回 success 时一次(不是每组一次)
  • ❌ 不触发:阶段 4 失败循环里的 generator retry 返回(直接回到 executor 重验)
  • ❌ 不触发:阶段 3A/5 PASS 后 review-fix 子循环里的 generator 返回(直接进 P4)
  • ❌ 不触发:阶段 4 lint-only fast path 里的 generator 返回(主 agent 自己轻量验证后进 P4)
  • ❌ 不触发:generator 返回 needs_planner_update(走 planner 同步路径,不在这一档)

Step 1: 报告 status

按当前流程展示:

  • generator 改动文件清单 + 编译结果 + spec §8 DONE 列表
  • dead_code_status 字段:
    • clean → 一句话过
    • auto_cleaned → 列出 generator 顺手删了哪些
    • needs_user_review高亮列出待用户判断的 dead-code 候选;用户可在阶段 3 PASS 后的 review-fix 子循环里挑修
    • skipped:<reason> → 一句话说明

Step 2: AskUserQuestion 问下一步

至少给这些选项(按推荐顺序排):

  • 进 executor 验收(Recommended,默认)—— 走阶段 3
  • 起模拟器跑起来给我看一下(仅 iOS 项目可点)—— 进 Step 3 起 simulator
  • 让 generator 接着改 X(用户在 Other 里填具体调整指令)—— 调 generator 走 Step 2.1 AMD 路径,prompt 用本节末尾「按用户口头指令修」模板;修完回到本闸口 Step 1
  • 跳过 executor 直接进 ship 流程(用户显式 bypass)—— 跳到 3A PASS 后流程的 Step P4 文档同步问询

Step 3: 起模拟器(仅当用户挑「起模拟器」时)

主 agent 自己跑,不派 subagent:

  1. Skill(find-ios-build-artifact)APP_PATH / BUNDLE_ID / SIMULATOR_UDID
  2. xcrun simctl install <UDID> <APP_PATH> + xcrun simctl launch <UDID> <BUNDLE_ID>
  3. BUNDLE_ID / SIMULATOR_UDID / 模拟器名一并报给用户
  4. 再次 AskUserQuestion 问下一步(这次不含「起模拟器」选项,包含「进 executor」/「让 generator 改 X」/「跳过 executor」/「暂停我自己看」)
  5. 用户显式说「真机 / 装我手机上」时才切真机路径(按用户具体说法走 idb / ios-deploy 等,不在 SOP 强制)

模拟器起不来(build 没产物 / sim boot 失败 / install 失败):报错给用户、AskUserQuestion 问「修 build 让 generator 再来一遍 / 直接进 executor 看 executor 能不能给出更具体的报错」。

硬约束

  • ❌ 不许在 Step 2 跳过 AskUserQuestion、直接调 executor(哪怕看起来 generator 的 status 完美)
  • ❌ 不许在 Step 3 起模拟器后直接调 executor、不等用户回复(必须再问一次)
  • ✅ 用户在 Step 2 / Step 3 的 AskUserQuestion 里直接说「进 executor」或「OK 验收」就算明确同意
  • ✅ 用户从一开始就在原始需求里说过「不用 executor」/「跳过验收」 → 整个闸口跳过,generator 完成后直接进 Step P4 文档同步

「按用户口头指令修」prompt 模板(用户在闸口 Step 2 挑「让 generator 改 X」时使用):

Agent({
  description: "<需求一句话> — 按用户调整指令修",
  subagent_type: "generator",
  prompt: """
    Worktree slug: <slug>
    Worktree 绝对路径: <pwd>
    本轮任务: 按用户口头追加的调整指令修复,不扩范围、不修 §1-7

    用户的具体调整指令(原话):
    <贴用户原话>

    按 ~/.claude/agents/generator.md 的 SOP 工作,本轮重点:
    - Step 2.1 把用户指令 append 成 §9 AMD([generator 写])再实现、改 DONE
    - 只改用户指令对应范围
    - 不修 spec §1-7、不扩任务范围
    - 修完跑编译确认没引入新错
  """
})

「按 review 修」prompt 模板(阶段 3A PASS 后的 review-fix 子循环复用此模板):

Agent({
  description: "<需求一句话> — 按 review 修",
  subagent_type: "generator",
  prompt: """
    Worktree slug: <slug>
    Worktree 绝对路径: <pwd>
    本轮任务: 按 executor review 报告修复,不扩范围、不修 §1-7

    Executor review 报告路径: <.reviews/<branch>-<ts>-executor.md 绝对路径>
    采纳范围: <全部 | 只 must-fix | 用户挑出的具体条目(列出来)>

    按 ~/.claude/agents/generator.md 的 SOP 工作,本轮重点:
    - Read review 报告全文,把采纳的项按 Step 2.1 append 成 §9 AMD([generator 写]),然后实现、改 DONE
    - 只改 review 里被采纳的项
    - 不修 spec §1-7、不扩任务范围
    - 修完跑编译确认没引入新错
  """
})

model 选择(B3):review-fix / 按用户口头指令修时 —— 若采纳项全是 nits / lint-error / 文案微调(无 logic / architecture / 跨调用方改动)→ 加 model: sonnet 起 generator(机械修复、省 opus);含实质逻辑 / 架构改动 → 不传(默认 opus)。拿不准走 opus。仅限 in-session Claude generator。

阶段 3: 调 executor(+ ui-reviewer,按用户触发)

executor 续问场景由 executor 自己 Step 0 cache 命中处理:主 agent 不必区分"续问 vs 真 retry"。executor 每轮 Step 9 把 verdict + repo 指纹(HEAD + porcelain hash)落盘 .specs/<slug>-verdict.md;下次 executor 启动时 Step 0 检测指纹一致即直接返回上轮 yaml(不重跑 Step 1-8)。

主 agent 想强制重跑(绕过 cache)→ 在 executor prompt 里显式传 force_rerun: true。典型场景:用户挑修 review 后回到 retry executor、主 agent 知道 generator 改了代码(其实 repo 指纹也会自动变、不必显式传,但显式传更安全)。

阶段 3A / 3B / 5 调 executor 时不必主动管 cache —— executor 自己处理。

Step 0: 判断本轮是否触发 ui-reviewer

UI 验收默认不跑。主 agent 在调 executor 前判断 ui_review_requested

  • 用户在本轮(或本需求的早期对话)说过「跑下 UI / UI 走查 / UI 验收 / review UI / 看下 UI 对不对 / 跑下模拟器 / 跑下 mobile-mcp」等关键词 → ui_review_requested = true
  • 没说 → ui_review_requested = false

不要自主判定:哪怕 spec §4 有「iOS UI 改动专项」用例、哪怕 generator 改了 view 文件,不是主 agent 自己决定要不要跑 ui-reviewer。用户没明说就 = false。spec §4 列了用例 + 用户没说 UI 验收时,主 agent 报告里提示「spec §4 有 UI 用例但本轮没跑 ui-reviewer,需要 UI 验收请明说」,让用户自己决定。

ui_review_requested == true 时主 agent 在调 executor 的同一个 message 里并行起一个 ui-reviewer(run_in_background: true)。两个 subagent 都 PASS 才算整体 PASS(详见下方分支)。

ui_review_requested == false 时本节后续所有 ui-reviewer 相关步骤跳过。

3A: 串行模式(默认)

# ui_review_requested == false 时只调 executor;== true 时同 message 里两个 Agent call 都 run_in_background
Agent({
  description: "<需求一句话> — 验收",
  subagent_type: "executor",
  prompt: """
    Worktree slug: <slug>
    Worktree 绝对路径: <pwd>
    Generator 改动文件清单: <generator 返回的清单>
    本轮重试次数: <1 | 2 | 3>
    run_review_subagent: true   ← 默认值;review-fix 后的 retry 改成 false(见下方「3A PASS 后 review-fix 子循环」)

    按 ~/.claude/agents/executor.md 的 SOP 工作。
  """
})

# 仅 ui_review_requested == true 时同 message 里再发一个:
Agent({
  description: "<需求一句话> — UI 验收",
  subagent_type: "ui-reviewer",
  run_in_background: true,
  prompt: """
    Worktree slug: <slug>
    Worktree 绝对路径: <pwd>
    Generator 改动文件清单: <generator 返回的清单>
    本轮重试次数: <1 | 2 | 3>

    按 ~/.claude/agents/ui-reviewer.md 的 SOP 工作。
  """
})

两个 subagent 返回结构化结论后合并 verdict:

  • 两个都 PASS(或 ui_review_requested==false 时单 executor PASS)→ 进入「3A PASS 后流程」
  • 任一 FAIL → 进入阶段 4(详见阶段 4「ui_review_requested == true 时的双路径」段)
3A PASS 后流程

verdict == PASS 时主 agent 顺序做下面三件事,不要跳序

Step P1: 报告 + amendment 提示

把这些字段一次性报给用户:

  • executor 通过了
  • 如果 ui_review_requested == trueui-reviewer 通过了 + ui-reviewer 返回的字段(详见下方「ui-reviewer 字段路由」段)
  • 如果 ui_review_requested == false 但 spec §4 有「iOS UI 改动专项」用例:提示「spec §4 有 UI 用例但本轮没跑 ui-reviewer,需要 UI 验收请明说『跑下 UI 验收』」
  • warning 列表(如有)
  • amendments_verified 三个 list(done_verified / done_failed 应为空 / todo_skipped)
  • decisions 审计总结(必报):Read .specs/<slug>/decisions.md 全文,按「自作主张 / 存疑 / 隐含偏差 / 借鉴 pattern」四类聚合所有非「无」条目成一段总结(按类合并、保留每条要点、不漏条目),附 .specs/<slug>/decisions.md 绝对路径供用户核对

ui-reviewer 字段路由(仅 ui_review_requested == true 时适用):

  • ui_verified: pass —— 把 ui_screenshots_dir 路径告诉用户。同时:
    • ui_dynamic_cases_verified 非空 → 透传给用户(让他知道 ui-reviewer 看了哪些动画 + 帧路径),允许用户 Read 帧自己复查;不强求他再跑 simulator
    • ui_dynamic_cases_skipped 非空(skill 失败的动态用例)→ 必须把列表展示给用户、提示「这几条 skill 验不了、要自己看动画」
  • ui_verified: fail —— 静态间距用例至少 1 条 frame/对齐与 spec 不符或动态 record skill verdict=fail。ui-reviewer verdict 一定是 FAIL;走阶段 4 重试
  • ui_verified: degraded —— 不是 generator 的错。两类原因:(a) environment 问题(build artifact / simulator / install/launch 失败);(b) 全部用例都是动态、record skill 全部失败降级。ui-reviewer verdict 仍可能 PASS;主 agent 把 ui_smoke_required: true + ui_degradation_reason + ui_dynamic_cases_skipped(如有)报给用户。不要因为 ui_verified: degraded 重调 generator
  • ui_verified: not_applicable —— spec 没 iOS UI 改动专项;如果 ui_review_requested == true 而 ui-reviewer 返回 not_applicable,提示用户「本需求没 UI 改动 / spec §4 没列 UI 用例,UI 验收无内容可跑」

Step P2: 展示 review 报告 + AskUserQuestion 问「review 怎么处理」

Step P2.0(保底闸口):先确保本轮 review 已跑过一次。

  • review_subagent_status == success(executor 在正常 PASS 时跑过)→ review 已跑,直接走下面 success 路由展示,不重跑
  • 否则(skipped:verdict_fail / 经 lint 快速路径或外部 generator 到达 PASS / 本轮根本没调 executor)→ review 还没跑 → 主 agent 现在跑一次:调 /review 的 review subagent(Opus extended thinking,审 dev...HEAD + 未提交改动,输出到 .reviews/<branch>-<ts>.md),拿到 verdict + findings 后按下面 success 路由展示。

确认 review 已跑(或刚补跑完)后,按 review_subagent_status(或主 agent 本轮补跑的结果)路由:

  • success → 把 review 元信息展示给用户:

    • review_subagent_verdict(pass / pass-with-nits / fail)
    • review_findings_count(must_fix / suggestions / test_residue / dead_code / spec_deviations / perf_advisory 各计数)
    • review_summary(一句话)
    • review_file 绝对路径 —— 让用户自己打开看细节,不要在 chat 里贴整份 review

    然后 AskUserQuestion 问「review 怎么处理」,给选项(第一个标 Recommended):

    • 全部采纳,调 generator 修(Recommended,当 review_subagent_verdict==fail 时)
    • 只采纳 must-fix,调 generator 修(Recommended,当 review_subagent_verdict==pass-with-nits 时)
    • 打开 review 文件我自己挑 —— 等用户在主对话里列具体条目
    • 跳过 review,进入下一步 —— review 留着以后参考;当 review_subagent_verdict==pass 时这个是 Recommended

    用户挑「修」 → 进入「Step P3 review-fix 单轮子循环」;挑「跳过」 → 直接进 Step P4

  • failed → 把 review_subagent_error 报给用户,AskUserQuestion 问「下一步」,给选项:

    • 跳过 review,进入下一步(Recommended)
    • 主动跑一次 /review 重试 —— 走 commands/review.md 的 SOP
    • 暂停,等我下一步指令
  • skipped:verdict_fail —— 出现在最终 PASS 路径里 = review 被上轮 FAIL 跳过、之后经快速路径 / 外部 generator 到了 PASS:由 Step P2.0 保底触发主 agent 补跑一次 review(不再当 warning 忽略)

  • skipped:flag_off —— 这是 review-fix 子循环后的 retry executor 才会出现(主 agent 自己传了 false),跳过 Step P2 直接进 Step P3 / P4

Step P3: review-fix(仅当用户挑「修」时)—— 不跑 retry executor

  1. 调 generator 按 review 修,prompt 用阶段 2.5 末尾的「按 review 修 prompt 模板」(带 Executor review 报告路径 字段)
  2. generator 修完返回 → 主 agent 自己做下面这套轻量验证(不调 executor):
    • Read generator 返回的结构化结论,确认:编译通过 / 改动文件清单合理 / 没动 spec §1-7 / §9 AMD 状态推进了
    • 把改动文件清单 + 编译结果一句话报给用户
  3. 直接进 Step P4 文档同步

注意

  • review-fix 期间 generator 可能改坏 §4-5 验收 / UI / 硬约束(前置假设:generator 遵守自己的 SOP——编译验证 / 不扩范围 / AMD append);用户在 P4 时可显式说「再跑一次 executor」bypass

  • 关键路径触发(任一即触发;主 agent 在 Step P3 第 2 步轻量验证完后判一次):

    1. 抽象层文件:generator 改的文件名匹配 *Protocol.swift / *Store.swift / *Reducer.swift / *Service.swift / *Manager.swift / *Coordinator.swift(跨调用方的抽象层)
    2. trigger-on-touch 命中:改动命中项目根 AGENTS.md / CLAUDE.md 列的「改动以下任一范围前先读该文档」路径(用 Skill(scan-trigger-docs) 跑一次校验)
    3. review issues 多review_findings_count.must_fix >= 3

    任一触发 → 主 agent 报给用户时加一句:「⚠️ 本轮 review-fix 触及关键路径(命中规则:<编号列表>),建议手动复核 / 或显式说『再跑一次 executor』」

  • 阶段 4 失败循环默认仍跑 retry executor;两条跳过路径:(1) PASS 后的 review-fix(本 Step P3);(2) 阶段 4 lint-only 快速路径(详见阶段 4 段)

Step P4: 文档同步问询 + 收尾

AskUserQuestion 问「要不要现在总结这次工作 + 更新项目文档?」,给 3 个选项:

  • 总结 + 更新文档(推荐):主 agent 自己复盘本轮改动里对未来 agent 行为有持续影响的部分(新工作流 / 改了项目结构 / 改了模块边界 / 引入新工具链 / 新约定)→ 列出建议更新的具体文档路径 + 每处改动大纲(CLAUDE.md / AGENTS.md / docs/*.md / rules / skills 都可能)→ 用户拍板大方向后 agent Edit 落地 → 让用户 review diff → 满意就 commit
  • 跳过文档:本次改动只是常规业务代码 / UI / bug fix,对 agent 没新约束,直接进入下一步
  • 稍后再说:留着这次改动,先做别的;后续 /openpr 时仍会再问一遍(见 commands/openpr.md「文档同步检查」)

落地文档时:先 Skill(agent-readable-docs) 把自检套到自己头上(回头精简不 append-only / 只写当前事实删 history 叙事 / always-load 优先下沉到 on-demand 索引),别只把它当分析对象。

不要默认跳过 —— 必须问。问完按用户的选择执行;用户选完后再告诉用户「可以 /openpr 或继续做下一个需求」。

3B: 并行模式(每组各自跑 executor,ui-reviewer 不进 3B)

并行模式下 ui-reviewer 不进 3B —— 每组 sub-worktree 各自跑 executor 时,UI 验收(如果用户触发了)留到 3C 合并后或阶段 5 最终验收时在主 worktree 跑一次。理由:mobile-mcp 不支持 UDID 透传,多 sub-worktree 同时跑会互相抢 simulator 交互;且 UI 用例本来就是看整体效果,分组分别跑 UI 反而拼不出全貌。

Step 1: 调 executor

阶段 2B 的所有 generator 都返回后,对每组各自调 executor。仍可以并行(每组在自己 sub-worktree 内独立跑),同一个 message 多个 Agent call + run_in_background: true

Agent({
  description: "<需求> — parallel-1 验收",
  subagent_type: "executor",
  run_in_background: true,
  prompt: """
    Worktree slug: <主 slug>--parallel-1
    Worktree 绝对路径: <主 worktree>/.subworktrees/parallel-1
    Spec 文件绝对路径: <主 worktree>/.specs/<slug>.md
    Generator 改动文件清单: <该组 generator 返回的清单>
    本轮重试次数: <1 | 2 | 3>
    并行模式: 是
    本组负责的子任务: <task ID 列表>
    run_review_subagent: false   ← 并行模式下单组验收不跑 review,review 留到阶段 5 最终验收时跑一次
    
    按 ~/.claude/agents/executor.md 的 SOP 工作。
    本轮验收范围**只看本组负责的子任务**对应的 spec 验收标准;
    spec 第 4 节里其他组的测试用例不要纳入本轮验收。
  """
})
Agent({...parallel-2 验收...}, run_in_background: true)
Agent({...serial 验收...}, run_in_background: true)

每组 verdict 独立追踪:

  • 该组 PASS → 关闭,不再循环
  • 该组 FAIL → 走阶段 4 失败循环只针对该组(≤3 次,重试时仍在该 sub-worktree 内重调 generator)。其他已 PASS 的组不动
  • 全部组 PASS → 进入 3C 合并验证
  • 任一组 3 次重试仍 FAIL → 整体停下报用户(参考阶段 4 末尾),其他已 PASS 组保持不动等用户决定(用户可能选「保留这部分、放弃失败的组」「整体回滚」「升级 spec 重新拆」)

3C: 合并验证(仅并行模式)

所有 sub-worktree 的 executor 都 PASS 后,主 agent 把各组提交合并回主 worktree 的主分支:

cd <主 worktree 绝对路径>

# 按 spec 第 2 节并行分组表里的顺序 merge(serial 组优先 merge,parallel-N 按编号)
# 用 --no-ff 保留并行分支拓扑,方便后续审查
for group in serial parallel-1 parallel-2 ...; do
  if git rev-parse --verify "<type/scope-slug>--$group" >/dev/null 2>&1; then
    git merge --no-ff "<type/scope-slug>--$group" -m "merge: $group into <type/scope-slug>"
  fi
done
合并冲突处理

任一 merge 报冲突 → 直接报用户人工介入,不要自己解。冲突说明:

  • planner 在阶段 1 误判了文件边界(标了 parallel 但其实有重叠)
  • 或 generator 越界改了不该改的文件

主 agent 给用户两个选项:

  • 回滚 merge + 调 planner 重划分组git merge --abort 撤销当前 merge,sub-worktree 还在)
  • 手动解冲突(用户在主 worktree 里自己改)
Merge 后跑 build 验证

跑项目的 build 命令(按 spec 第 5 节验收标准),验证合并没破环境。

build 失败 → 报用户(合并触发的隐性冲突,例如类型签名不一致),自动调 generator 修。

build 通过 → 清理 sub-worktree:

cd <主 worktree 绝对路径>
for group in serial parallel-1 parallel-2 ...; do
  git worktree remove .subworktrees/$group
  git branch -d "<type/scope-slug>--$group"   # 已 merge,安全删除
done
rmdir .subworktrees 2>/dev/null || true

清理完后 → 进入阶段 5(最终 executor,含 review;如 ui_review_requested == true 同时跑 ui-reviewer)

阶段 4: 失败循环(自动重试 ≤3 次;外部实现走用户闸口)

executor 判 FAIL 后,主 agent 先看本轮送验代码的实现归属 impl_source,再决定走自动重试还是停下问用户:

  • in-session-generator(默认)—— 代码由本 pipeline 内部 generator subagent 写(阶段 2 首次实现 / 本阶段 retry)。→ 走 4B 常规自动重试循环(≤3 次)。
  • external-generator —— 代码由外部 generator 实现(用户在阶段 1 末尾 / 2.5 选「我自己改 / 用外部 generator / Codex」、或代码来自当前 pipeline 之外的 resume 任务 / 手改 / 别的工具)。→ 走 4A 外部实现用户闸口不自动重调内部 generator

impl_source 真相源 = spec §3「实现归属」字段(planner 每次写 spec 必填、用户在阶段 1 末尾 / 2.5 选外部路径时由 planner 二次调用改成 external-generator)。主 agent 进阶段 4 先 Read spec §3 拿值,不靠对话历史推断:

  • spec §3 = in-session-generator(默认)→ 走 4B(并行模式各组恒为此值)
  • spec §3 = external-generator → 走 4A 用户闸口
  • 4A 闸口里用户挑「内部 generator(Claude)」修一次后 → 主 agent 当轮失败循环按 in-session-generator 处理(走 4B 自动重试);不必回头改 spec §3,若用户要求「以后都用内部」再调 planner 把 §3 翻回

4A: 外部实现用户闸口(impl_source == external-generator)

不自动重调任何 generator。AskUserQuestion 停下问,不预设 Recommended(让用户自己挑、不默认推内部):

  • 内部 generator(Claude) 修 —— 调本 session 内部 generator 按 review 修(prompt 用阶段 2.5 末尾「按 review 修」模板)。修完 → 当轮失败循环按 in-session-generator 处理 → 重跑 executor(传 force_rerun: true)→ 再 FAIL 进 4B 常规循环(≤3)
  • Codex 修 —— 调 codex:codex-rescue(外部 Codex runtime)按 review + spec 修,prompt 用下方「Codex 修 prompt 模板」。修完 → impl_source 保持 external-generator → 重跑 executor(传 force_rerun: true)→ 再 FAIL 回到本闸口(4A 再问一次,用户逐轮掌控节奏)
  • 暂停等指令 —— 停手,留 worktree + .specs/<slug>-review.md,等用户后续发话

4A 不计入 4B 的 ≤3 自动重试上限(用户逐轮拍板、随时可暂停)。

Codex 修 prompt 模板(4A 用户挑「Codex 修」时):

Agent({
  description: "<需求一句话> — Codex 按 review 修",
  subagent_type: "codex:codex-rescue",
  prompt: """
    Worktree 绝对路径: <pwd>
    Spec 文件绝对路径: <pwd>/.specs/<slug>.md
    Executor review 报告路径: <.specs/<slug>-review.md 绝对路径>
    本轮任务: 按 review 报告里的 blocking issues 修复,不扩范围、不动 spec §1-7

    在该 worktree 内用 Codex 实现修复:
    - Read spec(需求圣经)+ review 报告全文,按 review 列的 issues 逐条修
    - 只改 review 命中的范围,不顺手重构 / 不扩任务
    - 修完跑项目 build 命令自验编译通过,把改动文件清单 + build 结果返回
  """
})

4B: 常规自动重试循环(impl_source == in-session-generator)

i = 1
fast_path_used = false
while i <= 3:
    判断本轮入口模式:
    
    if (executor 上轮 lint_only_fail == true)
       and (ui-reviewer 上轮 PASS / not_applicable / 未触发)
       and (not fast_path_used):
        # 【lint-only 快速路径】—— 不调 retry executor
        调 generator(**用 `model: sonnet`** 起 —— lint 修复纯机械、不需要 opus;
                     仅限 in-session Claude generator,Codex 路径不受此影响),prompt 里追加:
          - executor review 文件路径: `.specs/<slug>-review.md`
          - 本轮是第 i 次重试 / 共 3 次
          - **显式说**「上轮 executor 仅 lint 失败、build / spec / AMD / 硬约束 / mock 等全过;
            本轮只修 review 文件里 issue_type=lint-error 的条目,不扩范围。
            修完跑 `just check` + 项目 build 命令自验、把 build/lint 状态写进结构化结论;
            主 agent 本轮**不**再调 executor」
        generator 返回 → 主 agent **自己**做轻量验证(同 Step P3 review-fix):
          - Read generator 结构化结论里 build / lint 状态字段
          - 改动文件清单合理(限于 review 列的 lint 修复范围)、没动 spec §1-7
          → build pass + lint pass + 改动范围合理 → 直接 break,进入 3A PASS 后流程
            (视同 executor 上轮 PASS;lint-only fail 等价于"软 PASS、只差最后一公里")
          → build fail / lint 仍 fail / 改动越界 → fast_path_used = true,i += 1,
            下一轮回到常规路径重调 executor 拿完整 issues(fast path 只用一次、失败退化)
    
    else:
        # 【常规路径】(原流程)
        调 generator,prompt 里追加:
          - **executor review 文件路径**(仅 executor 上轮 FAIL 时): `.specs/<slug>-review.md`
          - **ui-reviewer review 文件路径**(仅 ui-reviewer 上轮 FAIL 时): `.specs/<slug>-ui-review.md`
          - 本轮是第 i 次重试 / 共 3 次
          - 显式说「请 Read 给到的 review 文件拿完整 issues + 上轮 status diff,按 issues 修复,不要扩大改动范围」
        generator 返回 → 按上轮哪个 FAIL 重调对应 subagent:
          - 只 executor FAIL → 重调 executor (retry_count = i)
          - 只 ui-reviewer FAIL → 重调 ui-reviewer (retry_count = i)
          - 两个都 FAIL → 同 message 并行重调 (run_in_background: true)
        本轮 FAIL 的全部 PASS(或单 executor 模式下 executor PASS)→ break
        i += 1

if i > 3:
    停止重试。报给用户:
      "3 次重试仍未通过 executor 验收。
       最近一轮的 blocking issues:
       <列表>
       
       建议下一步:
       (1) 改 spec —— 验收标准/硬约束可能不合理,调 planner 改
       (2) 用户介入 —— 直接看代码、自己改或指导 generator 怎么改
       (3) 暂停这个需求 —— 留 worktree 等以后回来"

不要超过 3 次自动重试 —— 一直失败说明问题不在代码、是规划或理解层面,需要人介入。

lint-only fast path 注意just fix 极端边角可能改坏语义(SwiftFormat 换行连锁触发其他规则、误删 unused_variable 时删掉实际有副作用的代码);fast path 漏一次的兜底是只用一次 + 失败退化到常规路径。

ui_review_requested == true 时的双路径

阶段 3A / 5 同时跑 executor + ui-reviewer 时,两个都 PASS 才算整体 PASS

  • 只 executor FAIL → generator 修代码后只重调 executor(ui-reviewer 上轮 PASS、不重跑)
  • 只 ui-reviewer FAIL → generator 修代码后只重调 ui-reviewer(executor 上轮 PASS、不重跑)
  • 两个都 FAIL → generator 修代码后同 message 并行重调两个

ui-reviewer 单独失败的 retry 也算 generator 的失败重试次数(计入 ≤3 次循环),因为根因是 generator 写的 UI 代码不对。例外ui_verified: degraded 不算 generator 的错(environment 问题),主 agent 不重调 generator、直接走 PASS 路径报告给用户。

并行模式下的 scope 限定

阶段 3B 的某组 executor FAIL → 进入本循环但 scope 只针对该组

  • 重调 generator 的 prompt 里 worktree 绝对路径、spec 子任务 ID、本轮重试次数都限定到该组
  • 其他已 PASS 的组的 sub-worktree 不动、不重新 build、不重新 executor
  • 该组 3 次重试仍 FAIL → 报给用户决定,已 PASS 组保留等待
  • 用户决定的可能选项:放弃该组(接受其他组成果)/ 整体回滚 / 升级 spec 重划分组

阶段 5: 最终验收(仅并行模式)

并行模式下 3C 合并 + build 验证通过后必须再跑一次 executor —— review 也在这一步跑(3B 各组都没跑 review)。模板同阶段 3A,差异只在入参:

  • executor(总是调):最终验收模式: 是 + run_review_subagent: true(并行模式 review 唯一入口)+ 各组合并后的整体改动清单;验收范围 spec 第 4/5/6 节整体(不分组)。

  • ui-reviewer(仅 ui_review_requested == true,同 message run_in_background: true):最终验收模式: 是;验收范围 spec 第 4 节整体(不分组)。

  • 全部 PASS(executor + ui-reviewer 如有)→ 进入 3A PASS 后流程(Step P1 → P2 → P3 review-fix 子循环(按需)→ P4 文档同步)

  • 任一 FAIL → 走阶段 4 失败循环(不分组,整体重做改动;按上方「ui_review_requested == true 时的双路径」段路由),最多 3 次;阶段 4 retry 期间所有 executor 都传 run_review_subagent: false,直到下一次 PASS 才让 review 再跑(或如果首次 review 已经跑过、用户已经看过,retry 后的 PASS 也不重 review)

串行模式(2A)下不存在阶段 5 —— 阶段 3A 的 executor / ui-reviewer 已经在第一次 PASS 时跑过 review,不需要重复。

主 agent / planner / generator 在 §8 进度状态上的写权限边界

结构提醒:spec 是主索引 + 子目录两层(.specs/<slug>.md + .specs/<slug>/{tasks,risks,amendments}/,详见 ~/.claude/templates/spec-template.md)。§8 在主索引里是索引行表(status + 摘要 + 链接),每行对应一个 tasks/task-N.md 子文件。改 status 时必须同时改两处:主索引索引行的 status 列 + 子文件的 **状态** 字段。子文件是 status 真相源、主索引索引行是 status 快照。

§8(TODO/DOING/DONE 状态)默认是 generator 的写权限:

  • ✅ generator: 每完成一个 task,改子文件 tasks/task-N.md**状态** 字段 + 同步主索引 §8 索引行。这是日常完成度迁移
  • ❌ planner: 默认不动 §8 状态(避免 planner 与 generator 在同一节互相覆盖);初始 Write 子文件时填 TODO 是首次定义、不算 mutation
  • ❌ 主 agent: 默认不动 §8(按本 rule「主 agent 绝对不能做的事」第 2 条)

但下面两种场景下,planner 必须改 §8(这是计划性结构改动、不是完成度迁移、不算抢 generator 写权限):

场景 A: 用户决策导致已 DONE task 范围扩大(task 拆分)

触发:用户在阶段 1.5 / 2 / 2.5 / 3 给的决策让一个已 DONE 的 task 范围扩大(例:原 task-5 = "POST 阶段失败",用户决策 B 后扩成 "POST + commit 时机 + sidecar",但 task-5 已经在 §8 标了 DONE)。

planner 必须做:

  1. 主索引 §2 把原 task 拆成 task-Na(已 DONE 子范围)+ task-Nb(待做新增子范围);同步 Write tasks/task-Na.md(status=DONE)+ tasks/task-Nb.md(status=TODO)
  2. 主索引 §8 同步:task-N 索引行 → 删除;新增 task-Na 行(status=DONE)+ task-Nb 行(status=TODO)
  3. 在主索引 §8 段头加一行校准说明:§8 校准说明(YYYY-MM-DD iter-N 处理):本节由 planner 因 task 拆分破例修改一次。日常完成度迁移仍由 generator 自己写。

场景 B: 旧 task 被用户决策完全移出 scope(task 删除)

触发:用户决策让某 task 完全不再做。

planner 必须做:

  1. 主索引 §2 给该 task 索引行加删除线 + 一句说明(保留审计痕迹)
  2. 主索引 §8 同步:从索引表把该 task 行删掉(不留删除线 —— §8 是状态视图、删除线行是噪声)
  3. 子文件 tasks/task-N.md保留(审计痕迹),但可以在子文件顶部追加一行 > 用户决策移出 scope(YYYY-MM-DD)

主 agent 调 planner 时的 checklist

调 planner 走场景 A / B 时,prompt 里必须显式点出:

  • 触发场景(用户决策 / generator 反馈)+ 用户原话
  • 受影响的 task ID 列表
  • 期望 planner 做的 §8 改动(拆 / 删 / 状态调整)+ 明确写「主 agent 与用户特批 planner 改 §8」

不要让 planner 自己猜「这次能不能改 §8」—— 主 agent 显式授权 planner 才动。

Generator 启动前 §8 漂移自救(不停手等指令)

generator 启动前发现 §8 ↔ §2 / §7 / 子文件 status 不一致时,§2 是 task 定义真相源 + 子文件是 status 真相源,按下面处理(详见 ~/.claude/agents/generator.md Step 1.5):

  • 主索引 §2 列了 task 但 §8 缺索引行 → 自己加进 §8 TODO + 确认 tasks/task-N.md 子文件存在;缺则 Write 一份骨架
  • 主索引 §8 标 DONE 但子文件 tasks/task-N.md 标 DOING / 进度注记说"未完成" → 信任子文件、Edit 主索引把该行 status 退回 DOING
  • 主索引 §8 标 DOING 但子文件标 DONE → 信任子文件、Edit 主索引把该行 status 改 DONE
  • 主索引 §9 索引行 status 与 amendments/AMD-N.md 子文件 status 不一致 → 信任子文件、Edit 主索引 §9 索引行
  • 主索引 §8 有 task 但 §2 没列 → 这是真冲突 → 跑 Step 4 不确定流程(让 planner 处理)

前几种是漂移、自救即可,不要写 feedback 文件停手;最后一种才是真不确定。这条是为避免 planner / generator 双方退守 SOP 边界 → §8 漂移没人改 → 死锁。

§9 Amendments 写权限边界(与 §8 并列、与 §1-6 不同)

§9 收录实现阶段用户追加的具体指令(bug fix / 微调 / review-fix 修复项 / 临时新增的具体效果要求)。追加专用,不动 §1-6——原始需求快照(§1-6)保持纯净,方便回溯"最初想要什么"。

结构提醒:§9 在主索引里是索引行表(status + 作者 + 时间 + 摘要 + 链接),每行对应一个 amendments/AMD-N.md 子文件。append AMD = Write 新子文件 + Edit 主索引加一行索引(把指令正文写进主索引)。改 status 时同步改两处。

写权限

  • planner:场景 A 二次调用时,用户决策是实现层指令(不动硬约束 / scope 边界)→ Write 新子文件 amendments/AMD-N.md[planner 写],status: TODO)+ Edit 主索引 §9 加索引行(详见 ~/.claude/agents/planner.md「场景 A 路由表」段)
  • generator:迭代中收到用户具体指令(主对话里口头说 / review-fix 采纳项)→ Step 2.1 自己 Write 新子文件 amendments/AMD-N.md[generator 写],status: TODO)+ Edit 主索引 §9 加索引行(详见 ~/.claude/agents/generator.md Step 2.1)
  • 主 agent绝不直接 Edit §9 索引行或子文件 —— append AMD 一律走 planner 或 generator
  • 任何 agent不准修改 / 删除已有 AMD 子文件的「触发」/「指令」/「影响范围」字段(保留审计痕迹);若用户撤销某条,把主索引 status 改 ~~CANCELLED~~ + 在子文件追加原因

状态字段(与 §8 同口径)

每条 AMD 在子文件里有 **状态**: TODO | DONE 字段;主索引索引行的 status 列与之同步推进该 AMD 的当事 agent 自己改两处

  • planner append 的 AMD-N([planner 写])→ 通常 generator 后续推进时改两处 DONE
  • generator append 的 AMD-N([generator 写])→ generator 实现完自己改两处 DONE
  • executor 看到 status=DONE 的 AMD 才 Read 子文件 + 验收;status=TODO 跳过本轮 + 不 Read 子文件(与 §8 TODO 子任务同处理)

决策路由(主 agent 在阶段 1.5 / 2 / 2.5 / 3 收到用户反馈时)

用户反馈类型 主 agent 走法
改硬约束 / 改 scope / 拆任务 / 改测试用例 调 planner → planner Edit 主索引 §1-6(含 §2 索引表) + 必要时 Write/Edit tasks/task-N.md 子文件 + 更新日志
bug fix / 微调 / "这里加 loading" / 阶段 2.5 review-fix 挑的修复项 调 generator(在 prompt 里说「请按 Step 2.1 Write amendments/AMD-N.md + 加主索引 §9 索引行再修」)—— planner 不参与
用户决策同步阶段提的实现层指令("开始实现之前先把 X bug 修掉") 调 planner → planner 走「场景 A 路由表」Write AMD 子文件 + 加索引行([planner 写])

Executor 验收 §9 的口径

  • status=DONE 的 AMD:与 §1-6 等价的验收基线,Read 主索引 §9 索引行 → Read 对应 amendments/AMD-N.md 子文件全文 → 逐条核对实现是否真满足;不满足 → blocking issue(issue_type: amendment-not-fulfilledamendment_ref: AMD-Nspec_section: 9
  • status=TODO 的 AMD:跳过本轮(不影响 PASS/FAIL)+ 不 Read 子文件(节省 context),在 notes 里提一句「§9 还有 N 条 amendment 处于 TODO」
  • 结构化结论新增 amendments_verified 字段(done_verified / done_failed / todo_skipped 三个列表);详见 ~/.claude/agents/executor.md Step 7

Amendments 在阶段 4 失败循环里的角色

阶段 4 retry 时 generator 看 .specs/<slug>-review.md 拿 issues,同时仍要 Read 主索引(§1-6 内联 + §7/§8/§9 索引)+ 按本轮 scope 按需 Read 子文件 —— §9 是与 §1-6 等价的约束。executor 上一轮判 FAIL 时如果有 amendment_ref: AMD-N 的 issue(DONE 但实际没修对),下一轮 generator 要继续把那条 AMD 修对、子文件 + 主索引 status 都保持 DONE。

主 agent 绝对不能做的事

  • ❌ Edit / Write / NotebookEdit 任何代码文件 —— 一律走 generator
  • ❌ Edit / Write .specs/<slug>.md 主索引或 .specs/<slug>/ 子目录任何文件 —— §1-6 内联走 planner、§2/§7 索引行 + 对应子文件走 planner、§8 状态 + tasks/ 子文件走 generator(planner 仅初始 Write 骨架)、§9 索引行 + amendments/ 子文件走 planner / generator(按上方「§9 写权限边界」决策路由)
  • ❌ 跑项目的 build / lint / test 命令来「自己验证一下」—— 那是 generator / executor 的事
  • ❌ 跳过 planner 直接调 generator(除非用户显式说「跳过 planner」)
  • ❌ 跳过 generator 完成后的阶段 2.5 用户拍板 checkpoint、自动调 executor(除非用户显式说「不用 executor」/「直接验收」)
  • ❌ 跳过 executor 直接告诉用户「我做完了」(除非用户显式说「不用 executor」)
  • ❌ 在 generator 失败时自己出手改代码 —— 走重试循环;3 次后交给用户
  • ❌ 自己脑补「这个简单不用走流程」—— 只有用户显式 bypass 才跳

主 agent 可以做的事

  • ✅ 用 Bash 跑 git status / git log / pwd / ls 等只读命令了解状态
  • ✅ Read 任何文件来回答用户的问答类问题
  • ✅ AskUserQuestion 澄清需求 / 让用户在 planner 后拍板 / 报告 executor 失败
  • ✅ 用户在阶段 2.5 闸口挑「起模拟器」时跑 Skill(find-ios-build-artifact) + xcrun simctl install/launch 起 app —— 这是给用户看效果用、不算「自己验证」
  • ✅ 阶段 4A 用户挑「Codex 修」时调 codex:codex-rescue subagent —— 这是调度外部 generator、不是主 agent 自己写代码
  • ✅ 建 worktree、改全局 rule / settings / memory(meta 配置类操作不在本 rule 约束内)
  • ✅ 调 /openpr / /review / /pr-review 等 slash command(这些 command 内部的流程不受本 rule 约束)

Bypass

用户明确说以下任一种话时,本轮跳过对应阶段:

  • 「你直接改」「不用 planner」「跳过 spec」 → 跳 planner,主 agent 直接调 generator(generator 仍要遵守自己的 SOP)
  • 「不用 executor」「我自己 review」 → 跳 executor + 跳过阶段 2.5 闸口,generator 完成后直接进 P4 文档同步问询
  • 「全部你自己来」「这一行你直接改」 → 三段式整体 bypass,主 agent 回到默认行为可以自己 Edit

bypass 必须用户主动说。主 agent 不能自己判断「这个简单不用走流程」。

与现有 rule 的关系

  • use-worktree.md:本 rule 的阶段 0 仍按它执行
  • spec-before-code.md:本 rule 的阶段 1 (planner) 是它的具体执行者;现有 PreToolUse hook 卡 generator 的 Edit(generator 阶段如果 spec 不存在仍会被 hook 拦下)
  • iteration-checkpoint.md:planner 的 AskUserQuestion 是它的具体落地;generator 的「不确定流程」也是
  • parallel-subagents.md:本 rule 的并行模式(阶段 2B / 3B / 3C / 5)是 parallel-subagents 的具体执行路径之一 —— planner 在 spec 第 2 节标注多个 parallel-N 组、用户审 spec 未删除即视同「拆分方案过审」。用户也可以显式发令「拆开并行跑」直接 bypass 三段式走 parallel-subagents。两条入口共用 parallel-subagents 的核心约束(文件边界严格不重叠 / sub-worktree 隔离 / 主 agent 集成验证)。
  • post-change-verify.md:generator 阶段遵守(只跑 build);executor 阶段额外跑 lint
  • architecture-first skill:generator 阶段必 invoke;executor 阶段做 review 时再 invoke 一次
  • review-mobile-ui skill + ui-reviewer agent:UI 验收的独立路径;默认不跑、用户显式触发(关键词「跑下 UI / UI 走查 / UI 验收 / review UI / 看下 UI 对不对」)。验收 verdict blocking,UI fail 走阶段 4 重试;与 executor 平行、互不污染。详见 ~/.claude/skills/review-mobile-ui/SKILL.md~/.claude/agents/ui-reviewer.md

Why(核心)

  • 三个 subagent 独立 context;主 agent 不写代码、只调度 —— 通信走文件(spec / 代码)和主 agent 中转的结构化 message
  • 失败循环上限 = 3 —— 超过说明问题不在代码层,强制升级让用户介入
  • §9 Amendments 与 §1-7 分离 —— 原始需求快照纯净,实现阶段追加走 §9 + 给 executor 明确「DONE 必验 / TODO 跳过」口径
Install via CLI
npx skills add https://github.com/LuoYangcan/pele --skill dispatch-pipeline
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator