Commit 21e90b624cec13f41fb19f8143da147e43782c19
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="$project_dir/docs/superpowers/module-reports" |
| 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"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1;" |
| 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"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" "$DB_SCHEMA" \ |
| 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 '^## `' 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 "${CLAUDE_SKILL_DIR}/templates/docs-08-initial-template.md" 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
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` 按模å—è¿½åŠ æ®µè½ï¼‰ | ... | ... |