mlx-bun 0.0.4 → 0.0.6

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 (90) hide show
  1. package/README.md +175 -93
  2. package/docs/dag/training-inference-map.html +575 -0
  3. package/docs/design/adapters-end-to-end.md +50 -46
  4. package/docs/design/compat-cli-surface-design.md +10 -8
  5. package/docs/design/docs-reorg-plan.md +14 -1
  6. package/docs/design/hlg-sampling.md +12 -2
  7. package/docs/design/memory-system.md +193 -295
  8. package/docs/design/optimization_plan.md +4 -2
  9. package/docs/design/orpo-dynamic-lambda.md +179 -0
  10. package/docs/design/orpo-future-enhancements.md +340 -0
  11. package/docs/design/orpo-training.md +1212 -0
  12. package/docs/design/parallel-slots.md +34 -26
  13. package/docs/design/parity-tier-dag.md +143 -0
  14. package/docs/design/runtime-isolation.md +1 -1
  15. package/docs/design/segmented-backward-training.md +58 -39
  16. package/docs/design/tauri-desktop-app.md +127 -0
  17. package/docs/design/w4a16-compute-precision-spike.md +232 -0
  18. package/docs/investigations/orpo-base-uf-experiment-and-directions.md +120 -0
  19. package/docs/investigations/orpo-flash-cce-pin-leak.md +167 -0
  20. package/docs/investigations/orpo-uf-testing-handoff.md +126 -0
  21. package/docs/{segmented-backward-handoff.md → investigations/segmented-backward-handoff.md} +1 -1
  22. package/docs/investigations/starter-model-port-handoff.md +32 -13
  23. package/docs/investigations/steel-flash-cce-handoff.md +489 -0
  24. package/docs/investigations/trainer-validation-experiment.md +173 -0
  25. package/docs/planning/IDEAS.md +29 -0
  26. package/docs/planning/PRODUCT_ROADMAP.md +147 -27
  27. package/docs/planning/chunk-task-roadmap.md +1 -1
  28. package/docs/planning/journal.md +161 -0
  29. package/docs/reference/distribution.md +61 -5
  30. package/docs/reference/library-api.md +29 -14
  31. package/docs/reference/memory.md +77 -0
  32. package/docs/reference/orpo-quickstart.md +130 -0
  33. package/docs/reference/server-api.md +105 -7
  34. package/docs/reference/server-config.md +12 -5
  35. package/docs/reference/training.md +296 -0
  36. package/package.json +1 -1
  37. package/src/cli.ts +651 -18
  38. package/src/eval/ifeval.ts +138 -0
  39. package/src/eval/runner.ts +76 -6
  40. package/src/eval/tasks/bfcl.ts +49 -15
  41. package/src/eval/tasks/gsm8k.ts +21 -9
  42. package/src/eval/tasks/hashhop.ts +33 -4
  43. package/src/eval/tasks/humaneval.ts +30 -8
  44. package/src/eval/tasks/ifeval.ts +52 -18
  45. package/src/eval/tasks/mmlu.ts +85 -74
  46. package/src/eval/ultrafeedback.ts +60 -0
  47. package/src/jobs/runner.ts +6 -0
  48. package/src/lora.ts +12 -7
  49. package/src/memory/chunk.ts +25 -0
  50. package/src/memory/cluster.ts +24 -0
  51. package/src/memory/db.ts +114 -0
  52. package/src/memory/ingest.ts +22 -0
  53. package/src/memory/pipeline.ts +63 -0
  54. package/src/memory/prompts.ts +23 -0
  55. package/src/memory/schedule.ts +163 -0
  56. package/src/memory/synthesize.ts +29 -0
  57. package/src/memory/tools.ts +399 -0
  58. package/src/memory/vault.ts +694 -0
  59. package/src/memory/wikify.ts +23 -0
  60. package/src/mlx/metal-kernel.ts +31 -4
  61. package/src/model/flash-attention.ts +37 -19
  62. package/src/model/fused-geglu-kernel.ts +111 -0
  63. package/src/model/gemma4-base.ts +39 -1
  64. package/src/model/gemma4.ts +196 -21
  65. package/src/model/minicpm5.ts +44 -3
  66. package/src/pi-provider.ts +29 -13
  67. package/src/pi-session.ts +81 -0
  68. package/src/pi-terminal.ts +13 -24
  69. package/src/pi-web.ts +246 -166
  70. package/src/quantize/job.ts +17 -2
  71. package/src/quantize/quantizer.ts +26 -2
  72. package/src/server.ts +216 -47
  73. package/src/tokenizer.ts +6 -2
  74. package/src/train/dataset.ts +29 -6
  75. package/src/train/flash-cce.ts +1175 -0
  76. package/src/train/job.ts +64 -3
  77. package/src/train/lora-params.ts +53 -4
  78. package/src/train/loss.ts +947 -0
  79. package/src/train/optimizer.ts +10 -3
  80. package/src/train/prefix-shared.ts +435 -0
  81. package/src/train/rank.ts +36 -0
  82. package/src/train/segmented.ts +1148 -3
  83. package/src/train/steel-qmm-header.ts +1461 -0
  84. package/src/train/trainer.ts +570 -54
  85. package/src/train/watch.ts +542 -0
  86. package/src/web/app.html +285 -19
  87. package/src/web/skills/memory/SKILL.md +97 -0
  88. package/src/web/skills/web-research/SKILL.md +3 -1
  89. package/src/web/skills.ts +46 -8
  90. /package/{docs → src/assets}/curve-designer.html +0 -0
