CLAUDE.md 为何只增不减:247,694 条指令追踪出「灾难性记忆」,注释砍掉 99.3% 冗余

Why Does CLAUDE.md Keep Growing? Catastrophic Remembering in Agentic Coding

Kushal Chakrabarti

cs.AI, cs.LG, cs.SE

2026-08-12

追踪 247,694 条指令生命周期发现,CLAUDE.md 因「灾难性记忆」只增不减,文件生命周期内涨 226%;给指令加注释能削减 99.3% 冗余,并把真实指令遵循提升 23.1%。

这篇在解决什么

但凡用过 Claude Code、Cursor 的人都知道那个文件:CLAUDE.md、AGENTS.md、copilot-instructions.md。它告诉 agent 项目的红线、风格、该怎么干活。问题是这个文件只会越来越长。一个仓库跑下来,指令数平均涨 226%,几乎不删。

不删不是懒。删一条指令前,得先知道它当初为什么被加进来,它在防哪个 bug、哪次失败。这条「为什么」一旦在多次提交里被磨掉,想安全删它就得把这条指令和其余几十条指令的所有子集组合逐一跑一遍,看会不会让某项检查重新挂掉。这是个 O(2^|D|) 的活,|D| 是当前指令数。删一条要遍历幂集,加一条只要敲几个字。在「删的代价远大于加」的不对称下,只增不减几乎是唯一稳态。论文把它叫「灾难性记忆」(catastrophic remembering),正好是持续学习里「灾难性遗忘」的对偶:那边梯度学习覆盖了该留的,这边维护者留住了该覆盖的,失败原因同源,能让更新合法的那条信息没了。

方法

论文先做大尺度测量,再设计受控实验隔离机制,最后给对策。

测量。 作者把 1,867 个 GitHub 仓库里的 CLAUDE.md、AGENTS.md、copilot-instructions.md 逐提交拆成单条指令,跨版本匹配,得到 247,694 条指令的生命周期和 28,426 次删除。这套匹配在 50 个人工标注的迁移上做到 1.000 精度、0.933 召回。关键指标是「删除风险率」(deletion hazard),一条指令在某年龄被删的概率。

判别机制。 三个候选解释预测不同方向。若是指令过时(staleness),越老越该删,风险率该随年龄上升;若是脆弱指令早夭(fragility),风险率会被组成效应压低;若是「记不住为什么」(imperfect recall),风险率该随年龄下降,而且这个机制独有一项预测:风险率还该随「碰过这个文件的人数」下降,因为人越多,当初的理据被稀释得越快。

对策:prompt 注释。 直接借软件工程的老办法,代码注释记的是「为什么」而非「做什么」。给每条指令配一段注释,写清它防的是哪次失败、当时的假设、结果如何(含复发次数)。注释只给下一位维护者看,送到执行器之前会被 harness 剥掉。记一条注释 O(1),事后重建理据 O(2^|D|),注释就是把那份廉价品存下来。

怎么测对策有没有用。 难点在于真实 prompt 的「最优大小」不可知,没法算冗余了多少。作者反用 IFEval(invert IFEval):把每道题的原始指令藏起来当作已知的最小覆盖 D⋆,只把验证器留作隐藏约束集,再用强模型把指令压缩成一句模糊任务目标。维护者只能看到「做了还是没做」的噪声反馈,逐轮重学这套指令。这样冗余量(|Dt|/|D⋆|-1)首次变得可测。

结果

观测侧的数据很硬:

指标数值
文件生命周期内指令数增长+226%(均值)
每次提交净增指令+4.9 条(剔除大重写)
删除风险率随年龄-0.032/提交(95% CI [-0.047, -0.019])
多作者 × 年龄交互项β = -0.021(z = -11.7)
指令消亡中属整体重写或迁移77.3%

76.8% 的指令死亡发生在一次性把文件推平的那次提交里:删一条要理由,删全部不要理由。更说明问题的是重写之后:文件掉到原来的 59.5%,10 次提交内就涨回 91.5%,而且重写后涨得更快(4.9%/提交对 4.1%/提交)。重写重置了大小,没重置增长率,所以作者叫它「棘轮」(ratchet)。

风险率随年龄下降,直接证伪「指令过时」假说,它预测的是上升。用 gamma frailty 模型把「脆弱指令早夭」这种组成效应尽可能吸掉(最强形式按相同指令文本分层,吸走 30.8%),斜率仍然停在 -0.0355。而「碰的人越多、越不容易删」这一条,三个假说里只有「记不住为什么」能解释。

对策侧,反用 IFEval 的受控实验分三组:不给注释、给注释形状的噪声、给有信息的注释。15 轮下,冗余从无注释的 +60.4% 降到有注释的 -5.8%(66.2 个百分点),约束满足率持平。拉到 51 轮,无注释组冗余飙到 +211.3%,有注释组停在 +1.4%,等于削掉了 99.3% 的冗余。消融显示注释必须带上「结果」(尤其复发次数):只写尝试经过、不带结果的叙述组反而最差(+70.0%),把一个没验证过的前提交给了继任者去续写,丢掉复发次数这一项字段就损失了 37% 的削减量。

真实 prompt 上,作者同样反用 WildIFEval:给维护者塞进若干条来自别处题目的噪声指令。16 条噪声指令让原本就在 prompt 里的真指令损失 24.1 个百分点的遵循率。加注释把满足率从 50.4% 拉到 62.0%,相对增益 23.1%。

为什么重要

这事直接可落地。给 CLAUDE.md 里的每条指令配一行注释,写清它防的是哪次失败、假设、结果,送到模型前剥掉,和写代码注释一个道理。还有一个反直觉趋势:维护者越强(这里换成更强的 agent 维护者),棘轮拧得越狠,无注释组的冗余从 +67.7% 飙到 +571.9%。agent 越能干,这套注释纪律反而越重要,不是越不需要。

对做 coding agent 的人,这是一个产品级建议:给 prompt 加一套注释语法,让理据能跨维护者传递。作者的原型只是原型。

局限与存疑

作者自己把边界交代得很清楚。受控实验跑在「保留几乎免费」的区间:最优覆盖只有 2-3 条指令,对照真实文件中位数 39 条;只跑 15 步;维护者和执行器是同一个模型;约束都是机器可验证的英文约束。WildIFEval 那一组把噪声指令直接种进 benchmark prompt,并非在真实文件里长出来,它测的是「冗余值多少钱、注释能赎回多少」,没测真实规模下棘轮会不会持续。

更该记的是评判器问题。WildIFEVal 的约束是自然语言、没有代码验证器,所有满足率都靠一个看不到 arm 标签的 LLM judge 打分。作者用第二个 judge 重新判了全部 6,336 条,标准能复现,但效应量两组不一致:第二判官量出 7.8 个百分点,对照正文引的 11.6 个百分点,95% CI [-1.9, +9.6] 把零包进去了。两个 judge 都不是真值,所以这里测的是「能否复现」,不是「准不准」。

语料只覆盖公开 GitHub 上的三类文件,没统计语言分布,结论不保证对非英文指令成立;系统提示、agent skill 文件会不会同样只增不减,留作开放问题。

术语

原文与代码

社区讨论

相关论文

全部论文解读