AI 评审最怕的不是漏报,而是审完以后代码已经变了

你让 Agent 审一个未提交的改动。它读了十几个文件,过了一会儿给出一个看起来很完整的报告。

这时你顺手又改了两行代码。

报告还能用吗?

很多代码评审工具默认把答案当成一张静态截图:开始时拿到 diff,结束时输出 finding。可工作区不是截图。评审进行中,文件会变、分支会切、未跟踪文件会出现,甚至 HEAD 也可能移动。报告如果没有绑定它实际看过的目标,最后那句"第 8 行有问题"可能已经对应不到任何代码。

Blade Code v0.10.7 新增的 Session-native 只读 Code Review,把这个问题放到了运行时边界里处理。它的重点不是多一个 /review 命令,而是:评审先固定目标,目标变化就明确标记过期,无法证明位置对应时直接失败。

评审开始前,先给工作区做一张"指纹卡片"

packages/cli/src/services/GitReviewTargetService.ts 没有把目标简单写成一个路径。它先解析目标类型:

text 复制代码
/review uncommitted   当前 HEAD 到工作区的 staged、unstaged、untracked
/review base main     merge-base 到当前 HEAD 的变化
/review commit <sha>  某个 commit 引入的变化

然后把这些东西连续写进 SHA-256:

ts 复制代码
hash.update(`kind\0${request.kind}\0head\0${headSha}\0`);
hash.update(diff);
hash.update(`\0merge-base\0${mergeBase}`); // base review
hash.update(`\0commit\0${commitSha}`);    // commit review

未跟踪文件也不能漏掉。实现会把相对路径和文件内容写入同一个 digest,并为它们记录从第 1 行开始的 changed range。最后返回的 target 信息包含 headSha、文件数量和 digest,而不是只有一句"审当前目录"。

这张指纹卡片解决的是一个很具体的追责问题:当报告说"这个 finding 来自这次提交"时,系统至少知道它对应哪一个 commit 身份、哪一份 diff 和哪一批文件。

为什么一定要记录精确 changed line

只保存文件名还不够。一个文件里可能有 500 行,Agent 报告第 8 行的问题,必须证明第 8 行确实属于这次评审目标。

changedLinesFromDiff() 逐段解析 unified diff 的 hunk,维护旧行号和新行号,把新增、删除的行合并成连续范围。模型返回 finding 时,宿主会检查:

  • 路径属于 target;
  • 行号没有越界;
  • 行范围和真实 changed lines 有重叠;
  • priority、confidence 和结构化字段符合协议。

只要输出无法解析、引用了未改动的代码,整个 review 会 fail closed。这个选择有点严格,但它避免了一种很难排查的假精确:报告看上去指向 src/auth.ts:L8,实际上 Agent 读的是另一版文件。

Finding 不是一段自由文本,而是一个有边界的对象:

ts 复制代码
{
  title: "[P1] 命令式标题",
  body: "触发场景、影响和修复方向",
  priority: 1,
  confidenceScore: 0.99,
  codeLocation: {
    path: "src/auth.ts",
    lineStart: 8,
    lineEnd: 8
  }
}

这对读者的实际收益是,拿到报告后可以直接回到改动行处理,而不是重新猜 Agent 到底在说哪个版本。

评审跑着跑着,目标变了怎么办

最常见的现场是这样的:

sequenceDiagram participant W as 工作区 participant R as reviewer child Session participant S as 父 Session 事件流 W->>R: 固定 digest + changed lines R->>W: 只读检查 W->>W: 用户又改动文件 R->>S: review_completed(status=stale) S-->>用户: 这份报告不代表当前工作区

docs/reference/native-code-review.md 明确规定:评审运行期间 target 发生变化,结果标记为 stale。系统不把旧报告涂成绿色,也不自动把模型重新跑一遍来"补救"。

这是一条值得迁移到其他工具的判断规则:

评审结果要么绑定一个可复核的输入,要么公开承认输入已经失效。

很多工具只关注模型给出的结论,却没有把"结论对应哪一版代码"当成一等信息。实际协作中,后者往往更重要。

只读不是一句系统提示词

如果评审 Agent 可以写工作区,它就可能一边审、一边修,最后你分不清报告是针对原始改动,还是针对它自己改过的版本。

Blade 的内置 reviewer 只允许 ReadGlobGrep 和分类后的只读 BashGitReviewTargetService 还会限制目标最多 500 个文件、diff 与未跟踪内容合计最多 8 MiB。reviewer 进入 workspace-read-only sandbox,网络关闭,HOME、Blade storage、provider credentials 不可读,Git 使用隔离配置。

这里有两个不同的边界:

text 复制代码
工具白名单    防止 reviewer 主动修改或外传
target digest  防止 reviewer 的结论脱离它实际看到的输入

只做第一层,Agent 可能安全地审了一份已经过期的代码;只做第二层,Agent 仍可能在审查过程中改变代码。两层需要一起存在。

为什么 review 生命周期要写进 Session

Blade 没有把评审状态放在 Web 页面组件里。父 Session JSONL 会记录:

text 复制代码
review_started
→ review_completed
→ rendered assistant report

packages/cli/src/context/reviews.ts 会按 reviewId 投影这些事件。只有出现 review_started 且还没有完成事件的记录,才是 pending review。进程在 reviewer 完成前退出,下一次 owner 写入 interrupted;如果已经写入 review_completed,但渲染消息前崩溃,fresh Session 可以直接恢复报告,不需要重放模型。

这和"页面刷新后重新发起一次请求"差别很大。前者恢复的是已经落盘的事实,后者可能把一次只读评审变成两次不同输入的模型调用。

Fork 不复制 live review lifecycle,rewind 会移除 checkpoint 后的 review 事件和报告。它们不是 UI 细节,而是 Session 历史语义的一部分。

这次发布证明了什么,没证明什么

公开 v0.10.7 changelog 写明了三类 target、stale、abort、interrupted、crash projection、fork/rewind、finding contract 和只读 sandbox 的回归覆盖,也记录了 production Web、ACP、TUI 的真实 GPT 验证。

这些是 release notes 的交付声明,不是我在这篇文章里重新跑出的 production 结果。本文能直接核对的是公开源码和文档中的目标解析、digest、changed line、finding 校验以及 Session 投影逻辑。没有当前凭证时,不把 release note 写成自己的端到端复测。

如果你要评估自己的 AI 评审器,先问这五个问题:

  1. 评审输入有没有 commit identity、文件内容和 changed line 的摘要?
  2. 未跟踪文件是否被纳入目标,而不是默认忽略?
  3. 评审中目标变化后,结果是 stale、重跑,还是悄悄继续?
  4. finding 的路径和行号是否经过宿主校验?
  5. 进程重启后,恢复的是完成事件,还是重新调用模型?

回答不清楚之前,先别把"AI 代码评审"当成一份可以直接合并的意见。它首先是一份针对特定输入、在特定时间点生成的证据。

源码依据 :Blade Code v0.10.7(公开提交 1044d7e565fa55ba8b60ae6749d918c37dd59966),docs/reference/native-code-review.mdpackages/cli/src/services/GitReviewTargetService.tspackages/cli/src/context/reviews.ts

相关推荐
u1301307 小时前
GitHub 热榜项目:日榜(2026-08-10)
github
dong_junshuai8 小时前
每天一个开源项目#62 pdf-inspector:0.47秒解析200份PDF
开源·github
七牛开发者8 小时前
Codex 实践系列 Vol.04:用 Goal 和 Plan 管住一个长任务
java·数据库·人工智能·github·copilot
鬼手点金8 小时前
FreeLLMAPI 介绍
llm·github·nvidia·apikey·freellmapi·agnes ai·日日新
runningshark10 小时前
Github Copilot 智能编程助手深度评测
github·copilot
苏灿烤鱼10 小时前
AI Agent 深拆 | 图能让 AI 决策可追责吗?Semantica 登顶拆解
python·github·agent
fthux20 小时前
装闭 RenoPit 源码解析(04):装修图纸和合同文件上传处理流程
人工智能·ai·开源·github·open source·renopit
南巷羽1 天前
用 TRAE Work 把 20 条 GitHub Issue 变成可复核的需求优先级清单
github·产品
栩栩云生1 天前
AI 最大的安全问题:它让”发送数据”看起来像”继续思考”
安全·github·agent