长时 AI 编程会话质量下降并非模型能力问题,而是上下文管理失效:上下文窗口消耗过半后模型开始推翻早期决策,导致修复从未损坏的代码。
这个问题本周出现在中文 AI 开发者社区,发帖的人每天用 Claude Code 做七八个小时的 vibe coding。帖子内容足够实用,值得给英文读者拆解一番,因为它描述的核心问题大多数人其实都遇到过,只不过把锅赖错了地方。
失败模式是这样的:你的 session 进行了两个小时,context window 已经用到 60%,模型开始做出和一小时前它帮你做的决策相矛盾的改动。你花了 40 分钟调试一个根本没坏的东西。你加了更多指令。模型道了歉,然后用略有不同的方式再犯一遍。你没有写出糟糕的 prompt。你没有选错模型。你只是用完了可用的 context,而且直到问题已经造成才察觉。
这就是本文的核心论点:长时间 AI coding session 中大部分质量下降是 context 管理失败,而非模型能力失败,但大多数工作流都把它当成后者来处理。
原帖开篇给了一条听起来像是在说信任 AI 的建议:不要立即修补它生成的代码。如果错误太多,就重写 prompt,用 Claude Code 按两下 Escape 或 git revert 回滚,然后从头重试。
但这跟信任没关系。这是在说 context 的经济账。每一次在糟糕的生成结果之后做来回修正都要消耗 tokens。更重要的是,它会在 context window 里堆积噪声:模型现在必须在包含了错误版本、你的修正、它的确认、以及新版本的对话历史上做推理。这种积累会以很难归因的方式降解后续的生成质量。那个「直到突然不行之前一直都挺好」的 session?原因往往是两小时前的十轮小修补交互。
一次搞定的原则迫使你把 context 预算花在干净的尝试上,而不是修修补补上。这不是信心游戏,是算术。
原文描述的工作流值得仔细引述。在做重大改动之前,从业者会让 AI 把计划写到一个文档里。然后由一个独立的 agent 审查该文档。新的 session 再据此实现。
如果你没有被它坑过,这个低效之处很容易被忽略。当模型在同一个 session 里既做规划又做实现时,规划的 tokens 在实现开始时就已经消失了。模型是从它压缩后的内部表征来工作的,而不是从一个权威的外部记录。当实现中途出了问题,它是从 context 里重新构建意图,而不是在读规格文档。
把计划写到文件里改变了认识论的局面。计划现在是仓库里的一个事实,而不是 context 里的一段记忆。新的 session 可以冷启动读取它并据此实现,而不需要携带产生这个计划的探索性推理。这在实践中有实质性的差异。实现 session 从一个狭窄、高信号的 context window 开始,而不是从一个宽泛、嘈杂的 window 开始。
一位评论者反驳说:你不应该需要手动触发这个,它应该在你的 agent 配置里自动化,让计划-审查循环默认发生。这是一个合理的工程观点。但手动版本仍然比没有版本好,而且在你能够把它自动化好之前,理解它为什么有效是必要的。
这是原帖里最具体的可操作建议,而且数字很重要:当 context window 达到大约 50% 容量时,生成一个交接文档并启动一个新的 session。
这位从业者交接文档不用固定模板。他们直接告诉模型:我现在要开始一个新 session,把下一个 session 需要知道的一切都写下来。指令就是这么简单。
评论里提到的 Matt Pocock,据报保持 context 在 15% 以下。这个标准很激进,但方向是对的。降解曲线不是线性的。处于 80% context 的模型不会只比 40% 的模型稍微差一点点。这种遗忘是不均匀的:最近的 tokens 权重更高,但早期 session 里做出的具体决策——那些设定了架构约束、变量命名和 API 形状的决策——恰恰正是被压缩和丢失的东西。
持反对意见的评论者认为完整的原始 session 比全新 window 有更好的连贯性,他描述的是一个真实的效应。交接中确实有损失。但那种损失是可预测且可管理的。而降解的长 context 的损失是不可预测且隐蔽的。你可以写好一份交接文档。你没法给一个已经悄悄开始自相矛盾的模型写好补丁。
关于 claude.md 和 agent.md 文件的建议没有第一眼看起来那么显而易见。按目录拆分它们——前端配置放 /frontend/claude.md,后端配置放 /backend/claude.md——主要不是为了组织。是为了防止模型在每个 session 里加载无关的指令。
如果你的 system prompt 是 2000 tokens 的混合前后端 context,那每次只做后端任务时就有 1000 tokens 烧在了不可能有帮助且可能造成干扰的指令上。拆分文件意味着模型在后端目录工作时加载后端 context,忽略其余部分。你用于后端工作的可用 context window 因此多了 1000 tokens。
这还会累积。原帖指出,每一项实践——一次搞定尝试、书面计划、交接文档、分层配置——归根结底都是 context 管理实践。一次搞定生成保持 window 干净。书面计划把推理从 context 移入持久化存储。交接在降解叠加之前重置 window。分层配置降低每个 session 的固定开销。它们是针对同一个变量的不同干预手段。
让我把失败模式具体化,因为原帖在这个点上相当抽象。
你在构建一个 API。Session 早期你和模型商定了一个错误响应格式:{error: string, code: number}。两小时后,context 在 70%,模型生成了一个返回 {message: string, status: number} 的新端点。你没有立刻注意到。你基于那个端点又构建了三个东西。一小时后你有一个排不出问题的类型错误。你在错误的文件里花了时间。你最终找到了它。修复很简单。但定位问题并不简单。
这是个小小的例子。在更大的 session 里,模型可能会开始忽略你在早期设定的架构约束,或者重新引入你明确拒绝过的依赖,或者使用一个与最近没读过的文件中设定的命名规范冲突的命名规范。每一项都是表现为模型质量问题的 context 管理失败。
令人沮丧的是,当你指出错误时模型会同意你的看法。它不是糊涂了。它只是在做后面的决策时没有把早期的决定放在 active context 里。
如果你每天用这些工具交付代码,以下是精简版本:
优先回滚重试,而不是原地修补。修复的 context 代价通常超过重新生成的代价。
在重大改动之前把计划写到文件里。用一个独立的 session 或 agent 来审查。从文件实现,而不是从记忆实现。
观察你的 context 计量器。选一个阈值,50% 是合理的,15% 激进但可能正确,当你达到它时生成一个交接文档。
按相关目录拆分配置文件。每一点无关的固定 context 都是你无法使用的 working context。
当模型开始做出感觉不对的决策时,在你开始质疑 prompt 之前,先检查你上次重置 context 是什么时候。
这些道理在吃过苦头之后都不会觉得反直觉。问题是你要损失多少个小时才能养成这个习惯。
你在开始新 session 之前实际使用的阈值是多少?你有没有找到一种交接格式,能可靠地保留最重要的决策?