为什么跨会话的长任务会断片

长任务必然耗尽上下文,靠初始化与持久化工件让新会话三分钟接班。

Module C · 第 4 讲

立靶:第二个会话的 Agent 不知道自己昨天干了什么

设想一个跨三天的任务:把一批学习笔记重写成公开课讲义。第一天 Agent 干得漂亮——定了讲义体结构、选了某种构建脚本方案、跑通了第一讲。你关掉会话。

第二天打开新会话,Agent 看到的是一堆半成品文件。它不知道:第一讲为什么这么分段(决策历史丢了)、构建脚本为什么不用第三方库(设计原因丢了)、已经做到第几讲、下一件该干什么(工作进度丢了)。

于是它开始「合理推测」。它推测的方向往往和昨天的自己不一致:重新发明了一套分段逻辑、引入了一个三方依赖、把已经做完的讲又改了一遍。这就是断片(amnesia)

断片不是模型笨,而是上下文窗口的客观限制。窗口再大也有上限,而长任务的复杂度会无情地把它填满——决策、代码、日志、报错、对话,累加到某个点,最早的关键信息要么被挤出,要么被压缩成失真的摘要。指望「等窗口更大就好了」是幻觉:任务复杂度永远会追上窗口容量。

更隐蔽的是断片的前奏——上下文焦虑。当上下文逼近上限,Agent 的行为会肉眼可见地劣化,像一个快下班还没干完活的人:跳过验证(「应该没问题,直接标完成」)、选次优但更快的方案、草草收尾。这叫上下文焦虑(context anxiety)。它危险在于:劣化发生在 Agent 仍然「自信」的时候,输出看起来完整,实则偷工。

核心矛盾是:单个会话的容量有限,但任务的生命周期远超单个会话。解法分两步——先认清两种延续策略,再把「怎么开新会话」当成一个独立工程问题来设计。

框架一:压缩 vs 重置——两种跨越会话的策略

维度压缩(Compaction)重置(Reset)
发生位置同一会话内开一个全新会话
机制把已有上下文摘要成更短的版本,继续干丢弃旧上下文,靠持久化工件重建状态
保留什么保留「做了什么」的结论与产出靠文件重建「为什么这么做」+「做到哪」
丢什么丢「为什么」——决策推理被摘要抹平丢会话内的临时记忆(但这些本就该落盘)
适用短任务、单次会话内的局部瘦身长任务、跨天跨人接手
风险摘要失真,越压越偏,错误被固化工件不全则重建失败

关键判断:压缩省事但有上限。每压一次都损失信息,多轮压缩后,Agent 是在「摘要的摘要」上工作,原始决策的「为什么」早被磨平。对真正的长任务,重置往往必不可少——主动丢弃脏掉的上下文,从干净的持久化工件重新加载,反而比带着越来越失真的摘要硬撑更可靠。但重置有个前提:重建状态的成本必须足够低。如果新会话要花半小时考古才能接上,没人会愿意重置。

框架二:四层持久化——把状态从 LLM 记忆迁到确定性文件

断片的本质是「状态存在了不可靠的 LLM 记忆里」。解法是把状态外置到磁盘上确定性的文件。四类工件各司其职:

工件回答的问题本项目对应
进度PROGRESS.md / STATUS.md做到哪了?下一步干什么?STATUS.md 一句话状态 + 下次入口;M1/PROGRESS.md active_feature/blockers
决策DECISIONS.md为什么这么选?哪些路否决了?features.jsonrelated/affected/out_of_scope 三段关联
检查点Git commit代码处于哪个已知良好状态?feat/{feature_id} 分支 + 规范化 commit message
初始化启动流程文档 + 自检脚本怎么从零把环境跑起来、接上手?M1/AGENTS.md 接班说明 + M1/init.sh 环境自检

注意决策日志和进度文件是两回事。进度回答「到哪了」,决策回答「为什么」。压缩策略丢的恰恰是后者——所以即便你只做压缩,也该把关键决策单独落盘。

框架三:初始化是独立阶段,不是实现的附属

