AI 写代码越来越强,但它不知道我们上周修了什么 bug,把 Bug 重新引入生产环境了

13 小时 31 分钟前
 huoru

三个月前,我们花了两周时间修了一个 bug 。

用户账单偶尔会出现 ¥0.01 的误差。复现不稳定,线上偶发,客服一直在手动补差价。翻遍了日志,最后定位到一个经典问题:浮点数精度。

0.1 + 0.2 在 IEEE 754 里不等于 0.3,这个大家都听说过,但真的踩到还是很痛。

修复方案是把所有金额改成以「分」为单位存整数,展示时再除以 100 。改动不复杂,但涉及的地方很多,改完之后代码里到处是 amount * 100Math.round()/ 100,看起来有点丑,但能用,bug 消失了。

然后上个月,我让 Agent 帮我重构结算模块,优化一下代码结构。

它看到那堆乘除,觉得多此一举,顺手给「简化」了,改回了直接用浮点数。逻辑更清晰,代码更短,单元测试全过。

那个 ¥0.01 的 bug 悄悄回来了。


这件事让我开始认真想一个问题:

我们有代码审查,但我们需要「意图审查」。

这不是 AI 写了烂代码

大家讨论 AI 写代码,通常聚焦在输出质量上:架构合不合理、有没有 bug 、测试过了没有。

但我说的这个问题不一样。

Agent 那次重构质量是好的。逻辑清晰,可读性提升了,测试也没挂。它只是不知道「那堆看起来多余的乘除,是两周 debug 换来的」。

从它的角度看,price * 100 然后 / 100 是纯粹的噪音——数学上等价,白白增加了阅读负担。优化掉,天经地义。

你想想一个工作了五六年的老工程师,碰到这段代码会怎么做?

大概率不会直接删。他会皱着眉头想:「这里为什么要转成整数?不可能是手滑写的,一定有原因。」然后去翻 commit ,或者去问写这段的人。

这叫对不熟悉代码的谦逊感——被坑多了,知道看起来多余的代码往往不是真的多余。

AI Agent 没有这个。它被训练成「顺着干」,而不是「先问为什么」。代码看起来可以简化?简化它。逻辑看起来绕弯子?拉直它。它只会优化表面,不会追问历史。

新项目里这没问题,在一个有历史的真实代码库里,这会出事。

现有的方案都差点意思

每次我说起这个问题,大家都会推荐一些工具。我挨个想过,说说为什么都不够用:

注释:「// 不要修改这里,浮点精度问题」写上去当然有用。但你得先意识到这里需要警告,才会去写。当时修 bug 的人在想的是「终于修完了」,不是「三个月后的 Agent 可能会把这个改回去」。漏写的注释保护不了任何人。

AGENTS.md / CLAUDE.md:同理,你想到的禁忌才能写进去。但大多数坑是事后才知道是坑的,你没法提前把所有决策都整理成文档。

ADR / RFC:门槛太高,大多数团队第一个季度之后就不维护了。就算维护着,也是给人看的文档,不是供 Agent 在改代码前按需查询的。

Wiki / Notion / Confluence:文档会和代码脱节。「金额统一用分存储」这件事,可能在某个内部文档里提了一句,但 Agent 不会在重构代码前主动去翻 Confluence ,就算翻了,也是一堆非结构化的文字,未必能命中。

PR 描述:当时修 bug 的 PR 描述里可能写了原因,但埋在 GitHub 历史里,没人去翻,Agent 更不会主动去看。

每一个工具都是对真实问题的局部回应,但没有一个能在 Agent 动手之前,把「这里曾经踩过什么坑、为什么要这么写」这件事,可靠地送到它面前。

我们缺的是「意图审查」

现有的代码审查,回答的是:「这个变更实现得好不好?」

看 diff ,查正确性、风格、测试覆盖率。这个流程很成熟,也很必要。

但代码审查解决不了另一个问题:「这个变更,在已有的历史背景下,方向对不对?」

