Agent-almanac prune-agent-memory

install
source · Clone the upstream repo
git clone https://github.com/pjt222/agent-almanac
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/zh-CN/skills/prune-agent-memory" ~/.claude/skills/pjt222-agent-almanac-prune-agent-memory-5842ea && rm -rf "$T"
manifest: i18n/zh-CN/skills/prune-agent-memory/SKILL.md
source content

修剪智能体记忆

审计、分类并选择性地遗忘已存储的记忆。记忆是基础设施,遗忘是策略。此技能定义该策略。

manage-memory
专注于组织和扩充记忆(保留什么、如何结构化),而此技能专注于反面:丢弃什么、如何检测衰退,以及如何确保遗忘是刻意为之而非意外发生。两个技能相辅相成,应在定期维护期间配合使用。

适用场景

  • 记忆文件已大量增长且无人审核其相关性
  • 项目状态发生重大变化(重大重构、仓库重命名、里程碑完成),记忆可能引用过时的上下文
  • 检索质量下降——记忆产生噪声而非信号
  • 经过一段密集活动生成了许多未整理的记忆条目之后
  • 作为计划性维护任务(例如每 10-20 个会话或在项目里程碑时)
  • 多个记忆条目以细微差异覆盖同一主题(重复漂移)
  • 在让新协作者继承记忆上下文之前

