ChatGPT、Codex实战排查:Agent明明已经修好Bug,为什么换一个Worktree后又复现了?
用Codex同时处理多个任务时,还有一个特别容易让人误判的问题:
这个Bug在原Worktree里明明已经修好了,为什么换一个Worktree、重新拉一个分支,甚至换一个Agent以后,问题又出现了?
最典型的场景是:
你让Agent A修一个登录异常。
它分析代码、修改文件、跑测试。
最后:
Bug不再复现。
测试全部通过。
你甚至手动验证了一遍,也正常。
看起来已经结束。
但过一会儿,你新建一个Worktree,或者让另一个Codex任务基于同一个Repository继续开发。
结果:
同一个Bug又回来了。
这时候最容易产生一个判断:
“是不是刚才那个Agent其实根本没修好?”
不一定。
很多时候真正的问题是:
Workspace State ≠ Repository State
在一个Worktree里表现正确,不代表所有让它正确的状态都已经真正进入Repository。
也就是说,Bug可能真的“修好了”。
但修复的一部分,只存在于那个Worktree当时的本地环境里。
一、先看一个最常见的真实场景
假设Agent A在:
worktree-auth
里修登录问题。
它做了这些操作:
修改认证代码。
调整一个环境变量。
重新生成本地配置。
安装一个依赖。
清理了一次缓存。
重新初始化测试数据库。
最后Bug消失。
测试也通过。
但真正Commit进去的只有:
认证代码。
其他东西:
环境变量没有进入Git。
生成文件被.gitignore忽略。
依赖虽然安装了,但Lockfile没有更新。
数据库状态只存在本地。
缓存也只是当前Workspace被清理了。
于是换到:
worktree-feature
以后,新Worktree只拿到了:
Git真正记录下来的那部分状态。
那些“帮助Bug消失”的本地状态全部没过去。
问题自然重新出现。
所以第一件事一定要先区分:
Code Fix
代码修复
和:
Workspace Fix
工作区修复。
二、第一种原因:Agent改了文件,但没有真正提交进去
这是最基础,也最应该先查的。
Codex在一个Worktree里可能修改了多个文件。
但任务结束时,不代表这些文件全部已经进入Commit。
常见情况包括:
未提交修改。
Untracked文件。
本地补丁。
生成文件。
临时配置。
如果Agent在当前Workspace里跑测试,测试读取的是:
整个工作区状态。
而你换Worktree以后,只能拿到:
Repository里已经Commit的状态。
于是就出现:
原Worktree正确。
新Worktree错误。
怎么查?
先在原Worktree检查:
git status
重点看:
有没有modified但未提交文件。
有没有untracked files。
有没有本地生成文件。
再看:
git diff
git diff --cached
确认真正进入Commit的内容,和当前Worktree运行时使用的内容是不是一致。
如果不一致,先别继续排查业务逻辑。
三、第二种原因:修复其实依赖了.env或本地配置
这类问题非常常见。
比如Bug本质和:
API地址。
Feature Flag。
Retry次数。
缓存开关。
数据库连接。
测试模式。
有关。
Agent排查过程中可能修改了:
.env
.env.local
本地配置文件。
或者IDE/Runtime环境变量。
但这些文件通常:
不会进Git。
尤其很多.env本来就被.gitignore忽略。
结果就是:
原Worktree里配置正确。
新Worktree重新创建以后,配置还是旧的。
于是Bug重新出现。
排查重点
对比两个Worktree里的:
.env
.env.local
开发配置。
运行参数。
环境变量。
不要只看代码Diff。
一个很实用的判断是:
同一个Commit,在两个Worktree里环境变量完全一致吗?
如果不一致,问题大概率就不是代码本身。
四、第三种原因:依赖版本并没有真正固定
比如Agent为了修Bug:
安装了一个新版本依赖。
或者执行了:
npm install
pnpm install
pip install
当前Worktree里的依赖目录已经变化。
测试通过。
但如果:
Lockfile没更新。
依赖文件没提交。
新Worktree重新安装时拿到另一个版本。
Bug就可能重新出现。
这类情况尤其容易发生在:
前端依赖。
Python环境。
工具链版本。
原生依赖。
怎么查?
确认:
package.json
package-lock.json
pnpm-lock.yaml
requirements.txt
poetry.lock
是不是都和实际运行环境一致。
然后最好在新Worktree里做一次:
Clean Install
不要复用旧依赖缓存直接判断。
因为“旧Workspace能跑”并不能证明:
Repository本身能够重建出同样环境。
五、第四种原因:Bug被“本地缓存”遮住了
这也是特别容易误判的一类。
比如:
Redis缓存。
浏览器缓存。
构建缓存。
测试缓存。
编译产物。
临时文件。
Agent在排查过程中执行过清缓存动作。
之后Bug消失。
于是它认为代码修好了。
但真正原因可能是:
缓存状态变了。
而不是代码修复本身。
换Worktree以后:
缓存重新生成。
或者新任务走了另一套缓存状态。
问题又回来。
这时候你看到的现象会很迷惑:
原Worktree稳定正常。
新Worktree重新复现。
排查方法
把两个环境都做一次:
清缓存。
删除构建产物。
重新Build。
重新启动服务。
如果清理以后结果开始趋于一致,说明之前的“修复”很可能混入了:
Cached State
缓存状态影响。
六、第五种原因:测试数据库或Seed状态不同
如果Bug和:
数据。
唯一约束。
迁移。
默认记录。
权限。
历史状态。
有关,就必须检查数据库。
Agent在原Worktree里可能:
手动改了测试数据。
跑过Migration。
重建过数据库。
更新过Seed。
测试于是通过。
但这些操作不一定全部被代码化。
换一个Worktree以后,新环境重新初始化。
原来的数据修正不存在。
Bug再次出现。
特别注意
有时候Agent会在排查期间执行:
SQL。
数据库修复脚本。
临时数据修改。
这些行为对当前测试非常有效,但如果没有进入:
Migration。
Seed。
Fixture。
脚本。
Repository根本无法复现。
所以需要问:
这个修复依赖的数据状态,能不能从一个干净环境自动重建出来?
如果不能,就不能算真正修好。
七、第六种原因:生成文件没有被正确管理
很多项目会生成:
客户端代码。
Type定义。
ORM文件。
配置。
API Schema。
构建产物。
Agent可能修改源文件以后,又执行生成命令。
当前Worktree里的生成结果是新的。
测试通过。
但如果生成文件:
被Git忽略。
或者忘记提交。
新Worktree里仍然是旧生成状态。
结果Bug重现。
例如:
Schema已经变了。
但新Worktree没有重新执行Codegen。
于是运行时仍然使用旧类型或旧客户端。
怎么查?
先确认项目有哪些:
Codegen。
Build step。
Generated artifacts。
然后在新Worktree执行标准初始化流程。
如果重新生成以后Bug消失,说明之前的问题不是单纯代码错误,而是:
生成状态没有被稳定复制。
八、第七种原因:Agent测试通过,其实依赖了一个“脏Workspace”
这类问题很有代表性。
什么叫脏Workspace?
就是当前目录已经积累了很多:
未提交修改。
旧Build产物。
临时文件。
缓存。
测试结果。
本地配置。
Agent在这个环境里不断修。
最后测试通过。
但这个“通过”只能证明:
当前这个复杂Workspace状态能跑。
不能证明:
一个干净Checkout也能跑。
所以工程上真正可靠的验证,不应该只在修复Worktree里做。
还应该做一次:
Clean-room Verification
干净环境验证。
九、最有效的排查方式:先判断到底是“代码状态”还是“工作区状态”
如果出现:
原Worktree修好,新Worktree又复现
不要第一时间重新让Codex修Bug。
先做一个非常简单的二分判断。
第一步:确认两个Worktree是不是同一个Commit
先看:
git rev-parse HEAD
如果Commit不同,先解决代码版本问题。
如果Commit完全相同,但行为不同:
问题基本就指向:
Workspace State。
第二步:对比Git状态
看:
git status
确认原Worktree有没有未提交内容。
第三步:对比环境
包括:
环境变量。
Runtime版本。
依赖版本。
配置文件。
第四步:清缓存和生成物
重新:
Build。
Codegen。
Install。
初始化。
第五步:重新创建测试数据
确保数据库和Fixture状态一致。
第六步:重新跑完全相同的测试命令
不要一个Worktree跑:
Unit Test。
另一个跑:
Integration Test。
测试入口必须一致。
十、推荐一个最稳的验证顺序
以后Codex修完一个Bug,可以按照这个顺序确认:
① 原Worktree测试通过
先证明当前修改有效。
↓
② 确认所有必要修改都进入Git
检查:
Commit。
Untracked。
环境依赖。
↓
③ 新建一个干净Worktree
不要依赖原来的Workspace。
↓
④ 从零初始化环境
Install。
Config。
Migration。
Codegen。
↓
⑤ 用同样步骤复现和验证
如果Bug依旧消失,才能说明:
Repository本身包含完整修复。
这一步非常关键。
它能把:
“当前Workspace修好了”
升级成:
“任何干净环境都能重建这个修复”。
十一、一个很实用的自测指标:Clean Reproduction Rate
孤狼这类工程问题不需要搞很多指标。
看一个就够:
Clean Reproduction Rate
可以简单理解为:
一个Agent修好的结果,在全新Worktree或干净Checkout里,有多大概率可以直接重建出来?
如果最近10个Codex修复:
9个在干净Worktree里都能直接复现正确结果。
说明你的Repository State很完整。
如果经常出现:
原Workspace好好的。
换目录就失败。
新Session又不一样。
那说明当前大量成功其实依赖:
本地隐性状态。
这才是真正需要先解决的问题。
十二、怎么让Codex以后少踩这种坑?
第一,修复完成前要求Agent检查:
git status
不要把未提交状态留在Workspace里。
第二,重要环境信息要尽量:
显式化。
版本化。
可重建。
比如:
Runtime版本。
依赖。
初始化脚本。
配置模板。
第三,把:
Migration。
Seed。
Codegen。
Build。
尽量变成标准命令。
不要依赖某个Agent“记得做过什么”。
第四,高价值Bug修复最好增加一次:
Fresh Worktree Verification
如果新Worktree也能通过,可信度会高很多。
十三、为什么这类问题和Plus / Pro也有关系?
很多人遇到:
同一个Bug反复出现。
Worktree之间结果不一致。
不同Agent重复排查。
会感觉:
Codex消耗特别快。
于是想到:
是不是Plus容量不够?
但如果大量任务都在重复:
重新建立环境。
重新发现缺失配置。
重新安装依赖。
重新清缓存。
重新修同一个Bug。
那么真正的问题不是:
AI执行量不够。
而是:
Reproducibility太差
可复现性太差。
增加容量只会让Agent更快重复这些工作。
十四、什么时候Plus通常够用?
如果你现在主要处理:
Bug。
Feature。
测试。
中型Repository。
但经常出现:
Worktree之间环境不一致。
依赖状态混乱。
未提交文件多。
干净环境无法稳定复现。
那么Plus通常已经足够你继续优化工程流程。
优先做好:
Git状态。
环境管理。
依赖锁定。
初始化脚本。
Clean Verification。
等这些稳定以后,同样的Codex容量通常会好用很多。
十五、什么时候Pro才真正开始匹配?
如果你的情况已经是:
大部分Bug修复都能在新Worktree稳定复现。
环境初始化高度标准化。
依赖版本固定。
生成流程清楚。
Repository可以从零重建正确状态。
Clean Reproduction Rate很高。
但每天仍然有大量:
复杂Bug。
跨模块任务。
长任务。
多个独立工程任务。
持续排队等待Codex执行。
这时候问题才真正从:
Reproducibility Problem
可复现性问题
变成:
Capacity Problem
容量问题。
这时更高容量才更容易真正转化成更多有效工程产出。
最后
Agent明明已经修好Bug,换一个Worktree以后却又复现,不一定代表:
Agent第一次修错了。
很多时候真正的问题是:
修复不只存在于代码里。
还存在于:
环境变量。
依赖。
缓存。
数据库状态。
生成文件。
未提交修改。
这些东西组合起来,才形成了原Worktree里的“正确状态”。
所以以后遇到这个问题,先不要马上重新修Bug。
先问一句:
这次修复到底存在于Repository里,还是只存在于那个Workspace里?
真正可靠的修复,不应该只能在:
“那个Worktree”
成立。
而应该能够在:
一个全新的Worktree。
一个干净Checkout。
一个新的Agent Session。
里重新建立。
这才说明:
Bug真的被修进了项目,而不是暂时被某个工作区状态掩盖了。
持续更新Codex、大模型开发相关技术内容。
长期使用各类代码大模型,整理了稳定的Plus/Pro会员订阅渠道,有需要可自取!
更多推荐

所有评论(0)