配置文件里有两个函数,都写着 timeout = 30。你让编程智能体把生产环境的超时提到 60。结果取决于你问的是哪个智能体:要么编辑被拒绝,直到它补充更多上下文;要么文件里第一个 timeout = 30——也就是开发环境那个——被改掉了,补丁干净利落地应用成功。
![]()
决定这个结果的是编辑协议:智能体用什么格式描述一次改动,以及你机器上负责应用改动的代码怎么处理它。Claude Code、Codex 和 Aider 各用一套,它们的文档和源码写明了文本对不上时会发生什么。
下面这个文件贯穿所有案例:
def load_dev():
timeout = 30
retries = 3
def load_prod():
timeout = 30
retries = 5
三种"改这一行"的说法
Claude Code 走精确字符串替换。Edit 工具接收 old_string 和 new_string,文档原话是"不使用正则或模糊匹配"。三道检查必须通过:Claude 读过这个文件;old_string 与原文完全一致;除非设置 replace_all: true,否则它只能出现一次。读取规则对新模型更宽松——同一页文档说,Claude Opus 4.6、Claude Haiku 4.5 及更早的模型始终要求先读文件,而 Claude Code v2.1.208 或更高版本上的新模型,在 Read 工具可用且读取不需要权限提示时,可以跳过这一步。
Codex 走补丁信封。OpenAI 的 Codex Prompting Guide 建议单文件编辑使用 apply_patch,称模型"已被训练得擅长这种 diff 格式",并强烈推荐使用 OpenAI 自己的实现。该实现以开源形式放在 codex-rs/apply-patch crate 中。它的标记包括 *** Begin Patch、*** Add File:、*** Delete File:、*** Update File:、*** Move to:、*** End of File、@@ 和 *** End Patch。改动行以 - 或 + 开头,上下文行以一个空格开头,不带行号。
Aider 让你自己选格式。它的编辑格式包括 whole(模型返回整个文件)、diff(SEARCH/REPLACE 块)、diff-fenced(同样的块,路径写在围栏内,主要面向 Gemini 模型)、udiff(简化版统一 diff),以及 architect 模式下的两个编辑器变体。
Aider 还公布了模型把格式写对的频率。它的 polyglot 排行榜最后更新于 2025 年 11 月 20 日,在 225 道练习的通过率旁边列了一栏"Correct edit format"。gpt-5(high)以 88.0% 的正确率居首,使用 diff 格式时编辑格式正确率为 91.6%。即便是榜首模型,某些情况下也会发出格式错误的编辑,应用器必须逐一捕获。
重复行:一个拒绝,两个挑第一个
Claude Code 的唯一性检查会失败,因为 timeout = 30 出现了两次。按文档说法,Claude 随后"要么提供一个更长的字符串,带上足够的周边上下文来锁定其中一处,要么设置 replace_all: true 把它们全部替换"。有效的重试会带上函数头:old_string 为 "def load_prod():\n timeout = 30",new_string 为 "def load_prod():\n timeout = 60",replace_all: false。
Codex 的应用器不检查唯一性。在 file_update.rs 中,每个块的旧行从当前位置向前搜索,seek_sequence.rs 返回第一个匹配的窗口,不再看后面的。用上面那个只有裸 @@ 的补丁,第一个 timeout = 30 位于 load_dev 中,被改的就是那一行。
锚点能修正它。 后面写成 def load_prod():,改动就落在生产函数里。
Aider 的 diff 格式在这里与 Codex 行为一致。在 editblock_coder.py 中,perfect_replace 替换第一个匹配的行块然后返回。有一条路径更严格:当 SEARCH 块用 ... 省略行时,如果该片段出现不止一次,Aider 会拒绝这个块。
公平地说,模型很少只发一行裸文本。补丁里的上下文行和多行 SEARCH 块通常已经让匹配唯一。差别只在它们没做到的时候显现:Claude Code 停下来,另外两个在第一个匹配处应用。
过期上下文:模型看过之后文件变了
当你自己编辑文件、格式化工具跑过、或第二个智能体碰过它,模型手里的文件副本就过期了。
Claude Code 对这种情况有明文规则。自 v2.1.208 起,如果文件在 Claude 最后一次读取后发生变化,但 old_string 仍"精确且无歧义"地匹配当前内容,且读取文件不需要权限提示,编辑会应用,结果中会注明文件还带有其他改动,让 Claude 在依赖周边代码的编辑前重新读取。其他情况,比如 old_string 已过期,Claude 会先重读文件再编辑。在 v2.1.208 之前,它会拒绝任何针对读取后已在磁盘上变化的文件的编辑。
Codex 会返回一条模型能据此行动的错误消息。如果 @@ 行找不到,file_update.rs 返回 Failed to find context;如果旧行找不到,它返回 Failed to find expected lines,后面跟着它要找的那些行。API 指南为自建执行框架描述了同样的循环:报告 status: "failed" 并附一句简短的人类可读消息。
Aider 回复 SearchReplaceNoExactMatch,说明这个 SEARCH 块未能精确匹配文件中的行,并提醒"SEARCH 部分必须精确匹配一个已存在的行块,包括所有空白、注释、缩进、docstring 等"。如果持续失配,它的故障排查页建议改用 --edit-format whole 等做法。
whole 格式不可能匹配失败,因为根本没有匹配这回事。但如果模型手里的文件副本是旧的,重写会把旧版本盖回此后发生的所有改动之上,而且不报任何错误。另一个风险是省略。编辑格式页面说 udiff 主要与 GPT-4 Turbo 搭配使用,因为它减少了该模型用"原始代码在此"之类注释省略代码的习惯。在 Aider 关于统一 diff 的文章中,把 GPT-4 Turbo 从 SEARCH/REPLACE 换成 udiff,其懒惰基准分数从 20% 提升到 61%。
空白漂移:严格、宽容与居中
模型会重新敲一遍它想替换的文本,重敲就会漂移。一个制表符回来变成四个空格,行尾空白消失,直引号变成弯引号。
Claude Code 是刻意严格的。文档说"一个字符的空白或缩进差异就足以失配"。失配时,编辑不会应用。
Codex 的应用器是三者中最宽容的。seek_sequence 按其注释所说做四轮"逐级降低严格度"的尝试:精确匹配;忽略行尾空白;两端裁剪;把破折号、引号等常见 Unicode 标点规范化为 ASCII。旧行里的缩进漂移仍能找到目标。代价在没有任何精确匹配时显现:更宽松的一轮可能在更多位置匹配,而它找到的第一个窗口获胜。
Aider 居中。它先试精确匹配,再试容忍缺失前导空白的匹配,然后去掉多余的首个空行重试。同一个文件里存在一个模糊编辑距离匹配器,但调用前有一个裸 return,所以它永远不会执行。
宽容是有回报的。同一篇统一 diff 文章报告,关闭灵活补丁后"编辑错误增加了 9 倍"。
一种不关心字节怎么来的撤销
上面每种失败都有一个安静的版本:编辑应用到了错误的位置,或叠加在过期的假设上,而智能体报告成功。你在审查时发现它,然后想把那一轮收回来。
每个工具都有自己的答案。Claude Code 的检查点在每次提示前捕获你的代码,/rewind 可恢复代码、对话或两者。文档把边界说得很清楚:"检查点不追踪由 Bash 命令修改的文件",大多数子智能体的编辑也不会被恢复。Aider 把每次编辑以描述性消息提交到 git,/undo 丢弃最后一次改动。各自只覆盖自己智能体的编辑,别的一概不管。
如果 Claude Code 反复失配,先检查文件里有没有混用的制表符和空格、有没有不可见字符,再怪模型。如果你用 Aider 的 whole 格式,智能体工作期间别让其他写入者碰那个文件,因为基于旧副本的重写会无错误地应用。无论用哪种协议,都在编辑路径之外保留一份逐轮记录:普通提交、Aider 的自动提交,或逐轮快照。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.