# CLAUDE.md — ERP项目 Claude Code 主指令文件

> 本文件是 Claude Code 的"操作手册"。Claude Code 启动时会自动读取此文件。

---

## 🎯 项目概述

- **项目名称**: 小羚羊
- **项目简述**: 测试ERP
- **目标用户**: 企业内部管理人员
- **部署方式**: 私有化部署

---

## 🔄 B 阶段开发流程（模块循环 + 功能循环）

两层嵌套循环**全部固化到 skills**。入口：`/erp-workflow:coding-start`。

- **模块循环（外）**：`module-start` → `test-gate` → `module-report` → `mr-create` → 人工 Approve MR → 下一模块
- **功能循环（内，每 REQ-XXX-NNN 一遍）**：`feature-brainstorm` → `feature-plan` → `feature-tdd` → `feature-verify` → `feature-review`

MR 前测试闸门： 
   - `test-gate`（子会话跑 `scripts/test.sh` 全量——本模块所有 REQ + 已完成模块回归）；
   - `.githooks/pre-push` 兜底
   - `git push --no-verify` 被 `deny-no-verify.sh` 硬拦。

---

## ✅ 模块完成判定规则

`docs/08-模块任务管理.md § 二` 是**模块元数据表**——每个模块记录依赖 / 路径 / MR iid / 功能（REQ）子项清单。**模块完成由 `MR:` 字段 + `GitLab API state=merged` 判定**；功能子项勾选只作可视化进度，不参与模块完成判定。

### 规则定义

每个模块在 docs/08 § 二 中长这样：

```markdown
- module_0 系统管理
  - 依赖: —
  - 路径: backend/module/sys/, frontend/pages/sys/
  - MR: —
  - 功能:
    - [ ] REQ-SYS-001 用户登录
    - [ ] REQ-SYS-002 用户注册
```

- `MR:` 字段由 `mr-create` 在创建 MR 时从 `—` 改为 `!<iid>`。
- 每个 `REQ-*` 子项由 `feature-review` 在 `verdict=approve` 时自动勾选为 `[x]`
- 子项全部勾选不等于模块完成，模块完成判定仍以 `MR:` + GitLab API state 为准。

### 模块状态语义

| `MR:` 字段 | `GitLab API state` | 含义 | 你（Claude Code）的行为 |
|---|---|---|---|
| `—` | — | 模块未开始（未创建 MR） | ✅ 开始本模块开发 |
| `!<iid>` | `opened` / `closed` | 模块开发中 / 打回 | ✅ 继续推进该模块 |
| `!<iid>` | `merged` | 模块**已完成** | 🟢 进入下一未完成模块 |

### 模块完成报告

由 `module-report` skill 产出，模板位于 由 module-report skill 持有（12 节标准化，含跨模块改动等 CLAUDE.md 软规则映射节）。CC 不手写模块报告，仅填模板。

---

## 🏷️ 占位符统一约定

项目文档里有 **2 种填写占位** + **1 种提示占位**：

| 格式 | 谁填 | 使用阶段 | 说明 |
|------|-----|---------|------|
| `【人工填写：<简短说明>】` | 人 | 仅 A 阶段文档 | 密钥 / 账密 / 包名 / 命名约定 / 小版本号等人工才能决定的值；B 阶段 plan/spec 禁止出现，查不到真值时用 `AskUserQuestion` 问用户 |
| `TBD(<责任人>)` | CC 自动 | A 或 B | 后缀附带责任方（如 `TBD(A3 自动补)` / `TBD(A5 自动补)`）；由对应 skill 就地补填，`module-report` § ⑦ 检查 `TBD(CC 补)` 残留 |

**HTML 注释 `<!-- ... -->`**：提示占位，是**插件内部大纲模板**里给 LLM 的**填空提示 / 章节引导**，指引 LLM 按结构填实际内容。skill 生成时会**剥除**这些注释，最终产物里注释不会保留。

---

## 📐 编码行为约束

### 你必须做的 ✅

1. **严格遵循** `docs/04-技术规范.md`——命名 / 编码 / 统一响应 / 异常处理 / 数据访问 / 配置与安全 等项目专属技术规约全部在此
2. **严格遵循** `docs/09-项目目录结构.md`——文件放对位置
3. **每个后端接口** 必须先在 `docs/05-API接口契约.md` 定义，再编码实现
4. **每个功能可追溯到 `REQ-XXX-NNN`**——commit tag + 代码注释（如 `// REQ-SYS-001: 用户登录`）+ plan/spec 文件名均用此 tag
5. **遇到跨模块改动**（动到非当前模块的代码）——按 § 🟡 软规则 **S2** 执行（允许改，但必须留痕）
6. **遇到技术栈外组件引入**（`docs/04 § 零` 技术栈表外的框架 / 中间件 / 关键库），按 § 🟡 软规则 **S1** 执行（允许引入，但必须先 AskUserQuestion）

