# CLAUDE.md — ERP项目 Claude Code 主指令文件 > 本文件是 Claude Code 的"操作手册"。Claude Code 启动时会自动读取此文件。 --- ## 🎯 项目概述 - **项目名称**: 【人工填写:公司 + 项目名,例如"XX 公司 ERP 管理系统"】 - **项目简述**: 【人工填写:一句话描述项目目标,例如"面向中小制造企业的全流程 ERP,涵盖采购/库存/生产/销售/财务"】 - **目标用户**: 【人工填写:谁会用,例如"企业内部管理人员(采购员、仓管员、生产主管、销售员、财务人员、管理层)"】 - **部署方式**: 【人工填写:私有化部署 / 云部署 / Docker 容器化 等】 --- ## ✅ 模块完成判定规则 `docs/08-模块任务管理.md § 二` 是**模块元数据表**——每个模块一行 bullet,记录依赖 / 路径 / MR iid。**模块完成由 `MR:` 字段 + `GitLab API state=merged` 判定**。 ### 规则定义 每个模块在 docs/08 § 二 中长这样: ```markdown - module_0 系统管理 - 依赖: — - 路径: backend/module/sys/, frontend/pages/sys/ - MR: — ``` `MR:` 字段由 `erp-mr-create` 在创建 MR 时从 `—` 改为 `!`。 ### 模块状态语义 | `MR:` 字段 | `GitLab API state` | 含义 | 你(Claude Code)的行为 | |---|---|---|---| | `—` | — | 模块未开始(未创建 MR) | ✅ 开始本模块开发 | | `!` | `opened` / `closed` | 模块开发中 / 打回 | ✅ 继续推进该模块 | | `!` | `merged` | 模块**已完成** | 🟢 进入下一未完成模块 | ### 工作流规则 - **开发顺序权威在 `docs/02-开发计划.md § 二 开发顺序清单`**,不是 `docs/08 § 二` 的物理行序 - **下一个要做的模块** = `docs/02 § 二` 清单中**第一个所属模块 MR 状态非 merged 的 REQ** 的 `module_id`(由 `erp-coding-start` 步骤 3 扫描 `docs/08` 的 `MR:` 字段 + GitLab API state 判定) - `docs/02 § 二` 清单由 A5 `erp-downstream-gen` 生成阶段一次性确定(会交互询问业务偏好),之后通常不改;若开发中途需要调整顺序,重新触发 A5 生成阶段而非直接编辑文件 - **已完成模块**(`MR: !` + `GitLab API state=merged`):**默认不改**(不是禁止,是已交付无需改) - 如果在当前模块开发中发现某个**已完成模块**(MR merged)有 bug: - **不停下当前工作**,按软规则 S2 直接修复该模块代码;hook `log-cross-module.sh` 会自动留痕,调用 `erp-cross-module-log` 补「原因 / 影响评估」 - 修复随当前模块 MR 一起合并——不需要改 `docs/08`(模块已是 merged 状态,本插件不会标记重开;修复是以"当前模块依赖他的代码"的方式进入) - 在当前模块的《模块完成报告》第 ⑦ 节「跨模块改动」明确记录:哪个模块、哪个文件、什么问题、修复范围、影响评估 ### 模块完成流程 ``` 1. 对每个 REQ 跑完整功能循环: brainstorm → plan → TDD(红绿循环,每步 commit)→ verify(子会话执行 REQ 级测试)→ 自审 2. 所有 REQ 完成后,erp-local-test-gate 派子会话按顺序跑: a. schema 一致性检查(erp-local-test-gate 步骤 1 内联,schema 未漂移)+ 占位符扫描 b. scripts/test.sh 全套:build → lint → **unit + integration(全量重新运行当前模块所有 REQ 的功能测试 + 所有已完成模块的回归测试)** → e2e 任一失败停下修复再来 3. 测试全绿 → erp-module-report 输出《模块完成报告》 4. 自动 git push(.githooks/pre-push 会再执行一遍 scripts/test.sh 作为硬闸门) + 通过 GitLab API (curl) 创建 MR,报告嵌入 MR 描述 5. 人工 review MR → Approve + Merge(人工动作,唯一人工介入点) 6. 下次用户运行 `/erp-workflow:erp-coding-start` 时,入口自动检测到本模块 `GitLab API state=merged`,探测默认分支(main / master)后 `git checkout <默认分支> && git pull --ff-only` 同步远程 → 扫描下一模块并派发 7. 你**不需要**手工 Edit docs/08(模块元数据不变;下次 coding-start 自动扫描 MR state 判定是否完成) ``` > 两道测试闸门:功能级(`erp-feature-tdd` + `erp-feature-verify`,每 REQ 一遍)+ 模块级(`erp-local-test-gate` + pre-push hook,每模块一遍)。所有测试/验证都派发到子会话执行,主会话只接收结构化结论。 ### 模块完成报告 由 `erp-module-report` skill 产出,模板位于 由 erp-module-report skill 持有(12 节标准化,含跨模块改动等 CLAUDE.md 软规则映射节)。CC 不手写模块报告,仅填模板。 --- ## 🏷️ 占位符统一约定(`【人工填写:...】`) 所有"只有人工能决定"的位置(密钥 / 账密 / 包名 / 命名约定 / 小版本号 等)一律使用以下纯文本标记: ``` 【人工填写:<简短说明>】 ``` ### CC 行为规则 - **生成文档 / 模板时**:凡是项目专属值、敏感值、技术栈小版本号一律用此标记,不要自行编造 - **不要用 HTML 注释**(``),因为后者在 Obsidian 渲染视图被隐藏,开发者会漏填 - **必须带简短说明**:例如 `【人工填写:JWT 签名密钥,256+ bit 随机串】`,而不是空 `【人工填写】` - **项目专属标识**(Java 根包名 / C# 命名空间 / Python 顶层模块等)只在 `docs/07-环境配置.md` 引入一次占位,其他文件**复用**已有的占位,不重复创建 --- ## 🔄 开发流程(模块循环 + 功能循环) 两层嵌套循环的详细步骤**全部固化到 skills**,CLAUDE.md 不展开。入口调 `/erp-workflow:erp-coding-start`,自动分发: - **模块循环(外层,Layer 2)** → `erp-module-start` → `erp-local-test-gate`(commit test-gate.md)→ `erp-module-report`(commit 模块报告 + cross-module log)→ `erp-mr-create`(worktree clean 校验 → push → 创建 MR → 追加 MR URL 到报告并 commit → 写 `MR: !` 到 docs/08 并 commit → 再次 push)→ 人工 Approve+Merge → 下次运行 `/erp-workflow:erp-coding-start` 扫描到本模块 GitLab API `state=merged` → 探测默认分支并 `git pull --ff-only` → 推进下一模块 - **功能循环(内层,Layer 3,每个 REQ-XXX-NNN 走一遍)** → `erp-feature-brainstorm` → `erp-feature-plan` → `erp-feature-tdd` → `erp-feature-verify` → `erp-feature-review` **本地测试闸门**: `erp-local-test-gate` 是 MR 前的唯一硬闸门,子会话执行 `scripts/test.sh`:脚本先由 `setup-test-db.sh` 清空库 → build / lint → 执行测试(Spring Boot 启动时 Flyway 自动 apply `sql/migrations/V*.sql`)→ e2e → 再次清库。详见 § 🧪 自测要求。`.githooks/pre-push` 在 push 时会再次执行 `scripts/test.sh` 作为兜底;`git push --no-verify` 被 hook `deny-no-verify.sh` 硬拦截。本项目不配置 GitLab CI/CD。 > 占位符扫描 / schema 一致性校验都不在此闸门:前者在 A 阶段 skill 生成期完成;schema 演化通过 Flyway migration 保证一致(每次测试启动,Spring Boot 的 Flyway 从空库按序 apply V1~Vn,不存在"漂移"概念)。hook 产生的 `TBD(CC 补)` 存根由 CC 自主调 `erp-cross-module-log` 补齐,并在 `erp-module-report` § ⑦ 硬验收(非人工填写)。 --- ## 📐 编码行为约束 ### 你必须做的 ✅ 1. **严格遵循** `docs/04-技术规范.md` 中的命名和编码规范 2. **严格遵循** `docs/09-项目目录结构.md` 中的目录规范,文件放对位置 3. **每个后端接口** 必须先在 `docs/05-API接口契约.md` 中定义,再编码实现 4. **每个功能** 必须可追溯到 `docs/01-需求清单.md` 中的需求编号 5. **代码注释** 必须包含对应的需求编号,如 `// REQ-001: 用户登录` 6. **数据库 schema 走 migration**:所有业务 schema 改动(CREATE/ALTER/DROP TABLE/INDEX/VIEW)必须写成 `sql/migrations/V_n__.sql` 文件,由 Flyway 顺序 apply;**禁止**在主会话直接 `mysql -e` 跑业务 DDL(只读查询 / 临时本地调试探索除外)。详见 § Schema 演化规约 7. **提交代码前** 确保无编译错误、无明显运行时错误 8. **每个Controller方法** 必须有统一的响应格式包装 9. **异常处理** 使用全局异常处理器,不在业务代码中catch后吞掉异常 10. **分页查询** 统一使用 MyBatis-Plus 的 Page 对象 ### 你禁止做的 🚫 1. **默认禁止** 修改"非当前模块"(其他 REQ 所属模块)的代码;确为实现当前模块所必需时,按软规则 S2 执行(留痕 + 模块报告单列说明) 2. **禁止** 引入`docs/04-技术规范.md` 技术栈表以外的框架或中间件(如需要必须先报告) 3. **禁止** 硬编码配置(数据库连接、端口号等必须放在配置文件中) 4. **禁止** 在前端直接写SQL或直接操作数据库 5. **禁止** 跳过模块开发(必须按顺序) 6. **禁止** 删除或覆盖他人代码(如有冲突必须报告) 7. **禁止** 使用 `SELECT *`,必须显式列出需要的字段 8. **禁止** 在循环中执行数据库查询(N+1问题) 9. **禁止** 前端存储敏感信息到 localStorage 10. **禁止** 返回后端异常堆栈给前端 ### Schema 演化规约(Flyway migration) 1. **文件命名**:`sql/migrations/V__.sql`,例:`V5__add_user_email_unique_index.sql` 2. **版本号分配**:建文件前 `ls sql/migrations/V*.sql` 查当前最大 n,新文件 `n_max + 1` 3. **Apply 方式**:Spring Boot 启动 / 测试启动时 Flyway 自动 apply(项目必须在 `pom.xml` 声明 `flyway-core` + `flyway-mysql` 依赖)。`scripts/setup-test-db.sh` 只负责清空库,不做 apply 4. **已合并的 migration 永不修改**:发现错了写一个补救 migration(如 `V7__fix_V5_index_name.sql`),绝不编辑 git 历史里的旧 `V_n.sql` 5. **临时调试 DDL ≠ 业务 DDL**:临时在本地试字段/索引可手动 `mysql -e`,但不写 migration;下次 `setup-test-db.sh` 会 drop+create 清掉 6. **A3 生成的 V1**:`V1__initial_schema.sql` 是 A 阶段由 `erp-db-init` 从人工初始化的 schema 导出的初始版本;后续 V2/V3/... 由 B 阶段每个 REQ 按需写入 --- ## 🔄 统一响应格式 所有后端接口必须返回以下格式: ```json { "code": 200, "message": "操作成功", "data": {}, "timestamp": 1700000000000 } ``` 错误响应: ```json { "code": 40001, "message": "用户名或密码错误", "data": null, "timestamp": 1700000000000 } ``` 错误码规范: | 错误码范围 | 含义 | |-----------|------| | 200 | 成功 | | 400xx | 客户端参数错误 | | 401xx | 认证/授权错误 | | 403xx | 权限不足 | | 404xx | 资源不存在 | | 500xx | 服务端内部错误 | --- ## 🗂️ Git 提交规范 每次提交必须遵循以下格式: ``` (): type: feat|fix|refactor|docs|style|test|chore scope: 模块名,如 user, inventory, order subject: 简短描述,中文可 示例: feat(user): 实现用户登录接口 REQ-001 fix(order): 修复订单金额计算精度问题 refactor(common): 统一响应格式包装 ``` --- ## 🧪 自测要求 - 所有测试与验证(`scripts/test.sh` / `mvn test` / `pnpm test` / DB 测试集 diff 等)**一律派发到全新子会话 via `Agent` 执行**,主会话只接收结构化结论(命令 / 退出码 / 通过数 / 失败项 / 关键 stdout ≤30 行)。不在主会话直接执行测试。 - 由 `erp-feature-verify`(功能级)+ `erp-local-test-gate`(模块级)两道 skill 统一承接。前者每个 REQ 执行一次,后者模块闸门执行一次。 - 声称"完成"前必须贴出子会话返回的 evidence(模板:由 erp-feature-verify skill 持有)。 --- ## 🚩 静默执行红旗清单(中断机制) 功能循环(每个功能 REQ-XXX 的 Brainstorm → Plan → TDD → Verify → AI 自审)默认 **静默跑不打扰人**,但命中以下任何一条必须**立刻停下、记录原因、等人决策**,不得自行绕过: | # | 红旗 | 例子 | | - | --- | --- | | 1 | **测试反复失败** | 同一测试同一功能内连续 **10 次**修复失败 | | 2 | **要改密钥 / 账密 / 包名** | `docs/07-环境配置.md` 里由人工标注必须填的字段 | | 3 | **外部接口不可达** | 第三方 API 无法连接、证书失效等环境问题 | > 其余需要人类判断的场景(需求歧义 / schema 缺口 / 技术栈外组件引入)一律走普通 `AskUserQuestion` Q&A,不升格为红旗、不写 Blocker 文件。见下方「📘 技术栈外组件的处理规则」与各 feature-* skill 的 Q&A 流程。 **命中红旗时的固定动作:** 1. 在当前功能的 plan 文件里追加一节 `## 🚩 Blocker`,描述红旗编号、现象、初步判断 2. 停止后续所有功能的静默执行 3. 在主会话输出一句话摘要 + 指向 blocker 文件的路径,等人回复 **报告格式:** ```markdown ## ⚠️ 需要人工决策 **红旗编号**: [1–3 中的某一条] **问题描述**: [详细描述] **影响范围**: [影响哪些模块 / 功能] **我的建议**: [初步判断,可选] **等待决策**: [需要人工做什么决定] ``` --- ## 📘 技术栈外组件的处理规则 brainstorm / plan 阶段若发现需要 `docs/04-技术规范.md § 零` 技术栈表之外的框架、中间件或关键库: 1. 用 `AskUserQuestion` 询问用户(选项至少含:接受引入 / 换方案 / 拒绝) 2. **接受** → 同会话直接在 `docs/04 § 零` 追加一行 → 继续流程 3. **换方案 / 拒绝** → 视为常规歧义澄清,继续 Q&A 收敛 不写 Blocker 文件,不中断流程。 --- ## 🟡 软规则(允许继续,但有强制后续动作) 以下情况 **不触发中断**,CC 可自行继续推进,但必须在约定位置留痕,模块完成时统一审计。漏留痕 = 红旗。 | # | 软规则 | 允许动作 | 强制后续 | | - | ----- | ------- | ------- | | S2 | **跨模块改动**(动到非当前模块的代码——无论该模块是否已 MR merged) | 允许修改,但范围受限:仅为当前模块实现所必需 | ① 当次修改立即追加到 `docs/superpowers/module-reports/-cross-module.md`(含文件路径、改动原因、对目标模块功能/API 的影响评估)② 《模块完成报告》必须单列「跨模块改动」节完整贴入 ③ 漏留痕或未评估影响 → 升级为红旗 | --- ## 🧭 通用工作准则(General Principles) ### 1. Think Before Coding **Don't assume. Don't hide confusion. Surface tradeoffs.** Before implementing: - State your assumptions explicitly. If uncertain, ask. - If multiple interpretations exist, present them - don't pick silently. - If a simpler approach exists, say so. Push back when warranted. - If something is unclear, stop. Name what's confusing. Ask. ### 2. Simplicity First **Minimum code that solves the problem. Nothing speculative.** - No features beyond what was asked. - No abstractions for single-use code. - No "flexibility" or "configurability" that wasn't requested. - No error handling for impossible scenarios. - If you write 200 lines and it could be 50, rewrite it. Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. ### 3. Surgical Changes **Touch only what you must. Clean up only your own mess.** When editing existing code: - Don't "improve" adjacent code, comments, or formatting. - Don't refactor things that aren't broken. - Match existing style, even if you'd do it differently. - If you notice unrelated dead code, mention it - don't delete it. When your changes create orphans: - Remove imports/variables/functions that YOUR changes made unused. - Don't remove pre-existing dead code unless asked. The test: Every changed line should trace directly to the user's request. ### 4. Goal-Driven Execution **Define success criteria. Loop until verified.** Transform tasks into verifiable goals: - "Add validation" → "Write tests for invalid inputs, then make them pass" - "Fix the bug" → "Write a test that reproduces it, then make it pass" - "Refactor X" → "Ensure tests pass before and after" For multi-step tasks, state a brief plan: ``` 1. [Step] → verify: [check] 2. [Step] → verify: [check] 3. [Step] → verify: [check] ``` Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. --- ## ⚡ Skill & 模板入口索引 CC 会话启动请直接调 **`/erp-plan-start`** —— 顶层编排器会自动探测当前阶段(计划 / 模块循环 / 功能循环 / blocker)并分发到下一个 skill。 ### Skills(20 个,详细动作见各 `SKILL.md` 正文) | Layer | Skill | |---|---| | **0 入口** | `erp-plan-start` / `erp-project-init` | | **1 计划阶段** | `erp-scope-lock` / `erp-skeleton-gen` / `erp-db-init` / `erp-db-design-gen` / `erp-downstream-gen` | | **2 模块循环(外)** | `erp-module-start` / `erp-local-test-gate` / `erp-module-report` / `erp-mr-create` | | **3 功能循环(内)** | `erp-feature-brainstorm` / `erp-feature-plan` / `erp-feature-tdd` / `erp-feature-verify` / `erp-feature-review` | | **4 横切守门** | `erp-red-flag-check` / `erp-cross-module-log`(软规则 S2) | ### Hooks(3 个,由插件 `hooks/hooks.json` + `hooks/scripts/*.sh` 提供) - `deny-no-verify.sh` — 拒 `git push --no-verify` - `log-cross-module.sh` — 跨模块改动自动留痕(S2) ### 模板(分散在各 skill 的 插件 `skills/erp-*/templates/*`) 每个生成文件都对应一个模板(设计原则 #5)。模板保持纯净(原则 #6),帮助文本由 skill 通过 `AskUserQuestion` 交互引导。模板按"谁用谁拥有"原则分散到各自的 skill 目录下,便于打包成 plugin。一份共享模板(`cross-module-log-template.md`)在 `erp-module-start` 与 `erp-cross-module-log` 中各有一份副本。