mlx-bun 0.0.10 → 0.0.12

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 (216) hide show
  1. package/README.md +107 -32
  2. package/THIRD_PARTY_LICENSES.md +10 -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/colibri-glm52-port.md +1479 -0
  10. package/docs/design/compat-cli-surface-design.md +4 -3
  11. package/docs/design/decode-speed-program.md +172 -0
  12. package/docs/design/docs-reorg-plan.md +1 -1
  13. package/docs/design/dspark-serving-program.md +371 -0
  14. package/docs/design/dspark-speculative-decoding.md +167 -5
  15. package/docs/design/faithful-l1-consolidation.md +310 -0
  16. package/docs/design/generic-model-support.md +8 -5
  17. package/docs/design/grammar-spec-batching-integration.md +301 -0
  18. package/docs/design/minicpm5-decode-megakernel.md +16 -11
  19. package/docs/design/mlx-lm-tool-parity-plan.md +11 -1
  20. package/docs/design/omlx-adoption-map.md +14 -6
  21. package/docs/design/orpo-training.md +34 -30
  22. package/docs/design/paged-kv-cache.md +214 -0
  23. package/docs/design/parallel-slots.md +82 -49
  24. package/docs/design/parity-tier-dag.md +43 -33
  25. package/docs/design/pre-colibri-stabilization.md +329 -0
  26. package/docs/design/repo-cleanup-plan.md +189 -0
  27. package/docs/design/runtime-isolation.md +19 -3
  28. package/docs/design/segmented-backward-training.md +3 -2
  29. package/docs/design/ssd-kv-cold-tier.md +130 -0
  30. package/docs/design/structured-output.md +484 -0
  31. package/docs/design/the-dreaming-master-plan.md +2 -3
  32. package/docs/design/turboquant-kv.md +235 -0
  33. package/docs/design/unified-engine-frontier-plan.md +774 -0
  34. package/docs/design/web-chat-beat-matrix.md +315 -0
  35. package/docs/design/web-chat-redesign.md +1112 -0
  36. package/docs/investigations/colibri-oracle-pin.md +1284 -0
  37. package/docs/investigations/dspark-handoff.md +182 -16
  38. package/docs/investigations/indexshare-performance-spike.md +357 -0
  39. package/docs/investigations/lab-build-journal.md +2 -2
  40. package/docs/investigations/openwiki-evaluation.md +249 -0
  41. package/docs/planning/IDEAS.md +14 -0
  42. package/docs/planning/PRODUCT_ROADMAP.md +2 -3
  43. package/docs/planning/chat-ui-vision-memory-first.md +199 -0
  44. package/docs/planning/chat-ui-vision.md +50 -0
  45. package/docs/planning/memory-docs-and-dag-plan.md +15 -6
  46. package/docs/planning/release-notes-v0.0.11.md +239 -0
  47. package/docs/planning/release-notes-v0.0.12.md +80 -0
  48. package/docs/reference/cli.md +63 -18
  49. package/docs/reference/distribution.md +37 -6
  50. package/docs/reference/embedding.md +40 -16
  51. package/docs/reference/features-matrix.md +99 -0
  52. package/docs/reference/library-api.md +69 -20
  53. package/docs/reference/memory.md +26 -6
  54. package/docs/reference/models.md +60 -3
  55. package/docs/reference/orpo-quickstart.md +3 -4
  56. package/docs/reference/server-api.md +717 -24
  57. package/docs/reference/server-config.md +265 -129
  58. package/docs/reference/training.md +24 -16
  59. package/package.json +5 -3
  60. package/src/anthropic.ts +67 -44
  61. package/src/audio/conformer.ts +647 -0
  62. package/src/audio/decode.ts +133 -0
  63. package/src/audio/features.ts +202 -0
  64. package/src/audio/transcode.ts +67 -0
  65. package/src/chat-template.ts +155 -10
  66. package/src/cli.ts +483 -113
  67. package/src/config.ts +116 -24
  68. package/src/diffusion/diffusion-generate.ts +14 -8
  69. package/src/download.ts +143 -12
  70. package/src/eval/README.md +7 -6
  71. package/src/eval/ifeval.ts +63 -120
  72. package/src/eval/kl.ts +59 -3
  73. package/src/eval/quality-db.ts +2 -2
  74. package/src/eval/runner.ts +17 -8
  75. package/src/eval/tasks/ifeval.ts +167 -31
  76. package/src/expert-io.ts +391 -0
  77. package/src/expert-offload.ts +15 -2
  78. package/src/expert-residency.ts +1134 -0
  79. package/src/expert-usage.ts +415 -0
  80. package/src/flags.ts +13 -0
  81. package/src/generate.ts +438 -35
  82. package/src/grammar.ts +585 -0
  83. package/src/hf-push.ts +1 -1
  84. package/src/hub-rest.ts +242 -0
  85. package/src/index.ts +14 -2
  86. package/src/jobs/runner.ts +37 -18
  87. package/src/kv-store.ts +586 -93
  88. package/src/lora.ts +85 -14
  89. package/src/md-modules.d.ts +42 -0
  90. package/src/media-fetch.ts +426 -0
  91. package/src/memory/rest.ts +245 -0
  92. package/src/memory/vault.ts +74 -0
  93. package/src/mlx/array.ts +149 -19
  94. package/src/mlx/autograd.ts +53 -16
  95. package/src/mlx/checkpoint.ts +46 -13
  96. package/src/mlx/custom-vjp.ts +83 -35
  97. package/src/mlx/ffi.ts +27 -3
  98. package/src/mlx/metal-kernel.ts +7 -4
  99. package/src/mlx/ops.ts +153 -23
  100. package/src/mlx/turboquant-ops.ts +831 -0
  101. package/src/mlx/turboquant-tables.ts +237 -0
  102. package/src/model/batched-mask.ts +62 -1
  103. package/src/model/batched-quant.ts +206 -0
  104. package/src/model/batched-rotating-quant.ts +346 -0
  105. package/src/model/batched-rotating.ts +46 -1
  106. package/src/model/compiled-decode.ts +4 -15
  107. package/src/model/factory.ts +103 -6
  108. package/src/model/gemma4-base.ts +395 -39
  109. package/src/model/gemma4.ts +122 -33
  110. package/src/model/generated/gemma4-12b.ts +9 -13
  111. package/src/model/generated/gemma4-26b.ts +10 -5
  112. package/src/model/generated/gemma4-e4b.ts +14 -9
  113. package/src/model/glm52-atlas.ts +511 -0
  114. package/src/model/glm52-cache.ts +706 -0
  115. package/src/model/glm52-config.ts +262 -0
  116. package/src/model/glm52-container.ts +305 -0
  117. package/src/model/glm52-coupling.ts +388 -0
  118. package/src/model/glm52-dsa.ts +602 -0
  119. package/src/model/glm52-expert-layout.ts +253 -0
  120. package/src/model/glm52-layout.ts +152 -0
  121. package/src/model/glm52-memory.ts +473 -0
  122. package/src/model/glm52-mla.ts +786 -0
  123. package/src/model/glm52-moe.ts +223 -0
  124. package/src/model/glm52-pilot.ts +537 -0
  125. package/src/model/glm52-reference.ts +445 -0
  126. package/src/model/glm52-residency.ts +557 -0
  127. package/src/model/glm52-resident-weights.ts +135 -0
  128. package/src/model/glm52-streamed-experts.ts +453 -0
  129. package/src/model/glm52-streamed-metal.ts +610 -0
  130. package/src/model/glm52-weights.ts +503 -0
  131. package/src/model/glm52.ts +1153 -0
  132. package/src/model/minicpm5.ts +58 -102
  133. package/src/model/paged-kv.ts +253 -0
  134. package/src/model/qwen3-delta.ts +76 -15
  135. package/src/model/qwen3-moe.ts +404 -0
  136. package/src/model/qwen3.ts +9 -8
  137. package/src/model/qwen3_5.ts +88 -23
  138. package/src/model/support.ts +19 -1
  139. package/src/model/universal/dense.ts +40 -5
  140. package/src/model/universal/rope.ts +36 -21
  141. package/src/native/expert_io.c +523 -0
  142. package/src/native-pack.ts +6 -4
  143. package/src/pi-web.ts +1299 -82
  144. package/src/preflight.ts +27 -8
  145. package/src/prompt-cache.ts +293 -33
  146. package/src/quantize/quantizer.ts +16 -1
  147. package/src/registry.ts +57 -2
  148. package/src/responses.ts +62 -49
  149. package/src/serve/batch-scheduler.ts +1050 -78
  150. package/src/serve/generation-gateway.ts +252 -24
  151. package/src/serve/isolate.ts +417 -0
  152. package/src/serve/lane-registry.ts +44 -0
  153. package/src/serve/session-search.ts +326 -0
  154. package/src/server.ts +1701 -175
  155. package/src/spec/assistant-source.ts +150 -0
  156. package/src/spec/deepspec-source.ts +143 -0
  157. package/src/spec/dflash-source.ts +124 -0
  158. package/src/spec/dspark/ab-stats.ts +136 -0
  159. package/src/spec/dspark/calibration.ts +112 -0
  160. package/src/spec/dspark/deepspec-module.ts +801 -0
  161. package/src/spec/dspark/generate-dflash.ts +72 -20
  162. package/src/spec/dspark/loader.ts +23 -0
  163. package/src/spec/dspark/module-dflash.ts +278 -36
  164. package/src/spec/dspark/quantize-drafter.ts +91 -0
  165. package/src/spec/generate.ts +59 -25
  166. package/src/spec/glm52-mtp-source.ts +392 -0
  167. package/src/spec/ngram-source.ts +132 -0
  168. package/src/spec/serve-loop.ts +617 -0
  169. package/src/spec/source.ts +118 -0
  170. package/src/spec/two-model.ts +171 -0
  171. package/src/ssd-cache.ts +111 -35
  172. package/src/tokenizer.ts +288 -2
  173. package/src/tool-approvals.ts +131 -0
  174. package/src/tool-call.ts +438 -22
  175. package/src/train/flash-cce.ts +2 -2
  176. package/src/train/job.ts +0 -12
  177. package/src/train/lora-params.ts +17 -6
  178. package/src/train/trainer.ts +60 -30
  179. package/src/vision/prompt.ts +217 -48
  180. package/src/web/app.html +1197 -1791
  181. package/src/web/app.js +5694 -0
  182. package/src/web/icon.svg +13 -0
  183. package/src/web/manifest.webmanifest +24 -0
  184. package/src/web/src/adapters-panel.ts +288 -0
  185. package/src/web/src/api.ts +57 -0
  186. package/src/web/src/assistant.ts +485 -0
  187. package/src/web/src/chat.ts +1050 -0
  188. package/src/web/src/composer.ts +959 -0
  189. package/src/web/src/dataset.ts +132 -0
  190. package/src/web/src/finetune.ts +267 -0
  191. package/src/web/src/hub.ts +428 -0
  192. package/src/web/src/main.ts +98 -0
  193. package/src/web/src/markdown.ts +0 -0
  194. package/src/web/src/memory-panel.ts +572 -0
  195. package/src/web/src/model-picker.ts +159 -0
  196. package/src/web/src/palette.ts +346 -0
  197. package/src/web/src/protocol.ts +62 -0
  198. package/src/web/src/quantize.ts +167 -0
  199. package/src/web/src/rag.ts +274 -0
  200. package/src/web/src/sessions.ts +469 -0
  201. package/src/web/src/shell.ts +804 -0
  202. package/src/web/src/status.ts +300 -0
  203. package/src/web/src/ui-catalog.ts +92 -0
  204. package/src/web/sw.js +71 -0
  205. package/src/web/vendor/README.md +61 -0
  206. package/src/web/vendor/hljs-LICENSE +29 -0
  207. package/src/web/vendor/hljs-theme.css +59 -0
  208. package/src/web/vendor/hljs.js +26 -0
  209. package/src/web-tools.ts +54 -2
  210. package/src/weights.ts +82 -19
  211. package/src/model/fused-decode-kernel.ts +0 -312
  212. package/src/model/fused-geglu-kernel.ts +0 -198
  213. package/src/model/fused-mlp-kernel.ts +0 -169
  214. package/src/model/fused-swiglu-kernel.ts +0 -240
  215. package/src/model/steel-linear-kernel.ts +0 -96
  216. package/src/status-page.html +0 -497