### 你禁止做的 🚫

1. **主会话直接 `mysql -e` 跑业务 DDL**（只读查询 / 临时本地调试除外）——业务 schema 必须走 `sql/migrations/V_n__*.sql`，详见下方 Schema 演化规约
2. **手动 Edit `docs/08 § 二` 的 `MR:` 字段**，必须要由 `mr-create` 自动回写

### Schema 演化规约（Flyway migration）

1. **文件命名**：`sql/migrations/V<n>__<snake_case_desc>.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`），旧 `V_n.sql`
5. **临时调试 DDL**：临时在本地试字段/索引可手动 `mysql -e`，但不写 migration；下次 `setup-test-db.sh` 会 drop+create 清掉
6. **A4 生成的 V1**：`V1__initial_schema.sql` 是 A 阶段由 `db-init` 从 `docs/03-数据库设计文档.md`（A3 正向设计的 schema SSoT）翻译生成的初始版本；后续 V2/V3/... 由 B 阶段每个 REQ 按需写入，**同时**反向同步更新 docs/03 对应表小节以保持 SSoT 一致

---

## 🗂️ Git 提交规范

每次提交必须遵循以下格式：

```
<type>(<scope>): <subject>
```

- `scope`: 模块名，如 `user` / `inventory` / `order`
- `subject`: 简短描述；业务类（feat / fix / test）必须带 `REQ-XXX-NNN` 后缀

`type` 含义：

| type | 看到它意味着 |
|-----|-------------|
| `feat` | **新能力上线**——用户多了一个功能、接口、页面或业务规则 |
| `fix` | **修 bug**——原来行为错了，这次改对 |
| `refactor` | **重构**——外部行为不变，只改代码结构 / 命名 / 抽象 |
| `docs` | **文档改动**——只动 Markdown / 代码注释，不动实现 |
| `style` | **格式调整**——空白 / 缩进 / import 顺序，逻辑 0 变化 |
| `test` | **只动测试代码**——补用例 / 修 fixture，不碰实现 |
| `chore` | **流程维护**——构建 / 依赖 / 工具 / 证据档案 / MR 元数据等非业务动作 |

---

## 🚩 中断机制

功能循环（每个功能 REQ-XXX 的 Brainstorm → Plan → TDD → Verify → AI 自审）默认 **静默编程**，但触发以下任何一条必须**立刻停下、记录原因、等人决策**，不得自行绕过：

| # | 中断 | 例子 |
| - | --- | --- |
| 1 | **测试反复失败** | 同一测试同一功能内连续 **10 次**修复失败 |
| 2 | **要改密钥 / 账密 / 包名** | `docs/07-环境配置.md` 里由人工标注必须填的字段 |
| 3 | **外部接口不可达** | 第三方 API 无法连接、证书失效等环境问题，并无法自行解决 |

> 其余需要人类判断的场景一律走普通 `AskUserQuestion` Q&A，不中断、不写 Blocker 文件。

**触发中断时的固定动作：**

1. 在当前功能的 plan 文件里追加一节 `## 🚩 Blocker`（报告格式由 `interrupt-check` 的 `interrupt-block-template.md` 持有）
2. 停止后续所有功能的静默执行
3. 在主会话输出一句话摘要 + 指向 blocker 文件的路径，等人回复

---

## 🟡 软规则（允许继续，但有强制后续动作）

以下情况 **不触发中断**，CC 可自行继续推进，但必须在约定位置留痕，模块完成时统一审计。

| # | 软规则 | 允许动作 | 强制后续 |
| - | ----- | ------- | ------- |
| S1 | **技术栈外组件引入** | 用 `AskUserQuestion` 给用户三选一：接受引入 / 换方案 / 拒绝 | ① **接受** → 同会话直接在 `docs/04 § 零` 追加一行 → 继续流程 ② **换方案 / 拒绝** → 视为常规歧义澄清，继续 Q&A 收敛 ③ 不写 Blocker、不中断流程 |
| S2 | **跨模块改动** | **默认不改**，仅为当前模块实现所必需时允许修改 | ① hook `log-cross-module.sh` 自动落存根 ② `module-report` 一次性调用 `cross-module-log` skill 批量补齐「原因 / 影响评估」+ 「跨模块改动」节完整贴入《模块完成报告》 |

---

## 🧭 通用工作准则（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.
