@eldenring/ai-review
v0.4.7
Published
接入阿里云 Codeup 的 AI 代码审查机器人
Maintainers
Readme
AIReview
双轨 AI 代码助手:本地 CLI(可选深审 + 变更初稿)+ Codeup MR Webhook(强制 L2 变更说明)。
产品约定(何时审查、MR 文档优先、知识库放
docs/changes/):见 docs/PRODUCT.md。审查引擎已统一为 DeepSeek(本地/CI/MR 同一引擎,本地不再需要 Cursor)。想把审查升级为合并硬卡点(审出高风险则合并按钮锁死):见 docs/流水线卡点配置.md。
本地(可选) git diff → DeepSeek 审查(读盘补上下文)→ .ai-review/{分支}/审查发现.* → 可挡 push
MR(必经) Codeup MR → Webhook → L2 变更说明 + L1 索引 → MR 评论(不挡合并)
CI 卡点(可选)Flow 流水线 → ai-review --deep --fail-on high → 高风险则挡合并
定稿(合并前) MR 文档誊写 → docs/changes/ → 更新 docs/INDEX.md装什么
| 角色 | 需要安装 | 说明 |
|------|----------|------|
| 业务开发者 | Node.js 22+、pnpm、@eldenring/ai-review、DEEPSEEK_API_KEY | 在业务项目根目录跑本地审查;cwd 决定审哪个 Git 仓库 |
| Webhook 运维 | Node.js 22+、pnpm、本仓库源码 | 部署审查服务,接入 Codeup MR 事件 |
| 贡献本仓库 | 同上 + 开发依赖 | pnpm install 后用 pnpm ai:review / pnpm dev |
# 业务项目:全局安装 CLI(推荐)
pnpm add -g @eldenring/ai-review
# 或临时运行
pnpm dlx @eldenring/ai-review --help
# Webhook 服务 / 本仓开发
git clone <repo> && cd AIReview && pnpm install
pnpm build && pnpm start # 生产
pnpm dev # 开发(热重载)配什么
本地 CLI(业务项目 .env,勿提交)
本地审查引擎已统一为 DeepSeek,业务项目根目录 .env 只需一个变量:
DEEPSEEK_API_KEY= # DeepSeek 平台获取(必填)
# DEEPSEEK_BASE_URL= # 可选,默认 https://api.deepseek.com
# DEEPSEEK_MODEL= # 可选,默认 deepseek-chatWebhook 服务(部署机 .env,启动时校验)
复制 .env.example 为 .env,填写 服务端段(完整项见 .env.example):
| 变量 | 必填 | 默认 | 说明 |
|------|------|------|------|
| CODEUP_ACCESS_TOKEN | 是 | — | 云效个人访问令牌 |
| CODEUP_ORGANIZATION_ID | 是 | — | 云效组织 ID |
| DEEPSEEK_API_KEY | 是 | — | MR L2 文档与审查引擎 |
| PORT | 否 | 3000 | 服务端口 |
| LOG_LEVEL | 否 | info | 日志级别 |
| MR_DOC_ENABLED | 否 | true | 是否生成 L2 变更说明(建议保持开启) |
| MR_REVIEW_MODE | 否 | multi | MR 审查:none(仅文档)/ multi / single |
| REVIEW_ONLY_ON_PUSH | 否 | true | update 事件仅在 push 新代码时触发 |
| REVIEW_DEBOUNCE_SECONDS | 否 | 30 | 同一 MR 防抖间隔(秒) |
| DOC_SYNC_ENABLED | 否 | false | 是否将 L2 全文 commit 回源分支 docs/ai/mr-{id}/ |
| DOC_SYNC_ROOT | 否 | docs/ai | 文档回写根目录 |
| DOCS_AGENT_ENABLED | 否 | true | MR 合并时自动归档 L2 到 docs/changes/ 并更新 INDEX.md |
| DOCS_CHANGES_ROOT | 否 | docs/changes | 知识库目录 |
| WEBHOOK_SECRET | 否 | — | 签名校验(预留) |
CLI 与 Webhook 引擎统一为 DeepSeek。DeepSeek 读不了整库,本地/CI 审查时从磁盘读取变更文件全文 + 其 import 的关联文件补上下文。本地不跑 review 不影响 MR 出文档。
MR 产出什么
每个 MR(open / reopen / update 且 push)触发 Webhook,异步写入 一条 MR 评论(不阻断合并)。
处理流程
获取 MR diff
→ 无文本变更:评论说明跳过
→ 有变更:
1. L2 变更说明(优先复用 MR 内 背景和影响.md,否则 DeepSeek 生成)
2. L1 变更索引(文件数、模块、Top 文件)
3. 知识库归档提示
4. 文档回写状态(DOC_SYNC)
5. 双轨统一视图(本地/MR 审查与文档状态)
6. 审查结果(仅 MR_REVIEW_MODE≠none)MR 评论结构
# 🤖 AI Review
## 变更说明 ← L2(必有,对齐 docs/templates/change-note.md)
## 变更索引 ← L1 文件统计附录
## 知识库归档提示 ← 合并前誊写 docs/changes/ + 更新 INDEX
> 文档回写: … ← DOC_SYNC 状态
## 双轨统一视图 ← 本地审查 / L2 来源 / MR 审查 一览
## 审查结果 ← 仅 MR_REVIEW_MODE≠none 时出现
## 知识库归档结果 ← 仅归档失败时追加(合并事件)稳定性增强(L2 质量门槛 / 归档可观测性 / 幂等)
| 能力 | 行为 |
|------|------|
| L2 质量门槛 | L2 生成后校验必含章节(背景、改动范围、核心实现、对整体影响、验证方式);不达标在「变更说明」下追加「⚠️ 需人工补全」,不中断归档 |
| 归档可观测性 | 归档返回结构化 status(success/failed/skipped)+ reason(no_l2/parse_failed/commit_failed/already_archived/disabled/deduped);失败时在 MR 评论追加「## 知识库归档结果」可见提示 |
| 幂等去重 | INDEX 条目写隐藏标记 <!-- ai-mr:{id} ai-l2:{指纹} -->;重复合并 / 重试按「文件名 / MR / 指纹」任一命中即跳过,失败提示按标记替换而非重复堆叠 |
L2 来源优先级
| 优先级 | 条件 | 行为 |
|--------|------|------|
| 1 | MR diff 含 背景和影响.md | 直接复用(本地 ai-review --deep --doc 初稿) |
| 2 | MR_DOC_ENABLED=true | DeepSeek 按 change-note 结构生成 |
| 失败 | JSON 解析失败等 | L2 区显示失败提示,L1 索引仍附录,不导致 Webhook 整体失败 |
MR 审查双链路(MR_REVIEW_MODE=multi 默认)
| 情况 | 行为 |
|------|------|
| MR 含 审查发现.json 且 diffFingerprint 与 MR 一致 | 贴本地结论,跳过 MR DeepSeek 审查 |
| 无 json 或指纹不一致 | 执行 multi / single MR 审查 |
| MR_REVIEW_MODE=none | 仅出文档,不调审查 |
正式知识库 vs 过程产物
| 路径 | 进 Git? | 说明 |
|------|----------|------|
| MR 评论中的 L2 | 否(评论内) | 合并前人工誊写到 docs/changes/ |
| docs/changes/*.md | ✅ | 正式知识库 |
| .ai-review/{分支}/审查发现.* | ❌ | 本地过程产物(默认目录,可用 AI_REVIEW_OUTPUT_DIR 改) |
| .ai-review/{分支}/背景和影响.md | ❌ | 本地初稿;纳入 MR 可被 local-bridge 复用 |
| docs/ai/mr-*/ | 视配置 | DOC_SYNC_ENABLED=true 时回写;合并后建议删除 |
快速开始(CLI)
在业务项目根目录执行:
ai-review --deep- 退出码
0:门禁通过,可以 push - 退出码
1:门禁未通过,或审查/解析失败
变更说明初稿(可选,可被 MR local-bridge 复用):
ai-review --deep --doc # → .ai-review/{分支}/背景和影响.mdCLI 用法
命令总览
| 命令 | 说明 |
|------|------|
| ai-review --deep | 运行 AI 审查(必填 --deep) |
| ai-review annotate list | 列出所有问题及编号 |
| ai-review annotate --index N --as <状态> | 命令行标注(可选) |
| ai-review --help | 审查帮助 |
| ai-review annotate --help | 标注帮助 |
审查参数
| 参数 | 默认值 | 说明 |
|------|--------|------|
| --deep | — | 必填。调用 AI 引擎(DeepSeek)审查 |
| --fail-on <级别> | high | 门禁拦截级别,见下文 |
| --base <分支> | master | diff 对比基准分支 |
| --scope <范围> | auto | 审查范围:branch / staged / working / head;默认自动选 staged > working > branch |
| --path <路径> | 全仓库 | 仅审查指定路径下的变更 |
| --file <路径> | — | 仅审查单文件(快速审) |
| --name <名称> | 当前分支名 | 覆盖 .ai-review/ 下的报告文件夹名 |
| --doc | 关闭 | 额外生成 背景和影响.md(适合 MR 定稿归档) |
| --force | 关闭 | 全量重审(重新调用 AI 引擎);保留 md/json 中的人工标注 |
| --recheck | — | 与默认行为相同;已有报告且 commit 变化时自动增量复检 |
| -h / --help | — | 显示帮助 |
常用示例
# 标准 push 前审查
ai-review --deep
# 默认智能范围(无需记忆 --scope):
# staged 优先,其次 working,最后回退 branch
ai-review --deep
# commit 前最后一眼(仅 staged)
ai-review --deep --scope staged
# 审查工作区未提交改动
ai-review --deep --scope working
# 最近一次 commit 粒度
ai-review --deep --scope head
# 单文件快速审(工作区)
ai-review --deep --scope working --file src/api/user.ts
# 对比 main 分支
ai-review --deep --base main
# 只审查 src/api 目录
ai-review --deep --path src/api
# 全量重审(忽略缓存与旧报告)
ai-review --deep --force
# 审查 + 生成变更说明文档
ai-review --deep --doc
# 更严格的门禁(公共 medium 也拦截)
ai-review --deep --fail-on medium运行中交互
- 审查过程支持流式输出(TTY 下可见进度)
- 按 Ctrl+C 可中断审查
审查报告
报告固定写入:
.ai-review/{分支名}/
├── 审查发现.md # 人类可读报告
├── 审查发现.json # 结构化缓存(门禁与增量复检的数据源)
└── 背景和影响.md # 仅 --doc 时生成同分支多次审查会覆盖更新同一目录(不再按 commit 分子目录)。
知识库与 Git 提交
正式工程知识库在 docs/changes/(每需求一篇,纳入 Git)。本地审查报告是过程产物,请勿提交:
| 路径 | 进 Git? |
|------|--------|
| docs/changes/*.md | ✅ 正式知识库 |
| .ai-review/{分支}/审查发现.md | ❌ |
| .ai-review/{分支}/审查发现.json | ❌ |
| .ai-review/{分支}/背景和影响.md | ❌ 本地初稿,定稿后写入 changes/ |
.gitignore 已排除上述过程产物。合并前请将 --doc 初稿誊写为 docs/changes/YYYY-MM-DD-需求名.md 并更新 docs/INDEX.md。详见 docs/MR_DOC_FIRST.md 与 docs/WORKFLOW.md。
报告结构说明
审查发现.md 大致分为:
- 概览 — 门禁结论、进度、风险分布(一张表)
- 公共与系统影响 — 门禁判定的主要依据
- 待处理 — 按公共/局部分组,位置可点击跳转代码
- 已修复 — 增量复检时相对上次已消失的问题
- 已标注 — 人工确认可忽略的项,不参与门禁
每条问题格式简洁:可点击位置 + 严重度 + 描述,建议以引用块展示。标注说明在文档末尾。
门禁规则
审查策略为两条线并行:
| 类型 | scope | 行为 |
|------|-------|------|
| 公共/系统 | shared | 重点关注,高严重度可阻断 push |
| 局部功能 | local | 全面排查,列出问题但默认不单独阻断 |
--fail-on 拦截级别
| 值 | 行为 |
|----|------|
| high(默认) | systemImpact.overallRisk=high,或 shared + high finding → 拦截 |
| medium | 上述 + overallRisk=medium 或 shared medium → 拦截 |
| any | 任意公共影响或任意 finding → 拦截 |
| none | 永不拦截(仅生成报告) |
local 级问题无论 severity 多高,在默认
fail-on=high下不单独阻断 push。
缓存与增量复检
| 场景 | 行为 |
|------|------|
| 同 commit 再次运行 | 跳过模型调用,直接使用已有报告(会先同步 md 标注) |
| 新 commit + 已有报告 | 自动增量复检:核对旧问题 + 扫描新 diff |
| --force | 全量重审(重新调用 AI 引擎);保留人工标注,不需重新标注 |
增量复检时会:
- 保留人工标注(同文件同行或相同问题描述)
- 将已修复项写入「已修复」节
- 已标注项不会再次参与门禁
人工标注(推荐:在 Markdown 里写)
推荐直接在 审查发现.md 里标注,比命令行更方便。保存后,下次运行 ai-review --deep 会自动从 md 同步到 json。
写法
在对应问题下方加一行(与「建议」同级缩进):
- `src/foo.ts:42` `[局部]` — **某问题描述**
- 建议: 改成 xxx
- @wontfix 设计如此,不需要改支持的关键词
| 关键词 | 含义 | 别名 |
|--------|------|------|
| @wontfix | 不需要修改 | @nofix、@skip |
| @fp | 误报 | @false_positive |
| @deferred | 延后处理 | @later |
| @accepted | 已知风险可接受 | @accept |
| @open | 恢复为待处理 | — |
也支持中文标签:@不需要修改、@误报、@延后处理、@已知风险可接受。
标注示例
- @fp 测试数据,不是真漏洞
- @wontfix 与上游约定保持一致
- @accepted 已知性能问题,下版本优化
- @deferred 等需求确认后再改
- @open同步成功后,条目会移到「已标注」分区;终端会提示:已从 审查发现.md 同步 N 条标注。
标注注意事项
@行必须写在对应问题块下面,系统按`文件:行号`匹配- 仅改 md 里普通文字备注不会生效,必须用
@关键词格式 审查发现.json是机器数据源;md 标注会自动写回 json- 已标注项不参与门禁,增量复检时也不会重复拦截
命令行标注(可选)
不习惯改 md 时,可用 annotate 子命令,效果与 md 标注相同。
# 列出编号
ai-review annotate list
# 按编号标注
ai-review annotate --index 2 --as wontfix --reason "设计如此"
# 按文件定位
ai-review annotate --file src/a.ts --line 10 --as false_positive
# 恢复为待处理
ai-review annotate --index 1 --as open--as 可选值
| 值 | 含义 |
|----|------|
| wontfix | 不需要修改 |
| false_positive | 误报 |
| deferred | 延后处理 |
| accepted | 已知风险可接受 |
| open | 恢复为待处理 |
使用注意事项
- MR 必经、本地可选 — 每个 MR 自动出 L2 变更说明;本地
ai-review在提 MR / push 前、动公共模块时再跑。详见 docs/PRODUCT.md。 - 默认 scope 自动选择 — 不传
--scope时:staged→working→branch;整分支审查用--scope branch。 --deep必填 — 不带--deep只会打印帮助,不会执行审查。- 基准分支要存在 — 默认对比
master,仓库若无该分支请用--base指定(如main)。 - 同提交不重复调模型 — 同一 commit 重复运行会直接读缓存;改完 md 标注后重新运行即可同步,无需
--force。 - 需要彻底重审时再用
--force— 会重新调用 AI 引擎;你在 md/json 里的@标注会自动保留,不必重标。 - 局部问题不挡 push(默认) — 默认
fail-on=high只拦公共高风险;若希望更严,用--fail-on medium或any。 - 标注请用
@关键词— 在 md 里写普通备注不会被识别;annotate命令与 md 标注二选一即可。 - 审查报告勿提交 Git —
.ai-review/{分支}/审查发现.*为过程产物;正式知识库见docs/changes/。 .env不要提交 — 尤其DEEPSEEK_API_KEY、Codeup 密钥。- 解析失败视为未通过 — 本地审查模型未按 JSON 格式返回时,门禁不通过,可查看报告内「原始输出」或
--force重试。 - MR 不挡合并 — Webhook 只写评论;合并前将 L2 誊写到
docs/changes/并更新docs/INDEX.md。
环境变量参考
完整示例见 .env.example。上文 配什么 已列出 Webhook 关键项;下表为 CLI 补充。
本地 CLI
| 变量 | 必填 | 说明 |
|------|------|------|
| DEEPSEEK_API_KEY | 是 | DeepSeek API Key(本地审查引擎) |
| DEEPSEEK_BASE_URL | 否 | 默认 https://api.deepseek.com |
| DEEPSEEK_MODEL | 否 | 模型 ID,默认 deepseek-chat |
| AI_REVIEW_PROJECT_ID | 否 | CI 门禁拉 MR 评论豁免用(见 流水线卡点配置) |
| AI_REVIEW_MR_ID | 否 | 同上 |
Webhook 服务(可选)
启动 pnpm dev / pnpm start 时,除上表 Webhook 变量外,还需 CODEUP_* 与 DEEPSEEK_*(见 配什么)。
Webhook 服务部署
除本地 CLI 外,部署本仓库可接入 Codeup MR 自动文档与审查:
Codeup MR 事件 → POST /webhook/codeup → 异步 L2 + 可选审查 → 回写 MR 评论pnpm dev # 开发模式
pnpm build && pnpm start # 生产模式- 健康检查:
GET /health - Webhook:
POST /webhook/codeup - 收到 MR 事件后异步处理,立即返回
202 - 产出结构见上文 MR 产出什么
Codeup 侧配置 Webhook URL 指向 https://<host>/webhook/codeup,事件勾选合并请求相关动作。
开发脚本
本仓库内开发(无需全局安装):
pnpm install
pnpm ai:review --deep # 本地 CLI(tsx 直跑源码)
pnpm dev # Webhook 服务开发模式
pnpm build # 编译
pnpm start # 运行编译产物
pnpm typecheck # 类型检查
pnpm lint # ESLint
pnpm format # Prettier 格式化维护者发布 npm 包见 docs/PUBLISH.md。
License
MIT
