抗压缩状态持久化——Notepad 与 Project Memory
学习目标
- 理解上下文压缩(Context Compaction)对 Agent 持续性的影响
- 掌握 Notepad 和 Project Memory 的两层抗压缩设计
- 设计自己的 PreCompact Hook 策略
- 识别 Notepad 膨胀和信息遗漏的陷阱
前置知识
短期/长期记忆分层与文件系统存储方案已在通用知识中介绍:
下文假设你已理解记忆分层的基础概念,直接聚焦 OMC 的 抗压缩持久化模式——如何在上下文被截断时保留关键信息。
项目实践
上下文压缩的本质问题
当 Agent 对话过长时,系统会自动压缩上下文——删除早期消息以腾出空间。这导致 Agent 丢失:
- 关键决策记录
- 正在进行的工作状态
- 用户偏好和约束
- 多 Agent 编队的进度
OMC 的解决方案是主动保存 + 自动恢复:在压缩发生前写入持久化存储,压缩后通过 Hook 恢复。
三层抗压缩存储
| 层级 | 存储文件 | 保留策略 | 典型内容 |
|---|---|---|---|
| Notepad | .omc/notepad.md | 永久保留(手动清理) | 工作记忆、高优先级笔记 |
| Project Memory | .omc/project-memory.json | 跨会话持久化 | 项目知识、架构决策 |
| Plan Notepad | .omc/notepads/{plan-name}/ | 按 Plan 隔离 | 每个执行计划的 learnings、decisions |
PreCompact Hook 的工作流程
- 触发:Claude Code 决定压缩上下文前,触发
PreCompact事件 - 收集:OMC 的
pre-compact.mjsHook 在 10 秒超时内收集关键信息 - 写入:通过
notepad_write_working写入工作记忆,通过project-memory-precompact快照项目记忆 - 压缩:Claude Code 执行压缩——早期消息被删除
- 恢复:
SessionStartHook 读取 Notepad 内容,通过<system-reminder>注入恢复的信息
控制面与数据面的分离
OMC 将状态分为两类:
- 控制面(
.omc/state/):队列状态、Worker 分配、会话状态——小且频繁读写 - 数据面(
.omc/plans/、.omc/notepads/、.omc/prompts/):大持久化产物——通过 Descriptor 引用
Artifact Descriptor 模式:当控制面需要引用大产物时,使用 Descriptor 而非直接内联内容:
| 字段 | 用途 |
|---|---|
kind | 产物类别(plan、prompt、result、trace) |
path | 持久化路径 |
sizeBytes? | 负载大小(用于阈值决策) |
retention | 清理/归属生命周期提示 |
边界规则:小负载内联(当调用方阈值允许时),大负载使用 Descriptor + 简短人类可读摘要。
会话级状态隔离
OMC 支持多个会话同时运行同一项目,通过 .omc/state/sessions/{sessionId}/ 实现状态隔离:
.omc/state/sessions/abc123/prd.json ← 会话 A 的 PRD.omc/state/sessions/def456/prd.json ← 会话 B 的 PRD(互不干扰)问题与规避
问题 1:Notepad 膨胀
如果不定期清理,Notepad 会积累过时信息,浪费上下文窗口。
规避策略:OMC 提供了 notepad_prune 工具自动清理旧条目。notepad_write_priority 写入的条目不受自动清理影响。
问题 2:关键信息遗漏
PreCompact Hook 只有 10 秒超时,可能来不及收集所有关键信息。
规避策略:Hook 按优先级收集信息——Notepad 内容优先,Project Memory 次之。如果时间不足,至少保留最高优先级的信息。
问题 3:Descriptor 过期
Descriptor 引用的实际文件可能被删除或修改,导致引用失效。
规避策略:Descriptor 包含 retention 生命周期提示和可选的 contentHash 完整性校验。清理脚本会检查 Descriptor 引用关系。
设计取舍
为什么选择文件系统而非数据库?
| 维度 | 文件系统 | 数据库 |
|---|---|---|
| 可读性 | 高——人类可直接阅读和编辑 | 低——需要工具查询 |
| 版本控制 | 高——Git 可追踪变更 | 低——数据库变更不在 Git 中 |
| 查询能力 | 低——需要解析文件 | 高——SQL 查询 |
| 并发性 | 低——需要文件锁 | 高——事务隔离 |
OMC 的选择:Notepad 和 Project Memory 使用文件系统(.omc/ 目录),因为它们是面向人类可审计的设计决策。对于需要高并发查询的状态(如 Team 编队状态),OMC 使用 SQLite(better-sqlite3)。
为什么不使用 <remember> 标签作为主要持久化?
<remember> 标签(7 天/永久保留)由 Claude Code 原生支持,但 OMC 选择了 Notepad + Project Memory 作为主要持久化。原因是 <remember> 标签在压缩时可能不被正确处理,而 Notepad 是确定性恢复的。
参考来源
- OMC Architecture - State Management — 状态系统的官方文档
- Claude Code PreCompact Hooks — 压缩前 Hook 的规范