mlx-bun 0.0.10 → 0.0.11

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 (173) hide show
  1. package/README.md +66 -21
  2. package/THIRD_PARTY_LICENSES.md +1 -0
  3. package/docs/archive/mlx-bun-lab-report.html +275 -0
  4. package/docs/archive/wwdc-mlx-bun.html +848 -0
  5. package/docs/design/audio-input-plan.md +356 -0
  6. package/docs/design/batching-perf-path.md +58 -35
  7. package/docs/design/batching-v2-plan.md +23 -9
  8. package/docs/design/bucketing-stage.md +2 -1
  9. package/docs/design/compat-cli-surface-design.md +4 -3
  10. package/docs/design/decode-speed-program.md +172 -0
  11. package/docs/design/docs-reorg-plan.md +1 -1
  12. package/docs/design/dspark-serving-program.md +371 -0
  13. package/docs/design/dspark-speculative-decoding.md +167 -5
  14. package/docs/design/faithful-l1-consolidation.md +310 -0
  15. package/docs/design/generic-model-support.md +8 -5
  16. package/docs/design/grammar-spec-batching-integration.md +301 -0
  17. package/docs/design/minicpm5-decode-megakernel.md +16 -11
  18. package/docs/design/mlx-lm-tool-parity-plan.md +11 -1
  19. package/docs/design/omlx-adoption-map.md +14 -6
  20. package/docs/design/orpo-training.md +34 -30
  21. package/docs/design/paged-kv-cache.md +214 -0
  22. package/docs/design/parallel-slots.md +82 -49
  23. package/docs/design/parity-tier-dag.md +43 -33
  24. package/docs/design/repo-cleanup-plan.md +189 -0
  25. package/docs/design/runtime-isolation.md +19 -3
  26. package/docs/design/segmented-backward-training.md +3 -2
  27. package/docs/design/ssd-kv-cold-tier.md +130 -0
  28. package/docs/design/structured-output.md +484 -0
  29. package/docs/design/the-dreaming-master-plan.md +2 -3
  30. package/docs/design/turboquant-kv.md +235 -0
  31. package/docs/design/unified-engine-frontier-plan.md +774 -0
  32. package/docs/design/web-chat-beat-matrix.md +315 -0
  33. package/docs/design/web-chat-redesign.md +1112 -0
  34. package/docs/investigations/dspark-handoff.md +182 -16
  35. package/docs/investigations/lab-build-journal.md +2 -2
  36. package/docs/investigations/openwiki-evaluation.md +249 -0
  37. package/docs/planning/IDEAS.md +14 -0
  38. package/docs/planning/PRODUCT_ROADMAP.md +2 -3
  39. package/docs/planning/chat-ui-vision-memory-first.md +199 -0
  40. package/docs/planning/chat-ui-vision.md +50 -0
  41. package/docs/planning/memory-docs-and-dag-plan.md +15 -6
  42. package/docs/planning/release-notes-v0.0.11.md +239 -0
  43. package/docs/reference/cli.md +35 -16
  44. package/docs/reference/distribution.md +13 -6
  45. package/docs/reference/embedding.md +35 -14
  46. package/docs/reference/features-matrix.md +97 -0
  47. package/docs/reference/library-api.md +30 -9
  48. package/docs/reference/memory.md +26 -6
  49. package/docs/reference/models.md +11 -1
  50. package/docs/reference/orpo-quickstart.md +3 -4
  51. package/docs/reference/server-api.md +634 -22
  52. package/docs/reference/server-config.md +250 -121
  53. package/docs/reference/training.md +14 -15
  54. package/package.json +5 -3
  55. package/src/anthropic.ts +13 -0
  56. package/src/audio/conformer.ts +647 -0
  57. package/src/audio/decode.ts +133 -0
  58. package/src/audio/features.ts +202 -0
  59. package/src/audio/transcode.ts +67 -0
  60. package/src/cli.ts +356 -105
  61. package/src/config.ts +49 -2
  62. package/src/download.ts +40 -0
  63. package/src/eval/README.md +7 -6
  64. package/src/eval/kl.ts +59 -3
  65. package/src/eval/quality-db.ts +2 -2
  66. package/src/eval/runner.ts +3 -3
  67. package/src/expert-offload.ts +15 -2
  68. package/src/flags.ts +13 -0
  69. package/src/generate.ts +330 -24
  70. package/src/grammar.ts +585 -0
  71. package/src/hub-rest.ts +242 -0
  72. package/src/kv-store.ts +442 -88
  73. package/src/lora.ts +8 -0
  74. package/src/md-modules.d.ts +42 -0
  75. package/src/media-fetch.ts +284 -0
  76. package/src/memory/rest.ts +245 -0
  77. package/src/memory/vault.ts +74 -0
  78. package/src/mlx/array.ts +106 -19
  79. package/src/mlx/autograd.ts +2 -2
  80. package/src/mlx/ffi.ts +27 -3
  81. package/src/mlx/metal-kernel.ts +7 -4
  82. package/src/mlx/ops.ts +153 -23
  83. package/src/mlx/turboquant-ops.ts +831 -0
  84. package/src/mlx/turboquant-tables.ts +237 -0
  85. package/src/model/batched-mask.ts +62 -1
  86. package/src/model/batched-quant.ts +206 -0
  87. package/src/model/batched-rotating-quant.ts +346 -0
  88. package/src/model/batched-rotating.ts +46 -1
  89. package/src/model/compiled-decode.ts +4 -15
  90. package/src/model/factory.ts +10 -4
  91. package/src/model/gemma4-base.ts +363 -39
  92. package/src/model/gemma4.ts +122 -33
  93. package/src/model/generated/gemma4-12b.ts +9 -13
  94. package/src/model/generated/gemma4-26b.ts +10 -5
  95. package/src/model/generated/gemma4-e4b.ts +14 -9
  96. package/src/model/minicpm5.ts +58 -102
  97. package/src/model/paged-kv.ts +253 -0
  98. package/src/model/qwen3-delta.ts +76 -15
  99. package/src/model/qwen3-moe.ts +404 -0
  100. package/src/model/qwen3.ts +9 -8
  101. package/src/model/qwen3_5.ts +88 -23
  102. package/src/model/support.ts +12 -1
  103. package/src/model/universal/dense.ts +40 -5
  104. package/src/model/universal/rope.ts +36 -21
  105. package/src/pi-web.ts +1299 -82
  106. package/src/preflight.ts +27 -8
  107. package/src/prompt-cache.ts +293 -33
  108. package/src/quantize/quantizer.ts +16 -1
  109. package/src/registry.ts +57 -2
  110. package/src/serve/batch-scheduler.ts +965 -72
  111. package/src/serve/generation-gateway.ts +214 -11
  112. package/src/serve/isolate.ts +417 -0
  113. package/src/serve/lane-registry.ts +44 -0
  114. package/src/serve/session-search.ts +326 -0
  115. package/src/server.ts +1380 -135
  116. package/src/spec/assistant-source.ts +150 -0
  117. package/src/spec/deepspec-source.ts +143 -0
  118. package/src/spec/dflash-source.ts +124 -0
  119. package/src/spec/dspark/ab-stats.ts +136 -0
  120. package/src/spec/dspark/calibration.ts +112 -0
  121. package/src/spec/dspark/deepspec-module.ts +801 -0
  122. package/src/spec/dspark/generate-dflash.ts +72 -20
  123. package/src/spec/dspark/loader.ts +23 -0
  124. package/src/spec/dspark/module-dflash.ts +278 -36
  125. package/src/spec/dspark/quantize-drafter.ts +91 -0
  126. package/src/spec/generate.ts +59 -25
  127. package/src/spec/ngram-source.ts +132 -0
  128. package/src/spec/serve-loop.ts +536 -0
  129. package/src/spec/source.ts +93 -0
  130. package/src/spec/two-model.ts +171 -0
  131. package/src/ssd-cache.ts +107 -35
  132. package/src/tokenizer.ts +288 -2
  133. package/src/tool-approvals.ts +131 -0
  134. package/src/tool-call.ts +408 -20
  135. package/src/train/flash-cce.ts +2 -2
  136. package/src/train/job.ts +0 -2
  137. package/src/train/trainer.ts +1 -4
  138. package/src/vision/prompt.ts +217 -48
  139. package/src/web/app.html +1184 -1789
  140. package/src/web/app.js +5667 -0
  141. package/src/web/icon.svg +13 -0
  142. package/src/web/manifest.webmanifest +24 -0
  143. package/src/web/src/adapters-panel.ts +288 -0
  144. package/src/web/src/api.ts +57 -0
  145. package/src/web/src/assistant.ts +485 -0
  146. package/src/web/src/chat.ts +1050 -0
  147. package/src/web/src/composer.ts +959 -0
  148. package/src/web/src/dataset.ts +132 -0
  149. package/src/web/src/finetune.ts +267 -0
  150. package/src/web/src/hub.ts +428 -0
  151. package/src/web/src/main.ts +98 -0
  152. package/src/web/src/markdown.ts +0 -0
  153. package/src/web/src/memory-panel.ts +572 -0
  154. package/src/web/src/model-picker.ts +159 -0
  155. package/src/web/src/palette.ts +346 -0
  156. package/src/web/src/protocol.ts +62 -0
  157. package/src/web/src/quantize.ts +167 -0
  158. package/src/web/src/rag.ts +274 -0
  159. package/src/web/src/sessions.ts +469 -0
  160. package/src/web/src/shell.ts +804 -0
  161. package/src/web/src/status.ts +252 -0
  162. package/src/web/src/ui-catalog.ts +92 -0
  163. package/src/web/sw.js +71 -0
  164. package/src/web/vendor/README.md +61 -0
  165. package/src/web/vendor/hljs-LICENSE +29 -0
  166. package/src/web/vendor/hljs-theme.css +59 -0
  167. package/src/web/vendor/hljs.js +26 -0
  168. package/src/model/fused-decode-kernel.ts +0 -312
  169. package/src/model/fused-geglu-kernel.ts +0 -198
  170. package/src/model/fused-mlp-kernel.ts +0 -169
  171. package/src/model/fused-swiglu-kernel.ts +0 -240
  172. package/src/model/steel-linear-kernel.ts +0 -96
  173. package/src/status-page.html +0 -497
@@ -1,11 +1,176 @@
1
1
  # DSpark — handoff
2
2
 
3
- **State:** faithful DSpark (DFlash KV-injection + Markov + confidence) is **built
4
- and proven architecturally correct** (overfit τ=3.24, paper-range). It does not
5
- yet net a speedup on e4b — that's a data-scale + target-speed problem, not an
6
- architecture problem. Full design + measured numbers:
3
+ **State (2026-07-06): the DSpark paper is CODE-COMPLETE and serve-integrated.**
4
+ Architecture proven correct (overfit τ=3.24, paper-range); serve-integrated
5
+ behind `--draft-model` (Phase 1 — the `DraftSource` seam is KV-borrowing-ready;
6
+ sibling AssistantSource verified bit-lossless on real weights,
7
+ `tests/spec-serve-assistant.test.ts`); and every remaining paper component
8
+ landed in Phase 2 the same day: Alg-1 confidence-scheduled draft-length pruning
9
+ (checkpoint-driven, zero change for uncalibrated checkpoints), STS calibration
10
+ (§3.2.1, `calibration.ts` + `scripts/dspark-calibrate.ts`), the RNN sequential
11
+ head (Eq 6, `--seq-head rnn`, init-equivalent to Markov), the tightened draft
12
+ loop (on-device token chaining + deferred conf reads + `collectLogits:false`
13
+ on serve — bit-identity pinned), and the `dspark` variant rename + central
14
+ loader. Suites: smoke 21/21 · dspark tests 17/17 · adjacent server suites
15
+ green. **What remains is exactly the GPU work below** — data scale + 12B
16
+ retarget + train + calibrate + measure; e4b not netting a speedup is a
17
+ data/target-speed problem, not architecture. Full design:
7
18
  [docs/design/dspark-speculative-decoding.md](../design/dspark-speculative-decoding.md).