@@ -0,0 +1,239 @@
1
+ # v0.0.11 release notes
2
+
3
+ Everything since v0.0.10. The big themes: mlx-bun grows a second modality
4
+ (audio), a constrained-decoding stack (structured output / grammar),
5
+ speculative decoding, a novel KV-cache quantization scheme (TurboQuant),
6
+ completed dynamic batching, crash-isolated serving, and a ground-up
7
+ rewrite of the web chat UI. The decode-default story also resets: after
8
+ benchmarking every custom performance kernel in a paired A/B against the
9
+ bit-exact baseline and finding none of them won, they were deleted —
10
+ naked `mlx-bun serve` now runs the faithful, mlx-lm-parity kernel set by
11
+ default.
12
+
13
+ ## Audio input (Gemma e4b)
14
+
15
+ - OpenAI-style `input_audio` parts are served end-to-end: WAV/AAC
16
+ transcode, a USM mel-spectrogram extractor, and a Conformer tower
17
+ ported bit-exact (rel-RMSE 2.4e-8) against the oracle.
18
+ - Build-out ran phase-by-phase (A0–A5): a `bun:ffi` conv2d binding for
19
+ the front-end, the multimodal prompt builder wired to the LM, and
20
+ capability discovery for audio surfaced consistently across
21
+ `/v1/models`, `/library`, and the pi websocket handshake — mirroring
22
+ how vision capability is advertised.
23
+
24
+ ## Structured output / grammar-constrained generation
25
+
26
+ - `response_format` (`json_object`, `json_schema`, `text`) and
27
+ `guided_grammar`/`guided_regex`/`guided_choice`/`structured_outputs`
28
+ are wired into both `/v1/chat/completions` and `/v1/completions`, built
29
+ on `xgrammar`: a `GrammarController` masks logits inside the decode
30
+ loop, with a per-`TokenizerInfo` compiler cache and a `MLX_BUN_GRAMMAR=0`
31
+ kill switch.
32
+ - The batched lane got its own per-row matcher path so grammar-constrained
33
+ requests don't force a request onto the serial lane, and grammar
34
+ composes with `--draft-model` (the verify walk respects the mask).
35
+ - Two defects found and fixed during the build: the oMLX-parity
36
+ JSON-system-prompt degrade path (used when a client can't do function
37
+ calling) had gone unreachable behind a dropped hint, and the WASM
38
+ grammar controllers were leaking on every early-400 reject path
39
+ (SSRF-blocked media, vision/audio validation failures, bad
40
+ `logit_bias`, etc.) — both fixed, with disposal now covering all paths.
41
+
42
+ ## Speculative decoding
43
+
44
+ - `--draft-model` lands in serve: a two-model, serial-lane speculative
45
+ decoding path verified token-for-token against mlx-lm's own
46
+ `--draft-model` oracle (`DraftSource` seam, rewind rule, batched-verify
47
+ lm-head).
48
+ - An ngram / jump-forward draft kind ships alongside the model-based
49
+ drafter for cases with no small model available.
50
+ - A DeepSpec (DSpark) drafter-quant research track is underway
51
+ (Phase 1 landed) targeting the larger models; per
52
+ `benchmarks/RESULTS.md`, the first live pair (12B target +
53
+ bf16 DeepSpec drafter, 26–33% acceptance) measured net **slower**
54
+ than serial on a loaded box — spec decoding stays **off by default**
55
+ pending a quantized-drafter pair that clears the 1.3× bar.
56
+
57
+ ## TurboQuant KV-cache quantization
58
+
59
+ - `--kv-quant turbo[:kXvY]` adds a rotation-based per-group KV
60
+ quantization scheme (sign-FWHT + Lloyd-Max for values), proven
61
+ bit-exact against the vendored vllm-metal reference
62
+ (`goldens/turboquant.json`).
63
+ - Per `benchmarks/RESULTS.md`, the k8v3 default holds a lower KL-vs-bf16
64
+ than affine uniform kv4 while compressing KV **2.56×** (measured on
65
+ MiniCPM5-1B, paired quality/KL harness). It's a memory/context lever,
66
+ not a speed lever — v1 dequant-on-fetch is slower per decode step at
67
+ long context, so it stays **opt-in, not default**, per the project's
68
+ "levers must earn defaults" rule.
69
+
70
+ ## Batching: Phase D completed
71
+
72
+ - Aggregate `--kv-budget <GB>` admission with FIFO queuing, vectorized
73
+ homogeneous sampling (penalties/`logit_bias`/`min_p`/XTC all run
74
+ per-row in the batch), and extend-join so a request can join an
75
+ in-flight batch mid-flight instead of waiting for a full drain.
76
+ - Per-row RoPE lands for Tier-0 universal architectures, lifting the
77
+ batching gate for those models (e.g. Llama).
78
+ - Batched mixed-precision quantized KV — the first stack to compose
79
+ per-row KV quantization with batching.
80
+ - `--batch` default changes from 1 to 8 (see Breaking changes below).
81
+
82
+ ## Runtime isolation
83
+
84
+ - `--isolate` runs the engine as a crash-isolated child process behind a
85
+ reactor parent, restarting with backoff on a crash — the product rule
86
+ is **"the AI may crash, the UI never may"** (`docs/design/runtime-isolation.md`).
87
+ - `--model-pool` extends this to a child-per-model pool: LRU residency,
88
+ spawn-overlap switching (no dead time swapping models), and
89
+ `POST /admin/drain` for graceful eviction.
90
+
91
+ ## Optional paged KV cache
92
+
93
+ - `--paged-kv` adds a vLLM-style block-table paged KV cache
94
+ (`PagedKVCache` + `BlockPool`) feeding the unchanged stock SDPA via
95
+ block gather. Default off; v1 scope is serial `--batch 1`, the
96
+ Gemma4 family, bf16 — it refuses to silently combine with
97
+ `--batch N>1`, `--kv-quant`, or `--draft-model`.
98
+
99
+ ## Prompt cache overhaul
100
+
101
+ - Prefix-sharing v1: `take()` now returns non-consuming, ref-counted
102
+ clones instead of consuming/trimming the donor entry, so multiple
103
+ agents or sessions can reuse one prefill without cannibalizing each
104
+ other's cache.
105
+ - The SSD cold tier is promoted from an add-on to a first-class property
106
+ of the cache store, with `--ssd-demote-idle <seconds>` (default 300,
107
+ requires `--ssd-cache`) freeing GPU memory by demoting idle entries;
108
+ `/stats` gains `ssd_cache.demotions`.
109
+ - A stable-boundary snapshot fix restores prompt-cache hits for
110
+ multi-turn agent traffic beyond the sliding window — this was
111
+ previously a silent cache miss on turn 2+ of long conversations.
112
+ - The SSD write-behind flush is now idle-gated, so background disk
113
+ writes stop contending with decode at long context; the earlier A7
114
+ RSS regression on the ssd-cache path closed with zero-copy write views
115
+ and a streamed copy-restore.
116
+
117
+ ## Web chat UI: ground-up redesign (Phases 0–3)
118
+
119
+ - Streaming render rewritten to be block-memoized (no more O(n²)
120
+ re-parse of the growing message), with a typed module split.
121
+ - New surfaces: a memory panel, adapter routing, a system-prompt editor,
122
+ an approval gate, client-side RAG over chat history (BM25, no server
123
+ round-trip), a Model Hub, Canvas, per-message sampling controls,
124
+ self-healing tool calls, a command palette, full-text search, and
125
+ chat export.
126
+ - An app-aware assistant (v1) that can see and navigate its own UI —
127
+ spotlight/selector resolution now treats a model-invented or malformed
128
+ selector as a miss instead of throwing inside the websocket handler.
129
+ - PWA support, plus a round of visual-QA fixes: the phone nav band,
130
+ light-theme code legibility, a composer placeholder regression, memory
131
+ panel markdown chrome, the theme-toggle Auto button, a clipped status
132
+ pill, and tab flex-shrink pinned to zero on phones.
133
+
134
+ ## Security: media-fetch SSRF hardening
135
+
136
+ - `image_url`/`audio_url` fetches now refuse private/loopback/link-local/
137
+ CGNAT destinations and non-`http(s)` schemes by default, re-validate
138
+ through up to 5 redirect hops, enforce a 10s wall-clock timeout, and
139
+ cap bodies at 64MB.
140
+ - LAN use needs the new escape hatch: `--allow-private-media` /
141
+ `MLX_BUN_ALLOW_PRIVATE_MEDIA=1`.
142
+
143
+ ## Fixed
144
+
145
+ - 12B `/v1/completions` probe parity: adopted the oracle's step-0
146
+ prefill convention (drain to len−1, step 0 from an `L=1` forward of the
147
+ last prompt token). Per `benchmarks/RESULTS.md`, live HTTP probes are
148
+ now byte-identical to `mlx_lm.server`/optiq serve for MiniCPM5-1B,
149
+ gemma-4-e4b, and gemma-4-12B, on completion and chat probes, in both
150
+ the `--batch 8` default lane and `--batch 1`.
151
+ - BPE detokenization now mirrors mlx-lm's bare-space hold-back and
152
+ never-finalize semantics exactly.
153
+ - Cache invariant enforced on every tier; an FFI destructor deadlock
154
+ fixed; write-behind made non-blocking; per-row batch cache extraction
155
+ fixed.
156
+ - `generate()` now yields a macrotask between prefill chunks, keeping the
157
+ isolation path (and the server generally) responsive during long
158
+ prefills.
159
+ - Benchmark harness: the `--batch 1` serial control arm now runs by
160
+ default (it had been skippable, which undermined validating the new
161
+ batch-8 default); `--engine` is additive instead of mutually exclusive
162
+ with the serve pass; the batch-path test now asserts cumulative
163
+ `/stats` `submitted_rows` instead of a stale `cachedTokens=0` premise.
164
+ - `any_whitespace` grammar knob landed; batch-grammar gates re-anchored
165
+ to compact separators.
166
+
167
+ ## Infra / benchmark harness redesign
168
+
169
+ - `benchmark.sh` + `scripts/bench-modes.ts` now spawn real CLI paths
170
+ instead of bench-local server wrappers, folding bit-parity and
171
+ peak-memory checks into the same serve cells (one pass instead of
172
+ several). New columns: cold-start and restart-survival; new workload:
173
+ `xl` (~4k prefix); a feature-matrix benchmark mode.
174
+ - Repo cleanup: `lab/` consolidation, a binary-tracking hygiene gate, and
175
+ a git history rewrite that took the repo from 182MB to 20MB, removing
176
+ the last multi-MB binaries from the index.
177
+ - New design docs: `unified-engine-frontier-plan`, `dspark-serving-program`
178
+ (the DeepSpec/DSpark spec-decode research program), `structured-output`,
179
+ `web-chat-redesign` (+ app-aware-assistant, superset-doctrine, and
180
+ visual-QA-bar notes), `paged-kv-cache`, `batching-perf-path` /
181
+ `batching-v2-plan`, `runtime-isolation`.
182
+ - Doc drift swept: env-lever table entries (`MLX_BUN_DSPARK_MINCONF`,
183
+ `MLX_BUN_BATCH_NO_PIPELINE`, `MLX_BUN_EXPERT_OFFLOAD`), ngram
184
+ draft-kind coverage in README/server-api, doc-map sync, an openwiki
185
+ investigation write-up. STATUS.md was rewritten to current-state-only
186
+ several times through the release to keep handoff notes accurate.
187
+ - A new ground rule was recorded in CLAUDE.md: changes to the served
188
+ surface must update the user-facing reference docs in the same commit.
189
+ - A direct optiq mixed-KV bit-parity golden replaced an indirect
190
+ ours-vs-ours comparison; a bit-exact L1 parity harness was added for
191
+ the Qwen3-30B-A3B MoE port, with uniform quantized KV confirmed
192
+ bit-exact against mlx-lm's own `--kv-bits` and a stock-mlx-lm baseline
193
+ added to the bench.
194
+ - Dependency/CI bumps: pi, `actions/checkout`, and the site build moved
195
+ off a deprecated Node runtime.
196
+
197
+ ## Breaking / behavior changes
198
+
199
+ - **`--batch` default changes from 1 to 8.** Serving now batches by
200
+ default whenever concurrent requests arrive; pass `--batch 1` to force
201
+ strict serial (needed if you require arrival-order-independent,
202
+ bit-identical numerics).
203
+ - **The default decode path changed.** Naked, no-flag serving now runs
204
+ the faithful, bit-exact-vs-mlx-lm kernel set — what `--l1` used to
205
+ mean. `--l1`/`--l2`/`--l3` are now pure aliases over per-feature flags
206
+ rather than distinct performance tiers. Every custom-kernel path that
207
+ didn't beat this baseline in a paired A/B was deleted in the same
208
+ pass: the fused-decode kernel, fused-gelu/fused-swiglu/fused-mlp/
209
+ steel-linear Metal kernels, the flash-decode "perf" kernel and its
210
+ frozen-oracle test scaffolding, `--l3`, and `FaithfulMiniCPM5` /
211
+ `MLX_BUN_CPM5_FAITHFUL`. None of these flags or code paths exist
212
+ anymore. `MLX_BUN_FAITHFUL` is also gone (superseded by the faithful
213
+ kernels being the default) — the server's unset `--kv-quant` now
214
+ defaults to bf16 instead of `kv_config`, so getting the old default
215
+ composition requires an explicit `--kv-quant`.
216
+ - **New CLI/API surface:** `--kv-quant turbo[:kXvY]` (TurboQuant),
217
+ `--paged-kv` (off by default; refuses to combine with `--batch N>1`,
218
+ `--kv-quant`, or `--draft-model`), `--draft-model` (speculative
219
+ decoding), `--isolate` and `--model-pool` (runtime isolation),
220
+ `--kv-budget <GB>` (aggregate KV admission), `--ssd-demote-idle
221
+ <seconds>` (default 300, requires `--ssd-cache`),
222
+ `--allow-private-media` / `MLX_BUN_ALLOW_PRIVATE_MEDIA=1`, and the
223
+ `response_format` / `guided_grammar` / `guided_regex` / `guided_choice`
224
+ / `structured_outputs` request fields (kill switch:
225
+ `MLX_BUN_GRAMMAR=0`).
226
+ - **Media fetches are restricted by default.** `image_url`/`audio_url`
227
+ now refuse private/loopback/link-local/CGNAT destinations and
228
+ non-`http(s)` schemes — previously they fetched anything. LAN media
229
+ needs the new escape hatch above.
230
+ - **`PromptCache.take()` semantics changed.** Cache hits now return
231
+ non-consuming, ref-counted clones instead of consuming/trimming the
232
+ donor entry — code holding onto the old consuming behavior should
233
+ re-check callers.
234
+
235
+ Full details and measured numbers: STATUS.md, `benchmarks/RESULTS.md`,
236
+ and the design docs referenced above. Credit where due: TurboQuant's
237
+ codec is verified bit-exact against the vendored vllm-metal reference,
238
+ and the speculative-decoding path is verified token-for-token against
239
+ mlx-lm's own `--draft-model` implementation.
@@ -0,0 +1,80 @@
1
+ # v0.0.12 release notes
2
+
3
+ mlx-bun 0.0.12 completes the native Colibri/GLM-5.2 program: a Python-free,
4
+ direct-container runtime that can serve the approximately 357 GiB artifact on
5
+ a 32 GiB Apple Silicon Mac by keeping a bounded working set in memory and
6
+ streaming routed experts from fast storage.
7
+
8
+ ## GLM-5.2 direct-container serving
9
+
10
+ - Loads `mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp` directly. No converted
11
+ copy and no Python process are involved in the serving path.
12
+ - Preserves checkpoint precision and true top-8 routing. The port is gated
13
+ against pinned Colibri at tiny, production-component, real-model, MTP, cache,
14
+ and first-sparse DSA boundaries.
15
+ - Native int8 MTP is enabled by default and uses the serial speculative lane.
16
+ It produced a measured 1.306x warm end-to-end win over MTP-off on the 32 GiB
17
+ reference machine while preserving all target tokens.
18
+ - Compressed MLA/DSA/MTP cache persistence, restart restore, compressed-byte
19
+ admission, ordinary continuous batching, mixed-length join/leave/cancel, and
20
+ cross-row expert union are included. Per-row batched MTP remains a later
21
+ feature; MTP requests truthfully report `serial+spec`.
22
+ - Chat completions, text completions, Anthropic Messages, OpenAI Responses,
23
+ SSE, tools, structured output, stops, sampling, usage, and serial logprobs
24
+ are supported. Embeddings, vision/audio, LoRA, and training are explicitly
25
+ reported unsupported for this model instead of being emulated.
26
+
27
+ ## Memory and acquisition contract
28
+
29
+ - `mlx-bun get` now computes the exact remaining payload before the first
30
+ payload request, credits verified shared blobs and resumable prefixes, and
31
+ refuses an acquisition that cannot leave a fixed 1 GiB safety reserve.
32
+ - The GLM header-only preflight runs before resident weights or expert slabs
33
+ open. With the stock DSA overlay installed, 4,096 context / 128 generation
34
+ tokens and MTP on produce a 19.89 GiB plan under a 25 GiB process ceiling,
35
+ leaving 5.11 GiB of process/macOS headroom on a 32 GiB machine.
36
+ - `fit`, `/fit`, `/stats`, and the status page now distinguish the complete
37
+ artifact on disk from resident weights, main/MTP slabs, compressed KV, and
38
+ reserves. They also expose main/MTP residency, hit rate, SSD bytes, policy
39
+ telemetry, and repin events.
40
+
41
+ ## Performance: measured, not predicted
42
+
43
+ - Warm quality-preserving throughput on the M1 Max 32 GiB reference machine is
44
+ 0.1577 decode tok/s / 0.1487 end-to-end tok/s with MTP on. The same-machine
45
+ direct-Colibri control is approximately 0.27 tok/s.
46
+ - The 2 tok/s figure remains an aspiration, not a release gate or `fit`
47
+ prediction. The measured warm end-to-end result is 13.45x below it.
48
+ - Replicated telemetry measured 1,974,949,363,712 logical expert bytes per
49
+ 128-token warm turn (15.429 decimal GB/token) and a 1.66% cache hit rate.
50
+ Startup auto-pin, live LFRU, PILOT hints, two-step prediction, and coupling
51
+ did not improve paired end-to-end performance and remain off by default.
52
+ - The checkpoint's 21-full/57-shared DSA schedule is implemented and exact.
53
+ Paired 2K/8K tests did not establish an MTP-on product-speed win, so this
54
+ release makes no DSA speed claim. The public Colibri artifact does not ship
55
+ the stock DSA indexer overlay; without it the runtime follows the artifact's
56
+ available attention path.
57
+
58
+ ## Distribution and operator experience
59
+
60
+ - First-run native pack v0.2.0 adds the bounded native expert-I/O helper. The
61
+ npm/bunx fresh-cache path downloads, verifies, and extracts all five runtime
62
+ files; the signed/Homebrew bundle includes the same helper beside the binary.
63
+ - The pinned 32 GiB quickstart, volume selection, interrupted-download recovery,
64
+ model lineage, licenses, resource plan, measured performance, and limitations
65
+ are documented in README and the reference guides.
66
+ - The interactive Atlas report reproduces Colibri's expert topic-affinity
67
+ result: 29/30 leave-one-prompt-out classifications (96.7%) and 1,065 strong
68
+ specialists among 13,236 replicated experts.
69
+
70
+ ## Stability fixes since v0.0.11
71
+
72
+ - Closed pre-Colibri correctness and lifecycle findings, including expert-slab
73
+ post-close and lazy-graph reuse hazards, with forced native/MLX churn gates.
74
+ - Fixed selected-logprob readback stalling and revalidated the audio splice
75
+ boundary against the oracle.
76
+ - Corrected current Hugging Face LFS checksum-field handling and retained the
77
+ older spelling for compatibility.
78
+
79
+ Full provenance and exact numbers are in `benchmarks/RESULTS.md`, `STATUS.md`,
80
+ and `docs/design/colibri-glm52-port.md`.
@@ -11,20 +11,22 @@ candidates — just make it more specific.
11
11
  Bare `mlx-bun` with no verb runs `serve` — the appliance path: first run
12
12
  downloads a starter model, serves it, and opens the chat UI.
13
13
 
14
- > Verbs marked **(v0.0.9)** ship in v0.0.9; everything else is in v0.0.8.
14
+ > All verbs below ship in current releases; the release notes in
15
+ > `docs/planning/` record when each verb first appeared.
15
16
 
16
17
  ## Serving & chat
17
18
 
18
19
  ### `serve` — run the server
19
20
 
20
- Start the OpenAI/Anthropic-compatible server plus the status page and browser
21
- chat UI.
21
+ Start the OpenAI/Anthropic-compatible server plus the browser web app (chat,
22
+ status, and model tools).
22
23
 
23
24
  ```sh
24
25
  mlx-bun serve # default model, http://localhost:8080
25
26
  mlx-bun serve e4b # pick a model by substring
26
27
  mlx-bun serve gemma --memory-budget 18 # ...with admission control (GB)
27
28
  mlx-bun serve e4b --no-open # don't open the browser chat UI
29
+ mlx-bun serve GLM-5.2 --context-length 4096 # bounded Colibri runtime, native MTP
28
30
  ```
29
31
 
30
32
  Common flags (full list in [server-config.md](server-config.md)):
@@ -34,16 +36,34 @@ Common flags (full list in [server-config.md](server-config.md)):
34
36
  | `--host <addr>` | Interface to bind (default `127.0.0.1`, loopback only; `0.0.0.0` to expose) |
35
37
  | `--port <n>` | Listen port (default 8080) |
36
38
  | `--memory-budget <GB>` | Reject loads/requests that can't fit the budget |
37
- | `--kv-quant config\|off\|4\|8` | KV cache quantization: per-layer `kv_config.json`, bf16, or uniform bits (default `config`) |
39
+ | `--kv-budget <GB>` | Aggregate KV budget across concurrent batch rows: over-budget joiners queue until rows finish; a request over the budget alone is rejected (off unless set) |
40
+ | `--prompt-cache <GB>` | RAM prefix-KV cache, byte-capped LRU (default 8; `0` disables). Non-consuming prefix sharing: a hit clones instead of consuming the donor entry |
41
+ | `--isolate` | Run the inference engine as a crash-isolated child process on a unix socket; this process becomes a pure reverse-proxy (instant under GPU load, auto-respawns on engine crash) — default off ([runtime-isolation.md](../design/runtime-isolation.md)) |
42
+ | `--model-pool <n>` | With `--isolate`: cap on resident per-model engine children (default 1); over the cap the LRU engine drains its cache to the SSD tier and exits, respawning on demand |
43
+ | `--ssd-cache <dir>` | SSD cold tier under the prompt cache: idle/evicted prefix-KV spills to disk and restores on reattach, surviving restarts (default off — [ssd-kv-cold-tier.md](../design/ssd-kv-cold-tier.md)) |
44
+ | `--ssd-cache-max <GB>` | SSD tier byte cap, oldest-mtime evicted first (default 32; `--ssd-cache` only) |
45
+ | `--ssd-cache-verify` | Verify every tensor hash on restore, not just the header (integrity paranoia; roughly doubles restore reads; `--ssd-cache` only) |
46
+ | `--ssd-demote-idle <sec>` | Idle prompt-cache entries spill to the SSD tier and free GPU memory after this long (default 300 with `--ssd-cache`; `0` disables) |
47
+ | `--kv-quant config\|off\|4\|8\|turbo[:k<bits>v<bits>]` | KV cache quantization: per-layer `kv_config.json`, bf16, uniform bits, or TurboQuant (rotation-based, default `k8v3` — [turboquant-kv.md](../design/turboquant-kv.md); full-attention layers only, solo-only/serial) (default `off` — quantized KV trades 5–20% decode speed for memory headroom, so it's opt-in) |
48
+ | `--paged-kv` | OPTIONAL vLLM-style paged KV cache (block pool + gather before the stock SDPA; env `MLX_BUN_PAGED_KV=1`) — bit-exact with the plain path, default off. v1: serial only (pins `--batch 1` unless `--batch` is given; refuses `--batch N>1`, `--kv-quant`, `--draft-model`), Gemma4-family, bf16; bypasses the prompt cache and runs uncompiled decode. Expect a small decode cost at batch=1 — v1 ships the abstraction for batched/CoW follow-ups ([paged-kv-cache.md](../design/paged-kv-cache.md)) |
49
+ | `--paged-kv-block-size <n>` | Tokens per KV block (default 256 = the plain cache's growth step; `--paged-kv` only) |
38
50
  | `--adapter <dir>` | Mount a LoRA adapter at startup (`--adapter-path` accepted as the mlx_lm.server alias) |
39
- | `--batch <n>` | Continuous-batched bf16 serving (default 1 = serial) |
40
- | `--temperature` / `--top-p` / `--top-k` / `--max-tokens` | Server-wide sampling defaults (per-request fields still win) |
41
- | `--l1` / `--l2` / `--l3` | Parity tier: bit-exact to mlx-lm / bit-exact to mlx-optiq / best performance |
51
+ | `--draft-model <path\|query>` | Speculative decoding: a drafter proposes, the main model verifies — exact results, faster decode when drafts land. The artifact's kind is auto-detected: a full same-tokenizer model (mlx_lm.server parity), a Gemma `-assistant` KV-borrowing drafter, a DSpark checkpoint trained here, or one of DeepSeek's released DSpark drafters (DeepSpec `Gemma4DSparkModel`, e.g. `dspark_gemma4_12b_block7`). Serial lane only: with `--batch N` a mounted draft routes every request serial |
52
+ | `--draft-kind <kind>` | Override draft-artifact detection: `two-model` \| `assistant` \| `dspark` \| `deepspec` \| `ngram` (default: auto). `ngram` is MODEL-FREE prompt lookup — no `--draft-model` (mounting one alongside it is refused): drafts are copied from the request's own prompt+generation whenever its trailing tokens have occurred earlier in that stream, verified by the target like any other draft, so results stay exact at any temperature. Zero weights, zero memory; best on agentic/RAG/code-edit traffic that re-emits spans already in context (prior art: prompt-lookup decoding / vLLM's `ngram` proposer) |
53
+ | `--num-draft-tokens <n>` | Drafts per verify round (default 3; `ngram` defaults to 10 — drafting is free; a DSpark draft pins to its trained block width) |
54
+ | `--ngram-max <k>` / `--ngram-min <k>` | Prompt-lookup match-window bounds, `--draft-kind ngram` only: the longest/shortest trailing k-gram searched (defaults 3 / 1, the reference values) |
55
+ | `--mtp on\|off` | GLM-5.2 checkpoint-native MTP (default on). Native MTP uses the exact serial verify lane; `off` enables ordinary continuous batching (batched per-row MTP is post-release) |
56
+ | `--context-length <n>` | GLM-5.2 context reserved by the header-only resource equation (default 4096) |
57
+ | `--batch <n>` | Continuous-batched serving cap, mlx-lm B=N parity (default 8; `--batch 1` pins the serial path) |
58
+ | `--temperature` / `--top-p` / `--top-k` / `--max-tokens` | Server-wide sampling defaults (per-request fields still win; GLM-5.2 defaults to the planned 128 generated tokens) |
59
+ | `--l1` / `--l2` | Parity tier alias: bit-exact to mlx-lm / bit-exact to mlx-optiq. **No tier = `--l1`** (the default since 2026-07-05 — output-changing levers are opt-in until they beat the L1 baseline in a paired A/B). Each expands to per-fork flags (`--compiled-decode`, `--compiled-activations`, `--fused-sdpa`, `--kv-quant`); a fork flag overrides one. `--l3` was removed 2026-07-05 and now errors (the Lab replaces it — [unified-engine-frontier-plan.md](../design/unified-engine-frontier-plan.md)). See [server-config.md](server-config.md#fidelity-tiers-and-the-decode-route---l1----l2). |
60
+ | `--allow-private-media` | Let `image_url`/`audio_url` parts fetch from private/loopback/link-local hosts (blocked by default — SSRF guard; the 10 s timeout and 64 MB cap on remote media apply either way) |
42
61
  | `--no-open` | Don't auto-open the chat UI |
43
62
 
44
63
  Endpoints: `/v1/chat/completions`, `/v1/completions`, `/v1/messages`,
45
64
  `/v1/responses`, `/v1/models`, `/v1/adapters`, `/health`, `/stats`, `/fit`,
46
- `/library`, `/downloads` — status page at `/`, browser chat at `/chat`. Full
65
+ `/library`, `/downloads` — web app at `/` (lands on chat); `/chat`, `/status`,
66
+ `/quantize`, `/finetune`, `/dataset` deep-link its views. Full
47
67
  schemas in [server-api.md](server-api.md).
48
68
 
49
69
  ### `pi` — built-in coding agent
@@ -73,15 +93,16 @@ mlx-bun harness pi --remove # disconnect
73
93
 
74
94
  Load the model, generate, print, exit — no server. Renders through the chat
75
95
  template by default; `--raw` feeds the prompt verbatim. Sampling and
76
- decode-path levers mirror `serve` (`--temperature`, `--seed`, `--l1/--l2/--l3`,
96
+ decode-path levers mirror `serve` (`--temperature`, `--seed`, `--l1/--l2`,
77
97
  `--kv-quant`, …).
78
98
 
79
99
  ```sh
80
100
  mlx-bun generate gemma "a haiku about metal shaders"
81
101
  mlx-bun gen e4b --prompt "…" --max-tokens 512 --seed 42
102
+ mlx-bun generate GLM-5.2 --prompt "Explain DSA" --max-tokens 128
82
103
  ```
83
104
 
84
- ### `embed` — text embeddings **(v0.0.9)**
105
+ ### `embed` — text embeddings
85
106
 
86
107
  One-shot embeddings from a local Qwen3-Embedding model (last-token pooled,
87
108
  L2-normalized — bit-exact vs mlx-lm). One JSON vector per input line.
@@ -101,13 +122,21 @@ Full guide: [models.md](models.md).
101
122
  ### `get` — download a model
102
123
 
103
124
  Resumable, checksum-verified download into the standard Hugging Face cache
104
- (plain HTTPS, no Xet — no 0% stalls).
125
+ (plain HTTPS, no Xet — no 0% stalls). Before payload transfer, the downloader
126
+ credits complete blobs and partial prefixes, then requires enough free space
127
+ for the exact remainder plus a fixed 1 GiB reserve.
105
128
 
106
129
  ```sh
107
130
  mlx-bun get mlx-community/gemma-4-12B-it-OptiQ-4bit
108
131
  mlx-bun get 12B # no "/" = registry query; re-gets/refreshes the match
132
+ mlx-bun get mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp \
133
+ --revision 3cc8db99b1b13fc79325d987ba3c1c430766b3b8
109
134
  ```
110
135
 
136
+ The GLM artifact is roughly 357 GiB; select `HF_HUB_CACHE` on a sufficiently
137
+ large fast volume before starting. Rerunning the same command resumes verified
138
+ `.incomplete` prefixes. See the [32 GB GLM quickstart](models.md#glm-52-on-a-32-gb-mac).
139
+
111
140
  ### `scan` — index your cache
112
141
 
113
142
  Re-index the HF cache into the registry (config + safetensors headers only,
@@ -125,10 +154,12 @@ mlx-bun ls --vision --max-size 10GB # filter
125
154
  mlx-bun ls --all-revisions # one row per cached snapshot
126
155
  ```
127
156
 
128
- ### `gc` — reclaim disk **(v0.0.9)**
157
+ ### `gc` — reclaim disk
129
158
 
130
159
  Delete superseded snapshots and the blobs only they reference. Prints the plan
131
- by default; `--yes` actually deletes.
160
+ by default; `--yes` actually deletes. Same planner (`src/registry.ts`
161
+ `planGc`/`executeGc`) also backs `GET /api/gc/plan` / `POST /api/gc/execute`
162
+ on a running `serve` — see [server-api.md](server-api.md#get-apigcplan--post-apigcexecute).
132
163
 
133
164
  ```sh
134
165
  mlx-bun gc # dry-run: what would be reclaimed
@@ -146,6 +177,20 @@ mlx-bun fit gemma --ctx 32768 # for this machine
146
177
  mlx-bun fit gemma --ctx 8192 --skus # across the Apple Silicon lineup
147
178
  ```
148
179
 
180
+ The direct Colibri GLM-5.2 artifact is handled by its streamed-runtime
181
+ contract, not by the generic resident-weights estimator. `fit GLM-5.2`
182
+ defaults to the supported 4,096-token / 128-generation-token plan and reports
183
+ the artifact's disk footprint separately from resident weights, the main and
184
+ MTP expert slabs, KV, reserves, and the 25 GiB process ceiling. Its throughput
185
+ line is the measured warm quality-preserving result; the direct Colibri oracle
186
+ and the 2 tok/s aspiration are labeled separately. `--skus` explains that the
187
+ generic resident-model matrix does not apply to this streamed artifact.
188
+
189
+ ```sh
190
+ mlx-bun fit GLM-5.2
191
+ mlx-bun fit GLM-5.2 --ctx 4096
192
+ ```
193
+
149
194
  ## Training & model creation
150
195
 
151
196
  Full reference: [training.md](training.md); guided walkthrough:
@@ -170,7 +215,7 @@ Tails an adapter dir's `metrics.jsonl` and renders live loss / speed / memory.
170
215
  mlx-bun train-watch ~/.cache/mlx-bun/mlx-bun-finetunes/orpo-e4b
171
216
  ```
172
217
 
173
- ### `fuse` — merge an adapter into the base **(v0.0.9)**
218
+ ### `fuse` — merge an adapter into the base
174
219
 
175
220
  Folds LoRA deltas into the base weights and writes a standalone snapshot; a
176
221
  quantized base keeps its exact quantization layout. Flag names match
@@ -181,7 +226,7 @@ mlx-bun fuse e4b --adapter ./adapters --save-path ./fused_model
181
226
  mlx-bun serve ./fused_model
182
227
  ```
183
228
 
184
- ### `convert` — quantize a model **(v0.0.9)**
229
+ ### `convert` — quantize a model
185
230
 
186
231
  Quantize an HF model (local path, downloaded model, or repo id) into a local
187
232
  MLX snapshot — uniform 4/8-bit, or mixed-precision via `--target-bpw`
@@ -192,7 +237,7 @@ mlx-bun convert Qwen/Qwen3-4B -q # uniform 4-bit
192
237
  mlx-bun convert Qwen/Qwen3-4B --target-bpw 4.5 # mixed precision
193
238
  ```
194
239
 
195
- ### `upload` — push to the Hugging Face Hub **(v0.0.9)**
240
+ ### `upload` — push to the Hugging Face Hub
196
241
 
197
242
  Native push-to-hub, no Python: creates the repo if needed, uploads via the
198
243
  git-LFS batch protocol, commits. Flag names match `mlx_lm.upload`.
@@ -201,7 +246,7 @@ git-LFS batch protocol, commits. Flag names match `mlx_lm.upload`.
201
246
  mlx-bun upload --path ./fused_model --upload-repo you/my-model
202
247
  ```
203
248
 
204
- ### `perplexity` — evaluate on your data **(v0.0.9)**
249
+ ### `perplexity` — evaluate on your data
205
250
 
206
251
  `mlx_lm.perplexity` methodology exactly, over a **local** `.jsonl`/`.txt` file.
207
252
 
@@ -226,7 +271,7 @@ mlx-bun memory synthesize # conversations → cross-linked articles, all
226
271
  mlx-bun memory schedule --at 03:00
227
272
  ```
228
273
 
229
- `setup` is an alias for `memory` **(v0.0.9)**.
274
+ `setup` is an alias for `memory`.
230
275
 
231
276
  ## Measurement
232
277
 
@@ -14,6 +14,7 @@ tarball (~73 MB compressed, ~228 MB installed):
14
14
  |---|---|
15
15
  | `mlx-bun` | the CLI/server (`bun build --compile`), ~61 MB |
16
16
  | `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib` | MLX native runtime |
17
+ | `libmlx_bun_expert_io.dylib` | bounded native expert-streaming helper required by direct Colibri GLM-5.2 |
17
18
  | `mlx.metallib` | Metal kernels (~150 MB — the bulk) |
18
19
  | pi assets | `photon_rs_bg.wasm`, `theme/`, `assets/`, `export-html/`, `native/`, `package.json`, `CHANGELOG.md` |
19
20
 
@@ -156,8 +157,8 @@ manual escape hatch if offline.
156
157
 
157
158
  ## npm / bunx
158
159
 
159
- mlx-bun is published to npm as `mlx-bun` (current: 0.0.4). Install or
160
- run without a permanent install:
160
+ mlx-bun is published to npm as `mlx-bun`. Install or run without a
161
+ permanent install:
161
162
 
162
163
  ```sh
163
164
  # one-off (no install)
@@ -168,10 +169,40 @@ bun install -g mlx-bun
168
169
  mlx-bun --version
169
170
  ```
170
171
 
171
- The npm package wraps the same signed binary via a postinstall download
172
- step (it does not bundle the ~228 MB dylibs/metallib in the npm tarball
173
- itself). Publish to npm as part of a release:
172
+ The npm package is a thin launcher (no postinstall hook): it imports
173
+ `src/cli.ts` under Bun, which fetches the small (~52 MB compressed,
174
+ sha256-verified) native runtime pack — `libmlxc`/`libmlx`/`libjaccl`/
175
+ `mlx.metallib` plus `libmlx_bun_expert_io.dylib` — into
176
+ `~/Library/Caches/mlx-bun/` on first invocation if
177
+ no copy is already resolvable (env / beside the binary / cache /
178
+ Homebrew). This is the same npm/sidecar mechanism described above, not
179
+ the signed/notarized Homebrew bundle. `bun publish` is already run
180
+ automatically and idempotently as step 4 of `PUBLISH=1
181
+ ./scripts/release-binary.sh`; run it standalone only as a manual
182
+ fallback/retry:
174
183
 
175
184
  ```sh
176
- bun publish # from repo root; package.json version must already be bumped
185
+ bun publish # manual retry; package.json version must already be bumped
177
186
  ```
187
+
188
+ ### Publishing the first-run native pack
189
+
190
+ The npm/bunx path has an independent, versioned release asset. Whenever its
191
+ file manifest changes, build and publish it before shipping code that names the
192
+ new `NATIVE_PACK_VERSION`:
193
+
194
+ ```sh
195
+ sh scripts/build-native-pack.sh 0.2.0 dist-native
196
+ gh release create native-v0.2.0 \
197
+ dist-native/mlx-bun-native-v0.2.0-arm64.tar.gz \
198
+ dist-native/mlx-bun-native-v0.2.0-arm64.tar.gz.sha256 \
199
+ --title "mlx-bun native runtime v0.2.0" \
200
+ --notes "Adds the bounded native expert-I/O helper required by direct Colibri GLM-5.2."
201
+ ```
202
+
203
+ For v0.2.0 the arm64 archive is 52,307,647 bytes with SHA-256
204
+ `9bd3795c5ea8f52b18413501f2d68c32c264a20751302300a08dc04cd67df97c`.
205
+ It contains `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib`,
206
+ `mlx.metallib`, and `libmlx_bun_expert_io.dylib`. These values must match
207
+ `src/native-pack.ts`; a fresh-cache extraction plus real MLX dlopen and native
208
+ expert read is the pre-publish smoke.