输入

  • 必需:记忆目录路径(通常为
    ~/.claude/projects/<project-path>/memory/
  • 可选:保留策略覆盖(例如,「保留所有关于部署的内容」、「积极修剪调试注释」)
  • 可选:自上次审计以来已知的项目状态变化(例如,「仓库被重命名」、「从 Jest 迁移到 Vitest」)
  • 可选:用于趋势分析的先前修剪审计记录

步骤

第 1 步:枚举并分类记忆

读取所有记忆文件,按四个维度对每个条目进行分类。

# 列出记忆目录清单
ls -la <memory-dir>/
wc -l <memory-dir>/*.md

# 统计总条目数(通过计算顶层项目符号和标题近似)
grep -c "^- \|^## " <memory-dir>/MEMORY.md
for f in <memory-dir>/*.md; do echo "$f: $(grep -c '^- \|^## ' "$f") entries"; done

将每个记忆条目分类为以下类型之一:

类型描述示例默认保留
项目关于项目结构、架构、约定的事实「skills/ 有 310 个 SKILL.md 文件,分布在 55 个域中」保留直至验证为过时
决策做出的选择及其理由「因为...选择了 hub-and-spoke 而非 sequential 用于审查团队」永久保留
模式调试解决方案、工作流洞见、重复行为「退出码 5 表示引号错误——使用临时文件」保留直至被取代
参考链接、版本号、外部资源「mcptools 文档:https://...」保留直至验证为过时
反馈用户偏好、更正、风格指导「用户偏好文件名使用 kebab-case」永久保留
临时泄漏进持久记忆的会话特定上下文「当前正在处理 issue #42」立即修剪

对每个条目,还需注意:

  • 时间:何时写入或最后更新?
  • 访问频率:此条目在最近的会话中是否有用?(根据主题与近期工作的相关性估计)

预期结果: 完整的清单,每个记忆条目按类型分类,并附有时间和访问频率估计。临时条目已标记为立即删除。

失败处理: 若记忆文件太大或结构不清晰而无法逐条分类,则在章节级别进行。对整个章节而非单个项目符号进行分类。目标是覆盖率,而非粒度。

第 2 步:检测陈旧性

将记忆声明与当前项目状态进行比较。陈旧性是最常见的记忆衰退形式。

检查以下陈旧性模式:

  1. 计数漂移:已更改的文件、技能、智能体、域、团队成员的计数
  2. 路径漂移:已移动、重命名或删除的文件、目录或 URL
  3. 状态漂移:仍描述为开放或进行中的状态(已解决的问题、已完成的里程碑、已关闭的 PR)
  4. 决策逆转:后来被推翻的决策,但原始理由仍保留在记忆中
  5. 工具/版本漂移:已更改的版本号、API 签名或工具名称(例如包重命名)
# 对照真实来源抽查计数
grep -oP '\d+ skills' <memory-dir>/MEMORY.md
grep -c "^      - id:" skills/_registry.yml

# 检查不再存在的文件的引用
grep -oP '`[^`]+\.(md|yml|R|js|ts)`' <memory-dir>/MEMORY.md | sort -u | while read f; do
  path="${f//\`/}"
  [ ! -f "$path" ] && echo "STALE: $path referenced but not found"
done

# 检查旧名称/路径的引用
grep -i "old-name\|previous-name\|renamed-from" <memory-dir>/*.md

用陈旧类型和当前正确值标记每个过时条目。

预期结果: 列出有具体变化证据的过时条目。每个过时条目有推荐操作:更新(若已知正确值)、验证(若不确定)或修剪(若整个条目已过时)。

失败处理: 若无法验证某个声明(因其引用外部状态:API、第三方文档、部署状态),将其标记为

unverifiable
而非假设其正确。不可验证的条目是修剪的候选项(若不活跃有用的话)。

第 3 步:运行保真度检查

测试记忆在检索时是否仍能产生有用的上下文。这是最难的步骤,因为智能体无法验证自己压缩的记忆是否忠实——需要外部锚点。

保真度检查方法:

  1. 往返验证:读取一个记忆条目,然后检查其描述的实际项目状态。记忆是否引导你找到正确的文件、正确的模式、正确的结论?

  2. 压缩损失检测:将记忆摘要与原始源材料进行比较。当一个 50 行的讨论被压缩为 2 行的记忆时,压缩是否保留了可操作的洞见,还是仅保留了主题标签?

    # 查找记忆条目来源的原始内容
    # (git log、旧 PR、原始文件)
    git log --oneline --all --grep="<keyword from memory entry>" | head -5
    
  3. 矛盾扫描:搜索相互矛盾的记忆,或与 CLAUDE.md/项目文档矛盾的记忆。

    # 在计数中寻找潜在矛盾
    grep -n "total" <memory-dir>/MEMORY.md
    grep -n "total" CLAUDE.md
    # 比较数值——它们应该一致
    
  4. 实用性测试:对每个记忆条目,询问:「如果删除此条目,接下来 5 个会话中会出现问题吗?」若答案是「可能不会」,则该条目的保真度价值低,无论其准确性如何。

预期结果: 每个记忆条目现在有保真度评估:(已验证准确且有用)、(可能准确,偶尔有用)、(未验证或很少有用)或失败(已验证不准确或矛盾)。

失败处理: 若保真度检查对许多条目结果不确定,则专注于潜在影响最大的条目。关于项目架构的错误记忆比关于调试技巧的错误记忆更危险。优先检查骨架级事实而非细节级内容。

第 4 步:执行选择性删除

使用此决策树按优先顺序确定修剪内容:

修剪决策树(按顺序应用):

1. 临时条目(第 1 步分类)
   → 立即删除。这些内容不应该被持久化。

2. 保真度失败的条目(第 3 步)
   → 立即删除。不准确的记忆比没有记忆更糟糕。

3. 重复条目
   → 保留最完整/准确的版本,删除其他版本。
   → 若重复条目跨越 MEMORY.md 和主题文件,保留主题文件版本。

4. 有已知更正的过时条目(第 2 步)
   → 若条目否则有用则更新(将过时值改为当前值)。
   → 若整个条目已过时(主题不再重要)则删除。

5. 低保真度、低访问频率的条目
   → 删除。这些条目占用空间而不提供价值。

6. 关于已完成/已关闭工作的中等保真度条目
   → 归档或删除。过去的冲刺细节、已解决的事件、已合并的 PR。
   → 例外:若解决方案包含可复用的模式则保留。

7. 具有可自由获取来源的参考条目
   → 若引用是 Google 一下就能找到的则删除。
   → 若引用难以找到或具有项目特定上下文则保留。

对每次删除,记录条目、其分类以及删除原因(用于第 6 步)。

预期结果: 明确列出要删除、更新和保留的条目——每个都有记录的原因。保留/删除比例取决于记忆健康状况;维护良好的记忆可能修剪 5-10%,被忽视的记忆可能修剪 30-50%。

失败处理: 若决策树对许多条目产生模糊结果,应用更严格的过滤器:「知道我现在了解的情况,我今天还会写这个条目吗?」若否,则为删除候选。倾向于修剪——重新学习一个事实比绕开错误记忆工作更容易。

第 5 步:应用预防性过滤器

定义「不应保存什么」的规则,以防止未来的记忆污染。审查现有记忆,寻找在写入时应该被过滤的模式。

不应成为持久记忆的模式:

模式原因示例
会话特定的任务状态在下一个会话时就会过时「当前正在调试 issue #42」
中间推理过程不是结论「尝试了方法 A,因为...而不起作用」
调试输出/堆栈跟踪临时诊断数据「错误是:TypeError at line 234...」
精确命令序列脆弱,依赖版本「运行
npm install foo@3.2.1 && ...
情感/语气注释不可操作「用户似乎感到沮丧」
CLAUDE.md 的副本已在系统提示中「项目使用 renv 管理依赖」
未验证的单次观察可能是错的「我认为 API 速率限制是 100/分钟」

若在现有记忆中发现这些模式,将其添加到第 4 步的删除列表。

在 MEMORY.md 或

retention-policy.md
主题文件中记录过滤规则,以便未来会话在写入新记忆之前可以参考。

预期结果: 在记忆目录中记录一套预防性过滤规则。所有符合这些模式的现有条目都被标记为删除。

失败处理: 若记录过滤规则感觉为时过早(记忆小,污染最少),跳过文档,但仍应用过滤器以捕获任何现有违规。规则可在记忆目录更加成熟后正式化。

第 6 步:写入审计记录

记录每次删除,以便遗忘本身可被追溯。创建或更新修剪日志。

<!-- 在 <memory-dir>/pruning-log.md 中或附加到 MEMORY.md -->

## 修剪日志

### YYYY-MM-DD 审计
- **审计条目数**:N
- **修剪条目数**:M(X%)
- **更新条目数**:K
- **发现的陈旧性**:[检测到的陈旧模式列表]
- **保真度失败**:[验证失败的条目列表]

#### 删除记录
| 条目(摘要) | 类型 | 原因 |
|-------------|------|------|
| 「当前正在处理 issue #42」 | 临时 | 会话特定,已过时 |
| 「skills/ 有 280 个 SKILL.md 文件」 | 项目 | 计数漂移:实际为 310 |
| 「使用 acquaint::mcp_session()」 | 模式 | 包已重命名为 mcptools |

保持修剪日志简洁。它的存在是为了问责,不是为了考古。若日志本身变得庞大,可总结旧条目:「2025 年:3 次审计,共修剪了 47 个条目(主要是计数漂移和临时泄漏)。」

预期结果: 带时间戳的修剪日志条目,记录删除内容及原因。日志与记忆本身一起存储在记忆目录中。

失败处理: 若创建单独的日志文件感觉过度(仅修剪 1-2 个条目),改为在 MEMORY.md 中添加简短说明:

<!-- Last pruned: YYYY-MM-DD, removed 2 stale entries -->
。任何记录都比静默删除要好。

第 7 步:指定受保护的记忆

某些记忆条目应免于修剪,无论其时间、访问频率或保真度分数如何。这些代表不可替代的上下文,若丢失将需要大量精力重建。

受保护记忆标准:

类别示例为何受保护
架构决策「选择了平面技能目录而非嵌套目录」若后来重新推导,理由将丢失
用户身份偏好「始终使用 kebab-case」、「永不自动提交」明确的用户意图,无法推断
安全审计结果「最后审计:2025-12-13 — 通过」带时间戳的合规证据
重命名/迁移记录「仓库在日期 Z 从 X 重命名为 Y」交叉引用完整性依赖于此

指定方法:

<!-- PROTECTED -->
内联标记受保护条目,或在修剪日志中维护
protected
列表。第 4 步中的决策树在应用任何删除规则之前必须检查受保护状态。

取消保护: 若要修剪受保护条目,必须先明确移除指定并在修剪日志中记录原因。这个两步流程防止意外删除高价值记忆。

预期结果: 受保护条目在所有修剪过程中得以保留。修剪日志记录任何保护添加或移除。

失败处理: 若受保护集合增长过大(超过总条目的 30%),审查标准——保护是针对不可替代的上下文,不是针对「重要」条目。重要但可重建的事实应仍受正常修剪约束。

第 8 步:修剪后重新整合

删除后,剩余记忆可能是碎片化的——交叉引用指向已删除的条目,主题文件失去连贯性,MEMORY.md 可能有空白。重新整合恢复结构完整性。

重新整合清单:

  1. 解决断开的引用:扫描剩余条目,寻找指向已删除内容的链接。移除或重定向引用。
  2. 合并相关碎片:若修剪留下两个覆盖同一主题重叠方面的条目,将它们合并为一个连贯的条目。
  3. 更新主题文件结构:若主题文件丢失了 50% 以上的内容,考虑将剩余内容折叠回 MEMORY.md 并删除主题文件。
  4. 分类冷记忆:审查在修剪中幸存但最近未被访问的条目:
    • 因不使用而冷:主题与活跃项目目标一致,但生成它的特定阶段已过去。保留——当该阶段恢复时可能再次相关(例如,活跃开发期间的 CRAN 提交注释)。
    • 因不相关而冷:主题一直处于边缘——一次性实验、边缘调查或已被取代的方法。标记为下一个修剪周期中删除。
  5. 验证 MEMORY.md 连贯性:从头到尾阅读 MEMORY.md。它应该讲述一个关于项目的连贯故事,而不是读起来像随机事实的集合。

预期结果: 修剪后的记忆在结构上是健全的——没有孤立引用、没有冗余碎片、没有不连贯的主题文件。冷条目被分类以供未来修剪决策参考。

失败处理: 若重新整合揭示修剪过于激进(关键上下文丢失),检查修剪日志并从审计记录中重建。这就是审计记录存在的原因。

第 9 步:从记忆漂移中恢复

记忆漂移发生在存储的事实静默地变得错误时——不是因为它们一直是错误的,而是因为底层现实发生了变化而记忆没有更新。漂移恢复尝试就地修复记忆而非修剪它们。

漂移检测触发器:

  • 记忆声明与当前工具输出或文件内容矛盾
  • 记忆中的计数或版本号与注册表或锁文件不匹配
  • 记忆中的路径返回「文件未找到」
  • 关于依赖项的记忆引用了已重命名或已废弃的包

恢复流程:

  1. 识别漂移:将记忆声明与当前真实来源进行比较(git log、注册表、实际文件)
  2. 评估可恢复性:可以从当前项目状态确定正确值吗?
    • 是 → 用当前值就地更新记忆条目,并添加
      [corrected YYYY-MM-DD]
      注释
    • 否 → 将条目标记为
      unverifiable
      并标记为修剪
  3. 追溯原因:这是渐进漂移(计数慢慢偏离)还是离散事件(重命名、迁移)?离散事件通常影响多个条目——扫描相关条目。
  4. 防止复发:若漂移影响频繁变化的值(计数、版本),考虑是否记忆应该追踪该值,还是应该引用真实来源:「参见 skills/_registry.yml 获取当前计数」而非「317 个技能」。

预期结果: 漂移记忆在可能的情况下就地更正,保留上下文。无法更正的条目被标记为修剪。预防规则减少未来漂移。

失败处理: 若漂移普遍(超过 20% 的条目),记忆可能需要完全重建而非逐步更正。在这种情况下,归档当前记忆目录,重新开始,并选择性地重新导入通过验证的条目。

验证清单

  • 所有记忆文件已列出清单,条目按类型分类
  • 针对当前项目状态运行了陈旧性检查
  • 至少应用了一种保真度检查方法(往返、压缩损失、矛盾扫描或实用性测试)
  • 删除决策遵循决策树中的优先顺序
  • 没有条目在没有记录原因的情况下被删除
  • 预防性过滤规则已记录或已应用
  • 修剪日志记录了删除的内容、时间和原因
  • 修剪后 MEMORY.md 保持在 200 行以内
  • 剩余记忆准确(针对项目状态进行了抽查)
  • 通过从 MEMORY.md 删除引用没有创建孤立主题文件
  • 受保护条目已被指定,并在所有修剪过程中保留
  • 修剪后重新整合解决了断开的交叉引用并合并了碎片
  • 冷条目被分类为不使用 vs. 不相关,以供未来修剪决策使用
  • 漂移条目在可能的情况下就地更正,而不仅仅是删除

常见问题

  • 无验证地修剪:因为条目「看起来很旧」就删除,而不检查它是否仍然准确和有用。年龄本身不是删除标准——一些最有价值的记忆是仍然正确的旧架构决策。
  • 自我验证保真度:智能体读取自己压缩的记忆并得出「是的,这看起来是对的」不是保真度检查。保真度需要外部锚点:项目文件、git 历史、注册表计数、实际工具输出。没有锚点,你只是在检查一致性,而非准确性。
  • 无审计记录地激进修剪:在没有记录删除内容的情况下删除条目。当未来会话需要已修剪的事实时,审计记录解释了发生了什么,并可能包含足够的上下文来重建记忆。
  • 将修剪决策作为记忆:不要将「我决定修剪 X 是因为 Y」写成常规记忆条目。这只属于修剪日志。关于记忆管理的记忆条目是元污染。
  • 忽略预防性过滤器:修剪现有条目但不建立规则以防止相同模式复发。没有过滤器,接下来 10 个会话将重新创建你刚刚删除的相同临时条目。
  • 平等对待所有类型:决策记忆和反馈记忆几乎不应该被修剪——它们代表用户意图和理由。项目和参考记忆是主要修剪目标,因为它们追踪会变化的状态。
  • 混淆压缩与损坏:将复杂主题压缩为一行的记忆是被压缩的,不是损坏的。只有在压缩丢失了可操作洞见时才将其标记为保真度失败,而不仅仅是细节。
  • 过度固定:将太多条目标记为受保护会使修剪失去意义。若超过 30% 的条目是受保护的,则标准太宽松。保护不可替代的上下文,而不仅仅是重要的事实。
  • 重新整合循环:在重新整合期间合并碎片可能会创建自身在下一个修剪周期中需要修剪的新条目。保持合并最小化——只合并明显涵盖同一主题的条目。不要在修剪过程中综合新的洞见。

相关技能

  • manage-memory
    — 组织和扩充记忆的互补技能;配合使用以进行完整的记忆维护
  • meditate
    — 清理和接地,可能揭示哪些记忆在产生噪声
  • rest
    — 有时最好的记忆维护就是不做记忆维护
  • assess-context
    — 评估推理上下文健康状况,记忆质量直接影响于此