8
19
 
20
+ ## PATH A (preferred, no training) — DeepSeek's published 12B drafter
21
+
22
+ DeepSeek released a TRAINED drafter for our exact target:
23
+ `deepseek-ai/dspark_gemma4_12b_block7` (6.86 GB bf16, γ=7; DeepSpec repo is
24
+ the MIT reference impl + the oracle — see the "DeepSpec ground truth" section
25
+ of the design doc). Once the deepspec-variant port lands:
26
+
27
+ ```sh
28
+ # 1. download the trained drafter (~6.9 GB)
29
+ mlx-bun get deepseek-ai/dspark_gemma4_12b_block7
30
+ # 2. oracle gate: dump their reference trace (temp 0 = RNG-free deterministic)
31
+ # in a torch venv, then compare ours round-for-round (scripts staged)
32
+ # 3. measure + serve (auto-detected via config.json architectures field)
33
+ mlx-bun serve --model gemma-4-12B-it-OptiQ-4bit --draft-model <snapshot-of-dspark_gemma4_12b_block7>
34
+ ```
35
+
36
+ ### Oracle protocol (step 2, expanded)
37
+
38
+ Two staged scripts implement the temp-0 deterministic trace protocol against
39
+ DeepSpec's own reference implementation (github.com/deepseek-ai/DeepSpec, MIT).
40
+ At temperature 0 their leaky-rejection verify degenerates to exact argmax
41
+ token-match — the whole round trace is RNG-free and reproducible, so a
42
+ plain round-for-round diff is a real bit-exact gate (same discipline as the
43
+ D2 diffusion oracle, minus RNG parity entirely — see the design doc's
44
+ "DeepSpec ground truth" section).
45
+
46
+ ```sh
47
+ # a. dump the reference trace — needs its OWN torch venv (NOT the mlx-lm
48
+ # oracle venv at /Users/joshrossi/Code/mlx-lm/.venv, which has no
49
+ # torch/deepspec and shouldn't); see the script header for the exact
50
+ # venv-setup + pip install steps.
51
+ .venv-deepspec/bin/python scripts/oracle-dspark-deepspec.py \
52
+ --target <snapshot-dir-of-google/gemma-4-12B-it> \
53
+ --drafter <snapshot-of-dspark_gemma4_12b_block7> \
54
+ --data prompts.jsonl --n 8 --max-new-tokens 128 \
55
+ --temperature 0 --confidence-threshold 0 \
56
+ --out goldens/dspark-deepspec/trace-thr0.jsonl
57
+
58
+ # b. compare our port round-for-round
59
+ bun scripts/dspark-deepspec-compare.ts \
60
+ --fixture goldens/dspark-deepspec/trace-thr0.jsonl \
61
+ --target gemma-4-12B-it-bf16 --drafter <snapshot-of-dspark_gemma4_12b_block7>
62
+ ```
63
+
64
+ Run the pair twice — once at `--confidence-threshold 0` (no pruning), once at
65
+ `0.5` — to gate both the base draft loop and the confidence-truncation path.
66
+
67
+ Fixture location: `goldens/dspark-deepspec/*.jsonl` follows the house
68
+ manifest convention (goldens/README.md) — these are machine-independent
69
+ **JSON manifests** (prompts + token-id traces, no tensor blobs), so they are
70
+ the **tracked** kind, not the `.bin` machine-specific kind. Regenerate by
71
+ rerunning step (a); there is no `scripts/regen-*` wrapper for this family yet
72
+ since the oracle run needs its own GPU-hosting torch venv, not the mlx-lm
73
+ oracle venv this repo otherwise standardizes on.
74
+
75
+ **The OptiQ-4bit caveat is load-bearing, not a footnote**: the fixture above
76
+ is generated against the bf16 HF target. A `dspark-deepspec-compare.ts` run
77
+ with `--target` pointing at our bf16 12B is the TRUE bit-exact gate. A run
78
+ with `--target` pointing at the OptiQ-4bit-quantized 12B we actually serve is
79
+ a **separate acceptance-rate measurement** — tapped hiddens differ
80
+ numerically at 4-bit, so round-for-round divergence there is expected, not a
81
+ bug; pass `--acceptance-only` on that arm so the script reports an aggregate
82
+ accept-length reading instead of a PASS/FAIL assert.
83
+
84
+ Caveat: trained against the bf16 HF target; our serving 12B is OptiQ-4bit —
85
+ tapped hiddens differ numerically, so measure acceptance rather than assuming
86
+ their 60–85%.
87
+
88
+ **FIRST LIVE RUN (2026-07-07, loaded machine — directional only):** τ ≈ 2.8
89
+ committed/target-forward (200 tok / 72 verify rounds; per-token acceptance
90
+ 26–33% — the predicted OptiQ-4bit degradation), output coherent, losslessness
91
+ holding. **But wall-clock LOST ~3.4×** (spec 14.6 vs serial 49.8 agg tok/s;
92
+ the 20 s bench TTFT is conc-4 queueing on the serial-forced spec lane, not
93
+ prefill). The tax is the drafter itself. **The full step-by-step program for
94
+ the next pass is
95
+ [docs/design/dspark-serving-program.md](../design/dspark-serving-program.md)**
96
+ (phases, gates, dependency graph; pickup at TurboQuant merge, only its
97
+ Phase 5 waits for it). Lever summary:
98
+ 1. **Quantize the drafter** — the big one, and the ideal quantization target
99
+ PERIOD: drafter numerics only move ACCEPTANCE, never correctness
100
+ (losslessness is structural), so aggressive bpw is safe and the gate is a
101
+ single acceptance A/B. 6.9 GB bf16 → ~1.8 GB @4-bit kills both the
102
+ ~3 GB/round bandwidth tax (2 GB lm_head + 7×134 MB markov_w2 reads) and
103
+ the 14 GB two-model memory pressure on 24 GB. Uniform 4-bit (mlx-native)
104
+ first as the baseline; **TurboQuant (Phase 13), when it lands, competes
105
+ on acceptance-per-byte against that baseline** — the drafter is its
106
+ lowest-risk first customer. Enabler either way: quantized-weight support
107
+ in deepspec-module's forward (quantized_matmul, the house pattern).
108
+ 2. **Tighten deepspec draftBlock** — ~14 host syncs/round (7 argmax + 7
109
+ confidence reads); replay the on-device chaining + deferred-conf
110
+ tightening already done for our own module (threshold=0 needs NO conf
111
+ reads).
112
+ 3. **captureLayer in the GENERATED gemma forwards** — tapped verifies
113
+ currently fall back to the monolith (correct-but-unspecialized); teach
114
+ scripts/gen-model.ts to emit the tap so spec verifies keep the fast path.
115
+ 4. **γ sweep** — γ=7 at ~30% acceptance wastes drafts;
116
+ `--num-draft-tokens 2..3` may net better wall-clock free of any code.
117
+
118
+ ## PATH B — train our own module (custom targets / research)
119
+
120
+ The payoff target is **12B** (27B is memory-infeasible to train on 24 GB; the
121
+ pipeline stays dim-generic so 27B remains a future recipe). All three scripts
122
+ take `--model` and (new, 2026-07-06) `--tap-layers` — the retarget is now a
123
+ pure parameterization, no code edits. **`--tap-layers` MUST be identical across
124
+ regen and train** (the shard feature dim is `m*H`, `m = tapLayers.length`).
125
+
126
+ 12B tap set: use **`5,17,29,41,46`** — DeepSeek's actual trained
127
+ `target_layer_ids` for this model (their layer-output convention matches our
128
+ tapLayers indexing; audited 2026-07-06). Our earlier `24,37,47,48` guess is
129
+ superseded.
130
+
131
+ ```sh
132
+ # 0. one-time: cache the 12B target + a prompt/topic corpus (thousands of
133
+ # on-distribution topics — the data-scale lever; 160 only reached per-pos ~0.17).
134
+ mlx-bun get mlx-community/gemma-4-12B-it-OptiQ-4bit
135
+ # (12B target may need the serve process stopped to free memory for regen.)
136
+
137
+ # 1. regen multi-layer training shards from the 12B target's own generations
138
+ bun scripts/dspark-regen-dflash.ts \
139
+ --model gemma-4-12B-it-OptiQ-4bit --tap-layers 5,17,29,41,46 \
140
+ --topics <thousands-of-topics.txt> --out data/dspark-12b --max-resp 320
141
+
142
+ # 2. train the drafter against the 12B (warm-start survivable via --resume;
143
+ # GPU runs kept getting killed ~step 5000 pre-resume). Optional A/B:
144
+ # --seq-head rnn trains the Eq-6 RNN head instead of Markov (Eq 5).
145
+ bun scripts/dspark-train-dflash.ts \
146
+ --model gemma-4-12B-it-OptiQ-4bit --tap-layers 5,17,29,41,46 \
147
+ --data data/dspark-12b --out ckpt/dspark-12b \
148
+ --iters 8000 --batch 8 [--seq-head rnn] [--ddraft 2560] [--resume ckpt/dspark-12b]
149
+
150
+ # 3. STS-calibrate (§3.2.1): fit per-position confidence thresholds on real
151
+ # verify outcomes and stamp them into dspark.json — this ACTIVATES the
152
+ # Alg-1 confidence scheduler at decode (uncalibrated = fixed-γ, no change).
153
+ bun scripts/dspark-calibrate.ts \
154
+ --model gemma-4-12B-it-OptiQ-4bit \
155
+ --drafter ckpt/dspark-12b --data <prompts.jsonl> [--target 0.5]
156
+
157
+ # 4. measure live τ + tok/s vs vanilla 12B decode (clean machine — dirty
158
+ # numbers are garbage). Run BOTH pre- and post-calibration for the
159
+ # scheduler's own A/B (MLX_BUN_DSPARK_MINCONF=<c> = manual uniform knob).
160
+ bun scripts/dspark-measure-dflash.ts \
161
+ --model gemma-4-12B-it-OptiQ-4bit \
162
+ --drafter ckpt/dspark-12b --data <prompts.jsonl>
163
+
164
+ # 5. serve it (auto-detected as kind=dspark via dspark.json; γ pinned to cfg.gamma)
165
+ mlx-bun serve --model gemma-4-12B-it-OptiQ-4bit --draft-model ckpt/dspark-12b
166
+ ```
167
+
168
+ Decision gate (write it down, RESULTS.md only if clean-machine): does 12B live
169
+ τ net a wall-clock win? If the draft loop dominates, do the loop-tightening
170
+ (per-position host syncs + double 262K LM-head) first — see the open items in
171
+ the design doc. Memory guard (`server.ts`) caps context to fit; a client
172
+ sending huge `max_tokens` trips admission — lower it.
173
+
9
174
  ## What happened (short version)