@@ -1,339 +1,237 @@
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:
1
+ # Memory system
95
2
 
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
- ```
3
+ Status: **M0/M0.5 landed (2026-06-19)**. The vault, read tools, CLI, Obsidian open flow, and launchd scheduling are implemented. The actual synthesis stage bodies are still **M1 TODO**; `mlx-bun memory synthesize` is currently a safe no-op stub. The planned M1/M2 synthesis engine uses the same local models the user chats with, plus stage-specific LoRA adapters trained by Josh from the existing Lucien-scale memory corpus and distributed from Hugging Face.
107
4
 
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.
5
+ ## Contract
118
6
 
119
- ### The vault
7
+ The memory contract is ported from `../lucien`:
120
8
 
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:
9
+ > **Chat-time agents read memory. The synthesis pipeline writes memory.**
124
10
 
125
- ```markdown
126
- # Archie Project
11
+ Memory articles are durable priors. Conversations are evidence. Synthesis is the deliberate, auditable process that turns evidence into updated articles. Normal chat must not mutate articles.
127
12
 
128
- The **Archie Project** is an internal AI agent platform Josh built at
129
- [[AlphaPoint]] beginning spring 2026.[^1][^2]
13
+ This gives both terminal and web the full pi agent experience without turning memory into an unsafe scratchpad:
130
14
 
131
- ## Origin
132
- ...[^1]
15
+ - Terminal and web expose the same read-only memory tools through one shared pi surface factory.
16
+ - Memory tools/skill are exposed only when the user has enabled the vault.
17
+ - When enabled, memory is scoped to user-specific continuity: explicit recall, named personal projects/people/preferences/decisions/history, or missing personal context.
18
+ - Memory is **not** the default first step for weather, current public facts, generic web research, or ordinary coding/file tasks where the current files are sufficient.
19
+ - Mutating/coding tools remain full-power and approval-gated by pi/web as usual.
20
+ - Memory article writes happen only through `mlx-bun memory synthesize` once M1 lands.
21
+ - Users can always browse/edit their own Markdown vault directly, especially via Obsidian.
133
22
 
