# Prune Agent Memory

> 审计、分类并选择性地遗忘已存储的记忆。涵盖按类型/时间/访问频率进行记忆枚举 与分类、检测过时引用的陈旧性检测、使用外部锚点进行保真度检查、选择性删除的 决策树、对那些原本会被重新推导出来的失败策略进行反向记忆免疫、关于什么内容 不应成为记忆的预防性过滤规则，以及使遗忘本身可追溯的审计记录。当记忆已增长 为大型未整理状态、项目状态自记忆写入以来发生重大变化、检索质量下降，或作为 与 manage-memory 配套的定期维护时使用。

- Skill: `pjt222/prune-agent-memory-4` (Agent Skill)
- Install (CLI): `npx skillmds@latest add pjt222/prune-agent-memory-4`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pjt222/prune-agent-memory-4/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: pjt222 (https://skillmd.com/u/pjt222)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/pjt222/prune-agent-memory-4

---


# 修剪智能体记忆

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

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

## 适用场景

- 记忆文件已大量增长且无人审核其相关性
- 项目状态发生重大变化（重大重构、仓库重命名、里程碑完成），记忆可能引用过时的上下文
- 检索质量下降——记忆产生噪声而非信号
- 经过一段密集活动生成了许多未整理的记忆条目之后
- 作为计划性维护任务（例如每 10-20 个会话或在项目里程碑时）
- 多个记忆条目以细微差异覆盖同一主题（重复漂移）
- 在让新协作者继承记忆上下文之前
- 在放弃某种策略或模式后，但触发条件依然存在——需要进行免疫处理以防止重新推导，而不是仅依赖删除

## 输入

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

## 步骤

### 第 1 步：枚举并分类记忆

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

```bash
# Inventory the memory directory
ls -la <memory-dir>/
wc -l <memory-dir>/*.md

# Count total entries (approximate by counting top-level bullets and headers)
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 签名或工具名称（例如包重命名）

```bash
# Spot-check counts against source of truth
grep -oP '\d+ skills' <memory-dir>/MEMORY.md
grep -c "^      - id:" skills/_registry.yml

# Check for references to files that no longer exist
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

# Check for references to old names/paths
grep -i "old-name\|previous-name\|renamed-from" <memory-dir>/*.md
```

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

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

**失败处理：** 若无法验证某个声明（因其引用外部状态：API、第三方文档、部署状态），将其标记为 `unverifiable` 而非假设其正确。不可验证的条目是修剪的候选项（若不活跃有用的话）。

### 第 3 步：运行保真度检查

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

保真度检查方法：

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

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

   ```bash
   # Find the source that a memory entry was derived from
   # (git log, old PRs, original files)
   git log --oneline --all --grep="<keyword from memory entry>" | head -5
   ```

3. **矛盾扫描**：搜索相互矛盾的记忆，或与 CLAUDE.md/项目文档矛盾的记忆。

   ```bash
   # Look for potential contradictions in counts
   grep -n "total" <memory-dir>/MEMORY.md
   grep -n "total" CLAUDE.md
   # Compare the values — they should agree
   ```

4. **实用性测试**：对每个记忆条目，询问：「如果删除此条目，接下来 5 个会话中会出现问题吗？」若答案是「可能不会」，则该条目的保真度价值低，无论其准确性如何。

**预期结果：** 每个记忆条目现在有保真度评估：**高**（已验证准确且有用）、**中**（可能准确，偶尔有用）、**低**（未验证或很少有用）或**失败**（已验证不准确或矛盾）。

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

### 第 4 步：执行选择性删除

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

```text
修剪决策树（按顺序应用）：

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

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

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

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

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

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

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

对每次删除，记录条目、其分类以及删除原因（用于第 7 步）。

在执行此决策树中的任何 DELETE 操作之前，先检查该条目是否需要免疫处理（第 5 步）。失败的策略、被放弃的方法以及危险的模式都是「删除 + 免疫」而非仅仅删除的候选项。

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

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

### 第 5 步：免疫以防止模式重新推导

某些被放弃的结论无法安全地直接删除。当生成该记忆的条件依然存在时，单纯的删除会失效——系统会从相同的输入沿着相同的推理路径重建已删除的记忆。对于这些情况，需要在删除的同时（或代替删除）写一条反向记忆，以阻止重新推导。

**决策规则——仅删除 vs. 删除 + 免疫 vs. 仅免疫：**

| 记忆类别 | 操作 | 原因 |
|---|---|---|
| 过时事实、过期指针、过期上下文 | **仅删除** | 检索清理；即使再次生成也无行为风险 |
| 失败的策略、危险的模式、触发条件持续存在的被放弃方法 | **删除 + 免疫** | 否则推理路径会重新生成相同结论 |
| 后来被推翻但原始理由仍重要的决策 | **仅免疫** | 保留原始条目；新增 SUPERSEDED 反向记忆指向它 |

**SUPERSEDED 记录格式**（用于 auto-memory 的 frontmatter；其结构可适配其他记忆系统）：

```markdown
---
name: superseded-<short-id>
description: Counter-memory preventing re-derivation of <pattern>
type: superseded
---

SUPERSEDED <YYYY-MM-DD>
Pattern: <what was tried — describe the conclusion or strategy>
Period: <start> to <end>
Evidence: <what happened — concrete data, not narrative>
Abandonment reason: <specific cause; not "did not work">
Do not re-derive from: <signal types or input patterns that previously led here>
Supersedes: <path to original memory if delete + inoculate, or N/A>
```

将 SUPERSEDED 记录作为独立文件放在记忆目录中（例如 `superseded_strategy_X.md`），使它们在检索时与活跃记忆一起出现。这条反向记忆即是变更的实际生效机制：当类似信号到来时，SUPERSEDED 记录会浮现并阻断重新生成的路径。

**何时不应免疫：**

- 微不足道的过时事实（即使重新生成也无行为风险）
- 原始触发条件已不复存在的记忆（重命名已完成、依赖已被移除、团队已解散）
- 在新证据下重新推导本身是被期望的决策（该策略在未来某种状态下可能奏效，应被重新评估）

**免疫卫生：**

- 保持 `Pattern` 和 `Do not re-derive from` 字段具体明确。模糊的反向记忆（例如「不要尝试复杂的解决方案」）只会变成噪声。
- 给 SUPERSEDED 条目标注日期。若底层条件发生变化，旧的免疫记录本身也可能变得陈旧——它们会进入下一个修剪周期作为审查候选项。
- 每个被放弃的模式对应一条 SUPERSEDED。不要将多次放弃链接到同一条反向记忆中；这样会损害检索效果。
- 将 SUPERSEDED 文件路径与删除记录一起加入修剪日志，使审计记录捕获操作的两个部分。

**预期结果：** 对于第 4 步中涉及被放弃策略或危险模式的每一个删除候选项，在删除原始条目之前都创建了对应的 SUPERSEDED 反向记忆文件。修剪日志同时记录删除和免疫两侧。活跃记忆保持精简，而重新生成的路径已被阻断。

**失败处理：** 若不确定某条目是否需要免疫，默认进行免疫。多余一条 SUPERSEDED 记录代价很小；而重新生成一个糟糕的模式代价高得多。若 SUPERSEDED 列表本身大到成为噪声，这就是一个信号，提示应调查产生重复放弃的上游条件——修复在输入层，而非记忆层。

### 第 6 步：应用预防性过滤器

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

**不应**成为持久记忆的模式：

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

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

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

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

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

### 第 7 步：写入审计记录

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

```markdown
<!-- 在 <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 -->`。任何记录都比静默删除要好。

### 第 8 步：指定受保护的记忆

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

**受保护记忆标准：**

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

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

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

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

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

### 第 9 步：修剪后重新整合

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

**重新整合清单：**

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

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

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

### 第 10 步：从记忆漂移中恢复

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

**漂移检测触发器：**

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

**恢复流程：**

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

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

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

## 验证清单

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

## 常见问题

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

## 相关技能

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

