续跑护栏 · 长任务可校验交接
核心命题:交接失效的根因不是「没写文档」,而是「文档的内容由模型自述,而自述不可证伪」。
现有绝大多数交接方案(HANDOFF.md、/compact、记忆库)都是同一条路径:让模型把自己说过的话压缩一遍。
问题在于,压缩这个动作本身由那个正在衰退的上下文完成——它忘了的东西,不会出现在压缩结果里;
它「以为做完了」的事,会被写成已完成。你拿到的是一份无法证伪的自述。
本技能把交接拆成三层,其中只有一层交给模型:
| 层 | 谁写 | 能不能被证伪 |
|---|---|---|
| 客观层 | 脚本,从 git status/diff/log 与文件系统真实抽取 |
能,磁盘不会说谎 |
| 声称层 | 人或模型,写在 .resume/task.yaml |
不能直接证伪 |
| 交叉校验层 | 脚本,拿声称去撞客观 | 撞不上的就是问题 |
一、为什么是这个问题(外部证据)
四类互不相关的来源指向同一处:
- ICONIQ Capital《2026 State of AI: The Builder's Economy》(N=277 构建者):内部 Agent 最常见的故障模式里,
多步骤工作流分解失败占 26%,排第一;缺乏上下文或记忆 24%,排第二;幻觉输出 21%;错误推理 19%;工具/API 误用仅 8%。
→ 头号故障不是模型不会做,是做到一半接不上。 - Twilio 2026 Customer Insights(7,652 名消费者 + 660 名企业决策者,18 国):
70% 的亚太消费者曾因 AI 不掌握上下文而放弃一次服务交互,而 84% 的企业以为自己的 Agent 认得回头客;
65% 的消费者在转人工之后仍然要把信息重讲一遍。 - VB Pulse 2026 年 7 月(101 家百人以上企业):68% 的企业曾把一次「自信但错误」的 Agent 回答追溯到缺失或不一致的业务上下文,
且重复发生比例从 6 月的 31% 升到 37%——在上升,不是下降。 - 一线行为观察(Neodrop 2026-07-08~15 公开讨论扫描):「session limit hit,all that work remains incomplete」
是当周 workflow 类帖子中互动最高的一条;同批还有「cross-agent resume lost the whole context window」。
→ 用户自发在造 workaround:memory 文件、开新会话、review-first 流程。
补充参照:Composio 2026 Agent 报告称 97% 的高管部署过 Agent,但只有 12% 走到生产规模;
艾媒咨询 2026 中国用户调研中「灾难性遗忘」以 42.62% 位列大模型主要缺陷第三。
二、五条铁律
- 客观层不由模型写。 完成了什么、改了哪些文件、当前 HEAD 是什么——全部由脚本从磁盘读取。
模型只写「磁盘上看不出来的东西」:目标、理由、冻结决策、否决原因、下一步。 - 声称完成必须带证据。
done里的每一条都要给evidence指向一个真实路径。
路径不存在 = 幽灵完成(R1);给不出路径 = 无法判定,标 W1 待核,绝不替它判成通过。 - 决策要冻结,且冻结必须可机器校验。 光写「用 SQLite」没用——下一轮会话看不见你的理由。
必须配guard:contains(产物里必须出现什么)+forbids(不许出现什么),脚本才能判。 - 否决过的方案要留痕。 踩过的坑不写成
banned,下一轮一定会再踩一次(R3)。
这是长任务里最贵的一类返工:它不是做错,是重做已经否决过的错。 - 续跑先校验,校验不过不许开工。
resume命令有致命项就退出码 1。
让新会话在动手之前知道自己跑偏了,而不是改完三个文件才发现。
三、怎么用
# 0. 初始化(在项目根目录)
python3 scripts/resume_guard.py init --dir . --name "订单存储改造"
# 1. 填写 .resume/task.yaml:done / todo / frozen / banned / accept
# 2. 抓客观层(每次写完一段就跑一次)
python3 scripts/resume_guard.py capture --dir .
# 3. 交叉校验
python3 scripts/resume_guard.py check --dir . # 退出码 1 = 有致命项
# 4. 生成交接单
python3 scripts/resume_guard.py pack --dir . # -> HANDOFF.md + .resume/handoff.json
# 5. 新会话开工前(自动重抓客观层再校验)
python3 scripts/resume_guard.py resume --dir . # 退出码 1 = 不许开工
状态档写法(.resume/task.yaml)
task: 订单服务本地存储层改造
goal: 把订单存储从内存字典换成落盘 SQLite,单机部署,不引入外部中间件。
done:
- what: 实现 SQLite 存储层
evidence: src/store.py # 必须真实存在,脚本会校验
todo:
- what: 补 CI 里的单测步骤
next: 新建 .github/workflows/test.yml,加一步 pytest -q
frozen: # 跨会话不许被推翻
- decision: 用 sqlite3,不引入 Postgres
reason: 单机部署,运维成本必须为零
guard:
contains: ["sqlite3"] # 产物里必须有,否则 R4
forbids: ["psycopg", "postgresql://"] # 出现即 R2
banned: # 踩过的坑
- approach: 引入 Redis 做缓存
reason: 单机场景收益远小于运维成本
forbids: ["redis", "ioredis"] # 出现即 R3
accept:
- criterion: 重启进程后订单数据仍在
check: "python3 -m pytest -q tests/test_store.py"
什么时候 capture
| 时机 | 动作 |
|---|---|
| 上下文用到 60%~70% | 立即 capture + pack,不要等到被截断 |
| 每完成一个可独立验证的小块 | capture |
| 切换工具/模型/交接给人之前 | capture + pack |
| 新会话开工第一件事 | resume(它会自动重抓客观层) |
四、校验规则(三级结论)
R 致命 — 不许开工,退出码 1
| 编号 | 规则 | 判据 |
|---|---|---|
| R1 | 幽灵完成 | done.evidence 指向的路径在磁盘上不存在 |
| R2 | 冻结决策被违反 | frozen.guard.forbids 中的串出现在扫描范围内 |
| R3 | 重复踩已否决方案 | banned.forbids 中的串出现在扫描范围内 |
| R4 | 冻结决策未落地 | frozen.guard.contains 指定的串在扫描范围内找不到 |
W 待核 — 必须人工确认,脚本不替你判
| 编号 | 规则 | 判据 |
|---|---|---|
| W1 | 无据声称完成 | done 条目没有 evidence 字段 |
| W2 | 快照已过期 | 客观层快照时的 HEAD 与当前 HEAD 不一致 |
| W4 | 声称完成但无改动痕迹 | evidence 文件存在,但不在本次 git 改动集合内 |
N 提示 — 不阻塞,但会提高回归概率
| 编号 | 规则 | 判据 |
|---|---|---|
| N1 | 没有冻结任何决策 | frozen 为空 |
| N2 | 没有验收标准 | accept 为空 |
| N3 | 待办缺少下一步 | todo 条目没有 next 字段 |
| N4 | 静默扩面 | 有改动文件未被任何 done.evidence 引用 |
> 筛子不是法官。 所有规则只报告「撞不上」的事实,不判断谁对谁错。
> 撞不上可能是真错了,也可能只是你的 guard 写得不对——这两件事脚本分不清,由你判。
五、与相邻方案的分工
| 你需要什么 | 用什么 |
|---|---|
| 记住用户是谁、偏好是什么(长期、跨任务) | 记忆/偏好类技能 |
| 把一份长对话压缩成一段摘要(单次、事后) | /compact 或对话压缩工具 |
| 记住这个任务做到哪、哪些决策锁死了(短期、进行中) | 本技能 |
| 判断产出内容对不对(事实、数据、引用) | 事实/数据核查类技能 |
本技能与它们是互补关系,不替代。尤其注意:本技能不联网、不判事实真伪,
它只回答一个结构性问题——「上一轮说的话,和磁盘上的状态,对不对得上」。
六、约束与已知边界
- 只做结构级与文件级校验,不判断外部事实真伪,
contains/forbids的命中只是字符串匹配。 - 无 git 时降级为文件系统 mtime 扫描,「改动文件」= 最近修改的 N 个文件,精度低于 git 模式,R1 之外的判定会偏弱。
- 扫描范围默认排除
.resume/与HANDOFF.md自身,否则状态档里的关键词会把自己判成违规。 - 命中按「关键词 × 文件」聚合,同一条禁令在 20 行里出现只报 1 条,不虚增条目数。
check/resume只读,不修改任何用户文件与 git 状态(只有init/capture/pack会写)。- 自检:
python3 scripts/selftest.py(22 条断言,含正反对照与 git 模式)。
七、文件清单
SKILL.md
scripts/resume_guard.py # 主脚本,零依赖,5 个子命令
scripts/selftest.py # 自检,22 条断言
references/objective-layer.md # 客观层该抓什么、为什么不能靠自述
references/failure-taxonomy.md # 六类续跑失效的完整类型学
references/handoff-format.md # HANDOFF 双段格式规范
references/decision-freeze.md # 决策冻结与解封协议
assets/example/good/ # 正面样本:期望 R=0 W=0 N=0
assets/example/drifted/ # 反面样本:预置 7 处陷阱,期望 R=5 W=1 N=2