open-memex 0.2.0-alpha → 0.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -1,16 +1,23 @@
1
1
  # AGENTS.md
2
2
 
3
- Local-first memory plugin for opencode. See `README.md` and `PLAN.md` for user-facing docs and the roadmap. This file lists only the non-obvious things an agent needs to work in this repo.
3
+ Local-first memory plugin for opencode. See `README.md` (English) and `README.zh-CN.md` (Chinese)
4
+ for user-facing docs; `docs/V2-DESIGN.md` §18 for the roadmap. This file lists only the non-obvious things an agent needs to work in this repo.
4
5
 
5
6
  ## Runtime model — read before touching anything
6
7
 
7
- Two runtimes execute the same TypeScript source, with **no build step**:
8
+ Three entry points execute the same TypeScript source. **Development is build-free**;
9
+ the published npm package ships pre-compiled JS (`npm run build` → `dist/`,
10
+ via `prepublishOnly` — Node refuses `--experimental-strip-types` for files under
11
+ `node_modules`, so a global install cannot run `src/` directly):
8
12
 
9
13
  - **opencode host** loads `src/index.ts` under embedded **Bun**. SQLite here is `bun:sqlite` (built-in).
10
- - **CLI** (`src/cli.ts`) and smoke test run under **Node 22+** with `--experimental-strip-types`. SQLite here is `better-sqlite3` (native module).
14
+ - **CLI** (`src/cli.ts`) and smoke tests run under **Node 22+** with `--experimental-strip-types`. SQLite here is `better-sqlite3` (native module).
15
+ - **MCP server** (`src/mcp.ts`, stdio) runs under **Node 22+** with `--experimental-strip-types`. It exposes the same five memory tools to any MCP client (VS Code Copilot, Cursor, Claude Code). **stdout is the protocol channel — never log to stdout in `mcp.ts`; diagnostics go to stderr.**
11
16
 
12
17
  `src/store/db.ts` picks the backend at runtime by sniffing `globalThis.Bun`. Both backends share the same surface (`new Database(path)`, `.exec`, `.prepare().run/all/get`, `.close`). Any DB code you write must stay on that common subset — do not import `better-sqlite3` or `bun:sqlite` directly outside `db.ts`.
13
18
 
19
+ Tool logic is host-agnostic and lives in `src/tools/ops.ts` (plain functions + shared zod arg shapes + `TOOL_DESCRIPTIONS`). `src/tools/memory.ts` (opencode) and `src/mcp.ts` are thin adapters — when adding or changing a tool, change `ops.ts` once and both hosts pick it up.
20
+
14
21
  Consequences:
15
22
  - Imports **must** use explicit `.ts` extensions (`allowImportingTsExtensions: true`, `moduleResolution: "Bundler"`).
16
23
  - No transpile / bundle output. Do not add one; opencode loads the `.ts` file directly.
@@ -22,9 +29,26 @@ Consequences:
22
29
  npm install # once
23
30
  npm run typecheck # tsc --noEmit — the only lint/type gate
24
31
  npm run cli -- where | list | search "q" | add ... | forget <id> | reindex
32
+ npm run mcp # start the stdio MCP server
25
33
  node --experimental-strip-types scripts\smoke-pure.ts # runs pure-logic checks (no sqlite)
