mlx-bun 0.2.0 → 0.4.0

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 (433) hide show
  1. package/README.md +71 -588
  2. package/docs/README.md +94 -0
  3. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  4. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  5. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  6. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  7. package/docs/archive/investigations/openjarvis-fit.md +198 -0
  8. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  9. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  10. package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
  11. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  12. package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
  13. package/docs/design/batching.md +1841 -0
  14. package/docs/design/decode-speed-program.md +2346 -169
  15. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  16. package/docs/design/generic-model-support.md +655 -334
  17. package/docs/design/kv-cache.md +824 -0
  18. package/docs/design/orpo-training.md +673 -1239
  19. package/docs/design/speculative-decoding.md +1990 -0
  20. package/docs/design/turboquant.md +2212 -0
  21. package/docs/design/unified-engine-frontier-plan.md +1833 -727
  22. package/docs/design/web-chat-redesign.md +666 -1083
  23. package/docs/planning/PRODUCT_ROADMAP.md +50 -1
  24. package/docs/planning/release-notes-v0.4.0.md +45 -0
  25. package/docs/planning/video-series.md +2 -2
  26. package/docs/reference/benchmarks.md +3613 -0
  27. package/docs/reference/cli.md +434 -160
  28. package/docs/reference/distribution.md +328 -182
  29. package/docs/reference/environment.md +398 -0
  30. package/docs/reference/glossary.md +39 -0
  31. package/docs/reference/library-api.md +566 -168
  32. package/docs/reference/memory.md +227 -64
  33. package/docs/reference/models.md +113 -6
  34. package/docs/reference/server-api.md +944 -429
  35. package/docs/reference/server-config.md +740 -338
  36. package/docs/reference/training.md +393 -254
  37. package/docs/reference/troubleshooting.md +158 -0
  38. package/package.json +9 -4
  39. package/src/audio/decode.ts +2 -2
  40. package/src/audio/features.ts +2 -2
  41. package/src/backends/mlx/assistant-target.ts +46 -0
  42. package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
  43. package/src/backends/mlx/autoregressive.ts +108 -0
  44. package/src/backends/mlx/batch-group.ts +1790 -0
  45. package/src/backends/mlx/cache-attachment.ts +67 -0
  46. package/src/backends/mlx/cache-layout.ts +31 -0
  47. package/src/backends/mlx/checkpoint-state.ts +53 -0
  48. package/src/backends/mlx/continuation-persistence.ts +106 -0
  49. package/src/backends/mlx/continuation-request.ts +43 -0
  50. package/src/backends/mlx/continuation.ts +77 -0
  51. package/src/backends/mlx/diffusion.ts +39 -0
  52. package/src/backends/mlx/draft-target.ts +32 -0
  53. package/src/backends/mlx/evaluation.ts +105 -0
  54. package/src/backends/mlx/fill-append.ts +45 -0
  55. package/src/backends/mlx/full-kv-row-append.ts +32 -0
  56. package/src/backends/mlx/full-kv-row-donor.ts +54 -0
  57. package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
  58. package/src/backends/mlx/gateway-binding.ts +130 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/kv-codec.ts +9 -0
  61. package/src/backends/mlx/kv-maintenance.ts +133 -0
  62. package/src/backends/mlx/kv-tensor-rows.ts +212 -0
  63. package/src/backends/mlx/memory-client.ts +189 -0
  64. package/src/backends/mlx/methods.ts +90 -0
  65. package/src/backends/mlx/model-prompt.ts +164 -0
  66. package/src/backends/mlx/model-serving.ts +79 -0
  67. package/src/backends/mlx/prefill-cohort.ts +89 -0
  68. package/src/backends/mlx/prefill-rows.ts +200 -0
  69. package/src/backends/mlx/prefill.ts +33 -0
  70. package/src/backends/mlx/projected-context-rows.ts +72 -0
  71. package/src/backends/mlx/request-policy.ts +20 -0
  72. package/src/backends/mlx/request-state-policy.ts +41 -0
  73. package/src/backends/mlx/rollback.ts +89 -0
  74. package/src/backends/mlx/row-sampling.ts +49 -0
  75. package/src/backends/mlx/serial-executor.ts +242 -0
  76. package/src/backends/mlx/speculative-group.ts +359 -0
  77. package/src/backends/mlx/speculative-round.ts +161 -0
  78. package/src/backends/mlx/speculative.ts +114 -0
  79. package/src/backends/mlx/state-rows.ts +104 -0
  80. package/src/backends/mlx/state-views.ts +46 -0
  81. package/src/backends/mlx/target-layout-capability.ts +35 -0
  82. package/src/backends/mlx/text-engine.ts +73 -0
  83. package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
  84. package/src/cli.ts +66 -58
  85. package/src/client.ts +66 -0
  86. package/src/config.ts +21 -4
  87. package/src/contracts/completion.ts +16 -0
  88. package/src/contracts/execution.ts +60 -0
  89. package/src/contracts/generation.ts +103 -0
  90. package/src/contracts/host.ts +7 -0
  91. package/src/contracts/jobs.ts +66 -0
  92. package/src/contracts/pi-provider.ts +30 -0
  93. package/src/contracts/pi.ts +259 -0
  94. package/src/contracts/prefix-cache.ts +23 -0
  95. package/src/contracts/resources.ts +25 -0
  96. package/src/contracts/sampling.ts +23 -0
  97. package/src/contracts/scheduling.ts +45 -0
  98. package/src/contracts/tsconfig.json +14 -0
  99. package/src/diffusion/diffusion-generate.ts +218 -153
  100. package/src/embed.ts +1 -1
  101. package/src/engine/admission.ts +59 -0
  102. package/src/engine/cancellation.ts +38 -0
  103. package/src/engine/engine.ts +56 -0
  104. package/src/engine/execution-coordinator.ts +70 -0
  105. package/src/engine/execution-plan.ts +53 -0
  106. package/src/engine/resources.ts +53 -0
  107. package/src/engine/scheduler.ts +72 -0
  108. package/src/engine/session.ts +247 -0
  109. package/src/eval/README.md +44 -1
  110. package/src/eval/kl.ts +236 -3
  111. package/src/eval/reference-logits.ts +207 -0
  112. package/src/eval/runner.ts +8 -96
  113. package/src/fill/echo-index.ts +188 -0
  114. package/src/fill/fill-session.ts +452 -0
  115. package/src/fill/proposal.ts +68 -0
  116. package/src/fill/schema-rows.ts +506 -0
  117. package/src/fill/tool-boundary.ts +103 -0
  118. package/src/fit.ts +30 -16
  119. package/src/generate.ts +709 -417
  120. package/src/grammar.ts +12 -7
  121. package/src/harness-pi.ts +14 -33
  122. package/src/hub-rest.ts +4 -4
  123. package/src/index.ts +7 -0
  124. package/src/inference/denoising.ts +17 -0
  125. package/src/inference/draft-acceptance.ts +41 -0
  126. package/src/inference/draft-output.ts +49 -0
  127. package/src/inference/graph.ts +33 -0
  128. package/src/inference/prefill.ts +39 -0
  129. package/src/inference/rollback.ts +7 -0
  130. package/src/jobs/db.ts +4 -0
  131. package/src/jobs/index.ts +2 -0
  132. package/src/jobs/job-entry.ts +12 -12
  133. package/src/jobs/runner.ts +98 -13
  134. package/src/jobs/task-client.ts +19 -0
  135. package/src/jobs/types.ts +2 -58
  136. package/src/kv-scheme.ts +70 -12
  137. package/src/kv-store.ts +177 -63
  138. package/src/lab/README.md +18 -0
  139. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  140. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  141. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +5 -5
  142. package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
  143. package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
  144. package/src/library.ts +40 -0
  145. package/src/lora.ts +18 -0
  146. package/src/media-fetch.ts +1 -1
  147. package/src/memory/article.ts +1 -1
  148. package/src/memory/chunk.ts +1 -1
  149. package/src/memory/model.ts +30 -169
  150. package/src/memory/prompts.ts +1 -1
  151. package/src/memory/rest.ts +1 -1
  152. package/src/memory/schedule.ts +1 -1
  153. package/src/memory/stages.ts +4 -1
  154. package/src/memory/vault.ts +1 -3
  155. package/src/mlx/array.ts +11 -11
  156. package/src/mlx/compile.ts +12 -2
  157. package/src/mlx/ffi.ts +58 -11
  158. package/src/mlx/materialize.ts +23 -0
  159. package/src/mlx/metal-kernel.ts +10 -11
  160. package/src/mlx/ops.ts +33 -13
  161. package/src/mlx/quantized-rows.ts +36 -0
  162. package/src/mlx/token-bitmask.ts +52 -0
  163. package/src/mlx/turboquant-kv-decode.ts +82 -0
  164. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  165. package/src/mlx/turboquant-ops.ts +33 -3
  166. package/src/mlx/turboquant-tables.ts +2 -2
  167. package/src/model/artifact-identity.ts +73 -0
  168. package/src/model/batched-kv.ts +235 -0
  169. package/src/model/batched-mask.ts +20 -6
  170. package/src/model/batched-quant.ts +9 -3
  171. package/src/model/batched-quantized-kv.ts +144 -0
  172. package/src/model/batched-rotating-quant.ts +78 -17
  173. package/src/model/batched-rotating-state.ts +76 -0
  174. package/src/model/batched-rotating.ts +65 -23
  175. package/src/model/batched-row-storage.ts +52 -0
  176. package/src/model/batched-ssm.ts +52 -0
  177. package/src/model/batched-turboquant-kv.ts +93 -0
  178. package/src/model/compiled-decode.ts +8 -2
  179. package/src/model/decoded-kv-donor.ts +12 -0
  180. package/src/model/delayed-quantized-kv.ts +72 -0
  181. package/src/model/delayed-rotating-quantized-kv.ts +93 -0
  182. package/src/model/delayed-turboquant-kv.ts +55 -0
  183. package/src/model/diffusion-gemma.ts +8 -8
  184. package/src/model/factory.ts +76 -33
  185. package/src/model/fingerprint.ts +1 -1
  186. package/src/model/flash-attention.ts +3 -3
  187. package/src/model/full-prefill-padding.ts +56 -0
  188. package/src/model/full-prefill-row.ts +105 -0
  189. package/src/model/gemma4-base.ts +179 -80
  190. package/src/model/gemma4.ts +40 -32
  191. package/src/model/generated/gemma4-12b.ts +6 -3
  192. package/src/model/generated/gemma4-26b.ts +6 -3
  193. package/src/model/generated/gemma4-e4b.ts +6 -3
  194. package/src/model/glm52-cache.ts +80 -4
  195. package/src/model/glm52-dsa.ts +13 -9
  196. package/src/model/glm52-memory.ts +1 -1
  197. package/src/model/glm52-mla.ts +12 -6
  198. package/src/model/glm52.ts +19 -40
  199. package/src/model/implementation.ts +69 -0
  200. package/src/model/kv-attention-view.ts +67 -0
  201. package/src/model/minicpm5.ts +17 -15
  202. package/src/model/profile.ts +12 -2
  203. package/src/model/qwen-append.ts +12 -0
  204. package/src/model/qwen-conv.ts +52 -0
  205. package/src/model/qwen3-delta-state.ts +74 -0
  206. package/src/model/qwen3-delta.ts +59 -36
  207. package/src/model/qwen3_5-checkpoint.ts +164 -0
  208. package/src/model/qwen3_5.ts +202 -78
  209. package/src/model/rotating-kv-donor.ts +35 -0
  210. package/src/model/rotating-kv-layout.ts +262 -0
  211. package/src/model/rotating-row-transaction.ts +35 -0
  212. package/src/model/speculative-rotating-kv.ts +101 -0
  213. package/src/model/ssm-prefill-padding.ts +39 -0
  214. package/src/model/support.ts +1 -1
  215. package/src/model/trellis-balanced-scatter.ts +51 -0
  216. package/src/model/trellis-linear.ts +672 -0
  217. package/src/model/trellis-shared-m.ts +151 -0
  218. package/src/model/trellis-shared-scatter.ts +144 -0
  219. package/src/model/trellis-splitk-prefill.ts +158 -0
  220. package/src/model/trellis-tiled-prefill.ts +136 -0
  221. package/src/model/trellis-vector-expand.ts +62 -0
  222. package/src/model/trellis-wide-prefill.ts +94 -0
  223. package/src/model/turboquant-codec.ts +83 -0
  224. package/src/model/universal/dense.ts +15 -14
  225. package/src/model/universal/modules.ts +8 -1
  226. package/src/native-pack.ts +6 -5
  227. package/src/pi-provider.ts +6 -64
  228. package/src/pi-web.ts +8 -315
  229. package/src/preflight.ts +31 -15
  230. package/src/prompt-cache.ts +110 -69
  231. package/src/quantize/allocator.ts +1 -1
  232. package/src/quantize/config-writer.ts +10 -3
  233. package/src/quantize/rotate.ts +4 -4
  234. package/src/quantize/trellis.ts +586 -0
  235. package/src/responses.ts +28 -1
  236. package/src/runtime-config.ts +18 -4
  237. package/src/sampler.ts +40 -29
  238. package/src/serve/batch-scheduler.ts +8 -1671
  239. package/src/serve/chat-request.ts +391 -0
  240. package/src/serve/chat-stage.ts +195 -0
  241. package/src/serve/checkpoint-identity.ts +64 -0
  242. package/src/serve/completion-executor.ts +15 -7
  243. package/src/serve/discovery-routes.ts +12 -13
  244. package/src/serve/generation-gateway.ts +183 -213
  245. package/src/serve/http.ts +159 -0
  246. package/src/serve/inference-request.ts +79 -0
  247. package/src/serve/isolate.ts +297 -105
  248. package/src/serve/lab-routes.ts +3 -0
  249. package/src/serve/lane-registry.ts +2 -1
  250. package/src/serve/model-admin-routes.ts +7 -5
  251. package/src/serve/model-binding.ts +43 -0
  252. package/src/serve/model-host.ts +511 -0
  253. package/src/serve/openai-wire.ts +103 -0
  254. package/src/serve/parent-application.ts +56 -0
  255. package/src/serve/pipeline.ts +33 -0
  256. package/src/serve/preparation.ts +33 -0
  257. package/src/serve/request-plan.ts +23 -18
  258. package/src/serve/request-prep.ts +344 -0
  259. package/src/serve/response-lease.ts +24 -0
  260. package/src/serve/responses-client.ts +69 -0
  261. package/src/serve/session-completion-engine.ts +110 -0
  262. package/src/serve/session-search.ts +1 -1
  263. package/src/serve/static-routes.ts +5 -5
  264. package/src/serve/text-completion-stage.ts +104 -0
  265. package/src/serve/token-streams.ts +519 -0
  266. package/src/server.ts +335 -2711
  267. package/src/spec/assistant-rows.ts +92 -0
  268. package/src/spec/assistant-source.ts +31 -55
  269. package/src/spec/cache-identity.ts +22 -0
  270. package/src/spec/deepspec-rows.ts +29 -0
  271. package/src/spec/deepspec-source.ts +16 -14
  272. package/src/spec/dflash-source.ts +36 -12
  273. package/src/spec/drafter.ts +153 -142
  274. package/src/spec/dspark/ab-stats.ts +3 -3
  275. package/src/spec/dspark/calibration.ts +2 -2
  276. package/src/spec/dspark/deepspec-module.ts +97 -122
  277. package/src/spec/dspark/generate-dflash.ts +2 -2
  278. package/src/spec/dspark/generate.ts +2 -2
  279. package/src/spec/dspark/loader.ts +1 -1
  280. package/src/spec/dspark/module-dflash.ts +129 -172
  281. package/src/spec/dspark/module.ts +3 -3
  282. package/src/spec/dspark/quantize-drafter.ts +1 -1
  283. package/src/spec/generate.ts +1 -1
  284. package/src/spec/glm52-mtp-graph.ts +29 -0
  285. package/src/spec/glm52-mtp-rows.ts +132 -0
  286. package/src/spec/glm52-mtp-source.ts +54 -137
  287. package/src/spec/glm52-mtp-state.ts +33 -0
  288. package/src/spec/ngram-source.ts +93 -21
  289. package/src/spec/projected-draft-rows.ts +73 -0
  290. package/src/spec/qwen-mtp-module.ts +171 -0
  291. package/src/spec/qwen-mtp-rows.ts +219 -0
  292. package/src/spec/qwen-mtp-source.ts +147 -195
  293. package/src/spec/qwen-mtp-state.ts +30 -0
  294. package/src/spec/serve-loop.ts +201 -201
  295. package/src/spec/source.ts +110 -13
  296. package/src/spec/two-model-rows.ts +61 -0
  297. package/src/spec/two-model.ts +44 -102
  298. package/src/ssd-cache.ts +99 -19
  299. package/src/ssd-durability.ts +36 -20
  300. package/src/tool-call.ts +51 -14
  301. package/src/train/flash-cce.ts +2 -2
  302. package/src/train/forward.ts +6 -0
  303. package/src/train/loss.ts +1 -1
  304. package/src/train/prefix-shared.ts +5 -1
  305. package/src/train/segmented.ts +5 -3
  306. package/src/train/trainer.ts +6 -6
  307. package/src/vision/prompt.ts +1 -1
  308. package/src/vision/qwen3vl-tower.ts +52 -10
  309. package/src/web/app.html +1 -1
  310. package/src/web/app.js +62 -60
  311. package/src/web/src/adapters-panel.ts +3 -3
  312. package/src/web/src/assistant.ts +2 -36
  313. package/src/web/src/chat.ts +4 -4
  314. package/src/web/src/composer.ts +4 -4
  315. package/src/web/src/hub.ts +1 -1
  316. package/src/web/src/markdown.ts +0 -0
  317. package/src/web/src/memory-panel.ts +1 -1
  318. package/src/web/src/model-picker.ts +1 -1
  319. package/src/web/src/palette.ts +1 -1
  320. package/src/web/src/protocol.ts +3 -39
  321. package/src/web/src/sessions.ts +1 -1
  322. package/src/web/src/ui-catalog.ts +4 -18
  323. package/src/web-assets.ts +47 -0
  324. package/src/weights.ts +55 -9
  325. package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
  326. package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
  327. package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
  328. package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
  329. package/docs/archive/investigations/hlg-ab.html +0 -34
  330. package/docs/archive/investigations/hlg-explorer.html +0 -238
  331. package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
  332. package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
  333. package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
  334. package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
  335. package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
  336. package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
  337. package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
  338. package/docs/archive/investigations/hlg-report.html +0 -262
  339. package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
  340. package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  341. package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
  342. package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
  343. package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
  344. package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
  345. package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
  346. package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
  347. package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
  348. package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
  349. package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  350. package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
  351. package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
  352. package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
  353. package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  354. package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  355. package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  356. package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  357. package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  358. package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  359. package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  360. package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
  361. package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
  362. package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
  363. package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
  364. package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
  365. package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  366. package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
  367. package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
  368. package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
  369. package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
  370. package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
  371. package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  372. package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
  373. package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  374. package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  375. package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  376. package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  377. package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  378. package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  379. package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
  380. package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  381. package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
  382. package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  383. package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  384. package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  385. package/docs/archive/mlx-bun-lab-report.html +0 -275
  386. package/docs/archive/wwdc-mlx-bun.html +0 -848
  387. package/docs/design/adapters-end-to-end.md +0 -205
  388. package/docs/design/batching-perf-path.md +0 -255
  389. package/docs/design/batching-v2-plan.md +0 -529
  390. package/docs/design/bucketing-stage.md +0 -197
  391. package/docs/design/compat-cli-surface-design.md +0 -230
  392. package/docs/design/docs-reorg-plan.md +0 -165
  393. package/docs/design/dspark-serving-program.md +0 -371
  394. package/docs/design/dspark-speculative-decoding.md +0 -318
  395. package/docs/design/grammar-spec-batching-integration.md +0 -301
  396. package/docs/design/memory-inference-path.md +0 -422
  397. package/docs/design/memory-synthesis.md +0 -287
  398. package/docs/design/memory-system.md +0 -237
  399. package/docs/design/mlx-lm-serving-execution-seam.md +0 -81
  400. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  401. package/docs/design/omlx-adoption-map.md +0 -98
  402. package/docs/design/orpo-dynamic-lambda.md +0 -220
  403. package/docs/design/orpo-future-enhancements.md +0 -340
  404. package/docs/design/paged-kv-cache.md +0 -214
  405. package/docs/design/parallel-slots.md +0 -567
  406. package/docs/design/parity-tier-dag.md +0 -161
  407. package/docs/design/repo-cleanup-plan.md +0 -231
  408. package/docs/design/runtime-isolation.md +0 -263
  409. package/docs/design/segmented-backward-training.md +0 -543
  410. package/docs/design/spec-decode-larger-targets.md +0 -229
  411. package/docs/design/ssd-kv-cold-tier.md +0 -415
  412. package/docs/design/structured-output.md +0 -484
  413. package/docs/design/tauri-desktop-app.md +0 -127
  414. package/docs/design/the-dreaming-master-plan.md +0 -445
  415. package/docs/design/turboquant-kv.md +0 -235
  416. package/docs/design/turboquant-weights.md +0 -467
  417. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  418. package/docs/design/web-chat-beat-matrix.md +0 -315
  419. package/docs/design/write-pipeline-entity.md +0 -468
  420. package/docs/planning/IDEAS.md +0 -69
  421. package/docs/reference/embedding.md +0 -197
  422. package/docs/reference/features-matrix.md +0 -101
  423. package/docs/reference/orpo-quickstart.md +0 -135
  424. package/src/flags.ts +0 -11
  425. /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
  426. /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
  427. /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
  428. /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
  429. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  430. /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
  431. /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
  432. /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
  433. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -0,0 +1,53 @@
