name: milestone description: 单元(后端模块 / 前端阶段)全部 approve 后的收尾闸门:子会话跑测试 → 写精简完成报告 → 本地 merge 进默认分支 + 打 milestone/ tag + 回写 docs/08 → 自动回调 coding-start。phase 由当前分支推断。 user-invocable: false
allowed-tools: Read Write Edit Skill Agent Bash(git *)
所有输出必须使用中文。
milestone
单元(后端模块 / 前端阶段)所有功能完成、所有 approve 齐全后的唯一收尾闸门。把原来三个 skill 的职责合并为四个阶段依次执行:
- 推断 phase(分支名 → backend / frontend)
- 测试闸门(子会话跑测试,绿才能继续)
- 精简完成报告(6 节,commit 到当前分支)
- 本地集成 + tag + 回写 docs/08 + 自动回调
阶段 0:推断 phase 与关键变量
执行 git branch --show-current:
- 匹配
module-<id>→phase=backend,phase_id=<id>(去掉module-前缀),tag=milestone/<id>,test_command=./scripts/test.sh - 等于
frontend-phase→phase=frontend,phase_id=frontend-phase,tag=milestone/frontend-phase;test_command从docs/04-技术规范.md § 零 frontend.test_command/frontend.e2e_command拼接(缺失则pnpm test:ci && pnpm e2e:ci) - 其它任何分支 → 硬停,打印以下诊断并终止(分支切换职责在上游
phase-driver,不在此处):
[milestone] ⛔ 当前分支 <branch> 不满足执行条件。
milestone 只能在 module-<id> 或 frontend-phase 分支上运行。
请检查 phase-driver 是否正确切换了分支。
记录变量:branch(原始分支名),phase,phase_id,tag,test_command。
阶段 1:测试闸门(子会话硬门)
护栏(绝对规则):绝不在主会话直接执行测试命令。必须通过 Agent 子会话(general-purpose)运行,主会话只接收结构化 JSON 结论。
- 派发 Agent 子会话,传入
test_command,要求子会话仅返回以下结构化 JSON(不输出任何描述文字):
{
"command": "<实际执行的命令>",
"exit_code": <int>,
"passed": <int>,
"failed": <int>,
"stdout_excerpt": "<最后 30 行,含 FAIL 摘要>"
}
接收 JSON 后保存为本地变量(
test_json),不写独立文件——测试证据将折叠进阶段 2 的报告## ② 测试证据节。exit_code = 0(绿色) → 进入阶段 2。exit_code ≠ 0(红色) → 打印以下横幅并停止,不进入任何下游阶段,不自动重试,不自动修复:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[milestone] ⚠️ 测试未通过 (phase=<phase>)
命令: <test_command>
退出码: <exit_code>
失败: <failed>
摘要: <stdout_excerpt>
按失败类型选恢复路径:
① 测试脆弱(偶发 flakey)→ 重跑 /erp-workflow:coding-start
(phase-driver 幂等:所有单元已 approve 会跳过功能循环,直接重跑本闸门)
② 真有回归
后端:rm docs/superpowers/reviews/*-<REQ-id>.md
→ 重跑 /erp-workflow:coding-start(phase-driver 视该 REQ 未完成,重走功能循环)
前端:rm docs/superpowers/reviews/*-FE-<NN>.md
→ 重跑 /erp-workflow:coding-start(phase-driver 视该 FE 未完成,重走功能循环)
③ 环境 / 依赖问题(DB 连不上 / 外部 API 失败 / 证书失效 / Playwright 浏览器未装)
→ Skill(interrupt-check) 追加 Blocker → 修复环境
→ 参考 .env.local / docs/04 § 零 环境配置 → 重跑
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
阶段 2:精简完成报告
核心约束:只收集 git 摘要,绝不把 diff 正文读入主会话上下文。
2.1 收集输入
后端(phase=backend):
- §③ 文件变更:
bash git diff --stat <branch_start>..HEAD git diff --name-status <branch_start>..HEAD git log --oneline <branch_start>..HEAD<branch_start>= 本模块分支从默认分支分叉的 commit(git merge-base <branch> <default_branch>) - §④ Migration:
git diff --name-only --diff-filter=A <branch_start>..HEAD -- 'sql/migrations/V*.sql'列新增 migration 文件名;若有,逐个 Read 第一行作简短说明。 - §⑤ 偏离:Read
docs/superpowers/reviews/<日期>-<phase_id>-*.md(如存在),提取偏离与取舍说明。 - §① 覆盖单元:扫
docs/superpowers/reviews/下属于本模块的<日期>-<REQ-id>.md,列出 REQ ID 与标题。
前端(phase=frontend):
- §③ 文件变更:同上,区间为
frontend-phase分支起点 → HEAD - §① 覆盖单元:扫
docs/superpowers/reviews/<日期>-FE-*.md,按 FE-NN 顺序列出 - §④ Migration:填
N/A(前端阶段) - §⑤ 偏离:除常规偏离外,额外审查"实际渲染 DOM 与各 FE 关联原型主结构的差异",逐 FE 列出(关联原型清单见每个 FE 的 spec)
2.2 渲染并 commit 报告
按 ${CLAUDE_SKILL_DIR}/templates/milestone-report-template.md 渲染 6 节。{{milestone_tag}} 先填占位符 {{milestone_tag}}(阶段 3 步骤 6 回写)。
写入 docs/superpowers/milestone-reports/<YYYY-MM-DD>-<phase_id>.md。
git add docs/superpowers/milestone-reports/<YYYY-MM-DD>-<phase_id>.md
git commit -m "docs(<phase_id>): add completion report"
此 commit 是必需的——阶段 3 的 worktree-clean 前置检查依赖于此。
阶段 3:本地集成 + tag + 回写 docs/08
3.1 验证 worktree 干净
git status --porcelain
输出非空 → 停止,打印 dirty 文件清单:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[milestone] ⚠️ worktree 不干净,无法集成 + 打里程碑
<git status 输出>
集成前所有 evidence 必须已 commit。检查点:
- 阶段 2 是否已 commit 完成报告?
(阶段 1 测试证据已折叠进报告,无单独文件需 commit)
修复:git add <files> && git commit -m "...",然后重跑 /erp-workflow:coding-start。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3.2 探测本地默认分支
用 git rev-parse --verify 依次探测本地 main、master,取第一个存在的作为 default_branch。两者都不存在 → 停止报错(不自动创建分支)。
3.3 本地 merge
git checkout <default_branch>
git merge --no-ff <branch> -m "merge(<phase_id>): integrate <branch>"
合并冲突 → 停止,打印冲突文件清单,引导人工解决后重跑 /erp-workflow:coding-start(不自动 --abort,不强制覆盖)。
3.4 回写 docs/08 里程碑字段
在 default_branch 上 Edit docs/08-模块任务管理.md:
-
phase=backend:在 § 二 找到当前模块行
- 里程碑: —→- 里程碑: milestone/<phase_id> -
phase=frontend:在 § 三 找到
- 整体里程碑: —→- 整体里程碑: milestone/frontend-phase
git add docs/08-模块任务管理.md
git commit -m "chore(<phase_id>): record milestone/<phase_id> in docs/08"
3.5 打 annotated tag
git tag -a milestone/<phase_id> -m "milestone(<phase_id>): <phase> 阶段完成"
tag 已存在(重跑场景)→ 跳过,不重复打。
3.6 追加 tag 到报告 §⑥ 并 commit
Edit docs/superpowers/milestone-reports/<YYYY-MM-DD>-<phase_id>.md,把 {{milestone_tag}} 替换为 milestone/<phase_id>(已替换则跳过)。
git add docs/superpowers/milestone-reports/<YYYY-MM-DD>-<phase_id>.md
git commit -m "docs(<phase_id>): record milestone/<phase_id> in completion report"
阶段 4:自动回调
本阶段已集成 + 打 tag,不停下等人工。立即调用:
Skill(coding-start)
coding-start 重新检查后端 / 前端完成性(按 里程碑: 字段 + git tag -l),未完则推进下一模块 / 前端阶段;全部完成则打印"所有阶段已完成"。
护栏
-
绝不在主会话直接执行
./scripts/test.sh/pnpm test/pnpm e2e——必须通过 Agent 子会话 - 本闸门是里程碑 tag 前唯一的硬测试门——红色时绝不跳过直接进入集成 / 打 tag
- worktree 不干净时不执行 merge(停下,不修复)
- 合并冲突时不自动解决(停下,指引人工)
参考
-
${CLAUDE_SKILL_DIR}/templates/milestone-report-template.md(6 节精简报告) - 上游:
phase-driver(后端所有 REQ / 前端所有 FE 全部 approve 后派发到此) - 下游:
coding-start(自治回调,由其路由下一阶段)