Files
oc/memory/decisions/memory-store-format.md
T
xiaoshuai a64ea2acb3 Add memory plugin: three-tier markdown store with plugin-driven retrieval
A durable memory layer for OpenCode. Structure:

  ROOT.md          total plan: goals, hard rules, directory registry,
                   and a scenario -> file routing table
  <category>/
    index.md       one line per file, COMPILED from frontmatter
    <slug>.md      the memory itself

Two roots, same shape: <config>/memory/ (global) and
<project canonical>/.memory/ (project). Project wins on conflict; global
hard rules stay resident everywhere.

Why a plugin rather than a skill that tells the model to read a folder:
model-driven retrieval is unreliable — the model forgets, reads half the
files, or reads the wrong ones. Markdown is the human-facing format; the
plugin is the engine that parses, scores, and injects.

Measured, not assumed: FTS5's two built-in tokenizers both fail on this
corpus. On SQLite 3.53.4 with "部署脚本用 pnpm 而不是 npm...": unicode61
emits 7 terms for the whole sentence and matches 0 hits for "部署";
trigram needs >= 3 characters and also returns 0 for that two-character
word. So tokenization happens in the plugin (CJK bigrams, latin words)
and no SQL index is used — a thousand memories are fine to scan.

index.md and ROOT's two tables are compiled, never hand-edited: a
hand-maintained index drifts, a generated one cannot. Hit counters live
in .state.json so cross-device sync does not conflict on every recall.

Tools are named recall/remember/forget/inspect rather than
write/read/status: generic names were observed shadowing the harness's
own built-in tools.
2026-10-09 10:17:45 +08:00

27 lines
1.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: decisions/memory-store-format.md
kind: fact
summary: 选 Markdown 因为人类可纠正性和可同步性,检索由插件做而非模型。
highlight: 纯文本可手改、可 git diff;SQLite 的相关性排序解决的是规模问题,而记忆只有千级
created: 1791512156858
updated: 1791512156858
load_when:
- 记忆
- memory
- 存储选型
- 为什么用 markdown
---
评估过 SQLite + FTS5,最终选 Markdown + 插件检索。
**为什么放弃 SQLite**:
- 模型自动抽取一定会抽错。没有人类可读可编辑的存储,就没有纠正入口。**记忆错了比没有记忆更糟**。
- FTS5 的中文分词两种内置方案都不可用(见 pitfalls/sqlite-cjk-tokenizer 那条实测)。
- 相关性排序是**规模问题**,而记忆是千级条目,解决的是不存在的问题。
**Markdown 的代价及对策**:
- 检索不可靠 → 由插件解析、评分、注入,不依赖模型自觉
- 写入抖动(hit_count 每次检索都改文件)→ 统计拆到 .state.json,git 忽略
**已知边界**:万条量级时全表扫描会变慢,那时再换索引(正文是纯文本,迁移成本低)。