10
175
  - Built v1 first as a single-vector shortcut — it dropped the paper's core KV
11
176
  injection and was never really DSpark. Chunk (τ≈1.26) and article (τ≈1.16)
@@ -31,20 +196,21 @@ architecture problem. Full design + measured numbers:
31
196
  - Training `--resume` (warm-start from checkpoint) — the GPU runs kept getting killed ~step 5000; resume survives that.
32
197
 
33
198
  ## Next (in priority order)
34
- 1. **Retarget to a slow model (27B or 12b).** The drafter reads dims from the
35
- model + tapLayers is config, so it ports — but needs regen+train on that
36
- model. 27B on 32GB is memory-tight (17.75GB weights); may need the serve
37
- process stopped to free the ~14GB for regen. This is where a real speedup lives.
38
- 2. **Scale training data** — thousands of on-distribution generations (not 160)
39
- to lift generalizing τ toward the overfit ~0.75.
40
- 3. **Tighten the draft inference loop** — per-position host syncs + double 262K
41
- LM-head make the draft heavy; needed for τ to translate to wall-clock.
42
- 4. **Finish the paper:** RNN head (Eq 6), STS calibration (§3.2.1), hardware-aware
43
- prefix scheduler (Alg 1 — single-user = confidence-scheduled draft-length pruning).
44
- 5. **Rename** `dflash`→`dspark` (faithful module IS DSpark; v1 = legacy single-vector).
199
+ 1. **Retarget to 12B + scale data + train + calibrate + measure** — the GPU
200
+ recipe above is the complete remaining work. (27B stays a future recipe:
201
+ memory-infeasible to train on the 24 GB M4 Pro.)
202
+ 2. ~~Tighten the draft inference loop~~ **DONE 2026-07-06** (on-device token
203
+ chaining, deferred conf reads, `collectLogits:false`; bit-identity pinned).
204
+ 3. ~~Finish the paper~~ **DONE 2026-07-06**: RNN head (Eq 6, `--seq-head rnn`),
205
+ STS calibration (§3.2.1), Alg-1 confidence-scheduled draft-length pruning
206
+ (single-user form). ⚠ Eq 6 + §3.2.1 shapes are design-doc-faithful readings
207
+ (paper PDF absent) — verify against the paper when available.
208
+ 4. ~~Rename `dflash`→`dspark`~~ **DONE 2026-07-06** (canonical variant +
209
+ central loader `src/spec/dspark/loader.ts`; legacy stamps still load).
45
210
 
