name: erp-downstream-gen description: A5 下游文档生成——基于 docs/01 和 docs/03 推导,一次性生成 docs/02 + docs/05 + docs/06 § 五 + docs/10,回填 REQ 卡片依赖接口,把模块清单追加到 docs/08 § 二。 user-invocable: false
allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion Bash(cat *)
所有输出必须使用中文。
erp-downstream-gen
前置条件
-
docs/01-需求清单/*.md完整 REQ 卡片已就绪(A1 生成 + 人工审阅过)。 -
docs/03-数据库设计文档.md已就绪(A4 生成)。 -
docs/05/docs/06/docs/10/sql/seed-data.sql等下游文件尚不存在(本 skill 创建)。
执行步骤
步骤 0:打印当前位置流程图
向用户展示当前在 A 阶段流程中的位置(A-only,▶ 标在 A5):
┌──────────────────────────────────────────────────────┐
│ 📋 阶段 A:规划(一次性) │
│ │
│ A0 初始化项目 → A1 锁范围(REQ 卡片) │
│ ↓ │
│ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │
│ ↓ │
│ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → ▶ A5 生成下游文档│
│ ↓ │
│ 规划阶段到此结束 │
└──────────────────────────────────────────────────────┘
A. docs/02 — 开发计划(含 REQ 级开发顺序清单,CC 分发权威)
清单粒度:一行一个 REQ,同一模块的 REQ 必须连续排列。
- 构建模块依赖 DAG:
- docs/03 中的外键(表 A → 表 B ⇒ A 的模块依赖 B 的模块)
- docs/01 README 中的显式
depends_on提示
- 对模块 DAG 做拓扑排序得
module_topo_order[]。 - 对每个模块内部构建 REQ 间依赖(从 REQ 卡片
goal/rules/依赖表推断 REQ-A 是 REQ-B 的前置),得到模块内 REQ 顺序。 - 合成
req_order[]:按module_topo_order[]依次铺开每个模块内的 REQ 序列(同模块 REQ 连续)。 -
环依赖打破:
-
模块级:若模块 DAG 存在环(module_A ↔ module_B),按启发式(字母序 / 被依赖次数多者先)破环排出
module_topo_order,并在参与环的模块里第一个 REQ 的note字段填入原因(如 "A↔B 互依赖:先做 A 的骨架")。 -
REQ 级(同模块内):若模块内 REQ 互依赖,同样破环,
note填原因。 - 非环 REQ
note留—。
-
模块级:若模块 DAG 存在环(module_A ↔ module_B),按启发式(字母序 / 被依赖次数多者先)破环排出
- 为
req_order[]每项生成字段:-
index:行号(从 1 开始) -
req_id:如REQ-SYS-001 -
module_id:该 REQ 所属模块,如module_sys -
rationale(一行选中理由):依赖驱动的简短描述,如所属模块无依赖,基础模块/依赖 REQ-SYS-001 已在前/所属模块依赖 module_sys 已在前 -
note(一行备注):默认—;仅环依赖打破场景填原因
-
- 用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-02-template.md,填充modules[](含id/name/deps/tables)/req_order[](每项含index/req_id/module_id/rationale/note)/notes。 - 写入
docs/02-开发计划.md。
B. docs/05 — API 接口契约
- 用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md,写入docs/05-API接口契约.md头部。 - 对所有模块的每个 REQ:用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md,推断 method / path / auth / permission / 请求和响应 schema(不明确的询问用户),追加到 docs/05。
B2. 回填 REQ 卡片 依赖接口
- 用
Glob列出docs/01-需求清单/*.md(排除README.md)。 - 用
Grep在这些文件中搜索TBD(A5 自动补)的行号(不读全文)。 - 对每个命中的 REQ:
- 用
Read仅读取该 REQ 卡片所在的片段(REQ 标题行前后 20 行),提取req_id。 - 在步骤 B 刚生成的
docs/05-API接口契约.md里 Grep 属于该 REQ 的 endpoint(通过 REQ 标签或 req_id 关联)。 - 用
Edit:依赖接口: TBD(A5 自动补)→依赖接口: POST /api/xxx, GET /api/yyy(具体 method + path 列表,多个用,分隔)。
- 用
- 打印回填统计:
A5 回填 N 处 api_refs。
C. docs/06 — 页面清单
- 对每个有前端页面的模块:用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md,填充pages[](page_name、route、page_type、req_ids、menu_path、interactions)。 - 将每个渲染块追加到
docs/06-UI交互规范.md§ 五。
D. docs/08 § 二 — 追加模块清单
docs/08 已由 A0 erp-project-init 创建(含 Plan 进度骨架)。本步骤只往 § 二 追加模块行,不重写整个文件。
- 用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md(单模块 bullet 行模板)。 -
按
module_id字母序对每个模块:渲染一行 bullet,填充module_id/module_name/depends_on/path_scopes(不含 REQ 列表——REQ 级顺序以 docs/02 § 二 为准;模块完成信号由MR:字段 +glab mr view state判定)。
注意:docs/08 § 二 的行序不决定分发顺序——分发以 docs/02 § 二 为准,此处按字母序仅方便查找。
- 所有模块行拼成一段文本,用
Edit在docs/08-模块任务管理.md的## 二、Coding 阶段(按模块循环)标题后插入(定位用下一行注释"(A5 填入后..."作为锚,把模块清单插到该注释之前)。
E. docs/10 — 验收清单
- 用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md,写入docs/10-验收检查清单.md头部。 - 对每个模块:用
Read读取${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md,填充reqs[]、data_checks[]、ui_checks[],追加。
F. 验证 + 勾选 docs/08 进度 + 终止 Plan 阶段
-
一致性检查:
- docs/01 的每个 REQ 都出现在 docs/05(作为接口,如适用)、docs/10(作为验收项)。
-
docs/02 § 二开发顺序清单的module_id集合 =docs/08 § 二的module_id集合(数量、ID 全等);不相等 → 报错停下,列出差集。
最终占位符扫描(覆盖 Plan 阶段全部产出:
docs/01-需求清单/*.md+docs/02/docs/05/docs/06/docs/10+sql/seed-data.sql):
a. TBD → CC 自动补齐:用 Grep 搜索 TBD(A4 自动补) 和 TBD(A5 自动补)。有命中则按 A4 / B2 同样逻辑就地补填(A4 查 docs/03 填 依赖表:;A5 查 docs/05 按 REQ-ID 填 依赖接口:),再 Grep 确认 0 命中;仍残留报错停下。
b. 【人工填写:...】 → QA 循环等用户补(与 A2 erp-skeleton-gen 步骤 E 同风格):
循环执行直到两个条件**同时满足**:(1) 扫描 0 命中;(2) 用户选「继续」
- **b.1 扫描**:用 `Grep` 在上述所有文件中搜索 `【人工填写:`,得到命中数 N 和残留位置清单(`<文件:行号> — <行内容摘要>`)
- **b.2 打印汇总横幅**:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[erp-downstream-gen] 最终占位符审阅
<N=0 时打印:✅ 全部填完>
<N>0 时打印:⚠️ 还有 N 处待填:
<文件:行号> — <行内容摘要>
...>
需要调整 → 直接编辑对应文件
填完后 → 回来选「继续」放行完成 Plan
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
- **b.3 弹出 QA**:用 `AskUserQuestion` 询问:
- **question**: `最终占位符补填完毕?`
- **options** (每项为对象):
- `{"label": "继续", "description": "放行完成 Plan 阶段"}`
- `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}`
- **b.4 路由**:
- 选「有疑问想先沟通」→ 回答用户问题后**回 b.1 重新扫描**
- 选「继续」→ **回 b.1 重新扫描验证**:
- 新 N = 0 → 进入步骤 3
- 新 N > 0 → 用户以为填完其实还有残留,回 b.2 打印新横幅并再次弹出 QA
关键:**每次弹出 QA 前都重新扫描一次**,用户看到的 N 始终是最新的;只有 N = 0 且选「继续」才放行。
-
用
Edit在docs/08-模块任务管理.md勾选 7 个 checkbox(A5 的 6 个子项 + A5 父项):-
- [ ] docs/02 开发计划已生成→[x] -
- [ ] docs/05 API 契约已生成→[x] -
- [ ] docs/06 § 五 页面清单已填入→[x] -
- [ ] docs/10 验收清单已生成→[x] -
- [ ] 下方模块列表已填入→[x] -
- [ ] REQ 卡片依赖接口已回填→[x] -
- [ ] A5 下游文档生成 — erp-downstream-gen→[x]
-
输出:
downstream-gen: 写入 4 个文件 + <N> 个模块 + <M> 处 REQ 依赖接口回填。打印 Plan 阶段终止横幅并停下(不自动进入 B 阶段):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[erp-downstream-gen] ✅ Plan 阶段(A0~A5)全部完成
所有规划文档已就绪,docs/08 § 一 全部勾选。
⚠️ 进入 B 阶段前必须完成:
1. 人工通读 docs/01~10 + CLAUDE.md + sql/migrations/V1 + 各 scripts/*
2. 把全部 Plan 产物 commit 到 main 分支:
git add -A && git commit -m "chore: plan phase A0~A5 done"
3. 建 Plan MR 提交团队审核,合并后 main 成为 B 阶段每个模块分支的基线
4. MR 合并后再运行 /erp-workflow:erp-coding-start 进入 B 阶段
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
参考
${CLAUDE_SKILL_DIR}/templates/docs-02-template.md${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md-
${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md(模块 bullet 行模板) ${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md