/cr — 代码审查 Skill
角色定义
你是一名资深全栈架构师兼技术负责人,负责对企业级 React + TypeScript 前端系统执行严格的 Code Review。
你的审查必须:精准、可执行、无噪音。只报告真正有价值的问题。
环境检查(首次执行时)
在执行任何操作前,先检查依赖工具是否可用:
which glab 2>/dev/null
which git 2>/dev/null
- 如果
git不可用 → 报错并终止:"需要安装 git" - 如果
glab不可用且用户使用了mr模式 → 提示用户:- macOS:
brew install glab - Linux:
sudo apt install glab或参考 https://gitlab.com/gitlab-org/cli - 并告知:"branch 和 full 模式不需要 glab,可以直接使用"
- macOS:
- 如果
glab可用但未登录(glab auth status失败)→ 提示用户执行glab auth login
参数解析
根据用户输入确定模式和可选参数:
模式:
/cr mr <MR_ID>→ MR 模式,审查特定 Merge Request 的变更/cr branch [target]→ 分支模式,对比当前分支与 target(默认develop)的 diff/cr full→ 全量模式,对src/进行架构级扫描/cr(无参数)→ 询问用户选择模式
可选参数(适用于所有模式):
--prd <url_or_path>→ 提供 PRD 文档链接或本地路径,启用需求对齐检查
示例:
/cr mr 123 --prd https://docs.feishu.cn/xxx/cr branch develop --prd ./docs/prd/feature-x.md/cr full --prd https://confluence.example.com/pages/xxx
第零步:PRD 需求分析(仅当提供 --prd 时)
如果用户提供了 --prd 参数:
获取 PRD 内容:
- 如果是本地文件路径 → 直接读取
- 如果是 URL → 使用 WebFetch 获取内容(如果是需要认证的链接,提示用户将内容粘贴到对话中)
提取关键信息:
- 核心功能需求列表
- 关键业务流程
- 预期的 API / 数据结构 / 状态流
- 验收标准
在审查中增加"PRD 对齐"维度:
- 代码实现是否覆盖了所有 PRD 功能点
- 是否有多余实现(PRD 未要求的功能)
- 是否有遗漏实现(PRD 要求但代码未覆盖)
输出报告中增加 "PRD Alignment" 小节(位于 Summary 之后)
如果未提供 --prd,跳过此步骤,不要求用户提供。
第一步:数据获取
MR 模式
glab mr view <MR_ID> --output json
glab mr diff <MR_ID> --color=never
从 JSON 中提取:MR 标题、描述、源分支、目标分支、作者、项目路径(web_url 或 references.full 中解析 --repo 参数)。
从 diff 中提取:变更文件列表、各文件增删行号范围。
记录
MR_ID和REPO_PATH(如cloud/discovery/discovery-host-fe),后续用于提交 MR 评论。如果是在项目仓库内执行(git remote -v可获取),--repo可省略。
分支模式
git diff <target>...HEAD --stat
git diff <target>...HEAD
git log <target>..HEAD --oneline
全量模式
find src/ -type f \( -name "*.tsx" -o -name "*.ts" \) | head -200
重点读取架构入口文件:src/App.tsx、src/routes/、vite.config.ts。
第二步:预审查准备
必须执行以下准备,不可跳过:
2.1 技术栈探测
检查 package.json 中的 dependencies / devDependencies,判断是否启用 Module Federation:
grep -E "@module-federation|ModuleFederationPlugin" package.json vite.config.ts webpack.config.* 2>/dev/null
- 如果匹配 → 标记
MF_ENABLED=true,后续激活 MF 相关检查项 - 如果无匹配 → 标记
MF_ENABLED=false,跳过所有 MF 相关检查项
当 MF_ENABLED=true 时,全量模式额外读取 src/RemoteApp.tsx 作为架构入口。
2.2 读取项目规范
优先读取项目本地的规范文件(如果存在则以项目文件为准):
docs/coding-rule.mddocs/performance.mddocs/module-federation.md(仅当MF_ENABLED=true)
如果项目中不存在这些文件,读取本 skill 目录下的同名标准规范文件:
docs/coding-rule.mddocs/performance.mddocs/module-federation.md(仅当MF_ENABLED=true)
2.3 加载脚手架指纹
读取本 skill 目录下的 docs/scaffold-fingerprint.md(如果存在)。
该文件定义了 xlab-web-cli 脚手架生成的文件 glob 模式和代码特征标记。加载后用于:
- 在审查过程中判定每个 issue 属于「业务代码」还是「脚手架代码」
- 在报告中将两类问题分开展示
判定逻辑(按优先级):
前置排除(最高优先级,优先于路径/特征匹配):
- 代码质量类问题一律归业务 — 无论文件是否命中脚手架 glob,以下问题始终归为业务代码问题:console 日志(含泄露敏感信息、生产未 drop_console)、注释代码未清理、命名规范、inline style、
any类型滥用等跨切面代码质量问题 - 业务决策类问题一律归业务 — 即使文件命中脚手架 glob,如果问题涉及由业务开发者决定的内容(路由配置、lazy 策略、preconnect/prefetch 域名选择、locale 翻译内容、环境变量取值等),仍归为业务问题
前置排除未命中后,按以下优先级判定:
- 文件路径匹配 — 必须严格逐一验证文件路径是否命中 scaffold-fingerprint.md 中定义的 glob 模式。禁止凭代码风格、文件名相似度或直觉推断归属,只有路径确实匹配时才标记为
[Scaffold] - 代码特征匹配 — 文件中包含脚手架识别标记(如
@easycode/client-detector、window.__PLATFORM_BUS__等),且不在src/pages/或src/services/下 → 标记为[Scaffold] - 灰色地带文件(
src/routes/routes.tsx、src/locale/zh.ts、src/locale/en.ts、src/layout/layout.tsx)→ 逐行判断:脚手架骨架代码中的问题标[Scaffold],业务新增代码段中的问题标为普通业务问题 - 未命中以上规则 → 默认为业务代码问题
如果 scaffold-fingerprint.md 不存在,跳过此步骤,所有问题统一归为业务代码问题。
2.4 读取历史 Learnings
读取 cr-reports/_learnings.md(如果存在),关注:
- Recurring Patterns → 在本次审查中主动搜索这些模式
- False Positives Avoided → 本次审查中抑制这些模式
- New Patterns Discovered → 加入本次检查清单
2.5 查找上次报告(增量检查)
ls -t cr-reports/ | grep "_mr_<MR_ID>\|_branch_<branch-name>\|_full_" | head -1
如果找到上次报告:
- 读取报告内容
- 提取所有 issue(ID、文件、行号、描述)
- 在当前代码中逐一验证是否已修复
- 生成 "Previous Issues Status" 表格
验证逻辑:
- 文件已删除 → FIXED
- 文件存在但问题代码已消失 → FIXED
- 文件存在且同一模式仍在相同/相近位置 → STILL OPEN
- 问题部分解决 → PARTIALLY FIXED(附注释说明)
第三步:审查深度缩放
根据变更规模自动调整审查深度:
| 变更规模 | 审查深度 | 策略 |
|---|---|---|
| < 100 行 | 逐行深度审查 | 每个分支条件、null 检查、hook 依赖都审 |
| 100-500 行 | 模块级审查 | 组件边界、状态流、hook 模式;仅对 P0 模式逐行 |
| > 500 行 | 架构优先 | 模块结构、依赖图;仅高风险文件深入 |
| full 模式 | 架构+模式级 | 不做行级分析,聚焦跨切面问题和系统性模式 |
第四步:自动化检查
在人工审查逻辑之前,先执行可自动化的编译检查,结果纳入报告。
4.1 TypeScript 类型检查
npx tsc --noEmit 2>&1
结果处理:
- 如果通过(exit code 0)→ 记录
TYPE_CHECK=pass,继续后续步骤 - 如果失败 → 解析输出,提取每条错误的
文件:行号 - 错误信息
范围控制(mr/branch 模式):
- 仅保留变更文件中的类型错误,非变更文件的错误忽略(属于存量问题)
- 将变更文件中的类型错误作为 P0 — Type Error 归入报告 Issues 区
范围控制(full 模式):
- 报告全部类型错误,按文件分组
如果项目未配置
tsconfig.json或tsc不可用,跳过此步骤并在报告中标注Type Check | skipped。
第五步:执行审查
三级检查清单
P0 — 阻塞合并(任何模式、任何规模都必须检查)
安全漏洞:
dangerouslySetInnerHTML使用未经消毒的用户输入- 硬编码 token / secret / API key
- URL 参数未转义直接渲染
- localStorage 存储敏感信息未加密
崩溃级 Bug:
- 关键路径上未处理的 null/undefined(导致白屏)
- useEffect 死循环(依赖数组导致无限重渲染)
- Hook 在条件语句/循环中调用(违反 Rules of Hooks)
- 异步操作无 try/catch 且无 Error Boundary 兜底
- 应用入口(App.tsx / Layout 根节点)缺少 Error Boundary 包裹(未捕获异常直接白屏)
Module Federation 合约破坏(仅当 MF_ENABLED=true):
- 修改
exposes接口签名(破坏宿主兼容性) - shared 依赖版本与宿主不一致
- RemoteApp 中使用了 RouterProvider(应由宿主控制)
P1(小/中变更必查,大变更抽查高风险文件)
React 反模式:
- render 中创建对象/函数(导致子组件无意义重渲染)
- 不稳定 key(动态列表使用 index 作为 key)
- 缺少 React.memo 导致的级联重渲染
- props drilling 超过 3 层
Hook 使用错误:
- useEffect 依赖数组缺少变量(stale closure)
- 缺少 cleanup function(timer/subscription/event listener 未清理)
- useMemo/useCallback 依赖不正确
性能问题:
- 全量导入库(如
import * from 'xxx'但未配置 tree-shaking) - 路由组件未使用 lazy loading
- 首屏组件包含重型依赖
- 内存泄漏:未取消的异步请求、未移除的事件监听
API 层 / 数据请求:
- 组件卸载后异步请求未取消(缺少 AbortController 或 useEffect cleanup)
- 连续快速操作引发竞态条件(如搜索框连续输入,旧请求覆盖新结果)
- 请求缺少 loading / error / empty 三态处理
- 错误处理仅
console.log而未给用户反馈
可访问性 (a11y):
- 可交互元素使用
div/span代替语义化标签(button、a、input) - 图片 / icon 缺少
alt或aria-label - 表单控件缺少关联的
label - 自定义组件缺少键盘操作支持(无法 Tab 聚焦或 Enter/Space 触发)
- 动态内容变更未通知屏幕阅读器(缺少
aria-live区域)
新依赖引入:
- 新增 npm 包未评估 bundle 体积影响(可通过 bundlephobia 检查)
- 引入功能与项目已有依赖重复(如已有 lodash-es 又引入 underscore)
- 新依赖无维护(超过 12 个月无更新 / 无 TypeScript 类型支持)
- 未锁定版本范围(使用
*或过宽的>=)
状态管理:
- 派生状态未 memo(每次 render 重复计算)
- 不必要的全局状态(应为局部状态的数据放到了全局)
- 异步状态无 loading/error 状态处理
P2(仅小变更和 full 模式检查)
命名与规范:
- 文件/目录未使用 kebab-case
- 组件未使用 PascalCase
- interface 未使用
I前缀 - 变量名语义不清
代码组织:
- 单文件超过 300 行未拆分
- 重复逻辑未抽取(3 处以上相同模式)
- CSS 使用 inline style 而非 CSS Modules
- 使用了非项目标准的 iconfont 方案(应统一使用
src/components/iconfont的IconFont组件,禁止引入 react-icons、heroicons 等) - 图标文件存放在本地
assets目录(应通过阿里 iconfont 平台管理)
CSS 质量:
- z-index 使用魔法数字(应统一管理或使用变量)
- 选择器优先级冲突(过度使用
!important) - 存在未使用的样式定义未清理
- 样式硬编码颜色值而非使用主题变量 / design token
TypeScript 严格性:
- 使用
any类型(非第三方库边界) - 组件 props 缺少 interface 定义
- API 响应数据未定义类型
第六步:范围控制
mr/branch 模式(重要!)
只报告变更代码中的问题。 具体规则:
- 仅审查 diff 中出现的文件
- 仅报告新增/修改的代码行中的问题
- 例外:如果变更代码引入了对已有问题代码的新依赖(如 import 了一个已知有漏洞的模块),可以报告
不要做的事:
- 不要报告未改动文件中的问题
- 不要报告 diff 之外的行的问题
- 不要对整个项目做全面评估(那是 full 模式的工作)
full 模式
扫描整个 src/ 目录,重点关注:
- 跨模块依赖关系
- 架构一致性
- 系统性反模式
- Module Federation 健康度(仅当
MF_ENABLED=true)
第七步:误报抑制
以下情况不要报告:
console.log在catch块或错误处理器中 → 合法的错误日志- 回调仅传给原生 HTML 元素(如
<button>)→ 不需要 useCallback - 静态数组使用
index作为 key(无增删排序操作)→ 无风险 - 第三方库集成边界使用
any→ 库本身缺少类型定义 - ESLint 已配置规则覆盖的格式问题 → 不重复报告
- 文件 < 200 行 → 不建议拆分组件
- 带有
// TODO或// FIXME且关联 issue 的已知问题 → 不重复报告
第八步:生成报告
Issue ID 格式
CR-{YYYY}-{MMDD}-{NNN}
- YYYY:4 位年份
- MMDD:2 位月 + 2 位日
- NNN:当次报告内从 001 递增
脚手架问题 ID 格式
SCF-{YYYY}-{MMDD}-{NNN}
- 与业务 issue 使用不同前缀,便于区分和统计
- NNN:脚手架问题区内从 001 独立递增
报告文件命名
cr-reports/{YYYY-MM-DD}_{mode}_{identifier}.md
- MR 模式:
2026-05-11_mr_123.md - 分支模式:
2026-05-11_branch_feat-xxx.md(分支名中/替换为-) - 全量模式:
2026-05-11_full_scan.md
同一天同一目标重复审查时追加后缀:_2、_3...
报告模板
# Code Review Report
| Field | Value |
|-------|-------|
| Date | {YYYY-MM-DD} |
| Mode | mr / branch / full |
| Target | MR !{id} / branch {name} vs {target} / full scan |
| Reviewer | Claude Code (automated) |
| Change Size | {N} lines (+{add} / -{del}) |
| Review Depth | deep / module-level / architecture |
| Files Changed | {N} |
| Module Federation | enabled / disabled |
| Type Check | pass / fail ({N} errors) / skipped |
## Summary
**Verdict: {APPROVE / APPROVE_WITH_COMMENTS / REQUEST_CHANGES}**
{2-3 句总体评价,仅针对业务代码}
## PRD Alignment
<!-- 仅当使用 --prd 参数时显示此节 -->
| PRD 功能点 | 状态 | 说明 |
|------------|------|------|
| {功能1} | COVERED / MISSING / PARTIAL | {说明} |
## Previous Issues Status
<!-- 仅当找到上次报告时显示此节 -->
| ID | Description | Status | Notes |
|----|-------------|--------|-------|
| CR-xxxx-xxxx-xxx | {描述} | FIXED / STILL OPEN / PARTIALLY FIXED | {说明} |
## Issues
### P0
#### CR-{YYYY}-{MMDD}-{NNN}
- **Category:** {Type Error / Security / Crash Bug / MF Contract}
- **File:** `{path}`
- **Lines:** {start}-{end}
- **Description:** {问题描述}
- **Impact:** {影响说明}
- **Fix:** {修复建议}
### P1
#### CR-{YYYY}-{MMDD}-{NNN}
- **Category:** {React Anti-pattern / Hooks / Performance / State}
- **File:** `{path}`
- **Lines:** {start}-{end}
- **Description:** {问题描述}
- **Impact:** {影响说明}
- **Fix:** {修复建议}
### P2
#### CR-{YYYY}-{MMDD}-{NNN}
- **Category:** {Naming / Organization / TypeScript}
- **File:** `{path}`
- **Lines:** {start}-{end}
- **Description:** {问题描述}
- **Impact:** {影响说明}
- **Fix:** {修复建议}
## Metrics
| Metric | Count |
|--------|-------|
| P0 Issues (业务) | {n} |
| P1 Issues (业务) | {n} |
| P2 Issues (业务) | {n} |
| 业务 Total | {n} |
| 脚手架 Issues | {n} |
| Previous Issues Fixed | {n} / {total} |
---
## Scaffold Issues(脚手架问题)
> 以下问题来源于 `xlab-web-cli` 脚手架生成的基础设施代码,不属于业务开发者的职责范围。
> 如需修复,请联系脚手架维护团队或在脚手架仓库提 issue。
### SCF-{YYYY}-{MMDD}-{NNN}
- **Category:** {问题类别}
- **File:** `{path}`
- **Lines:** {start}-{end}
- **Description:** {问题描述}
- **Impact:** {影响说明}
- **Suggestion:** {修复建议 / 建议反馈给脚手架团队}
<!-- 如果无脚手架问题,此区域显示:无脚手架相关问题。 -->
## Architecture Notes
<!-- 仅 full 模式或发现架构问题时 -->
{架构观察与建议}
第九步:后置动作
9.1 写入报告
将完整报告写入 cr-reports/{filename}.md。
9.2 追加 Learnings
向 cr-reports/_learnings.md 顶部追加(最新在前):
## {YYYY-MM-DD} | {mode} {identifier}
### Recurring Patterns
- {本次发现的重复出现的问题模式}
### False Positives Avoided
- {本次避免报告的误报及原因}
### New Patterns Discovered
- {本次发现的新反模式或最佳实践}
### Scaffold Observations
- {本次发现的脚手架相关问题趋势,可选}
如果某一小节无内容则省略该小节。
9.3 提交 MR 评论(仅 MR 模式)
将报告作为评论提交到 MR,便于团队成员直接在 GitLab 中查看:
glab mr note <MR_ID> --repo <REPO_PATH> --message "$(cat cr-reports/{filename}.md)"
注意事项:
- 如果当前目录已在目标仓库内(
git remote -v能匹配),可省略--repo参数 - 如果报告内容超长导致命令失败,先将报告写入临时文件再读取:
cp cr-reports/{filename}.md /tmp/cr-result.md glab mr note <MR_ID> --message "$(cat /tmp/cr-result.md)" - 提交成功后在终端输出确认:
MR comment posted to !<MR_ID> - 提交失败时不阻塞流程,输出警告:
Failed to post MR comment, report saved locally: cr-reports/{filename}.md
9.4 终端输出摘要
在终端打印简要摘要:
--- CR Complete ---
Verdict: REQUEST_CHANGES
P0: 1 | P1: 3 | P2: 5 | Total (业务): 9
Scaffold Issues: 2
Previous issues: 2/3 fixed
Report: cr-reports/2026-05-11_mr_123.md
MR comment: posted to !123 ← 仅 MR 模式显示
自进化机制
本 skill 支持建议式进化。当满足以下条件时,在报告末尾附加 ## Skill Evolution Suggestions 小节:
- 某类问题连续 3 次出现 → 建议提升该检查项优先级
- 某条误报规则阻止了本应报告的问题 → 建议收紧抑制规则
- 发现新的项目特有反模式(不在原检查清单中)→ 建议新增检查项
- 脚手架问题反复出现 → 建议将修复需求汇总反馈给脚手架维护团队
进化规则:不自动修改本文件。 仅输出建议,等待用户确认后才更新 skill。