34
+ node --experimental-strip-types scripts\smoke-mcp.ts # MCP handshake + tool round-trip (temp dirs, no real data)
26
35
  ```
27
36
 
37
+ After `npm i -g open-memex@alpha` (or `npm link` from source), the `open-memex` bin is on
38
+ PATH: `open-memex mcp` starts the MCP server, `open-memex mcp --print-config <client>`
39
+ prints a client config snippet (client: vscode|cursor|claude|opencode|visualstudio),
40
+ `open-memex init [--client vscode|cursor|opencode|visualstudio] [--force] [--yes]`
41
+ one-command project setup (editor MCP config + .github/copilot-instructions.md;
42
+ resolves the server command at init time — npx fallback when no durable bin is on PATH, D17),
43
+ `open-memex config` prints the effective config, `open-memex capture --dry-run "text"`
44
+ previews keyword capture without writing, `open-memex doctor` runs health checks
45
+ (node version, config, scope resolution, storage writability, MCP handshake).
46
+ `open-memex init` asks editor + two settings on a TTY (`--yes` skips, scripts never
47
+ prompt); `open-memex config set <key> <value>` edits settings after install.
48
+ The published `open-memex` bin points at `dist/cli.js` (compiled at publish time).
49
+ From a source checkout, `npm run cli` / `npm run mcp` still run `src/` directly
50
+ with type-stripping — no build step needed for development.
51
+
28
52
  There is **no `npm test`** and no CI. Verification loop is: `npm run typecheck` + `smoke-pure.ts` + (if touching sqlite) `npm run cli -- reindex` against a scratch `MY_O_MEMORY_HOME`.
29
53
 
30
54
  To load the plugin in opencode locally, `~/.config/opencode/opencode.jsonc` must have:
@@ -56,7 +80,7 @@ Layout: `memories/<scope_key>/<id>.md` (YAML frontmatter + body) + `index.db` (S
56
80
 
57
81
  Every write path (tool, keyword hook, CLI `add`) must:
58
82
  1. Call `redact(content, cfg.redactPatterns)`. Built-in provider patterns live in `src/redact.ts` (always on); config `redactPatterns` is for user extras only.
59
- 2. If `hadSecret` → refuse the write (do not save `[REDACTED]` unless the user wrapped it in `<private>…</private>`).
83
+ 2. If `hadSecret` → the matched secret is **masked in place** (first 4 characters kept, the rest replaced with `x`) and the write proceeds; never save the unmasked original. `<private>…</private>` spans are stripped to `[REDACTED]` instead (design D14).
60
84
  3. Check `findDuplicates` (design §3.4): identical content is idempotent (return existing id); near-duplicates (similarity ≥ 0.8) warn but save — suggest `supersede` when the new content replaces the old.
61
85
  4. `writeMemoryFile` first, then `readMemoryFile` + `upsertFromFile` to keep FTS in sync.
62
86
 
@@ -67,7 +91,7 @@ Every write path (tool, keyword hook, CLI `add`) must:
67
91
  - Chain integrity is self-healing: on read, a missing counterpart is auto-completed with a warning; a dangling pointer warns but is never fabricated. Don't "fix" chains by editing frontmatter directly — let the read path do it.
68
92
  - Frontmatter is `schema_version: 2`. The SQLite index schema is versioned separately and rebuilds automatically on version change — never hand-edit `index.db`.
69
93
 
70
- Keyword capture fires from `chat.message` on the assistant's `output.parts` text. Patterns live in `src/capture/keywords.ts` / config `keywordPatterns`; regex group 1 is the memory body.
94
+ Keyword capture fires from `chat.message` on the user's message parts (`UserMessage`). Patterns live in `src/capture/keywords.ts` / config `keywordPatterns`; regex group 1 is the memory body. Scope routing: personal patterns (`cfg.keywordPersonalPatterns`) force the personal scope — the rule is 我 → personal (记住我/替我记/我觉得/我喜欢/remember for me), 我们 → current scope (我们认为/我们决定/帮我们记住); personal patterns run first and claim their line so a generic trigger can't double-fire.
71
95
 
72
96
  Context injection happens exactly once per session in `experimental.chat.system.transform`, guarded by an in-memory `Set<sessionID>` in `src/index.ts`. It is not persisted — restarting opencode re-injects on the next first turn.
73
97
 
@@ -83,7 +107,7 @@ log records what was already considered and rejected.
83
107
  Still hard: no cloud, no silent sync (explicit pull only), Markdown is the source
84
108
  of truth, `personal` scope never leaves the machine. Embeddings are an *optional
85
109
  capability* per the design — do not add them (or LLM-driven extraction, or a
86
- knowledge graph) without updating the design doc first. `PLAN.md` tracks the
110
+ knowledge graph) without updating the design doc first. `docs/V2-DESIGN.md` §18 tracks the
87
111
  build roadmap; the design doc tracks the *why*.
88
112
 
89
113
  ## Branch workflow
@@ -97,3 +121,9 @@ hold `V2` and `V2/…` simultaneously. Full rules: `CONTRIBUTING.md`.
97
121
  - `strict: true`, `verbatimModuleSyntax: false`. Prefer `import type` for types anyway.
98
122
  - Log prefix is `[open-memex]`. Gate verbose logs behind `cfg.logLevel === "debug"`.
99
123
  - Windows is a first-class target (this workspace is Windows). Use `node:path` and never hardcode `/`.
124
+ - **Docs ship with code.** Every code change updates the docs it affects in the same commit:
125
+ new/changed tools → `README.md` + `README.zh-CN.md` tool tables + MCP section (keep both
126
+ languages in sync); behavior changes → both READMEs
127
+ and the frozen `docs/V2-DESIGN.md` (append a `D<n>` decision entry, never rewrite history);
128
+ new commands → README CLI sections + this file's Commands. A change without its docs
129
+ is not done.
package/README.md CHANGED
@@ -1,45 +1,172 @@
1
1
  # open-memex
2
2
 
3
- Local-first persistent memory plugin for [opencode](https://opencode.ai).
3
+ [中文文档](./README.zh-CN.md)
4
+
5
+ Local-first persistent memory for AI coding agents: an [opencode](https://opencode.ai) plugin
6
+ plus a generic MCP server (VS Code Copilot, Cursor, Claude Code, Visual Studio, …).
4
7
 
5
8
  - **Markdown files** as the source of truth (human-editable, git-friendly)
6
9
  - **SQLite FTS5** as a rebuildable index (BM25 keyword search, via `better-sqlite3`)
7
10
  - **Zero cloud**, zero account, zero third-party API
8
- - Loads directly under opencode's embedded Bun runtime; CLI runs under Node — no build step, no Bun install
11
+ - Loads directly under opencode's embedded Bun runtime; CLI and MCP server run under Node — no build step in development (the published npm package ships pre-compiled JS), no Bun install
12
+
13
+ ## Installation
14
+
15
+ ### Requirements
16
+
17
+ - **Node.js ≥ 22.6** (`open-memex doctor` verifies this for you)
18
+
19
+ ### Step 1 — Install the CLI
20
+
21
+ **npm (recommended):**
22
+
23
+ ```sh
24
+ npm install -g open-memex@alpha
25
+ ```
26
+
27
+ This installs the `0.3.0-alpha` prerelease channel. (`latest` still points at the older
28
+ `0.1.0` stable.)
9
29
 
10
- ## Install (dev)
30
+ **No install — run via npx:**
11
31
 
32
+ ```sh
33
+ npx -y open-memex@alpha <command> # e.g. npx -y open-memex@alpha init --client vscode
12
34
  ```
13
- cd c:\github\open-memex
35
+
36
+ **From source** (bleeding edge, `V2-dev-p2` branch):
37
+
38
+ ```sh
39
+ git clone -b V2-dev-p2 https://github.com/stoneskin/open-memex.git
40
+ cd open-memex
14
41
  npm install
