SKILL.md 14.3 KB

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 卡片(<code>-<name>.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

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):

#!/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

chmod +x scripts/*.sh .githooks/pre-push
git config core.hooksPath .githooks

D. 追加 .gitignore 忽略项

调用脚本完成合并:

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: 请输入 <说明>(将填充到 <N> 处)
  • 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
 待填字段(<N> 个):
   <列出实际命中的字段名,如 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

    占位符状态:
      <N=0 时打印:✅ 全部填完>
      <N>0 时打印:⚠️ 还有 N 处待填:
                   <文件:行号> — <行内容摘要>
                   ...>

    需要调整 → 直接编辑对应文件(尤其 .env.local 敏感字段)
    填完后   → 选「继续」放行 A3
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  1. AskUserQuestion 询问:

    • question: 架构文档审阅 & 占位符补填完毕?
    • options
      • {"label": "继续", "description": "进入 A3 数据库配置"}
      • {"label": "有疑问想先沟通", "description": "需要讨论或修改"}
  2. 路由:

    • 选「有疑问想先沟通」→ 回答用户问题后回 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. Editdocs/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 逐行判重合并脚本)