W
AI-Wiki
CONCEPT

Progressive Enhancement

定义

Progressive Enhancementclaude-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:避免把记忆层错误变成对用户主流程的噪音干扰。

这与 PostToolUseSessionStartSessionEnd 所代表的生命周期阶段有关:这些 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