sync: WIN11-BOWEI 2026-09-02 新增 bmem 记忆 skill;imx6-flow/plan-review 文档与脚本更新

远端 pack 服务仍故障(git-upload-pack 返回 0008NAK 后截断),push 待服务器恢复。
未跟踪的 5 个归档临时副本(rtl-ip-replace / sim-rtl-flow / simulink_rtl_dev /
simulink-rtl-redev / zynq-imx6-flow)刻意不入库,待 pull 后由远端提供。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0135YszNe4pwwJxwaLqKTCKG
This commit is contained in:
Myfro9
2026-09-02 14:53:28 -05:00
co-authored by Claude Opus 5
parent 9c1012f5b8
commit bb71470e07
6 changed files with 582 additions and 4 deletions
+282
View File
@@ -0,0 +1,282 @@
---
name: bmem
description: 用 bmem 记忆系统读写跨机器、跨 agent 的长期记忆——判断一条信息该进全局/项目/机器/log 哪一层、把 ./Notes 下的 PRxx/Taskxx/Resultxx 导入记忆、会话收尾该沉淀什么、怎么查以前做过什么、以及 bmem 命令报错时怎么修。当用户提到"记住"、"记一下"、"存到记忆里"、"之前/以前是不是做过"、"上次怎么解决的"、"查一下历史"、"这台机器装了什么"、"这个项目在别的机器上在哪"、"账号密码记下来"、"同步记忆"、"这个项目不做了/从记忆里删掉"、"bmem"、"记忆系统",或者在一个根目录有 bmem_<prjID>.md 的项目里开始实质性工作、需要知道过去的决策和踩过的坑时,必须使用此技能——即使用户没有说"skill"或"bmem"两个字。用户改完 ./Notes 下的需求/方案/结果文档、或一段实质性工作收尾时也要用它。bmem 命令报错(未加入 bmem / 不在项目内 / PG 不可达 / git 冲突 / 重复注册)时同样用它。
---
# bmem:Claude Code 与 Codex 共享的跨机器长期记忆
bmem 把记忆分四层:三层是 Markdown(用 gitea 在多机之间同步),第四层 log 是中心
PostgreSQL + 本机 SQLite 镜像。**Markdown 是三层记忆的唯一事实源,SQLite 镜像是可
随时删掉重建的派生物。**
一句话分工:**Markdown 记知识(我们知道什么、为什么这么定),log 记经历(什么时候、发生了什么)。**
| 层 | 回答什么 | 存在哪 | 判据 |
|---|---|---|---|
| 全局 global | 我通常怎么工作、跨项目的通用规则 | `~/bmem.md` | 换个项目还成立吗?成立 → global |
| 项目 project | 这个项目是什么、为什么这样设计 | `<项目根>/bmem_<prjID>.md` | 项目结束后还有意义吗?没有 → project |
| 机器 machine | 这台机器有什么、能做什么、账号配在哪 | `~/bmem_<machineID>.md` | 换台机器就不成立了吗?是 → machine |
| log | 这个项目发生过什么、Notes 里写了什么 | 中心 PG + `~/.bmem/bmem_local.sqlite` | 这是"发生了一件事"还是"我们知道一件事"?发生 → log |
`~/bmem.md` 里还有两张注册表:哪些机器加入了系统、每个项目在每台机器上的绝对路径。
**项目身份是 prjID,不是路径**——同一个项目在不同机器上路径不同,引用项目内文件要用相对路径。
## 先确认它能用
```bash
bmem help
```
`bmem` 不在 PATH 上时,用 `<langgraph conda env>/Scripts/bmem.exe`(路径见 `~/skills_env.md`)。
本机还没加入系统会提示 `run bmem install first`;当前目录不属于任何项目会提示先 `bmem init`。
## 开工之前:先把记忆取回来
bmem 没有 `context` 命令——**记忆就是几个 Markdown 文件,直接读**:
1. `~/bmem.md` 的「全局规则」节:适用于所有项目的硬约束,**先读这个**。
2. 当前项目根目录的 `bmem_<prjID>.md`:项目简介、规则/约束、设计决策、当前状态与未解决问题。
3. 需要了解本机环境(工具装在哪、账号怎么配)时再读 `~/bmem_<machineID>.md`。
要查"以前做过没有、上次怎么解决的",用本 skill 自带的检索脚本查 log 层:
```bash
python <skill>/scripts/bmem_recall.py "时延 扩展" # 语义条目 + 文档章节 + 事件
python <skill>/scripts/bmem_recall.py "CP 长度" --project 52-link
python <skill>/scripts/bmem_recall.py --kind decision # 这个项目做过哪些决策
python <skill>/scripts/bmem_recall.py --recent 10 # 最近发生了什么
```
它只读本机镜像,不连中心库,离线可用。中文按 bigram 索引,**两到四个字的词组比整句命中率高**。
**为什么值得在动手前花这一分钟**:你即将做的决定可能三个月前已经做过,理由写在某条
decision 里;你即将踩的坑可能上次已经踩过并记了下来。事后返工的成本远大于开头查一次。
命中只是线索,不是依据——**按结果里的 `项目:Notes/xxx.md § N` 回读原文再下结论。**
## ./Notes 是这个记忆系统的一等公民
用户的工作习惯是:`PRxx.md`(需求)→ `Taskxx.md`(方案)→ `Resultxx.md`(结果),
都放在项目的 `./Notes` 下。bmem 按文件名把它们认成一组任务,全文入库、按标题拆成章节。
```bash
bmem notes # 扫描 ./Notes,把变化同步进记忆
bmem notes --check # 只比对差异,不写入任何内容
bmem notes --sync # 导入后立即同步到中心库
```
每次扫描会报出四种状态:**新增 / 变更 / 一致 / 消失**。判定用的是内容的 canonical
sha256(去 BOM、CRLF→LF、NFC),所以改了空行或换行符不会被误判成变更,反复跑是安全的——
内容没变就什么都不写。
两件值得知道的事:
- **文档从 ./Notes 里删掉后会被标记为"消失"**:它的历史修订全部保留(那是历史),
但不再计入任务闭环——否则闭环会显示成"由一个已不存在的文件闭合",那是假信息。
文件放回来会自动恢复。
- **项目记忆 `bmem_<prjID>.md` 里有一个自动维护的「Notes 索引」小节**:任务闭环表
(含「最近更新」= 日期 + 内容指纹)+ 其它文档清单。它完全由文件名、标题和内容 sha
确定性推导(不经 LLM),**内容变了它就变、没变它就一动不动**(连日期都不写,
否则会天天重写文件、每台机器都收到空更新);且只动这一节,手写的「设计决策」等内容不会被碰。
好处是:**只读项目记忆就能知道有哪些文档、哪些任务还没闭环、各自是不是最新的**,
不必查数据库。
**目录铁律(这是全局规则 G-0001)**:`./Notes` 根目录只允许放用户手动创建、或用户明确要求
创建的 md 文档。**你不能把运行过程中自动产生的状态、日志、中间结果写进 `./Notes/` 根目录**,
那些只能写到 `./Notes/auto/`(该子目录不会被导入记忆)。临时脚本和分析产物同理。
什么时候跑 `bmem notes`:用户新写或改完一篇 PR/Task/Result 之后、一段实质性工作收尾时。
重复跑是安全的——内容没变就什么都不做(不脏数据、不写 journal)。
### 语义条目:把文档内容变成可检索的结构
`bmem notes` 只做到"全文 + 章节"。**把文档内容抽成需求/决策/结论/遗留问题/参数/账号指针,
是你的活**——bmem 自己不调用 LLM。跑完 `bmem notes` 它会打印新修订清单和 sha256,
按这个格式写 JSON 再喂回去:
```json
{"facts": [
{"rel_path": "Notes/Task07.md",
"content_sha256": "<该修订的 sha256,从 bmem notes 的输出里抄>",
"items": [
{"kind": "decision", "title": "N2 的 CP 取 2us",
"body": "1us 余量不足,4us 损失过多有效符号时间;2us 是鲁棒性与效率的折中。",
"status": "done", "event_date": "2026-09-01", "section_no": 3}
]}
]}
```
```bash
bmem notes --facts facts.json --agent claude-code --model <你的模型名>
```
`kind` 取值:`requirement` `decision` `result` `issue` `param` `credential-pointer` `lesson` `other`。
`status` 取值:`open` `done` `superseded`(可省略)。
三件事值得知道:
- 条目**挂在具体修订的 sha256 下**,所以文档一改,旧条目自动退出"当前"视图,不会拿过期结论骗人。
- 同一修订**重复提交 = 重抽**,bmem 会写成新一代 `extraction_gen`,旧代保留但不再是当前——
抽得不好可以重来,不用怕污染。
- 抽取失败不影响主流程:全文和章节已经进库了,检索仍然兜得住。
**抽什么值得抽**:设计取舍和它的理由、被否决的方案和否决理由、遗留问题、关键参数、
踩过的坑。**不值得抽**:文档结构的复述、代码里已经写清楚的东西。
## 判断:这条信息该进哪一层
这是用 bmem 时唯一真正需要判断力的地方。用最上面那张表的判据问自己一遍。
```bash
# 全局:跨项目成立
bmem add --global "改完 Simulink 原生模型必须同步仿真模型,否则 RTL 已变而仿真还在验证旧行为"
# 项目:这个项目的约束/结论(默认写进「项目规则/约束」)
bmem add --prj "ADC 采样率固定 61.44MSps,下游所有速率按它推导"
# 项目:设计决策要写进「设计决策」节,并说清备选项和否决理由
bmem add --prj --section "设计决策" "N2 的 CP 取 2us:1us 余量不足,4us 损失过多有效符号时间"
# 机器:只对这台机器成立的事实
bmem add --machine "ADRV9009 评估板接在这台机器上,JTAG 走 USB-Blaster II"
bmem add --machine --section "账号/服务配置" "gitea 账号 bowei,凭证在 Windows 凭据管理器"
```
条目会自动编号(G-/P-/D-/M-)并带日期,追加写入,不会覆盖已有内容。
**`--section` 决定它落在文件的哪一节,不给就用默认节。** 各层可用的节和默认值:
| 层 | 默认节 | 其它可用节 |
|---|---|---|
| `--global` | 全局规则 | (通常就这一个) |
| `--prj` | 项目规则/约束 | 设计决策、当前状态 / 未解决问题、项目简介 |
| `--machine` | 工具环境 | 账号/服务配置、本机项目位置 |
节名要**原样写全**(含空格,如 `--section "当前状态 / 未解决问题"`);写一个不存在的节名会新建一节。
这件事值得留意:**尚未解决的问题不是"规则/约束"**。用默认节会把一条待办混进项目铁律里,
半年后读的人分不清哪些是必须遵守的、哪些只是还没做完的。用
`bmem add --prj --section "当前状态 / 未解决问题" "..."` 直接放对位置——
不要写完再去手工编辑 Markdown 搬家,那样绕过了自动编号,也容易破坏表格和已有条目。
**凭证的处理**:默认只在机器记忆里记「账号 + 凭证放在哪」,明文口令留在本机
`~/.bmem/config.toml`(不进任何仓库)。用户明确要求把某条明文写进机器记忆时照做——
那是他的私有 gitea,由他决定;但不要自作主张替他把口令写进去。
## 什么不值得记
写太多等于没记,检索会被噪音淹没:
- **代码和 git 历史已经说清楚的**:文件结构、某次修复的 diff、函数签名。记忆要回答"为什么这么改"。
- **只对当前这轮对话有意义的中间状态**:临时变量、调试到一半的猜测、下一步计划。
- **未经验证的猜测**——除非明确写成 `issue` 并标 `status: open`。
- **会话转录全文**。
反过来有一类东西特别值得记而常常被忘记:**被否决的方案和否决它的理由**。
只记结论,半年后会有人(很可能是你自己)重新提出同一个被否决的方案。
## 收尾之前
一段实质性工作结束前:
1. 该写的记忆按层写进去(`bmem add`);
2. 用户新增/改动的 Notes 文档导进来,并附上本次会话摘要:
```bash
bmem notes --session-summary <摘要文件> --agent claude-code
```
摘要文件写到临时目录或 `./Notes/auto/`,**不要写进 `./Notes/` 根目录**。
3. 对新修订生成语义条目 JSON 并入库(见上);
4. 同步出去:
```bash
bmem sync
```
`bmem sync` 做两件事:git 同步三层 Markdown(工作副本 ↔ `~/.bmem/repo` clone ↔ gitea),
以及与中心 PostgreSQL 双向同步 log 层。**它只碰 bmem 自己的文件,不会动你项目的 git 分支。**
## 多机与本机状态
```bash
bmem machines # 所有机器 + 各自的项目和路径
bmem machines --project 52-link # 这个项目在哪些机器上、各自路径、最近谁动过
bmem machines --json # 结构化输出
bmem sqlite # 本机镜像:位置、表结构、项目情况、内容摘要
bmem sqlite --schema # additionally 每张表的列定义
```
两条都**只读本机镜像、不连中心库**,离线可用。
`bmem machines` 会报注册表漂移:某机器只在 `bmem.md` 里有 = 它还没 push 或你还没 pull 到;
只在镜像里有 = **本机的 bmem.md 落后了**。这不是错误,是状态,读的时候要把它当成
"我看到的可能不是最新的"。
## 新项目、新机器
```bash
bmem install # 每台机器一次:生成 machineID、拉记忆仓库、装 CLAUDE.md/AGENTS.md adapter
bmem init # 每个项目一次,在项目根目录跑
```
`bmem init` 自己会判断三种情况:本机已注册过就提示不要重复注册;`bmem.md` 里已有这个项目
(说明别的机器建过)就从记忆仓库把 `bmem_<prjID>.md` 取回来并登记本机路径;全新项目才新建。
**所以在第二台机器上直接跑 `bmem init` 是对的**,不会造成身份分裂。
`bmem install` 幂等,可以反复跑:它会顺带把机器记忆里的 OS、用户根目录刷新成当前实际值。
## 从本机注销一个项目
```bash
bmem delete # 只打印会动哪些东西,不做任何改动
bmem delete --yes --sync # 确认执行并同步给其它机器
```
**它只注销本机**:删掉项目根目录的 `bmem_<prjID>.md`(**直接删除,不留备份文件**——
`find_project` 是向上查找的,残留一份会让它下面所有子目录都被误判成这个项目的根;
删除前会先把内容存进记忆仓库 `~/.bmem/repo/projects/`,所以内容不丢)、
`bmem.md` 里本机那一行、机器记忆的位置行、项目 `CLAUDE.md`/`AGENTS.md` 里的 BMEM 块,
以及中心库里 `project_locations` 中本机那一行。
**它不会删**:`./Notes` 下的任何文档、log 层的历史(修订/章节/条目/事件都留在中心库和镜像里)、
其它机器的登记、记忆仓库里的 `projects/bmem_<prjID>.md`。所以将来在任意机器上
`bmem init` 就能重新接上,历史一条不少。
三件要注意的事:
- **默认只预览**。不加 `--yes` 什么都不会发生,输出会逐项列出"将删除"与"不会删除"。
破坏性操作先看清楚再动手,这是这条命令唯一的使用纪律。
- 预览会告诉你**还有哪些机器登记着这个项目**。如果显示"本机是最后一台",说明删完就没有
任何机器持有它了——不是不能删,但要清楚这一步的含义。
- 中心库的删除是**排队执行**的:离线也能删,删除意图记在本地并写进 journal,
下次 `bmem sync` 成功后其它机器才会看到。所以删完记得 sync。
## 出问题时
| 症状 | 含义与处理 |
|---|---|
| `pg: 不可用(cannot reach PostgreSQL…)` | 中心库连不上。**数据没丢**:留在本机 outbox 和 `~/.bmem/journal/` 里,网络恢复后重跑 `bmem sync` 即可。所有命令本地照常可用 |
| `git: 冲突,已中止 rebase` | 两台机器改了同一个记忆文件。bmem **不会自动合并**(Markdown 是事实源),去 `~/.bmem/repo` 手工合并再 `bmem sync`。本地内容一条没丢 |
| `pull failed before any merge` | 传输失败,不是冲突。本地提交完好,push 仍会照常尝试 |
| 本地库损坏 / 想清空重来 | 直接删 `~/.bmem/bmem_local.sqlite` 再 `bmem sync`:已同步部分从中心库拉回,未推送部分由 journal 回放补齐。**这是设计好的恢复路径,不是下策** |
| `项目 X 已在本机注册,无需重复注册` | 正常提示,不是错误 |
| `facts reference an unknown revision` | facts JSON 里的 sha256 对不上。先跑一次 `bmem notes`,用它打印出来的 sha256 |
| `unknown fact kind` / `unknown status` | 枚举值写错了,对照上面的取值表 |
| 想知道还有多少没推上去 | `bmem sqlite` 底部的「未推送」和 journal 那一行 |
**一条通则**:bmem 的报告里出现的不都是待办。「pg 不可用」「bmem.md 落后了」描述的是状态,
先判断这个状态该不该改,再决定要不要动手。为了让输出变干净而执行有副作用的命令,
是把手段当成了目的。
## 命令速查
| 用途 | 命令 |
|---|---|
| 读记忆 | 直接读 `~/bmem.md`、`bmem_<prjID>.md`、`~/bmem_<machineID>.md` |
| 查历史 | `scripts/bmem_recall.py <关键词>` / `--kind` / `--recent` |
| 写记忆 | `bmem add --global\|--prj\|--machine [--section 节名] <内容>` |
| 导入 Notes | `bmem notes [--check] [--session-summary F] [--facts F] [--sync]` |
| 看多机/本机状态 | `bmem machines [--project P] [--json]` / `bmem sqlite [--schema] [--json]` |
| 同步 | `bmem sync` |
| 安装与初始化 | `bmem install` / `bmem init` |
| 注销项目 | `bmem delete`(预览)/ `bmem delete --yes --sync`(执行) |
| 帮助 | `bmem help` |
已知边界:当前 gitea 的 pack 服务故障,**push 正常但 clone/fetch 失败**,所以第二台机器
暂时拉不到 Markdown 层(log 层走 PostgreSQL 不受影响,Notes 全文在中心库里)。
看到 `bmem machines` 报"本机的 bmem.md 落后了"时,先想到这条。