--- name: code-review description: >- L2 特性级多维度代码审查。Feature 全部任务完成后执行。 用法:/code-review --base TRIGGER when: 用户运行 /code-review,或在 merge 前要求特性级代码审查。 --- # Skill: code-review ## 描述 L2 特性级多维度代码审查。Feature 全部任务完成后执行。 ## 触发 ``` /code-review --base 2.5.0-PM ``` --- ## 审查流程 1. 执行 `git diff 2.5.0-PM...HEAD --stat` 获取变更文件列表 2. 执行 `git diff 2.5.0-PM...HEAD` 获取完整 diff 3. 对照 Feature 的 `spec.md`、`design.md` 和 `tasks.md` 4. 按 7 维度逐一审查 5. 输出审查报告 --- ## 7 维度审查框架 ### 维度 1:边界条件 | 检查项 | 说明 | |--------|------| | null/None 处理 | 外部输入是否校验 None/空字符串 | | 空集合 | 列表/字典为空时是否正确处理(不抛异常) | | 数值边界 | 分页 page/size 合法性、ID 为 0/-1 | | 字符串长度 | 数据库字段长度限制是否在 API 层校验 | | 超时处理 | 外部调用(LLM/MCP/HTTP)是否设置超时 | | 分页溢出 | 请求超出总页数时返回空列表而非错误 | ### 维度 2:权限与认证 | 检查项 | 说明 | |--------|------| | 认证注入 | 需要认证的端点是否使用 `UserPayload = Depends(UserPayload.get_login_user)` | | 五级权限链路 | 是否遵循:super_admin → tenant 归属 → tenant admin → ReBAC → RBAC 菜单 | | PermissionService | 权限检查是否走 `PermissionService.check()` 而非直接查旧表 | | 资源授权 | 创建资源时是否调用 `PermissionService.authorize()` 写入 owner 元组 | | tenant_id 隔离 | 跨租户访问是否被阻止(SQLAlchemy event 自动注入) | | WebSocket 认证 | WS 端点是否使用 `UserPayload.get_login_user_from_ws` | ### 维度 3:并发安全 | 检查项 | 说明 | |--------|------| | OpenFGA 双写 | MySQL + OpenFGA 写入是否有失败补偿(failed_tuples 表) | | 数据库事务 | 多表写入是否在同一事务内 | | Celery 幂等 | 异步任务是否支持重试不产生副作用 | | 竞态条件 | 并发创建同名资源是否有唯一约束或乐观锁 | | 会话状态 | Redis 缓存读写是否考虑过期和并发更新 | ### 维度 4:信息泄漏 | 检查项 | 说明 | |--------|------| | 硬编码敏感信息 | 代码中无明文密码/密钥/token | | 错误信息 | 异常响应不暴露堆栈/SQL/内部路径 | | 日志脱敏 | logger 输出中敏感字段已脱敏 | | 前端暴露 | 前端代码不包含后端 IP/密钥/内部 API 路径 | | tenant_id 泄漏 | API 响应不向前端返回其他租户的 tenant_id | ### 维度 5:测试覆盖 | 检查项 | 说明 | |--------|------| | Service 测试 | 核心 Service 方法有单元测试(mock DAO) | | API 测试 | 新端点有集成测试(happy path + 主要 error path) | | AC 覆盖 | spec 中每条 AC 都有对应测试或手动验证 | | 错误路径 | 权限拒绝、参数校验失败等错误路径有测试 | | 测试质量 | mock 合理,不 mock 掉核心逻辑 | > **务实适配**:当前测试基础薄弱,降低阈值但要求核心 Service 方法必须有测试。 > 前端暂用手动验证替代(tasks.md 中有「手动验证」描述即可)。 ### 维度 6:代码风格 | 检查项 | 说明 | |--------|------| | DDD 分层 | 新代码在正确的层级(domain/services vs api/endpoints) | | 命名一致 | DAO/Service/错误码命名遵循项目约定 | | 代码重复 | 无复制粘贴式重复逻辑(应提取到 Service 或工具函数) | | 未使用代码 | 无 dead code、注释掉的代码块、空函数 | | 格式化 | Python 代码通过 ruff check(hook 自动处理) | ### 维度 7:文档同步(design.md 现状快照) > **目的**:确保 feature 合入后,新 agent 接手时读 design.md 能 5 分钟建立准确认知 —— 没有过期描述、没有缺失的反直觉坑、没有未声明的对外契约。 | 检查项 | 说明 | 严重度 | |--------|------|--------| | design.md 存在 | feature 目录下有 `design.md`(按 `features/_templates/design.md` 起的稿) | HIGH(缺失直接 NEEDS_FIX) | | 决策同步 | diff 中新增/替换的关键技术决策(数据格式、配对/匹配策略、同步 vs 异步、二进制依赖等)在 §3 方案对比有记录,且给出"何时该重新考虑" | HIGH | | 数据流/契约同步 | diff 触及 API 路径 / 请求响应字段 / 内部 Service 入参出参 / 数据库新表新字段 / 关键文件职责变化 → §4.1 数据流、§4.2 字段约定、§4.3 模块职责对应章节已更新 | HIGH | | 已知坑同步 | 修了一个"代码里看不出的"反直觉 bug(典型:上游字段格式不符合直觉、运行时值与文档不符、必须的兜底逻辑)→ §5 已知坑 表新增一行(带"如果不知道会怎样"+"在哪处理") | HIGH | | 契约/依赖同步 | 新增对外 endpoint / 新依赖 chat/knowledge/permission 等模块的隐式契约 / 新增系统二进制依赖 → §6 Outgoing / Incoming 已补 | HIGH | | 修订历史 | §修订历史 末尾追加了本次 feature 完成的条目(日期 + 改动 + 触发原因) | MEDIUM | | 与 spec 不冲突 | design.md 对当前实现的描述未与 spec.md AC 矛盾(spec 是不变目标,design 是当前实现,二者口径必须对齐) | HIGH | **判定要点**: - 若 design.md 与代码现状偏离 → 必须修复(视为 HIGH),不能合入 - 仅本地小修小补(不改变对外行为、不引入新坑、不动决策)→ 本维度全 PASS 即可 - design.md 不存在但已在 SDD 流程要求之内 → HIGH,要求按模板补全后再审 --- ## 判定规则 | 结果 | 条件 | 动作 | |------|------|------| | **PASS** | 无 HIGH 或 MEDIUM | 可合并 | | **PASS_WITH_WARNINGS** | 仅 MEDIUM 级 | 可合并,记录待改进 | | **NEEDS_FIX** | 有 HIGH 级 | 修复后重审(最多 2 轮) | --- ## 输出格式 ```markdown # Code Review Report **Feature**: **Review scope**: <描述> **Base branch**: 2.5.0-PM **Changed files**: <数量> ## Summary | Dimension | High | Medium | Low | Status | |-----------|------|--------|-----|--------| | Boundary Conditions | 0 | 0 | 0 | PASS | | Permission & Auth | 0 | 0 | 0 | PASS | | Concurrency Safety | 0 | 0 | 0 | PASS | | Information Leakage | 0 | 0 | 0 | PASS | | Test Coverage | 0 | 0 | 0 | PASS | | Code Style | 0 | 0 | 0 | PASS | | Docs Sync (design.md) | 0 | 0 | 0 | PASS | ## Findings(如有) ### HIGH - [Permission] `xxx_endpoint.py:42` — 缺少 PermissionService.check() 调用 ### MEDIUM - [Style] `xxx_service.py:18` — DAO 方法未使用 @classmethod ## Overall: PASS / PASS_WITH_WARNINGS / NEEDS_FIX ```