使用 ChatGPT、Codex Agent 修 Bug 时,经常会遇到一种很典型的情况:

你明明只让它修一个问题,最后却发现十几个文件都被改了。

常见表现包括:

  • 原本只需要补一个判断,Agent顺手把整个函数拆了;
  • 修接口异常时,同时统一了变量命名;
  • 修一个组件Bug,又顺手抽了公共组件;
  • 原来只改3行代码,最后Diff变成几百行;
  • Bug确实修好了,但Review反而更困难;
  • 一旦测试失败,也分不清到底是修复逻辑出了问题,还是重构引入了新问题。

这种情况并不一定说明 Codex Agent “乱改”。

更常见的原因是:

它把“解决当前问题”和“顺便把代码变得更好”混成了同一个任务。


一、为什么Agent修Bug时特别容易顺手重构?

人类开发者看到一段不好看的旧代码,往往也会产生一个想法:

这里顺便整理一下吧。

Codex Agent同样如此。

例如它为了修一个空值异常,读到附近代码以后发现:

  • 函数太长;
  • 判断重复;
  • 命名混乱;
  • 公共逻辑可以抽取;
  • 类型定义不统一。

于是它可能认为:

既然已经要修改,不如一次把结构一起整理。

从“代码质量”的角度看,这似乎合理。

但从 Bug 修复角度看,风险反而变大了。


二、修Bug最重要的不是“代码更漂亮”,而是缩小变量

假设原来的问题是:

用户信息为空时页面报错。

最小修改可能只是:

增加一次空值判断。

如果同时又:

  • 重写数据处理;
  • 抽公共函数;
  • 改变量名;
  • 调整组件结构;

那么即使最后测试失败,也很难快速判断:

到底是哪一个变化导致的。

Bug修复阶段最重要的一件事其实是:

一次尽量只改变和当前问题有关的东西。

这样故障定位和回滚都会简单很多。


三、“顺手优化”为什么会放大Review成本?

一个Bug本来可能只需要Review:

5行修改。

如果 Agent 顺手重构以后变成:

300行Diff。

Review的人就必须同时确认:

  • Bug有没有真正修好;
  • 重构有没有改变旧行为;
  • 公共函数抽取是否正确;
  • 命名调整有没有漏引用;
  • 测试是否覆盖新的结构。

原本是一次简单修复,最后变成了小型重构项目。

所以大Diff最大的成本,不只是代码变多。

而是:

原来的修复目标被淹没了。


四、先区分“必须改”和“可以以后改”

让 Codex Agent 修Bug之前,可以先把修改分成两类。

必须修改

为了修复当前Bug,不改就无法解决问题。

例如:

  • 增加边界判断;
  • 修正错误条件;
  • 调整一个接口参数;
  • 修复错误状态处理。

可选优化

即使不改,也不影响本次Bug修复。

例如:

  • 重命名;
  • 抽公共方法;
  • 格式统一;
  • 文件重构;
  • 清理旧代码。

这两类不要混在一个任务里。

先完成:

必须修改。

等Bug验证通过以后,再决定要不要单独开一个重构任务。


五、可以给Agent设置“Diff预算”

这是一个很实用的办法。

例如可以明确:

本次只修当前Bug,优先最小修改。除非确实必要,不要修改无关文件,不要重构公共模块。如果预计需要修改超过3个文件,请先说明原因再继续。

这里的“3个文件”不是绝对标准。

真正作用是:

让Agent在扩大修改范围之前停一下。

从“默认可以随便扩展”,变成:

扩大范围需要理由。


六、不要让“顺手重构”混进修复提交

即使某个重构确实有价值,也最好拆开。

例如:

第一步:

Fix:修复订单状态异常。

第二步:

Refactor:整理订单状态处理逻辑。

这样有几个好处:

  • 修复本身容易Review;
  • 出问题时容易回滚;
  • 重构不会掩盖Bug修复;
  • 测试失败时更容易判断来源。

如果两个动作混在一起,一旦上线异常,回滚也会比较麻烦。


七、Agent什么时候才应该扩大修改范围?

最小修改不等于:

永远只改一行。

有些Bug确实暴露的是底层设计问题。

例如:

三个接口都复制了同一段错误逻辑。

这时候只修一个地方,反而会留下另外两个问题。

所以更合理的判断是:

如果不扩大修改范围:

同一个Bug还会在其他路径继续出现吗?

如果会,那么扩大范围可能是必要的。

但这时候 Agent 应该先说明:

  • 为什么必须扩;
  • 会影响哪些文件;
  • 哪些行为需要重新验证。

而不是直接开始大面积重构。


八、验证也应该围绕“原Bug”展开

Agent修改完成以后,第一轮验证不要马上跑一大堆和任务无关的检查。

先确认:

原来的Bug还能不能复现?

然后检查:

  • 正常路径是否保持不变;
  • 边界情况是否修复;
  • 有没有影响相邻逻辑。

只有当前修复稳定以后,再扩大验证范围。

否则如果一开始就同时做:

修Bug + 重构 + 全项目优化

问题一多,定位就会变得非常困难。


九、看到大Diff时,先问一句“哪些不是必须的?”

如果 Codex Agent 已经改了很多内容,可以先让它重新分类:

请把当前Diff分成“修复这个Bug必须的修改”和“可选重构”两组。保留必须修改,把与当前Bug无关的重构先撤回。

这个动作非常实用。

很多时候你会发现:

真正修Bug需要的修改其实很少。

其余只是 Agent 根据“最佳实践”顺手做的优化。


十、可以直接这样约束ChatGPT、Codex Agent

以后让 ChatGPT、Codex Agent 修Bug,可以直接要求:

本次任务只修当前Bug,优先采用最小修改方案。不要顺手重命名、抽公共函数、调整目录或重构无关代码。先说明Bug根因和必须修改的文件,再执行修改。如果需要扩大到更多文件,请先说明为什么不扩大就无法完整修复。修复后先验证原Bug和相邻正常路径,其他代码质量优化单独列为后续建议,不要混入本次Diff。

这类约束能明显降低:

Bug修好了,但项目被顺手改了一大片。


最后

Codex Agent修Bug时总喜欢顺手重构,真正的问题通常不是:

Agent太喜欢优化代码。

而是:

任务里没有明确“修复边界”。

稳定的Bug修复流程应该是:

确认根因 → 找到最小修改 → 限制Diff范围 → 修复 → 验证原问题 → 再决定是否单独重构。

Agent越能自主修改代码,越应该明确:

这次到底是在“修问题”,还是在“改善结构”。

这两件事都重要。

但最好不要默认一次全部做完。


持续更新 ChatGPT、Codex、AI Agent 与大模型开发工作流实战内容,更多深度内容欢迎搜索关注「孤狼GPT」。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