--- name: erp-skeleton-gen description: A2 骨架生成——基于 docs/04 § 零 技术栈 + docs/01-需求清单/README.md 模块索引,生成项目专属的架构文档(docs/04 § 一+、docs/06、docs/07、docs/09)和工具脚本。固定工具文件走 cp,架构文档由 LLM 按大纲生成。 user-invocable: false allowed-tools: Read Write Edit Skill Grep Glob AskUserQuestion Bash(mkdir *) Bash(cp *) Bash(touch *) Bash(chmod *) Bash(git config *) Bash(cat *) Bash(bash *) --- **所有输出必须使用中文。** # erp-skeleton-gen ## 前置条件 本 skill 从 docs/08 进度推进而来。 **输入文件**: - `docs/04-技术规范.md § 零`:erp-scope-lock 写入的技术栈表。本 skill 基于它推导 § 一+ 编码规范、docs/07 依赖清单、docs/09 目录结构、scripts/test.sh 的构建/测试命令。 - `docs/01-需求清单/`:A1 已产出 README.md(模块索引表)+ 每模块一份 REQ 卡片(`-.md`,用户已审阅确认)。A2 只用其中的**模块 ID 列表**生成 docs/09 的后端/前端模块目录树(`module/user/` / `module/order/` 等),REQ 卡片详情不在本 skill 使用(留给 A4 回填 schema、A5 生成 API/验收清单)。 - `docs/08-模块任务管理.md`:末尾 Edit 勾选 A2 checkbox。 **产出覆盖提醒**: - 本 skill 会 `Write` 覆盖以下文件:docs/04(拼接 § 零 + § 一+)、docs/06、docs/07、docs/09、scripts/test.sh、scripts/setup-test-db.sh、.githooks/pre-push、.env.local。 - 如果之前运行过本 skill 且用户手动改过这些文件,**重新运行会覆盖修改**。 ## 执行步骤 ### 步骤 0:打印当前位置流程图 向用户展示当前在 A 阶段流程中的位置(A-only,`▶` 标在 A2): ``` ┌──────────────────────────────────────────────────────┐ │ 📋 阶段 A:规划(一次性) │ │ │ │ A0 初始化项目 → A1 锁范围(REQ 卡片) │ │ ↓ │ │ ⏸ 等你审阅 REQ,重新运行 /erp-plan-start 继续 │ │ ↓ │ │ ▶ A2 生成骨架 → A3 初始化 DB → A4 生成 DB 设计 → A5 生成下游文档│ │ ↓ │ │ 规划阶段到此结束 │ └──────────────────────────────────────────────────────┘ ``` ### A. 读取锁定的输入 用 `Read` 读取: - `docs/04-技术规范.md` § 零 技术栈表 - `docs/01-需求清单/README.md` 模块索引 这两份是本次生成的**唯一权威输入**,后续所有内容都基于它们推导。 ### B.1 生成 3 个全新架构文档(docs/06 / 07 / 09) 对下表每个目标文件: 1. 用 `Read` 读取对应的大纲模板(只含 section 标题 + HTML 注释形式的填写提示) 2. 基于步骤 A 的输入,按大纲生成项目专属内容 3. **剥掉所有 `` 注释**(注释是给 LLM 的提示,不应出现在最终文档里) 4. 用 `Write` 写入目标路径 | 目标文件 | 大纲模板 | |---|---| | `docs/06-UI交互规范.md`(写 § 一 ~ 四,§ 五 占位) | `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md` | | `docs/07-环境配置.md` | `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md` | | `docs/09-项目目录结构.md` | `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md` | 项目专属标识(根包名 / 命名空间)保留 `【人工填写:<说明>】` 占位,等人工在 docs/09 顶部补填一次后,其他文件复用。 ### B.2 追加 docs/04 § 一+(保留 § 零 不覆盖) docs/04 已由 erp-scope-lock 写入 § 零。本步骤追加 § 一 ~ 三。 1. 用 `Read` 读取 `docs/04-技术规范.md`(拿现有 § 零 完整内容)。 2. 用 `Read` 读取 `${CLAUDE_SKILL_DIR}/templates/docs-04-skeleton-template.md`(§ 一+ 大纲)。 3. 基于步骤 A 技术栈,按大纲生成 § 一 ~ 三 的项目专属内容,剥掉 HTML 注释。 4. 拼接 `<§ 零 原文>\n\n<新生成的 § 一+>` → 用 `Write` 写回 `docs/04-技术规范.md`。 ### C. 生成工具脚本 #### C.1 零槽位文件:纯 `cp` ```bash mkdir -p scripts .githooks sql/migrations touch sql/migrations/.gitkeep cp "${CLAUDE_SKILL_DIR}/templates/env-local-template" .env.local cp "${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh" .githooks/pre-push cp "${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh" scripts/setup-test-db.sh ``` 说明: - `sql/migrations/` 是 Flyway migration 目录。A3 `erp-db-init` 会在此生成 `V1__initial_schema.sql`,后续 B 阶段每个 REQ 的业务 DDL 也写在这(`V2__xxx.sql` / `V3__xxx.sql` ...) - `setup-test-db.sh` 只做 **drop + create 空库**,schema 由 **Flyway 在 Spring Boot 启动时自动应用** - **硬依赖**:项目 `pom.xml` 必须包含 `flyway-core` + `flyway-mysql` 依赖(已列入 docs/04 § 零 技术栈);否则 Spring 启动不会 apply migration,测试会因表不存在而失败 - seed 数据(`sql/seed-data.sql`)由 A3 `erp-db-init` 从本地 MySQL 导出,开发者选一种装载方式(Spring `@Sql` / Flyway `R__seed.sql` / `data.sql`);setup-test-db.sh 只负责清空库 #### C.2 `scripts/test.sh` —— 直接 Write 基于步骤 A 的技术栈推断 build / lint / unit+integration / e2e 四条命令,直接 `Write` 完整 `scripts/test.sh`。 骨架如下(CC 把 4 个 `<推断的 ... 命令>` 替换成实际值后 Write): ```bash #!/usr/bin/env bash # scripts/test.sh —— 合并到默认分支(main / master)前的唯一硬闸门。 # 顺序:setup-db → build → lint → unit+integration → e2e → reset-db # 由 .githooks/pre-push 和 erp-local-test-gate skill(通过子会话)调用。 set -euo pipefail PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$PROJECT_ROOT" echo "[test.sh] 1/6 setup test db" ./scripts/setup-test-db.sh echo "[test.sh] 2/6 build" <推断的 build 命令,如:(cd backend && mvn -DskipTests clean package) && (cd frontend && pnpm build)> echo "[test.sh] 3/6 lint" <推断的 lint 命令> echo "[test.sh] 4/6 unit + integration" <推断的 unit+integration 命令> echo "[test.sh] 5/6 E2E" <推断的 e2e 命令> echo "[test.sh] 6/6 reset test db" ./scripts/setup-test-db.sh echo "[test.sh] GREEN" ``` #### C.3 赋权 + 配置 git hooks ```bash chmod +x scripts/*.sh .githooks/pre-push git config core.hooksPath .githooks ``` ### D. 追加 .gitignore 忽略项 调用脚本完成合并: ```bash bash "${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh" "${CLAUDE_SKILL_DIR}/templates/gitignore-append-template" ``` 脚本行为: - 若项目根无 `.gitignore` → 直接 `cp` 整份模板 - 若已有 → 读模板每一行,跳过注释/空行,用 `grep -xF` 整行精确匹配判重(避免 `.env` 误匹配 `.env.local`、通配符 `*.iml` 被当正则),只追加缺失的规则 ### E. 占位符智能填充 + `.env.local` 独立提示 + QA 循环验证 目标:减少用户重复编辑。同一"逻辑占位"(如根包名出现多处)只问用户一次,CC 批量填;派生占位(如 Java 路径从根包名派生)由 CC 自己推断。敏感占位(`.env.local` 凭据 / 密钥)不进会话上下文,让用户自己去文件里填。 循环执行直到**两个条件同时满足**: (a) 所有占位符已填(重新扫描命中数 N = 0) (b) 用户选「继续」 #### E.1 扫描 + 分组 用 `Grep` 在以下 8 个路径下扫描 `【人工填写:`,记录每处命中(文件 + 行号 + 说明文字): - `docs/04-技术规范.md` - `docs/06-UI交互规范.md` - `docs/07-环境配置.md` - `docs/09-项目目录结构.md` - `scripts/*.sh` - `.githooks/pre-push` - `.gitignore` - `.env.local` 对每个命中提取 `【人工填写:<说明>】` 的 `<说明>`,**分两组**: - **敏感组**:`.env.local` 路径下的全部命中(密码 / 密钥 / 账号等)。**不**通过 `AskUserQuestion` 问——留给 E.4 提示用户手动编辑。 - **非敏感组**:其他文件的命中。按语义聚合成"逻辑占位": - **说明文字完全相同** → 同一个根占位(多处共用同一值),如"根包名"出现 3 次 - **说明表达派生关系** → 派生占位,派生自某根占位(如"后端 java 根包路径"派生自"根包名") - **无法归类** → 视作独立根占位单独问 若总 N=0(无任何占位)→ 直接跳 E.5 验证。 #### E.2 向用户询问非敏感"根占位" 对每个非派生根占位用 `AskUserQuestion` 询问: - **question**: `请输入 <说明>(将填充到 处)` - **options**(给**默认值候选 + 自由输入**,供用户快速选择;"Other" 由 CC 运行时自动提供,无需显式列): - `{"label": "<合理默认值>", "description": "示例默认值"}` - (可选)`{"label": "<第二个常见默认>", "description": "..."}` 示例(根包名): ``` question: "请输入 Java 根包名(将填充到 3 处)" options: - {"label": "com.example.erp", "description": "示例默认"} ``` - 用户选默认值 → 取该值 - 用户选 Other → 用户输入的字符串为该值 **派生占位不问用户**——由 CC 在 E.3 自行推断。 #### E.3 CC 批量 Edit 填充 1. 对每个根占位:遍历所有命中位置,用 `Edit` 把 `【人工填写:<说明>】` 替换为 E.2 用户输入的值。 2. 对每个派生占位:CC 基于说明文字 + 根占位值**自行推断**派生值,用 `Edit` 填入。例如: - 根 `根包名 = com.xly.erp` → 派生 `后端 java 根包路径 = backend/src/main/java/com/xly/erp/` - 根 `根包名 = com.xly.erp` → 派生 `测试 java 根包路径 = backend/src/test/java/com/xly/erp/` 3. 若 CC 对某派生占位无法可靠推断(说明不清 / 上下文不足),**回退**:把该占位当作独立根占位,弹 `AskUserQuestion` 问用户。 #### E.4 `.env.local` 敏感占位提示(不弹出 QA) 若敏感组非空,打印提示横幅(只打印,不问): ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [erp-skeleton-gen] ⚠️ 敏感占位需你亲自填 📄 文件: ./.env.local 待填字段( 个): <列出实际命中的字段名,如 DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_SCHEMA / JWT_SECRET> 这些是凭据 / 密钥,CC 不通过会话询问(避免写入聊天记录)。 请直接编辑 .env.local 填入实际值。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ``` #### E.5 验证 + QA 循环 1. 用 `Grep` **重新扫** `【人工填写:` 于所有 8 个路径,得新命中数 N 和残留清单。 2. 打印汇总横幅: ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [erp-skeleton-gen] 骨架生成完成,请审阅 📄 架构文档: ✓ docs/04-技术规范.md (§ 一 ~ 三) ✓ docs/06-UI交互规范.md (§ 一 ~ 四) ✓ docs/07-环境配置.md ✓ docs/09-项目目录结构.md 📄 工具文件: ✓ scripts/test.sh ✓ scripts/setup-test-db.sh ✓ .githooks/pre-push ✓ .env.local ✓ .gitignore(新建 / 追加 / 跳过) ✓ sql/migrations/.gitkeep 占位符状态: 0 时打印:⚠️ 还有 N 处待填: <文件:行号> — <行内容摘要> ...> 需要调整 → 直接编辑对应文件(尤其 .env.local 敏感字段) 填完后 → 选「继续」放行 A3 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ``` 3. 用 `AskUserQuestion` 询问: - **question**: `架构文档审阅 & 占位符补填完毕?` - **options**: - `{"label": "继续", "description": "进入 A3 数据库配置"}` - `{"label": "有疑问想先沟通", "description": "需要讨论或修改"}` 4. 路由: - 选「有疑问想先沟通」→ 回答用户问题后**回 E.5.1 重新扫描** - 选「继续」→ **回 E.5.1 重新扫描验证**: - 新 N = 0 → 进入步骤 F(放行 A3) - 新 N > 0 → 用户以为填完其实还有残留,回 E.5.2 打印新横幅并再次弹出 QA 关键点:**每次弹出 QA 前都重新扫描一次**,用户看到的 N 始终是最新的;只有 N = 0 且选「继续」才放行。 ### F. 勾选 docs/08 进度 + 进入 A3 1. 用 `Edit` 在 `docs/08-模块任务管理.md` 勾选 4 个 checkbox(A2 的 3 个子项 + A2 父项): - ` - [ ] 架构文档已生成(docs/04 § 一+、docs/06、docs/07、docs/09)` → `[x]` - ` - [ ] 工具脚本已生成(scripts/*.sh、.githooks/pre-push、.env.local)` → `[x]` - ` - [ ] .gitignore 已配置` → `[x]` - `- [ ] A2 骨架生成 — erp-skeleton-gen` → `[x]` 2. 输出 `skeleton-gen: 完成(docs/04 § 一+ / docs/06 / docs/07 / docs/09 + scripts/*.sh + .githooks/pre-push + .env.local + .gitignore)`。 3. 立即调用 `Skill(erp-db-init)` 进入 A3,不等用户手动输入。 ## 参考 - `docs/04-技术规范.md` § 零(技术栈输入) - `docs/01-需求清单/README.md`(模块索引输入) - `${CLAUDE_SKILL_DIR}/templates/docs-04-skeleton-template.md`(大纲) - `${CLAUDE_SKILL_DIR}/templates/docs-06-static-template.md`(大纲) - `${CLAUDE_SKILL_DIR}/templates/docs-07-env-template.md`(大纲) - `${CLAUDE_SKILL_DIR}/templates/docs-09-structure-template.md`(大纲) - `${CLAUDE_SKILL_DIR}/templates/scripts-setup-test-db-template.sh`(0 槽位) - `${CLAUDE_SKILL_DIR}/templates/githooks-pre-push-template.sh`(0 槽位) - `${CLAUDE_SKILL_DIR}/templates/env-local-template`(0 槽位) - `${CLAUDE_SKILL_DIR}/templates/gitignore-append-template`(0 槽位) - `${CLAUDE_SKILL_DIR}/scripts/merge-gitignore.sh`(.gitignore 逐行判重合并脚本)