# pi-memory-auto

给你的 pi 编码助手配一个记忆。上周说过的事，这周不用再说一遍。

[English](README.md) · **中文** · [技术文档](TECHNICAL.md)

## 一句话说明

想象一个**记事本 + 一叠索引卡**。你从来不用把整本笔记念一遍——只要瞥一眼卡片，
看到跟手上的活对得上的那个词，就让助理把那一页拿给你。

这套系统的逻辑就是这样：

- 每条记忆 = **一小段话 + 一个关键词**；
- 每次开新会话，助理只看到关键词，**看不到正文**；
- 当某个关键词跟当前的工作对上了，助理自己去把正文取出来，不需要你提醒。

## 一条记忆长什么样

> 部署用 rsync，先把上一版备份好。
> `#部署`

关键词是"以后能找回这条记忆的钩子"。所以关键词比措辞重要：只挑**未来的你最会搜的那个词**，
用你真正会打的那种语言写。一条记忆一个词，词表才短得扫得动。

## 每次开工你看到的东西

一张词表，仅此而已：

```
你自己（全局）            这个项目
#macos                   #部署 (3)
#svg (2)                 #发版 (2)
#utools (4)              #端口
```

`(3)` 表示有三条记忆共享这个词。正文留在硬盘上，等真的需要了才去取——绝大多数
跟今天要干的活没有关系。

## 三条"防止笔记本越记越烂"的规矩

三条都遵循同一个原则：**拿不准就什么都不做，绝不弄丢东西。**

**1. 同一件事说了两遍 → 在原来那条上打个勾。**

不会多出一张卡。原来那条会默默记上"已确认 3 次，最近一次是周二"。所以重复说话
不会让笔记本变厚，只会让老条目更可信。

**2. 发现记错了 → 贴一张"以新的为准"。**

比如先记了"用 MySQL"，后来改成"用 PostgreSQL"。旧条目会被贴上"已被替代"：内容还留在
纸上，但不再出现在关键词卡里，查找时永远排在最后，并注明去看新的那条。

为什么不撕掉？因为旧的那句话里经常藏着新版本漏掉的细节，而“撕掉”是不可逆的——
一旦判断错了，细节就永久没了。

真正难缠的情况是“你改了，但没人记下来”：某次你说“别用 MySQL 了，改用 PostgreSQL”，
而那一次的内容没有被提取，几个月后纸上写着的仍然只有“用 MySQL”。所以插件会分三层去
抓这件事：在提示里说明记忆只是“写下来那一刻的事实”、当前指令优先，并要求它在同一轮
把过时的那条标为已替代；审查记忆时把“共享同一个关键词、内容却对不上”的条目配对
（端口 3000 对 8080、rsync 对 GitHub Actions）当作“疑似冲突”交给模型判断；而下一次
整理时，即使没有任何一轮注意到过这个变化，也会把这类配对里较旧的那条标为已替代。

**3. 太久没确认过 → 贴一张"该复核了"。**

工具和习惯几个月就会变，"这个库不支持 X"放两年可能已经是错的。到期的条目会被标上
"已经 263 天，用之前先核实一下"，并排在新的后面。

**它只是贴标签**：不会删、不会藏、也不因为旧就当成错的。系统里没有任何自动清理——
判断"这条还有用吗"需要瞎猜，猜错就是数据丢失。

## 定期收拾

每积累 20 条新记忆（或者你手动喊一声），会做一次整理：把说的是同一件事的两条并成一条，
把同一个概念的不同叫法统一成一个关键词；如果两条其实是同一个事实的两个版本，较旧的那条
会被标为已替代。整理完会告诉你并掉了几条，而且**每个被改动的文件都留了备份**。

平时打开 `/memory` 能做一次体检：哪些条目已经被替代、哪些关键词从来没人搜过、哪些该复核了、
哪两条看起来很像可以合并，哪两条其实是**同一个事实的新旧两版、旧的还没被替代**。
报告里的每一条都是**建议**，不会背着你执行。

## 它猜得越来越准

系统会悄悄统计**哪些关键词真的帮你找到了东西**，然后在下一张词表里把有用的往前排。
因为词表位置有限，这个反馈会让它慢慢贴近你的实际习惯。

词表只在**会话之间**更新，不会在对话中途变。

## 命令

| 输入 | 会发生什么 |
|---|---|
| `/memory` | 体检报告：关键词表、各项计数、需要你决定的事、文件位置 |
| `/memory compact project` | 合并**这个项目**里重复的记忆 |
| `/memory compact user` | 合并**你自己的全局笔记**里重复的记忆 |
| `/memory rebuild project` | 给**这个项目**的每条记忆重新挑一个更好搜的关键词，再重建词表 |
| `/memory rebuild user` | 同上，针对**你自己的全局笔记** |
| `/memory help` | 打印这份用法 |

`compact` 和 `rebuild` 必须指明是哪一层（`project` 或 `user`），不会替你猜——
否则每个项目都会重复改写你共享的全局笔记。

`/memory rebuild` 也是老记忆的补齐方式：早先版本一条记忆最多存过三个关键词，重建会把
它们收敛成最该留的那一个。

## 记忆存在哪

- **你的全局笔记** —— `~/.pi/agent/memory-auto/` —— 习惯、偏好、工具、通用经验，
  换到任何仓库都成立的东西。
- **这个项目的笔记** —— `.pi/agent/memory-auto/` —— 只属于这个仓库的决策、约定和踩过的坑。
  把这个目录提交进 Git，同事就自动继承了。

两边都是纯 markdown，你可以随时手动读、改、删——它们才是真源。旁边的 `MEMORY.md` 是自动
生成的视图，改了也会被覆盖，不用管它。

## 安装

```sh
pi install npm:@shanelevs/pi-memory-auto
```

## 设置（可选）

都是环境变量，都有默认值：

| 变量 | 默认 | 含义 |
|---|---|---|
| `PI_MEMORY_AUTO_REVIEW_TURNS` | `10` | 每几轮对话想一次"要不要记点什么" |
| `PI_MEMORY_AUTO_CONSOLIDATE_EVERY` | `20` | 新增多少条记忆后整理一次 |
| `PI_MEMORY_AUTO_DIR` | `~/.pi/agent/memory-auto` | 全局笔记放在哪 |
| `PI_MEMORY_AUTO_INDEX_BUDGET` | `3000` | 关键词表最多占多少篇幅 |
| `PI_MEMORY_AUTO_LLM_MAX_TOKENS` | `10000` | 后台记笔记时的回答长度上限 |
| `PI_MEMORY_AUTO_REVIEW_MONTHS` | `0` | 多久提醒复核一次（月），`0` = 按内容类型 3/6/12 |

## 新版有什么

**1.0.0** —— 一条记忆只留一个关键词，不再是最多三个。词表因此短得多，真正有用的那个词
不会被两个更弱的词埋掉。多写的关键词会被直接忽略（不会报错重来），
`/memory rebuild project|user` 会把老的三关键词记忆收敛成一个。

**0.9.0** —— 修两个问题。长会话不再越堆越多重复记忆：同一个轮次最多只审查一次，每次审查
只看上次之后新增的内容。改了却忘了重新存下来的要求也不再无人问津：互相矛盾的记忆会被
检测出来交给模型判断，过时的那条标为已替代，而不是被当作仍然有效。

更早的版本：见[技术文档](TECHNICAL.md#changelog-detailed)。

## 许可

MIT
