Commit 21e90b624cec13f41fb19f8143da147e43782c19

Authored by zichun
1 parent 4bb71298

fix plan phase

Showing 35 changed files with 655 additions and 552 deletions
README.md
... ... @@ -2,7 +2,7 @@
2 2  
3 3 Claude Code 插件:ERP / 后端管理系统全流程开发框架。
4 4  
5   -把"从零到 N 个模块上线"的整个流程固化成 **21 个 skill + 1 个 agent + 2 个 hook + 37 份模板**,让 CC 在 schema 演化用 Flyway migration、需求可追溯、人工审核可控的前提下推进编码。
  5 +把"从零到 N 个模块上线"的整个流程固化成 **21 个 skill + 1 个 agent + 2 个 hook + 35 份模板**,让 CC 在 schema 演化用 Flyway migration、需求可追溯、人工审核可控的前提下推进编码。
6 6  
7 7 ## 这个插件做什么
8 8  
... ... @@ -44,13 +44,13 @@ Claude Code 插件:ERP / 后端管理系统全流程开发框架。
44 44 ```
45 45 Plan 阶段**三段式**执行,中间有两个人工审阅断点:
46 46  
47   - - **第一段(首次运行)**:执行 **A0 → A1**(创建骨架 / 锁技术栈 / 填需求 / 生成 REQ 卡片骨架)后**停下**,等你审阅并补全 `docs/01-需求清单/<module>/REQ-*.md`(CC 已起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各保留「主表 + 从表1」骨架表,留 `-` 等你按业务补;依赖表 / 依赖接口保留 `TBD(A3/A5 自动补)` 由后续 skill 回填——Plan 阶段第一个人工关口:业务范围)
  47 + - **第一段(首次运行)**:执行 **A0 → A1**(创建骨架 / 锁技术栈 / 填需求 / 生成 REQ 卡片骨架)后**停下**,等你审阅并补全 `docs/01-需求清单/<module>/REQ-*.md`(CC 已起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各含一句简述 + N 张示例字段表,模板原样复制由你按业务编辑;依赖表 / 依赖接口保留 `TBD(A3/A5 自动补)` 由后续 skill 回填——Plan 阶段第一个人工关口:业务范围)
48 48 - **第二段(REQ 审阅完重新运行)**:继续 **A2 → A3**(生成骨架 / 从 REQ 正向设计 `docs/03-数据库设计文档.md` 并回填 REQ 依赖表)后再次**停下**,等你审阅 docs/03 的表 / 字段 / 索引 / 外键(第二个人工关口:数据库 schema —— A4 会基于它翻译 DDL 并 apply 到 MySQL,所以这关口与 REQ 审阅同等重要)
49 49 - **第三段(docs/03 审阅完重新运行)**:执行 **A4 → A5**(解析 docs/03 → 生成 V1 migration → 自动 `DROP+CREATE` 本地 schema 并 apply → 生成下游文档),Plan 完成后再次**停下**
50 50  
51 51 每次运行都会自动接上次停下的地方继续;中途可以随时关闭 CC,下次运行同样的命令即可恢复。Plan 完成后**不会自动进入编码**,需要你手动运行 `/erp-workflow:coding-start`。
52 52  
53   - > 两个审阅断点的勾选位置都在 `docs/08-模块任务管理.md § 一`:A1 审阅完后系统已自动勾选 A1 全部子项;A3 审阅完后需要手动勾选「用户已审阅 docs/03 表结构」+ A3 父项 `[ ]` → `[x]`,下次 `/plan-start` 才会派发到 A4
  53 + > 两个审阅断点的处理方式一致:A1 / A3 完成时 skill 已自动勾选 `docs/08-模块任务管理.md § 一` 该阶段的全部子项 + 顶层;审阅是隐式的——你看完 REQ 卡片 / docs/03 后直接重新运行 `/plan-start`,下次入口就会派发到下一阶段。如果审阅时发现需要修订,直接编辑 docs/01 / docs/03 即可,不依赖 docs/08 的勾选状态
54 54  
55 55 3. **Coding 阶段入口**(模块循环):
56 56 ```
... ... @@ -102,7 +102,7 @@ erp-workflow-plugin/
102 102 | # | Skill | 作用 | 流程中谁调用 |
103 103 |---|---|---|---|
104 104 | A0 | `project-init` | • 依赖检查(`mysql` 在 PATH,缺失则尝试自动安装)<br>• 空目录初始化:`cp` 模板创建 CLAUDE.md / docs/01/index.md / docs/08<br>• `git init` | `plan-start` |
105   -| A1 | `scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引<br>• 按 `docs/01-需求清单/<module>/{_module.md, REQ-*.md}` 子目录结构生成 REQ 卡片骨架(CC 起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各保留「主表 + 从表1」骨架,每张表表头 + 1 行 `-` 等人工补;`依赖表 / 依赖接口` 留 `TBD(A3/A5 自动补)`)<br>• **停下**等人工审阅 + 填输入 / 输出表,审阅完毕用 `/plan-start` 恢复续进 A2 | A0 |
  105 +| A1 | `scope-lock` | • 引导填项目概述 / 技术栈 / 需求索引<br>• 按 `docs/01-需求清单/<module>/{_module.md, REQ-*.md}` 子目录结构生成 REQ 卡片骨架(CC 起草 req_id / title / goal / rules / constraints / acceptance;输入 / 输出 各含一句简述 + N 张示例字段表(输入 7 列 / 输出 3 列),全部原样复制自模板,由人工按业务编辑;`依赖表 / 依赖接口` 留 `TBD(A3/A5 自动补)`)<br>• **停下**等人工审阅 + 改输入 / 输出,审阅完毕用 `/plan-start` 恢复续进 A2 | A0 |
106 106 | A2 | `skeleton-gen` | • 生成架构文档:docs/04 § 一+ / docs/06 / docs/07 / docs/09<br>• 生成工具脚本:scripts/*.sh、.githooks/pre-push、.env.local<br>• 创建 `sql/migrations/` 空目录(Flyway 准备)<br>• 合并 .gitignore(逐行判重) | `plan-start` |
107 107 | A3 | `db-design-gen` | • 从 docs/01 REQ 卡片正向设计 `docs/03-数据库设计文档.md`(schema SSoT)<br>• 回填 REQ 卡片依赖表(`TBD(A3 自动补)` → 实际表名)<br>• **停下**等人工审阅 docs/03,审阅完毕用 `/plan-start` 恢复续进 A4 | A2 |
108 108 | A4 | `db-init` | • LLM 解析 docs/03 → `sql/migrations/V1__initial_schema.sql`(DDL only)<br>• **5 维度全量校验** DDL ↔ docs/03(表名 / 列名+列序 / 类型+nullable+默认值 / 索引名 / FK 名),fail-closed<br>• 验证 MySQL 连接<br>• 调 `scripts/setup-test-db.sh` 复用三层防护(与 B 阶段 test.sh 共用)→ DROP+CREATE 空库<br>• apply V1 + `SHOW TABLES` 行数自检 | A3 |
... ... @@ -177,6 +177,22 @@ erp-workflow-plugin/
177 177 |---|---|---|---|
178 178 | `superpower-code-reviewer` | `superpowers:code-reviewer` 5.0.7 agent,仅改 name | 对 REQ diff 做 AI 自审,产出 `must_fix[]` / `nice_to_have[]` / `gaps` | `feature-review` 步骤 1:`Agent(subagent_type=superpower-code-reviewer)` |
179 179  
  180 +## Banners 清单(7 份,`bash cat` 直接输出,绕开 LLM 复读)
  181 +
  182 +step 0 流程图被抽到独立 `.txt` 文件,SKILL.md 步骤 0 改为 `bash cat` 输出——保证 ASCII 边框对齐不被 LLM 复读破坏 + 减少 LLM 输出 token。
  183 +
  184 +| 所属 Skill | Banner 文件 | 用途 |
  185 +|---|---|---|
  186 +| project-init | `banners/flow.txt` | A 阶段流程图(▶ 标在 A0) |
  187 +| scope-lock | `banners/flow.txt` | A 阶段流程图(▶ 标在 A1) |
  188 +| skeleton-gen | `banners/flow.txt` | A 阶段流程图(▶ 标在 A2) |
  189 +| db-design-gen | `banners/flow.txt` | A 阶段流程图(▶ 标在 A3) |
  190 +| db-init | `banners/flow.txt` | A 阶段流程图(▶ 标在 A4) |
  191 +| downstream-gen | `banners/flow.txt` | A 阶段流程图(▶ 标在 A5) |
  192 +| plan-start | `banners/flow-done.txt` | A 阶段流程图(▶ 标在"规划阶段到此结束",仅 2.1 Plan 完成分支) |
  193 +
  194 +**字节对齐保证**:每个文件 17 行,每行 visible width = 58 cell(内宽 56 + 2 个 `│` 边框)。改动需重新校准。
  195 +
180 196 ## Templates 清单(37 份)
181 197  
182 198 | 所属 Skill | 模板文件 | 用途 |
... ... @@ -185,7 +201,7 @@ erp-workflow-plugin/
185 201 | project-init | `docs-01-index-template.md` | 需求清单索引骨架,等用户填模块表 |
186 202 | project-init | `docs-08-initial-template.md` | 工作流进度文件骨架(Plan A0~A5 checkbox) |
187 203 | project-init | `docs-04-stack-template.md` | docs/04 § 零 默认技术栈总览(零槽位,cp 即可) |
188   -| scope-lock | `req-card-template.md` | 单张 REQ-XXX-NNN 卡片骨架(6 个 `{{...}}` 占位符由 CC 替换;输入 / 输出 各含「主表 + 从表1」骨架表,留 `-` 等人工补) |
  204 +| scope-lock | `req-card-template.md` | 单张 REQ-XXX-NNN 卡片骨架(6 个 `{{...}}` 占位符由 CC 替换;输入 / 输出 各含一句简述 + N 张示例字段表,模板原样复制由人工编辑) |
189 205 | scope-lock | `_module-template.md` | 模块子目录的 `_module.md` 模块头(4 行:模块代码-名 / 简述 / 依赖模块 TBD / 涉及表 TBD) |
190 206 | skeleton-gen | `docs-04-skeleton-template.md` | docs/04 § 一+ 编码规范大纲(HTML 注释引导 LLM) |
191 207 | skeleton-gen | `docs-06-static-template.md` | docs/06 § 一~四 UI 模式大纲 |
... ... @@ -196,7 +212,6 @@ erp-workflow-plugin/
196 212 | skeleton-gen | `githooks-pre-push-template.sh` | pre-push → 调 scripts/test.sh(0 槽位) |
197 213 | skeleton-gen | `env-local-template` | 6 字段凭据模板(DB_* + JWT_SECRET) |
198 214 | skeleton-gen | `gitignore-append-template` | 插件推荐忽略项(`.env.local`、`.tmp/`、构建产物等) |
199   -| db-init | `migration-v1-header-template.sql` | V1 initial migration 文件头部注释 |
200 215 | db-design-gen | `docs-03-header-template.md` | docs/03 数据库设计头部 |
201 216 | db-design-gen | `docs-03-table-template.md` | docs/03 单表小节模板 |
202 217 | downstream-gen | `docs-02-template.md` | docs/02 开发计划 |
... ... @@ -204,10 +219,8 @@ erp-workflow-plugin/
204 219 | downstream-gen | `docs-05-endpoint-template.md` | docs/05 单接口小节 |
205 220 | downstream-gen | `docs-06-module-pagelist-template.md` | docs/06 § 五 单模块页面清单 |
206 221 | downstream-gen | `docs-08-module-row-template.md` | docs/08 § 二 单模块 bullet 行 |
207   -| downstream-gen | `docs-10-header-template.md` | docs/10 验收清单头部 |
208   -| downstream-gen | `docs-10-module-template.md` | docs/10 单模块验收项 |
  222 +| downstream-gen | `docs-10-header-template.md` | docs/10 验收清单(项目级 SOP,零槽位 + 引用指针) |
209 223 | module-start | `module-start-banner-template.md` | 模块启动横幅 |
210   -| module-start | `cross-module-log-template.md` | cross-module 日志头(副本) |
211 224 | feature-brainstorm | `feature-spec-template.md` | 功能 spec 结构 |
212 225 | feature-plan | `feature-plan-template.md` | 功能 plan 结构 |
213 226 | feature-tdd | `commit-message-template.md` | TDD 每步 commit 信息 |
... ... @@ -218,7 +231,7 @@ erp-workflow-plugin/
218 231 | mr-create | `mr-title-template.md` | MR 标题模板 |
219 232 | mr-create | `mr-description-template.md` | MR 描述模板(嵌入模块报告) |
220 233 | interrupt-check | `interrupt-block-template.md` | Blocker 节追加模板 |
221   -| cross-module-log | `cross-module-log-template.md` | cross-module 日志头(主本) |
  234 +| cross-module-log | `cross-module-log-template.md` | cross-module 日志头(由 hook log-cross-module.sh 在首次跨模块改动时渲染创建;skill 自身不再读取) |
222 235 | cross-module-log | `cross-module-log-row-template.md` | 单条改动行模板 |
223 236  
224 237 **流程使用情况**:所有模板都被对应 skill 的 `SKILL.md` 引用,没有孤儿模板。
... ...
hooks/scripts/log-cross-module.sh
... ... @@ -65,12 +65,20 @@ log_dir=&quot;$project_dir/docs/superpowers/module-reports&quot;
65 65 mkdir -p "$log_dir"
66 66 log_file="$log_dir/${current_module}-cross-module.md"
67 67 if [ ! -f "$log_file" ]; then
68   - {
69   - echo "# 跨模块改动日志 — ${current_module}"
70   - echo ""
71   - echo "| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 |"
72   - echo "|---|---|---|---|---|---|"
73   - } > "$log_file"
  68 + # 单一来源:hook 是日志文件的唯一创建者,从插件模板渲染表头。
  69 + plugin_root="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/../.." && pwd)}"
  70 + template="$plugin_root/skills/crosscut/cross-module-log/templates/cross-module-log-template.md"
  71 + if [ -f "$template" ]; then
  72 + sed "s/{{module_name}}/${current_module}/g" "$template" > "$log_file"
  73 + else
  74 + # 模板缺失的兜底(不该发生):写最小可用表头,避免阻塞当前 Edit/Write
  75 + {
  76 + echo "# 跨模块改动日志 — ${current_module}"
  77 + echo ""
  78 + echo "| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 |"
  79 + echo "|---|---|---|---|---|---|"
  80 + } > "$log_file"
  81 + fi
74 82 fi
75 83  
76 84 ts="$(date -u +%FT%TZ)"
... ...
skills/coding/module-start/SKILL.md
... ... @@ -56,25 +56,21 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *
56 56 - 不存在 → `git checkout -b <target_branch>`
57 57 - 若当前工作区有未提交改动且 checkout 失败 → 打印错误并停止(请用户手工处理 dirty state)。
58 58  
59   -### 步骤 4:初始化跨模块日志(幂等)
60   -
61   -`docs/superpowers/module-reports/<module_id>-cross-module.md` — 不存在则从 `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` 创建。
62   -
63   -### 步骤 5:计算已完成 REQ 集合 `done_reqs[]`(幂等断点恢复关键)
  59 +### 步骤 4:计算已完成 REQ 集合 `done_reqs[]`(幂等断点恢复关键)
64 60  
65 61 - 对 `req_list[]` 每个 `req_id`,用 `Glob` 查 `docs/superpowers/reviews/*-<req_id>.md`。
66 62 - 命中后用 `Grep`(pattern `^verdict:\s*approve`,`-i` 不敏感)检查首部 verdict。
67 63 - 两者都命中 → 加入 `done_reqs[]`。
68 64  
69   -### 步骤 6:渲染并打印模块横幅
  65 +### 步骤 5:渲染并打印模块横幅
70 66  
71 67 `Read ${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md`,填充槽位;`reqs[]` 每项的 `status` 字段根据 `done_reqs[]` 填 `x`(已完成)或空格(未完成)。
72 68  
73   -### 步骤 7:推进主循环
  69 +### 步骤 6:推进主循环
74 70  
75 71 - 从 `req_list[]` 取第一个不在 `done_reqs[]` 中的 REQ 作为 `next_req`。
76 72 - **没有 `next_req`**(全部完成)→ 调用 `Skill(test-gate)` 进入模块闸门。
77   -- **有 `next_req`** → 调用 `Skill(feature-brainstorm)` 启动该 REQ 的功能循环。功能循环链(brainstorm → plan → tdd → verify → review)完成后,`feature-review` 在 `verdict=approve` 分支会回调 `Skill(module-start)` —— 再次进入本 skill 时,步骤 5 会把刚通过的 REQ 加入 `done_reqs[]`,步骤 7 自动取下一 REQ,形成可重入推进。
  73 +- **有 `next_req`** → 调用 `Skill(feature-brainstorm)` 启动该 REQ 的功能循环。功能循环链(brainstorm → plan → tdd → verify → review)完成后,`feature-review` 在 `verdict=approve` 分支会回调 `Skill(module-start)` —— 再次进入本 skill 时,步骤 4 会把刚通过的 REQ 加入 `done_reqs[]`,步骤 6 自动取下一 REQ,形成可重入推进。
78 74 - 任何停止条件触发(中断触发 / 测试持续失败 / review 5 轮仍 request-changes)→ 停止本模块,不要静默跳下一 REQ。
79 75  
80 76 ## 参考
... ... @@ -83,5 +79,5 @@ allowed-tools: Read Write Skill Glob Grep Bash(git branch *) Bash(git checkout *
83 79 - `docs/08-模块任务管理.md § 二`(模块元数据,含 `MR:` 字段;完成判定以 MR state 为准)
84 80 - `docs/superpowers/reviews/*.md`(REQ 级进度事实——verdict=approve 即完成)
85 81 - `${CLAUDE_SKILL_DIR}/templates/module-start-banner-template.md`
86   -- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md`
87 82 - 下游:`feature-*`、`test-gate`
  83 +- 注:跨模块日志文件的创建由 `hooks/scripts/log-cross-module.sh` 在首次跨模块改动时按需完成,本 skill 不再做防御性初始化。
... ...
skills/coding/module-start/templates/cross-module-log-template.md deleted
1   -# 跨模块改动日志 — {{module_name}}
2   -
3   -软规则 S2:本模块开发期间对**非当前模块**代码的改动(无论目标模块是否已 MR merged)记录在此;模块完成报告必须单列「跨模块改动」节完整贴入。漏留痕或未评估影响 → 升级为中断。
4   -
5   -**本日志由 CC 自主维护**——hook `log-cross-module.sh` 自动落存根(含 `TBD(CC 补)` 占位),CC 调 `cross-module-log` skill 自主推断补「原因 / 影响评估」两列。**不需要人工填写**。
6   -
7   -| 时间戳 | 目标模块 | 文件 | 改动摘要 | 原因 | 影响评估 |
8   -|---|---|---|---|---|---|
skills/crosscut/coding-start/SKILL.md
... ... @@ -7,20 +7,20 @@ allowed-tools: Skill Read Glob Grep Bash(curl *) Bash(jq *) Bash(git branch *) B
7 7  
8 8 **所有输出必须使用中文。**
9 9  
10   -B 阶段(Coding)的入å£åˆ†å‘器。èŒè´£ï¼š**éªŒè¯ Plan å·²å®Œæˆ â†’ 按 docs/02 § 二 REQ åº + MR state 定ä½å½“剿¨¡å— → åˆ‡å›žé»˜è®¤åˆ†æ”¯å¹¶åŒæ­¥è¿œç¨‹ → æ´¾å‘ module-start**。ä¸ç›´æŽ¥ç”Ÿæˆä»»ä½•文件。开å‘顺åºä»¥ `docs/02 § 二` 为准;完æˆåˆ¤å®šä»¥ `docs/08 æ¡ç›®çš„ MR: 字段 + GitLab API state` 为准(curl 调用,凭æ®è¯» `.env.local` çš„ `GITLAB_API_URL` / `GITLAB_TOKEN` / `GITLAB_PROJECT_ID`)。默认分支(`main` 或 `master`)在步骤 4 自动探测,ä¸ç¡¬ç¼–ç ã€‚
  10 +B 阶段(Coding)的入å£åˆ†å‘器。
11 11  
12 12 ## 执行步骤
13 13  
14 14 ### 步骤 1:确认 docs/08 存在
15 15  
16   -用 `Glob` 检查 `docs/08-模å—任务管ç†.md`。
  16 +检查 `docs/08-模å—任务管ç†.md`存在。
17 17 - ä¸å­˜åœ¨ → 打å°"âš ï¸ é¡¹ç›®å°šæœªåˆå§‹åŒ–,请先è¿è¡Œ `/erp-workflow:plan-start`"å¹¶åœä¸‹ã€‚
18 18  
19 19 ### 步骤 2:Plan å®Œæˆæ€§æ£€æŸ¥
20 20  
21 21 用 `Grep` 在 `docs/08-模å—任务管ç†.md` æœç´¢ `^- \[ \] A[0-5]`(pattern å¯ä»¥ç›´æŽ¥åŒ¹é…父项未勾的情况;也å¯ä»¥ç”¨æ›´å®½çš„ `^[[:space:]]*- \[ \].*A[0-5]` 覆盖å­é¡¹ï¼‰ã€‚
22 22  
23   -- **命中任一 A 未勾** → 打å°ï¼š
  23 +- **命中任一A 阶段未勾选** → 打å°å¹¶åœä¸‹ï¼š
24 24 ```
25 25 â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”
26 26 [coding-start] âš ï¸ Plan 尚未完æˆ
... ... @@ -31,7 +31,6 @@ B 阶段(Coding)的入å£åˆ†å‘器。èŒè´£ï¼š**éªŒè¯ Plan å·²å®Œæˆ â†’ æŒ
31 31 ç»§ç»­ Plan 阶段直到 A5 下游文档生æˆå®Œæˆï¼Œå†å›žæ¥è¿è¡Œ coding-start。
32 32 â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”
33 33 ```
34   - **åœä¸‹**。
35 34  
36 35 - 无命中 → Plan 已完æˆï¼Œè¿›å…¥æ­¥éª¤ 3。
37 36  
... ...
skills/crosscut/cross-module-log/SKILL.md
... ... @@ -18,7 +18,7 @@ allowed-tools: Read Write Edit Bash(git branch *)
18 18 ## 执行步骤
19 19  
20 20 1. 确定当前模块(从当前 git 分支名推导:`git branch --show-current` → `module-<module_id>` → 取 `module_id`。`module-start` 步骤 3 保证本 skill 执行时一定处于 `module-*` 分支)。
21   -2. 打开 `docs/superpowers/module-reports/<current>-cross-module.md`(不存在则从 `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md` 初始化)。
  21 +2. 打开 `docs/superpowers/module-reports/<current>-cross-module.md`。**文件不存在 → 打印 `cross-module-log: 无跨模块改动,跳过` 并退出**(hook 是日志文件的唯一创建者;文件缺失意味着本模块周期内 hook 从未追加过条目,没有 TBD 需要补)。
22 22 3. 找到「原因」或「影响评估」列中含 `TBD(CC 补)` 的行。
23 23 4. 对每个 TBD 行,CC **自主推断**填写以下两列(基于当前 session 的改动上下文 + REQ 卡片 + 目标模块的代码):
24 24 - **原因**:为什么要修改目标模块的代码?当前模块的哪个需求迫使这样做?
... ... @@ -32,6 +32,6 @@ allowed-tools: Read Write Edit Bash(git branch *)
32 32  
33 33 ## 参考
34 34  
35   -- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md`
36   -- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-row-template.md`
  35 +- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-template.md`(仅供 `hooks/scripts/log-cross-module.sh` 创建日志文件时渲染表头;本 skill 自身不再读取)
  36 +- `${CLAUDE_SKILL_DIR}/templates/cross-module-log-row-template.md`(行结构参考,hook 内联拼接行字符串,本 skill 直接编辑已有行)
37 37 - `CLAUDE.md` § 🟡 软规则 S2
... ...
skills/crosscut/plan-start/SKILL.md
... ... @@ -2,7 +2,7 @@
2 2 name: plan-start
3 3 description: A 阶段(Plan)入口与分发器。根据 docs/08 § 一 的 checkbox 状态派发到 A0~A5 对应 skill。Plan 全部完成(A5 已勾)时打印提示让用户运行 /erp-workflow:coding-start 进入 B 阶段。
4 4 user-invocable: true
5   -allowed-tools: Skill Read Glob Grep
  5 +allowed-tools: Skill Read Glob Grep Bash(cat *)
6 6 ---
7 7  
8 8 **所有输出必须使用中文。**
... ... @@ -38,19 +38,13 @@ docs/08 § 一 是**Plan 阶段进度追踪**(A0~A5 的 checkbox)。§ 二
38 38  
39 39 A 阶段所有 checkbox 均 `[x]`。无后续 skill,本步骤**自行打印流程图**,然后**停下**:
40 40  
  41 +```bash
  42 +cat "${CLAUDE_PLUGIN_ROOT}/skills/crosscut/plan-start/banners/flow-done.txt"
41 43 ```
42   -┌──────────────────────────────────────────────────────┐
43   -│ 📋 阶段 A:规划(一次性) │
44   -│ │
45   -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │
46   -│ ↓ │
47   -│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │
48   -│ ↓ │
49   -│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│
50   -│ ↓ │
51   -│ ▶ 规划阶段到此结束 │
52   -└──────────────────────────────────────────────────────┘
53 44  
  45 +再向用户输出完成横幅:
  46 +
  47 +```
54 48 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
55 49 [plan-start] ✅ Plan 阶段全部完成
56 50  
... ...
skills/crosscut/plan-start/banners/flow-done.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ A5 生成下游文档 │
  15 +│ │
  16 +│ ▶ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/db-design-gen/SKILL.md
... ... @@ -2,7 +2,7 @@
2 2 name: db-design-gen
3 3 description: A3 DB 设计 + REQ 回填——基于 docs/01-需求清单/<module>/REQ-*.md 正向设计 docs/03-数据库设计文档.md(业务实体 → 表 + 字段 + 索引 + 外键 + 业务注记),并把回填值写入 REQ 卡片的「依赖表: TBD(A3 自动补)」与模块头的「涉及表: TBD(A3 自动补)」占位。生成完毕停下等人工审阅。
4 4 user-invocable: false
5   -allowed-tools: Read Write Edit Grep Glob Skill AskUserQuestion
  5 +allowed-tools: Read Write Edit Grep Glob Bash(cat *)
6 6 ---
7 7  
8 8 **所有输出必须使用中文。**
... ... @@ -18,74 +18,56 @@ allowed-tools: Read Write Edit Grep Glob Skill AskUserQuestion
18 18  
19 19 ### 步骤 0:打印当前位置流程图
20 20  
21   -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A3):
  21 +用 `Bash` 执行 `cat` 命令向用户展示当前位置流程图(stdout 即 ASCII 框图):
22 22  
23   -```
24   -┌──────────────────────────────────────────────────────┐
25   -│ 📋 阶段 A:规划(一次性) │
26   -│ │
27   -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │
28   -│ ↓ │
29   -│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │
30   -│ ↓ │
31   -│ A2 生成骨架 → ▶ A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│
32   -│ ↓ │
33   -│ ⏸ 等你审阅 docs/03,重新运行 /plan-start 继续 │
34   -└──────────────────────────────────────────────────────┘
  23 +```bash
  24 +cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/db-design-gen/banners/flow.txt"
35 25 ```
36 26  
37 27 ### A. 读取设计输入
38 28  
39   -用 `Read` / `Glob` 读取
  29 +
40 30  
41   -- `docs/04-技术规范.md` § 一+ 命名规范(表名 / 字段名 / 索引名 / 外键名约定,及主键 / 时间戳 / 软删等审计列约定)
42   -- `docs/01-需求清单/index.md` 模块索引(模块代码 ↔ 中文名)
43   -- `docs/01-需求清单/*/REQ-*.md` 所有 REQ 卡片,提取 `req_id` / `goal` / `输入`(主表+从表的字段清单)/ `输出`(主表+从表的字段清单)/ `跨字段规则` / `边界` / `验收`
  31 +- `docs/04-技术规范.md`
  32 +- `docs/01-需求清单/index.md` 模块索引
  33 +- `docs/01-需求清单/*/REQ-*.md` 所有 REQ 卡片
44 34  
45   -### B. LLM 推导 schema
  35 +### B. 推导 schema
46 36  
47 37 基于步骤 A 读到的 REQ + 命名规范,**正向推导**业务实体 → 表 + 字段 + 索引 + 外键。要求:
48 38  
49   -1. **表名 / 列名 / 索引名 / 外键名** 严格套用 `docs/04 § 一+` 的命名规范
50   -2. **审计列**:除明确不需要的辅助表外,每张业务表至少含 `created_at` / `updated_at`;如 `docs/04 § 一+` 约定了 `created_by` / `updated_by` / 软删 `deleted_at`,一并补全
51   -3. **主键**:默认 `id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT`,除非 REQ 明确要求复合主键 / UUID / 业务主键
52   -4. **外键**:依据 REQ 中的引用关系(如「订单引用客户」),明确列出 `ON DELETE` / `ON UPDATE` 策略;不能确定时默认 `RESTRICT`
53   -5. **索引**:根据 REQ 的查询模式(如"按时间范围查"、"按状态筛选")推导业务索引;外键列默认建索引
54   -6. **业务注记**:对每张表用一两句话说明业务用途、关键约束、与其他表的关系
  39 +1. 严格套用 `docs/04` 的命名规范
  40 +2. **主键**:模板内置 `iIncrement` 为主键。REQ 明确要求复合主键 / UUID / 业务主键时按 REQ;其他主键变更需同步改 docs-03-header / docs-03-table 两份模板
  41 +3. **外键**:依据 REQ 中的引用关系(如「订单引用客户」),明确列出 `ON DELETE` / `ON UPDATE` 策略;不能确定时默认 `RESTRICT`
  42 +4. **索引**:根据 REQ 的查询模式推导业务索引;外键列默认建索引;标准列里 `sBrandsId` / `sSubsidiaryId` 这类多租户隔离列,按业务查询模式建组合索引
  43 +5. **业务注记**:对每张表用一两句话说明业务用途、关键约束、与其他表的关系
55 44  
56   -如果某 REQ 表述模糊以致无法推断关键 schema 细节(如:枚举值范围 / 字段长度上限 / 必填性),先按合理默认推导并在该字段「业务含义」列加 `[需用户审阅]` 标注,待步骤 E 用户审阅时调整;**不打断本次推导**。
  45 +如果某 REQ 表述模糊以致无法推断关键 schema 细节(如:枚举值范围 / 字段长度上限 / 必填性),先按合理默认推导并在该字段「业务含义」列加 `【人工填写:需用户审阅】` 标注,待步骤 E 用户审阅时调整;**不打断本次推导**。
57 46  
58 47 ### C. 渲染 docs/03
59 48  
60   -1. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md`,填充 `schema_name`(从 `.env.local` 读 `DB_SCHEMA`,无则填 `【人工填写:DB_SCHEMA】`)、`er_overview`(基于步骤 B 表关系生成的纯文本 ER 概览)。
61   -2. 渲染「表清单」:每行 `- \`<table_name>\` — <一句话用途>`。
62   -3. 对每张表:用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-table-template.md`,填充字段 / 索引 / 外键 / 业务注记。
63   -4. 用 `Write` 写入 `docs/03-数据库设计文档.md`。
  49 +1. 读取 `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md`,填充 `schema_name`(从 `.env.local` 读 `DB_SCHEMA`,无则填 `【人工填写:DB_SCHEMA】`)、`er_overview`(纯文本 ER 概览)。
  50 +2. 渲染「表清单」:对每张表:读取并填充 `${CLAUDE_SKILL_DIR}/templates/docs-03-table-template.md`。
  51 +3. 写入 `docs/03-数据库设计文档.md`。
  52 +
  53 +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
  54 +- ` - [ ] docs/03-数据库设计文档.md 已生成`
64 55  
65 56 ### D. 回填模块头 + REQ 卡片的 TBD 字段
66 57  
67   -1. 用 `Glob` 列出 `docs/01-需求清单/*/_module.md`(模块头)和 `docs/01-需求清单/*/REQ-*.md`(REQ 卡片)。
68   -2. 用 `Grep` 在这些文件中搜索 `TBD(A3 自动补)` 的**行号**(不读全文)。两种行命中:
69   - - `涉及表: TBD(A3 自动补)` → 模块级(仅在 `_module.md`,每文件一次)
70   - - `依赖表: TBD(A3 自动补)` → REQ 级(仅在 `REQ-*.md`,每文件一次)
71   -3. 对每个命中行按类型回填:
72   - - **模块级 `涉及表`**(`_module.md`):用 `Read` 取该文件 `module_code` + `module_name`,聚合步骤 B 中所有归属该模块的表(多表用 `, ` 分隔);`Edit` 替换为 `涉及表: <table1>, <table2>, ...`
73   - - **REQ 级 `依赖表`**(`REQ-*.md`):从文件名直接得 `req_id`(`REQ-USR-001.md` → `REQ-USR-001`);根据步骤 B 推导结果定位该 REQ 关联的表;`Edit` 替换为 `依赖表: <table1>, <table2>`
74   - - **不动** `TBD(A5 自动补)` 的两种行(`依赖接口` REQ 级 / `依赖模块` 模块级)—— 由 A5 `downstream-gen` 生成 docs/05 + 完成模块 DAG 后回填
75   -4. 用 `Grep` 再次扫 `TBD(A3 自动补)` 应 0 命中;仍有残留则打印残留位置清单并停下。
76   -5. 打印回填统计:`A3 回填 <M> 处模块涉及表 + <N> 处 REQ schema_refs`。
  58 +1. 列出 `docs/01-需求清单/*/_module.md`(模块头)和 `docs/01-需求清单/*/REQ-*.md`(REQ 卡片)。
  59 +2. 在这些文件中搜索 `TBD(A3 自动补)` 的并回填。 不动 `TBD(A5 自动补)`
  60 +3. 打印回填统计:`A3 回填 <M> 处模块"涉及表" + <N> 处 REQ"依赖表"`。
77 61  
78   -### E. 勾选 docs/08 自动项 + 停下等人工审阅
  62 +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
  63 +- ` - [ ] docs/01 各 REQ 卡片"依赖表" + 模块头"涉及表" 已回填`
79 64  
80   -1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 2 个自动项(**不勾**第 3 个人工闸门,由用户审阅后自己勾):
81   - - ` - [ ] docs/03-数据库设计文档.md 已生成` → `[x]`
82   - - ` - [ ] docs/01 各 REQ 卡片"涉及数据表"已回填` → `[x]`
83   - - ` - [ ] 用户已审阅 docs/03 表结构` 保持 `[ ]`(人工勾)
84   - - `- [ ] A3 DB 设计 + REQ 回填 — db-design-gen` 保持 `[ ]`(最后一个子项勾后再勾父项)
  65 +### E. 勾选 A3 顶层 + 停下等人工审阅
85 66  
86   -2. 输出 `db-design-gen: docs/03 已生成 + N 处 REQ 已回填依赖表`。
  67 +1. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选 A3 顶层(A3 两个子项已在 C / D 步骤分别勾选):
  68 + - `- [ ] A3 DB 设计 + REQ 回填 — db-design-gen`
87 69  
88   -3. 打印停下横幅并**停下**(**不调** `Skill(db-init)`,A4 由用户审阅后手动恢复)
  70 +2. 打印停下横幅并**停下**
89 71  
90 72 ```
91 73 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
... ... @@ -95,31 +77,22 @@ allowed-tools: Read Write Edit Grep Glob Skill AskUserQuestion
95 77 ✓ docs/03-数据库设计文档.md
96 78 ✓ docs/01-需求清单/<module>/REQ-*.md 依赖表已回填 + _module.md 涉及表已回填
97 79  
98   - ⏸ 现在请你审阅 docs/03(表 / 字段 / 索引 / 外键 / 业务注记)
  80 + ⏸ 现在请你审阅 docs/03
99 81 重点关注:
100 82 - 业务实体覆盖是否完整
101 83 - 字段类型 / 长度 / 是否可空 / 默认值是否合理
102 84 - 索引是否覆盖主要查询模式
103 85 - 外键 ON DELETE / ON UPDATE 策略是否符合业务
104   - - 字段「业务含义」列含 `[需用户审阅]` 标注的位置需逐一确认
  86 + - 字段「业务含义」列含 `【人工填写:需用户审阅】` 标注的位置需逐一确认
105 87  
106   - 审阅完成后,到 docs/08 § 一 把 A3 的「用户已审阅 docs/03 表结构」
107   - 手动勾上(`[ ]` → `[x]`),然后再勾父项 `- [ ] A3 DB 设计 + REQ 回填`,
108   - 再运行:
  88 + 审阅完成后,再运行:
109 89 /erp-workflow:plan-start
110 90  
111   - (入口会读取 docs/08 进度,自动派发到 A4 db-init)
112 91 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
113 92 ```
114 93  
115 94 **停止**,不调用任何下游 skill。
116 95  
117   -## 不变量
118   -
119   -- 本 skill **不连接任何数据库**,纯文档驱动;MySQL 连接验证 / DDL apply 由 A4 `db-init` 负责
120   -- REQ 卡片的 `依赖接口` 字段不在此处填充,留给 A5 `downstream-gen` 在生成 docs/05 后按 `TBD(A5 自动补)` 回填
121   -- DB 设计与 REQ 卡片同等重要,必须留出人工审阅闸门,避免 LLM 推导的表结构未经把关就被 A4 翻译成 DDL 并 apply 到 MySQL
122   -
123 96 ## 参考
124 97  
125 98 - `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md`
... ...
skills/plan/db-design-gen/banners/flow.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ ▶ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ A5 生成下游文档 │
  15 +│ │
  16 +│ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/db-design-gen/templates/docs-03-header-template.md
1 1 # 03-数据库设计文档
2 2  
3   -Schema: `{{schema_name}}`
4   -Migration 清单: `sql/migrations/V*.sql`(由 Flyway 顺序 apply)
5   -生成方式: 由 A3 `db-design-gen` 基于 `docs/01-需求清单/<module>/REQ-*.md` REQ 卡片正向设计生成(schema SSoT)。
  3 +- **Schema**: `{{schema_name}}`
  4 +- **Migration 清单**: `sql/migrations/V*.sql`(由 Flyway 顺序 apply)
  5 +- **生成方式**: 由 A3 `db-design-gen` 基于 `docs/01-需求清单/<module>/REQ-*.md` REQ 卡片正向设计生成(schema SSoT)。
  6 +
  7 +## 项目标准列约定
  8 +
  9 +下文每张业务表的字段清单都自动包含以下 5 个标准列(匈牙利前缀 `i` int / `s` varchar / `t` datetime)。渲染时由 `docs-03-table-template.md` 模板内置原样输出。
  10 +
  11 +| 列名 | 类型 | 可空 | 主键 | 说明 |
  12 +|---|---|---|---|---|
  13 +| `iIncrement` | int | 否 | 是 | 整数主键 ID(自增方式由实现决定:DB `AUTO_INCREMENT` 或应用 / 触发器分配) |
  14 +| `sId` | varchar(100) | 是 | — | 业务 ID(对外暴露的字符串标识,如 UUID / 人类可读编号) |
  15 +| `sBrandsId` | varchar(100) | 是 | — | 品牌 ID(多租户隔离) |
  16 +| `sSubsidiaryId` | varchar(100) | 是 | — | 子公司 ID(组织层级隔离) |
  17 +| `tCreateDate` | datetime | 否 | — | 记录创建时间 |
  18 +
  19 +字典 / 辅助表如有豁免,在该表业务注记里注明豁免原因。
6 20  
7 21 ## ER 关系概览
8 22  
... ...
skills/plan/db-design-gen/templates/docs-03-table-template.md
... ... @@ -4,6 +4,11 @@
4 4  
5 5 | 字段 | 类型 | Nullable | 默认 | 业务含义 |
6 6 |---|---|---|---|---|
  7 +| `iIncrement` | int | 否 | — | 整数主键 ID(标准列) |
  8 +| `sId` | varchar(100) | 是 | — | 业务 ID(标准列) |
  9 +| `sBrandsId` | varchar(100) | 是 | — | 品牌 ID(多租户隔离,标准列) |
  10 +| `sSubsidiaryId` | varchar(100) | 是 | — | 子公司 ID(组织层级隔离,标准列) |
  11 +| `tCreateDate` | datetime | 否 | — | 创建时间(标准列) |
7 12 {{#each columns}}
8 13 | {{name}} | {{type}} | {{nullable}} | {{default}} | {{business_meaning}} |
9 14 {{/each}}
... ...
skills/plan/db-init/SKILL.md
... ... @@ -2,111 +2,76 @@
2 2 name: db-init
3 3 description: A4 DB 初始化——LLM 解析 docs/03-数据库设计文档.md → 生成 sql/migrations/V1__initial_schema.sql(DDL only,Flyway 初始 migration)→ 全量校验 DDL ↔ docs/03 一致性 → 验证 MySQL 连接 → 调 scripts/setup-test-db.sh 复用三层防护并 DROP+CREATE 空库 → apply V1。
4 4 user-invocable: false
5   -allowed-tools: Read Write Edit Glob Skill Bash(mkdir *) Bash(mysql *) Bash(set *) Bash(. .env.local) Bash(sed *) Bash(cat *) Bash(grep *) Bash(./scripts/setup-test-db.sh)
  5 +allowed-tools: Read Write Edit Glob Skill Bash(mkdir *) Bash(mysql *) Bash(set *) Bash(. .env.local) Bash(grep *) Bash(bash *) Bash(./scripts/setup-test-db.sh) Bash(cat *)
6 6 ---
7 7  
8 8 **所有输出必须使用中文。**
9 9  
10 10 # db-init
11 11  
12   -## 前置条件
13   -
14   -- A3 `db-design-gen` 已完成:`docs/03-数据库设计文档.md` 已生成,用户已审阅,docs/08 § 一 A3 全部 checkbox 均 `[x]`。
15   -- A2 `skeleton-gen` 已完成:`.env.local` 已存在(含 `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_SCHEMA`)。
16   -
17 12 ## 执行步骤
18 13  
19 14 ### 步骤 0:打印当前位置流程图
20 15  
21   -向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A4):
  16 +用 `Bash` 执行 `cat` 命令向用户展示当前位置流程图(stdout 即 ASCII 框图):
22 17  
23   -```
24   -┌──────────────────────────────────────────────────────┐
25   -│ 📋 阶段 A:规划(一次性) │
26   -│ │
27   -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │
28   -│ ↓ │
29   -│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │
30   -│ ↓ │
31   -│ A2 生成骨架 → A3 生成 DB 设计 → ▶ A4 初始化 DB → A5 生成下游文档│
32   -│ ↓ │
33   -│ 规划阶段最后一步:A5 由本 skill 末尾自动调起 │
34   -└──────────────────────────────────────────────────────┘
  18 +```bash
  19 +cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/db-init/banners/flow.txt"
35 20 ```
36 21  
37 22 ### A. DDL 生成(不依赖数据库连接)
38 23  
39   -#### A.1 读 docs/03 并 LLM 翻译为 DDL
  24 +#### A.1 读 docs/03 并翻译为 DDL
40 25  
41   -用 `Read` 读取 `docs/03-数据库设计文档.md`,按字段 / 索引 / 外键 / 业务注记**严格翻译**为:
  26 +读取 `docs/03-数据库设计文档.md`,按字段 / 索引 / 外键 / 业务注记**严格翻译**为:
42 27  
43   -- 每张表一段 `CREATE TABLE \`<name>\` (...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='<业务用途>';`
  28 +- 每张表一段 `CREATE TABLE`
44 29 - 字段顺序与 docs/03 表格行序一致;`Nullable` 列直接映射 `NOT NULL` / `NULL`;`默认` 列映射 `DEFAULT <value>`;列尾用 `COMMENT '<业务含义>'` 写注释
45   -- 索引:在表创建后追加 `CREATE [UNIQUE] INDEX \`<name>\` ON \`<table>\` (<cols>);`(主键 / 唯一约束已在 CREATE TABLE 内联的不重复声明)
46   -- 外键:在所有表创建完成后**统一追加**:`ALTER TABLE \`<from_table>\` ADD CONSTRAINT \`<name>\` FOREIGN KEY (\`<from_col>\`) REFERENCES \`<to_table>\` (\`<to_col>\`) ON DELETE <policy>;`(避免顺序问题)
  30 +- 索引
  31 +- 外键:在所有表创建完成后**统一追加**
47 32  
48 33 要求:
49 34 - **严禁臆造** docs/03 中没有的表 / 字段 / 索引 / 外键
50 35 - **严禁省略** docs/03 中已有的列、注释或约束
51 36 - 字符集统一 `utf8mb4` + `utf8mb4_unicode_ci`,引擎统一 `InnoDB`,除非 docs/03 业务注记明确要求其他设置
52 37  
53   -#### A.2 拼装 V1 文件
  38 +#### A.2 落盘 V1 文件
54 39  
55   -用 `Bash` 拼装最终文件:
  40 +`Bash`: `mkdir -p sql/migrations`。
56 41  
57   -```bash
58   -mkdir -p sql/migrations
59   -PROJECT="<从 CLAUDE.md 读到的项目名称>"
60   -TS="$(date -u +%FT%TZ)"
61   -set -a; . .env.local; set +a
62   -{
63   - sed -e "s|{{project_name}}|$PROJECT|g" \
64   - -e "s|{{timestamp}}|$TS|g" \
65   - -e "s|{{schema_name}}|$DB_SCHEMA|g" \
66   - "${CLAUDE_SKILL_DIR}/templates/migration-v1-header-template.sql"
67   - echo ""
68   - cat <<'DDL_EOF'
69   -<把 A.1 推导出的 CREATE TABLE / CREATE INDEX / ALTER ADD FK 全部按顺序粘贴在此>
70   -DDL_EOF
71   -} > sql/migrations/V1__initial_schema.sql
72   -```
  42 +用 `Write` 写 `sql/migrations/V1__initial_schema.sql`,内容 = 头部注释 + DDL 主体:
73 43  
74   -#### A.3 全量校验 DDL ↔ docs/03 一致性
  44 +1. **头部注释**(6 行 SQL 注释):
  45 + - `-- Flyway migration V1 — initial schema for <project_name>`(从 `CLAUDE.md § 🎯 项目概述` 读)
  46 + - `-- Generated: <YYYY-MM-DDTHH:MM:SSZ>`(UTC ISO 8601 时间戳)
  47 + - `-- Source: 由 A4 db-init 从 docs/03-数据库设计文档.md 翻译生成(schema SSoT 是 docs/03)`
  48 + - `-- This is the FIRST migration; subsequent schema changes must be written as new files sql/migrations/V2__<desc>.sql, V3__... etc.`
  49 + - `-- Apply: Flyway runs this automatically at Spring Boot startup.`
  50 + - `-- Do not hand-edit this file after it is committed; write a new migration instead.`
75 51  
76   -5 维度全量校验。**任一不一致** → 报错停下,**列出全部差异明细**;V1.sql 保留以便人工 diff
  52 +2. **DDL 主体**:A.1 推导出的所有 `CREATE TABLE` → `CREATE INDEX` → `ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY`,按此顺序拼接
77 53  
78   -1. **表名集合相等**
79   - - `S_doc` = grep `^## \`<name>\`` of docs/03
80   - - `S_sql` = grep `CREATE TABLE \`<name>\`` of V1
81   - - `S_doc - S_sql` 非空(漏表)/ `S_sql - S_doc` 非空(多表)→ 报错列出差集
  54 +#### A.3 校验 V1 ↔ docs/03 集合一致性 + 自主修正
82 55  
83   -2. **每张表全列名 + 列序相等**(**遍历 S_sql 全部表,无抽样**)
84   - - 对每张表 t:
85   - - 从 docs/03 抽该表 `### 字段` 表格行序,得 `cols_doc[t]`
86   - - 从 V1 抽该 `CREATE TABLE` 段内 `\`<col>\`` 出现序,得 `cols_sql[t]`
87   - - **数组相等**(含顺序);不等则列出 `<table>: docs=[...], sql=[...]`
  56 +调 `${CLAUDE_SKILL_DIR}/scripts/validate.sh` 做脚本化的校验:
88 57  
89   -3. **每个字段类型 / Nullable / 默认值一致**
90   - - 对每个 `<table>.<col>`,归一化后字符串比对。归一化规则:
91   - - 类型主词转小写(`BIGINT` → `bigint`)
92   - - `UNSIGNED` 保留为小写
93   - - 显示宽度 `INT(11)` → `int`(去括号)
94   - - Nullable:docs/03 `否` ↔ DDL `NOT NULL`;docs/03 `是` ↔ DDL 无 `NOT NULL`
95   - - 默认值:去多余空格 + 统一大小写
96   - - **`COMMENT` / `COLLATE` / `CHARSET` 不参与比对**(避免装饰差异误报)
97   - - 不一致 → 列出 `<table>.<col>: docs=<X>, ddl=<Y>`
98   -
99   -4. **每张表索引名集合相等**
100   - - `idx_doc[t]` = docs/03 该表 `### 索引` 列表的名字
101   - - `idx_sql[t]` = V1 中归属该表的 `CREATE INDEX <name>` + inline `KEY \`<name>\` / UNIQUE KEY \`<name>\``(排除 `PRIMARY` 自动名)
102   - - 集合不等 → 报错列出差集
  58 +```bash
  59 +bash "${CLAUDE_SKILL_DIR}/scripts/validate.sh" \
  60 + sql/migrations/V1__initial_schema.sql \
  61 + docs/03-数据库设计文档.md
  62 +```
103 63  
104   -5. **外键名集合相等**(全局,不分表)
105   - - `fk_doc` = docs/03 各表 `### 外键` 列表的所有名字
106   - - `fk_sql` = V1 中所有 `ADD CONSTRAINT \`<name>\` FOREIGN KEY` 的名字
107   - - 集合不等 → 报错列出差集
  64 +退出码与处理:
  65 +- `0` → 通过,进入步骤 B
  66 +- `1` → **自主修正循环**(最多 3 轮,docs/03 是 SSoT 不动):
  67 + 1. 解析 stderr 差异清单,修正 V1.sql
  68 + 2. 重跑 validate.sh
  69 + 3. 退出 0 → 进入 B;退出 1 且本轮 < 3 → 回步骤 1;本轮 ≥ 3 仍失败 → 停下,打印最终残留差异 + 已尝试的 3 轮修正摘要,让用户介入
  70 +- `2` → 用法错(V1 / docs 路径找不到),打印路径并停下
108 71  
109   -校验全部通过 → 进入步骤 B。**任一维度不通过都不许继续**;提示用户 diff `docs/03` ↔ `V1.sql` 后修正 docs/03(SSoT),重跑 A3 让 `db-design-gen` / 本 skill 重新生成 V1。
  72 +完成后(V1 写入并通过 validate.sh 校验),用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
  73 +- ` - [ ] sql/migrations/V1__initial_schema.sql 已生成`
  74 +- ` - [ ] DDL 与 docs/03 全量一致`
110 75  
111 76 ### B. 数据库环境检查
112 77  
... ... @@ -126,8 +91,6 @@ done
126 91  
127 92 任一缺失 → 打印缺失字段名并停下,提示用户编辑 `.env.local` 后重跑。
128 93  
129   -> 注:密码中含 `$`、`` ` ``、空格、`!` 等字符时,`.env.local` 需用单引号包裹,例如 `DB_PASSWORD='p@ss$w0rd!'`。`set -a; . file; set +a` 与 `source` 行为一致但更明确,配合单引号可避免特殊字符被 shell 展开。
130   -
131 94 #### B.2 验证 MySQL 连接
132 95  
133 96 ```bash
... ... @@ -136,26 +99,19 @@ mysql -h&quot;$DB_HOST&quot; -P&quot;$DB_PORT&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; -e &quot;SELECT 1;&quot;
136 99 ```
137 100  
138 101 - **成功** → 进入步骤 C
139   -- **失败** → 打印具体错误(认证 / 主机不可达 / 端口拒接等),提示检查 `.env.local`,**停下**。`sql/migrations/V1__initial_schema.sql` 已在步骤 A 落盘,用户可在修复连接后手动 `mysql < V1.sql`,无需重跑 A4 的 DDL 生成
  102 +- **失败** → 打印具体错误(认证 / 主机不可达 / 端口拒接等),提示检查 `.env.local`,**停下**。
140 103  
141   -### C. 自动导入 MySQL
  104 +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
  105 +- ` - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)`
142 106  
143   -#### C.1 调 setup-test-db.sh 做防护 + DROP+CREATE 空库
144   -
145   -A2 `skeleton-gen` 已生成 `scripts/setup-test-db.sh`,内置三层防护(**单一真相源,与 B 阶段 test.sh 共用同款规则**):
146   -- 防护 1:host 白名单(默认 `localhost / 127.0.0.1 / ::1`,严格相等匹配;可通过 `.env.local` 的 `TEST_DB_ALLOWED_HOSTS` 显式扩展)
147   -- 防护 2:schema 命名后缀检查(必须含 `test` 或以 `_dev / _local / _ci` 结尾)
148   -- 防护 3:远程 host DROP 警告横幅
  107 +### C. 自动导入 MySQL
149 108  
150   -直接调用,由它处理凭据加载 + 三层防护 + DROP+CREATE:
  109 +#### C.1 DROP+CREATE 空库
151 110  
152 111 ```bash
153 112 ./scripts/setup-test-db.sh
154 113 ```
155 114  
156   -任一防护失败 → 脚本自身停下并打印明细(host 不在白名单 / schema 名不像测试库 / `.env.local` 缺失等),本 skill **立即停下不做后续步骤**。
157   -`sql/migrations/V1__initial_schema.sql` 已在步骤 A 落盘,用户调整 `.env.local`(如 `TEST_DB_ALLOWED_HOSTS` 加 host)或 schema 命名后可直接重跑 A4,无需重新生成 V1。
158   -
159 115 #### C.2 把 V1 灌入已清空的 schema
160 116  
161 117 ```bash
... ... @@ -166,6 +122,9 @@ mysql -h&quot;$DB_HOST&quot; -P&quot;$DB_PORT&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; &quot;$DB_SCHEMA&quot; \
166 122  
167 123 非零退出 → 报错停下,打印 mysql stderr。
168 124  
  125 +完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选:
  126 +- ` - [ ] setup-test-db.sh 防护通过 + DROP+CREATE + apply V1 已执行`
  127 +
169 128 #### C.3 自检 SHOW TABLES
170 129  
171 130 ```bash
... ... @@ -180,28 +139,16 @@ EXPECTED=$(grep -c &#39;^## `&#39; docs/03-数据库设计文档.md)
180 139  
181 140 ### D. 勾选 docs/08 进度 + 进入 A5
182 141  
183   -1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 5 个 checkbox(A4 的 4 个子项 + A4 父项):
184   - - ` - [ ] sql/migrations/V1__initial_schema.sql 已生成` → `[x]`
185   - - ` - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)` → `[x]`
186   - - ` - [ ] setup-test-db.sh 防护通过 + DROP+CREATE + apply V1 已执行` → `[x]`
187   - - ` - [ ] SHOW TABLES 行数 == docs/03 表数量` → `[x]`
188   - - `- [ ] A4 DB 初始化 — db-init` → `[x]`
189   -
190   -2. 输出 `db-init: 完成(V1 ✓, schema=<名称>, tables=<T>,已 apply 到本地 MySQL)`。
191   -
192   -3. 立即调用 `Skill(downstream-gen)` 进入 A5,不等用户手动输入。
193 142  
194   -## 不变量
  143 +1. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选(A4 子项 + A4 顶层):
  144 + - ` - [ ] SHOW TABLES 行数 == docs/03 表数量`
  145 + - `- [ ] A4 DB 初始化 — db-init`
195 146  
196   -- **DDL 来源唯一**:V1 完全由 docs/03 翻译而来;docs/03 是 schema 单一真相源(SSoT)。后续 V2/V3 由 B 阶段 `feature-tdd` 在 REQ 实现时写入,并**同步**回写 docs/03 对应表小节
197   -- **测试夹具归属 B 阶段**:测试数据由 B 阶段每个 REQ 在自己的测试代码 / Spring `@Sql` / testcontainers fixture 中按需提供
198   -- **安全守护单一真相源**:DROP / 写操作的防护逻辑统一在 `scripts/setup-test-db.sh`(三层防护:host 白名单 + schema 命名后缀 + 远程 host 横幅),本 skill 与 B 阶段 `test.sh` 共用同一份规则;本 skill 不重复实现防护
199   -- **DDL 校验 fail-closed**:A.3 5 维度全量校验任一不通过都不许进入 apply 阶段
200   -- **失败可恢复**:每次重跑都从空库 `DROP+CREATE` 开始;中途失败重跑无状态残留
  147 +2. 立即调用 `Skill(downstream-gen)` 进入 A5,不等用户手动输入。
201 148  
202 149 ## 参考
203 150  
204   -- `${CLAUDE_SKILL_DIR}/templates/migration-v1-header-template.sql`(V1 头部注释
  151 +- `${CLAUDE_SKILL_DIR}/scripts/validate.sh`(A.3 表名 + 每表列名集合校验脚本
205 152 - `docs/03-数据库设计文档.md`(DDL 翻译输入,SSoT)
206 153 - `.env.local`(DB 凭据)
207 154 - 产物:`sql/migrations/V1__initial_schema.sql`(由 Flyway 在 Spring Boot 启动时验证 / apply)
... ...
skills/plan/db-init/banners/flow.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ ▶ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ A5 生成下游文档 │
  15 +│ │
  16 +│ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/db-init/scripts/validate.sh 0 → 100644
  1 +#!/usr/bin/env bash
  2 +# validate.sh — 校验 V1.sql 与 docs/03 的两个集合一致性:
  3 +# 维度 1: 表名集合
  4 +# 维度 2: 每张共有表的列名集合
  5 +#
  6 +# 用法: bash validate.sh <V1.sql> <docs/03 path>
  7 +# 退出码:
  8 +# 0 = 一致
  9 +# 1 = 不一致(差异明细打印到 stderr)
  10 +# 2 = 用法错误(路径找不到等)
  11 +
  12 +set -uo pipefail
  13 +export LC_ALL=C # sort / comm 行为确定
  14 +
  15 +V1=${1:?missing V1 sql path}
  16 +DOC=${2:?missing docs/03 path}
  17 +
  18 +[ -f "$V1" ] || { echo "validate.sh: V1 not found: $V1" >&2; exit 2; }
  19 +[ -f "$DOC" ] || { echo "validate.sh: docs not found: $DOC" >&2; exit 2; }
  20 +
  21 +ERR=0
  22 +
  23 +# ─── 维度 1: 表名集合 ───────────────────────────────────────────
  24 +TABLES_DOC=$(grep -E '^## `[^`]+`' "$DOC" \
  25 + | sed -E 's/^## `([^`]+)`.*/\1/' | sort -u)
  26 +TABLES_SQL=$(grep -E '^CREATE TABLE `[^`]+`' "$V1" \
  27 + | sed -E 's/^CREATE TABLE `([^`]+)`.*/\1/' | sort -u)
  28 +
  29 +ONLY_DOC=$(comm -23 <(echo "$TABLES_DOC") <(echo "$TABLES_SQL"))
  30 +ONLY_SQL=$(comm -13 <(echo "$TABLES_DOC") <(echo "$TABLES_SQL"))
  31 +
  32 +if [ -n "$ONLY_DOC" ] || [ -n "$ONLY_SQL" ]; then
  33 + {
  34 + echo "=== 维度 1: 表名集合不一致 ==="
  35 + [ -n "$ONLY_DOC" ] && { echo " docs/03 有但 V1 无:"; echo "$ONLY_DOC" | sed 's/^/ - /'; }
  36 + [ -n "$ONLY_SQL" ] && { echo " V1 有但 docs/03 无:"; echo "$ONLY_SQL" | sed 's/^/ - /'; }
  37 + } >&2
  38 + ERR=1
  39 + # 表数差异 → 不再做列校验
  40 + exit 1
  41 +fi
  42 +
  43 +# ─── 维度 2: 每张共有表的列名集合 ──────────────────────────────
  44 +COMMON=$(comm -12 <(echo "$TABLES_DOC") <(echo "$TABLES_SQL"))
  45 +
  46 +extract_doc_cols() {
  47 + local table=$1
  48 + awk -v t="$table" '
  49 + $0 ~ "^## `" t "`" { in_table=1; in_fields=0; next }
  50 + in_table && /^## `/ { exit }
  51 + in_table && /^### 字段/ { in_fields=1; next }
  52 + in_table && in_fields && /^###/ { in_fields=0 }
  53 + in_table && in_fields && /^\|/ {
  54 + n = split($0, a, "|")
  55 + gsub(/^[ ]+|[ ]+$/, "", a[2])
  56 + gsub(/`/, "", a[2])
  57 + if (a[2] != "" && a[2] != "字段" && a[2] !~ /^-+$/) print a[2]
  58 + }
  59 + ' "$DOC" | sort -u
  60 +}
  61 +
  62 +extract_sql_cols() {
  63 + local table=$1
  64 + awk -v t="$table" '
  65 + $0 ~ "^CREATE TABLE `" t "`" { in_table=1; next }
  66 + in_table && /^\)/ { in_table=0; next }
  67 + in_table && /^[[:space:]]*`[^`]+`/ \
  68 + && $0 !~ /^[[:space:]]*(PRIMARY|UNIQUE|KEY|FOREIGN|CONSTRAINT|INDEX)/ {
  69 + match($0, /`[^`]+`/)
  70 + print substr($0, RSTART+1, RLENGTH-2)
  71 + }
  72 + ' "$V1" | sort -u
  73 +}
  74 +
  75 +while IFS= read -r t; do
  76 + [ -z "$t" ] && continue
  77 + D_COLS=$(extract_doc_cols "$t")
  78 + S_COLS=$(extract_sql_cols "$t")
  79 + ONLY_D=$(comm -23 <(echo "$D_COLS") <(echo "$S_COLS"))
  80 + ONLY_S=$(comm -13 <(echo "$D_COLS") <(echo "$S_COLS"))
  81 + if [ -n "$ONLY_D" ] || [ -n "$ONLY_S" ]; then
  82 + {
  83 + echo "=== 维度 2: 表 \`$t\` 列名不一致 ==="
  84 + [ -n "$ONLY_D" ] && { echo " docs/03 有但 V1 无:"; echo "$ONLY_D" | sed 's/^/ - /'; }
  85 + [ -n "$ONLY_S" ] && { echo " V1 有但 docs/03 无:"; echo "$ONLY_S" | sed 's/^/ - /'; }
  86 + } >&2
  87 + ERR=1
  88 + fi
  89 +done <<< "$COMMON"
  90 +
  91 +if [ $ERR -ne 0 ]; then
  92 + exit 1
  93 +fi
  94 +
  95 +echo "validate.sh: ✓ 表名集合 + 每表列名集合 与 docs/03 一致"
  96 +exit 0
... ...
skills/plan/db-init/templates/migration-v1-header-template.sql deleted
1   --- Flyway migration V1 — initial schema for {{project_name}}
2   --- Generated: {{timestamp}}
3   --- Source: 由 A4 `db-init` 从 `docs/03-数据库设计文档.md` 翻译生成(schema SSoT 是 docs/03)
4   --- This is the FIRST migration; subsequent schema changes must be written
5   --- Apply: Flyway runs this automatically at Spring Boot startup.
6   --- Do not hand-edit this file after it is committed; write a new migration instead.
7   --- =========================================================
skills/plan/downstream-gen/SKILL.md
... ... @@ -2,49 +2,29 @@
2 2 name: downstream-gen
3 3 description: A5 下游文档生æˆâ€”—基于 docs/01 å’Œ docs/03 æŽ¨å¯¼ï¼Œä¸€æ¬¡æ€§ç”Ÿæˆ docs/02 + docs/05 + docs/06 § 五 + docs/10,回填 REQ å¡ç‰‡ä¾èµ–接å£ï¼ŒæŠŠæ¨¡å—清å•追加到 docs/08 § 二。
4 4 user-invocable: false
5   -allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion Bash(cat *) Bash(git remote *)
  5 +allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion Bash(cat *) Bash(cp *)
6 6 ---
7 7  
8 8 **所有输出必须使用中文。**
9 9  
10 10 # downstream-gen
11 11  
12   -## å‰ç½®æ¡ä»¶
13   -
14   -- `docs/01-需求清å•/<module>/_module.md` + `docs/01-需求清å•/<module>/REQ-*.md` 完整 REQ å¡ç‰‡å·²å°±ç»ªï¼ˆA1 ç”Ÿæˆ + 人工审阅过 + A3 已回填ä¾èµ–表)。
15   -- `docs/03-æ•°æ®åº“设计文档.md` 已就绪(A3 ç”Ÿæˆ + 人工审阅过)。
16   -- `sql/migrations/V1__initial_schema.sql` 已生æˆå¹¶ apply(A4 完æˆï¼‰ã€‚
17   -- `docs/05` / `docs/06 § 五` / `docs/10` 等下游文件尚ä¸å­˜åœ¨ï¼ˆæœ¬ skill 创建)。
18   -
19 12 ## 执行步骤
20 13  
21 14 ### 步骤 0:打å°å½“å‰ä½ç½®æµç¨‹å›¾
22 15  
23   -å‘用户展示当å‰åœ¨ A 阶段æµç¨‹ä¸­çš„ä½ç½®ï¼ˆA-only,`â–¶` 标在 A5):
  16 +用 `Bash` 执行 `cat` 命令å‘用户展示当å‰ä½ç½®æµç¨‹å›¾ï¼ˆstdout å³ ASCII 框图):
24 17  
25   -```
26   -┌──────────────────────────────────────────────────────â”
27   -│ 📋 阶段 A:规划(一次性) │
28   -│ │
29   -│ A0 åˆå§‹åŒ–项目 → A1 é”范围(REQ å¡ç‰‡ï¼‰ │
30   -│ ↓ │
31   -│ ⸠等你审阅 REQï¼Œé‡æ–°è¿è¡Œ /plan-start ç»§ç»­ │
32   -│ ↓ │
33   -│ A2 生æˆéª¨æž¶ → A3 ç”Ÿæˆ DB 设计 → A4 åˆå§‹åŒ– DB → â–¶ A5 生æˆä¸‹æ¸¸æ–‡æ¡£â”‚
34   -│ ↓ │
35   -│ è§„åˆ’é˜¶æ®µåˆ°æ­¤ç»“æŸ â”‚
36   -└──────────────────────────────────────────────────────┘
  18 +```bash
  19 +cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/downstream-gen/banners/flow.txt"
37 20 ```
38 21  
39   -### A. docs/02 — å¼€å‘è®¡åˆ’ï¼ˆå« REQ 级开å‘é¡ºåºæ¸…å•,CC åˆ†å‘æƒå¨ï¼
  22 +### A. docs/02 — å¼€å‘è®¡åˆ’ï¼ˆå« REQ 级开å‘é¡ºåºæ¸…å•ï¼
40 23  
41   -**清å•粒度**:一行一个 REQ,åŒä¸€æ¨¡å—çš„ REQ å¿…é¡»**连续排列**。
  24 +**清å•颗粒度**:一行一个 REQ,åŒä¸€æ¨¡å—çš„ REQ å¿…é¡»**连续排列**。
42 25  
43   -1. 构建**模å—ä¾èµ– DAG**:
44   - - docs/03 中的外键(表 A → 表 B ⇒ A 的模å—ä¾èµ– B 的模å—)
45   - - docs/01 index ä¸­çš„æ˜¾å¼ `depends_on` æç¤º
46   -2. å¯¹æ¨¡å— DAG åšæ‹“扑排åºå¾— `module_topo_order[]`。
47   -3. 对**æ¯ä¸ªæ¨¡å—内部**构建 REQ é—´ä¾èµ–(从 REQ å¡ç‰‡ `goal` / `rules` / `ä¾èµ–表` 推断 REQ-A 是 REQ-B çš„å‰ç½®ï¼‰ï¼Œå¾—到模å—内 REQ 顺åºã€‚
  26 +1. 构建**模å—ä¾èµ– DAG**。
  27 +3. 对**æ¯ä¸ªæ¨¡å—内部**构建 REQ é—´ä¾èµ–,得到模å—内 REQ 顺åºã€‚
48 28 4. åˆæˆ `req_order[]`:按 `module_topo_order[]` 便¬¡é“ºå¼€æ¯ä¸ªæ¨¡å—内的 REQ åºåˆ—(**åŒæ¨¡å— REQ 连续**)。
49 29 5. **环ä¾èµ–打破**:
50 30 - **模å—级**ï¼šè‹¥æ¨¡å— DAG 存在环(module_A ↔ module_B),按å¯å‘å¼ï¼ˆå­—æ¯åº / 被ä¾èµ–次数多者先)破环排出 `module_topo_order`,并在**å‚与环的模å—里第一个 REQ** çš„ `note` 字段填入原因(如 "A↔B 互ä¾èµ–ï¼šå…ˆåš A 的骨架")。
... ... @@ -54,135 +34,84 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion Bash(cat *) Bash(
54 34 - `index`:行å·ï¼ˆä»Ž 1 开始)
55 35 - `req_id`:如 `REQ-SYS-001`
56 36 - `module_id`:该 REQ 所属模å—,如 `module_sys`
57   - - `rationale`(一行**选中ç†ç”±**):ä¾èµ–驱动的简短æè¿°ï¼Œå¦‚ `æ‰€å±žæ¨¡å—æ— ä¾èµ–,基础模å—` / `ä¾èµ– REQ-SYS-001 已在å‰` / `所属模å—ä¾èµ– module_sys 已在å‰`
58   - - `note`(一行**备注**):默认 `—`;仅环ä¾èµ–打破场景填原因
59   -7. 用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md`,填充 `modules[]`ï¼ˆå« `id` / `name` / `deps` / `tables`)/ `req_order[]`(æ¯é¡¹å« `index` / `req_id` / `module_id` / `rationale` / `note`)/ `notes`。
  37 + - `rationale`(**选中ç†ç”±**):ä¾èµ–驱动的简短æè¿°ï¼Œå¦‚ `æ‰€å±žæ¨¡å—æ— ä¾èµ–,基础模å—` / `ä¾èµ– REQ-SYS-001 已在å‰` / `所属模å—ä¾èµ– module_sys 已在å‰`
  38 + - `note`(**备注**):默认 `—`;仅环ä¾èµ–打破场景填原因
  39 +7. 读å–å¹¶å¡«å…… `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md`。
60 40 8. 写入 `docs/02-å¼€å‘计划.md`。
61 41  
  42 +完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 中勾选:
  43 +- ` - [ ] docs/02 å¼€å‘计划已生æˆ`
  44 +
62 45 ### B. docs/05 — API 接å£å¥‘约
63 46  
64   -1. 用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md`,写入 `docs/05-API接å£å¥‘约.md` 头部。
65   -2. 对所有模å—çš„æ¯ä¸ª REQ:用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md`,推断 method / path / auth / permission / 请求和å“应 schemaï¼ˆä¸æ˜Žç¡®çš„询问用户),追加到 docs/05。
  47 +1. è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-05-header-template.md`,写入 `docs/05-API接å£å¥‘约.md` 头部。
  48 +2. 对所有模å—çš„æ¯ä¸ª REQ:读å–并推断 `${CLAUDE_SKILL_DIR}/templates/docs-05-endpoint-template.md`,追加到 docs/05。
  49 +
  50 +完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 中勾选:
  51 +- ` - [ ] docs/05 API 契约已生æˆ`
66 52  
67 53 ### B2. 回填模å—头 + REQ å¡ç‰‡çš„ TBD(A5) 字段
68 54  
69   -1. 用 `Glob` 列出 `docs/01-需求清å•/*/_module.md`(模å—头)和 `docs/01-需求清å•/*/REQ-*.md`(REQ å¡ç‰‡ï¼‰ã€‚
70   -2. 用 `Grep` 在这些文件中æœç´¢ `TBD(A5 自动补)` 的行å·ï¼ˆä¸è¯»å…¨æ–‡ï¼‰ã€‚两ç§è¡Œå‘½ä¸­ï¼š
71   - - `ä¾èµ–模å—: TBD(A5 自动补)` → 模å—级(仅在 `_module.md`ï¼Œæ¯æ–‡ä»¶ä¸€æ¬¡ï¼‰
72   - - `ä¾èµ–接å£: TBD(A5 自动补)` → REQ 级(仅在 `REQ-*.md`ï¼Œæ¯æ–‡ä»¶ä¸€æ¬¡ï¼‰
73   -3. 对æ¯ä¸ªå‘½ä¸­è¡ŒæŒ‰ç±»åž‹å›žå¡«ï¼š
74   - - **模å—级 `ä¾èµ–模å—`**(`_module.md`):用 `Read` å–该文件 `module_code` + `module_name`,从步骤 A çš„ `module_topo_order[]` + DAG 查该模å—的上游ä¾èµ–(多模å—用 `, ` 分隔);`Edit` 替æ¢ä¸º `ä¾èµ–模å—: <module_x>, <module_y>`(无ä¾èµ–å¡« `—`)
75   - - **REQ 级 `ä¾èµ–接å£`**(`REQ-*.md`):从文件å直接得 `req_id`(`REQ-USR-001.md` → `REQ-USR-001`);在步骤 B 刚生æˆçš„ `docs/05-API接å£å¥‘约.md` 里 Grep 属于该 REQ çš„ endpointï¼›`Edit` 替æ¢ä¸º `ä¾èµ–接å£: POST /api/xxx, GET /api/yyy`(多个用 `, ` 分隔)
76   -4. 打å°å›žå¡«ç»Ÿè®¡ï¼š`A5 回填 <M> 处模å—ä¾èµ– + <N> 处 REQ api_refs`。
  55 +1. 在`docs/01-需求清å•/*/_module.md`(模å—头)和 `docs/01-需求清å•/*/REQ-*.md`(REQ å¡ç‰‡ï¼‰ä¸­æœç´¢å¹¶å›žå¡« `TBD(A5 自动补)`
  56 +2. 打å°å›žå¡«ç»Ÿè®¡ï¼š`A5 回填 <M> 处模å—"ä¾èµ–模å—" + <N> 处 REQ"ä¾èµ–接å£"`。
  57 +
  58 +完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 中勾选:
  59 +- ` - [ ] REQ å¡ç‰‡ä¾èµ–接å£å·²å›žå¡«`
77 60  
78 61 ### C. docs/06 — 页颿¸…å•
79 62  
80   -1. 对æ¯ä¸ªæœ‰å‰ç«¯é¡µé¢çš„æ¨¡å—:用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`,填充 `pages[]`(page_nameã€routeã€page_typeã€req_idsã€menu_pathã€interactions)。
81   -2. å°†æ¯ä¸ªæ¸²æŸ“å—追加到 `docs/06-UI交互规范.md` § 五。
82   -
83   -### D. docs/08 § 二 — è¿½åŠ æ¨¡å—æ¸…å•ï¼ˆå« REQ å­é¡¹ï¼‰
84   -
85   -docs/08 已由 A0 project-init åˆ›å»ºï¼ˆå« Plan 进度骨架)。本步骤åªå¾€ § 二 追加模å—行,**ä¸é‡å†™æ•´ä¸ªæ–‡ä»¶**。
86   -
87   -1. 用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`ï¼ˆå•æ¨¡å— bullet 行模æ¿ï¼‰ã€‚
88   -2. **按 `module_id` å­—æ¯åº**对æ¯ä¸ªæ¨¡å—:
89   - - 从步骤 A `req_order[]` 过滤出 `module_id` 匹é…çš„ REQ åˆ—è¡¨ï¼ˆä¿æŒæ­¥éª¤ A 算出的模å—内 REQ 顺åºï¼‰ã€‚
90   - - 对æ¯ä¸ª REQ 从 `docs/01-需求清å•/<module>/<req_id>.md` 读出其一å¥è¯æ ‡é¢˜ï¼ˆREQ å¡ç‰‡æ ‡é¢˜è¡Œæˆ– `goal` 字段)。
91   - - 渲染 `{{req_checklist}}` å—:æ¯è¡Œ ` - [ ] <req_id> <title>`(4 ç©ºæ ¼ç¼©è¿›å¯¹é½ `- 功能:`)。
92   - - æ¸²æŸ“æ•´æ¡ bullet,填充 `module_id` / `module_name` / `depends_on` / `path_scopes` / `req_checklist`。
93   -
94   - > 注æ„一:docs/08 § 二 çš„**模å—行åº**ä¸å†³å®šåˆ†å‘顺åºâ€”—分å‘以 docs/02 § 二 REQ 清å•ä¸ºå‡†ï¼Œæ­¤å¤„æ¨¡å—æŒ‰å­—æ¯åºä»…方便查找。
95   - > 注æ„二:REQ å­é¡¹çš„ `[ ]` ç”± `feature-review` 在 `verdict=approve` 时自动勾选,作为功能级进度å¯è§†åŒ–ï¼›**模å—完æˆåˆ¤å®šä»ç”± `MR:` 字段 + GitLab API state å•独决定**,ä¸ä¾èµ–å­é¡¹å‹¾é€‰çжæ€ã€‚
96   -3. 所有模å—行拼æˆä¸€æ®µæ–‡æœ¬ï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` çš„ `## 二ã€Coding 阶段(按模å—循环)` æ ‡é¢˜åŽæ’入(定ä½ç”¨ä¸‹ä¸€è¡Œæ³¨é‡Š"(A5 å¡«å…¥åŽ..."ä½œä¸ºé”šï¼ŒæŠŠæ¨¡å—æ¸…啿’到该注释之å‰ï¼‰ã€‚
97   -
98   -### E. docs/10 — 验收清å•
99   -
100   -1. 用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md`,写入 `docs/10-验收检查清å•.md` 头部。
101   -2. 对æ¯ä¸ªæ¨¡å—:用 `Read` è¯»å– `${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md`,填充 `reqs[]`ã€`data_checks[]`ã€`ui_checks[]`,追加。
102   -
103   -### F. éªŒè¯ + 勾选 docs/08 进度 + 终止 Plan 阶段
104   -
105   -1. 一致性检查:
106   - - docs/01 çš„æ¯ä¸ª REQ 都出现在 docs/05(作为接å£ï¼Œå¦‚适用)ã€docs/10(作为验收项)。
107   - - `docs/02 § 二` å¼€å‘é¡ºåºæ¸…å•çš„ `module_id` é›†åˆ = `docs/08 § 二` çš„ `module_id` 集åˆï¼ˆæ•°é‡ã€ID 全等);ä¸ç›¸ç­‰ → 报错åœä¸‹ï¼Œåˆ—出差集。
108   -
109   -2. **最终å ä½ç¬¦æ‰«æ**(覆盖 Plan 阶段全部产出:`docs/01-需求清å•/index.md` + `docs/01-需求清å•/*/_module.md` + `docs/01-需求清å•/*/REQ-*.md` + `docs/02` / `docs/03` / `docs/05` / `docs/06` / `docs/10`):
110   -
111   - a. **`TBD` → CC 自动补é½**:用 `Grep` æœç´¢ `TBD(A3 自动补)` å’Œ `TBD(A5 自动补)`。有命中则按 A3 / B2 åŒæ ·é€»è¾‘就地补填(A3 查 docs/03 å¡« `ä¾èµ–表:`ï¼›A5 查 docs/05 按 REQ-ID å¡« `ä¾èµ–接å£:`ï¼‰ï¼Œå† Grep 确认 0 å‘½ä¸­ï¼›ä»æ®‹ç•™æŠ¥é”™åœä¸‹ã€‚
112   -
113   - b. **`ã€äººå·¥å¡«å†™ï¼š...】` → QA 循环等用户补**(与 A2 skeleton-gen 步骤 E åŒé£Žæ ¼ï¼‰ï¼š
114   -
115   - 循环执行直到两个æ¡ä»¶**åŒæ—¶æ»¡è¶³**:(1) 扫æ 0 命中;(2) 用户选「继续ã€
116   -
117   - - **b.1 扫æ**:用 `Grep` 在上述所有文件中æœç´¢ `ã€äººå·¥å¡«å†™ï¼š`,得到命中数 N 和残留ä½ç½®æ¸…å•(`<文件:行å·> — <行内容摘è¦>`)
118   - - **b.2 æ‰“å°æ±‡æ€»æ¨ªå¹…**:
119   - ```
120   - â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”
121   - [downstream-gen] 最终å ä½ç¬¦å®¡é˜…
122   -
123   - <N=0 时打å°ï¼šâœ… 全部填完>
124   - <N>0 时打å°ï¼šâš ï¸ 还有 N 处待填:
125   - <文件:行å·> — <行内容摘è¦>
126   - ...>
127   -
128   - 需è¦è°ƒæ•´ → 直接编辑对应文件
129   - å¡«å®ŒåŽ â†’ 回æ¥é€‰ã€Œç»§ç»­ã€æ”¾è¡Œå®Œæˆ Plan
130   - â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”
131   - ```
132   - - **b.3 弹出 QA**:用 `AskUserQuestion` 询问:
133   - - **question**: `最终å ä½ç¬¦è¡¥å¡«å®Œæ¯•?`
134   - - **options** (æ¯é¡¹ä¸ºå¯¹è±¡):
135   - - `{"label": "ç»§ç»­", "description": "æ”¾è¡Œå®Œæˆ Plan 阶段"}`
136   - - `{"label": "有疑问想先沟通", "description": "需è¦è®¨è®ºæˆ–修改"}`
137   - - **b.4 路由**:
138   - - 选「有疑问想先沟通ã€â†’ 回答用户问题åŽ**回 b.1 釿–°æ‰«æ**
139   - - 选「继续ã€â†’ **回 b.1 釿–°æ‰«æéªŒè¯**:
140   - - æ–° N = 0 → 进入步骤 3
141   - - æ–° N > 0 → 用户以为填完其实还有残留,回 b.2 æ‰“å°æ–°æ¨ªå¹…并冿¬¡å¼¹å‡º QA
142   -
143   - 关键:**æ¯æ¬¡å¼¹å‡º QA å‰éƒ½é‡æ–°æ‰«æä¸€æ¬¡**,用户看到的 N å§‹ç»ˆæ˜¯æœ€æ–°çš„ï¼›åªæœ‰ N = 0 ä¸”é€‰ã€Œç»§ç»­ã€æ‰æ”¾è¡Œã€‚
144   -
145   -3. 用 `Edit` 在 `docs/08-模å—任务管ç†.md` 勾选 7 个 checkbox(A5 çš„ 6 个å­é¡¹ + A5 父项):
146   - - ` - [ ] docs/02 å¼€å‘计划已生æˆ` → `[x]`
147   - - ` - [ ] docs/05 API 契约已生æˆ` → `[x]`
148   - - ` - [ ] docs/06 § 五 页颿¸…å•已填入` → `[x]`
149   - - ` - [ ] docs/10 验收清å•已生æˆ` → `[x]`
150   - - ` - [ ] 下方模å—列表已填入` → `[x]`
151   - - ` - [ ] REQ å¡ç‰‡ä¾èµ–接å£å·²å›žå¡«` → `[x]`
152   - - `- [ ] A5 ä¸‹æ¸¸æ–‡æ¡£ç”Ÿæˆ â€” downstream-gen` → `[x]`
153   -
154   -4. **从 `origin` 远程派生 GitLab 凭æ®å¹¶å›žå¡« `.env.local`**
155   -
156   - ä»…å½“å¯¹åº”å­—æ®µä»æ˜¯ `TBD(A5 自动补)` 或空时回填;用户已手填为别的值一律ä¸åŠ¨ã€‚
157   -
158   - a. å–远程 URL:`Bash`: `git remote get-url origin 2>/dev/null` → `REMOTE_URL`。为空 → è·³è¿‡æœ¬æ­¥éª¤ï¼Œä»…æ‰“å°æç¤º"未é…ç½® origin 远程,`GITLAB_*` 留给用户手填"。
159   - b. è§£æžï¼š
160   - - `PROJECT_PATH` = 去掉 `<scheme>://<host>/` 或 `git@<host>:` 或 `ssh://<host>/` å‰ç¼€ + 去掉末尾 `.git`(如 `zhuzc/test`)
161   - - `PROJECT_ID_ENC` = `PROJECT_PATH` çš„ `/` 替æ¢ä¸º `%2F`(如 `zhuzc%2Ftest`)
162   - - `HOST` = 远程主机å(如 `git.xlyprint.cn`)
163   - - `SCHEME` 三分支(**ç»ä¸æŠŠ SSH remote é™çº§æˆ http**——Private Token ä¸èƒ½èµ°æ˜Žæ–‡ï¼‰ï¼š
164   - - `REMOTE_URL` 以 `https://` 开头 → `https`
165   - - `REMOTE_URL` 以 `http://` 开头 → `http`ï¼ˆæ˜Žç¡®å£°æ˜Žï¼ŒéžæŽ¨æ–­ï¼‰
166   - - 其他(`git@` / `ssh://` / 异常)→ `https`(默认走安全侧)
167   - - `API_URL_GUESS` = `<SCHEME>://<HOST>/api/v3`
168   - c. 用 `Read` 读 `.env.local`:
169   - - è‹¥ `GITLAB_PROJECT_ID` 当å‰å€¼ä¸º `TBD(A5 自动补)` 或空 → 用 `Edit` 改为 `GITLAB_PROJECT_ID=<PROJECT_ID_ENC>`
170   - - è‹¥ `GITLAB_API_URL` 当å‰å€¼ä¸º `TBD(A5 自动补)` 或空 → `Edit` 改为 `GITLAB_API_URL=<API_URL_GUESS>`
171   - - ä¸Šä¸¤å­—æ®µè‹¥å·²è¢«ç”¨æˆ·æ‰‹æ”¹è¿‡ï¼ˆéž `TBD(A5 自动补)` 也éžç©ºï¼‰â†’ ä¸è¦†ç›–,仅核对打å°
172   - - `GITLAB_TOKEN` 派生ä¸äº†ï¼Œå ä½ä¿æŒ `ã€äººå·¥å¡«å†™ï¼š...】`,用户去 GitLab Profile → Account → Private token 手填
173   - d. 打å°å›žå¡«æ‘˜è¦ï¼š
174   - ```
175   - [downstream-gen] GitLab 凭æ®è‡ªåŠ¨æ´¾ç”Ÿï¼ˆä»Ž origin 远程):
176   - GITLAB_PROJECT_ID = <回填值 或「ä¿ç•™å ä½: 已手填 xxxã€>
177   - GITLAB_API_URL = <回填值 或「ä¿ç•™å ä½: 已手填 xxxã€>
178   - GITLAB_TOKEN = ä¿æŒå ä½ — 请去 GitLab Profile → Account → Private token 手填
179   - ```
180   - è‹¥ `SCHEME` 是 `http`,é¢å¤–æç¤ºï¼š"âš ï¸ æœ¬æ¬¡æ´¾ç”Ÿç”¨ `http://`——Private Token 将走明文;仅当你的 GitLab 部署真的没上 HTTPS æ—¶å¯ä»¥ä¿ç•™ï¼Œå¦åˆ™è¯·æ‰‹åŠ¨æ”¹ä¸º `https://`。"
181   - è‹¥ `SCHEME` 是推断æ¥çš„ `https`(æ¥è‡ª ssh/git@ remote),é¢å¤–æç¤ºï¼š"API URL çš„ scheme 是从 SSH remote é»˜è®¤æŽ¨æˆ `https`;如实际 API èµ° http,请手动改 `GITLAB_API_URL`。"
182   -
183   -5. 输出:`downstream-gen: 写入 4 个文件 + <N> ä¸ªæ¨¡å— + <M> 处 REQ ä¾èµ–接å£å›žå¡«ã€‚`
184   -
185   -6. æ‰“å° Plan 阶段终止横幅并**åœä¸‹**(ä¸è‡ªåŠ¨è¿›å…¥ B 阶段):
  63 +对æ¯ä¸ªæœ‰å‰ç«¯é¡µé¢çš„æ¨¡å—:读å–å¹¶å¡«å…… `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`,追加到 `docs/06-UI交互规范.md` § 五。
  64 +
  65 +完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 中勾选:
  66 +- ` - [ ] docs/06 § 五 页颿¸…å•已填入`
  67 +
  68 +### D. docs/08 — è¿½åŠ æ¨¡å—æ¸…å•
  69 +
  70 +读 `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`,按 `module_id` å­—æ¯åºä¸ºæ¯ä¸ªæ¨¡å—渲染 bullet(模å—å…ƒæ•°æ® + REQ å­é¡¹æ¸…å•,REQ åºä¿æŒæ­¥éª¤ A 模å—内顺åºï¼‰ï¼Œè¿½åŠ åˆ° docs/08。
  71 +
  72 +完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 中勾选:
  73 +- ` - [ ] 下方模å—列表已填入`
  74 +
  75 +### E. docs/10 — 验收清å•(项目级 SOP)
  76 +
  77 +```bash
  78 +cp "${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md" docs/10-验收检查清å•.md
  79 +```
  80 +
  81 +完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 中勾选:
  82 +- ` - [ ] docs/10 验收清å•已生æˆ`
  83 +
  84 +### F. éªŒè¯ + 勾选 docs/08 进度 + ç»“æŸ Plan
  85 +
  86 +1. 一致性检查 + 自主修å¤å¾ªçŽ¯ï¼ˆæœ€å¤š 3 轮,docs/01 是 REQ SSoT ä¸åŠ¨ï¼‰ï¼š
  87 +
  88 + **检查项**:
  89 + - æ¯ä¸ª docs/01 REQ 都出现在 docs/05(作为接å£ï¼Œå¦‚适用)
  90 + - `docs/02 § 二` çš„ `module_id` é›†åˆ = `docs/08 § 二` çš„ `module_id` 集åˆ
  91 +
  92 + **ä¸ä¸€è‡´ → 按差异类型自主修å¤**:
  93 + - **REQ 缺 docs/05 endpoint** → 按步骤 B 规则为该 REQ 推测,并追加到 docs/05
  94 + - **module_id 缺 docs/08 § 二** → 按步骤 D è§„åˆ™æ¸²æŸ“è¯¥æ¨¡å— bulletï¼ˆå« REQ å­é¡¹ï¼‰ï¼ŒæŒ‰ `module_id` å­—æ¯åºæ’入正确ä½ç½®
  95 + - **module_id 缺 docs/02 § 二** → é‡ç®—该模å—çš„ `req_order` 段(步骤 A å­æµç¨‹ï¼‰ï¼ŒæŒ‰æ‹“æ‰‘åºæ’å…¥ docs/02 § 二
  96 +
  97 + ä¿®å¤åŽé‡è·‘检查;通过 → 进入 2ï¼›3 è½®ä»å¤±è´¥ → åœä¸‹ï¼Œæ‰“å°æœ€ç»ˆæ®‹ç•™å·®å¼‚ + å·²å°è¯•çš„ 3 è½®ä¿®å¤æ‘˜è¦è®©ç”¨æˆ·ä»‹å…¥ã€‚
  98 +
  99 +2. **最终å ä½ç¬¦æ‰«æ**(覆盖 Plan 阶段全部产出):
  100 +
  101 + a. **`TBD` → 自动补é½**:Grep æœç´¢ `TBD(A3 自动补)` å’Œ `TBD(A5 自动补)`。有命中则就地补填(A3 残留 → 查 docs/03 å¡« `ä¾èµ–表`ï¼›A5 残留 → 查 docs/05 按 REQ-ID å¡« `ä¾èµ–接å£`ï¼‰ï¼Œå† Grep 确认 0 å‘½ä¸­ï¼›ä»æ®‹ç•™æŠ¥é”™åœä¸‹ã€‚
  102 +
  103 + b. **`ã€äººå·¥å¡«å†™ï¼š...】` → QA 循环等用户补**:
  104 +
  105 + 循环执行直到æœç´¢ä¸åˆ° `ã€äººå·¥å¡«å†™ï¼š` 且用户选「继续ã€ï¼š
  106 + - 0 命中 → 直接放行进入步骤 3
  107 + - 有命中 → æ‰“å°æ®‹ç•™æ¸…å•(`<文件:行å·> — <内容摘è¦>`),用 `AskUserQuestion` 弹「继续ã€/「有疑问想先沟通ã€äºŒé€‰ä¸€ï¼›ç”¨æˆ·å›žç­”åŽé‡æ‰«éªŒè¯å†å†³å®šæ”¾è¡Œ / 继续循环
  108 +
  109 + **æ¯æ¬¡å¼¹ QA å‰éƒ½é‡æ‰«ä¸€æ¬¡**——ä¿è¯ç”¨æˆ·çœ‹åˆ°çš„ N 是最新的,é¿å…「用户以为填完但实际还有残留ã€ç›´æŽ¥æ”¾è¡Œã€‚
  110 +
  111 +3. 完æˆåŽï¼Œç”¨ `Edit` 在 `docs/08-模å—任务管ç†.md` 勾选 A5 父项:
  112 + - `- [ ] A5 ä¸‹æ¸¸æ–‡æ¡£ç”Ÿæˆ â€” downstream-gen`
  113 +
  114 +4. æ‰“å° Plan 阶段终止横幅并**åœä¸‹**(ä¸è‡ªåŠ¨è¿›å…¥ B 阶段):
186 115  
187 116 ```
188 117 â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”
... ... @@ -191,7 +120,7 @@ docs/08 已由 A0 project-init åˆ›å»ºï¼ˆå« Plan 进度骨架)。本步骤åªå
191 120 所有规划文档已就绪,docs/08 § 一 全部勾选。
192 121  
193 122 âš ï¸ è¿›å…¥ B 阶段å‰å¿…须完æˆï¼š
194   - 1. 人工通读 docs/01~10 + CLAUDE.md + sql/migrations/V1 + å„ scripts/*
  123 + 1. 审核 docs/01~10 + CLAUDE.md + sql/migrations/V1 + å„ scripts/*
195 124  
196 125 2. 把全部 Plan 产物 commit:
197 126 git add -A && git commit -m "chore: plan phase A0~A5 done"
... ... @@ -201,26 +130,19 @@ docs/08 已由 A0 project-init åˆ›å»ºï¼ˆå« Plan 进度骨架)。本步骤åªå
201 130 情况 A — 远程仓库是全新的(尚无 main / master):
202 131 git remote add origin <gitlab-url> # 若尚未添加
203 132 git -c core.hooksPath=/dev/null push -u origin master
204   - # 首次 push 本地 DB 尚未就ä½ã€scripts/test.sh 必然失败。
205   - # `-c core.hooksPath=/dev/null` åªå¯¹æœ¬æ¬¡ push 临时指å‘空的 hooksPath,
206   - # 跳过 .githooks/pre-push,ä¸åЍ repo çš„ core.hooksPath é…置,
207   - # 也ä¸ç”¨ --no-verify(åŽè€…被 CC çš„ deny-no-verify hook 硬拦)。
208   - # push 完æˆåŽåˆ° GitLab UI 把 master(或 main)设为 protected
209 133  
210 134 情况 B — 远程已有 main 需è¦èµ° MR 审核:
211 135 git checkout -b plan-init
212 136 git push -u origin plan-init
213 137 # 在 GitLab 打开 plan-init → main çš„ MR,审核并åˆå¹¶
214 138  
215   - 4. è¡¥é½ `.env.local`:
216   - - `GITLAB_TOKEN`(必填):去 GitLab Profile → Account → Private token 生æˆåŽç²˜è´´
217   - - `GITLAB_API_URL` / `GITLAB_PROJECT_ID`:步骤 4 已从 origin è¿œç¨‹è‡ªåŠ¨å›žå¡«ï¼ˆè‹¥ä»æ˜¾ç¤º
218   - `TBD(A5 自动补)`,说明 origin 没é…,手动填;若 scheme 错请改 http↔https)
219   - B 阶段 mr-create 用 token 通过 curl 创建 MR。
  139 + 4. è¡¥é½ `.env.local` 三个 GITLAB_* 字段
  140 +
  141 + - `GITLAB_TOKEN`:去 GitLab Profile → Account → Private token 生æˆåŽç²˜è´´
  142 + - `GITLAB_PROJECT_ID`,`GITLAB_API_URL`:è¿è¡Œ
  143 + bash <plugin-skill-dir>/scripts/derive-gitlab.sh
220 144  
221   - 5. main(或 master)就绪åŽï¼Œå†è¿è¡Œ /erp-workflow:coding-start
222   - 进入 B 阶段。届时 .env.local åº”æŒ‡å‘æœ¬åœ° MySQL(éžå…±äº«è¿œç¨‹ DB),
223   - å¦åˆ™ B é˜¶æ®µæ¯æ¬¡æµ‹è¯•闸门都会因 setup-test-db.sh 的防护失败。
  145 + 5. remote git 就绪åŽï¼Œå†è¿è¡Œ /erp-workflow:coding-start
224 146 â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”â”
225 147 ```
226 148  
... ... @@ -232,4 +154,4 @@ docs/08 已由 A0 project-init åˆ›å»ºï¼ˆå« Plan 进度骨架)。本步骤åªå
232 154 - `${CLAUDE_SKILL_DIR}/templates/docs-06-module-pagelist-template.md`
233 155 - `${CLAUDE_SKILL_DIR}/templates/docs-08-module-row-template.md`ï¼ˆæ¨¡å— bullet 行模æ¿ï¼‰
234 156 - `${CLAUDE_SKILL_DIR}/templates/docs-10-header-template.md`
235   -- `${CLAUDE_SKILL_DIR}/templates/docs-10-module-template.md`
  157 +- `${CLAUDE_SKILL_DIR}/scripts/derive-gitlab.sh`(**用户å¯é€‰è¾…助**:在 add origin ä¹‹åŽæ‰‹åŠ¨è·‘ä¸€æ¬¡ï¼Œè‡ªåŠ¨æ´¾ç”Ÿ GITLAB_PROJECT_ID / GITLAB_API_URL 写入 .env.local)
... ...
skills/plan/downstream-gen/banners/flow.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ ▶ A5 生成下游文档 │
  15 +│ │
  16 +│ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/downstream-gen/scripts/derive-gitlab.sh 0 → 100644
  1 +#!/usr/bin/env bash
  2 +# derive-gitlab.sh — 从 git origin 远程派生 GitLab 凭据并回填 .env.local
  3 +#
  4 +# 用法: bash derive-gitlab.sh [.env.local 路径,默认 .env.local]
  5 +#
  6 +# 派生字段:
  7 +# GITLAB_PROJECT_ID = origin 的 namespace/path(/ 编码成 %2F)
  8 +# GITLAB_API_URL = <scheme>://<host>/api/v3
  9 +#
  10 +# 仅当字段值为 TBD(A5 自动补) 或空时回填;用户手填值不动。
  11 +# 仅支持 http(s) origin URL;其他协议(ssh / git@)跳过。
  12 +# GITLAB_TOKEN 不派生,留给用户手填。
  13 +#
  14 +# 退出码:
  15 +# 0 = 派生完成或主动跳过(origin 不存在 / 协议不支持)
  16 +# 2 = .env.local 路径错
  17 +
  18 +set -uo pipefail
  19 +
  20 +ENV_FILE=${1:-.env.local}
  21 +[ -f "$ENV_FILE" ] || { echo "derive-gitlab.sh: env file not found: $ENV_FILE" >&2; exit 2; }
  22 +
  23 +URL=$(git remote get-url origin 2>/dev/null || true)
  24 +if [ -z "$URL" ]; then
  25 + echo "derive-gitlab.sh: 未配置 origin 远程,GITLAB_* 留给用户手填" >&2
  26 + exit 0
  27 +fi
  28 +
  29 +case "$URL" in
  30 + https://*) SCHEME=https ;;
  31 + http://*) SCHEME=http ;;
  32 + *)
  33 + echo "derive-gitlab.sh: origin 不是 http(s) URL ($URL),跳过派生" >&2
  34 + exit 0
  35 + ;;
  36 +esac
  37 +
  38 +REST=${URL#${SCHEME}://}
  39 +HOST=${REST%%/*}
  40 +PATH_RAW=${REST#*/}
  41 +PATH_RAW=${PATH_RAW%.git}
  42 +
  43 +PROJECT_ID=${PATH_RAW//\//%2F}
  44 +API_URL="${SCHEME}://${HOST}/api/v3"
  45 +
  46 +update_field() {
  47 + local key=$1 newval=$2
  48 + local line
  49 + line=$(grep -E "^${key}=" "$ENV_FILE" | head -1)
  50 + if [ -z "$line" ]; then
  51 + echo " ${key} = (.env.local 中无此行,跳过)" >&2
  52 + return
  53 + fi
  54 + local current=${line#${key}=}
  55 + if [ -z "$current" ] || [ "$current" = "TBD(A5 自动补)" ]; then
  56 + sed -i.bak -E "s|^${key}=.*$|${key}=${newval}|" "$ENV_FILE" && rm -f "${ENV_FILE}.bak"
  57 + echo " ${key} = ${newval}"
  58 + else
  59 + echo " ${key} = (保留用户手填: ${current})"
  60 + fi
  61 +}
  62 +
  63 +echo "derive-gitlab.sh: 从 origin ($URL) 派生 GitLab 凭据:"
  64 +update_field GITLAB_PROJECT_ID "$PROJECT_ID"
  65 +update_field GITLAB_API_URL "$API_URL"
  66 +echo " GITLAB_TOKEN = (保持占位,请去 GitLab Profile → Account → Private token 手填)"
... ...
skills/plan/downstream-gen/templates/docs-05-endpoint-template.md
... ... @@ -4,19 +4,8 @@
4 4 - **Path**: `{{path}}`
5 5 - **Auth**: {{auth}}
6 6 - **Permission**: {{permission}}
7   -
8   -#### 请求参数
9   -{{request_params}}
10   -
11   -#### 请求体
12   -```json
13   -{{request_body_schema}}
14   -```
15   -
16   -#### 响应体
17   -```json
18   -{{response_body_schema}}
19   -```
  7 +- **请求**: {{request_summary}}
  8 +- **响应**: {{response_summary}}
20 9  
21 10 #### 错误码
22 11 {{#each errors}}
... ...
skills/plan/downstream-gen/templates/docs-10-header-template.md
1 1 # 10-验收检查清单
2 2  
3   -通用验收项(全项目适用):
  3 +通用验收项(全项目适用)
4 4  
5 5 - [ ] `scripts/test.sh` 本地全绿
6 6 - [ ] 所有 schema 改动都有对应 `sql/migrations/V_n__<desc>.sql`
... ... @@ -10,5 +10,7 @@
10 10 - [ ] 异常走全局处理器,不暴露堆栈到前端
11 11 - [ ] 前端不存敏感信息到 localStorage
12 12  
13   -## 模块专项
14   -(各模块验收段落见下方,由 `downstream-gen` 按模块填入)
  13 +> 本文档仅维护项目级验收 SOP。粒度更细的验收信息分散在:
  14 +> - **每 REQ 的业务验收点**:`docs/01-需求清单/<module>/<req_id>.md § 验收`
  15 +> - **每模块的实测验收(数据 / UI / 自动化用例位置)**:由 B 阶段 `module-report` 在该模块完成时填入模块完成报告
  16 +> - **REQ 开发进度(feature-review approve 状态)**:`docs/08 § 二`
... ...
skills/plan/downstream-gen/templates/docs-10-module-template.md deleted
1   -### {{module_id}} {{module_name}}
2   -
3   -#### 功能级验收(每个 REQ 对应可执行用例)
4   -{{#each reqs}}
5   -- [ ] {{req_id}} {{title}}
6   - - 自动化用例: `{{test_file}}::{{test_name}}`
7   - - 手动验收: {{manual_check}}
8   -{{/each}}
9   -
10   -#### 数据级验收
11   -{{#each data_checks}}
12   -- [ ] {{check}}
13   -{{/each}}
14   -
15   -#### UI 级验收(若含前端)
16   -{{#each ui_checks}}
17   -- [ ] {{check}}
18   -{{/each}}
skills/plan/project-init/SKILL.md
... ... @@ -2,7 +2,7 @@
2 2 name: project-init
3 3 description: A0 项目初始化——从插件模板幂等地复制 CLAUDE.md / docs/01-需求清单/index.md / docs/04-技术规范.md / docs/08-模块任务管理.md(已存在则跳过),并初始化 Git(如未初始化)。session-start 在 docs/08 缺失时派发本 skill。
4 4 user-invocable: false
5   -allowed-tools: Glob Edit Skill Bash(mkdir *) Bash(cp -n *) Bash(git init) Bash(command -v *) Bash(uname *) Bash(brew *) Bash(apt *) Bash(apt-get *) Bash(yum *) Bash(apk *) Bash(export PATH=*) Bash(echo *)
  5 +allowed-tools: Glob Edit Skill Bash(mkdir *) Bash(cp -n *) Bash(git init) Bash(command -v *) Bash(uname *) Bash(brew *) Bash(apt *) Bash(apt-get *) Bash(yum *) Bash(apk *) Bash(export PATH=*) Bash(echo *) Bash(cat *)
6 6 ---
7 7  
8 8 **所有输出必须使用中文。**
... ... @@ -13,20 +13,10 @@ allowed-tools: Glob Edit Skill Bash(mkdir *) Bash(cp -n *) Bash(git init) Bash(c
13 13  
14 14 ### 步骤 0:打印当前位置流程图
15 15  
16   -向用户展示当前在 A 阶段流程中的位置
  16 +用 `Bash` 执行 `cat` 命令向用户展示当前位置流程图(stdout 即 ASCII 框图)
17 17  
18   -```
19   -┌──────────────────────────────────────────────────────┐
20   -│ 📋 阶段 A:规划(一次性) │
21   -│ │
22   -│ ▶ A0 初始化项目 → A1 锁范围(REQ 卡片) │
23   -│ ↓ │
24   -│ 等你审阅 REQ,重新运行 /plan-start 继续 │
25   -│ ↓ │
26   -│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│
27   -│ ↓ │
28   -│ 规划阶段到此结束 │
29   -└──────────────────────────────────────────────────────┘
  18 +```bash
  19 +cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/project-init/banners/flow.txt"
30 20 ```
31 21  
32 22 ### A. 幂等复制模板文件
... ... @@ -89,3 +79,11 @@ cp -n &quot;${CLAUDE_SKILL_DIR}/templates/docs-08-initial-template.md&quot; docs/08-模块
89 79 ```
90 80  
91 81 立即调用 `Skill(scope-lock)` 进入 A1,不等用户手动输入。
  82 +
  83 +## 参考
  84 +
  85 +- `${CLAUDE_SKILL_DIR}/templates/CLAUDE-template.md`(项目级 CLAUDE.md 模板)
  86 +- `${CLAUDE_SKILL_DIR}/templates/docs-01-index-template.md`(需求索引初稿)
  87 +- `${CLAUDE_SKILL_DIR}/templates/docs-04-stack-template.md`(默认技术栈)
  88 +- `${CLAUDE_SKILL_DIR}/templates/docs-08-initial-template.md`(A 阶段进度初始化)
  89 +- 下游:`scope-lock`(A1,自动派发)
... ...
skills/plan/project-init/banners/flow.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ ▶ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ A5 生成下游文档 │
  15 +│ │
  16 +│ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/project-init/templates/docs-01-index-template.md
1 1 # 需求清单
2 2  
3   -> 本目录按模块组织所有功能需求。每个模块一个子目录,含 `_module.md`(模块头)和 `REQ-XXX-NNN.md`(每张 REQ 卡片一个文件)。下方核心功能点供 CC 拆分出 REQ 编号 + 标题 + 草拟规则;卡片内输入 / 输出的主从表字段由人工填写
  3 +> 本目录按模块组织所有功能需求。每个模块一个子目录,含 `_module.md`(模块头)和 `REQ-XXX-NNN.md`(每张 REQ 卡片一个文件)。下方核心功能点供 CC 拆分出 REQ 编号 + 标题 + 草拟规则;卡片内输入 / 输出的简述句和 N 张字段表由人工编辑
4 4  
5 5 ## 模块索引
6 6  
... ... @@ -12,5 +12,5 @@
12 12 ## 填写说明
13 13  
14 14 1. 每个模块占一行,`模块代码` 用大写英文缩写(如 SYS / PUR / INV / SAL / FIN / HR)
15   -2. `核心功能点` 只需列关键词,CC 会基于此拆分出 N 张 REQ 卡片骨架(卡片内输入 / 输出的主从表字段仍由人工填
  15 +2. `核心功能点` 只需列关键词,CC 会基于此拆分出 N 张 REQ 卡片骨架(卡片内输入 / 输出的简述句和字段表仍由人工编辑
16 16 3. 填完后运行 `/erp-workflow:plan-start`,CC 会自动检测并进入需求生成阶段
... ...
skills/plan/project-init/templates/docs-08-initial-template.md
... ... @@ -24,12 +24,11 @@
24 24  
25 25 - [ ] A3 DB 设计 + REQ 回填 — db-design-gen
26 26 - [ ] docs/03-数据库设计文档.md 已生成
27   - - [ ] docs/01 各 REQ 卡片"涉及数据表"已回填
28   - - [ ] 用户已审阅 docs/03 表结构
  27 + - [ ] docs/01 各 REQ 卡片"依赖表" + 模块头"涉及表" 已回填
29 28  
30 29 - [ ] A4 DB 初始化 — db-init
31 30 - [ ] sql/migrations/V1__initial_schema.sql 已生成
32   - - [ ] DDL 与 docs/03 全量一致(5 维度校验通过)
  31 + - [ ] DDL 与 docs/03 全量一致
33 32 - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)
34 33 - [ ] setup-test-db.sh 防护通过 + DROP+CREATE + apply V1 已执行
35 34 - [ ] SHOW TABLES 行数 == docs/03 表数量
... ...
skills/plan/scope-lock/SKILL.md
1 1 ---
2 2 name: scope-lock
3   -description: A1 计划范围锁定——引导用户填写项目概述 + 技术栈 + 需求索引,并按模块子目录生成 REQ 卡片骨架(CC 推断 req_id/title/goal/rules/constraints/acceptance;输入/输出 主从表骨架留 `-` 等人工填;依赖表/依赖接口模板写死 `TBD(A3/A5 自动补)` 由后续 skill 回填)。
  3 +description: A1 计划范围锁定——引导用户填写项目概述 + 技术栈 + 需求索引,并按模块子目录生成 REQ 卡片骨架(CC 推断 req_id/title/goal/rules/constraints/acceptance;输入/输出 各含一句简述 + N 张示例字段表全部原样复制由人工编辑;依赖表/依赖接口模板写死 `TBD(A3/A5 自动补)` 由后续 skill 回填)。
4 4 user-invocable: false
5   -allowed-tools: Read Write Edit Grep Skill AskUserQuestion Bash(mkdir *)
  5 +allowed-tools: Read Edit Grep Skill AskUserQuestion Bash(mkdir *) Bash(cp *) Bash(sed *) Bash(bash *) Bash(cat *)
6 6 ---
7 7  
8 8 **所有输出必须使用中文。**
... ... @@ -13,20 +13,10 @@ allowed-tools: Read Write Edit Grep Skill AskUserQuestion Bash(mkdir *)
13 13  
14 14 ### 步骤 0:打印当前位置流程图
15 15  
16   -向用户展示当前在 A 阶段流程中的位置
  16 +用 `Bash` 执行 `cat` 命令向用户展示当前位置流程图(stdout 即 ASCII 框图)
17 17  
18   -```
19   -┌──────────────────────────────────────────────────────┐
20   -│ 📋 阶段 A:规划(一次性) │
21   -│ │
22   -│ A0 初始化项目 → ▶ A1 锁范围(REQ 卡片) │
23   -│ ↓ │
24   -│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │
25   -│ ↓ │
26   -│ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│
27   -│ ↓ │
28   -│ 规划阶段到此结束 │
29   -└──────────────────────────────────────────────────────┘
  18 +```bash
  19 +cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/scope-lock/banners/flow.txt"
30 20 ```
31 21  
32 22 ### A. 提示用户填写项目概述并等待
... ... @@ -101,7 +91,7 @@ allowed-tools: Read Write Edit Grep Skill AskUserQuestion Bash(mkdir *)
101 91  
102 92 请按业务列出所有模块:
103 93 - 每行一个模块(如 SYS 系统管理 / PUR 采购 / SAL 销售)
104   - - 「核心功能点」只需关键词,CC 会拆分为 REQ 卡片骨架(卡片内输入 / 输出的主从表字段由你后续人工填)
  94 + - 「核心功能点」只需关键词,CC 会拆分为 REQ 卡片
105 95 改完后回来选择「继续」。
106 96 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
107 97 ```
... ... @@ -118,16 +108,20 @@ allowed-tools: Read Write Edit Grep Skill AskUserQuestion Bash(mkdir *)
118 108  
119 109 1. 用 `Grep` 校验 `docs/01-需求清单/index.md` 无 `【人工填写:` 残留;有则回步骤 C。
120 110 2. 用 `Read` 读 `index.md` 解析模块索引。
121   -3. 对每个模块:
122   - - 基于「核心功能点」推断出 N 个 REQ,每个 REQ 产出六元组
123   - `{req_id, title, goal, rules, constraints, acceptance}`:
124   - - `req_id` / `title`:从核心功能点拆分命名(如「用户/角色/权限」→ `REQ-SYS-001 用户管理`、`REQ-SYS-002 角色管理`、`REQ-SYS-003 权限管理`)
125   - - `goal`:用一句话展开 `title`
126   - - `rules` / `constraints` / `acceptance`:业务语义层面的合理起草,待人工审阅修订
127   - - **不推断输入 / 输出的主从表字段**——模板内保留 `主表 + 从表1` 骨架(每张表表头 + 1 行 `-`),等人工按业务自行复制行 / 增删从表
128   - - 用 `Bash`: `mkdir -p docs/01-需求清单/<module_code>-<module_name>` 创建模块目录
129   - - 用 `${CLAUDE_SKILL_DIR}/templates/_module-template.md` 渲染 `_module.md`,填充 `{module_code, module_name, module_brief}`,`Write` 到 `docs/01-需求清单/<module_code>-<module_name>/_module.md`
130   - - 对每个 REQ:用 `${CLAUDE_SKILL_DIR}/templates/req-card-template.md` 渲染(渲染约定见模板顶部 HTML 注释),替换 6 个占位符,`Write` 到 `docs/01-需求清单/<module_code>-<module_name>/<req_id>.md`
  111 +3. **单次 Bash 写入所有文件**(替代 N×9 次 Edit):
  112 +
  113 + - **每模块推断**:三元组 `{module_code, module_name, module_brief}` + N 个 REQ 的六元组 `{req_id, title, goal, rules, constraints, acceptance}`。`req_id`/`title` 从核心功能点拆分;`goal` 展开 `title`;`rules`/`constraints`/`acceptance` 起草业务语义。**不推断**输入 / 输出(模板原样保留示例)。
  114 + - **单次 Bash**:调 `${CLAUDE_SKILL_DIR}/scripts/render.sh` 落盘所有文件(脚本内部完成模板读取 + 占位符替换 + HTML 注释剥离)。下面是**调用形态**示例,`<MOD>` / `<模块名>` / `<REQ-MOD-NNN>` 等尖括号位置 CC 按 `index.md` 实际值替换:
  115 +
  116 + ```bash
  117 + R="${CLAUDE_SKILL_DIR}/scripts/render.sh"
  118 + # 每个模块:mkdir + 1 个 render module + N 个 render req(每 REQ 一行)
  119 + mkdir -p "docs/01-需求清单/<MOD>-<模块名>"
  120 + bash "$R" module "docs/01-需求清单/<MOD>-<模块名>/_module.md" "<MOD>" "<模块名>" "<module_brief>"
  121 + bash "$R" req "docs/01-需求清单/<MOD>-<模块名>/<REQ-MOD-NNN>.md" "<REQ-MOD-NNN>" "<title>" "<goal>" "<rules>" "<constraints>" "<acceptance>"
  122 + ```
  123 +
  124 + - **兜底**:值含字面 `$xxx` 或 `}}` 的 REQ 单独走 cp + Edit。
131 125 4. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选(A1 子项 + A1 顶层):
132 126 - ` - [ ] REQ 卡片骨架已生成(docs/01-需求清单/<module>/REQ-*.md,业务内容留待人工填写)`
133 127 - `- [ ] A1 范围锁定 — scope-lock`
... ... @@ -145,16 +139,14 @@ allowed-tools: Read Write Edit Grep Skill AskUserQuestion Bash(mkdir *)
145 139 ✓ docs/01-需求清单/<module>/REQ-*.md REQ 卡片骨架
146 140  
147 141 ⏸ 现在请你逐张打开 REQ 卡片:
148   - - **必填**:输入(主表 + N 从表)、输出(主表 + N 从表)
149   - · 每张表先把 `-` 行按实际字段数复制;没有从表就删掉 `从表1` 整段,多于一个就复制为 `从表2 / 从表3 / ...`
150   - - **审阅**:目标 / 跨字段规则 / 边界 / 验收(CC 已起草,对照业务校正)
151   - - **保留**:依赖表 / 依赖接口 行的 `TBD(A3/A5 自动补)` 不要改,由 A3/A5 自动回填
  142 + - **必改**:输入 / 输出 两段
  143 + · `表1` / `表2` 是模板示例,按本 REQ 业务**改字段 / 增删行 / 增删整张表**
  144 + - **审阅**:目标 / 跨字段规则 / 边界 / 验收(已起草,对照业务校正)
  145 + - **保留**:`TBD` 不要改,由之后流程自动回填
152 146  
153   - 审阅是 Plan 阶段的关键人工关口,请认真逐张过一遍。
154 147 审阅完成后,运行以下命令继续进入 A2:
155 148 /erp-workflow:plan-start
156 149  
157   - (入口会读取 docs/08 进度,自动派发到 A2 skeleton-gen)
158 150 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
159 151 ```
160 152  
... ... @@ -167,3 +159,4 @@ allowed-tools: Read Write Edit Grep Skill AskUserQuestion Bash(mkdir *)
167 159 - `docs/01-需求清单/<module>/REQ-*.md`(REQ 卡片骨架输出,A3 db-design-gen / A5 downstream-gen 会回填 TBD 字段)
168 160 - `${CLAUDE_SKILL_DIR}/templates/req-card-template.md`
169 161 - `${CLAUDE_SKILL_DIR}/templates/_module-template.md`
  162 +- `${CLAUDE_SKILL_DIR}/scripts/render.sh`(步骤 D 渲染助手,dispatch `module` / `req` 两种模式)
... ...
skills/plan/scope-lock/banners/flow.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ ▶ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ A5 生成下游文档 │
  15 +│ │
  16 +│ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/scope-lock/examples/example.md deleted
1   -<!--
2   -本文件示例 scope-lock 步骤 D 渲染后的单张 REQ 卡片产物。
3   -路径:docs/01-需求清单/USR-用户管理/REQ-USR-001.md
4   -
5   -CC 已替换 6 个占位符(req_id / title / goal / rules / constraints / acceptance);
6   -输入 / 输出 各保留「主表 + 从表1」骨架,每张表只有表头 + 1 行 `-`,等人工按业务补;
7   -依赖表 / 依赖接口 保留 `TBD(...)`,等 A3/A5 自动回填。
8   --->
9   -### REQ-USR-001 增加用户
10   -
11   -**目标**: 在系统中创建新用户账号,绑定员工并配置登录凭据、用户类型与权限组
12   -
13   -- **输入**:
14   - - **主表**:
15   -
16   - | 字段 | 类型 | 必填 | 输入方式 | 显示来源 | 默认值 | 业务规则 |
17   - | --- | --- | --- | --- | --- | --- | --- |
18   - | - | - | - | - | - | - | - |
19   -
20   - - **从表1**:
21   -
22   - | 字段 | 类型 | 必填 | 输入方式 | 显示来源 | 默认值 | 业务规则 |
23   - | --- | --- | --- | --- | --- | --- | --- |
24   - | - | - | - | - | - | - | - |
25   -
26   -- **输出**:
27   - - **主表**:
28   -
29   - | 字段 | 类型 | 必填 | 输入方式 | 显示来源 | 默认值 | 业务规则 |
30   - | --- | --- | --- | --- | --- | --- | --- |
31   - | - | - | - | - | - | - | - |
32   -
33   - - **从表1**:
34   -
35   - | 字段 | 类型 | 必填 | 输入方式 | 显示来源 | 默认值 | 业务规则 |
36   - | --- | --- | --- | --- | --- | --- | --- |
37   - | - | - | - | - | - | - | - |
38   -
39   -- **跨字段规则**: 员工名选定后用户号 / 用户名 / 手机号 / 邮箱自动带出;权限组至少 1 个
40   -- **边界**: 同一员工名不能重复创建账号;超级管理员仅允许系统内置创建
41   -- **验收**: 新增成功后可立即登录;字段校验失败时给出明确提示
42   -- **依赖表**: TBD(A3 自动补)
43   -- **依赖接口**: TBD(A5 自动补)
skills/plan/scope-lock/scripts/render.sh 0 → 100644
  1 +#!/usr/bin/env bash
  2 +# render.sh — scope-lock 步骤 D 渲染单个 _module.md 或 REQ-*.md
  3 +#
  4 +# 用法:
  5 +# bash render.sh module <out_path> <module_code> <module_name> <module_brief>
  6 +# bash render.sh req <out_path> <req_id> <title> <goal> <rules> <constraints> <acceptance>
  7 +#
  8 +# 模板路径自定位:脚本同级父目录下 templates/{_module-template.md, req-card-template.md}
  9 +
  10 +set -euo pipefail
  11 +
  12 +TYPE=${1:?missing type (module|req)}
  13 +shift
  14 +
  15 +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
  16 +TPL_DIR="$SCRIPT_DIR/../templates"
  17 +
  18 +case "$TYPE" in
  19 + module)
  20 + out=${1:?missing out_path}; code=${2:?}; name=${3:?}; brief=${4:?}
  21 + c=$(cat "$TPL_DIR/_module-template.md")
  22 + c="${c//\{\{module_code\}\}/$code}"
  23 + c="${c//\{\{module_name\}\}/$name}"
  24 + c="${c//\{\{module_brief\}\}/$brief}"
  25 + ;;
  26 + req)
  27 + out=${1:?missing out_path}; req_id=${2:?}; title=${3:?}; goal=${4:?}; rules=${5:?}; constraints=${6:?}; acceptance=${7:?}
  28 + c=$(sed '/^<!--$/,/^-->$/d' "$TPL_DIR/req-card-template.md")
  29 + c="${c//\{\{req_id\}\}/$req_id}"
  30 + c="${c//\{\{title\}\}/$title}"
  31 + c="${c//\{\{goal\}\}/$goal}"
  32 + c="${c//\{\{rules\}\}/$rules}"
  33 + c="${c//\{\{constraints\}\}/$constraints}"
  34 + c="${c//\{\{acceptance\}\}/$acceptance}"
  35 + ;;
  36 + *)
  37 + echo "render.sh: unknown type '$TYPE' (expect module|req)" >&2
  38 + exit 1
  39 + ;;
  40 +esac
  41 +
  42 +printf '%s\n' "$c" > "$out"
... ...
skills/plan/scope-lock/templates/_module-template.md
1 1 # {{module_code}}-{{module_name}}
2 2  
3   -模块简述: {{module_brief}}
4   -依赖模块: TBD(A5 自动补)
5   -涉及表: TBD(A3 自动补)
  3 +- **模块简述**: {{module_brief}}
  4 +- **依赖模块**: TBD(A5 自动补)
  5 +- **涉及表**: TBD(A3 自动补)
... ...
skills/plan/scope-lock/templates/req-card-template.md
... ... @@ -6,9 +6,10 @@ req-card-template:å•å¼  REQ å¡ç‰‡éª¨æž¶ã€‚æ¯å¼ å¡ç‰‡æ˜¯ docs/01-需求清å
6 6 - req_id / title:从核心功能点拆分命åå¾—æ¥
7 7 - goal:用一å¥è¯å±•å¼€ title
8 8 - rules / constraints / acceptance:业务语义层é¢çš„åˆç†èµ·è‰ï¼Œå¾…人工审阅修订
9   -2) `**输入**` / `**输出**` å„å«ã€Œä¸»è¡¨ + N 个从表ã€äºŒçº§ç»“构,æ¯å¼ è¡¨å†…å­—é¢ `-` 是**å­—é¢å ä½**,模æ¿åŽŸæ ·ä¿ç•™ã€‚等人工拿到生æˆçš„å¡ç‰‡åŽæŒ‰å®žé™…业务自己改:
10   - - æ¯å¼ è¡¨ï¼šä»…ä¿ç•™è¡¨å¤´ + 1 行 `-` 示æ„;人工按字段数å¤åˆ¶è¡Œ
11   - - 没有从表的 REQ:删掉 `从表1` 整段;多于一个从表:å¤åˆ¶ `从表1` æ®µå¹¶æ”¹æˆ `从表2 / 从表3 / ...`
  9 +2) `**输入**` / `**输出**` äºŒçº§ç»“æž„ï¼šæ¯æ®µå…ˆä¸€å¥è¯æ€»ç»“(如「用户æäº¤...ã€/「返回用户 idã€ï¼‰ï¼Œå†è·Ÿã€Œè¡¨1 / 表2 / ...ã€N 张平铺的字段表。CC 渲染时对**两段简述 + 所有表(å«ç¤ºä¾‹æ•°æ®ï¼‰å…¨éƒ¨åŽŸæ ·å¤åˆ¶**,ä¸è¦æ ¹æ® REQ 业务篡改示例字段ã€ä¹Ÿä¸è¦æ¢åˆ—结构:
  10 + - `输入` 的表:7 列(字段 / 类型 / å¿…å¡« / è¾“å…¥æ–¹å¼ / æ˜¾ç¤ºæ¥æº / 默认值 / 业务规则),模æ¿å†…å«ç¤ºä¾‹æ•°æ®ï¼ˆè¡¨1 6 行ã€è¡¨2 3 行)
  11 + - `输出` 的表:3 列(字段 / 类型 / æ˜¾ç¤ºæ¥æºï¼‰ï¼Œæ¨¡æ¿å†…å«ç¤ºä¾‹æ•°æ®ï¼ˆè¡¨1 / 表2 å„ 3 行)
  12 + - è¡¨çš„æ•°é‡æ˜¯å¯å˜çš„:人工拿到å¡ç‰‡åŽæŒ‰ REQ 实际情况增删表(删多余的 `表N` 整段 / å¤åˆ¶ä¸º `表3 / 表4 / ...`)和编辑字段
12 13 3) `**ä¾èµ–表**: TBD(A3 自动补)` å’Œ `**ä¾èµ–接å£**: TBD(A5 自动补)` 是åŽç»­ skill 自动回填的å ä½ï¼Œæ¸²æŸ“æ—¶**ä¿æŒåŽŸæ ·**,ä¸è¦æ›¿æ¢ä¸º `-` 也ä¸è¦æ›¿æ¢ä¸º `{{...}}`
13 14 4) 渲染åŽè¿™æ®µ HTML 注释è¦**剥掉**,ä¸è¿›å…¥æœ€ç»ˆå¡ç‰‡
14 15 -->
... ... @@ -16,31 +17,44 @@ req-card-template:å•å¼  REQ å¡ç‰‡éª¨æž¶ã€‚æ¯å¼ å¡ç‰‡æ˜¯ docs/01-需求清å
16 17  
17 18 **目标**: {{goal}}
18 19  
19   -- **输入**:
20   - - **主表**:
  20 +- **输入**: 用户æäº¤ç”¨æˆ·å(3-20 ä½å­—æ¯æ•°å­—下划线,系统内唯一)ã€å§“å(2-50å­—ç¬¦ï¼‰ã€æ‰‹æœºå·ï¼ˆ11 使•°å­—,系统内唯一)ã€é‚®ç®±ï¼ˆæ ‡å‡†é‚®ç®±æ ¼å¼ï¼Œå¯é€‰ï¼‰ã€åˆå§‹å¯†ç ï¼ˆ8-20ä½å«å¤§å°å†™å­—æ¯å’Œæ•°å­—)
  21 +
  22 + - **表1**:
21 23  
22   - | 字段 | 类型 | å¿…å¡« | è¾“å…¥æ–¹å¼ | æ˜¾ç¤ºæ¥æº | 默认值 | 业务规则 |
23   - | --- | --- | --- | --- | --- | --- | --- |
24   - | - | - | - | - | - | - | - |
  24 + | 字段 | 类型 | å¿…å¡« | è¾“å…¥æ–¹å¼ | æ˜¾ç¤ºæ¥æº | 默认值 | 业务规则 |
  25 + | ---- | ---- | --- | ---- | ----- | --- | ------------------- |
  26 + | 用户å | 文本 | 是 | 手工输入 | `èŒå‘˜è¡¨` | — | 3-20 ä½å­—æ¯æ•°å­—下划线;系统内唯一 |
  27 + | å§“å | 文本 | 是 | 下拉å•选 | `èŒå‘˜è¡¨` | — | 2-50 个字符 |
  28 + | æ‰‹æœºå· | 文本 | 是 | 手工输入 | `èŒå‘˜è¡¨` | — | 11 使•°å­—;系统内唯一 |
  29 + | 邮箱 | 文本 | å¦ | 手工输入 | `èŒå‘˜è¡¨` | — | æ ‡å‡†é‚®ç®±æ ¼å¼ |
  30 + | 角色 | 文本 | 是 | 下拉å•选 | 普通用户/超级管ç†å‘˜ | 普通用户 | 至少选择 1 个 |
  31 + | åˆå§‹å¯†ç  | 文本 | 是 | 手工输入 | — | — | 8-20 ä½ï¼›å«å¤§å°å†™å­—æ¯å’Œæ•°å­—ï¼›æ˜¾ç¤ºæ˜Ÿå· |
25 32  
26   - - **从表1**:
  33 + - **表2**:
27 34  
28 35 | 字段 | 类型 | å¿…å¡« | è¾“å…¥æ–¹å¼ | æ˜¾ç¤ºæ¥æº | 默认值 | 业务规则 |
29 36 | --- | --- | --- | --- | --- | --- | --- |
30   - | - | - | - | - | - | - | - |
  37 + | 用户å | 文本 | 是 | 手工输入 | `èŒå‘˜è¡¨` | — | 3-20 ä½å­—æ¯æ•°å­—下划线;系统内唯一 |
  38 + | å§“å | 文本 | 是 | 下拉å•选 | `èŒå‘˜è¡¨` | — | 2-50 个字符 |
  39 + | æ‰‹æœºå· | 文本 | 是 | 手工输入 | `èŒå‘˜è¡¨` | — | 11 使•°å­—;系统内唯一 |
31 40  
32   -- **输出**:
33   - - **主表**:
  41 +- **输出**: 返回用户 id
  42 +
  43 + - **表1**:
34 44  
35   - | 字段 | 类型 | å¿…å¡« | è¾“å…¥æ–¹å¼ | æ˜¾ç¤ºæ¥æº | 默认值 | 业务规则 |
36   - | --- | --- | --- | --- | --- | --- | --- |
37   - | - | - | - | - | - | - | - |
  45 + | 字段 | 类型 | æ˜¾ç¤ºæ¥æº |
  46 + | --- | --- | --- |
  47 + | 用户å | 文本 | `èŒå‘˜è¡¨` |
  48 + | å§“å | 文本 | `èŒå‘˜è¡¨` |
  49 + | 角色 | 文本 | `èŒå‘˜è¡¨` |
38 50  
39   - - **从表1**:
  51 + - **表2**:
40 52  
41   - | 字段 | 类型 | å¿…å¡« | è¾“å…¥æ–¹å¼ | æ˜¾ç¤ºæ¥æº | 默认值 | 业务规则 |
42   - | --- | --- | --- | --- | --- | --- | --- |
43   - | - | - | - | - | - | - | - |
  53 + | 字段 | 类型 | æ˜¾ç¤ºæ¥æº |
  54 + | --- | --- | --- |
  55 + | 用户å | 文本 | `èŒå‘˜è¡¨` |
  56 + | å§“å | 文本 | `èŒå‘˜è¡¨` |
  57 + | 角色 | 文本 | `èŒå‘˜è¡¨` |
44 58  
45 59 - **跨字段规则**: {{rules}}
46 60 - **边界**: {{constraints}}
... ...
skills/plan/skeleton-gen/SKILL.md
... ... @@ -13,20 +13,10 @@ allowed-tools: Read Write Edit Skill Grep Glob AskUserQuestion Bash(mkdir *) Bas
13 13  
14 14 ### 步骤 0:打印当前位置流程图
15 15  
16   -向用户展示当前在 A 阶段流程中的位置
  16 +用 `Bash` 执行 `cat` 命令向用户展示当前位置流程图(stdout 即 ASCII 框图)
17 17  
18   -```
19   -┌──────────────────────────────────────────────────────┐
20   -│ 📋 阶段 A:规划(一次性) │
21   -│ │
22   -│ A0 初始化项目 → A1 锁范围(REQ 卡片) │
23   -│ ↓ │
24   -│ ⏸ 等你审阅 REQ,重新运行 /plan-start 继续 │
25   -│ ↓ │
26   -│ ▶ A2 生成骨架 → A3 生成 DB 设计 → A4 初始化 DB → A5 生成下游文档│
27   -│ ↓ │
28   -│ 规划阶段到此结束 │
29   -└──────────────────────────────────────────────────────┘
  18 +```bash
  19 +cat "${CLAUDE_PLUGIN_ROOT}/skills/plan/skeleton-gen/banners/flow.txt"
30 20 ```
31 21  
32 22 ### A. 读取锁定的输入
... ... @@ -159,6 +149,7 @@ QA 横幅涵盖:产出文件清单(docs/04 / 06 / 07 / 09 + scripts/*.sh + .
159 149 - `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md`(大纲)
160 150 - `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md`(大纲)
161 151 - `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md`(大纲)
  152 +- `${CLAUDE_SKILL_DIR}/templates/scripts-test-template.sh`(推断命令填充:build/lint/test/e2e)
162 153 - `${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh`(0 槽位)
163 154 - `${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh`(0 槽位)
164 155 - `${CLAUDE_SKILL_DIR}/templates/env-local-template`(0 槽位)
... ...
skills/plan/skeleton-gen/banners/flow.txt 0 → 100644
  1 +┌────────────────────────────────────────────────────────┐
  2 +│ 📋 阶段 A:规划(一次性) │
  3 +│ │
  4 +│ A0 初始化项目 │
  5 +│ ↓ │
  6 +│ A1 锁范围(生成 REQ 卡片) → 人工审核 │
  7 +│ ↓ │
  8 +│ ▶ A2 生成骨架 │
  9 +│ ↓ │
  10 +│ A3 生成 DB 设计 → 人工审核 │
  11 +│ ↓ │
  12 +│ A4 初始化 DB │
  13 +│ ↓ │
  14 +│ A5 生成下游文档 │
  15 +│ │
  16 +│ 规划阶段到此结束 │
  17 +└────────────────────────────────────────────────────────┘
... ...
skills/plan/skeleton-gen/templates/docs-06-static-template.md
... ... @@ -43,5 +43,5 @@ UI ç»†èŠ‚ï¼ˆå¸ƒå±€å‚æ•°ã€é¢œè‰²ã€ç»„件选型)æ¥è‡ª § é›¶ å‰ç«¯ UI 组ä»
43 43 ## å››ã€ä¸»é¢˜ä¸Žé¢œè‰²
44 44 <!-- 基于 § é›¶ UI 库的主题 token;主色 / æˆåŠŸ / 警告 / 错误 色值。 -->
45 45  
46   -## 五ã€é¡µé¢æ¸…å•(CC 生æˆï¼‰
  46 +## 五ã€é¡µé¢æ¸…å•
47 47 (由 `downstream-gen` 按模å—追加段è½ï¼‰
... ...