Commit d61c07b15790812ceb77f6dcfdbc0068ef5188a9
1 parent
f7306acf
skill(plan A3-A6): trim banners, drop redundant verification loops, defer plan-start narration
Showing
4 changed files
with
52 additions
and
205 deletions
skills/plan/db-design-gen/SKILL.md
| 1 | --- | 1 | --- |
| 2 | name: db-design-gen | 2 | name: db-design-gen |
| 3 | -description: A3 DB 设计 + REQ 回填——基于 docs/01-需求清单/<module>/REQ-*.md 正向设计 docs/03-数据库设计文档.md(业务实体 → 表 + 字段 + 索引 + 外键 + 业务注记),并把回填值写入 REQ 卡片的「依赖表: TBD(A3 自动补)」与模块头的「涉及表: TBD(A3 自动补)」占位。生成完毕停下等人工审阅。 | 3 | +description: A3 DB 设计 + REQ 回填——A0 确认 schema 约定写入 docs/04 + CLAUDE.md;基于 docs/01 REQ 卡片正向设计 docs/03(表/字段/索引/外键/业务注记),并回填 REQ 卡片「依赖表」与模块头「涉及表」的 `TBD(A3 自动补)`。停下等人工审阅。 |
| 4 | user-invocable: false | 4 | user-invocable: false |
| 5 | allowed-tools: Read Write Edit Grep Glob AskUserQuestion | 5 | allowed-tools: Read Write Edit Grep Glob AskUserQuestion |
| 6 | --- | 6 | --- |
| @@ -18,30 +18,15 @@ allowed-tools: Read Write Edit Grep Glob AskUserQuestion | @@ -18,30 +18,15 @@ allowed-tools: Read Write Edit Grep Glob AskUserQuestion | ||
| 18 | 18 | ||
| 19 | ### 步骤 A0:确认 ERP schema 约定(一次性) | 19 | ### 步骤 A0:确认 ERP schema 约定(一次性) |
| 20 | 20 | ||
| 21 | -在正向设计 schema 之前,**先确认本项目的 3 项数据库约定**。默认值即现 ERP 约定,用户可逐项覆盖。结果写入 `docs/04` + `CLAUDE.md`,本 skill 后续步骤(B/C)严格引用确认后的值,不再字面写死。 | 21 | +先 `Grep` `docs/04-技术规范.md § 四 数据库 schema 约定`。已存在则读取后直接进入步骤 A;缺失则按下表默认值,逐项问用户是否覆盖: |
| 22 | 22 | ||
| 23 | -> 先用 `Grep` 检查 `docs/04-技术规范.md` 是否已含 `## 四、数据库 schema 约定` 节。**已存在则视为本约定已确认**,跳过本步骤直接读取该节作为 `PK_CONVENTION` / `TENANT_COLS` / `COL_PREFIX_RULE` 的值,进入步骤 A。 | 23 | +| 键 | 默认值(ERP 沿用) | |
| 24 | +|---|---| | ||
| 25 | +| `PK_CONVENTION` | `iIncrement` int 主键 + `sId` varchar(100) 业务 ID | | ||
| 26 | +| `TENANT_COLS` | `sBrandsId` varchar(100) + `sSubsidiaryId` varchar(100),默认值 `1111111111`(无多租户则填「无」) | | ||
| 27 | +| `COL_PREFIX_RULE` | 匈牙利前缀 `i`=int / `s`=varchar / `t`=datetime(无前缀则填「无前缀」) | | ||
| 24 | 28 | ||
| 25 | -用 `AskUserQuestion` 一次性提出以下 3 个问题(每题给「沿用默认」与「自定义」两类选项;选自定义时追问具体值): | ||
| 26 | - | ||
| 27 | -1. **主键约定(PK_CONVENTION)** | ||
| 28 | - - 默认(沿用 ERP):`iIncrement` int 整数主键(自增方式由实现决定:DB `AUTO_INCREMENT` 或应用/触发器分配),另设 `sId` varchar(100) 业务 ID 对外暴露。 | ||
| 29 | - - 自定义:用户给出主键列名 / 类型 / 生成策略(如复合主键 / UUID / 业务主键)。 | ||
| 30 | - | ||
| 31 | -2. **租户隔离列(TENANT_COLS)** | ||
| 32 | - - 默认(沿用 ERP):`sBrandsId` varchar(100)(品牌 ID,多租户隔离)+ `sSubsidiaryId` varchar(100)(子公司 ID,组织层级隔离),默认值均为 `1111111111`。 | ||
| 33 | - - 自定义:用户给出租户列名 / 类型 / 默认值,或声明本项目不做多租户隔离(此时 TENANT_COLS = 「无」)。 | ||
| 34 | - | ||
| 35 | -3. **列命名前缀规则(COL_PREFIX_RULE)** | ||
| 36 | - - 默认(沿用 ERP):匈牙利前缀——`i` = int、`s` = varchar、`t` = datetime。 | ||
| 37 | - - 自定义:用户给出自己的前缀/命名规则,或声明不使用前缀(此时 COL_PREFIX_RULE = 「无前缀,列名直接用业务语义」)。 | ||
| 38 | - | ||
| 39 | -得到三项确认值后: | ||
| 40 | - | ||
| 41 | -- **写入 `docs/04-技术规范.md`**:用 `Grep` 确认无 `## 四、数据库 schema 约定` 节后,用 `Edit` 在文末追加该节,列出 `PK_CONVENTION` / `TENANT_COLS` / `COL_PREFIX_RULE` 三项的确认值(每项含列名/类型/默认值/生成策略的完整描述)。 | ||
| 42 | -- **写入 `CLAUDE.md`**:用 `Edit` 在「Schema 演化规约」节末尾追加一条「数据库 schema 约定(A3 确认)」小节,简述三项约定,并注明「详见 `docs/04 § 四`」。 | ||
| 43 | - | ||
| 44 | -后续步骤 B/C 用到 `{{PK_CONVENTION}}` / `{{TENANT_COLS}}` / `{{COL_PREFIX_RULE}}` 处,一律引用此处确认后的值。 | 29 | +如 `docs/04 § 四` 缺失,用 `AskUserQuestion` 一次性收三项覆盖(默认即沿用上表),然后 `Edit` 追加 `docs/04 § 四` + 在 `CLAUDE.md`「Schema 演化规约」末尾追加「数据库 schema 约定(A3 确认)」一段引用 `docs/04 § 四`。后续 B/C 步骤一律引用确认后的值。 |
| 45 | 30 | ||
| 46 | ### A. 读取设计输入 | 31 | ### A. 读取设计输入 |
| 47 | 32 | ||
| @@ -86,32 +71,15 @@ allowed-tools: Read Write Edit Grep Glob AskUserQuestion | @@ -86,32 +71,15 @@ allowed-tools: Read Write Edit Grep Glob AskUserQuestion | ||
| 86 | 1. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选 A3 顶层(A3 两个子项已在 C / D 步骤分别勾选): | 71 | 1. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选 A3 顶层(A3 两个子项已在 C / D 步骤分别勾选): |
| 87 | - `- [ ] A3 DB 设计 + REQ 回填 — db-design-gen` | 72 | - `- [ ] A3 DB 设计 + REQ 回填 — db-design-gen` |
| 88 | 73 | ||
| 89 | -2. 打印停下横幅并**停下**: | 74 | +2. 打印停下横幅并**停下**,不调用任何下游 skill: |
| 90 | 75 | ||
| 91 | ``` | 76 | ``` |
| 92 | - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
| 93 | - [db-design-gen] ✅ A3 DB 设计完成 | ||
| 94 | - | ||
| 95 | - 产出: | ||
| 96 | - ✓ docs/03-数据库设计文档.md | ||
| 97 | - ✓ docs/01-需求清单/<module>/REQ-*.md 依赖表已回填 + _module.md 涉及表已回填 | ||
| 98 | - | ||
| 99 | - ⏸ 现在请你审阅 docs/03。 | ||
| 100 | - 重点关注: | ||
| 101 | - - 业务实体覆盖是否完整 | ||
| 102 | - - 字段类型 / 长度 / 是否可空 / 默认值是否合理 | ||
| 103 | - - 索引是否覆盖主要查询模式 | ||
| 104 | - - 外键 ON DELETE / ON UPDATE 策略是否符合业务 | ||
| 105 | - - 字段「业务含义」列含 `【人工填写:需用户审阅】` 标注的位置需逐一确认 | ||
| 106 | - | ||
| 107 | - 审阅完成后,再运行: | ||
| 108 | - /erp-workflow:plan-start | ||
| 109 | - | ||
| 110 | - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | 77 | + [db-design-gen] ✅ A3 DB 设计完成 |
| 78 | + 产出:docs/03-数据库设计文档.md + REQ 卡片依赖表/模块头涉及表已回填 | ||
| 79 | + ⏸ 请审阅 docs/03(业务实体覆盖、字段类型/默认值、索引、外键策略、`【人工填写:需用户审阅】` 标注)。 | ||
| 80 | + 审阅完成后运行:/erp-workflow:plan-start | ||
| 111 | ``` | 81 | ``` |
| 112 | 82 | ||
| 113 | - **停止**,不调用任何下游 skill。 | ||
| 114 | - | ||
| 115 | ## 参考 | 83 | ## 参考 |
| 116 | 84 | ||
| 117 | - `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md` | 85 | - `${CLAUDE_SKILL_DIR}/templates/docs-03-header-template.md` |
skills/plan/db-init/SKILL.md
| @@ -15,31 +15,20 @@ allowed-tools: Read Write Edit Glob Skill Bash(node *) Bash(mysql *) | @@ -15,31 +15,20 @@ allowed-tools: Read Write Edit Glob Skill Bash(node *) Bash(mysql *) | ||
| 15 | 15 | ||
| 16 | #### A.1 读 docs/03 并翻译为 DDL | 16 | #### A.1 读 docs/03 并翻译为 DDL |
| 17 | 17 | ||
| 18 | -读取 `docs/03-数据库设计文档.md`,按字段 / 索引 / 外键 / 业务注记**严格翻译**为: | ||
| 19 | - | ||
| 20 | -- 每张表一段 `CREATE TABLE` | ||
| 21 | -- 字段顺序与 docs/03 表格行序一致;`Nullable` 列直接映射 `NOT NULL` / `NULL`;`默认` 列映射 `DEFAULT <value>`;列尾用 `COMMENT '<业务含义>'` 写注释 | ||
| 22 | -- 索引 | ||
| 23 | -- 外键:在所有表创建完成后**统一追加** | ||
| 24 | - | ||
| 25 | -要求: | ||
| 26 | -- **严禁臆造** docs/03 中没有的表 / 字段 / 索引 / 外键 | ||
| 27 | -- **严禁省略** docs/03 中已有的列、注释或约束 | ||
| 28 | -- 字符集统一 `utf8mb4` + `utf8mb4_unicode_ci`,引擎统一 `InnoDB`,除非 docs/03 业务注记明确要求其他设置 | 18 | +读取 `docs/03-数据库设计文档.md`,对每张表生成一段 `CREATE TABLE`(字段顺序/可空/默认/列注释严格对齐 docs/03 行序),随后按顺序追加 `CREATE INDEX` 与统一追加的 `ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY`。**严禁臆造或省略** docs/03 中的任何表/字段/索引/外键/约束。字符集 `utf8mb4` + `utf8mb4_unicode_ci`、引擎 `InnoDB`,除非 docs/03 业务注记另有说明。 |
| 29 | 19 | ||
| 30 | #### A.2 落盘 V1 文件 | 20 | #### A.2 落盘 V1 文件 |
| 31 | 21 | ||
| 32 | -用 `Write` 写 `sql/migrations/V1__initial_schema.sql`(`Write` 会自动创建缺失的父目录 `sql/migrations/`),内容 = 头部注释 + DDL 主体: | ||
| 33 | - | ||
| 34 | -1. **头部注释**(6 行 SQL 注释): | ||
| 35 | - - `-- Flyway migration V1 — initial schema for <project_name>`(从 `CLAUDE.md § 🎯 项目概述` 读) | ||
| 36 | - - `-- Generated: <YYYY-MM-DDTHH:MM:SSZ>`(UTC ISO 8601 时间戳) | ||
| 37 | - - `-- Source: 由 A4 db-init 从 docs/03-数据库设计文档.md 翻译生成(schema SSoT 是 docs/03)` | ||
| 38 | - - `-- This is the FIRST migration; subsequent schema changes must be written as new files sql/migrations/V2__<desc>.sql, V3__... etc.` | ||
| 39 | - - `-- Apply: Flyway runs this automatically at Spring Boot startup.` | ||
| 40 | - - `-- Do not hand-edit this file after it is committed; write a new migration instead.` | 22 | +用 `Write` 写 `sql/migrations/V1__initial_schema.sql`(`Write` 自动创建父目录)。文件开头是以下 6 行注释,其后接 A.1 的 DDL 主体(`CREATE TABLE` → `CREATE INDEX` → `ALTER TABLE ... ADD FOREIGN KEY`): |
| 41 | 23 | ||
| 42 | -2. **DDL 主体**:A.1 推导出的所有 `CREATE TABLE` → `CREATE INDEX` → `ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY`,按此顺序拼接。 | 24 | +```sql |
| 25 | +-- Flyway migration V1 — initial schema for <project_name> -- 从 CLAUDE.md § 🎯 项目概述 读 | ||
| 26 | +-- Generated: <YYYY-MM-DDTHH:MM:SSZ> -- UTC ISO 8601 | ||
| 27 | +-- Source: 由 A4 db-init 从 docs/03-数据库设计文档.md 翻译生成(schema SSoT 是 docs/03) | ||
| 28 | +-- This is the FIRST migration; subsequent schema changes must be written as new files sql/migrations/V2__<desc>.sql, V3__... etc. | ||
| 29 | +-- Apply: Flyway runs this automatically at Spring Boot startup. | ||
| 30 | +-- Do not hand-edit this file after it is committed; write a new migration instead. | ||
| 31 | +``` | ||
| 43 | 32 | ||
| 44 | #### A.3 校验 V1 ↔ docs/03 5 维一致性 + 自主修正 | 33 | #### A.3 校验 V1 ↔ docs/03 5 维一致性 + 自主修正 |
| 45 | 34 | ||
| @@ -65,24 +54,15 @@ node "${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs" \ | @@ -65,24 +54,15 @@ node "${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs" \ | ||
| 65 | 54 | ||
| 66 | ### B. 数据库环境检查 | 55 | ### B. 数据库环境检查 |
| 67 | 56 | ||
| 68 | -#### B.1 检查 .env.local 凭据 | ||
| 69 | - | ||
| 70 | -用 `Glob` 检查 `.env.local` 是否存在;不存在 → 提示用户重新运行 A2 `skeleton-gen` 重建并停下。 | 57 | +用 `Glob` 确认 `.env.local` 存在(不存在 → 提示重跑 A2 `skeleton-gen` 并停下)。用 `Read` 逐行解析 `KEY=VALUE`(跳过空行 / `#` 注释,**不做 shell-source / 变量展开**),校验 `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_SCHEMA` 5 项均非空——任一缺失 → 打印缺失字段并停下。 |
| 71 | 58 | ||
| 72 | -用 `Read` 读取 `.env.local`,逐行解析 `KEY=VALUE`(跳过空行 / `#` 注释,**不做** shell-source / 变量展开),校验 5 个必填字段 `DB_HOST`、`DB_PORT`、`DB_USER`、`DB_PASSWORD`、`DB_SCHEMA` 均存在且非空。 | ||
| 73 | - | ||
| 74 | -任一缺失 → 打印缺失字段名并停下,提示用户编辑 `.env.local` 后重跑。 | ||
| 75 | - | ||
| 76 | -#### B.2 验证 MySQL 连接 | ||
| 77 | - | ||
| 78 | -用 B.1 解析出的字段值(**不要** shell-source `.env.local`)拼出 `mysql` 客户端调用,做一次连通性自检。把 `<DB_HOST>` 等占位替换为读到的实际值: | 59 | +用解析出的值跑连通性自检: |
| 79 | 60 | ||
| 80 | ```bash | 61 | ```bash |
| 81 | mysql -h<DB_HOST> -P<DB_PORT> -u<DB_USER> -p<DB_PASSWORD> -e "SELECT 1;" | 62 | mysql -h<DB_HOST> -P<DB_PORT> -u<DB_USER> -p<DB_PASSWORD> -e "SELECT 1;" |
| 82 | ``` | 63 | ``` |
| 83 | 64 | ||
| 84 | -- **成功** → 进入步骤 C | ||
| 85 | -- **失败** → 打印具体错误(认证 / 主机不可达 / 端口拒接等),提示检查 `.env.local`,**停下**。 | 65 | +成功 → 进入步骤 C;失败 → 打印具体错误(认证 / 主机不可达 / 端口拒接)并停下。 |
| 86 | 66 | ||
| 87 | 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: | 67 | 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: |
| 88 | - ` - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)` | 68 | - ` - [ ] .env.local 凭据已验证(mysql -e "SELECT 1" OK)` |
| @@ -104,29 +84,16 @@ node "${CLAUDE_PLUGIN_ROOT}/lib/apply-ddl.mjs" .env.local sql/migrations/V1__ini | @@ -104,29 +84,16 @@ node "${CLAUDE_PLUGIN_ROOT}/lib/apply-ddl.mjs" .env.local sql/migrations/V1__ini | ||
| 104 | ``` | 84 | ``` |
| 105 | 85 | ||
| 106 | 退出码与处理: | 86 | 退出码与处理: |
| 107 | -- `0` → 成功,进入 C.3 | ||
| 108 | -- `1` → 失败:若错误提示 `mysql2 not found`,先在目标项目执行 `npm i mysql2` 再重跑;其余错误打印 stderr 并停下 | 87 | +- `0` → 成功,进入步骤 D |
| 88 | +- `1` → 失败:打印 stderr 并停下 | ||
| 109 | - `2` → 用法错(路径找不到),打印路径并停下 | 89 | - `2` → 用法错(路径找不到),打印路径并停下 |
| 110 | 90 | ||
| 111 | 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: | 91 | 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: |
| 112 | - ` - [ ] setup-test-db.mjs 防护通过 + DROP+CREATE + apply V1 已执行` | 92 | - ` - [ ] setup-test-db.mjs 防护通过 + DROP+CREATE + apply V1 已执行` |
| 113 | 93 | ||
| 114 | -#### C.3 自检:docs/03 ↔ V1 表集合一致 | ||
| 115 | - | ||
| 116 | -再跑一次 `validate-ddl.mjs`,确认刚 apply 的 `V1__initial_schema.sql` 与 docs/03 的表/列/类型/索引/外键 5 维仍然一致(参数顺序:docs/03 在前,V1.sql 在后): | ||
| 117 | - | ||
| 118 | -```bash | ||
| 119 | -node "${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs" \ | ||
| 120 | - docs/03-数据库设计文档.md \ | ||
| 121 | - sql/migrations/V1__initial_schema.sql | ||
| 122 | -``` | ||
| 123 | - | ||
| 124 | -退出码 `0` → 进入步骤 D;`1` → 打印 stderr 5 维 diff 并停下;`2` → 路径错,打印路径并停下。 | ||
| 125 | - | ||
| 126 | ### D. 勾选 docs/08 进度 + 进入 A5 | 94 | ### D. 勾选 docs/08 进度 + 进入 A5 |
| 127 | 95 | ||
| 128 | - | ||
| 129 | -1. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选(A4 子项 + A4 顶层): | 96 | +1. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选(A4 子项 + A4 顶层;DDL ↔ docs/03 5 维一致已由 A.3 校验过,V1 文件自此未变): |
| 130 | - ` - [ ] DDL ↔ docs/03 apply 后 5 维一致(validate-ddl.mjs)` | 97 | - ` - [ ] DDL ↔ docs/03 apply 后 5 维一致(validate-ddl.mjs)` |
| 131 | - `- [ ] A4 DB 初始化 — db-init` | 98 | - `- [ ] A4 DB 初始化 — db-init` |
| 132 | 99 | ||
| @@ -134,7 +101,7 @@ node "${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs" \ | @@ -134,7 +101,7 @@ node "${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs" \ | ||
| 134 | 101 | ||
| 135 | ## 参考 | 102 | ## 参考 |
| 136 | 103 | ||
| 137 | -- `${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs`(A.3 / C.3 docs/03 ↔ V1.sql 5 维一致性校验,跨平台纯 Node) | 104 | +- `${CLAUDE_PLUGIN_ROOT}/lib/validate-ddl.mjs`(A.3 docs/03 ↔ V1.sql 5 维一致性校验,跨平台纯 Node) |
| 138 | - `${CLAUDE_PLUGIN_ROOT}/lib/apply-ddl.mjs`(C.2 安全解析 .env.local + mysql2 灌入 DDL,不 shell-source) | 105 | - `${CLAUDE_PLUGIN_ROOT}/lib/apply-ddl.mjs`(C.2 安全解析 .env.local + mysql2 灌入 DDL,不 shell-source) |
| 139 | - `docs/03-数据库设计文档.md`(DDL 翻译输入,SSoT) | 106 | - `docs/03-数据库设计文档.md`(DDL 翻译输入,SSoT) |
| 140 | - `.env.local`(DB 凭据) | 107 | - `.env.local`(DB 凭据) |
skills/plan/downstream-gen/SKILL.md
| @@ -15,21 +15,9 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion | @@ -15,21 +15,9 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion | ||
| 15 | 15 | ||
| 16 | **清单颗粒度**:一行一个 REQ,同一模块的 REQ 必须**连续排列**。 | 16 | **清单颗粒度**:一行一个 REQ,同一模块的 REQ 必须**连续排列**。 |
| 17 | 17 | ||
| 18 | -1. 构建**模块依赖 DAG**。 | ||
| 19 | -2. 对**每个模块内部**构建 REQ 间依赖,得到模块内 REQ 顺序。 | ||
| 20 | -3. 合成 `req_order[]`:按 `module_topo_order[]` 依次铺开每个模块内的 REQ 序列(**同模块 REQ 连续**)。 | ||
| 21 | -4. **环依赖打破**: | ||
| 22 | - - **模块级**:若模块 DAG 存在环(module_A ↔ module_B),按启发式(字母序 / 被依赖次数多者先)破环排出 `module_topo_order`,并在**参与环的模块里第一个 REQ** 的 `note` 字段填入原因(如 "A↔B 互依赖:先做 A 的骨架")。 | ||
| 23 | - - **REQ 级(同模块内)**:若模块内 REQ 互依赖,同样破环,`note` 填原因。 | ||
| 24 | - - 非环 REQ `note` 留 `—`。 | ||
| 25 | -5. 为 `req_order[]` 每项生成字段: | ||
| 26 | - - `index`:行号(从 1 开始) | ||
| 27 | - - `req_id`:如 `REQ-SYS-001` | ||
| 28 | - - `module_id`:该 REQ 所属模块,如 `module_sys` | ||
| 29 | - - `rationale`(**选中理由**):依赖驱动的简短描述,如 `所属模块无依赖,基础模块` / `依赖 REQ-SYS-001 已在前` / `所属模块依赖 module_sys 已在前` | ||
| 30 | - - `note`(**备注**):默认 `—`;仅环依赖打破场景填原因 | ||
| 31 | -6. 读取并填充 `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md`。 | ||
| 32 | -7. 写入 `docs/02-开发计划.md`。 | 18 | +1. 拓扑排模块得 `module_topo_order[]`,对每个模块内部拓扑排 REQ;按模块顺序依次铺开生成 `req_order[]`(同模块 REQ 连续)。出现环(模块级或模块内 REQ 级)用启发式(字母序 / 被依赖次数多者先)破环,并把原因填入参与环的首个 REQ 的 `note`;非环 REQ `note` 留 `—`。 |
| 19 | +2. 为每项生成 `index`(从 1)/ `req_id` / `module_id` / `rationale`(依赖驱动短描述)/ `note`。 | ||
| 20 | +3. 读取并填充 `${CLAUDE_SKILL_DIR}/templates/docs-02-template.md`,写入 `docs/02-开发计划.md`。 | ||
| 33 | 21 | ||
| 34 | 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: | 22 | 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 中勾选: |
| 35 | - ` - [ ] docs/02 开发计划已生成` | 23 | - ` - [ ] docs/02 开发计划已生成` |
| @@ -73,67 +61,25 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion | @@ -73,67 +61,25 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion | ||
| 73 | 61 | ||
| 74 | ### F. 验证 + 勾选 docs/08 进度 + 结束 Plan | 62 | ### F. 验证 + 勾选 docs/08 进度 + 结束 Plan |
| 75 | 63 | ||
| 76 | -1. 一致性检查 + 自主修复循环(最多 3 轮,docs/01 是 REQ SSoT 不动): | 64 | +1. **合并扫描三类问题**(最多 3 轮自主修复,docs/01 是 REQ SSoT 不动)——一次性扫一致性 + `TBD(A3/A5 自动补)` + 结构性残留: |
| 77 | 65 | ||
| 78 | - **检查项**: | ||
| 79 | - - 每个 docs/01 REQ 都出现在 docs/05(作为接口,如适用) | ||
| 80 | - - `docs/02 § 二` 的 `module_id` 集合 = `docs/08 § 二` 的 `module_id` 集合 | 66 | + - **一致性**:docs/01 REQ 全部出现在 docs/05;`docs/02 § 二` `module_id` 集合 = `docs/08 § 二` `module_id` 集合。 |
| 67 | + - **TBD 残留**:`TBD(A3 自动补)` → 查 docs/03 填依赖表;`TBD(A5 自动补)` → 查 docs/05 按 REQ-ID 填依赖接口。 | ||
| 68 | + - **结构性**:docs/05 每个 `### REQ-` 端点段含非空 `- **请求**:` / `- **响应**:`(非 `TBD`/`—`/`【人工填写:…】`);docs/01 全部 REQ-ID 都出现在 `docs/02 § 二` 顺序清单。 | ||
| 81 | 69 | ||
| 82 | - **不一致 → 按差异类型自主修复**: | ||
| 83 | - - **REQ 缺 docs/05 endpoint** → 按步骤 B 规则为该 REQ 推测,并追加到 docs/05 | ||
| 84 | - - **module_id 缺 docs/08 § 二** → 按步骤 D 规则渲染该模块 bullet(含 REQ 子项),按 `module_id` 字母序插入正确位置 | ||
| 85 | - - **module_id 缺 docs/02 § 二** → 重算该模块的 `req_order` 段(步骤 A 子流程),按拓扑序插入 docs/02 § 二 | 70 | + 命中即按对应步骤规则就地补填(缺端点 → 按 B 推测;缺 module 行 → 按 D 渲染;缺 REQ 顺序行 → 按 A 子流程拓扑插入)。3 轮后仍残留 `【人工填写:】` 或结构缺口 → 打印清单 + 用 `AskUserQuestion` 弹「继续」/「有疑问想先沟通」二选一;每次弹问前重扫一次,避免脏读放行。 |
| 86 | 71 | ||
| 87 | - 修复后重跑检查;通过 → 进入 2;3 轮仍失败 → 停下,打印最终残留差异 + 已尝试的 3 轮修复摘要让用户介入。 | 72 | +2. **docs/05 + docs/02 人工评审闸**(未确认不得勾选 A5):摘要展示 docs/05 全部端点(`METHOD PATH — REQ-ID`,标注「由 A5 自动推断」的项)+ docs/02 `req_order[]`(特别标 `note ≠ —` 的环依赖打破项)。`AskUserQuestion` 多问题表单同时问两项:「docs/05 端点/字段无误」+「docs/02 构建顺序可接受」,各二选一 `确认` / `需要修改`。任一需修改 → 收集修改点就地修订并重跑本闸,直到两项均 `确认`;否则禁止勾选 A5、禁止打印横幅。 |
| 88 | 73 | ||
| 89 | -2. **最终占位符扫描 + 结构性残留检查**(覆盖 Plan 阶段全部产出): | ||
| 90 | - | ||
| 91 | - a. **`TBD` → 自动补齐**:Grep 搜索 `TBD(A3 自动补)` 和 `TBD(A5 自动补)`。有命中则就地补填(A3 残留 → 查 docs/03 填 `依赖表`;A5 残留 → 查 docs/05 按 REQ-ID 填 `依赖接口`),再 Grep 确认 0 命中;仍残留报错停下。 | ||
| 92 | - | ||
| 93 | - b. **结构性残留检查(不只看字面占位符,校验 SSoT 完整性)**: | ||
| 94 | - | ||
| 95 | - - **docs/05 每个端点都有请求/响应 schema**:逐个解析 docs/05 的每个 endpoint 段(以 `### REQ-` 开头的小节)。每段必须同时含非空的 `- **请求**:` 与 `- **响应**:` 行——值不得为空、`TBD`、`—` 或 `【人工填写:…】`。缺失/留空 → 按步骤 B 规则就地为该端点推测补全请求/响应 schema,再复核;3 轮仍补不全则计入残留清单(见下方 c),交由 QA 循环让用户介入。 | ||
| 96 | - - **docs/02 DAG 覆盖每个 REQ**:收集 docs/01 全部 REQ-ID 集合,与 `docs/02 § 二、开发顺序清单` 表中出现的 `req_id` 集合比对。任一 docs/01 REQ 未出现在 docs/02 顺序清单 → 按步骤 A 子流程把该 REQ 插入其所属模块段的正确拓扑位置(保持同模块 REQ 连续),再复核;3 轮仍无法补齐则计入残留清单交由 QA 循环。 | ||
| 97 | - | ||
| 98 | - c. **`【人工填写:...】` + 结构性残留 → QA 循环等用户补**: | ||
| 99 | - | ||
| 100 | - 循环执行直到(搜索不到 `【人工填写:`)**且**(步骤 b 两项结构检查均通过)且用户选「继续」: | ||
| 101 | - - 0 残留 → 直接放行进入步骤 3 | ||
| 102 | - - 有残留 → 打印残留清单(含字面占位符 `<文件:行号> — <内容摘要>`,以及结构性缺口 `docs/05 端点 <REQ-ID> 缺请求/响应 schema` / `docs/02 顺序清单缺 REQ <REQ-ID>`),用 `AskUserQuestion` 弹「继续」/「有疑问想先沟通」二选一;用户回答后重扫 + 重跑结构检查再决定放行 / 继续循环 | ||
| 103 | - | ||
| 104 | - **每次弹 QA 前都重扫一次**(含两项结构检查)——保证用户看到的 N 是最新的,避免「用户以为填完但实际还有残留」直接放行。 | ||
| 105 | - | ||
| 106 | -3. **docs/05 + docs/02 人工评审闸(强制,未确认不得勾选 A5)**: | ||
| 107 | - | ||
| 108 | - 向用户摘要展示两份 SSoT 的关键内容,请其确认无误: | ||
| 109 | - - **docs/05 API 契约**:列出全部端点(`METHOD PATH — REQ-ID`),并标注任何「由 A5 自动推断」的端点/字段供重点核对。 | ||
| 110 | - - **docs/02 构建顺序**:展示 `req_order[]` 顺序,**特别标出所有 `note ≠ —` 的环依赖打破项**(启发式选定的顺序 + 原因),供用户判断该顺序是否可接受。 | ||
| 111 | - | ||
| 112 | - 用 `AskUserQuestion` 同时问两项确认(多问题表单),每项二选一: | ||
| 113 | - - 「docs/05 端点/字段确认无误」:`确认` / `需要修改` | ||
| 114 | - - 「docs/02 构建顺序可接受(含 cycle-breaking 选定的顺序)」:`确认` / `需要修改` | ||
| 115 | - | ||
| 116 | - 裁决: | ||
| 117 | - - 两项均 `确认` → 进入步骤 4 勾选 A5。 | ||
| 118 | - - 任一为 `需要修改` → 用 `AskUserQuestion` 收集具体修改点,就地修订对应文档(docs/05 端点/字段或 docs/02 顺序/备注),改完重新展示摘要并重跑本评审闸,直到两项均 `确认`。**未两项确认前禁止勾选 A5、禁止打印终止横幅。** | ||
| 119 | - | ||
| 120 | -4. 完成后,用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 A5 父项: | 74 | +3. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 A5 父项: |
| 121 | - `- [ ] A5 下游文档生成 — downstream-gen` | 75 | - `- [ ] A5 下游文档生成 — downstream-gen` |
| 122 | 76 | ||
| 123 | -5. 打印 A5 完成横幅并**停下**(A6 仍未跑——A5 之后由 plan-start 派发 A6 frontend-scope-lock,A6 完成后再由 plan-start 跑 5 项终结闸;只有终结闸全过才会提示运行 coding-start): | 77 | +4. 打印 A5 完成横幅并**停下**: |
| 124 | 78 | ||
| 125 | ``` | 79 | ``` |
| 126 | - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
| 127 | - [downstream-gen] ✅ A5 下游文档生成完成(A0~A5) | ||
| 128 | - | ||
| 129 | - docs/02 / docs/05 / docs/06 § 三 / docs/08 § 二 / docs/10 已就绪; | ||
| 130 | - docs/05 + docs/02 评审闸已通过;docs/08 § 一 A0~A5 已全勾。 | ||
| 131 | - | ||
| 132 | - ⏭️ 下一步:运行 /erp-workflow:plan-start | ||
| 133 | - plan-start 会派发到 A6 frontend-scope-lock 锁定前端 scope, | ||
| 134 | - A6 完成后再由 plan-start 跑 5 项终结闸校验; | ||
| 135 | - 全过才会提示运行 /erp-workflow:coding-start 进入 B 阶段。 | ||
| 136 | - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | 80 | + [downstream-gen] ✅ A5 下游文档生成完成(A0~A5) |
| 81 | + 产出:docs/02 / docs/05 / docs/06 § 三 / docs/08 § 二 / docs/10;docs/08 § 一 A0~A5 已全勾。 | ||
| 82 | + ⏭️ 下一步:运行 /erp-workflow:plan-start | ||
| 137 | ``` | 83 | ``` |
| 138 | 84 | ||
| 139 | ## 参考 | 85 | ## 参考 |
skills/plan/frontend-scope-lock/SKILL.md
| @@ -9,32 +9,10 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion | @@ -9,32 +9,10 @@ allowed-tools: Read Write Edit Glob Grep Skill AskUserQuestion | ||
| 9 | 9 | ||
| 10 | # frontend-scope-lock | 10 | # frontend-scope-lock |
| 11 | 11 | ||
| 12 | -A6 是 **Plan 阶段最后一个前端守门 skill**,由 `plan-start` 在 A5(downstream-gen)完成后派发。 | ||
| 13 | - | ||
| 14 | -**定位**:把原 Coding 阶段晚到的前端闸(`frontend-start` 的 prototype 检查 + `fe-feature-brainstorm` / `fe-feature-plan` 的交互式 Q&A)整体**前移到 Plan 期**。Plan 期允许 `AskUserQuestion` 问人;问清后写入 SSoT(docs/06 + docs/04),Coding 阶段的前端循环只读不问。 | ||
| 15 | - | ||
| 16 | -## 阶段范围 | ||
| 17 | - | ||
| 18 | -锁定**项目级**前端契约:UI 约定 / Design Tokens / 组件库选型 + 每个 FE-NN 的设计决策。**不涉及** SQL / migration / controller / service / DTO(后端范畴),也**不在此实现**任何页面代码(Coding 阶段做)。 | ||
| 19 | - | ||
| 20 | ## 执行步骤 | 12 | ## 执行步骤 |
| 21 | 13 | ||
| 22 | > **关于 AskUserQuestion**:下文只描述「问什么、给哪些选项、各选项导向什么后续」。`header` / 各选项的 `description` / `multiSelect` 等具体参数由你按工具 schema 自行填全合法值——不要把下文的选项文字当成完整调用照抄。 | 14 | > **关于 AskUserQuestion**:下文只描述「问什么、给哪些选项、各选项导向什么后续」。`header` / 各选项的 `description` / `multiSelect` 等具体参数由你按工具 schema 自行填全合法值——不要把下文的选项文字当成完整调用照抄。 |
| 23 | 15 | ||
| 24 | -### 步骤 0:打印当前位置流程图 | ||
| 25 | - | ||
| 26 | -向用户**直接输出**(模型自己打印,不调 bash / cat)当前位置: | ||
| 27 | - | ||
| 28 | -``` | ||
| 29 | -┌────────────────────────────────────────────────────────┐ | ||
| 30 | -│ 📋 阶段 A:规划(一次性) │ | ||
| 31 | -│ A0 初始化 → A1 锁范围 → A2 骨架 → A3 DB 设计 │ | ||
| 32 | -│ → A4 DB 初始化 → A5 下游文档 │ | ||
| 33 | -│ ▶ A6 前端范围锁定(prototype + tokens + 约定) │ | ||
| 34 | -│ 规划阶段到此结束 │ | ||
| 35 | -└────────────────────────────────────────────────────────┘ | ||
| 36 | -``` | ||
| 37 | - | ||
| 38 | ### 步骤 1:检查 prototype(缺失则在此问) | 16 | ### 步骤 1:检查 prototype(缺失则在此问) |
| 39 | 17 | ||
| 40 | 用 `Glob` 检查项目根 `prototype/**/*.html`: | 18 | 用 `Glob` 检查项目根 `prototype/**/*.html`: |
| @@ -42,11 +20,10 @@ A6 是 **Plan 阶段最后一个前端守门 skill**,由 `plan-start` 在 A5 | @@ -42,11 +20,10 @@ A6 是 **Plan 阶段最后一个前端守门 skill**,由 `plan-start` 在 A5 | ||
| 42 | - **至少 1 个 `.html`** → 通过,记下文件清单,进入步骤 2。 | 20 | - **至少 1 个 `.html`** → 通过,记下文件清单,进入步骤 2。 |
| 43 | - **0 个** → 这是 Plan 期,**可以问**。用 `AskUserQuestion` 告知用户「未在 prototype/ 找到任何 .html 原型,前端范围锁定依赖原型作为页面骨架权威」,给「我已补齐原型,请重新检查」和「本项目无前端,跳过 A6」两个选项。 | 21 | - **0 个** → 这是 Plan 期,**可以问**。用 `AskUserQuestion` 告知用户「未在 prototype/ 找到任何 .html 原型,前端范围锁定依赖原型作为页面骨架权威」,给「我已补齐原型,请重新检查」和「本项目无前端,跳过 A6」两个选项。 |
| 44 | - 选「已补齐」→ 重新 `Glob`:命中则进入步骤 2,仍为 0 则重复本问。 | 22 | - 选「已补齐」→ 重新 `Glob`:命中则进入步骤 2,仍为 0 则重复本问。 |
| 45 | - - 选「无前端」→ 在 docs/08 § 一 把 A6 的**父项 + 全部 3 个子项**一并勾选并在父项行尾注明「(无前端,A6 跳过)」,打印步骤 6 的终止横幅(产出标注「跳过」),**停止**,不写 docs/06 / docs/04。 | ||
| 46 | - > 必须同时勾子项:`plan-start` 的分发依据是「§ 一 第一个未勾 [ ] 子项」,若只勾父项会让下一次 plan-start 重复派发回本 skill,无前端项目无法满足 Plan 终结闸。具体要勾的子项: | ||
| 47 | - > - ` - [x] docs/06 项目级 UI 约定 + Design Tokens + 组件库已锁定(无前端跳过)` | ||
| 48 | - > - ` - [x] docs/04 § 二 前端栈已锁定(引用 docs/06)(无前端跳过)` | ||
| 49 | - > - ` - [x] 各 FE-NN 设计决策表已生成(docs/06 § 三之后 / docs/08 § 三)(无前端跳过)` | 23 | + - 选「无前端」→ 在 docs/08 § 一 同时勾父项 + 3 子项(否则下次 plan-start 会重派),父项行尾注「(无前端,A6 跳过)」,打印步骤 6 横幅(产出标注「跳过」)并**停止**,不写 docs/06 / docs/04。3 子项: |
| 24 | + - ` - [x] docs/06 项目级 UI 约定 + Design Tokens + 组件库已锁定(无前端跳过)` | ||
| 25 | + - ` - [x] docs/04 § 二 前端栈已锁定(引用 docs/06)(无前端跳过)` | ||
| 26 | + - ` - [x] 各 FE-NN 设计决策表已生成(docs/06 § 三之后 / docs/08 § 三)(无前端跳过)` | ||
| 50 | 27 | ||
| 51 | ### 步骤 2:收集证据(只读,不问) | 28 | ### 步骤 2:收集证据(只读,不问) |
| 52 | 29 | ||
| @@ -98,23 +75,12 @@ A6 是 **Plan 阶段最后一个前端守门 skill**,由 `plan-start` 在 A5 | @@ -98,23 +75,12 @@ A6 是 **Plan 阶段最后一个前端守门 skill**,由 `plan-start` 在 A5 | ||
| 98 | - ` - [ ] docs/04 § 二 前端栈已锁定(引用 docs/06)` | 75 | - ` - [ ] docs/04 § 二 前端栈已锁定(引用 docs/06)` |
| 99 | - ` - [ ] 各 FE-NN 设计决策表已生成(docs/06 § 三之后 / docs/08 § 三)` | 76 | - ` - [ ] 各 FE-NN 设计决策表已生成(docs/06 § 三之后 / docs/08 § 三)` |
| 100 | - `- [ ] A6 前端范围锁定 — frontend-scope-lock` | 77 | - `- [ ] A6 前端范围锁定 — frontend-scope-lock` |
| 101 | -2. 向用户**直接输出**终止横幅并**停止**(不自动进入 B 阶段,回交给 plan-start 的终结闸判定): | 78 | +2. 向用户**直接输出**终止横幅并**停止**: |
| 102 | 79 | ||
| 103 | ``` | 80 | ``` |
| 104 | -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
| 105 | - [frontend-scope-lock] ✅ A6 前端范围锁定完成 | ||
| 106 | - | ||
| 107 | - 产出: | ||
| 108 | - ✓ docs/06 § 一 项目级 UI 约定(通用交互规则) | ||
| 109 | - ✓ docs/06 § 二 Design Tokens(全局调色板 + 组件级状态色) | ||
| 110 | - ✓ docs/06 § 三之后 各 FE-NN 设计决策表 | ||
| 111 | - ✓ docs/04 § 二 前端栈 + 组件库选型(引用 docs/06) | ||
| 112 | - | ||
| 113 | - 前端契约已全部锁定,Coding 阶段前端循环将只读不问。 | ||
| 114 | - | ||
| 115 | - Plan 阶段(A0~A6)到此结束。请运行 /erp-workflow:plan-start | ||
| 116 | - 让终结闸校验全部前移闸门是否通过,再进入 B 阶段。 | ||
| 117 | -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | 81 | +[frontend-scope-lock] ✅ A6 前端范围锁定完成 |
| 82 | +产出:docs/06 § 一/二 + § 三之后各 FE-NN 决策表;docs/04 § 二 前端栈(引用 docs/06)。 | ||
| 83 | +Plan 阶段(A0~A6)到此结束。请运行 /erp-workflow:plan-start 进入终结闸。 | ||
| 118 | ``` | 84 | ``` |
| 119 | 85 | ||
| 120 | ## 参考 | 86 | ## 参考 |