这个问题需要审查者记住代码库的历史,记得这堆乘除是两周 debug 换来的,记得某个绕弯子的写法是填过坑之后留下的疤。大多数审查者没这个上下文,就算是原作者,三个月后也可能忘了当时为什么。

所以我觉得我们需要一层新的审查,叫意图审查,发生在代码被改之前,而不是之后。

它问的是:

对人类工程师来说,这些审查以非正式的方式发生:发条消息、瞄一眼 commit 历史、和写那段代码的人聊三十秒。

对 AI Agent 来说,这根本不会发生。没有「去问问当时踩过坑的人」的等价操作。Agent 读当前代码,看起来可以优化,就优化了,历史上踩过的坑对它来说是不可见的。

意图审查要怎么做

要真的能用起来,得满足三点:

第一,决策必须是结构化的。

「金额统一用分存储,避免浮点精度」这句话写在 Wiki 上供人阅读没问题。但 Agent 需要的是:决定了什么、为什么这么决定、涉及哪些文件、哪些操作是被明确禁止的。自由文本把这些结构藏起来了,Agent 每次都要重新解析一遍,还不一定能命中。

第二,决策必须住在代码旁边。

Wiki 会漂移,Notion 会被遗忘,Slack 消息串会被淹没。唯一能和代码永远保持连接的是 git 本身。决策活在 git 里,就能跟着代码一起被 clone 、被 fork 、被带到三个月后还没接手过这块的人面前。

第三,查询必须自动发生,在改代码之前。

如果需要提醒 Agent 「先查一下历史决策」,它就不会查。这个步骤必须内嵌在正常工作流里,就像它在重构前会先 grep 符号定义一样,查历史的摩擦要低于直接动手的摩擦。

我做了个工具

我最近在开发一个叫 Mainline 的东西,把团队决策以结构化记录的形式存进 git 本身,让 Agent 在改代码前可以查询。

每条「意图记录」长这样:

如果当时修浮点 bug 的时候封存了一条意图记录,三个月后 Agent 重构结算模块,运行 mainline context billing,就会看到:「金额统一用分存储,直接用浮点运算会导致 ¥0.01 偶发误差,已确认线上踩坑,禁止还原。」

那次「简化」大概率就不会发生了。

用了一个月,有几点出乎我意料:

摩擦不在我以为的地方。 我以为工程师会抗拒写这些记录,结果没有——因为 Agent 负责起草,工程师只是过目和调整。真正的摩擦在于:什么时候该封存一条记录?封太频繁是噪音,封太少会漏掉重要的坑。

收益来得比预期晚。 第一周感觉纯粹是额外负担。第三周开始出现「这段为什么要这么写?」的时刻,答案就在日志里。第六周,Agent 开始不用提示就把历史决策当作上下文来用。

两个人协作比一个人用难得多。 一个人用的时候,意图记录是写给自己的备忘。两个工程师同时工作时,它变成了一个协调协议——你得知道对方封存了什么,你们的方向有没有冲突。

工具是开源的( Apache 2.0 ),目前小范围私测,地址在 mainline.sh

https://github.com/mainline-org/mainline

说回这件事本身

AI Agent 现在在很多团队里写相当比例的新代码。代码审查的负担没有降低,反而在升高——因为审查 AI 写的代码认知成本更高,你没办法像问同事一样问它「你为什么这么改」。

现在的情况是,每次代码审查都得身兼两职:一边看实现,一边猜方向对不对。大多数时候,方向验证是静默失败的。审查者不知道那堆乘除是修 bug 留下来的,点了 approve ,坑就回来了。

这个问题靠更好的 prompt 解决不了,靠更大的上下文窗口解决不了,靠更强的模型也解决不了。

这是一个结构性问题:团队踩过的坑住在哪里?

现在它住在人的脑子里、Slack 里、PR 描述里——Agent 不会主动去看的地方。

要让 AI 真正能在一个有历史的代码库里可靠地工作,我们需要把这些知识搬到它会可靠地去看的地方。对大多数团队来说,那就是 git 。