46
211
  ## Key files
47
- `src/spec/dspark/{module,data,generate}-dflash.ts`, `{loss,sample}.ts`;
212
+ `src/spec/dspark/{module,data,generate}-dflash.ts`, `{loss,sample,calibration,loader}.ts`;
213
+ `src/spec/{source,serve-loop,dflash-source,assistant-source}.ts` (the serve seam);
48
214
  `src/model/gemma4.ts` (hiddenTap), `gemma4-base.ts` (trim bypass);
49
215
  `scripts/dspark-{regen,train,measure}-dflash.ts`, `dspark-dflash-smoke.ts`.
50
216
 
@@ -1,7 +1,7 @@
1
1
  # Build journal — mlx-bun Lab (web UI + native quantize/train/dataset + pi web chat)
2
2
 
3
3
  *Branch `web-ui-and-native-lab`, 2026-06-13/14. Visual summary:
4
- [archive/mlx-bun-lab-report.html](../../archive/mlx-bun-lab-report.html). Evidence
4
+ [archive/mlx-bun-lab-report.html](../../docs/archive/mlx-bun-lab-report.html). Evidence
5
5
  artifact: `benchmarks/lab-verification.json` (regenerable, gitignored — produced by
6
6
  `scripts/verify-lab.ts`).*
7
7
 
@@ -22,7 +22,7 @@ page. Compute is **native Bun/MLX (no Python)** per Josh's decision.
22
22
 
23
23
  2. **Gate the riskiest unknown first.** Native LoRA needs autograd across the
24
24
  FFI boundary. Rather than discover mid-build that it's infeasible, the first
25
- thing built was `spikes/phase-train-vag.ts`: a tiny LoRA-shaped loss
25
+ thing built was `lab/spikes/phase-train-vag.ts`: a tiny LoRA-shaped loss
26
26
  (`mean((x + (x@A)@B − y)²)`) differentiated by `mlx_value_and_grad` through a
27
27
  `bun:ffi` JSCallback closure, checked against central finite differences.
28
28
  **PASS (<1e-2), exactly 2 grads returned (base frozen).** Only then was the
@@ -0,0 +1,249 @@
1
+ # OpenWiki — evaluation & fit analysis
2
+
3
+ **Date:** 2026-07-06
4
+ **Author:** investigation (agent), worktree `investigate/openwiki-memory`
5
+ **Subject:** [langchain-ai/openwiki](https://github.com/langchain-ai/openwiki) — "a CLI that writes and
6
+ maintains agent documentation for your codebase, built specifically for agents to consume."
7
+ **Question asked:** how (if at all) does OpenWiki fit inside our memory system ("The Dreaming"), and
8
+ is it a good fit anywhere else in mlx-bun?
9
+
10
+ ---
11
+
12
+ ## TL;DR — four verdicts
13
+
14
+ | # | Question | Verdict | One-liner |
15
+ |---|----------|---------|-----------|
16
+ | 1 | Adopt OpenWiki **as the memory engine**? | ❌ **No** | Architecturally the mirror-image of The Dreaming; would throw away the hard-won decomposition + gate design and drag LangChain into a Bun/MLX-only repo. |
17
+ | 2 | Borrow OpenWiki **patterns** into memory? | 🟡 **Marginal** | We already independently arrived at its good ideas, usually in stronger form. One minor borrow (the `_plan.md` durable-plan artifact). |
18
+ | 3 | Run OpenWiki **on mlx-bun the repo** (its own agent docs)? | ✅ **Yes, good fit** | It targets exactly our named failure mode — reference-doc drift — and runs as an external dev tool, not a vendored dep. |
19
+ | 4 | Point OpenWiki **at our own OpenAI-compatible server**? | ✅ **Yes — the strategic find** | DeepAgents-over-local-mlx-bun is an on-brand, zero-cloud dogfood showcase *and* a hard agentic-tool-use conformance test for the server. |
20
+
21
+ The headline: **OpenWiki is not a fit *inside* the memory pipeline, but it is a fit *around* mlx-bun** —
22
+ as a doc tool for our own repo and, more interestingly, as a real LangChain agent to run *against* our
23
+ server to prove the "drop-in, local, agentic" thesis.
24
+
25
+ ---
26
+
27
+ ## 1. What OpenWiki is (full rundown)
28
+
29
+ A CLI (`npm install -g openwiki`) from LangChain, released **v0.0.1 on 2026-07-05** (i.e. one day old at
30
+ time of writing; ~7.7k stars, but 42 open PRs / 48 issues — treat as brand-new and unstable). MIT
31
+ licensed. TypeScript/JavaScript.
32
+
33
+ **Purpose.** Generate and maintain a repo's documentation *for coding agents*, not for humans. The
34
+ generated wiki is "structured markdown optimized for LLM context — headings, cross-references, and
35
+ summaries designed for an agent to quickly find relevant context." Motivation from the launch post:
36
+ *"Agents write better code when they understand the repo they're working in,"* and stuffing the whole
37
+ repo into one `CLAUDE.md` wastes context in large repos.
38
+
39
+ **Surface.**
40
+ ```
41
+ openwiki --init # pick provider + API key, then generate the wiki
42
+ openwiki # interactive
43
+ openwiki "<request>" # interactive, seeded
44
+ openwiki -p "<request>" # one-shot, non-interactive
45
+ openwiki --update # refresh from repo changes since last run
46
+ ```
47
+ - Writes an `openwiki/` directory of markdown pages.
48
+ - Patches `AGENTS.md` / `CLAUDE.md` with a pointer to the wiki **and a "when to use it" note**.
49
+ - Ships a **GitHub Action** and **GitLab CI** template that open a PR/MR when docs need updating.
50
+ - Config in `~/.openwiki/.env`: provider, API key, model id, optional LangSmith tracing.
51
+ - Providers: OpenRouter (default, an open model), Fireworks, Baseten, OpenAI, Anthropic, and
52
+ **OpenAI-compatible** via `OPENAI_COMPATIBLE_BASE_URL` (also `ANTHROPIC_BASE_URL`). ← load-bearing
53
+ for verdict 4.
54
+
55
+ ## 2. How OpenWiki works (architecture)
56
+
57
+ Built on LangChain's **DeepAgents** + **LangGraph**. The construction is deliberately thin:
58
+
59
+ ```ts
60
+ const agent = createDeepAgent({
61
+ model,
62
+ tools: [], // NO custom tools
63
+ checkpointer, // thread memory
64
+ backend: new LocalShellBackend({ /* vfs → repo root */ }),
65
+ systemPrompt: createSystemPrompt(command),
66
+ });
67
+ ```
68
+
69
+ - **No bespoke tools.** It hands a general coding agent a `LocalShellBackend`: a virtual filesystem
70
+ mapped to the repo root exposing `ls / read_file / write_file / edit_file / glob / grep` plus a
71
+ sandboxed `execute` (120 s timeout, 100 KB output cap). All capability comes from the shell backend.
72
+ - **All the IP is in the system prompt + the loop.** The prompt encodes:
73
+ - **Discovery → plan.** Before writing, the agent writes a temporary `openwiki/_plan.md` listing
74
+ *intended pages, source evidence per page, and remaining questions.*
75
+ - **Granularity rules.** ≤~10 primary source files → a `quickstart.md` + at most 1–2 supporting
76
+ pages. *"Do not create a directory unless it represents a real documentation area."*
77
+ - **One canonical page per concept.** *"Keep each concept in one canonical page… keep the detailed
78
+ explanation in the canonical page and make other mentions brief or link-only."* Inline source-file
79
+ references so a reader can verify.
80
+ - **Surgical, diff-budgeted updates.** On `--update` it *"checks which commits landed since the last
81
+ run, uses git diffs to understand what changed, then updates the wiki."* Soft budget: *"if fewer
82
+ than about 5 source files changed, update at most 1–2 wiki pages… Updates may be a no-op."*
83
+ - **Change detection** by content snapshot (`createOpenWikiContentSnapshot`); persists run metadata
84
+ only when the wiki actually changed.
85
+ - Streaming LangGraph invocation with a checkpointer keyed by `thread_id` (interactive Q&A over the
86
+ wiki + codebase reuses the thread).
87
+
88
+ **Design bet:** a *strong single model* + a *good prompt* + a *free-roaming agent* with raw shell
89
+ tools. Trust the model to hold the repo in its head and write files directly.
90
+
91
+ ## 3. The Dreaming, in one screen (for contrast)
92
+
93
+ Our memory system ("The Dreaming", `src/memory/*`, ~12 k LoC, running end-to-end on real data):
94
+
95
+ - **Corpus:** the user's conversation history (pointer-DB of `messages` → `chunks` as
96
+ `(conv,start,end)` ranges), not a code tree.
97
+ - **Engine:** ONE local model (`gemma-4-e4b-it-OptiQ-4bit`) + per-stage LoRAs, loaded once. No cloud.
98
+ - **Pipeline:** `SEGMENT → EXTRACT → ROUTE → SECTION-ROUTE → PATCH → NORMALIZE → LINK → WIKIFY →
99
+ RECONCILE → COMMIT`, every stage the *smallest atomic task* (binary yes/no preferred).
100
+ - **Output:** entity-centric wiki — articles are *things*, with infoboxes, wikilinks, categories.
101
+ - **Invariants enforced by code, not the model:** *"LoRAs propose, gates dispose"* — ≥70% prose floor,
102
+ every citation survives, weak output → NO-OP, deterministic footnote bijection + wikilink
103
+ canonicalization, one git commit per run.
104
+ - **Single writer:** *"Chat agents read memory; `mlx-bun memory synthesize` is the only writer."* Reads
105
+ go through 7 read-only `memory_*` tools + a bundled skill.
106
+ - **Self-healing:** chronological walk; latest statement wins; AI errors silently overwritten.
107
+
108
+ **Design bet:** the exact opposite of OpenWiki — a *weak local model* + *heavy decomposition* +
109
+ *deterministic scaffolding*. Assume the model **cannot** hold an article in its head or be trusted to
110
+ write files freely, and engineer around that.
111
+
112
+ ## 4. Head-to-head: same shape, opposite philosophy
113
+
114
+ Both are *"corpus → agentic synthesis → LLM-navigable markdown wiki → agent consumes it, kept fresh
115
+ incrementally."* That surface similarity is why the question is worth asking. But under the hood they
116
+ are mirror images:
117
+
118
+ | Axis | OpenWiki | The Dreaming |
119
+ |------|----------|--------------|
120
+ | Corpus | Code repository | Personal conversation history |
121
+ | Model | Strong cloud model (default OpenRouter) | Weak local e4b + LoRAs, no cloud |
122
+ | Capacity model | Big context — model holds the repo | *Capacity by decomposition* — can't hold an article |
123
+ | Harness | Thin (shell tools + one prompt) | Thick (10-stage DAG, ledgers, gates) |
124
+ | Writes | Agent writes files freely | Single writer, gated, git-committed |
125
+ | Dedup | Prompt rule ("one canonical page") | Deterministic entity name-match routing |
126
+ | Update trigger | `git diff` since last commit | Chronological chunk cursor / new sessions |
127
+ | Self-healing | Re-edit page on diff | Chronological latest-value reconcile |
128
+ | Determinism | Trusts the model | Code enforces invariants |
129
+ | Deps | LangChain + DeepAgents + LangGraph | Bun-native, MLX-only, minimal |
130
+
131
+ Pithily: **OpenWiki = smart model, dumb harness. The Dreaming = dumb model, smart harness.** They solve
132
+ the same *shape* of problem from opposite ends of the model-capability axis.
133
+
134
+ ## 5. The four fit verdicts, argued
135
+
136
+ ### Verdict 1 — OpenWiki as the memory engine: ❌ No
137
+
138
+ - **Architectural inversion.** The Dreaming's entire thesis is that a local 4-bit e4b *cannot* do
139
+ OpenWiki's free-roaming, hold-it-in-context, write-files-directly loop — which is *why* the
140
+ decomposition + gate architecture exists. Adopting OpenWiki means discarding the exact design that
141
+ makes local synthesis work.
142
+ - **Contract violation.** OpenWiki's agent writes files freely; The Dreaming has a single gated writer
143
+ with a git-commit-per-run audit trail and NO-OP-on-weak-output. These are incompatible write models.
144
+ - **Corpus mismatch.** OpenWiki reads a code tree via shell/grep; The Dreaming reads a pointer-DB of
145
+ conversation chunks with chronological self-healing. Different input, different invariants.
146
+ - **Identity/deps.** Pulling LangChain + LangGraph into a repo whose stated identity is Bun-native,
147
+ MLX-only, minimal-dep, private (see the `mlx-bun scope & framing` and `drop-in replacement` notes)
148
+ is a non-starter as a runtime dependency.
149
+ - **Maturity.** v0.0.1, one day old. Nothing load-bearing should sit on it yet.
150
+
151
+ ### Verdict 2 — Borrow OpenWiki's patterns: 🟡 Marginal
152
+
153
+ We have *convergently* arrived at most of OpenWiki's good ideas, usually stronger:
154
+
155
+ | OpenWiki idea | Our equivalent | Who's ahead |
156
+ |---------------|----------------|-------------|
157
+ | `_plan.md` before writing | CREATE flow: sub-cluster → outline → draft | ~tie; their durable, reviewable *plan artifact* is a nice touch |
158
+ | Soft diff budget, updates may be no-op | Idempotency ledger + conservative gate + NO-OP | **us** (ledger is stronger than a prompt heuristic) |
159
+ | One canonical page (prompt rule) | Deterministic entity name-match routing | **us** (mechanism > instruction) |
160
+ | Patch `AGENTS.md`/`CLAUDE.md` with pointer | 7 read-only `memory_*` tools + bundled skill | **us** (tools > prose pointer) |
161
+ | git-diff-driven refresh | chronological chunk cursor | different corpus; both valid |
162
+
163
+ **Only genuinely fresh borrow:** emit a durable, auditable **plan artifact** (their `_plan.md`) in the
164
+ CREATE flow, so a synthesis run's *intended* article/section changes are reviewable in the git diff
165
+ alongside the result. Low effort, small upside. Not worth a dedicated work item; fold in opportunistically.
166
+
167
+ ### Verdict 3 — Run OpenWiki on mlx-bun the repo: ✅ Good fit
168
+
169
+ This is where OpenWiki was literally built to help, and mlx-bun is close to a canonical target:
170
+
171
+ - **It attacks our named failure mode.** `CLAUDE.md` calls reference-doc drift *"the observed failure
172
+ mode"* (the 2026-07-03 sweep found undocumented flags, dead version pins). The doc-map even carries a
173
+ manual chore: *"keep these lists in sync with `ls docs/…`."* OpenWiki's diff-driven refresh + CI-PR is
174
+ exactly this job.
175
+ - **Additive, not a replacement.** It would generate a *derived, agent-facing structural index of the
176
+ code* — it does **not** replace the curated, opinionated human docs (`PLAN.md` is "the engineering
177
+ contract"; `STATUS.md`, design docs). Think: an auto-maintained `openwiki/` map of `src/` that points
178
+ back into the hand-written design docs.
179
+ - **Nice synergy with the vault.** The memory vault already symlinks mlx-bun docs into
180
+ `~/.mlx-bun/wiki/Reference/` (read-only). An auto-maintained repo wiki would flow straight into that
181
+ Reference surface — the personal vault gets a fresher code map for free.
182
+ - **Runs as an external dev tool**, a global npm CLI in CI — *not* a vendored dependency. No LangChain
183
+ contamination of the shipped codebase. This sidesteps the Verdict-1 dependency objection entirely.
184
+
185
+ **Caveat:** the one tension is "cloud API on a local/private repo." Verdict 4 dissolves it.
186
+
187
+ ### Verdict 4 — Point OpenWiki at our own OpenAI-compatible server: ✅ The strategic find
188
+
189
+ OpenWiki speaks **OpenAI-compatible base URL**; mlx-bun *is* an OpenAI-compatible server (the whole
190
+ "drop-in replacement for mlx-lm / serving speed is the user metric" thesis). Compose them:
191
+
192
+ ```
193
+ OPENAI_COMPATIBLE_BASE_URL=http://localhost:<mlx-bun-port> \
194
+ OPENAI_COMPATIBLE_API_KEY=… openwiki --init # generate mlx-bun's own wiki, 100% local
195
+ ```
196
+
197
+ Why this is the most interesting outcome of the investigation:
198
+
199
+ 1. **On-brand, zero-cloud.** Resolves the Verdict-3 tension: a real LangChain agent documents our repo
200
+ with *no* cloud call, on a Gemma running in mlx-bun. Directly demonstrates the `local-to-you` and
201
+ `install-to-chat` theses on an external, third-party agent.
202
+ 2. **A hard conformance test.** DeepAgents drives many tool calls + long contexts + streaming. Chat
203
+ parity is easy; *agentic tool-use conformance* is the bar that actually matters for "agents need the
204
+ server" (`serving speed is the user metric`). If OpenWiki runs unmodified end-to-end against our
205
+ server, that's a strong, concrete proof point for the README/website. If it *doesn't*, we've found a
206
+ real function-calling / prefill / KV gap under agentic load — also valuable.
207
+ 3. **Coverage/stress.** It exercises the server the way a coding agent does (glob/grep/read/write loops,
208
+ big prefills), complementing the batch/spec-decode perf work with a realistic agentic workload.
209
+
210
+ **Caveat to measure, not assume:** DeepAgents presumes a *capable* model — the very assumption The
211
+ Dreaming rejects for local e4b. A 4-bit e4b may drive the free-roaming loop poorly and produce a
212
+ mediocre wiki. Mitigations: point it at a larger local model (the 12B parity target) via the same
213
+ server, and/or judge output quality explicitly. Either way the *conformance* result (does the loop run?)
214
+ is decoupled from the *quality* result (is the wiki good?), and both are worth knowing.
215
+
216
+ ## 6. Recommendation — what to actually do
217
+
218
+ 1. **Do not** put OpenWiki inside the memory pipeline. The Dreaming is more mature for its constraints
219
+ and philosophically opposite. (Verdicts 1 & 2.)
220
+ 2. **Spike Verdict 4 first — it's the highest-information, lowest-cost move.** Point OpenWiki at a
221
+ running mlx-bun server (Josh runs the server; no session starts it) and try `openwiki --init` on a
222
+ small repo, then on mlx-bun itself. Outcome is binary-useful: either a showcase demo of
223
+ "third-party LangChain agent runs locally on mlx-bun," or a concrete agentic-tool-use bug list for
224
+ the server. Bench it under the standard preflight if any perf number gets quoted
225
+ (`dirty-machine-numbers-are-garbage`).
226
+ 3. **If the spike is clean,** consider OpenWiki as an *external CI doc tool* for the repo (Verdict 3):
227
+ an auto-maintained `openwiki/` structural map that feeds the vault's `Reference/` surface. Keep it
228
+ clearly subordinate to the hand-written `PLAN.md`/design docs.
229
+ 4. **Opportunistically** add a durable `_plan.md`-style plan artifact to the memory CREATE flow for
230
+ reviewability (Verdict 2). Not a standalone work item.
231
+
232
+ ## 7. Risks & unknowns
233
+
234
+ - OpenWiki is **v0.0.1, ~1 day old**, 42 open PRs / 48 issues — API and behavior will churn. Pin a
235
+ commit if used in CI.
236
+ - **Local-model quality** driving DeepAgents is unproven (contradicts our own capacity-by-decomposition
237
+ finding). Measure; don't assume the wiki is good just because the loop runs.
238
+ - **DeepAgents ⇄ our server function-calling compatibility** is the actual thing under test in Verdict
239
+ 4 — tool-call formatting, streaming, and long-prefill behavior are where it could break.
240
+ - Do **not** treat any OpenWiki-generated wiki as a source of truth over the curated docs; it's a
241
+ derived index.
242
+
243
+ ## Sources
244
+
245
+ - [langchain-ai/openwiki](https://github.com/langchain-ai/openwiki) — repo, README, `src/agent/*`
246
+ - [LangChain blog — Introducing OpenWiki](https://www.langchain.com/blog/introducing-openwiki-an-open-source-agent-for-repo-documentation)
247
+ - Internal: `docs/design/memory-system.md`, `memory-synthesis.md`, `memory-inference-path.md`,
248
+ `write-pipeline-entity.md`, `the-dreaming-master-plan.md`, `the-dreaming-handoff.md`,
249
+ `docs/reference/memory.md`; `src/memory/*` (~12 k LoC).
@@ -53,3 +53,17 @@ persistent memory of *you*; mlx-bun is the local, private model runtime.
53
53
  Combined: a model that runs entirely on your machine **and** is continuously
54
54
  grounded in your own accumulated context — local in both senses, and yours in a
55
55
  way no hosted frontier model can be.
56
+
57
+
58
+ ## Library/app split (idea only — NOT planned, Josh 2026-07-05)
59
+
60
+ Two pulls: "one executable, everything you want to do with local AI" (the
61
+ product's charm) vs "some people just want a JS ML library — do they need
62
+ the rest?" The runtime-isolation work (2026-07-05) drew the exact boundary
63
+ either future needs: the engine child = the GPU stuff (src/model, src/mlx,
64
+ caches, scheduler, generate); the parent = the app (serve/UI/registry/
65
+ jobs/proxy). If a split ever happens it is a PACKAGING decision, not a
66
+ refactor — e.g. npm subpath exports (mlx-bun/model vs the full CLI bundle)
67
+ so library users import only the core. Library usage is unaffected by
68
+ isolation today (in-process generate(), no server involved). Revisit only
69
+ if Josh decides; both directions stay open from the current structure.
@@ -171,7 +171,6 @@ Each profile should eventually carry:
171
171
  kv: "mixed",
172
172
  memoryBudgetBytes: "...",
173
173
  compiledDecode: true,
174
- perfKernel: false,
175
174
  expectedDecodeTps: 30,
176
175
  expectedTtftMs: 100,
177
176
  label: "Recommended for this Mac",
@@ -309,8 +308,8 @@ to text-only mode when no image is present, so the chat UI gains image support
309
308
  with no startup cost. Features are within ~1% rel-RMSE of the optiq oracle;
310
309
  every MLX primitive (rms_norm, gelu, matmul, SDPA, RoPE, pooling) is bit-exact.
311
310
  The residual is sub-bf16 floating-point accumulation across the deep encoder,
312
- not a porting gap. L1/L2/L3 paths all work; vision falls back to the monolith
313
- path on L1 and L2.
311
+ not a porting gap. The L1 and L2 paths both work; vision falls back to the
312
+ monolith path on L1 and L2.
314
313
 
315
314
  ### Adapter web selector and CLI /v1/adapters (shipped)
316
315