42
+ node --experimental-strip-types src/cli.ts <command>
15
43
  ```
16
44
 
17
- Then add to `~/.config/opencode/opencode.jsonc`:
45
+ > The `0.3.0-alpha` npm publish is cut from this branch — if `npx` still resolves an
46
+ > older alpha, install from source until the publish lands.
18
47
 
19
- ```jsonc
20
- {
21
- "$schema": "https://opencode.ai/config.json",
22
- "plugin": ["file:///c:/github/open-memex/src/index.ts"]
23
- }
48
+ #### "`open-memex` is not recognized" — PATH setup
49
+
50
+ A global `npm install -g` puts the `open-memex` launcher in npm's global bin folder.
51
+ If your terminal can't find it, that folder isn't on your `PATH`:
52
+
53
+ 1. Find the folder: `npm config get prefix`
54
+ - **Windows:** the launcher (`open-memex.cmd`) sits directly in that folder, e.g.
55
+ `C:\Users\<you>\AppData\Roaming\npm`
56
+ - **macOS / Linux:** it's in `<prefix>/bin`, e.g. `/usr/local/bin` or
57
+ `~/.nvm/versions/node/v22.x.x/bin`
58
+ 2. Add it to `PATH`:
59
+ - **Windows:** Settings → System → About → Advanced system settings →
60
+ Environment Variables → add the folder to the *User* `Path` → **restart the
61
+ terminal**. Verify with `where open-memex`.
62
+ - **macOS / Linux:** add `export PATH="$(npm prefix -g)/bin:$PATH"` to
63
+ `~/.zshrc` (or `~/.bashrc`), restart the shell, verify with
64
+ `command -v open-memex`.
65
+ 3. No admin rights / don't want to touch `PATH`? Use the npx form above — npx
66
+ resolves the package itself and needs no `PATH` changes.
67
+
68
+ ### Step 2 — One-command setup for your editor
69
+
70
+ Run from your **project root** (so the project scope resolves to this repo):
71
+
72
+ **VS Code** (Copilot):
73
+
74
+ ```sh
75
+ open-memex init --client vscode
76
+ # …or without a global install:
77
+ npx -y open-memex@alpha init --client vscode
24
78
  ```
25
79
 
26
- Restart opencode.
80
+ Writes `.vscode/mcp.json` and `.github/copilot-instructions.md`, then reload the
81
+ window and confirm the `open-memex` server is started in Copilot Chat's MCP panel.
82
+
83
+ **Cursor:**
84
+
85
+ ```sh
86
+ open-memex init --client cursor
87
+ ```
88
+
89
+ Writes `.cursor/mcp.json` and `.github/copilot-instructions.md`.
90
+
91
+ **opencode** (as a plain MCP consumer):
92
+
93
+ ```sh
94
+ open-memex init --client opencode
95
+ ```
96
+
97
+ Writes project-level `opencode.jsonc` (`type: "local"`). Prefer the native plugin
98
+ instead? Add `"plugin": ["file:///absolute/path/to/open-memex/src/index.ts"]` to
99
+ `~/.config/opencode/opencode.jsonc` — you get keyword auto-capture and first-turn
100
+ context injection on top of the tools.
101
+
102
+ **Claude Code** (from your project root):
103
+
104
+ ```sh
105
+ claude mcp add open-memex -- open-memex mcp
106
+ # …or print the config snippet: open-memex mcp --print-config claude
107
+ ```
108
+
109
+ **Visual Studio** (from your solution directory):
110
+
111
+ ```sh
112
+ open-memex init --client visualstudio
113
+ ```
27
114
 
28
- ## Tools the plugin exposes to the agent
115
+ Writes solution-level `.mcp.json` and `.github/copilot-instructions.md`. Requires
116
+ Visual Studio 2022 17.14+ or Visual Studio 2026 (**Windows-only**). Visual Studio
117
+ also auto-discovers `.vscode/mcp.json` and `.cursor/mcp.json`, so the VS Code setup
118
+ above works too.
119
+
120
+ **Codex:** no `init` client yet — add the server manually via
121
+ `open-memex mcp --print-config` as a starting point (`[mcp_servers]` in
122
+ `config.toml`, or `codex mcp add`).
123
+
124
+ `init` notes:
125
+
126
+ - On a terminal it interactively asks which editor to set up, whether to enable
127
+ keyword auto-capture, and whether to inject memories on the first turn.
128
+ `--yes` accepts the defaults; scripts / non-TTY never prompt (editor defaults to
129
+ VS Code).
130
+ - Existing config files are **merged, never clobbered** — re-running is safe.
131
+ `--force` overwrites.
132
+ - With no durable `open-memex` on `PATH` (e.g. one-shot npx), `init` writes an
133
+ `npx -y open-memex@alpha mcp` server command into the config so the setup keeps
134
+ working. `npm i -g open-memex@alpha` + `open-memex init --force` switches to the
135
+ faster direct command later.
136
+
137
+ ### Step 3 — Verify it works
138
+
139
+ ```sh
140
+ open-memex doctor
141
+ ```
142
+
143
+ Checks: Node version, config source, scope resolution for the current directory,
144
+ storage writability, then boots a real MCP server and runs `initialize` +
145
+ `tools/list` against it — all five tools must show up.
146
+
147
+ ## Tools the agent gets
29
148
 
30
149
  | Tool | What it does |
31
150
  |---|---|
32
- | `memory_add` | Save a fact, preference, decision, note |
33
- | `memory_search` | Keyword search (BM25) across project + personal memories |
34
- | `memory_list` | List memories in a scope, newest first |
151
+ | `memory_add` | Save a fact, preference, decision, note |
152
+ | `memory_search` | Keyword search (BM25) across project + personal memories |
153
+ | `memory_list` | List memories in a scope, newest first |
35
154
  | `memory_supersede` | Replace a memory with a newer version (keeps a supersede chain) |
36
- | `memory_forget` | Delete a memory by id |
155
+ | `memory_forget` | Delete a memory by id |
37
156
 
38
157
  ## Capture
39
158
 
40
- - **Keyword triggers** in user messages: `remember ...`, `note that ...`, `TIL ...`, `save this: ...`
159
+ - **Keyword triggers** in user messages (opencode native plugin): `remember …`,
160
+ `note that …`, `don't forget …`, `TIL …`, `save this …`, plus Chinese
161
+ `记住…` / `记一下` / `记录一下` / `别忘了…`.
162
+ Scope routing: first-person singular goes **personal** (`remember for me`,
163
+ `记住我…`, `替我记…`, `我觉得…`, `我喜欢…`); first-person plural goes to the
164
+ current **project** scope (`我们认为…`, `我们决定…`, `帮我们记住…`).
41
165
  - **Explicit tool calls** by the agent (via `memory_add`)
42
- - **Redaction**: content inside `<private>...</private>` tags is stripped; content matching secret patterns (API keys, tokens) is refused
166
+ - **Redaction**: content inside `<private>…</private>` tags is stripped; detected
167
+ secrets (API keys, tokens, high-entropy credentials) are masked in place — first
168
+ 4 characters kept, the rest replaced with `x` — and the memory is saved.
169
+ Preview what a message would capture with `open-memex capture --dry-run "…"`.
43
170
 
44
171
  ## Scopes
45
172
 
@@ -66,39 +193,115 @@ $XDG_DATA_HOME/open-memex/ (Linux/macOS)
66
193
  ```
67
194
 
68
195
  Each `.md` file has v2 YAML frontmatter (`id, scope, scope_key, visibility, role, type,
69
- importance, status, tags, created_at, updated_at, schema_version`, ...) followed by the
196
+ importance, status, tags, created_at, updated_at, schema_version`, …) followed by the
70
197
  memory content. You can edit them by hand — the plugin re-syncs on startup by comparing
71
198
  file mtimes. Markdown is the source of truth; the SQLite index is derived and rebuildable
72
199
  (`open-memex reindex`).
73
200
 
74
201
  ## Config
75
202
 
76
- Optional file at `~/.config/opencode/open-memex.jsonc`. See `PLAN.md` for defaults.
203
+ Optional file at `~/.config/opencode/open-memex.jsonc` (override path with
204
+ `MY_O_MEMORY_CONFIG`; override storage root with `MY_O_MEMORY_HOME`).
77
205
 
78
- ## CLI
206
+ Defaults:
79
207
 
80
- Runs under Node 22 with the built-in experimental TypeScript loader (no build step).
208
+ ```jsonc
209
+ {
210
+ "maxProjectMemories": 8, // top-N project memories injected on first turn
211
+ "maxProfileItems": 5, // top-N personal items injected on first turn
212
+ "injectOnFirstTurn": true, // [OPEN-MEMEX] system-prompt block
213
+ "keywordCaptureEnabled": true,
214
+ "logLevel": "info" // info | debug
215
+ }
216
+ ```
217
+
218
+ `open-memex config` prints the effective config (defaults + file).
219
+ Change a setting after install:
81
220
 
221
+ ```sh
222
+ open-memex config set keywordCaptureEnabled false
223
+ open-memex config set maxProjectMemories 12
82
224
  ```
83
- node --experimental-strip-types src/cli.ts where
84
- node --experimental-strip-types src/cli.ts list --scope project
85
- node --experimental-strip-types src/cli.ts search "auth flow"
86
- node --experimental-strip-types src/cli.ts add "This repo uses better-sqlite3" --type project-config
87
- node --experimental-strip-types src/cli.ts supersede <id> "Updated content"
88
- node --experimental-strip-types src/cli.ts status <id> deprecated
89
- node --experimental-strip-types src/cli.ts forget <id>
90
- node --experimental-strip-types src/cli.ts reindex
91
- node --experimental-strip-types src/cli.ts scopes
92
- node --experimental-strip-types src/cli.ts migrate --from <old-scope-key> [--dry-run]
93
- node --experimental-strip-types src/cli.ts migrate --to-v2 [--dry-run]
225
+
226
+ Settable keys: `maxProjectMemories`, `maxProfileItems`, `injectOnFirstTurn`,
227
+ `keywordCaptureEnabled`, `logLevel`. Full design: [docs/V2-DESIGN.md](./docs/V2-DESIGN.md).
228
+
229
+ ## CLI reference
230
+
231
+ Setup & health:
232
+
233
+ ```sh
234
+ open-memex init [--client vscode|cursor|opencode|visualstudio] [--force] [--yes]
235
+ open-memex config # print effective config
236
+ open-memex config set <key> <value> # change a setting
237
+ open-memex doctor # environment health check
238
+ open-memex capture --dry-run "记住我喜欢简洁的回答" # preview keyword capture
239
+ open-memex mcp --print-config vscode|cursor|claude|opencode|visualstudio
94
240
  ```