1
+ import type { ExecutionCapabilities, ExecutionFeatures, ExecutionRequirements, ResolvedExecution } from "../contracts/execution";
2
+
3
+ /** Select the request method, then place it using executor capabilities. */
4
+ export function resolveExecution(
5
+ request: ExecutionRequirements, capabilities: ExecutionCapabilities,
6
+ features: ExecutionFeatures = { pagedKv: false, fill: false },
7
+ ): ResolvedExecution {
8
+ const reasons: string[] = [];
9
+ const sharedRequestExclusions = [
10
+ [!capabilities.continuous, "continuous-unavailable"],
11
+ [request.hasVision, "media-requires-serial"],
12
+ [request.hasAdapters && !capabilities.adapterBatch, "adapters-require-serial"],
13
+ [request.kvQuant && !capabilities.quantizedBatch, "kv-scheme-requires-serial"],
14
+ [request.turboQuant && !capabilities.turboQuantBatch, "turbo-kv-requires-serial"],
15
+ [request.hasGrammar && !capabilities.grammarBatch, "grammar-batching-disabled"],
16
+ [features.pagedKv && !capabilities.pagedBatch, "paged-kv-requires-serial"],
17
+ ] as const;
18
+ const sharedAdapterMethod = capabilities.sharedSpeculativeAdapters === true &&
19
+ !sharedRequestExclusions.some(([excluded]) => excluded) &&
20
+ capabilities.groupedMethods?.includes("speculative") === true;
21
+ const speculative = capabilities.method === "autoregressive" && request.hasDraft &&
22
+ !request.hasVision && (!request.hasAdapters || sharedAdapterMethod) && (!request.wantsLogprobs || capabilities.speculativeLogprobs === true) &&
23
+ (!request.kvQuant || capabilities.speculativeKvQuant === true) &&
24
+ (!request.turboQuant || capabilities.speculativeTurboQuant === true) && !features.pagedKv;
25
+ const method = speculative ? "speculative" : capabilities.method;
26
+ const continuousExclusions = [sharedRequestExclusions[0],
27
+ [!(capabilities.groupedMethods ?? ["autoregressive"]).includes(method), "method-requires-serial"],
28
+ ...sharedRequestExclusions.slice(1),
29
+ ] as const;
30
+ for (const [excluded, reason] of continuousExclusions) if (excluded) reasons.push(reason);
31
+ const mechanism = reasons.length ? "serial" : "continuous";
32
+ if (request.hasDraft && !speculative) reasons.push("draft-incompatible-with-request");
33
+ const pagedKv = features.pagedKv && !request.hasVision && !request.hasAdapters;
34
+ if (features.pagedKv && !pagedKv) reasons.push("paged-kv-bypassed-for-media-or-adapters");
35
+ const promptCache = method !== "speculative" && !request.hasVision && !pagedKv;
36
+ const fill = features.fill && method === "autoregressive" && mechanism === "serial" &&
37
+ !request.hasDraft && !request.hasVision && !request.userSeed && !request.hasGrammar &&
38
+ !request.wantsLogprobs && !request.kvQuant && !request.turboQuant;
39
+ if (features.fill && !fill) reasons.push("fill-incompatible-with-request");
40
+ const checkpoint = capabilities.checkpoints && method === "autoregressive" &&
41
+ (mechanism === "serial" || capabilities.sharedCheckpoints === true) && promptCache && !request.hasGrammar &&
42
+ !features.fill && !request.wantsLogprobs;
43
+ const compiledDecode = features.compiledDecode === true && capabilities.compiledDecode === true &&
44
+ method === "autoregressive" && !request.hasAdapters && !pagedKv;
45
+ if (features.compiledDecode && !compiledDecode) reasons.push("compiled-decode-unavailable-for-request");
46
+ const grammarJump = features.grammarJump === true && request.hasGrammar &&
47
+ method === "autoregressive" && mechanism === "serial" && !request.wantsLogprobs;
48
+ if (features.grammarJump && request.hasGrammar && !grammarJump)
49
+ reasons.push("grammar-jump-incompatible-with-request");
50
+ return Object.freeze({ method, mechanism, pagedKv, promptCache, checkpoint, fill,
51
+ compiledDecode, grammarJump,
52
+ reasons: Object.freeze(reasons) });
53
+ }
@@ -0,0 +1,53 @@
1
+ import type { DisposableResource, PreparedStateChange, ResourceOwner } from "../contracts/resources";
2
+
3
+ export function ownResource<T>(value: T, release: (value: T) => void): ResourceOwner<T> {
4
+ let held: { value: T } | undefined = { value };
5
+ const borrow = () => {
6
+ if (!held) throw new Error("resource ownership has ended");
7
+ return held.value;
8
+ };
9
+ return {
10
+ borrow,
11
+ transfer() { const result = borrow(); held = undefined; return result; },
12
+ close() {
13
+ if (!held) return;
14
+ const result = held.value;
15
+ held = undefined;
16
+ release(result);
17
+ },
18
+ };
19
+ }
20
+
21
+ /** Attempt every release once. One failed destructor must not leak siblings. */
22
+ export function disposeResources(resources: Iterable<DisposableResource>): void {
23
+ const errors: unknown[] = [];
24
+ for (const resource of new Set(resources)) {
25
+ try { resource.dispose(); } catch (error) { errors.push(error); }
26
+ }
27
+ if (errors.length === 1) throw errors[0];
28
+ if (errors.length) throw new AggregateError(errors, "resource cleanup failed");
29
+ }
30
+
31
+ /** Used at failure boundaries to retain the execution error as well as cleanup. */
32
+ export function cleanupFailure(error: unknown, cleanup: () => void): never {
33
+ try { cleanup(); }
34
+ catch (cleanupError) { throw new AggregateError([error, cleanupError], "execution and cleanup failed"); }
35
+ throw error;
36
+ }
37
+
38
+ /** Complete every preparation before publishing any owner's replacement.
39
+ * Old state is released only after all owners have committed. */
40
+ export function applyStateChanges(prepare: readonly (() => PreparedStateChange)[]): void {
41
+ const changes: PreparedStateChange[] = [];
42
+ try {
43
+ for (const build of prepare) changes.push(build());
44
+ for (const change of changes) change.commit();
45
+ } catch (error) { return cleanupFailure(error, () => disposeResources(changes.splice(0))); }
46
+ disposeResources(changes);
47
+ }
48
+
49
+ export function withResource<T, R>(owner: Pick<ResourceOwner<T>, "borrow" | "close">, use: (value: T) => R): R {
50
+ try { return use(owner.borrow()); }
51
+ catch (error) { cleanupFailure(error, () => owner.close()); }
52
+ finally { owner.close(); }
53
+ }
@@ -0,0 +1,72 @@
1
+ import type { ExecutionGroup, SchedulingClock } from "../contracts/scheduling";
2
+ import { disposeResources } from "./resources";
3
+
4
+ /** Continuous scheduling policy. Each advance is a backend-defined safe unit;
5
+ * this driver neither handles native state nor forces pending work to evaluate. */
6
+ export async function driveExecutionGroup(
7
+ group: ExecutionGroup, clock: SchedulingClock, yieldAfterPreparation = false,
8
+ ): Promise<void> {
9
+ let execution: (() => void) | undefined;
10
+ let residency: (() => void) | undefined;
11
+ let lastYield = 0;
12
+ let terminalError: unknown = new Error("scheduler closed");
13
+ const release = () => {
14
+ const releases = [execution, residency];
15
+ execution = residency = undefined;
16
+ disposeResources(releases.filter((fn): fn is () => void => !!fn).map((dispose) => ({ dispose })));
17
+ };
18
+ try {
19
+ while (!group.closed) {
20
+ group.pruneCancelled();
21
+ const held = group.admissionHeld;
22
+ if (!group.active && !group.preparing && (held || !group.queued)) {
23
+ release();
24
+ await group.waitForWork();
25
+ continue;
26
+ }
27
+ residency ??= group.reserveResidency();
28
+ if (!execution && group.acquireExecution) execution = await group.acquireExecution();
29
+ if (group.closed) break;
30
+
31
+ if (!group.preparing && !held && group.queued && group.active < group.maxActive)
32
+ group.admitNext();
33
+ while (group.preparing && group.canPrepareMore && !held && group.queued &&
34
+ group.active + (group.preparingRows ?? 1) < group.maxActive && group.canBurst() &&
35
+ (group.preparingTokens ?? 0) + (group.nextPreparationTokens ?? 0) <= (group.maxPreparationTokens ?? Infinity)) {
36
+ if (!group.admitNext()) break;
37
+ }
38
+ if (group.preparing) {
39
+ const activeBefore = group.active;
40
+ await group.advancePreparation();
41
+ // A bounded preparation may publish output before its state work ends.
42
+ // Flush it before the next work unit; queued short admissions still
43
+ // form a group across yields. Re-enter policy to observe new work,
44
+ // cancellation, admission holds and shutdown.
45
+ if (group.preparationPublishedOutput ||
46
+ (yieldAfterPreparation && !activeBefore && !group.preparing && group.active === 1 && !group.queued)) {
47
+ lastYield = clock.now();
48
+ await clock.yield();
49
+ continue;
50
+ }
51
+ }
52
+
53
+ // Finish short admissions before decode; long preparation interleaves
54
+ // with active work because the group still reports preparing=true.
55
+ if (!group.preparing && !held && group.queued && group.active < group.maxActive && group.canBurst())
56
+ continue;
57
+ if (group.active) {
58
+ try { await group.advance(); }
59
+ catch (error) { group.failActive(error); }
60
+ }
61
+ // Preserve the serial responsiveness budget for the single active run.
62
+ if (group.active === 1 && !group.queued && !group.preparing &&
63
+ !group.admissionHeld && clock.now() - lastYield < 25) continue;
64
+ lastYield = clock.now();
65
+ await clock.yield();
66
+ }
67
+ } catch (error) {
68
+ terminalError = error;
69
+ } finally {
70
+ disposeResources([{ dispose: () => group.failAll(terminalError) }, { dispose: release }]);
71
+ }
72
+ }
@@ -0,0 +1,247 @@
1
+ import type {
2
+ Cancellation, CancelReason, ExecutionPlan, GenerationEvent, GenerationOutcome,
3
+ GenerationOutput, GenerationSession, MethodResult, MethodRun, RunControl,
4
+ SessionState, Timer, TokenLogprobs,
5
+ } from "../contracts/generation";
6
+ import { CancellationSource, throwIfCancelled } from "./cancellation";
7
+
8
+ export interface SessionResources {
9
+ readonly timer: Timer;
10
+ readonly idleTimeoutMs: number;
11
+ readonly maxQueuedEvents: number;
12
+ readonly maxQueuedTokens: number;
13
+ readonly maxTopLogprobs: number;
14
+ reserveOutput(tokens: number): { buffer: Uint32Array; release(): void };
15
+ }
16
+
17
+ /** Lifecycle and bounded delivery only. No graph, cache, sampler, or method branches. */
18
+ export class EngineSession<Metrics> implements GenerationSession<Metrics> {
19
+ readonly result: Promise<GenerationOutcome<Metrics>>;
20
+ readonly events: AsyncIterable<GenerationEvent>;
21
+ #state: SessionState = "created";
22
+ #cancel = new CancellationSource();
23
+ #settle!: (outcome: GenerationOutcome<Metrics>) => void;
24
+ #started = false;
25
+ #readerClaimed = false;
26
+ #reading = false;
27
+ #publishing = false;
28
+ #queue: GenerationEvent[] = [];
29
+ #queuedTokens = 0;
30
+ #committed = 0;
31
+ #sequence = 0;
32
+ #wakeReader: (() => void) | undefined;
33
+ #wakeProducer: (() => void) | undefined;
34
+ #stopTimer: (() => void) | undefined;
35
+ #unsubscribe: (() => void) | undefined;
36
+ #buffer: Uint32Array | undefined;
37
+ #limit = 0;
38
+ #outputStopped = false;
39
+
40
+ constructor(
41
+ readonly id: string,
42
+ private readonly prepare: (cancellation: Cancellation) => Promise<ExecutionPlan<Metrics>>,
43
+ private readonly control: RunControl,
44
+ private readonly resources: SessionResources,
45
+ private readonly onTerminal: () => void,
46
+ ) {
47
+ this.result = new Promise((resolve) => { this.#settle = resolve; });
48
+ this.events = { [Symbol.asyncIterator]: () => this.#iterator() };
49
+ const unsubscribe = control.cancellation?.subscribe((reason) => { void this.cancel(reason); });
50
+ if (this.#state === "terminal") unsubscribe?.();
51
+ else this.#unsubscribe = unsubscribe;
52
+ if (this.#state !== "terminal") {
53
+ if (control.output !== "stream") this.#start();
54
+ else this.#armIdle();
55
+ }
56
+ }
57
+
58
+ get state(): SessionState { return this.#state; }
59
+
60
+ async cancel(reason: CancelReason = "requested"): Promise<void> {
61
+ if (this.#state !== "terminal") {
62
+ this.#cancel.cancel(reason);
63
+ this.#queue = [];
64
+ this.#queuedTokens = 0;
65
+ this.#wakeReader?.();
66
+ this.#wakeProducer?.();
67
+ this.#stopTimer?.();
68
+ if (!this.#started) this.#finish({ status: "cancelled", reason, committedTokens: 0 });
69
+ }
70
+ await this.result;
71
+ }
72
+
73
+ close(): Promise<void> { return this.cancel("consumer_closed"); }
74
+
75
+ #armIdle(): void {
76
+ this.#stopTimer?.();
77
+ this.#stopTimer = this.resources.timer.after(this.resources.idleTimeoutMs,
78
+ () => { void this.cancel("consumer_idle"); });
79
+ }
80
+
81
+ #iterator(): AsyncIterator<GenerationEvent> {
82
+ if (this.control.output !== "stream") throw new Error("collect sessions return output through result");
83
+ if (this.#readerClaimed) throw new Error("generation events have one consumer");
84
+ this.#readerClaimed = true;
85
+ return {
86
+ next: async () => {
87
+ if (this.#reading) throw new Error("concurrent next() is not supported");
88
+ this.#reading = true;
89
+ this.#stopTimer?.();
90
+ try {
91
+ this.#start();
92
+ while (!this.#queue.length && this.#state !== "terminal") {
93
+ await new Promise<void>((resolve) => { this.#wakeReader = resolve; });
94
+ this.#wakeReader = undefined;
95
+ }
96
+ const event = this.#queue.shift();
97
+ if (!event) return { done: true, value: undefined };
98
+ if (event.type === "committed") this.#queuedTokens -= event.tokenIds.length;
99
+ this.#wakeProducer?.();
100
+ if (this.#state !== "terminal") this.#armIdle();
101
+ return { done: false, value: event };
102
+ } finally { this.#reading = false; }
103
+ },
104
+ return: async () => { await this.close(); return { done: true, value: undefined }; },
105
+ throw: async (error) => { await this.close(); throw error; },
106
+ };
107
+ }
108
+
109
+ #start(): void {
110
+ if (this.#started || this.#state === "terminal") return;
111
+ this.#started = true;
112
+ void this.#execute();
113
+ }
114
+
115
+ async #execute(): Promise<void> {
116
+ let run: MethodRun<Metrics> | undefined;
117
+ let reservation: ReturnType<SessionResources["reserveOutput"]> | undefined;
118
+ let result: MethodResult<Metrics> | undefined;
119
+ let failure: unknown;
120
+ let failed = false;
121
+ try {
122
+ this.#state = "preparing";
123
+ throwIfCancelled(this.#cancel);
124
+ const plan = await this.prepare(this.#cancel);
125
+ throwIfCancelled(this.#cancel);
126
+ if (!Number.isSafeInteger(plan.outputTokenLimit) || plan.outputTokenLimit < 0)
127
+ throw new Error("invalid planned output token limit");
128
+ this.#limit = plan.outputTokenLimit;
129
+ if (this.control.output === "collect") {
130
+ reservation = this.resources.reserveOutput(this.#limit);
131
+ this.#buffer = reservation.buffer;
132
+ }
133
+ run = await plan.method.createRun(this.#cancel);
134
+ throwIfCancelled(this.#cancel);
135
+ this.#state = "running";
136
+ const output: GenerationOutput = {
137
+ commit: (ids, logprobs) => this.#publish(ids, logprobs),
138
+ progress: (completed, total) => this.#progress(completed, total),
139
+ };
140
+ result = await run.execute(output, this.#cancel);
141
+ } catch (error) { failure = error; failed = true; }
142
+ this.#state = "settling";
143
+ // Terminal means resources are safe to release, not merely that JS stopped reading.
144
+ let cleanupFailed = false;
145
+ let cleanupError: string | undefined;
146
+ try { await run?.close(); }
147
+ catch (error) {
148
+ cleanupError = error instanceof Error ? error.message : String(error);
149
+ if (!failed) failure = error;
150
+ failed = true;
151
+ cleanupFailed = true;
152
+ }
153
+ reservation?.release(); // Completed output ownership transfers to the caller.
154
+ const common = { committedTokens: this.#committed,
155
+ ...(this.#buffer ? { output: this.#buffer.subarray(0, this.#committed) } : {}) };
156
+ if (this.#cancel.reason && !cleanupFailed) {
157
+ this.#finish({ status: "cancelled", reason: this.#cancel.reason, ...common });
158
+ } else if (failed) {
159
+ this.#finish({ status: "failed", error: { code: cleanupFailed ? "cleanup_failed" : "execution_failed",
160
+ message: failure instanceof Error ? failure.message : String(failure),
161
+ ...(cleanupError === undefined ? {} : { cleanupError }) }, ...common });
162
+ } else {
163
+ this.#finish({ status: "completed", result: result!, ...common });
164
+ }
165
+ }
166
+
167
+ async #publish(ids: readonly number[], logprobs?: readonly (TokenLogprobs | undefined)[]): Promise<void | false> {
168
+ if (this.#publishing) throw new Error("method must await each publication");
169
+ this.#publishing = true;
170
+ try {
171
+ throwIfCancelled(this.#cancel);
172
+ if (this.#state !== "running") throw new Error("publication outside method execution");
173
+ if (this.#outputStopped) throw new Error("method published after the consumer requested a stop");
174
+ if (ids.length > this.#limit - this.#committed) throw new Error("method exceeded planned output limit");
175
+ if (logprobs && logprobs.length !== ids.length) throw new Error("logprobs must align with committed tokens");
176
+ if (logprobs?.some((item) => (item?.top?.length ?? 0) > this.resources.maxTopLogprobs))
177
+ throw new Error("top logprobs exceed session delivery capacity");
178
+ for (const id of ids)
179
+ if (!Number.isInteger(id) || id < 0 || id > 0xffffffff) throw new Error("invalid committed token id");
180
+ if (this.control.output === "callback") {
181
+ this.#committed += ids.length;
182
+ const result = await this.control.onTokens(ids, logprobs);
183
+ if (result === false) this.#outputStopped = true;
184
+ return result;
185
+ }
186
+ if (this.#buffer) {
187
+ if (logprobs) throw new Error("token logprobs require stream consumption");
188
+ this.#buffer.set(ids, this.#committed);
189
+ this.#committed += ids.length;
190
+ return;
191
+ }
192
+ for (let offset = 0; offset < ids.length;) {
193
+ const length = Math.min(ids.length - offset, this.resources.maxQueuedTokens);
194
+ await this.#space(length);
195
+ // Snapshot producer-owned arrays; later scratch-buffer reuse cannot alter events.
196
+ const event: GenerationEvent = { type: "committed", sequence: this.#sequence++,
197
+ tokenIds: ids.slice(offset, offset + length),
198
+ ...(logprobs ? { logprobs: logprobs.slice(offset, offset + length).map((item) => item && ({
199
+ ...(item.logprob === undefined ? {} : { logprob: item.logprob }),
200
+ ...(item.top ? { top: item.top.map((entry) => ({ id: entry.id, logprob: entry.logprob })) } : {}),
201
+ })) } : {}) };
202
+ this.#queue.push(event);
203
+ this.#queuedTokens += length;
204
+ this.#committed += length;
205
+ offset += length;
206
+ this.#wakeReader?.();
207
+ }
208
+ } finally { this.#publishing = false; }
209
+ }
210
+
211
+ async #progress(completed: number, total?: number): Promise<void> {
212
+ if (this.#publishing) throw new Error("method must await each publication");
213
+ this.#publishing = true;
214
+ try {
215
+ throwIfCancelled(this.#cancel);
216
+ if (this.#state !== "running") throw new Error("publication outside method execution");
217
+ if (!Number.isFinite(completed) || completed < 0 ||
218
+ (total !== undefined && (!Number.isFinite(total) || total < completed)))
219
+ throw new Error("invalid progress");
220
+ if (this.control.output !== "stream") return;
221
+ await this.#space(0);
222
+ this.#queue.push({ type: "progress", completed, ...(total === undefined ? {} : { total }) });
223
+ this.#wakeReader?.();
224
+ } finally { this.#publishing = false; }
225
+ }
226
+
227
+ async #space(tokens: number): Promise<void> {
228
+ while (this.#queue.length >= this.resources.maxQueuedEvents ||
229
+ this.#queuedTokens + tokens > this.resources.maxQueuedTokens) {
230
+ throwIfCancelled(this.#cancel);
231
+ this.#armIdle();
232
+ await new Promise<void>((resolve) => { this.#wakeProducer = resolve; });
233
+ this.#wakeProducer = undefined;
234
+ }
235
+ throwIfCancelled(this.#cancel);
236
+ }
237
+
238
+ #finish(outcome: GenerationOutcome<Metrics>): void {
239
+ if (this.#state === "terminal") return;
240
+ this.#state = "terminal";
241
+ this.#stopTimer?.();
242
+ this.#unsubscribe?.();
243
+ this.#settle(outcome);
244
+ this.#wakeReader?.();
245
+ this.onTerminal();
246
+ }
247
+ }
@@ -29,6 +29,45 @@ repo rule: free-running greedy "measures chaos").
29
29
  `KL(compat ‖ fused)` is literally "measure the output difference."
30
30
  - **two-model (optiq-style absolute quality):** a separate reference model
31
31
  (bf16 if it fits, else uniform-4bit), both resident.
32
+ - **saved-teacher (`--reference-logits <dir>`):** the reference is a
33
+ **dump on disk**, not a resident model — the only way to score against a
34
+ bf16 teacher on 32 GB. A Python-side script forwards the teacher once and
35
+ writes, per teacher-forced position, the top-2048 logits plus the
36
+ **full-vocab logsumexp**; every candidate is then scored through OUR
37
+ engine. Format (`format_version` 1, read by `reference-logits.ts`):
38
+
39
+ ```
40
+ runs/kl-teacher/<tag>/
41
+ manifest.json {format_version, model, corpus_sha256, ctx_len, n_seqs,
42
+ top_k, positions_per_seq, created, notes}
43
+ tokens.bin int32 LE [n_seqs][ctx_len]
44
+ seq-<i>.bin record r (r = 0…ctx_len-2, the distribution over token
45
+ r+1, i.e. candidate POSITION r):
46
+ int32[top_k] indices, descending by logit
47
+ float16[top_k] reference logits
48
+ float32 full-vocab logsumexp
49
+ ```
50
+
51
+ `KL = Σ_{j∈topK} p_j·(log p_j − log q_j)`, `p_j = exp(ref_j − ref_lse)`,
52
+ `log q_j = cand_j − logsumexp(cand, full vocab)`, float32 throughout.
53
+ The sum is truncated to top-k, so the run also reports **captured mass**
54
+ `Σ_j p_j` (how much of `p` the number covers — a low-mass run is not a
55
+ comparable KL) and **top-1 agreement** (argmax over the full vocab).
56
+ The forward is the SERVING path (`makeCache` + chunked `forwardHidden` +
57
+ `logitsFromHidden` per chunk, `--chunk` positions at a time so a 4k
58
+ context's full-vocab logits never exist at once), **not** `trainForward` —
59
+ which is why this works on qwen3_5, where `mlx-bun perplexity` cannot go
60
+ (docs/design/turboquant.md, "Known engine gaps"). KV stays bf16: this is a
61
+ weights-only instrument.
62
+
63
+ Noise floor (measured, M1 Max, Qwen3.5-0.8B-OptiQ-4bit, 2×128 ctx,
64
+ top-64): scoring a dump against the model that produced it gives KL
65
+ **exactly 0** at the same `--chunk`, and mean 9.3e-6 / p95 8.3e-7 across
66
+ chunk 64 → 40. float16 storage is lossless for a bf16 teacher (bf16's
67
+ 7 mantissa bits fit float16's 10, and logits sit far inside float16's
68
+ 65504 range), so the residual is only the engine's own L-dependent bf16
69
+ rounding — the same effect that makes prefill chunk size ulp-visible
70
+ (`generate.ts`, prefill-tail-split). Compare candidates at one `--chunk`.
32
71
 
33
72
  ## Run (on a cleared machine — loads models, not from an agent session)
34
73
 
@@ -42,6 +81,10 @@ bun scripts/eval.ts kl --candidate e4b --self MLX_BUN_NO_FUSED_SDPA --ref-value
42
81
  # optiq-style absolute drift vs a reference model:
43
82
  bun scripts/eval.ts kl --candidate e4b --reference <bf16-or-4bit-id>
44
83
 
84
+ # vs a saved bf16 teacher-logits dump (--n caps sequences, --chunk positions
85
+ # per forward; the dump brings its own corpus, so --prompts-file/--seq don't apply):
86
+ bun scripts/eval.ts kl --candidate <model> --reference-logits runs/kl-teacher/<tag>
87
+
45
88
  # higher-fidelity prompts (optiq's calibration mix):
46
89
  bun scripts/eval.ts kl --candidate e4b --prompts-file \
47
90
  /Users/joshrossi/Code/mlx-lm/.venv/.../optiq/calibration/data/optiq.jsonl
@@ -71,7 +114,7 @@ the throughput `runs` table). Each row records the active perf levers
71
114
  perf levers (NO_FUSED_SDPA) actually bite.
72
115
  - **M1 (done):** all six capability tasks ported + runtime-validated, plus
73
116
  `capability` aggregation and the `smoketest` (KL + GSM8K-50) gate. Datasets
74
- exported by `scripts/eval/export-datasets.py` → `~/.cache/mlx-bun/eval-data/`.
117
+ exported by `scripts/oracle/export-datasets.py` → `~/.cache/mlx-bun/eval-data/`.
75
118
  Tasks run through the real quantized-KV path (`runner.ts`). HumanEval executes
76
119
  in a sandbox-exec + venv-python subprocess; HashHop reconstructs Magic AI's
77
120
  generator (`MultiHopEval` isn't on PyPI). **Open quality checks** (need a real