用 Codex 修 bug:先验证原因,再动实现 - AIPlan

用 Codex 修 bug 时,先复现并缩小变量,再验证根因与最小修复。说明应提供的日志、边界样本和回归检查,避免连改多处碰运气。

用 Codex 修 bug:先验证原因,再动实现 - AIPlan
修 bug 的第一步不是改代码,是让 Codex 把问题复现出来给你看。一个有明确报错、明确输入、明确期望的 bug,修复通常在 1 到 2 轮内收敛;一个只有“有时候会失败”的 bug,改 5 个文件也未必对。截至 2026 年 10 月 18 日核对,这条经验在 Codex 的各入口上一致。 复现是唯一能验证的东西 模型不会自己知道你的 bug 长什么样。它能做的是照着你的描述去读代码、猜原因、改实现。这三步里只有第一步有确定答案。 所以任务的开头应该是一段可执行的复现路径: 现象:提交订单后偶发 500,日志出现 "database is locked" 复现:连续提交 3 次,第 2 次必现 环境:SQLite,MaxOpenConns=1 期望:3 次全部返回 200 这四行比 300 字的背景描述有用。环境 那行尤其关键,同一个异常在 SQLite 和 PostgreSQL 上是完全不同的问题。 先让它读,别让它改 第一轮任务只做一件事:定位。可以这样写: 只读任务,不要修改任何文件。读 internal/order/ 下的提交路径, 找出哪些查询没有走事务句柄。输出:文件路径、行号、函数名、为什么会在 事务内触达全局连接。不要给修复方案。 为什么要禁止它顺手修?因为定位阶段的错误判断如果被写进代码,你后面是在审查一个建立在错误前提上的补丁,比从零开始更费劲。 /review 的审查面板在这种场景里很好用:它只报发现、不动工作区。让 Codex 跑一轮 /review 看它认为哪里有问题,和你自己的判断对照。 缩小变量比读代码重要 一个偶发问题背后可能有 3 个独立因素。一次性全改,你不知道哪个改动起了作用。可操作的缩小方式: • 把触发条件从“偶发”压缩成“必现”。加日志、加延时、减少并发数,直到 10 次里有 10 次能复现。 • 二分变量。先固定输入不变只改环境;环境不变只改输入;一路砍到只剩 1 个差异。 • 把缩小过程写成笔记,后面修完还要用它验证。 第 1 步能拿到必现路径,后面所有工作都变简单。拿不到的话,先花时间在复现上,不要急着改代码。 根因和现象要能分开说 好的根因描述长这样: service.GetSetting() 在事务闭包里被调用,它自己开了一个 DB 连接。SQLite 的 MaxOpenConns=1,连接被占住,事务无法提交,30 秒后超时。 这段话有三个特征:指向具体函数、解释了机制、能预测后果。如果 Codex 给出的解释是“可能是数据库连接问题”,那不是根因,是猜测。 验证方法很简单,让它回答一句话:如果把 A 改成 B,现象会消失吗?为什么?答不上来就别动实现。 最小修复的边界怎么划 修 bug 的常见失败是顺手重构。原本 3 行的改动变成 80 行,多出来的 77 行没人审过。 任务描述里可以把边界钉死: 只改这一处。不改函数签名、不改文件结构、不动无关的格式化。 如果需要改动超出 1 个文件,先停下来告诉我原因。 “先停下来告诉我”这句很有效。模型在改动要扩散时会遵守这类指令,你就有机会判断这个扩散是必要的还是它在乱来。 回归检查要写在修复之前 修完不算完,得证明没修坏别的。最少三条: • 原来那条复现路径现在通过 • 相邻的正常路径仍然通过 • 边界输入不崩 第三条最容易被跳过。金额为 0、字符串为空、列表只有 1 项、并发数为 0,这类输入在修 bug 时往往正是触发条件所在。让 Codex 给一份边界清单,再挑 2 到 3 个写成测试。 写测试这件事单独展开会更好,测试该发现什么错误、怎么验证测试本身有效,可以看 让 Codex 写测试:先问这条测试能发现什么错误。 让它自己跑验证命令 Codex 能执行本地命令,这意味着它能在修改后自己跑 go test ./... 或者 npm test。用起来,但要看清楚两件事。 输出里有 FAIL 就是没通过,不管后面跟了什么解释。模型有时会把“测试本身写错了”当成通过的理由,你得自己判断。 测试超时也是失败。跑 300 秒没结果的测试,在 CI 上会被判失败,在本地也一样。 Go 项目还有一条:gofmt -l 应该没有输出,go vet ./... 应该干净。格式和静态检查挂了,测试全绿也不算完成。 什么时候该换思路 三种情况说明当前方向不对: • 改了 3 处还没让复现路径通过 • 每修一次就有新的失败点冒出来 • 需要修改测试来让代码通过 第三种最危险。测试是行为的定义,改测试让代码过等于先改标准再改实现。这时候要么测试写错了,要么根本问题是需求理解偏了,两者都不该由 Codex 自行决定。 一次完整的时间分配 按 30 分钟一个 bug 估算,比较健康的分配是:复现 10 分钟,定位 8 分钟,修复 5 分钟,验证 5 分钟,收尾 2 分钟。修复本身占比最小,这是正常的。 反过来,如果发现自己花了 25 分钟在改代码还改不对,说明前 10 分钟的复现没做扎实。 Claude Code 之类工具和 Codex 在这一点上一致:换的是入口,不是流程。用同一个仓库任务横评 Codex、Cursor 和 Claude Code,结论通常也落在复现质量上,而不是工具本身。 额度方面,修 bug 是相对省量的任务,输入集中在少数几个文件。如果你只在周末集中处理积压的 bug,Plus 的 $20 折算约 ¥133.80 够用,¥115.50 的 Plus 月卡 买的就是这一档。真正吃额度的是那种要读 50 个文件的大型排查,那种情况下值得先看 Codex 额度不够用时先看任务怎么消耗。 下一个 bug 到手时,先用那四行格式把它写清楚,再让 Codex 只读定位。省下来的返工时间比配额更值钱。 参考资料资料核对日期:2026-10-17 • Codex CLI • Code review 延伸阅读• 让 Codex 写测试:先问这条测试能发现什么错误 • 给 Codex 下任务怎么写?让目标、边界和验收都可检查 • 用 Codex 做代码审查:每个发现都要说明怎样触发