# Code Review Checklist

适用于本仓库的分层代码评审流程。目标是先看高返工成本层，再看表现层，避免 reviewer 一开始陷入 UI 或局部实现细节。

规则优先级：`docs/` > `AGENTS.md` / `CLAUDE.md` > skill。

---

## 两遍审查机制

对 diff 应用两遍审查：

### Pass 1 (CRITICAL) — 必须在 Pass 2 之前完成

| 类别 | 关注点 |
|------|--------|
| 数据安全 | Prisma 原始 SQL 注入、缺失事务、迁移破坏兼容性 |
| 竞态与并发 | 缺乏乐观锁/悲观锁的状态变更、并发写入未处理 |
| 枚举与值完整性 | 新增 enum/status/type 值未在所有引用点处理 |
| 契约冲突 | 文档 ↔ schema ↔ DTO ↔ 返回结构之间的不一致 |
| 鉴权缺失 | 新接口无 Guard、无权限校验、无组织隔离 |

### Pass 2 (INFORMATIONAL) — Pass 1 无阻断后执行

| 类别 | 关注点 |
|------|--------|
| 条件副作用 | if/else 分支中遗漏副作用（如只在 happy path 写日志） |
| 魔法数字/字符串耦合 | 硬编码状态码、路径、配置值 |
| 死代码与一致性 | 新增但未使用的导出、不一致的命名模式 |
| 测试缺口 | 新代码路径无对应测试 |
| 前端问题 | 未国际化文案、硬编码导航、绕过设计系统 |
| 文档过时 | 代码变更影响了文档描述但文档未更新 |

---

## 枚举与值完整性检查（跨 diff 检查）

**此类别必须读取 diff 之外的代码。** 当 diff 引入新的 enum 值、状态、类型常量时：

1. 用 Grep 找到所有引用同组值的文件
2. 读取这些文件，检查新值是否被处理
3. 特别关注 switch/case、条件分支、前端映射、i18n key

这是唯一需要超出 diff 范围检查的类别。

---

## 文档过时检查

交叉检查 diff 与文档文件：

1. 对 `docs/modules/{module}/` 下的每个 `.md` 文件，检查 diff 中的代码变更是否影响了文件描述的功能/组件
2. 如果文档**未更新**但其描述的代码**有变更**，标记为 INFORMATIONAL：
   `"文档可能过时: [file] 描述了 [功能/组件] 但代码在此分支有变更。"`
3. 同时检查 `CLAUDE.md`、`AGENTS.md` 中的入口信息是否仍准确

---

## Fix-First 机制

每个发现归类为 **AUTO-FIX** 或 **ASK**：

### 归类规则

| 情况 | 归类 |
|------|------|
| CRITICAL 且修复方式唯一、无歧义 | ASK（关键问题需确认） |
| CRITICAL 且修复涉及设计决策 | ASK |
| INFORMATIONAL 且修复机械化（加缺失导入、补遗漏 i18n key、删死代码） | AUTO-FIX |
| INFORMATIONAL 且修复涉及判断 | ASK |

### 执行流程

1. **AUTO-FIX 项**：直接修复。每项输出一行：`[AUTO-FIXED] [file:line] 问题 → 修复内容`
2. **ASK 项**：合并到一个提问中，逐项列出：
   - 编号、严重级别、问题描述、推荐修复
   - 每项选项：A) 修复 B) 跳过
   - 总体推荐
3. 如果 ASK 项不超过 3 个，可以逐个提问

**注意：** code-review 默认是只读审查。Fix-First 仅在用户明确要求"审查并修复"时启用。常规审查仍以输出评审意见为主。

---

## 评审顺序

1. 数据模型与迁移
2. API 契约
3. 后端业务与状态机
4. 前端契约消费
5. 权限、安全与组织隔离
6. 测试与文档

前一层存在阻断问题时，后一层只做轻量扫视，不深入样式、重构或低信号建议。

## 阻断级问题

- 文档、schema、DTO、返回结构之间存在明确冲突
- Prisma schema 缺失关键外键、唯一约束、组织隔离字段
- 状态机非法流转，或废弃状态仍在写入/查询
- 状态转换类 API 未返回完整资源对象
- 新接口缺鉴权/授权/数据范围限制
- 修改历史迁移，或绕过标准迁移流程
- API 变更未提供契约校验或集成验证依据
- 新增 enum/status 值未在相关 switch/case/前端映射中处理（枚举完整性）

