Progressive Enhancement
定义
Progressive Enhancement 是 claude-mem 记忆系统的一条设计原则,其原文表述是:Core functionality works without memory, memory enhances it。
对应到 Claude Code 的语境,这句话的含义非常具体:
- 没有 memory 时,Claude Code 仍可正常工作。
- 有 memory 时,Claude Code 可获得来自过去会话的上下文。
- memory 损坏时,会退回到正常工作的无记忆状态。
因此,这里的重点不是“memory 必须存在”,而是“memory 只能作为增强层存在,不能成为核心能力的前提条件”。
在本文档中的语境
该原则出现在一组设计模式中,与 Fire-and-Forget Hooks、队列化处理、Graceful Degradation 并列,用来约束 claude-mem 如何与 Claude Code 集成。
文档给出的三种运行状态非常直接:
Without memory: Claude Code works normally
With memory: Claude Code + context from past sessions
Memory broken: Falls back to working normally
这说明 claude-mem 的目标不是接管 Claude Code 的主流程,而是在不破坏原有体验的前提下,额外提供“过去会话上下文”这一增强能力。
关键机制
1. memory 被设计成增强层,而不是硬依赖
文档明确把 memory 定义为 enhancement,而不是 prerequisite。也就是说,系统从架构上要求:
- 核心对话、工具调用、会话进行等主流程,不应依赖 memory 成功。
- memory 的成功写入、压缩、检索,只会提升体验,不应决定主流程是否可继续。
- 如果 memory 子系统出现故障,主流程应继续,而不是报错中断。
这与 Graceful Degradation 是一体两面的关系:Graceful Degradation 讲“失败时不要拖垮系统”,而 Progressive Enhancement 讲“从一开始就不要把增强能力设计成主路径硬依赖”。
2. 有 memory 时,Claude Code 结合过去会话上下文
文档对“增强”给出的具体内容不是抽象的“体验更好”,而是来自过去会话的上下文。
在已有条目中,SessionStart 会在用户打开或恢复会话时,通过 hookSpecificOutput.additionalContext 静默注入历史上下文。结合本文档语境,可以把 Progressive Enhancement 理解为:
- 当记忆系统可用时,Claude Code 不只是“正常工作”,而是会带着过去会话信息进入当前会话。
- 这种增强发生在会话启动与后续记忆处理链路之上,但不改变核心会话机制本身。
也就是说,memory 带来的不是“能不能用”,而是“是否能在当前会话中利用历史上下文”。
3. 失败时回退到无记忆模式
该原则要求出现故障时,系统进入 fallback,而不是 cascading failure。文档明确写到:Memory broken: Falls back to working normally。
这意味着当 memory 相关组件失效时,预期行为是:
- Claude Code 继续像没有安装 memory 一样工作。
- 记忆增强能力暂时消失,但核心功能不受影响。
- 用户不会因为 memory 故障而失去基本会话能力。
这也是“核心功能无需 memory 也能工作,memory 只负责增强体验”的完整落地方式。
与后台 Worker 架构的关系
Progressive Enhancement 能成立,不只是理念问题,也依赖具体架构安排。
文档在 Worker Service Architecture 中说明:Hook 必须非常快,而 AI 压缩一次 observation 需要 5–30 秒。因此方案不是让 Hook 同步等待记忆处理完成,而是:
- Hook 读取输入,目标是 < 1ms。
- Hook 把 observation 插入队列,目标是 < 10ms。
- Hook 总体在 < 20ms 内返回成功。
- Worker 每 1 秒轮询队列。
- Worker 再通过 Claude SDK 异步处理 observation,耗时 5–30 秒。
这种“快速捕获 + 异步处理”的拆分,使得 memory 天然成为附加层:即便后台处理慢、失败或需要重试,也不会阻塞 Claude 的主流程。
换言之,若把记忆压缩直接放进 Hook 主路径,就很难实现 Progressive Enhancement;因为增强层一旦变慢,就会反向拖累核心功能。
失败边界与典型故障
文档在相关设计模式里给出多种 failure mode,这些边界条件恰好说明 Progressive Enhancement 不是空泛口号,而是面对具体故障的行为约束。
数据库锁定
当出现 Database locked 时,系统行为是:
- 跳过当前 observation。
- 记录错误日志。
- 不让错误中断主流程。
这体现的是:记忆采集失败可以接受,但 Claude Code 不能因此不可用。
Worker 崩溃
当后台 Worker 崩溃时,文档给出的处理是:
- 通过 Bun 自动重启。
即使 Worker 尚未恢复,前台系统也不应因此失去核心能力;最坏情况只是 memory 暂时不起作用。
网络问题
当出现网络问题时,处理方式是:
- 使用指数退避重试。
这说明 memory 处理链路允许异步、允许延迟,也再次强调它不是必须在当前交互内同步成功的核心步骤。
磁盘写满
当出现 Disk full 时,系统行为是:
- 向用户发出警告。
- 禁用 memory。
这里最关键的不是“修复磁盘”,而是“禁用 memory 后仍能继续使用 Claude Code”。这正是 Progressive Enhancement 的边界测试:增强层可以被关闭,主功能仍必须存在。
与 Hook 行为的关系
Progressive Enhancement 还要求 Hook 的返回策略必须偏向“继续执行”而非“失败中断”。文档中的示例是:
try {
await captureObservation();
} catch (error) {
console.error('Memory capture failed:', error);
return { continue: true, suppressOutput: true };
}
这里的关键信号有两个:
continue: true:即使 memory capture 失败,也继续后续流程。suppressOutput: true:避免把记忆层错误变成对用户主流程的噪音干扰。
这与 PostToolUse、SessionStart、SessionEnd 所代表的生命周期阶段有关:这些 Hook 可以参与增强,但不应变成阻塞 Claude 正常工作的前提。
与性能目标的关系
文档还给出了 Hook 的性能目标与实测值,这些数字从另一个侧面支撑了 Progressive Enhancement:增强层必须足够轻,不得绑架核心路径。
Hook 执行时间目标
- 目标:每个 Hook < 100ms。
实测数据
- Setup:平均 8ms,p95 20ms,p99 40ms。
- Setup(marker mismatch,stderr 提示但不阻塞):平均 10ms,p95 25ms,p99 50ms。
- SessionStart(context):平均 45ms,p95 120ms,p99 250ms。
- SessionStart(user-message):平均 5ms,p95 10ms,p99 15ms。
- UserPromptSubmit:平均 12ms,p95 25ms,p99 50ms。
- PostToolUse:平均 8ms,p95 15ms,p99 30ms。