新手常把「配环境」和「写功能」混在第一个会话里干。这是错的,因为两者的优化目标根本不同:实现阶段优化「功能正确」,初始化阶段优化「任何一个未来会话都能低成本接手」。混在一起,初始化就会被功能压力裹挟着做得潦草——依赖没锁版本、测试框架没验证、没人写下「怎么启动」。

所以第一个会话应该是纯初始化:不写业务功能,只干四件事——配好依赖、验证测试/构建框架能跑、写下启动契约、留好进度文件的空壳。衡量初始化是否完成,用一张启动就绪清单

就绪项判据本项目实现
能启动一条命令把环境拉起、依赖齐全bash M1/init.sh 六段自检,FAIL=0 即绿灯
能测试测试/构建框架已验证可跑init.sh 第 6 段「端到端冒烟」:跑 build 并检查产物存在
能看进度有文件回答「做到哪了」STATUS.md + M1/PROGRESS.md 已就位
能接手下一步有明确的「选下一件事」算法AGENTS.md 的「选 feature 算法」+「Session 启动 5 步」

目标是一个可量化的数字:新会话重建成本 < 3 分钟。 超过这个,重置就会变成负担,团队(和未来的你)会本能地逃避重置、转而硬撑压缩,最后回到断片。热启动还有个加速器:项目模板——把这套结构做成可复用脚手架,新项目第一个会话直接套,初始化从「现攒」变「填空」。

case:本项目的「三件套」如何把重置成本压到三分钟内

入口唯一且有序。 CLAUDE.md 写死了入会顺序:先读 STATUS.md,再读三件套文档,再跑 init.sh。新会话不靠任何人口头讲背景。

STATUS.md 是「一句话状态 + 下次入口」。 它不堆历史,只回答两个问题:现在是什么状态、下一件该干什么。新会话读完这一句,方向就定了。

AGENTS.md 是「接班说明」,把模糊的『开始干活』拆成确定步骤:① cat M1/PROGRESS.md 看 active_feature/blockers/next_candidates ② 读 STATUS.mdbash M1/init.sh 环境全绿才开工 ④ 按「选 feature 算法」挑下一件事 ⑤ 动手 → 收尾更新 PROGRESS+STATUS。它甚至把「选哪个 feature」这种最容易拍脑袋的决策也算法化了:优先 failing 且阻塞已清的最低编号 feature;同一切片做完再进下一切片,不跳。

init.sh 是「能启动 + 能测试」的确定性证据。 六段统一报告,刻意不用 set -e——一路跑到底,把所有问题一次性报出来,最后给 FAIL=0 绿灯。区分 WARN(不阻塞)和 FAIL(阻塞)。新会话跑一次就知道环境能不能开工。

三件套合起来,新会话接班动作是:读一句话状态(30 秒)→ 按 5 步走(含一次自检脚本,1-2 分钟)→ 拿到下一件确定的事。重置成本被压进三分钟,于是「重置」从一件痛苦的事,变成一个随时可做的常规操作。

可操作做法:给你的长任务装上抗断片底座

  1. 第一个会话只做初始化,不碰业务功能。 用「启动就绪清单」四项验收。
  2. 写一个 init.sh 式自检脚本,不用 set -e 一次跑完所有检查,统一报告 FAIL/WARN。
  3. 进度和决策分开落盘。 STATUS/PROGRESS 回答「到哪了」;DECISIONS(或 features 三段字段)回答「为什么」。
  4. 写一份 AGENTS.md 式接班说明,把『选下一件事』算法化。
  5. 每个会话收尾强制更新 STATUS + 进度文件。 这是把「会话记忆」兑换成「下个会话能读的工件」的唯一时机。
  6. 优先重置而非无限压缩。 当上下文开始焦虑,不要硬撑——主动重置,靠工件重建。前提是重建成本已压到三分钟内。
  7. 把这套结构沉淀成项目模板。

收口

长任务断片不是要不要发生的问题,而是什么时候发生——上下文窗口的物理上限决定了它必然到来。

真正该优化的不是「让单个会话活得更久」,而是「让任何一个新会话三分钟内满血接手」。能被随时丢弃重建的会话,才是不会断片的会话。