## 关注级问题

- PR 包含 ≥ 2 个**无关主题**（commit message 一句话讲不清干啥）——**不是按规模判断**，单一主题的大 PR 接受。详见 CLAUDE.md § "PR 拆分准则"。
- PR 描述不符合 [`13-pr-description-spec.md`](../../../../docs/standards/13-pr-description-spec.md) 的「评审检查清单」（最高频违规：解决 issue 漏写 `Closes #N`、堆演进过程、含"我们/本 PR/AI"填充主语、PR push 新 commit 后 title + body 没 PATCH 跟上最终状态）
- 同一概念存在重复模型或重复事实源
- 前端出现大量兼容映射、兜底判断、临时转换
- 自由字符串字段本应收敛为 enum
- `deletedAt` 与唯一约束、`skipDuplicates` 组合存在隐患
- 缺测试报告、缺验证命令、缺文档同步
- 代码变更影响了文档描述但文档未同步更新

## 预检项

- PR 不是关闭、草稿或 WIP
- 相关模块事实源已经定位
- PR 描述按 [`13-pr-description-spec.md`](../../../../docs/standards/13-pr-description-spec.md)「评审检查清单」逐项核对（单一事实源，本 skill 不重复列项）
- 同时混改多层时按**主题**判断是否该拆：服务于同一个功能 / 同一个 bug 的"DB + 后端 + 前端 + 测试"是一个主题，**不拆**；不相关的两个功能塞在一起才拆。高风险路径（`prisma/schema/**` / `docs/standards/**` / `CLAUDE.md` / `AGENTS.md` / `.gitea/workflows/**`）即使主题相关也单独抽出 PR。

## 各层重点检查

### 1. 数据模型与迁移

- schema 是否符合模块文档和状态机
- 外键关联是否指向正确模型
- 唯一约束、索引、非空约束是否完整
- `organizationId`、租户或数据范围字段是否缺失
- JSON 字段是否掩盖了本应建模的关系
- 迁移是否向后兼容（零停机），是否有表锁风险

### 2. API 契约

- 请求 DTO 与前端请求参数是否一致
- controller 返回字段与前端 response interface 是否一致
- Decimal/Date/enum 是否稳定序列化
- 列表空态是否返回空结构
- 新增枚举值是否同步到前端类型定义和 i18n

### 3. 后端业务与状态机

- controller 是否只处理 HTTP
- service 是否校验前置条件、权限、幂等性
- 状态转换是否与 `04-state-machine.md` 一致
- 废弃枚举值是否仍在 set/query
- 并发状态变更是否有保护（乐观锁/事务）

### 4. 前端契约消费

- 页面是否直接消费正式契约
- 用户可见文案是否国际化
- 是否出现未文档化导航、结构或设计系统改动
- 是否用前端逻辑弥补后端建模缺陷
- 新增的后端枚举值在前端是否有对应映射/显示

### 5. 权限、安全与组织隔离

- 新接口是否补权限码和角色权限
- 是否能跨组织读写数据
- 是否暴露了不该下发的敏感字段
- 权限种子数据（roles.seed.ts）是否同步更新

### 6. 测试与文档

- API 变更是否先过 L0 再跑 L1
- 是否给出测试命令、报告或复现步骤
- 文档、skills、入口文件是否同步
- 新代码路径是否有对应测试覆盖

## 协作效率原则

- 小 PR 优先于大 PR；大 PR 即使方向正确，也应视为评审风险
- 功能改动与重构尽量拆开，不要混在一个评审单元中
- reviewer 优先快速给出方向性反馈，再深入细节，避免作者长时间阻塞

## 输出模板

输出摘要头：`评审结果: N 个问题 (X CRITICAL, Y INFORMATIONAL)`

1. Findings
- 阻断或高优先级问题，附文件和行号
- 标注来自 Pass 1 还是 Pass 2

2. Risks
- 非阻断，但上线风险高

3. Gaps
- 缺测试、缺文档、缺权限、缺契约校验
- 枚举完整性缺口（如有）
- 文档过时项（如有）

4. Verdict
- `block` / `needs-fix` / `pass-with-risk` / `pass`
