mlx-bun 0.0.13 → 0.3.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 (427) hide show
  1. package/README.md +71 -578
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/README.md +91 -0
  4. package/docs/{design → archive}/hlg-sampling.md +3 -3
  5. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  6. package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
  7. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  8. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  9. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  10. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  11. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  12. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  13. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  14. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  15. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  16. package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
  17. package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
  18. package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
  19. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  20. package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
  21. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  22. package/docs/design/batching.md +569 -0
  23. package/docs/design/decode-speed-program.md +3178 -169
  24. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  25. package/docs/design/generic-model-support.md +579 -334
  26. package/docs/design/kv-cache.md +680 -0
  27. package/docs/design/orpo-training.md +673 -1239
  28. package/docs/design/speculative-decoding.md +1627 -0
  29. package/docs/design/turboquant.md +2102 -0
  30. package/docs/design/unified-engine-frontier-plan.md +1831 -727
  31. package/docs/design/web-chat-redesign.md +666 -1083
  32. package/docs/planning/PRODUCT_ROADMAP.md +34 -1
  33. package/docs/planning/release-notes-v0.3.0.md +35 -0
  34. package/docs/planning/video-series.md +421 -0
  35. package/docs/reference/benchmarks.md +1162 -0
  36. package/docs/reference/cli.md +395 -149
  37. package/docs/reference/distribution.md +321 -181
  38. package/docs/reference/environment.md +348 -0
  39. package/docs/reference/glossary.md +39 -0
  40. package/docs/reference/library-api.md +580 -142
  41. package/docs/reference/memory.md +227 -64
  42. package/docs/reference/models.md +137 -6
  43. package/docs/reference/server-api.md +938 -422
  44. package/docs/reference/server-config.md +652 -320
  45. package/docs/reference/training.md +393 -254
  46. package/docs/reference/troubleshooting.md +166 -0
  47. package/package.json +10 -5
  48. package/src/admission-plan.ts +18 -0
  49. package/src/anthropic.ts +92 -3
  50. package/src/audio/decode.ts +2 -2
  51. package/src/audio/features.ts +2 -2
  52. package/src/backends/mlx/autoregressive.ts +108 -0
  53. package/src/backends/mlx/batch-group.ts +1646 -0
  54. package/src/backends/mlx/diffusion.ts +39 -0
  55. package/src/backends/mlx/draft-target.ts +47 -0
  56. package/src/backends/mlx/evaluation.ts +105 -0
  57. package/src/backends/mlx/fill-append.ts +45 -0
  58. package/src/backends/mlx/gateway-binding.ts +71 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/memory-client.ts +189 -0
  61. package/src/backends/mlx/memory-guard.ts +40 -0
  62. package/src/backends/mlx/methods.ts +90 -0
  63. package/src/backends/mlx/model-prompt.ts +164 -0
  64. package/src/backends/mlx/model-serving.ts +79 -0
  65. package/src/backends/mlx/prefill.ts +33 -0
  66. package/src/backends/mlx/request-policy.ts +20 -0
  67. package/src/backends/mlx/rollback.ts +51 -0
  68. package/src/backends/mlx/serial-executor.ts +273 -0
  69. package/src/backends/mlx/speculative.ts +114 -0
  70. package/src/backends/mlx/state-views.ts +26 -0
  71. package/src/backends/mlx/text-engine.ts +73 -0
  72. package/src/cli.ts +189 -61
  73. package/src/client.ts +66 -0
  74. package/src/config.ts +21 -4
  75. package/src/contracts/completion.ts +16 -0
  76. package/src/contracts/execution.ts +49 -0
  77. package/src/contracts/generation.ts +103 -0
  78. package/src/contracts/host.ts +7 -0
  79. package/src/contracts/jobs.ts +66 -0
  80. package/src/contracts/pi-provider.ts +30 -0
  81. package/src/contracts/pi.ts +259 -0
  82. package/src/contracts/resources.ts +18 -0
  83. package/src/contracts/scheduling.ts +27 -0
  84. package/src/contracts/tsconfig.json +14 -0
  85. package/src/diffusion/diffusion-generate.ts +218 -153
  86. package/src/embed.ts +1 -1
  87. package/src/engine/admission.ts +59 -0
  88. package/src/engine/cancellation.ts +38 -0
  89. package/src/engine/engine.ts +56 -0
  90. package/src/engine/execution-coordinator.ts +70 -0
  91. package/src/engine/execution-plan.ts +51 -0
  92. package/src/engine/resources.ts +42 -0
  93. package/src/engine/scheduler.ts +67 -0
  94. package/src/engine/session.ts +247 -0
  95. package/src/eval/README.md +44 -1
  96. package/src/eval/kl.ts +263 -23
  97. package/src/eval/reference-logits.ts +207 -0
  98. package/src/eval/runner.ts +10 -79
  99. package/src/eval/tasks/bfcl.ts +2 -1
  100. package/src/eval/tasks/gsm8k.ts +2 -1
  101. package/src/eval/tasks/hashhop.ts +2 -1
  102. package/src/eval/tasks/humaneval.ts +5 -4
  103. package/src/eval/tasks/ifeval.ts +2 -1
  104. package/src/eval/tasks/mmlu.ts +2 -1
  105. package/src/expert-io.ts +3 -1
  106. package/src/expert-offload.ts +3 -1
  107. package/src/fill/echo-index.ts +188 -0
  108. package/src/fill/fill-session.ts +452 -0
  109. package/src/fill/proposal.ts +68 -0
  110. package/src/fill/schema-rows.ts +506 -0
  111. package/src/fill/tool-boundary.ts +103 -0
  112. package/src/fit.ts +24 -43
  113. package/src/generate.ts +740 -337
  114. package/src/grammar.ts +14 -8
  115. package/src/harness-pi.ts +15 -34
  116. package/src/hub-rest.ts +4 -4
  117. package/src/index.ts +27 -0
  118. package/src/inference/denoising.ts +17 -0
  119. package/src/inference/graph.ts +33 -0
  120. package/src/inference/prefill.ts +39 -0
  121. package/src/inference/rollback.ts +7 -0
  122. package/src/jobs/db.ts +4 -0
  123. package/src/jobs/index.ts +2 -0
  124. package/src/jobs/job-entry.ts +15 -14
  125. package/src/jobs/runner.ts +98 -13
  126. package/src/jobs/task-client.ts +19 -0
  127. package/src/jobs/types.ts +2 -58
  128. package/src/kv-scheme.ts +199 -0
  129. package/src/kv-store.ts +459 -234
  130. package/src/lab/README.md +18 -0
  131. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  132. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  133. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
  134. package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
  135. package/src/library.ts +40 -0
  136. package/src/lora.ts +18 -0
  137. package/src/media-fetch.ts +20 -4
  138. package/src/memory/article.ts +1 -1
  139. package/src/memory/chunk.ts +1 -1
  140. package/src/memory/model.ts +32 -170
  141. package/src/memory/prompts.ts +1 -1
  142. package/src/memory/rest.ts +1 -1
  143. package/src/memory/schedule.ts +1 -1
  144. package/src/memory/stages.ts +4 -1
  145. package/src/memory/vault.ts +3 -4
  146. package/src/mlx/array.ts +9 -10
  147. package/src/mlx/compile.ts +12 -2
  148. package/src/mlx/ffi.ts +66 -22
  149. package/src/mlx/materialize.ts +23 -0
  150. package/src/mlx/metal-kernel.ts +10 -11
  151. package/src/mlx/ops.ts +64 -19
  152. package/src/mlx/quantized-rows.ts +36 -0
  153. package/src/mlx/token-bitmask.ts +52 -0
  154. package/src/mlx/turboquant-kv-decode.ts +82 -0
  155. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  156. package/src/mlx/turboquant-ops.ts +33 -3
  157. package/src/mlx/turboquant-tables.ts +2 -2
  158. package/src/model/batched-mask.ts +9 -3
  159. package/src/model/batched-quant.ts +2 -2
  160. package/src/model/batched-rotating-quant.ts +45 -99
  161. package/src/model/batched-rotating-state.ts +73 -0
  162. package/src/model/batched-rotating.ts +57 -106
  163. package/src/model/batched-row-storage.ts +127 -0
  164. package/src/model/compiled-decode.ts +4 -3
  165. package/src/model/diffusion-gemma.ts +8 -8
  166. package/src/model/factory.ts +87 -49
  167. package/src/model/fingerprint.ts +1 -1
  168. package/src/model/flash-attention.ts +3 -3
  169. package/src/model/gemma4-base.ts +187 -17
  170. package/src/model/gemma4.ts +6 -6
  171. package/src/model/generated/gemma4-12b.ts +52 -148
  172. package/src/model/generated/gemma4-26b.ts +34 -94
  173. package/src/model/generated/gemma4-e4b.ts +28 -76
  174. package/src/model/glm52-cache.ts +19 -9
  175. package/src/model/glm52-dsa.ts +13 -9
  176. package/src/model/glm52-memory.ts +28 -1
  177. package/src/model/implementation.ts +69 -0
  178. package/src/model/minicpm5.ts +7 -8
  179. package/src/model/profile.ts +443 -0
  180. package/src/model/qwen-append.ts +12 -0
  181. package/src/model/qwen-conv.ts +52 -0
  182. package/src/model/qwen3-delta.ts +98 -2
  183. package/src/model/qwen3-mrope.ts +252 -0
  184. package/src/model/qwen3_5-checkpoint.ts +164 -0
  185. package/src/model/qwen3_5.ts +336 -60
  186. package/src/model/support.ts +1 -1
  187. package/src/model/trellis-balanced-scatter.ts +51 -0
  188. package/src/model/trellis-linear.ts +672 -0
  189. package/src/model/trellis-shared-m.ts +151 -0
  190. package/src/model/trellis-shared-scatter.ts +144 -0
  191. package/src/model/trellis-splitk-prefill.ts +158 -0
  192. package/src/model/trellis-tiled-prefill.ts +136 -0
  193. package/src/model/trellis-vector-expand.ts +62 -0
  194. package/src/model/trellis-wide-prefill.ts +94 -0
  195. package/src/model/universal/dense.ts +1 -1
  196. package/src/model/universal/modules.ts +8 -1
  197. package/src/native/frame_extract.swift +140 -0
  198. package/src/native-pack.ts +15 -7
  199. package/src/pi-provider.ts +6 -64
  200. package/src/pi-web.ts +14 -320
  201. package/src/prompt-cache.ts +97 -54
  202. package/src/quantize/allocator.ts +1 -1
  203. package/src/quantize/atomic-output.ts +38 -0
  204. package/src/quantize/calibration.ts +2 -1
  205. package/src/quantize/config-writer.ts +16 -3
  206. package/src/quantize/index.ts +28 -1
  207. package/src/quantize/job.ts +11 -0
  208. package/src/quantize/quantizer.ts +265 -100
  209. package/src/quantize/rotate.ts +603 -0
  210. package/src/quantize/safetensors-writer.ts +79 -1
  211. package/src/quantize/sensitivity.ts +41 -59
  212. package/src/quantize/trellis.ts +586 -0
  213. package/src/quantize/weight-transform.ts +292 -0
  214. package/src/responses.ts +130 -3
  215. package/src/runtime-config.ts +81 -0
  216. package/src/sampler.ts +276 -4
  217. package/src/serve/admin-routes.ts +184 -0
  218. package/src/serve/aux-routes.ts +132 -0
  219. package/src/serve/batch-scheduler.ts +8 -1558
  220. package/src/serve/chat-request.ts +391 -0
  221. package/src/serve/chat-stage.ts +195 -0
  222. package/src/serve/checkpoint-identity.ts +64 -0
  223. package/src/serve/completion-executor.ts +354 -0
  224. package/src/serve/completion-sink.ts +157 -0
  225. package/src/serve/discovery-routes.ts +204 -0
  226. package/src/serve/generation-gateway.ts +211 -243
  227. package/src/serve/http.ts +159 -0
  228. package/src/serve/inference-request.ts +79 -0
  229. package/src/serve/isolate.ts +297 -105
  230. package/src/serve/kv-budget.ts +14 -0
  231. package/src/serve/lab-routes.ts +341 -0
  232. package/src/serve/lane-registry.ts +2 -1
  233. package/src/serve/model-admin-routes.ts +155 -0
  234. package/src/serve/model-binding.ts +43 -0
  235. package/src/serve/model-host.ts +512 -0
  236. package/src/serve/openai-wire.ts +103 -0
  237. package/src/serve/parent-application.ts +56 -0
  238. package/src/serve/pipeline.ts +33 -0
  239. package/src/serve/preparation.ts +33 -0
  240. package/src/serve/prompt-response-trace.ts +147 -0
  241. package/src/serve/request-plan.ts +162 -0
  242. package/src/serve/request-prep.ts +346 -0
  243. package/src/serve/response-lease.ts +24 -0
  244. package/src/serve/responses-client.ts +69 -0
  245. package/src/serve/session-completion-engine.ts +110 -0
  246. package/src/serve/session-search.ts +1 -1
  247. package/src/serve/static-routes.ts +101 -0
  248. package/src/serve/text-completion-stage.ts +104 -0
  249. package/src/serve/token-streams.ts +519 -0
  250. package/src/server.ts +523 -3551
  251. package/src/spec/assistant-source.ts +10 -44
  252. package/src/spec/deepspec-source.ts +6 -6
  253. package/src/spec/dflash-source.ts +9 -8
  254. package/src/spec/dspark/ab-stats.ts +3 -3
  255. package/src/spec/dspark/calibration.ts +2 -2
  256. package/src/spec/dspark/deepspec-module.ts +2 -2
  257. package/src/spec/dspark/generate-dflash.ts +2 -2
  258. package/src/spec/dspark/generate.ts +2 -2
  259. package/src/spec/dspark/loader.ts +1 -1
  260. package/src/spec/dspark/module-dflash.ts +5 -4
  261. package/src/spec/dspark/module.ts +3 -3
  262. package/src/spec/dspark/quantize-drafter.ts +1 -1
  263. package/src/spec/generate.ts +1 -1
  264. package/src/spec/glm52-mtp-source.ts +9 -1
  265. package/src/spec/ngram-source.ts +1 -1
  266. package/src/spec/prefix-state.ts +45 -0
  267. package/src/spec/qwen-mtp-source.ts +528 -0
  268. package/src/spec/serve-loop.ts +179 -213
  269. package/src/spec/source.ts +42 -10
  270. package/src/spec/two-model.ts +1 -1
  271. package/src/ssd-cache.ts +95 -24
  272. package/src/ssd-durability.ts +207 -0
  273. package/src/tool-call.ts +51 -14
  274. package/src/train/flash-cce.ts +14 -13
  275. package/src/train/forward.ts +38 -1
  276. package/src/train/loss.ts +3 -2
  277. package/src/train/prefix-shared.ts +5 -1
  278. package/src/train/segmented.ts +9 -6
  279. package/src/train/trainer.ts +9 -8
  280. package/src/vision/preprocess.ts +1 -1
  281. package/src/vision/prompt.ts +48 -2
  282. package/src/vision/qwen3vl-preprocess.ts +409 -0
  283. package/src/vision/qwen3vl-prompt.ts +196 -0
  284. package/src/vision/qwen3vl-tower.ts +555 -0
  285. package/src/vision/video-frames.ts +148 -0
  286. package/src/web/app.html +1 -1
  287. package/src/web/app.js +15 -6
  288. package/src/web/src/adapters-panel.ts +3 -3
  289. package/src/web/src/assistant.ts +2 -36
  290. package/src/web/src/chat.ts +16 -9
  291. package/src/web/src/composer.ts +4 -4
  292. package/src/web/src/hub.ts +1 -1
  293. package/src/web/src/markdown.ts +0 -0
  294. package/src/web/src/memory-panel.ts +1 -1
  295. package/src/web/src/model-picker.ts +1 -1
  296. package/src/web/src/palette.ts +1 -1
  297. package/src/web/src/protocol.ts +3 -39
  298. package/src/web/src/sessions.ts +1 -1
  299. package/src/web/src/ui-catalog.ts +4 -18
  300. package/src/web-assets.ts +47 -0
  301. package/src/weights.ts +134 -33
  302. package/docs/archive/mlx-bun-lab-report.html +0 -275
  303. package/docs/archive/wwdc-mlx-bun.html +0 -848
  304. package/docs/design/adapters-end-to-end.md +0 -205
  305. package/docs/design/batching-perf-path.md +0 -255
  306. package/docs/design/batching-v2-plan.md +0 -529
  307. package/docs/design/bucketing-stage.md +0 -197
  308. package/docs/design/compat-cli-surface-design.md +0 -230
  309. package/docs/design/docs-reorg-plan.md +0 -165
  310. package/docs/design/dspark-serving-program.md +0 -371
  311. package/docs/design/dspark-speculative-decoding.md +0 -268
  312. package/docs/design/grammar-spec-batching-integration.md +0 -301
  313. package/docs/design/memory-inference-path.md +0 -422
  314. package/docs/design/memory-synthesis.md +0 -287
  315. package/docs/design/memory-system.md +0 -237
  316. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  317. package/docs/design/omlx-adoption-map.md +0 -98
  318. package/docs/design/orpo-dynamic-lambda.md +0 -220
  319. package/docs/design/orpo-future-enhancements.md +0 -340
  320. package/docs/design/paged-kv-cache.md +0 -214
  321. package/docs/design/parallel-slots.md +0 -567
  322. package/docs/design/parity-tier-dag.md +0 -161
  323. package/docs/design/repo-cleanup-plan.md +0 -189
  324. package/docs/design/runtime-isolation.md +0 -263
  325. package/docs/design/segmented-backward-training.md +0 -543
  326. package/docs/design/spec-decode-larger-targets.md +0 -229
  327. package/docs/design/ssd-kv-cold-tier.md +0 -288
  328. package/docs/design/structured-output.md +0 -484
  329. package/docs/design/tauri-desktop-app.md +0 -127
  330. package/docs/design/the-dreaming-master-plan.md +0 -445
  331. package/docs/design/turboquant-kv.md +0 -235
  332. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  333. package/docs/design/web-chat-beat-matrix.md +0 -315
  334. package/docs/design/write-pipeline-entity.md +0 -468
  335. package/docs/investigations/curve-runs/bisector-route.json +0 -98
  336. package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
  337. package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
  338. package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
  339. package/docs/investigations/hlg-ab.html +0 -34
  340. package/docs/investigations/hlg-explorer.html +0 -238
  341. package/docs/investigations/hlg-figs/cliff.svg +0 -1
  342. package/docs/investigations/hlg-figs/cross.svg +0 -1
  343. package/docs/investigations/hlg-figs/edges.svg +0 -1
  344. package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
  345. package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
  346. package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
  347. package/docs/investigations/hlg-figs/terrain.svg +0 -1
  348. package/docs/investigations/hlg-report.html +0 -262
  349. package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
  350. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  351. package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
  352. package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
  353. package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
  354. package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
  355. package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
  356. package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
  357. package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
  358. package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
  359. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  360. package/docs/investigations/hlg-runs/hlg-map.json +0 -383
  361. package/docs/investigations/hlg-runs/run0-original.log +0 -159
  362. package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
  363. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  364. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  365. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  366. package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  367. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  368. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  369. package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  370. package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
  371. package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
  372. package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
  373. package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
  374. package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
  375. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  376. package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
  377. package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
  378. package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
  379. package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
  380. package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
  381. package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  382. package/docs/investigations/hlg-runs/runN-verify.log +0 -116
  383. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  384. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  385. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  386. package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  387. package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  388. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  389. package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
  390. package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  391. package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
  392. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  393. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  394. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  395. package/docs/planning/IDEAS.md +0 -69
  396. package/docs/reference/embedding.md +0 -197
  397. package/docs/reference/features-matrix.md +0 -100
  398. package/docs/reference/orpo-quickstart.md +0 -135
  399. package/src/flags.ts +0 -13
  400. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  401. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  402. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  403. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  404. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  405. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  406. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  407. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  408. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  409. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  410. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  411. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  412. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  413. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  414. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  415. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  416. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  417. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  418. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  419. /package/docs/{planning → archive/planning}/journal.md +0 -0
  420. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  421. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  422. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  423. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  424. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  425. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
  426. /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
  427. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -545,7 +545,7 @@ export function flashBackward(
545
545
  // (dK_j[d] → [kv_row][d]); no post-transpose. (An earlier "fix" transposed
546
546
  // it on the false belief the buffer was swapped — that transpose is only the
547
547
  // identity at Tkv==D and corrupted dK for Tkv≠D; removed after
548
- // scripts/experiments/flash-dkv-debug.ts showed the raw output is correct.)
548
+ // flash-dkv-debug.ts (deleted 2026-08-23; git history) showed the raw output is correct.)
549
549
  return [dq[0]!, dkv[0]!, dkv[1]!];
550
550
  } finally {
551
551
  Dvec.dispose();
@@ -621,8 +621,8 @@ export function flashAttention(
621
621
  // - This flash kernel is the L2 path: a port of mlx-optiq's
622
622
  // flash_attention_metal (O(L) backward memory). Its parity oracle is OPTIQ,
623
623
  // not finite differences. Confirmed: optiq's flash dK == ops.sdpa to f16
624
- // (scripts/flash-optiq-check.py, rel 0.0%), and mlx-bun's flash == ops.sdpa
625
- // (tests/flash-attention.test.ts) ⟹ mlx-bun flash == optiq flash (L2 parity).
624
+ // (scripts/oracle/flash-optiq-check.py, rel 0.0%), and mlx-bun's flash == ops.sdpa
625
+ // (tests/unit/flash-attention.test.ts) ⟹ mlx-bun flash == optiq flash (L2 parity).
626
626
  //
627
627
  // Two real port bugs were fixed to reach that parity (the original diverged
628
628
  // ~100% from optiq on dK): a spurious dK transpose in flashBackward (corrupted
@@ -1,5 +1,5 @@
1
1
  // gemma4-base — the config-INDEPENDENT machinery shared by every
2
- // architecture variant (docs/design/optimization_plan.md Phase B: pure code
2
+ // architecture variant (docs/archive/investigations/optimization_plan.md Phase B: pure code
3
3
  // movement out of the gemma4.ts monolith; every definition here is
4
4
  // verbatim from it). Cache classes, quantized-KV SDPA, masks, the
5
5
  // quantized primitives + LoRA machinery, and small graph helpers live
@@ -13,8 +13,10 @@ import type { Weights } from "../weights";
13
13
  import { MlxArray } from "../mlx/array";
14
14
  import { Dtype } from "../mlx/ffi";
15
15
  import * as ops from "../mlx/ops";
16
+ import { quantizedMatmulRows } from "../mlx/quantized-rows";
16
17
  import { expertOffloadArray } from "../expert-offload";
17
18
  import * as tq from "../mlx/turboquant-ops";
19
+ import { runtimeValue } from "../runtime-config";
18
20
 
19
21
  export type MaskMode = "" | "causal";
20
22
  export interface Mask {
@@ -53,6 +55,15 @@ export class LoraState {
53
55
  dropoutSeed: number | null = null;
54
56
  }
55
57
 
58
+ /** Replaceable quantized payload. Inference sees this as read-only through
59
+ * QuantizedLinear getters; sensitivity analysis exchanges it atomically. */
60
+ export interface QuantizedLinearState {
61
+ w: MlxArray;
62
+ scales: MlxArray;
63
+ biases: MlxArray | null;
64
+ spec: ops.QuantSpec;
65
+ }
66
+
56
67
  /** Inverted LoRA-input dropout, keyed by (seed, id) so it is deterministic —
57
68
  * the same (seed, id, shape) reproduces the mask, which is what makes the
58
69
  * segmented / gradient-checkpoint recompute correct. kept ⇒ x/(1-p),
@@ -79,18 +90,48 @@ export class QuantizedLinear {
79
90
  /** Stable per-target index for keying training-only LoRA dropout (set by
80
91
  * attachForTraining). Gives each adapted linear an independent dropout mask. */
81
92
  dropoutId = 0;
93
+ private _w: MlxArray;
94
+ private _scales: MlxArray;
95
+ private _biases: MlxArray | null;
96
+ private _spec: ops.QuantSpec;
82
97
 
83
98
  constructor(
84
- readonly w: MlxArray,
85
- readonly scales: MlxArray,
86
- readonly biases: MlxArray | null,
87
- readonly spec: ops.QuantSpec,
99
+ w: MlxArray,
100
+ scales: MlxArray,
101
+ biases: MlxArray | null,
102
+ spec: ops.QuantSpec,
88
103
  /** ADDITIVE bias term (`.bias`, mlx nn.QuantizedLinear's optional bias —
89
104
  * qwen2 qkv, starcoder2, …). Distinct from `biases`, the quantization
90
105
  * zero-points. Applied after the matmul, before any LoRA residual,
91
106
  * exactly like mlx's QuantizedLinear.__call__. */
92
107
  readonly bias: MlxArray | null = null,
93
- ) {}
108
+ ) {
109
+ this._w = w;
110
+ this._scales = scales;
111
+ this._biases = biases;
112
+ this._spec = spec;
113
+ }
114
+
115
+ get w(): MlxArray { return this._w; }
116
+ get scales(): MlxArray { return this._scales; }
117
+ get biases(): MlxArray | null { return this._biases; }
118
+ get spec(): ops.QuantSpec { return this._spec; }
119
+
120
+ /** Atomically install a quantized payload and return the previous one.
121
+ * This is the sole mutation capability used by sensitivity sweeps. */
122
+ exchangeQuantizedState(next: QuantizedLinearState): QuantizedLinearState {
123
+ const previous = {
124
+ w: this._w,
125
+ scales: this._scales,
126
+ biases: this._biases,
127
+ spec: this._spec,
128
+ };
129
+ this._w = next.w;
130
+ this._scales = next.scales;
131
+ this._biases = next.biases;
132
+ this._spec = next.spec;
133
+ return previous;
134
+ }
94
135
 
95
136
  static load(weights: Weights, path: string, config: ModelConfig): QuantizedLinear {
96
137
  if (!weights.has(`${path}.scales`))
@@ -109,14 +150,23 @@ export class QuantizedLinear {
109
150
  /** (in_features, out_features) from the quantized tensors (reference
110
151
  * _infer_linear_shape: scales are [out, in/group_size]). */
111
152
  get inFeatures(): number {
112
- return this.scales.shape[1]! * this.spec.groupSize;
153
+ return this._scales.shape[1]! * this._spec.groupSize;
113
154
  }
114
155
  get outFeatures(): number {
115
- return this.scales.shape[0]!;
116
- }
117
-
118
- forward(x: MlxArray): MlxArray {
119
- let out = ops.quantizedMatmul(x, this.w, this.scales, this.biases, this.spec, true);
156
+ return this._scales.shape[0]!;
157
+ }
158
+
159
+ forward(x: MlxArray, independentRows = false): MlxArray {
160
+ let out = independentRows ? quantizedMatmulRows(
161
+ x, this._w, this._scales, this._biases, this._spec,
162
+ ) : ops.quantizedMatmul(
163
+ x,
164
+ this._w,
165
+ this._scales,
166
+ this._biases,
167
+ this._spec,
168
+ true,
169
+ );
120
170
  // Additive bias (mlx QuantizedLinear: `x = x + self["bias"]`), before
121
171
  // the LoRA residual (LoRALinear calls the base linear bias-inclusive).
122
172
  if (this.bias) out = disposing(out, ops.add(out, this.bias));
@@ -216,6 +266,20 @@ export type SharedKv =
216
266
 
217
267
  export interface Cache {
218
268
  offset: number;
269
+ /** Stable storage identity for compatibility guards and persistence.
270
+ * REQUIRED: every capability predicate (isPlainKvCache, isRotating*,
271
+ * kv-store codecs) is a string compare on this value, so a missing
272
+ * override used to fail OPEN into wrong routing (PRs #42/#43:
273
+ * BatchedRotatingCache shipped without one and batched joins dropped
274
+ * running rows). Wrappers report their own kind plus the inner kind. */
275
+ signature(): string;
276
+ /** Physical cache storage consumed by one additional token for one row.
277
+ * Recurrent caches return 0 because their state does not grow with the
278
+ * sequence. Optional for stateless/training adapters that are never
279
+ * admitted or persisted. */
280
+ bytesPerToken?(): number;
281
+ /** state() returned temporary views that the caller must release. */
282
+ readonly stateNeedsDispose?: boolean;
219
283
  /** Compiled-decode trace adapters expose the RoPE offset as an int32
220
284
  * array input here; real caches leave it unset (static int path). */
221
285
  readonly ropeOffsetArr?: MlxArray;
@@ -231,9 +295,56 @@ export interface Cache {
231
295
  * speculative-decode rollback case (trim the last n ≤ γ tips right after a
232
296
  * >1 concat write); rotating caches then physically shrink the buffer tail. */
233
297
  trim(n: number, bypass?: boolean): void;
298
+ /** Speculative verify-round support for NON-trimmable recurrent caches
299
+ * (SSMCache — gated-DeltaNet conv + recurrent state). A cache exposing
300
+ * these is spec-eligible without isTrimmable(): the serve loop arms a
301
+ * round before the verify forward (the layer snapshots pre-round state —
302
+ * free, MLX arrays are immutable — and records its position-local kernel
303
+ * inputs), then resolves it: commit on full accept, or rollback(keep)
304
+ * which restores the snapshot and bit-exactly REPLAYS the first `keep`
305
+ * window tokens through the recurrence (identical arithmetic prefix ⇒
306
+ * identical state). Trimmable caches leave these unset and keep trim(). */
307
+ specRoundBegin?(): void;
308
+ specRoundCommit?(): void;
309
+ specRoundRollback?(keep: number): void;
234
310
  dispose(): void;
235
311
  }
236
312
 
313
+ export function cacheSignature(cache: Cache | undefined): string {
314
+ return cache ? cache.signature() : "unknown";
315
+ }
316
+
317
+ export interface RowBatchCache extends Cache {
318
+ readonly batchSize: number;
319
+ filterRows(keep: readonly number[]): void;
320
+ extractRow(row: number): Cache | null;
321
+ }
322
+
323
+ export function isRowBatchCache(cache: Cache): cache is RowBatchCache {
324
+ const candidate = cache as Partial<RowBatchCache>;
325
+ return typeof candidate.batchSize === "number" &&
326
+ typeof candidate.filterRows === "function" &&
327
+ typeof candidate.extractRow === "function";
328
+ }
329
+
330
+ export function isPlainKvCache(cache: Cache | undefined): cache is KVCache {
331
+ return cacheSignature(cache) === "kv:plain";
332
+ }
333
+
334
+ export function isQuantizedKvCache(cache: Cache | undefined): cache is QuantizedKVCache {
335
+ return cacheSignature(cache).startsWith("kv:quant:");
336
+ }
337
+
338
+ export function isRotatingPlainCache(cache: Cache | undefined): cache is RotatingKVCache {
339
+ return cacheSignature(cache) === "kv:rotating-plain";
340
+ }
341
+
342
+ export function isRotatingQuantizedCache(
343
+ cache: Cache | undefined,
344
+ ): cache is RotatingQuantizedKVCache {
345
+ return cacheSignature(cache).startsWith("kv:rotating-quant:");
346
+ }
347
+
237
348
  /**
238
349
  * Capability contract for cache layouts that own their dynamic-row batching.
239
350
  * The scheduler uses this for non-K/V state families (for example GLM's
@@ -296,6 +407,13 @@ export class KVCache implements Cache {
296
407
  values: MlxArray | null = null;
297
408
  offset = 0;
298
409
 
410
+ signature(): string { return "kv:plain"; }
411
+
412
+ bytesPerToken(): number {
413
+ const steps = this.keys?.shape[2] ?? 0;
414
+ return steps > 0 ? (this.keys!.nbytes + this.values!.nbytes) / steps : 0;
415
+ }
416
+
299
417
  updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
300
418
  const prev = this.offset;
301
419
  const L = k.shape[2]!;
@@ -469,6 +587,18 @@ export class QuantizedKVCache implements Cache {
469
587
 
470
588
  constructor(readonly groupSize: number, readonly bits: number) {}
471
589
 
590
+ signature(): string { return `kv:quant:${this.bits}:${this.groupSize}`; }
591
+
592
+ bytesPerToken(): number {
593
+ const steps = this.keys?.packed.shape[2] ?? 0;
594
+ if (steps === 0 || !this.keys || !this.values) return 0;
595
+ const tensors = [
596
+ this.keys.packed, this.keys.scales, this.keys.biases,
597
+ this.values.packed, this.values.scales, this.values.biases,
598
+ ];
599
+ return tensors.reduce((bytes, array) => bytes + array.nbytes, 0) / steps;
600
+ }
601
+
472
602
  updateAndFetch(): [MlxArray, MlxArray] {
473
603
  throw new Error("QuantizedKVCache: use updateAndFetchQuantized");
474
604
  }
@@ -681,6 +811,13 @@ export class RotatingKVCache implements Cache {
681
811
  this.maxSize = maxSize;
682
812
  }
683
813
 
814
+ signature(): string { return "kv:rotating-plain"; }
815
+
816
+ bytesPerToken(): number {
817
+ const steps = this.keys?.shape[2] ?? 0;
818
+ return steps > 0 ? (this.keys!.nbytes + this.values!.nbytes) / steps : 0;
819
+ }
820
+
684
821
  /** v with ring contents rearranged into temporal order (keep=0). */
685
822
  #temporalOrder(v: MlxArray): MlxArray {
686
823
  const S = v.shape[2]!;
@@ -1011,6 +1148,18 @@ export class RotatingQuantizedKVCache implements Cache {
1011
1148
  this.maxSize = maxSize;
1012
1149
  }
1013
1150
 
1151
+ signature(): string { return `kv:rotating-quant:${this.bits}:${this.groupSize}`; }
1152
+
1153
+ bytesPerToken(): number {
1154
+ const steps = this.keys?.packed.shape[2] ?? 0;
1155
+ if (steps === 0 || !this.keys || !this.values) return 0;
1156
+ const tensors = [
1157
+ this.keys.packed, this.keys.scales, this.keys.biases,
1158
+ this.values.packed, this.values.scales, this.values.biases,
1159
+ ];
1160
+ return tensors.reduce((bytes, array) => bytes + array.nbytes, 0) / steps;
1161
+ }
1162
+
1014
1163
  updateAndFetch(): [MlxArray, MlxArray] {
1015
1164
  throw new Error("RotatingQuantizedKVCache: use updateAndFetchQuantized");
1016
1165
  }
@@ -1358,7 +1507,7 @@ export class RotatingQuantizedKVCache implements Cache {
1358
1507
  /** One TurboQuant-encoded (K, V) storage tuple — the 5 arrays kv-store.ts
1359
1508
  * and toQuantized/fromKVCache pass around. Not `ops.QuantizedTensor`
1360
1509
  * (mlx's affine int4/int8 scheme): this is the rotation + Lloyd-Max
1361
- * layout (docs/design/turboquant-kv.md), asymmetric-affine for keys,
1510
+ * layout (docs/design/turboquant.md), asymmetric-affine for keys,
1362
1511
  * FWHT+Lloyd-Max for values. Field order is the kv-store.ts tensor-slot
1363
1512
  * contract — do not reorder without updating snapshotCache/loadKvCache. */
1364
1513
  export interface TurboQuantTensor {
@@ -1377,7 +1526,7 @@ export const disposeTurboQuant = (t: TurboQuantTensor): void => {
1377
1526
  t.vScales.dispose();
1378
1527
  };
1379
1528
 
1380
- /** TurboQuant KV cache — v1 (docs/design/turboquant-kv.md): dequantize-
1529
+ /** TurboQuant KV cache — v1 (docs/design/turboquant.md): dequantize-
1381
1530
  * on-fetch. Deliberately does NOT subclass KVCache/RotatingKVCache (or
1382
1531
  * QuantizedKVCache) — a novel class fails every generated-file
1383
1532
  * `#matches()` guard and every batching `instanceof` allow-list, so it
@@ -1396,6 +1545,7 @@ export const disposeTurboQuant = (t: TurboQuantTensor): void => {
1396
1545
  * a full-window dequant every step; the deferred-InvFWHT trick is a
1397
1546
  * documented non-goal until the quality gate passes. */
1398
1547
  export class TurboQuantKVCache implements Cache {
1548
+ readonly stateNeedsDispose = true;
1399
1549
  static readonly STEP = 256;
1400
1550
  /** Set only by compiled-decode trace adapters (see Cache) — TurboQuant
1401
1551
  * is not a compiled-decode participant in v1 (novel class, monolith
@@ -1406,9 +1556,22 @@ export class TurboQuantKVCache implements Cache {
1406
1556
  offset = 0;
1407
1557
  /** Validated lazily on first update, once head_dim is known. */
1408
1558
  #headDim: number | null = null;
1559
+ /** Experimental operation selection, captured once for this cache. */
1560
+ readonly #fusedDecode = process.env.MLX_BUN_TURBOQUANT_FUSED_DECODE === "1";
1409
1561
 
1410
1562
  constructor(readonly kBits: number, readonly vBits: number) {}
1411
1563
 
1564
+ signature(): string { return `kv:turboquant:${this.kBits}:${this.vBits}`; }
1565
+
1566
+ bytesPerToken(): number {
1567
+ const steps = this.#seqLen();
1568
+ if (steps === 0 || !this.#kv) return 0;
1569
+ return [
1570
+ this.#kv.kIdx, this.#kv.kScales, this.#kv.kZeros,
1571
+ this.#kv.vPacked, this.#kv.vScales,
1572
+ ].reduce((bytes, array) => bytes + array.nbytes, 0) / steps;
1573
+ }
1574
+
1412
1575
  get headDim(): number | null {
1413
1576
  return this.#headDim;
1414
1577
  }
@@ -1473,6 +1636,13 @@ export class TurboQuantKVCache implements Cache {
1473
1636
  const [B, H, , D] = a.shape as [number, number, number, number];
1474
1637
  return a.slice([0, 0, 0, 0], [B, H, upTo, D]);
1475
1638
  };
1639
+ if (this.#fusedDecode) {
1640
+ const inputs = [cut(t.kIdx), cut(t.kScales), cut(t.kZeros), cut(t.vPacked), cut(t.vScales)] as const;
1641
+ try {
1642
+ const decoded = tq.tryDecodePackedKv(inputs, this.kBits, this.vBits, headDim, deferV);
1643
+ if (decoded) return decoded;
1644
+ } finally { for (const input of inputs) input.dispose(); }
1645
+ }
1476
1646
  const kIdxCut = cut(t.kIdx);
1477
1647
  const kIdxUnpacked = this.kBits < 8 ? tq.unpackBits(kIdxCut, this.kBits, headDim) : kIdxCut;
1478
1648
  if (kIdxUnpacked !== kIdxCut) kIdxCut.dispose();
@@ -1927,9 +2097,9 @@ export function quantizedSdpaTiled(
1927
2097
  function fusedSdpaSupported(q: MlxArray, mask: Mask, groupSize: number, bits: number): boolean {
1928
2098
  // Escape hatch mirroring optiq serve's --no-fused-kv: forces the
1929
2099
  // stock unfused path everywhere. Also the A/B lever for
1930
- // scripts/bench-fused-prefill.ts. Read per call (cheap next to the
2100
+ // scripts/bench-levers.ts fused-prefill. Read per call (cheap next to the
1931
2101
  // FFI work) so tests and paired A/B harnesses can flip it in-process.
1932
- if (process.env.MLX_BUN_NO_FUSED_SDPA === "1") return false;
2102
+ if (runtimeValue("MLX_BUN_NO_FUSED_SDPA") === "1") return false;
1933
2103
  if (bits !== 4 && bits !== 8) return false;
1934
2104
  if (groupSize !== 32 && groupSize !== 64 && groupSize !== 128) return false;
1935
2105
  if (q.dtype !== Dtype.bfloat16 && q.dtype !== Dtype.float16) return false;
@@ -1971,7 +2141,7 @@ export function quantizedSdpa(
1971
2141
  * as a compile-time constant and call this for the rest. The combined
1972
2142
  * predicate is exactly fusedSdpaSupported. */
1973
2143
  export function fusedSdpaRuntimeOk(q: MlxArray, mask: Mask): boolean {
1974
- if (process.env.MLX_BUN_NO_FUSED_SDPA === "1") return false;
2144
+ if (runtimeValue("MLX_BUN_NO_FUSED_SDPA") === "1") return false;
1975
2145
  if (q.dtype !== Dtype.bfloat16 && q.dtype !== Dtype.float16) return false;
1976
2146
  if (mask.mode === "causal" || mask.mode === "") return true;
1977
2147
  if (mask.mode === "array")
@@ -23,7 +23,7 @@ import type { Weights } from "../weights";
23
23
  import { MlxArray } from "../mlx/array";
24
24
  import { Dtype } from "../mlx/ffi";
25
25
  import * as ops from "../mlx/ops";
26
- import { isExpertTracing, recordRouting } from "../expert-trace";
26
+ import { isExpertTracing, recordRouting } from "../lab/expert-trace/expert-trace";
27
27
 
28
28
  // The shared, config-independent machinery lives in gemma4-base.ts
29
29
  // (Phase B extraction); this file keeps the architecture-specific
@@ -56,7 +56,7 @@ import { Checkpoint } from "../mlx/checkpoint";
56
56
  import { flashAttention, getTrainingAttn, flashSupported } from "./flash-attention";
57
57
  import { unrotateValues as tqUnrotateValues } from "../mlx/turboquant-ops";
58
58
  import { CompiledFunction } from "../mlx/compile";
59
- import { flagOn } from "../flags";
59
+ import { flagOn } from "../runtime-config";
60
60
 
61
61
  /** Verbatim port of mlx_lm/models/gemma4_text.py:
62
62
  * `@partial(mx.compile, shapeless=True) def geglu(gate, x): return nn.gelu_approx(gate) * x`
@@ -242,7 +242,7 @@ class Attention {
242
242
  /** A number offset takes the static fast::rope; an array offset (set by
243
243
  * compiled-decode trace adapters) takes the dynamic variant — same
244
244
  * kernel, offset read from the array (bit-exactness asserted in
245
- * tests/compile.test.ts). */
245
+ * tests/unit/compile.test.ts). */
246
246
  rope(x: MlxArray, offset: number | MlxArray): MlxArray {
247
247
  return typeof offset === "number"
248
248
  ? ops.rope(x, this.headDim, this.ropeBase, offset, this.ropeFreqs)
@@ -370,7 +370,7 @@ class Attention {
370
370
  // verified route: its dQ/dK/dV vjps are exact (finite-difference checked;
371
371
  // it's what mlx-lm's tuner differentiates). The two historical bugs were
372
372
  // in THIS flash kernel (spurious dK transpose, divergent dQ barrier),
373
- // both fixed and gated by tests/flash-attention.test.ts vs the ops.sdpa
373
+ // both fixed and gated by tests/unit/flash-attention.test.ts vs the ops.sdpa
374
374
  // oracle — see flash-attention.ts's routing comment. Flash also remains
375
375
  // Gemma-guarded in the trainer (e4b >=2K SIGTRAP not yet re-validated).
376
376
  // Full layers → window 0 (pure causal); sliding layers → their window.
@@ -885,7 +885,7 @@ export class Gemma4Model {
885
885
  * which attend bidirectionally among themselves (use_bidirectional_attention:
886
886
  * "vision" — text stays causal; audio prompts pass NO bidir mask, and a
887
887
  * mixed image+audio prompt drops the image overlay too, §3.3 Q1 of
888
- * docs/design/audio-input-plan.md). `ids` ([1, L], the spliced token ids)
888
+ * docs/design/generic-model-support.md). `ids` ([1, L], the spliced token ids)
889
889
  * is required for per-layer-input models (e2b/e4b): multimodal soft-token
890
890
  * positions get token 0's per-layer embedding, and their tower content
891
891
  * enters only through the projection term (the merged hidden). Matches
@@ -1015,7 +1015,7 @@ export class Gemma4Model {
1015
1015
  return h;
1016
1016
  }
1017
1017
 
1018
- // --- Segmented-backward support (docs/design/segmented-backward-training.md
1018
+ // --- Segmented-backward support (docs/design/orpo-training.md
1019
1019
  // §4 Phase B). These are ADDITIVE — forwardLayers is untouched. The segmented
1020
1020
  // driver builds masks + per-layer inputs ONCE, then drives runLayerRange per
1021
1021
  // segment, threading the KV-shared donor K/V across segment boundaries.
@@ -4,14 +4,15 @@
4
4
  // fingerprint: 9f812d2eb461fcbe
5
5
  //
6
6
  // Branch-resolved, unrolled forward pass for this architecture
7
- // (docs/design/optimization_plan.md Phase C). Bit-exactness vs the monolith is the
8
- // generator's gate: tests/generated-parity.test.ts. The cache-signature
7
+ // (docs/archive/investigations/optimization_plan.md Phase C). Bit-exactness vs the monolith is the
8
+ // generator's gate: tests/parity/generated-parity.test.ts. The cache-signature
9
9
  // guard falls back to the monolith for anything this file wasn't
10
10
  // generated for (bf16 compat runs, vision bidir prefill).
11
11
 
12
12
  import { MlxArray } from "../../mlx/array";
13
13
  import * as ops from "../../mlx/ops";
14
14
  import {
15
+ cacheSignature,
15
16
  disposing,
16
17
  fusedSdpaRuntimeOk,
17
18
  KVCache,
@@ -202,155 +203,58 @@ function donorFullQuantG64B4KeqVScal(layer: DecoderLayer, x: MlxArray, mask: Mas
202
203
  }
203
204
 
204
205
  export class GeneratedGemma4 extends Gemma4Model {
205
- /** Per-layer cache classes must match what this file was generated
206
- * for; anything else runs the monolith path. */
206
+ /** Per-layer cache signatures must match what this file was generated for. */
207
207
  #matches(cache: Cache[]): boolean {
208
208
  return (
209
209
  cache.length === 48 &&
210
- cache[0] instanceof RotatingQuantizedKVCache &&
211
- cache[0].bits === 4 &&
212
- cache[0].groupSize === 64 &&
213
- cache[1] instanceof RotatingQuantizedKVCache &&
214
- cache[1].bits === 4 &&
215
- cache[1].groupSize === 64 &&
216
- cache[2] instanceof RotatingQuantizedKVCache &&
217
- cache[2].bits === 4 &&
218
- cache[2].groupSize === 64 &&
219
- cache[3] instanceof RotatingQuantizedKVCache &&
220
- cache[3].bits === 8 &&
221
- cache[3].groupSize === 64 &&
222
- cache[4] instanceof RotatingQuantizedKVCache &&
223
- cache[4].bits === 4 &&
224
- cache[4].groupSize === 64 &&
225
- cache[5] instanceof QuantizedKVCache &&
226
- cache[5].bits === 4 &&
227
- cache[5].groupSize === 64 &&
228
- cache[6] instanceof RotatingQuantizedKVCache &&
229
- cache[6].bits === 8 &&
230
- cache[6].groupSize === 64 &&
231
- cache[7] instanceof RotatingQuantizedKVCache &&
232
- cache[7].bits === 8 &&
233
- cache[7].groupSize === 64 &&
234
- cache[8] instanceof RotatingQuantizedKVCache &&
235
- cache[8].bits === 8 &&
236
- cache[8].groupSize === 64 &&
237
- cache[9] instanceof RotatingQuantizedKVCache &&
238
- cache[9].bits === 4 &&
239
- cache[9].groupSize === 64 &&
240
- cache[10] instanceof RotatingQuantizedKVCache &&
241
- cache[10].bits === 8 &&
242
- cache[10].groupSize === 64 &&
243
- cache[11] instanceof QuantizedKVCache &&
244
- cache[11].bits === 4 &&
245
- cache[11].groupSize === 64 &&
246
- cache[12] instanceof RotatingQuantizedKVCache &&
247
- cache[12].bits === 8 &&
248
- cache[12].groupSize === 64 &&
249
- cache[13] instanceof RotatingQuantizedKVCache &&
250
- cache[13].bits === 4 &&
251
- cache[13].groupSize === 64 &&
252
- cache[14] instanceof RotatingQuantizedKVCache &&
253
- cache[14].bits === 4 &&
254
- cache[14].groupSize === 64 &&
255
- cache[15] instanceof RotatingQuantizedKVCache &&
256
- cache[15].bits === 4 &&
257
- cache[15].groupSize === 64 &&
258
- cache[16] instanceof RotatingQuantizedKVCache &&
259
- cache[16].bits === 4 &&
260
- cache[16].groupSize === 64 &&
261
- cache[17] instanceof QuantizedKVCache &&
262
- cache[17].bits === 4 &&
263
- cache[17].groupSize === 64 &&
264
- cache[18] instanceof RotatingQuantizedKVCache &&
265
- cache[18].bits === 4 &&
266
- cache[18].groupSize === 64 &&
267
- cache[19] instanceof RotatingQuantizedKVCache &&
268
- cache[19].bits === 4 &&
269
- cache[19].groupSize === 64 &&
270
- cache[20] instanceof RotatingQuantizedKVCache &&
271
- cache[20].bits === 4 &&
272
- cache[20].groupSize === 64 &&
273
- cache[21] instanceof RotatingQuantizedKVCache &&
274
- cache[21].bits === 4 &&
275
- cache[21].groupSize === 64 &&
276
- cache[22] instanceof RotatingQuantizedKVCache &&
277
- cache[22].bits === 4 &&
278
- cache[22].groupSize === 64 &&
279
- cache[23] instanceof QuantizedKVCache &&
280
- cache[23].bits === 4 &&
281
- cache[23].groupSize === 64 &&
282
- cache[24] instanceof RotatingQuantizedKVCache &&
283
- cache[24].bits === 4 &&
284
- cache[24].groupSize === 64 &&
285
- cache[25] instanceof RotatingQuantizedKVCache &&
286
- cache[25].bits === 4 &&
287
- cache[25].groupSize === 64 &&
288
- cache[26] instanceof RotatingQuantizedKVCache &&
289
- cache[26].bits === 4 &&
290
- cache[26].groupSize === 64 &&
291
- cache[27] instanceof RotatingQuantizedKVCache &&
292
- cache[27].bits === 4 &&
293
- cache[27].groupSize === 64 &&
294
- cache[28] instanceof RotatingQuantizedKVCache &&
295
- cache[28].bits === 4 &&
296
- cache[28].groupSize === 64 &&
297
- cache[29] instanceof QuantizedKVCache &&
298
- cache[29].bits === 4 &&
299
- cache[29].groupSize === 64 &&
300
- cache[30] instanceof RotatingQuantizedKVCache &&
301
- cache[30].bits === 4 &&
302
- cache[30].groupSize === 64 &&
303
- cache[31] instanceof RotatingQuantizedKVCache &&
304
- cache[31].bits === 4 &&
305
- cache[31].groupSize === 64 &&
306
- cache[32] instanceof RotatingQuantizedKVCache &&
307
- cache[32].bits === 4 &&
308
- cache[32].groupSize === 64 &&
309
- cache[33] instanceof RotatingQuantizedKVCache &&
310
- cache[33].bits === 4 &&
311
- cache[33].groupSize === 64 &&
312
- cache[34] instanceof RotatingQuantizedKVCache &&
313
- cache[34].bits === 4 &&
314
- cache[34].groupSize === 64 &&
315
- cache[35] instanceof QuantizedKVCache &&
316
- cache[35].bits === 4 &&
317
- cache[35].groupSize === 64 &&
318
- cache[36] instanceof RotatingQuantizedKVCache &&
319
- cache[36].bits === 4 &&
320
- cache[36].groupSize === 64 &&
321
- cache[37] instanceof RotatingQuantizedKVCache &&
322
- cache[37].bits === 4 &&
323
- cache[37].groupSize === 64 &&
324
- cache[38] instanceof RotatingQuantizedKVCache &&
325
- cache[38].bits === 4 &&
326
- cache[38].groupSize === 64 &&
327
- cache[39] instanceof RotatingQuantizedKVCache &&
328
- cache[39].bits === 4 &&
329
- cache[39].groupSize === 64 &&
330
- cache[40] instanceof RotatingQuantizedKVCache &&
331
- cache[40].bits === 4 &&
332
- cache[40].groupSize === 64 &&
333
- cache[41] instanceof QuantizedKVCache &&
334
- cache[41].bits === 4 &&
335
- cache[41].groupSize === 64 &&
336
- cache[42] instanceof RotatingQuantizedKVCache &&
337
- cache[42].bits === 4 &&
338
- cache[42].groupSize === 64 &&
339
- cache[43] instanceof RotatingQuantizedKVCache &&
340
- cache[43].bits === 4 &&
341
- cache[43].groupSize === 64 &&
342
- cache[44] instanceof RotatingQuantizedKVCache &&
343
- cache[44].bits === 4 &&
344
- cache[44].groupSize === 64 &&
345
- cache[45] instanceof RotatingQuantizedKVCache &&
346
- cache[45].bits === 4 &&
347
- cache[45].groupSize === 64 &&
348
- cache[46] instanceof RotatingQuantizedKVCache &&
349
- cache[46].bits === 4 &&
350
- cache[46].groupSize === 64 &&
351
- cache[47] instanceof QuantizedKVCache &&
352
- cache[47].bits === 4 &&
353
- cache[47].groupSize === 64
210
+ cacheSignature(cache[0]) === "kv:rotating-quant:4:64" &&
211
+ cacheSignature(cache[1]) === "kv:rotating-quant:4:64" &&
212
+ cacheSignature(cache[2]) === "kv:rotating-quant:4:64" &&
213
+ cacheSignature(cache[3]) === "kv:rotating-quant:8:64" &&
214
+ cacheSignature(cache[4]) === "kv:rotating-quant:4:64" &&
215
+ cacheSignature(cache[5]) === "kv:quant:4:64" &&
216
+ cacheSignature(cache[6]) === "kv:rotating-quant:8:64" &&
217
+ cacheSignature(cache[7]) === "kv:rotating-quant:8:64" &&
218
+ cacheSignature(cache[8]) === "kv:rotating-quant:8:64" &&
219
+ cacheSignature(cache[9]) === "kv:rotating-quant:4:64" &&
220
+ cacheSignature(cache[10]) === "kv:rotating-quant:8:64" &&
221
+ cacheSignature(cache[11]) === "kv:quant:4:64" &&
222
+ cacheSignature(cache[12]) === "kv:rotating-quant:8:64" &&
223
+ cacheSignature(cache[13]) === "kv:rotating-quant:4:64" &&
224
+ cacheSignature(cache[14]) === "kv:rotating-quant:4:64" &&
225
+ cacheSignature(cache[15]) === "kv:rotating-quant:4:64" &&
226
+ cacheSignature(cache[16]) === "kv:rotating-quant:4:64" &&
227
+ cacheSignature(cache[17]) === "kv:quant:4:64" &&
228
+ cacheSignature(cache[18]) === "kv:rotating-quant:4:64" &&
229
+ cacheSignature(cache[19]) === "kv:rotating-quant:4:64" &&
230
+ cacheSignature(cache[20]) === "kv:rotating-quant:4:64" &&
231
+ cacheSignature(cache[21]) === "kv:rotating-quant:4:64" &&
232
+ cacheSignature(cache[22]) === "kv:rotating-quant:4:64" &&
233
+ cacheSignature(cache[23]) === "kv:quant:4:64" &&
234
+ cacheSignature(cache[24]) === "kv:rotating-quant:4:64" &&
235
+ cacheSignature(cache[25]) === "kv:rotating-quant:4:64" &&
236
+ cacheSignature(cache[26]) === "kv:rotating-quant:4:64" &&
237
+ cacheSignature(cache[27]) === "kv:rotating-quant:4:64" &&
238
+ cacheSignature(cache[28]) === "kv:rotating-quant:4:64" &&
239
+ cacheSignature(cache[29]) === "kv:quant:4:64" &&
240
+ cacheSignature(cache[30]) === "kv:rotating-quant:4:64" &&
241
+ cacheSignature(cache[31]) === "kv:rotating-quant:4:64" &&
242
+ cacheSignature(cache[32]) === "kv:rotating-quant:4:64" &&
243
+ cacheSignature(cache[33]) === "kv:rotating-quant:4:64" &&
244
+ cacheSignature(cache[34]) === "kv:rotating-quant:4:64" &&
245
+ cacheSignature(cache[35]) === "kv:quant:4:64" &&
246
+ cacheSignature(cache[36]) === "kv:rotating-quant:4:64" &&
247
+ cacheSignature(cache[37]) === "kv:rotating-quant:4:64" &&
248
+ cacheSignature(cache[38]) === "kv:rotating-quant:4:64" &&
249
+ cacheSignature(cache[39]) === "kv:rotating-quant:4:64" &&
250
+ cacheSignature(cache[40]) === "kv:rotating-quant:4:64" &&
251
+ cacheSignature(cache[41]) === "kv:quant:4:64" &&
252
+ cacheSignature(cache[42]) === "kv:rotating-quant:4:64" &&
253
+ cacheSignature(cache[43]) === "kv:rotating-quant:4:64" &&
254
+ cacheSignature(cache[44]) === "kv:rotating-quant:4:64" &&
255
+ cacheSignature(cache[45]) === "kv:rotating-quant:4:64" &&
256
+ cacheSignature(cache[46]) === "kv:rotating-quant:4:64" &&
257
+ cacheSignature(cache[47]) === "kv:quant:4:64"
354
258
  );
355
259
  }
356
260