134
- ## References
135
- [^1]: `conv:a1b2c3d4` (2026-05-10, mlx-bun) — Archie design overview
136
- ```
23
+ ## User-facing model
137
24
 
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).
25
+ - User-facing capability: **memory**.
26
+ - Store on disk: `~/.mlx-bun/wiki/` (override: `MLX_BUN_WIKI`).
27
+ - User articles: `~/.mlx-bun/wiki/articles/*.md`.
28
+ - Read-only reference residents: `~/.mlx-bun/wiki/Reference/*.md` symlinked to mlx-bun's own docs.
29
+ - Operational pages: `~/.mlx-bun/wiki/Meta/*.md`.
30
+ - Talk pages: `~/.mlx-bun/wiki/Talk/`.
31
+ - Synthesis DB: `~/.cache/mlx-bun/memory.sqlite`.
142
32
 
143
- ### Ingestion — mlx-bun sessions only
33
+ The vault is plain Markdown and git-tracked. It is intentionally usable as an Obsidian vault. `Reference/` is a separate read-only namespace: chat tools may search/read it, but synthesis must skip it and never write through those symlinks. The SQLite DB is derived state and lives in the rebuildable cache, not in the user-owned Markdown vault.
144
34
 
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`.
35
+ Stage-specific memory LoRAs are product assets, not user-authored vault content. The creator trains them from the existing memory-pipeline data, publishes them to Hugging Face, and `memory init` can offer to download/cache them for local synthesis.
151
36
 
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.
37
+ ## What is implemented now
156
38
 
157
- ### The nightly pipeline (on `src/jobs/*`)
39
+ ### Vault and article helpers
158
40
 
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.
41
+ `src/memory/vault.ts` implements:
164
42
 
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
43
+ - `vaultRoot()` → `~/.mlx-bun/wiki` or `MLX_BUN_WIKI`.
44
+ - `setupVault()` — idempotent directory/Meta/README/git setup plus `Reference/` symlinks.
45
+ - `listArticles()` / `listReferenceDocs()` / `listMemoryDocuments()`.
46
+ - `readArticle()` / `searchArticles()` over both user articles and read-only references.
47
+ - `parseToc()` / `extractSection()`.
48
+ - `getArticleLinks()` with resolved inbound/outbound wikilinks.
49
+ - `importArticlesFrom()` for seeding from an existing vault such as `~/Dreaming`.
50
+ - `vaultStatus()` with article/reference counts and recent user article mtimes.
51
+
52
+ The read/search/link logic is ported from Lucien's pure filesystem helpers, not from MCP.
53
+
54
+ ### CLI
55
+
56
+ `mlx-bun memory` supports:
57
+
58
+ ```bash
59
+ mlx-bun memory init # create vault, optionally import + schedule
60
+ mlx-bun memory setup # alias for init
61
+ mlx-bun memory status # path, article count, git, schedule, recent articles
62
+ mlx-bun memory open # open the vault in Obsidian, fallback Finder
63
+ mlx-bun memory open <article> # open one article in Obsidian/default Markdown app
64
+ mlx-bun memory list # list article stems + Reference/* docs
65
+ mlx-bun memory search <query> # search articles
66
+ mlx-bun memory toc <article> # headings + anchors
67
+ mlx-bun memory section <article> <anchor>
68
+ mlx-bun memory links <article> # inbound/outbound wikilinks
69
+ mlx-bun memory read <article> # print full article
70
+ mlx-bun memory synthesize [--dry-run] [--model <q>] [--since <cursor>]
71
+ mlx-bun memory schedule [--at HH:MM]
72
+ mlx-bun memory unschedule
173
73
  ```
174
74
 
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.
75
+ `memory synthesize` currently reports the M1 stub and writes nothing. Scheduling is real; the scheduled job is harmless until synthesis lands. In the full flow, `memory init` should also offer to download the memory pipeline adapter pack from Hugging Face so synthesis is ready to run locally.
179
76
 
180
- ### Synthesis runs on the local model
77
+ ### pi/web tools
181
78
 
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]]).
79
+ `src/memory/tools.ts` defines native pi custom tools:
191
80
 
192
- ### Read tools — how the assistant consults memory
81
+ - `memory_search`
82
+ - `memory_read`
83
+ - `memory_toc`
84
+ - `memory_section`
85
+ - `memory_links`
86
+ - `memory_list` (user articles plus read-only `Reference/*` docs)
87
+ - `memory_status` (vault path, setup state, article count, git state, last-synthesis placeholder, schedule state, recent changed articles)
193
88
 
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:
89
+ These tools are registered by the shared pi surface in `src/pi-session.ts` and consumed by both front doors:
198
90
 
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
91
+ - `src/pi-terminal.ts`
92
+ - `src/pi-web.ts`
204
93
 
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.)
94
+ If the vault does not exist, memory tools and the memory skill are not exposed at all, avoiding prompt fixation on unavailable memory. If the vault exists, `memoryIndexHint()` adds a short scoped presence hint. Detailed usage lives in the memory skill rather than dumping article titles into the prompt.
215
95
 
216
- ## Two front doors: CLI + assistant
96
+ Read-only mlx-bun docs are now a separate lookup surface (`reference_search`, `reference_read`, `reference_list`) rather than being mixed into personal-memory search. Personal memory answers “what does the user think / what did we decide”; reference tools answer “what do mlx-bun docs say.”
217
97
 
218
- One implementation (the CLI / `src/memory` module), two ways to reach it.
98
+ ### Bundled memory skill
219
99
 
220
- ### CLI — `mlx-bun memory <subcommand>`
100
+ `src/web/skills/memory/SKILL.md` is bundled through `src/web/skills.ts` and materialized under `~/.mlx-bun/skills` for pi to load.
221
101
 
222
- New `case "memory"` in [cli.ts](../../src/cli.ts) + a `HELP.memory` entry.
102
+ The skill tells the agent to:
223
103
 
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)
104
+ - consult memory quietly for personal context;
105
+ - use `memory_search` then `memory_read`, or `memory_toc` + `memory_section` for focused reads;
106
+ - use `memory_links` for nearby concepts/backlinks;
107
+ - use `memory_status` for setup/location/schedule questions;
108
+ - never announce retrieval as the user's experience;
109
+ - never edit memory articles during chat;
110
+ - open the vault/article for the user if asked via `mlx-bun memory open [article]`.
111
+
112
+ ### Session capture substrate
113
+
114
+ The synthesis pipeline will ingest mlx-bun's own pi sessions only:
115
+
116
+ - web sessions: `~/.mlx-bun/sessions/...` / `~/.mlx-bun/pi-sessions/...` depending on the web `SessionManager` path;
117
+ - terminal sessions: `~/.mlx-bun/pi/sessions/...`.
118
+
119
+ No Playwright, scraping, cloud transcript import, or Lucien runtime dependency is planned for mlx-bun memory.
120
+
121
+ ### Scheduling
122
+
123
+ `src/memory/schedule.ts` installs a launchd agent:
124
+
125
+ - label: `com.mlx-bun.memory`
126
+ - plist: `~/Library/LaunchAgents/com.mlx-bun.memory.plist`
127
+ - command: `mlx-bun memory synthesize`
128
+ - logs: `~/.mlx-bun/logs/memory-synthesis.{out,err}.log`
129
+
130
+ `mlx-bun memory schedule --at 03:00` installs/loads it. `unschedule` unloads/removes it. `status` and `memory_status` report it.
131
+
132
+ ## Synthesis pipeline design (M1/M2)
133
+
134
+ The M1/M2 pipeline mirrors Lucien's proven stages while running on the same local model stack the user chats with. The difference is execution context and authority: chat uses the model conversationally and read-only; synthesis runs the model as a constrained editor behind deterministic gates.
135
+
136
+ ```text
137
+ ingest deterministic: pi session JSONL -> memory.sqlite conversations
138
+ chunk base model + memory-chunk LoRA -> topic chunks
139
+ cluster base model + memory-bucket LoRA -> buckets / target articles
140
+ synthesize base model + memory-synthesis LoRA -> candidate article updates
141
+ wikify base model + memory-editor LoRA + deterministic normalization
142
+ changelog deterministic: run summary + git commit
233
143
  ```
234
144
 
235
- ### Assistant-driven setup (a bundled skill)
145
+ The chunking LoRA has already been trained as a WIP artifact. The remaining stage adapters are planned product assets trained by Josh from the existing Lucien/pipeline data and published to Hugging Face. mlx-bun should download/cache them during `memory init` (with user consent) or lazily on first `memory synthesize`.
236
146
 
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:
147
+ Important nouns must stay distinct:
239
148
 
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.
149
+ - **Conversation** — source transcript/evidence.
150
+ - **Chunk** — topical segment from a conversation.
151
+ - **Bucket** — staging group that collects related chunks.
152
+ - **Article** — durable Markdown memory page.
247
153
 
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.
154
+ ### Bookkeeping DB
250
155
 
251
- ### Consent model
156
+ `src/memory/db.ts` defines `MemoryStore` over `~/.cache/mlx-bun/memory.sqlite` with tables for:
252
157
 
253
- Drawn deliberately, two tiers:
158
+ - `conversations`
159
+ - `chunks`
160
+ - `buckets`
161
+ - `watermarks`
162
+ - `synthesized_bucket_chunks`
254
163
 
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.
164
+ The DB is derived and rebuildable from sessions + articles. It should not be committed to the vault.
265
165
 
266
- ## Scheduling (launchd)
166
+ ### Stage-specific adapters
267
167
 
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`.
168
+ The pipeline deliberately uses **four specialized LoRA adapters** rather than one generic memory adapter:
276
169
 
277
- ## Privacy (the throughline)
170
+ | Stage | Adapter | Job | Primary quality signal |
171
+ | --- | --- | --- | --- |
172
+ | Chunk | memory-chunk | Conversation transcript → topic-coherent chunks | Boundary/label accuracy vs gold chunks |
173
+ | Bucket | memory-bucket | Chunk → existing bucket or new bucket proposal | Stable routing, low duplicate topics, good article target |
174
+ | Synthesize | memory-synthesis | New chunks + existing article → conservative candidate update | Citation preservation, faithful integration, no hallucinated claims |
175
+ | Edit/wikify | memory-editor | Candidate article → normalized wiki Markdown | Style, wikilinks, references, deterministic format compliance |
278
176
 
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]]).
177
+ These adapters do **not** get direct write authority. They produce candidates. The pipeline validates, normalizes, and decides whether to write/commit.
283
178
 
284
- ## Module layout (reusable)
179
+ Implementation notes:
285
180
 
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:
181
+ - Adapters should be cached with the rest of mlx-bun's HF/downloaded artifacts, not stored in the wiki vault.
182
+ - `memory init` should describe the adapter pack plainly and ask before downloading multi-MB/GB assets.
183
+ - `memory synthesize --dry-run` must work without downloading adapters when it only builds the deterministic manifest.
184
+ - If a required adapter is missing for a real synthesis stage, the command should offer the download or fail cleanly; it should not silently fall back to an untrained prompt path unless explicitly requested.
185
+ - Future routing should use the existing adapter-scoped generation path: one resident base model, stage LoRA mounted per pipeline call.
288
186
 
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
- ```
187
+ ### Current stage modules
188
+
189
+ These files exist as typed stubs and currently throw if called directly:
190
+
191
+ - `src/memory/ingest.ts`
192
+ - `src/memory/chunk.ts`
193
+ - `src/memory/cluster.ts`
194
+ - `src/memory/synthesize.ts`
195
+ - `src/memory/wikify.ts`
196
+ - `src/memory/prompts.ts`
197
+
198
+ `src/memory/pipeline.ts` intentionally does **not** call them yet. It emits a no-op M1-stub plan so manual and scheduled synthesis cannot accidentally corrupt the vault before gates exist.
199
+
200
+ ## Synthesis quality gates to port from Lucien
201
+
202
+ M1 should preserve these Lucien properties:
203
+
204
+ - deterministic manifest / dry-run before writes;
205
+ - per-bucket/per-article workers so failures are isolated;
206
+ - idempotency via `synthesized_bucket_chunks`;
207
+ - backfill behavior for existing imported articles;
208
+ - orphan detection when ledger and files disagree;
209
+ - conservative update prompt: integrate, do not rewrite wholesale;
210
+ - minimum word-count/truncation guard, e.g. Lucien's 70% floor;
211
+ - citation preservation: every original `conv:` reference survives;
212
+ - deterministic footnote repair;
213
+ - deterministic wikilink normalization;
214
+ - git commit for article changes;
215
+ - changelog / run summary.
216
+
217
+ A weak local-model synthesis pass should no-op, not damage the vault. This remains true even with trained adapters: LoRAs propose; deterministic gates dispose. Synthesis must operate only on `articles/` and must treat `Reference/` as immutable read-only context.
218
+
219
+ ## Consent and safety
220
+
221
+ - Local session capture is local-only and part of pi/web session persistence.
222
+ - Creating the vault is explicit: `mlx-bun memory init`.
223
+ - Scheduling is explicit: `mlx-bun memory schedule` or the init wizard prompt.
224
+ - Chat-time memory tools are read-only and auto-allowed.
225
+ - Opening Obsidian/Finder is user-directed browsing/editing; it is not agent mutation.
226
+ - Article mutation by the agent during chat is out of bounds.
227
+
228
+ ## Next implementation steps
303
229
 
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.
230
+ 1. Implement `memory synthesize --dry-run` manifest generation without model calls.
231
+ 2. Add memory adapter-pack metadata and `memory init` download prompt (HF-hosted LoRAs; chunk adapter exists as WIP, others follow).
232
+ 3. Implement ingest from saved pi session JSONL into `MemoryStore`.
233
+ 4. Wire the chunk stage to the memory-chunk LoRA and evaluate with chunk boundary/label accuracy.
234
+ 5. Implement bucket assignment with the memory-bucket LoRA and article manifest create/update/backfill/orphan modes.
235
+ 6. Implement per-article synthesis workers with the memory-synthesis LoRA and conservative gates.
236
+ 7. Implement editor/wikify adapter pass plus deterministic footnote/wikilink normalization and git commits.
237
+ 8. Move synthesis execution onto the jobs runner with SSE progress once manual synthesis is reliable.
@@ -1,8 +1,10 @@
1
1
  # mlx-bun: gemma4.ts decompose & optimize — action plan
2
2
 
3
3
  > This is the canonical **design/rationale** for the optimization work.
4
- > Live **status/tracking** (checkboxes, findings) lives in PLAN.md under
5
- > "Optimization plan Phase A–E".
4
+ > Live **status/tracking** (checkboxes, findings) for Phases A–D lives in
5
+ > PLAN-archive.md; Phase E remains in PLAN.md.
6
+
7
+ **Status (verified 2026-06-17):** Phases A–D are **DONE** (`[x]` in PLAN-archive.md, all landed 2026-06-10/11). Phase E — per-config fused decode-SDPA kernel — is **in progress** (`[~]` in PLAN.md, started 2026-06-11; fused kernel exists and is quality-gated per PLAN.md Step 4). The body of this doc remains the durable design rationale; completed phase checkboxes and findings live in PLAN-archive.md; Phase E tracking lives in PLAN.md.
6
8
 
7
9
  **Premise (confirmed from the source read):** the current engine sits at
8
10
  parity-to-ahead vs mlx-lm on the 12B *while still interpreting the decode