我们有代码审查。我们需要意图审查。


你们有没有被 Agent 悄悄还原过某个 bug 修复?现在是怎么防的?

4841 次点击
所在节点    推广
98 条回复
Coverlove
10 小时 56 分钟前
敲代码的时候习惯使用 Comment Anchors 各种添加 //ANCHOR - //NOTE - ...
尤其是修改别人的代码,得先理解,再动手
thrinity
10 小时 54 分钟前
我习惯让 agent 修改前看看这个块区域的 git 历史,了解清楚前因后果再落笔。
huoru
10 小时 54 分钟前
@justdoitzZ 你说的非常对,最好就是 AI 留痕,持续整理。问题是文档不跟代码走,所以我们做了意图绑定 commit ,从而也跟代码绑定了

之后就不会有文档孵化的问题了
hubianluanma
10 小时 52 分钟前
目前我们项目的做法是对于这种错误完善 ut ,每次 AI 在改完后进行测试,随着 ut 的完善,重现 bug 的概率也会降低,还有就是建立 bug 库,通过关键词或者指定的方式进行辅助
cvbnt
10 小时 51 分钟前
我个人认为涉及高精度数字计算应该要专门出个工具类来处理,再不济也有现成的依赖可以用
huoru
10 小时 51 分钟前
@Coverlove 人的好习惯👍
villivateur
10 小时 50 分钟前
所以,我只用 AI 做代码审查,但是不让他直接改。就算改了,每一行也要人工确认。
ca2oh4
10 小时 47 分钟前
用 claude code 和他强调做什么不做什么,写清楚项目规则,基本上 ai 不会犯一样的错误了
xiaomushen
10 小时 43 分钟前
别听那些自媒体和大 V ,搞许愿池
justdoitzZ
10 小时 43 分钟前
@huoru #43 仔细看了你的网站,所以你们想做的是管理经验。好像对大型项目,多人工作的团队更有帮助,对个人开发者,小项目,其实 markdown 文档也够用了。还有一点建议,建议增加演示使用的视频或者动图,我大概弄懂了你想干嘛,但是没太懂,如何实现,如何高效保存来跟随项目的。
dtdths1
10 小时 42 分钟前
不是。。这种问题在项目一开始设计的时候都不应该存在。。而且你说单元测试全过,只能说你们单元测试有跟没有没啥区别
huoru
10 小时 40 分钟前
review 时,点开一个 intent ,详情是这样子的: https://imgur.com/a/mImqF4R

会跟 git commit 绑定一起,agent 自动填写的
xuanbg
10 小时 39 分钟前
不是。。。用浮点数处理金额,你们怎么敢的
huoru
10 小时 39 分钟前
@justdoitzZ 是的~,我们接下来会更新说明文档。现在做得太 geek 了,就觉得很有必要做这个工具自己用
Linczh
10 小时 39 分钟前
@guidao #14
这个是正解,修 bug 要补充测试,不然后续必然会在重构重丢失这个 bug 的上下文,,,一般这种明显奇怪的写法也要留注释,通常会留下一个 issue#xxx 的标记,还是工程实践没做好
justdoitzZ
10 小时 35 分钟前
@huoru #54 已经很牛逼了。网站风格我很喜欢,文档也写得不错。棒棒哒!!!!
4seasons
10 小时 34 分钟前
我现在一般较大的改动,都会先生成 spec ,这样它后面改动就知道前面干了什么事情了
huoru
10 小时 34 分钟前
@justdoitzZ 感谢,希望对你有用啊。Solo 开发也能用上的,起码直观看到 ai 做了啥
Cruzz
10 小时 32 分钟前
整个项目给他让他改,你是真敢啊
SD10
10 小时 31 分钟前
写的真好 有机会尝试一下

我现在很少看 AI 修改的代码了,对代码的理解完全就是一团浆糊,主要还是小公司路子太野了,曾经吹牛皮一天一个版本,鼓励的就是人不要再看了... 摆烂中

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://study.congcong.us/t/1211151

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX