mlx-bun 0.0.4

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.
Files changed (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +362 -0
  3. package/THIRD_PARTY_LICENSES.md +41 -0
  4. package/bin/mlx-bun.mjs +32 -0
  5. package/docs/curve-designer.html +303 -0
  6. package/docs/design/adapters-end-to-end.md +201 -0
  7. package/docs/design/compat-cli-surface-design.md +227 -0
  8. package/docs/design/docs-reorg-plan.md +152 -0
  9. package/docs/design/hlg-sampling.md +340 -0
  10. package/docs/design/memory-system.md +339 -0
  11. package/docs/design/optimization_plan.md +344 -0
  12. package/docs/design/parallel-slots.md +515 -0
  13. package/docs/design/runtime-isolation.md +247 -0
  14. package/docs/design/segmented-backward-training.md +508 -0
  15. package/docs/investigations/chunk-finetune-experiment.md +84 -0
  16. package/docs/investigations/curve-bisector-routing.md +123 -0
  17. package/docs/investigations/curve-runs/bisector-route.json +98 -0
  18. package/docs/investigations/curve-runs/bisector-trace.json +1393 -0
  19. package/docs/investigations/curve-runs/curve-terrain.json +1179 -0
  20. package/docs/investigations/curve-runs/curve-terrain.svg +42 -0
  21. package/docs/investigations/curve-terrain.html +105 -0
  22. package/docs/investigations/expert-offload-single-user-moe.md +292 -0
  23. package/docs/investigations/hlg-ab.html +34 -0
  24. package/docs/investigations/hlg-explorer.html +238 -0
  25. package/docs/investigations/hlg-figs/cliff.svg +1 -0
  26. package/docs/investigations/hlg-figs/cross.svg +1 -0
  27. package/docs/investigations/hlg-figs/edges.svg +1 -0
  28. package/docs/investigations/hlg-figs/k20-grids.svg +1 -0
  29. package/docs/investigations/hlg-figs/k20-peaks.svg +1 -0
  30. package/docs/investigations/hlg-figs/lw-curve.svg +1 -0
  31. package/docs/investigations/hlg-figs/terrain.svg +1 -0
  32. package/docs/investigations/hlg-report.html +262 -0
  33. package/docs/investigations/hlg-runs/hlg-ab.json +149 -0
  34. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +87 -0
  35. package/docs/investigations/hlg-runs/hlg-blind.json +107 -0
  36. package/docs/investigations/hlg-runs/hlg-cliff.json +197 -0
  37. package/docs/investigations/hlg-runs/hlg-cross.json +505 -0
  38. package/docs/investigations/hlg-runs/hlg-edge.json +388 -0
  39. package/docs/investigations/hlg-runs/hlg-eval1.json +25 -0
  40. package/docs/investigations/hlg-runs/hlg-frontier.json +86 -0
  41. package/docs/investigations/hlg-runs/hlg-grid.json +242 -0
  42. package/docs/investigations/hlg-runs/hlg-grid2.json +343 -0
  43. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +110 -0
  44. package/docs/investigations/hlg-runs/hlg-map.json +383 -0
  45. package/docs/investigations/hlg-runs/run0-original.log +159 -0
  46. package/docs/investigations/hlg-runs/runA-recommended.log +131 -0
  47. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +26 -0
  48. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +18 -0
  49. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +25 -0
  50. package/docs/investigations/hlg-runs/runAD-ab-samples.log +8 -0
  51. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +51 -0
  52. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +10 -0
  53. package/docs/investigations/hlg-runs/runAG-eval-config2.log +16 -0
  54. package/docs/investigations/hlg-runs/runB-gain-variants.log +192 -0
  55. package/docs/investigations/hlg-runs/runC-pivots.log +162 -0
  56. package/docs/investigations/hlg-runs/runD-oetf.log +132 -0
  57. package/docs/investigations/hlg-runs/runE-eotf.log +162 -0
  58. package/docs/investigations/hlg-runs/runF-shaper-working.log +86 -0
  59. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +101 -0
  60. package/docs/investigations/hlg-runs/runH-wsweep.log +176 -0
  61. package/docs/investigations/hlg-runs/runI-asweep.log +176 -0
  62. package/docs/investigations/hlg-runs/runJ-knobmap.log +49 -0
  63. package/docs/investigations/hlg-runs/runK-frontier.log +19 -0
  64. package/docs/investigations/hlg-runs/runL-widemap.log +65 -0
  65. package/docs/investigations/hlg-runs/runM-frontier-emb.log +15 -0
  66. package/docs/investigations/hlg-runs/runN-verify.log +116 -0
  67. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +15 -0
  68. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +15 -0
  69. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +15 -0
  70. package/docs/investigations/hlg-runs/runR-blind-transcript.log +79 -0
  71. package/docs/investigations/hlg-runs/runS-cross-coherence.log +33 -0
  72. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +33 -0
  73. package/docs/investigations/hlg-runs/runU-cross-12b.log +33 -0
  74. package/docs/investigations/hlg-runs/runV-lw-e4b.log +22 -0
  75. package/docs/investigations/hlg-runs/runW-lw-12b.log +22 -0
  76. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +22 -0
  77. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +26 -0
  78. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +26 -0
  79. package/docs/investigations/hlg-sampling-investigation.md +970 -0
  80. package/docs/investigations/lab-build-journal.md +157 -0
  81. package/docs/investigations/pi-builtin-investigation.md +308 -0
  82. package/docs/investigations/starter-model-port-handoff.md +323 -0
  83. package/docs/planning/IDEAS.md +26 -0
  84. package/docs/planning/PRODUCT_ROADMAP.md +426 -0
  85. package/docs/planning/ResearchTopics.md +119 -0
  86. package/docs/planning/chunk-task-roadmap.md +77 -0
  87. package/docs/planning/journal.md +155 -0
  88. package/docs/reference/distribution.md +121 -0
  89. package/docs/reference/embedding.md +168 -0
  90. package/docs/reference/library-api.md +153 -0
  91. package/docs/reference/server-api.md +224 -0
  92. package/docs/reference/server-config.md +243 -0
  93. package/docs/segmented-backward-handoff.md +148 -0
  94. package/package.json +68 -0
  95. package/src/anthropic.ts +491 -0
  96. package/src/chat-template.ts +186 -0
  97. package/src/cli.ts +1075 -0
  98. package/src/config.ts +229 -0
  99. package/src/curve-sampler.ts +122 -0
  100. package/src/dataset/generators.ts +1087 -0
  101. package/src/dataset/index.ts +12 -0
  102. package/src/dataset/job.ts +81 -0
  103. package/src/dataset/llm.ts +71 -0
  104. package/src/dataset/registry.ts +528 -0
  105. package/src/download.ts +283 -0
  106. package/src/eval/README.md +86 -0
  107. package/src/eval/kl-prompts.ts +29 -0
  108. package/src/eval/kl.ts +294 -0
  109. package/src/eval/quality-db.ts +92 -0
  110. package/src/eval/runner.ts +102 -0
  111. package/src/eval/score.ts +49 -0
  112. package/src/eval/tasks/bfcl.ts +500 -0
  113. package/src/eval/tasks/gsm8k.ts +85 -0
  114. package/src/eval/tasks/hashhop.ts +109 -0
  115. package/src/eval/tasks/humaneval.ts +252 -0
  116. package/src/eval/tasks/ifeval.ts +354 -0
  117. package/src/eval/tasks/mmlu.ts +145 -0
  118. package/src/evaldb.ts +199 -0
  119. package/src/expert-offload-build.ts +77 -0
  120. package/src/expert-offload.ts +61 -0
  121. package/src/expert-trace.ts +67 -0
  122. package/src/fit.ts +254 -0
  123. package/src/generate.ts +451 -0
  124. package/src/harness-pi.ts +177 -0
  125. package/src/hf-push.ts +628 -0
  126. package/src/index.ts +22 -0
  127. package/src/jobs/db.ts +139 -0
  128. package/src/jobs/index.ts +29 -0
  129. package/src/jobs/job-entry.ts +106 -0
  130. package/src/jobs/runner.ts +304 -0
  131. package/src/jobs/sse.ts +114 -0
  132. package/src/jobs/types.ts +58 -0
  133. package/src/kv-store.ts +185 -0
  134. package/src/lora.ts +314 -0
  135. package/src/md-modules.d.ts +7 -0
  136. package/src/mlx/array.ts +237 -0
  137. package/src/mlx/autograd.ts +267 -0
  138. package/src/mlx/checkpoint.ts +116 -0
  139. package/src/mlx/compile.ts +158 -0
  140. package/src/mlx/custom-vjp.ts +140 -0
  141. package/src/mlx/ffi.ts +433 -0
  142. package/src/mlx/metal-kernel.ts +130 -0
  143. package/src/mlx/ops.ts +707 -0
  144. package/src/mmap.ts +90 -0
  145. package/src/model/batched-mask.ts +204 -0
  146. package/src/model/batched-rotating.ts +300 -0
  147. package/src/model/compiled-decode.ts +681 -0
  148. package/src/model/factory.ts +27 -0
  149. package/src/model/fingerprint.ts +33 -0
  150. package/src/model/flash-attention.ts +674 -0
  151. package/src/model/fused-decode-kernel.ts +305 -0
  152. package/src/model/fused-geglu-kernel.ts +87 -0
  153. package/src/model/gemma4-base.ts +1616 -0
  154. package/src/model/gemma4.ts +1012 -0
  155. package/src/model/generated/gemma4-12b.ts +526 -0
  156. package/src/model/generated/gemma4-26b.ts +500 -0
  157. package/src/model/generated/gemma4-e4b.ts +757 -0
  158. package/src/model/generated/index.ts +18 -0
  159. package/src/model/minicpm5.ts +278 -0
  160. package/src/model/qwen3-delta.ts +224 -0
  161. package/src/model/qwen3_5.ts +429 -0
  162. package/src/model/support.ts +46 -0
  163. package/src/native-pack.ts +152 -0
  164. package/src/pi-provider.ts +95 -0
  165. package/src/pi-terminal.ts +264 -0
  166. package/src/pi-web.ts +924 -0
  167. package/src/preflight.ts +123 -0
  168. package/src/prompt-cache.ts +113 -0
  169. package/src/quantize/allocator.ts +627 -0
  170. package/src/quantize/calibration.ts +180 -0
  171. package/src/quantize/config-writer.ts +132 -0
  172. package/src/quantize/index.ts +57 -0
  173. package/src/quantize/job.ts +136 -0
  174. package/src/quantize/quantizer.ts +462 -0
  175. package/src/quantize/safetensors-writer.ts +171 -0
  176. package/src/quantize/sensitivity.ts +234 -0
  177. package/src/registry.ts +336 -0
  178. package/src/responses.ts +774 -0
  179. package/src/safetensors.ts +158 -0
  180. package/src/sampler.ts +517 -0
  181. package/src/serve/batch-scheduler.ts +362 -0
  182. package/src/serve/generation-gateway.ts +160 -0
  183. package/src/server.ts +1891 -0
  184. package/src/spec/drafter.ts +261 -0
  185. package/src/spec/generate.ts +221 -0
  186. package/src/status-page.html +497 -0
  187. package/src/tokenizer.ts +38 -0
  188. package/src/tool-call.ts +242 -0
  189. package/src/train/dataset.ts +461 -0
  190. package/src/train/export.ts +32 -0
  191. package/src/train/forward.ts +229 -0
  192. package/src/train/index.ts +43 -0
  193. package/src/train/job.ts +148 -0
  194. package/src/train/lora-params.ts +194 -0
  195. package/src/train/loss.ts +342 -0
  196. package/src/train/merge.ts +195 -0
  197. package/src/train/optimizer.ts +176 -0
  198. package/src/train/rank.ts +101 -0
  199. package/src/train/segmented.ts +520 -0
  200. package/src/train/trainer.ts +600 -0
  201. package/src/tui.ts +161 -0
  202. package/src/vision/embedder.ts +168 -0
  203. package/src/vision/preprocess.ts +247 -0
  204. package/src/vision/prompt.ts +158 -0
  205. package/src/vision/siglip.ts +599 -0
  206. package/src/web/app.html +2471 -0
  207. package/src/web/skills/web-research/SKILL.md +44 -0
  208. package/src/web/skills.ts +59 -0
  209. package/src/web-tools.ts +426 -0
  210. package/src/weights.ts +91 -0
@@ -0,0 +1,339 @@
1
+ # Memory system — design sketch
2
+
3
+ Status: **design** (nothing built yet; capture prerequisite already landed)
4
+ Owner: assistant layer (pi-web / pi-terminal / web-tools / jobs)
5
+ Default: **off** until the user opts in (vault + schedule are explicit, consented actions)
6
+
7
+ Ported from **lucien** (`~/Code/lucien`, vault at `~/Dreaming`) — a separate,
8
+ already-working system at real scale (thousands of conversations, hundreds of
9
+ articles). We are **not importing lucien**; we are reimplementing its ideas as a
10
+ first-class, reusable mlx-bun module that runs on the **local model** and wires
11
+ into mlx-bun's own substrate (sessions, jobs, web-tools, skills, CLI).
12
+
13
+ ## Goal
14
+
15
+ Give the local assistant durable, user-specific memory so it can **resume
16
+ instead of restart**. The product thesis is "local to you" — the moat is
17
+ private accumulated context, not the weights ([[local-to-you-thesis]]). Memory
18
+ is how that context accumulates.
19
+
20
+ Three steps, the **flywheel**:
21
+
22
+ 1. **Capture** — conversations during sessions are saved to disk.
23
+ 2. **Synthesize** — nightly, a scheduled pass turns those conversations into
24
+ *articles* (a small personal wiki).
25
+ 3. **Consult** — the assistant (web + CLI) has read tools + a skill that make it
26
+ read the relevant articles when answering.
27
+
28
+ Talk → assistant reads the wiki → you add/correct context → nightly synthesis
29
+ folds it into articles → richer next conversation. Articles are *priors*,
30
+ conversations are *evidence*, synthesis updates the priors over time; chat-time
31
+ access is read-only.
32
+
33
+ ## Naming: "memory", not "the Dreaming"
34
+
35
+ Recommendation: user-facing name is **memory** (`mlx-bun memory …`), the store
36
+ is `~/.mlx-bun/memory/`. We keep lucien's *good descriptive concepts* (articles,
37
+ wikilinks, Meta governance pages, Talk pages, conservative integrate-don't-
38
+ overwrite synthesis) but drop the mythology ("the Dreaming", "librarian",
39
+ "dreaming"). Reasons:
40
+
41
+ - The Dreaming mythology is Josh's personal branding for a *different* project.
42
+ mlx-bun has its own identity (MLX-only, bun/JS, Apple Silicon, "local to
43
+ you" — [[mlx-bun-scope-and-framing]]). Importing the cosmology muddies the
44
+ product story.
45
+ - "Memory" is the term users already hold (ChatGPT/Claude memory). It's
46
+ self-explanatory in `--help` and in the assistant's "what can you do?" list —
47
+ no glossary required.
48
+ - This is a port/reimplementation, not lucien-the-dependency. A plain name
49
+ avoids implying we ship or require the external lucien MCP.
50
+
51
+ ## Port, not import: what carries over and what changes
52
+
53
+ | Aspect | lucien | mlx-bun memory |
54
+ | --- | --- | --- |
55
+ | Read interface | MCP server (stdio) | native web-tools + a bundled skill |
56
+ | Synthesis engine | spawns `claude -p --model opus` (cloud) | **the local model** (in-process / local server) |
57
+ | Conversation sources | claude-code JSONL + claude.ai (Playwright) + codex | **mlx-bun's own sessions** only (web + pi terminal) |
58
+ | Pipeline orchestration | `nightly.sh` + ~36 standalone scripts | a **job runner** on `src/jobs/*` (progress → web UI via SSE) |
59
+ | Scheduling | user-added crontab line | `mlx-bun memory schedule` installs a **launchd** agent |
60
+ | Setup | `lucien_setup` MCP tool | `mlx-bun memory setup` **or** the assistant via a skill |
61
+ | Vault | `~/Dreaming` markdown + git | `~/.mlx-bun/memory/` markdown + git (same format) |
62
+ | State DB | `.lucien/lucien.db` (sqlite) | `memory.sqlite` (sqlite) — see storage decision below |
63
+
64
+ The hard, proven parts we keep wholesale: the **article format** (lead +
65
+ sections + `## References` with `conv:` footnotes + `[[wikilinks]]`), the
66
+ **Meta governance pages** (editorial conventions live *in* the vault, read by
67
+ the synthesis prompts), **idempotency** (watermarks + per-chunk synthesized
68
+ markers so re-runs are safe), and the **conservative synthesis gate** (preserve
69
+ prose, ≥70% word-count floor, every original citation survives).
70
+
71
+ The big departure is **synthesis runs locally**. lucien outsources the hard NLP
72
+ to Opus; we do it on e4b/12B. That fits the privacy thesis (nothing leaves the
73
+ machine) and lines up with the planned **memory LoRAs** — each pipeline stage
74
+ (chunk / classify / synthesize / wikify) is a future specialized adapter routed
75
+ via `adapterScoped` ([[lora-routing-architecture]]). Synthesis quality on a
76
+ local model is the main open *quality* risk; it's a nightly batch job where
77
+ latency doesn't matter, so we gate output the way lucien does. Graceful
78
+ degradation applies
79
+ ([[three-tier-parity-and-degradation]]): a weak synthesis pass should no-op, not
80
+ corrupt the vault.
81
+
82
+ ## Architecture
83
+
84
+ ### Storage layout
85
+
86
+ mlx-bun already splits durable user state from rebuildable cache:
87
+
88
+ - `~/.mlx-bun/` — **durable, user-owned**: `sessions/` (web chat JSONL),
89
+ `pi/` (terminal sessions), `pi-sessions/` (web agentDir), `skills/`,
90
+ `hf.json`.
91
+ - `~/.cache/mlx-bun/` — **rebuildable / derived**: `registry.sqlite`,
92
+ `evals.sqlite`, `jobs.sqlite`, `jobs/`, `datasets/`, `quants/`, `adapters/`.
93
+
94
+ Proposed:
95
+
96
+ ```
97
+ ~/.mlx-bun/memory/ # the vault — precious, user-owned, git-tracked
98
+ articles/ # Topic_Name.md (underscored stems)
99
+ Meta/ # Editorial_Guidelines.md, Article_Conventions.md,
100
+ # Buckets.md, Topics_to_Ignore.md, Synthesis_Pipeline.md
101
+ Talk/ # per-article discussion / conflict notes
102
+ README.md
103
+ .git/ # every synthesis run commits here
104
+ .gitignore # ignores memory.sqlite* (don't commit a binary)
105
+ memory.sqlite # synthesis bookkeeping (cursors, chunks, buckets)
106
+ ```
107
+
108
+ **Everything lives under `~/.mlx-bun/memory/`** — the vault *and* the bookkeeping
109
+ DB (decided 2026-06-14). The win is that "your memory" is one self-contained,
110
+ portable folder: copy it and your memory moves to another machine, intact. It
111
+ also keeps the privacy story literal — one place to point at and one place to
112
+ delete. The DB is derived state (it can be rebuilt from the transcripts +
113
+ articles), so the seeded `.gitignore` excludes `memory.sqlite*` — git tracks the
114
+ articles (the source of truth, with history), not the binary index. This is a
115
+ deliberate, documented exception to the codebase's cache-vs-durable split
116
+ (`evals`/`jobs`/`registry` dbs live in `~/.cache/mlx-bun/`), justified by
117
+ treating memory as a single portable unit.
118
+
119
+ ### The vault
120
+
121
+ Identical in spirit to lucien's. `mlx-bun memory setup` seeds it idempotently:
122
+ create dirs, write Meta pages (only if missing — never clobber user edits),
123
+ write README, `git init` + initial commit. Articles are plain markdown:
124
+
125
+ ```markdown
126
+ # Archie Project
127
+
128
+ The **Archie Project** is an internal AI agent platform Josh built at
129
+ [[AlphaPoint]] beginning spring 2026.[^1][^2]
130
+
131
+ ## Origin
132
+ ...[^1]
133
+
134
+ ## References
135
+ [^1]: `conv:a1b2c3d4` (2026-05-10, mlx-bun) — Archie design overview
136
+ ```
137
+
138
+ Citations point at `conv:<hash>` — a stable id derived from the source session,
139
+ so an article is traceable back to the conversation that produced it. The vault
140
+ is a valid Obsidian vault for free (browse with Obsidian, edit by hand; the next
141
+ synthesis run respects your edits).
142
+
143
+ ### Ingestion — mlx-bun sessions only
144
+
145
+ No Playwright, no web scraping. The capture prerequisite **already exists**:
146
+ web chat persists each session to `~/.mlx-bun/sessions/*.jsonl` via
147
+ `SessionManager.create(...)` ([pi-web.ts:398](../../src/pi-web.ts)), and the
148
+ comment there already names this as "the durable transcript store the nightly
149
+ memory pipeline reads." Terminal pi persists to `~/.mlx-bun/pi`. Both are pi's
150
+ own JSONL format, enumerable via `SessionManager.list/listAll`.
151
+
152
+ So ingestion = read pi sessions → normalize to `{conv uuid, messages[]}` →
153
+ upsert into `memory.sqlite`, tracking a per-source watermark so each nightly run
154
+ only processes what's new. pi's session format becomes the ingestion contract
155
+ for free.
156
+
157
+ ### The nightly pipeline (on `src/jobs/*`)
158
+
159
+ Reuse the existing background-job substrate (`src/jobs/{db,runner,sse}.ts`):
160
+ register a `memory-synthesis` runner and `submitSubprocess(...)` it so model
161
+ state is GPU-isolated. Stages mirror lucien, each emitting `stage`/`log` events
162
+ that stream to the web UI through the existing SSE endpoint — synthesis shows up
163
+ in the same jobs panel as quantize/finetune.
164
+
165
+ ```
166
+ ingest pi sessions → memory.sqlite (watermark-gated, upsert)
167
+ chunk segment each new conversation into topic chunks (model call)
168
+ cluster assign chunks to existing buckets / propose new (model call)
169
+ synthesize per bucket: create-or-update its article (model call)
170
+ wikify deterministic gate + Wikipedia-style cleanup (non-fatal)
171
+ normalize canonical [[wikilinks]], footnote repair
172
+ changelog per-run digest → Meta/Changelog.md, git commit
173
+ ```
174
+
175
+ Idempotency is inherited from lucien's design: watermarks (don't re-ingest),
176
+ `chunked_at > updated_at` (re-chunk only changed convs), and a
177
+ `synthesized_bucket_chunks` table (never feed the same chunk into an article
178
+ twice). A killed run resumes cleanly.
179
+
180
+ ### Synthesis runs on the local model
181
+
182
+ `mlx-bun memory synthesize` loads a model in-process (or reuses a running
183
+ server) and drives every model call through it — **no cloud, local-only**
184
+ (decided 2026-06-14). Default synthesis model: **e4b** (decided 2026-06-14) —
185
+ lighter, lower memory, and mlx-bun's strongest h2h result; a weak pass is gated
186
+ to no-op rather than allowed to corrupt the vault. Overridable per-run
187
+ (`--model 12B` when you want the parity model's quality). This is the seam where
188
+ the future memory
189
+ LoRAs plug in: today base-model + prompt per stage; later `adapterScoped` per
190
+ stage ([[lora-routing-architecture]]).
191
+
192
+ ### Read tools — how the assistant consults memory
193
+
194
+ Add native read tools in `src/web-tools.ts` (the `defineTool` pattern), name
195
+ them in `WEB_TOOL_NAMES`, list them in `ALL_TOOLS` in both
196
+ [pi-web.ts](../../src/pi-web.ts) and [pi-terminal.ts](../../src/pi-terminal.ts);
197
+ read-only, so they auto-allow (no approval gate). Mirror lucien's read surface:
198
+
199
+ - `memory_search` — keyword/substring search across articles → ranked hits with
200
+ section anchors (the discovery entry point)
201
+ - `memory_read` — full article body
202
+ - `memory_list` — list article titles (fallback / overview)
203
+ - (later) `memory_section`, `memory_links` for focused reads + wikilink graph
204
+
205
+ **Knowing *when* to consult** uses three reinforcing mechanisms:
206
+ 1. Tool descriptions that strongly cue "search the user's memory when they
207
+ mention their own projects, people, tools, preferences, or history."
208
+ 2. A bundled **memory skill** (below) that says "consult quietly before
209
+ answering personal-context questions" — same trigger surface as the
210
+ `anthropic-skills:lucien` skill.
211
+ 3. Cheap **index injection**: at session start, put the *list of article titles*
212
+ into the system prompt (a few hundred tokens) so the model knows what exists
213
+ and can fetch the right page. (Not the article bodies — that's what the tools
214
+ are for.)
215
+
216
+ ## Two front doors: CLI + assistant
217
+
218
+ One implementation (the CLI / `src/memory` module), two ways to reach it.
219
+
220
+ ### CLI — `mlx-bun memory <subcommand>`
221
+
222
+ New `case "memory"` in [cli.ts](../../src/cli.ts) + a `HELP.memory` entry.
223
+
224
+ ```
225
+ mlx-bun memory setup create the vault + Meta pages + git (idempotent)
226
+ mlx-bun memory status vault path, #articles, last synthesis, schedule state
227
+ mlx-bun memory synthesize run the pipeline now (--model, --since, --dry-run)
228
+ mlx-bun memory schedule install the nightly launchd agent (--at 03:00)
229
+ mlx-bun memory unschedule remove the launchd agent
230
+ mlx-bun memory search <q> inspect: search articles from the terminal
231
+ mlx-bun memory read <title> inspect: print an article
232
+ mlx-bun memory forget <title> delete an article (git-tracked, recoverable)
233
+ ```
234
+
235
+ ### Assistant-driven setup (a bundled skill)
236
+
237
+ Add `src/web/skills/memory/SKILL.md` to `BUNDLED_SKILLS`
238
+ ([web/skills.ts](../../src/web/skills.ts)). This is the best vehicle because:
239
+
240
+ - The skill's **description** makes "manage memory" appear under "what can you
241
+ do?" for free.
242
+ - The skill's **body** encodes the explain → consent → setup script: explain in
243
+ plain terms (it's a folder of markdown articles; it saves your conversations;
244
+ it synthesizes them into articles nightly; it uses them to remember you), then
245
+ on agreement run the `mlx-bun memory setup` and `mlx-bun memory schedule`
246
+ commands via the bash tool.
247
+
248
+ So the assistant can both **offer/explain** memory and **set it up** for you,
249
+ and the single CLI implementation stays the source of truth.
250
+
251
+ ### Consent model
252
+
253
+ Drawn deliberately, two tiers:
254
+
255
+ - **Capture is default-on, not a consent gate.** Saving sessions locally is what
256
+ pi already does (like shell history) and it never leaves the machine. But
257
+ default-on ≠ silent: state it once ("I keep our chats at `~/.mlx-bun/sessions`
258
+ so I can remember — clear them anytime"). The recent-chats sidebar doubles as
259
+ the "where's my data / delete it" surface.
260
+ - **Synthesis into a persistent wiki + a scheduled job IS the consent gate** —
261
+ that's what changes the privacy posture. The skill asks in prose, and the
262
+ per-action approval gate confirms each persistent change (writing the vault,
263
+ installing the launchd agent). Two natural confirmations, the right amount for
264
+ installing a recurring job.
265
+
266
+ ## Scheduling (launchd)
267
+
268
+ mlx-bun has no scheduler today. Recommendation: **launchd**, not crontab.
269
+ mlx-bun is macOS/Apple-Silicon-only by identity, so launchd is the native
270
+ choice — it survives reboot, runs missed jobs, and gives clean
271
+ install/uninstall. `mlx-bun memory schedule` writes
272
+ `~/Library/LaunchAgents/com.mlx-bun.memory.plist` (a `StartCalendarInterval` at
273
+ ~03:00 running `mlx-bun memory synthesize`) and `launchctl load`s it;
274
+ `unschedule` unloads + removes it. Schedule state surfaces in
275
+ `mlx-bun memory status`.
276
+
277
+ ## Privacy (the throughline)
278
+
279
+ Local model + local vault + local cron + local transcripts — **nothing leaves
280
+ the machine**. This is consistent with the web-chat privacy framing where the
281
+ web tools are the only outbound path. It is also the differentiator: not the
282
+ best AI, the best at knowing *you* ([[local-to-you-thesis]]).
283
+
284
+ ## Module layout (reusable)
285
+
286
+ A self-contained `src/memory/` module so the feature is reusable by both the CLI
287
+ and the server, and is testable in isolation:
288
+
289
+ ```
290
+ src/memory/
291
+ vault.ts paths, setup (dirs + Meta + git), article read/write/list
292
+ db.ts memory.sqlite: conversations, chunks, buckets, watermarks
293
+ ingest.ts pi sessions → db (uses SessionManager.list/listAll)
294
+ chunk.ts conversation → topic chunks (local-model call)
295
+ cluster.ts chunks → buckets (local-model call)
296
+ synthesize.ts bucket → article create/update + gate (local-model call)
297
+ wikify.ts deterministic editorial gate + normalize
298
+ pipeline.ts registerRunner("memory-synthesis", …) — ties stages together
299
+ tools.ts memory_search / memory_read / memory_list (web-tools)
300
+ schedule.ts launchd plist install/remove
301
+ prompts/ per-stage prompts (the future LoRA seams)
302
+ ```
303
+
304
+ ## Phasing
305
+
306
+ - **M0 — vault + read path.** `src/memory/{vault,db}.ts`, `memory setup`, the
307
+ read tools + index injection, the bundled skill (offer/explain/setup). No
308
+ synthesis yet — the assistant can already read a hand-written or imported
309
+ vault. Lets us validate the *consult* half against a real vault (even one
310
+ copied from `~/Dreaming`) before building the pipeline.
311
+ - **M1 — ingest + pipeline (manual).** `ingest/chunk/cluster/synthesize/wikify`
312
+ as a `memory-synthesis` job, run on demand via `memory synthesize`. Validate
313
+ synthesis quality on the local model against every model/quant we care about
314
+ ([[per-model-quant-specialization]]).
315
+ - **M2 — schedule.** launchd install/remove; status surfacing; transparency
316
+ line on first capture.
317
+ - **M3 — quality + LoRAs.** Per-stage memory LoRAs via `adapterScoped`; KL /
318
+ quality benchmarks for the synthesis output ([[lora-routing-architecture]]).
319
+
320
+ ## Help text + docs changes (don't forget)
321
+
322
+ - `HELP.memory` in [cli.ts](../../src/cli.ts) (+ the top-of-file command list).
323
+ - README: a "Memory" section under the pitch (the flywheel + privacy).
324
+ - `docs/reference/`: a `memory.md` (vault format, CLI surface, tool list).
325
+ - This design doc; update PLAN.md with a Memory phase + exit criteria.
326
+ - The bundled skill description (so "manage memory" shows in "what can you do?").
327
+
328
+ ## Decisions (settled 2026-06-14)
329
+
330
+ 1. **Storage** — everything (vault + `memory.sqlite`) under `~/.mlx-bun/memory/`,
331
+ one portable folder; `.gitignore` excludes the DB.
332
+ 2. **Synthesis engine** — local-only, no cloud; weak output is gated to no-op.
333
+ 3. **Default synthesis model** — e4b, overridable per-run (`--model 12B`).
334
+
335
+ ## Open decisions
336
+
337
+ 1. **Retroactive capture.** On first setup, synthesize past sessions too, or
338
+ future-only? Recommendation: offer "synthesize what's already here" as a
339
+ one-time step right after setup, surfaced by the skill.