我打回了 AI 写的 PR:新立 3 条规矩,第 1 条就有争议

31 阅读5分钟

最近打回 AI 写的 PR 越来越勤。说它写得差倒不至于,速度和整洁度它都超过我了。麻烦在另一个地方:拿人写代码的老标准去评机器写的代码,评不出重点。

我把现在的处置标准压成了 3 条规矩,先全部摆出来:

规矩触发条件处置
1三态不齐(loading / error / empty)直接打回,不商量
2AI 的需求理解没随 PR 提交打回,先补材料
3diff 里混进任务外的「顺手改动」打回,越权行零容忍

第 1 条争议最大,因为它明摆着是双标。往下看我的理由。

规矩一:三态不齐,直接打回

AI 生成的前端代码有一种天然的迷惑性:看起来对。UI 能点,数据能显示,演示的时候网络刚好也好。它默认产出 happy path,不是它笨,是你给的上下文里只有 happy path。

一个典型的 AI 产出,数据列表组件:

function OrderList() {
  const { data } = useQuery({ queryKey: ['orders'], queryFn: fetchOrders });

  return (
    <ul>
      {data.map((o) => (
        <li key={o.id}>¥{o.amount.toFixed(2)}</li>
      ))}
    </ul>
  );
}

演示的时候毫无问题。但 React Query 在请求成功之前 data 是 undefined,接口一抖动,这行 data.map 直接白屏;接口报错,用户看到的还是白屏,一条提示都没有。

打回标准很具体:三态补齐才算完成。

function OrderList() {
  const { data, isLoading, isError, refetch } = useQuery({
    queryKey: ['orders'],
    queryFn: fetchOrders,
  });

  if (isLoading) return <Skeleton rows={3} />;
  if (isError) return <ErrorState onRetry={refetch} />;
  if (data.length === 0) return <EmptyState />;

  return (
    <ul>
      {data.map((o) => (
        <li key={o.id}>¥{o.amount.toFixed(2)}</li>
      ))}
    </ul>
  );
}

这条被质疑得最多,理由很整齐:人写的组件三态不齐的时候,你怎么就留个 comment 提醒一下,合了?

对,就是双标。我的理由:打回人的代码,对方一下午白干,还搭一次不愉快的沟通;打回 AI 的代码,它重跑三分钟。这个动作变便宜了,标准还停在原地,那才是浪费。

顺着这个逻辑还有个推论:AI 的 PR 我要求得比人更严,反正它改起来不心疼。

规矩二:理解不随 PR 提交,就是盲盒评审

规矩二管的是另一件事:AI 对需求的理解,代码倒是其次。它以为的「列表要分页」和产品说的「列表要分页」,中间可能隔着一万个默认值。

所以任务描述必须贴进 PR。看不到它以为什么是需求,这 PR 就没法评,你评的是盲盒。

我现在的 PR 描述固定三段:

## 需求原文
(产品的话原样贴,不改写、不翻译成技术语言)

## AI 的计划
(agent 的 plan 输出原样贴,含它打算动的文件清单)

## 我纠正过的理解
(它哪条理解错了、我改成了什么,这段是评审最该看的)

第三段最值钱。Claude Code、Codex 这类 agent 都有计划模式,先让它列方案再动手,那份计划输出就是现成的评审材料,比从 diff 里反推它当时在想什么省事得多。

评审动作也跟着变了。以前逐行看代码猜意图,现在先看「它的理解」和「需求原文」差多少,再决定代码细看到什么程度。理解全对的,代码扫一眼结构就行;理解跑偏的,diff 再漂亮也白搭。

规矩三:任务外的顺手行,零容忍

AI 修一个按钮对齐,能顺手把半个目录按 prettier 重排一遍,删两个它判定没人用的导出,再把某个依赖悄悄升个小版本。

人干这种事叫顺手,机器干这种事叫越权。人会为自己的顺手负责,机器不会:它不记得自己顺手改过什么,等下次出问题排查的时候,这些混在任务 diff 里的无关行全是噪音。

识别方法很机械:diff 的文件清单和任务对不上,就有越权。比如一个「修复按钮文案对齐」的 PR 里出现这个:

--- a/package.json
+++ b/package.json
@@
-    "react": "^18.3.1",
+    "react": "^19.0.0"

不用看第二眼,打回。格式化噪音和依赖版本好认,难的是「删了没人用的导出」:前端项目里动态引用、字符串调用、被构建脚本扫的导出太多了,AI 的静态分析看不见这些。

规矩三是三条里最没有讨论空间的。规矩一你还可以吵吵双标合不合理,规矩三连吵的余地都没有。

给 AI 的打回评论,和人写的不是一种东西

打回之后怎么写评论,是我最近才想明白的环节。

给人写评审意见,重点是把 why 讲清楚,因为人需要被说服;给 AI 写,重点是把 what、边界、验收标准给足。它执行 what 的效率极高,领会 why 的能力很差。

问题:OrderList 在加载中和请求失败时白屏
要求:补三态(骨架屏 / 错误态带重试 / 空列表态)
边界:只改 src/components/OrderList.jsx,不要动其他文件
验收:DevTools 里切 offline 刷新页面,不白屏

四个字段里最值钱的是「边界」。不写边界,它修 OrderList 的时候顺手把整个 components 目录「优化」一遍,正好撞回规矩三。

我自己用下来的体感:这种填空式的打回,一次返工就过的比例高了不少,比「这里有点问题你看看」管用。现在打回全是填这个。

打回的能力,是有保质期的

最后说个我的真实感受。

「看起来没问题就合」这件事有隐性成本。三个月后你可能就打不动它了,权限都在,但读不动了:它的产出速度早就超过你逐行确认的速度,等你只能扫一眼 diff 就点合并的时候,标准想立也立不住。

外面也差不多是这个方向。arXiv 今年有论文专门讨论 agent 时代的 code review 怎么重新设计,CodeRabbit 这种 AI 审 AI 的机器人快成开源项目的标配了。连 Anthropic 自己的研究都被拉到 Reddit 上吵了一圈:AI 辅助编码的效率提升没那么大,还可能影响开发者的能力。

评审这条流水线上,人还说了算的地方不多了,打回算一个。

你们团队现在 AI 生成的 PR,过评审用的是和人同一套标准吗?规矩一这种「该不该双标」,我站更严这边。你呢?