最近用 ChatGPT、Codex 同时推进多个开发任务时,我越来越明显地遇到一个新问题:
单个PR没问题,不代表多个PR合在一起以后也没问题。
比如一个大型项目里,同时开了三个Agent任务。
Agent A负责改鉴权逻辑。
Agent B负责调整缓存。
Agent C负责修改公共DTO。
三个任务互相看起来都很独立。
每个Agent都在自己的Branch里工作。
各自测试通过。
各自CI也是绿色。
Code Review单独看,也找不出明显错误。
于是三个PR陆续合并。
结果最后一个PR合进主干以后,线上测试突然失败。
更麻烦的是:
Git根本没有Conflict。
三个PR都能顺利Merge。
代码也能编译。
但最终系统行为就是不对。
这时候真正的问题已经不是:
哪个Agent写错了?
而是:
三个“单独正确”的改动组合起来以后,破坏了彼此原本依赖的假设。
这也是多Agent并行开发里非常容易被低估的一层:
PR Correctness,不等于 Composition Correctness。
一、先给核心判断:Git没有冲突,不代表业务没有冲突
我们平时最熟悉的是:
Text Conflict。
两个人同时修改同一行代码。
Git没法自动决定保留谁,于是直接报Conflict。
这种反而好处理。
因为系统明确告诉你:
这里发生冲突了。
真正麻烦的是:
Semantic Conflict——语义冲突。
两个PR修改的是不同文件。
甚至不同模块。
Git完全可以自动合并。
但它们改变的系统假设彼此矛盾。
例如:
Agent A修改鉴权逻辑,认为:
userId永远来自当前登录态。
Agent C修改DTO以后,允许某些后台任务不再携带userId。
两个PR单独测试都成立。
合到一起:
后台任务直接被新鉴权逻辑拒绝。
Git不会告诉你:
“这里冲突了。”
因为文件层面根本没有冲突。
真正冲突的是:
对系统行为的理解。
二、为什么多Agent特别容易放大这个问题?
人工开发时,同一个团队成员通常会知道:
“隔壁那个人正在改什么。”
开会。
聊天。
Review。
上下文会自然传播。
但多个Agent并行工作时,每个Agent看到的往往是:
自己的任务上下文。
Agent A知道:
我要重构鉴权。
Agent B知道:
我要优化缓存。
Agent C知道:
我要改DTO。
每个Agent都能在自己的局部范围里做出非常合理的选择。
但它们未必知道:
其他Branch正在同时改变哪些系统条件。
于是会形成一个很典型的问题:
Local Optimization,Global Collision。
每个Agent都把自己的任务做对了。
系统却在最后组合阶段出错。
三、一个很典型的现场:缓存和权限分别都改对了
假设原来用户权限每次请求都会实时查询数据库。
Agent A负责优化权限逻辑。
它增加了一条规则:
权限变化以后必须立即生效。
自己的测试全部通过。
与此同时,Agent B负责优化性能。
它给用户权限结果增加了:
5分钟缓存。
它的测试也完全正确。
单独看:
Agent A没有Bug。
Agent B也没有Bug。
但两个PR合并以后:
权限修改之后,缓存还可能继续保存旧结果5分钟。
系统最终行为变成:
“必须立即生效”的权限,被“允许缓存5分钟”的策略破坏了。
这类问题不一定有:
异常。
报错。
编译失败。
甚至功能测试都可能大部分正常。
真正出问题的是:
两个改动对同一份业务语义做出了不同假设。
四、所以多个PR真正危险的不是“改同一个文件”
我反而觉得:
改同一个文件没那么可怕。
因为Git很容易暴露问题。
真正危险的是:
不同文件,修改了同一个系统行为。
比如:
一个PR修改:
API默认值。
另一个PR修改:
Consumer处理逻辑。
一个PR修改:
数据库字段约束。
另一个PR修改:
写入逻辑。
一个PR调整:
Feature Flag。
另一个PR把相关旧逻辑删掉。
一个PR修改:
缓存TTL。
另一个PR假设数据实时一致。
这些地方文件可能相距非常远。
但业务意义上是同一个Change Surface。
所以多Agent并行以后,真正应该建立的不是:
File Conflict Map。
而是:
Semantic Dependency Map。
五、Merge Order为什么会影响最终结果?
假设有两个PR。
PR A修改公共接口,并保留旧字段兼容。
PR B基于旧接口重构Consumer,同时把旧字段处理逻辑删除。
如果先合A,再合B:
主干最终可能直接失去旧兼容路径。
如果先合B,再合A:
A的兼容逻辑可能又把一部分旧行为重新带回来。
虽然两个最终Git Diff可能非常接近,但:
合并过程中执行的测试、生成代码、配置更新,甚至后续PR重新基于主干的结果,都可能不同。
尤其当一个PR会:
重新生成SDK。
更新Lock File。
生成Schema。
重写配置。
调整Feature Flag
时,Merge Order就不只是Git顺序问题。
而是:
Integration State变化的问题。
所以多个Agent开PR以后,不能默认:
“谁先Review完谁先合。”
六、第二个PR合并以后,第一个PR的测试结论可能已经失效
这个点特别重要。
PR A自己的CI通过,只能证明:
PR A + 当时的Main
是正确的。
后来PR B先合进去了。
Main已经变了。
这时候PR A原来的测试结果其实已经过期。
因为真正准备进入主干的是:
PR A + 新Main
而不是:
PR A + 旧Main。
如果PR A和PR B存在潜在语义依赖,那么原来的绿色CI并不能继续证明:
组合状态安全。
所以多Agent并行开发以后,真正稳定的流程应该是:
每次主干发生关键变化后,待合并PR重新基于最新Main验证。
这也是Merge Queue存在价值的原因之一。
七、为什么“每个PR都重新Rebase”还不够?
Rebase可以解决一部分问题。
它至少能让:
当前PR基于最新主干重新生成。
但它主要解决的是:
代码基线。
不自动解决:
业务组合验证。
例如:
PR A重新Rebase以后。
能编译。
CI也过。
但CI里根本没有覆盖:
PR B新引入的某个行为组合。
所以:
Latest Main + Green CI
仍然不等于:
Composition Verified。
真正还需要确认:
哪些PR之间存在业务依赖。
哪些组合需要额外测试。
哪些修改会改变彼此的假设。
八、多个Agent同时工作前,最好先声明“谁依赖谁”
我现在越来越倾向在任务拆分阶段就先做:
PR Dependency。
比如三个Agent任务:
A:新增新字段。
B:Consumer使用新字段。
C:删除旧字段。
这三个任务不能简单理解成:
三个并行PR。
真正关系应该是:
A先提供兼容能力。
B完成迁移。
C最后清理。
如果强行并行,很容易出现:
C先合了。
B还没完成。
线上旧Consumer直接断。
所以:
并行执行,不代表并行合并。
Agent可以同时做。
但Integration Order仍然应该人为设计。
这点和跨仓库升级其实很像。
真正危险的不是执行速度慢。
而是:
所有任务都完成得很快,但进入系统的顺序错了。
九、哪些地方最容易发生Semantic Conflict?
我会特别注意下面几类:
公共DTO和Schema
一个Agent改字段结构,另一个Agent继续按旧结构假设。
Feature Flag
一个PR准备逐步启用,另一个PR已经把旧逻辑删除。
默认值
一个模块把默认值改成A,另一个模块仍然假设默认是B。
缓存
一个PR追求实时一致,另一个PR增加缓存。
权限
一个Agent扩大访问范围,另一个Agent收紧验证。
数据库Migration
一个PR增加兼容字段,另一个PR提前清理旧字段。
公共配置
两个Agent分别调整不同模块,却共同依赖同一个配置语义。
这些地方即使文件完全不同,也非常容易产生组合风险。
十、所以Review应该多问一个问题:这个PR依赖哪些假设?
以前Review可能主要看:
代码有没有Bug。
测试有没有覆盖。
现在多个Agent并行以后,我更愿意多问一句:
这个PR成立的前提是什么?
比如:
这个PR假设旧字段还存在。
这个PR假设缓存TTL是0。
这个PR假设Feature Flag默认关闭。
这个PR假设旧Consumer已经全部升级。
一旦把这些Assumption写出来,就更容易发现:
另一个PR是不是正在同时改变它。
这比单纯比较Diff更有价值。
十一、Merge Queue真正解决的是什么?
很多团队把Merge Queue理解成:
防止大家同时Merge。
其实更重要的是:
让PR在接近真实合并顺序的状态下重新验证。
比如:
PR A准备进队列。
系统把它放到最新Main上跑一遍。
如果PR B排在A前面,
那A最终验证的应该是:
Main + B + A
而不是几小时前:
旧Main + A
这样至少能减少:
CI绿了,但组合以后炸了
这种问题。
当然,Merge Queue本身也不是万能的。
如果测试根本没覆盖语义冲突,它依然可能放过去。
但它至少把:
合并顺序
纳入验证过程。
十二、我更推荐多Agent任务走“执行并行,集成串行”
这句话听起来好像降低效率。
其实不是。
Agent A、B、C完全可以同时:
分析。
写代码。
补测试。
准备PR。
真正进入Main的时候,再按照依赖顺序:
一个一个合。
每合一个:
重新验证下一个。
这样你仍然获得了Agent并发执行的速度。
但没有把:
系统集成
也变成毫无顺序的并发行为。
也就是:
Parallel Execution + Controlled Integration。
这是我现在更喜欢的方式。
十三、什么时候可以放心并行合并?
如果几个PR之间:
业务边界完全独立。
没有共享Contract。
没有公共Schema。
不影响同一份状态。
不依赖相同配置。
不存在共同运行路径。
那并行风险自然低很多。
例如:
一个PR改后台管理页面文案。
另一个PR修完全独立的离线报表。
它们的Composition Risk就比较小。
所以重点不是:
“多Agent一定不能并行。”
而是:
“并行之前先确认这些任务是不是真正独立。”
任务边界判断越准确,并行收益越高。
十四、一个主指标:Composition Validation Coverage
这篇我建议只留一个指标:
Composition Validation Coverage——组合验证覆盖率
可以简单理解为:
已经验证过的关键PR组合数量 ÷ 本次并行开发中识别出的关键组合数量
假设三个PR之间存在:
A+B
A+C
B+C
以及A+B+C
4种真正值得验证的组合。
当前只验证了:
A单独。
B单独。
C单独。
那组合验证覆盖率其实接近:
0%。
即使三个PR自己的CI全部是绿色。
这个指标的意义就是:
不再把“单PR验证”误认为“系统组合验证”。
十五、多个Agent同时开PR,我会怎么安排流程?
我更倾向于:
先拆任务 → 标出共享边界 → 标出PR依赖 → Agent并行执行 → PR单独验证 → 确定Merge Order → 基于最新主干重新验证 → 关键组合测试 → 合并
重点不在于增加流程。
而是提前回答:
哪些PR可以随便换顺序?
哪些PR必须A先于B?
哪些PR合并以后必须重新跑一次关键验证?
这样多Agent真正提升的是:
开发吞吐。
而不是:
把Integration Risk一起放大。
十六、ChatGPT、Codex在这里最适合做什么?
不要只让不同Agent各自完成任务。
还可以再加一个“集成视角”。
让ChatGPT、Codex帮助比较:
多个PR分别修改了哪些业务概念。
有没有共享Contract。
有没有共同配置。
有没有互相依赖的Feature Flag。
有没有一个PR改变了另一个PR的前提。
哪些合并顺序更安全。
也就是说,多Agent之后还需要一次:
Cross-PR Review。
不是Review某个PR写得好不好。
而是Review:
这些PR放在一起以后会发生什么。
十七、Plus和Pro怎么判断?
如果你平时主要让ChatGPT、Codex:
处理几个独立小任务。
PR规模不大。
大多数任务彼此无关。
偶尔做一次Cross-PR分析。
这种情况下,Plus通常已经够用。
如果你的工作已经是:
大型仓库。
多个Agent同时修改不同模块。
一天产生很多PR。
还要持续分析共享Contract、Merge Order、CI、组合测试和主干状态。
需要Codex在每次主干变化以后继续重跑验证、修复冲突,
这种高并发、多PR、长时间Agent Workflow已经成为日常,
那Pro会更适合。
真正的判断标准不是:
同时开几个Agent。
而是:
你是不是已经把多Agent并行开发变成了持续的工程生产流程。
最后
多个Agent同时开PR,为什么每个PR都正确,合并以后却可能出错?
因为:
单个PR验证的是局部正确性。
系统真正运行的是:
多个变化叠加以后的组合状态。
Git只能很好地发现:
文本冲突。
却不一定能发现:
Semantic Conflict。
所以多Agent并行以后,真正需要补的一层不是:
更多单PR测试。
而是:
Integration Order + Cross-PR Validation。
真正稳定的流程应该是:
Agent可以并行工作,但PR不能无脑并行进入系统。
先看依赖。
再定Merge Order。
每次主干变化后重新验证。
最后确认关键组合仍然成立。
当ChatGPT、Codex让并行开发速度越来越快以后,人真正需要守住的,也不只是:
每个Agent有没有把自己的任务做对。
而是: