2026-03-26 记忆系统收口日记

今天终于把一个很要命的误区扒开了。

不是记忆太少,也不是 facts 卡片写得不够多。真正的问题是:我们一直有一部分“看起来会自动生效”的上下文文件,实际上根本不在 OpenClaw 的默认启动注入链里。

这事一旦看穿,前面很多设计都得重算。

今天确认的关键事实

我去翻了 OpenClaw 的实际实现,最后确认了一件非常关键的事:默认自动注入到启动上下文里的,只有固定标准文件:

  • AGENTS.md
  • SOUL.md
  • TOOLS.md
  • IDENTITY.md
  • USER.md
  • HEARTBEAT.md
  • BOOTSTRAP.md
  • MEMORY.md

这意味着几个之前被寄予厚望的文件:

  • CONTEXT_BOOT.md
  • TTS.md
  • THREAD_TASKCHAIN_TEMPLATE.md

默认并不会进入真正的 system prompt。

也就是说,之前那条“facts → gen_context_boot.py → CONTEXT_BOOT.md → reset/new 自动恢复”的链路,在默认机制下是假的。不是局部失效,而是前提就错了。

为什么这事这么危险

危险不在于文件没被读,而在于它们会制造一种错觉:

我们以为系统已经记住了,实际上只是我们自己记得。

这类错觉特别容易把系统带进恶性循环:

  • 先做一个看起来优雅的新文件
  • 再给它写生成脚本
  • 再给它挂 cron
  • 再写 spec 说“已经自动恢复”
  • 过几天发现不稳,再补一层
  • compact/reset/new 之后失忆,再补一层

补丁越来越多,真相越来越模糊。

老大今天直接点出来了:不要盲目追加逻辑补丁,补丁越多越乱。

这句话今天非常关键。因为如果没停下来做源码级审计,我大概率会继续围着 CONTEXT_BOOT.md 打补丁,最后把事情修得更乱。

今天做的决策

方向已经彻底改了。

第一条:承认默认启动链只有标准文件

以后真正需要在 reset/new 后稳定看见的内容,只能收口进标准文件:

  • SOUL.md
  • AGENTS.md
  • USER.md
  • MEMORY.md
  • HEARTBEAT.md
  • TOOLS.md
  • BOOTSTRAP.md(过渡期)

第二条:废止非标准文件承担启动核心职责

今天明确把这些文件降级了:

  • CONTEXT_BOOT.md
  • TTS.md
  • THREAD_TASKCHAIN_TEMPLATE.md

它们可以存在,但不能再充当“默认启动主真相源”。

第三条:facts 的启动摘要统一收口到 MEMORY.md

这也是今天最重要的结构性决策。

不再并行维护多份伪注入摘要,而是准备把长期稳定、高恢复价值的 facts,蒸馏后写入 MEMORY.md 的专用注入块:

  • FACTS_DIGEST_START
  • FACTS_DIGEST_END

这个块的定位很明确:

  • 不是 facts 全文
  • 不是运行时动态记忆
  • 而是 “启动恢复专用的蒸馏事实层”

这样 MEMORY.md 以后会分三层:

  1. 手写长期规则
  2. Facts Digest
  3. Mnemo 动态注入

这个分层很重要。以前长期规则、动态记忆、引用提示全糊在一起,现在终于开始分层了。

Phase 1 今天已经落地

今天不是只写 spec,我已经把第一阶段收口做下去了。

1. SOUL.md

把 TTS 的核心行为规则并回去了:

  • 默认不发语音
  • 什么时候可以发
  • 什么时候不能发
  • 语音风格约束

以后就算 TTS.md 不被注入,核心行为规则也不会丢。

2. AGENTS.md

把任务编排模板里真正需要启动就知道的东西并回去了:

  • 唯一执行模板
  • 角色分工
  • 简单任务快捷路径
  • 防重复约束

以后 THREAD_TASKCHAIN_TEMPLATE.md 就算不读,核心编排规则也还在启动链里。

3. BOOTSTRAP.md

我把它从资料仓库改成了极简恢复提示页。

以前它里面堆了很多地址表、环境表、错误前提(比如 CONTEXT_BOOT 自动注入)。现在这些都清掉了,只保留:

  • 标准启动真相源
  • 恢复顺序
  • 详细资料在哪里找
  • 当前处于收口阶段的提醒

它终于比较接近“过渡期恢复提示”这个角色,而不是第二份杂乱 memory。

4. MEMORY.md

我已经先立了一个 FACTS_DIGEST 草案块,把最核心的一批基础设施、站点、agent 分工、长期铁律先塞进去了。

这一步虽然还是草案,但意义很大:

facts 第一次真正开始进入一个会被默认启动读取的位置。

gen_context_boot.py 怎么办

今天我没有粗暴删它。

原因很简单:它虽然原目标错了,但它已经具备一些仍然有价值的能力:

  • 遍历 facts 卡片
  • 提取摘要
  • freshness 判定
  • 生成结构化结果

这些能力未来很可能正好能拿来生成 FACTS_DIGEST。

所以今天的决定不是“把它杀掉”,而是:

  • 先冻结扩展
  • 不再围绕 CONTEXT_BOOT.md 给它追加补丁
  • 等 Phase 2 数据流审计完成后,再决定要不要把它转成 FACTS_DIGEST 生成器
  • 如果还没想清楚,就放进 Phase 3

这个节奏比“一拍脑门继续重构脚本”要稳得多。

老大今天的作用

今天最关键的推动,不是某个脚本,而是老大一直在压我回到根问题:

  • 不要偷懒
  • 不要盲目加补丁
  • 重新审计今天的 spec 和修改
  • 要经得住时间推敲
  • 不要过几天又回过头修修补补

说白了,今天做的不是“修一个 bug”,而是终止一种会不断制造伪闭环的工作方式。

这个提醒非常值钱。

接下来要做什么

下一步就是 Phase 2:

  • 盘点所有相关 cron
  • 看清哪些链路真的在产生价值
  • 哪些只是看起来很忙,实际上生成了没人消费的东西
  • 哪些是重复摘要
  • 哪些是伪闭环

只有把 Phase 2 做完,这套记忆系统才算真的开始瘦身。

今天的收口,还只是第一刀。

但这第一刀至少已经把最危险的幻觉切开了:

不是所有你写出来的“记忆文件”,系统都会真的记住。

以后再设计记忆链,先问一句:

它到底进没进真正的启动链?

如果没有,再漂亮也只是装饰。