95
241
 
96
- Or via the npm script: `npm run cli -- list --scope project`.
97
- **Note:** flag arguments beyond the first must be passed via direct `node` invocation, not `npm run cli --`, because npm swallows unknown `--flag` args.
242
+ Memory operations:
243
+
244
+ ```sh
245
+ open-memex add "This repo uses better-sqlite3" --type project-config
246
+ open-memex search "auth flow"
247
+ open-memex list --scope project
248
+ open-memex supersede <id> "Updated content"
249
+ open-memex status <id> deprecated
250
+ open-memex forget <id>
251
+ ```
252
+
253
+ Maintenance:
254
+
255
+ ```sh
256
+ open-memex where # show storage + config paths
257
+ open-memex scopes # list project scopes with memory counts
258
+ open-memex reindex # rebuild the SQLite index from markdown
259
+ open-memex migrate --to-v2 [--dry-run] # v1 data → v2
260
+ ```
261
+
262
+ The CLI runs under Node 22. From a source checkout it uses the built-in experimental
263
+ TypeScript loader (no build step); the published npm package ships pre-compiled JS
264
+ (`npm run build` at publish time). From a source checkout, prefix every command with
265
+ `node --experimental-strip-types src/cli.ts` (or `npm run cli -- <command>` for
266
+ simple cases — npm swallows unknown `--flag` args, so prefer direct `node`).
267
+
268
+ ## MCP server
269
+
270
+ The same five memory tools over the Model Context Protocol via a stdio server —
271
+ no host-specific plugin needed. Any MCP client can use open-memex.
272
+
273
+ ```sh
274
+ open-memex mcp # after a global install
275
+ npx -y open-memex@alpha mcp # no install needed
276
+ ```
277
+
278
+ The project scope is resolved from the process working directory, so configure the
279
+ server with cwd set to your project root (`init` handles this for you).
280
+
281
+ > **Note:** MCP is request/response — it gives the agent tools, not the opencode
282
+ > plugin's automatic keyword capture or first-turn context injection. Proactive
283
+ > memory use depends on the agent's instructions (the `.github/copilot-instructions.md`
284
+ > that `init` writes).
285
+
286
+ ## Roadmap
287
+
288
+ **`0.3.0-alpha` (this release):** generic MCP server, `open-memex` bin/CLI, one-command
289
+ `init` setup, Chinese keyword capture with personal/project routing, `config` /
290
+ `capture --dry-run` / `doctor` helpers, Visual Studio support.
291
+
292
+ **Coming — `0.3.0-beta`:** team sync — shared memory via git (`propose` / `promote` /
293
+ `resolve` workflow, in-repo memory dir), 1–2 colleague pilot.
294
+
295
+ **Coming — `0.3.0` (stable):** org layer — org memory repo, curator convention,
296
+ distill-to-AGENTS.md assist.
98
297
 
99
- ## Status
298
+ **Future (signal-gated, no version committed):** native agent plugins (Claude Code /
299
+ Codex hooks as enhancement paths over the same MCP tools); local embeddings as a
300
+ benchmark-gated experiment (no embedding model is ever downloaded without explicit
301
+ opt-in); cloud `RemoteProvider` customization only if multi-repo sharing, ACL, or
302
+ compliance needs demand it.
100
303
 
101
- v2 alpha (`0.2.0-alpha`): v2 data model + migration, dedup + lifecycle (supersede/status), redaction hardening, CJK bigram retrieval. See `PLAN.md` for the roadmap (local embeddings, auto-capture, compaction hook, etc).
304
+ Design details: [docs/V2-DESIGN.md](./docs/V2-DESIGN.md) (append-only decision log D1–D20).
102
305
 
103
306
  ## License
104
307