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
@@ -1,3 +1,6 @@
1
+ import { type CheckpointAttachment, materializeCheckpoint, attachmentBytes, cloneAttachments, disposeAttachments } from "./backends/mlx/checkpoint-state";
2
+ import { leaseCacheState, minimumReusableOffset } from "./backends/mlx/state-views";
3
+ import { withResource, cleanupFailure, disposeResources, ownResource } from "./engine/resources";
1
4
  // Byte-capped LRU prompt cache — the RAM tier of the Layer-0 KV store.
2
5
  //
3
6
  // The mlx-lm lesson (PLAN.md): a count-capped cache of multi-GB KV
@@ -5,14 +8,12 @@
5
8
  // per entry) and evicts least-recently-used until under the cap.
6
9
  //
7
10
  // Usage pattern (single generation queue, so take/put is race-free):
8
- // const hit = cache.take(promptIds); // longest-prefix match → CLONES
11
+ // const hit = cache.take(promptIds); // longest-prefix match
9
12
  // generate(model, promptIds, { cache: hit?.caches ?? fresh })
10
13
  // cache.put([...promptIds, ...generated], caches, ns, hit?.retain);
11
- // take() is NON-CONSUMING (prefix sharing): it serves zero-copy clones and
12
- // leaves the donor entry in place — N agents sharing a system prompt all
13
- // clone from one donor, one prefill; put() supersedes same-ns
14
- // prefix-ancestors (when the new entry is trimmable) so a conversation
15
- // stays one entry, not one per turn.
14
+ // take() lends zero-copy views and leaves every RAM donor in place, including
15
+ // recurrent and method state. SSD persistence runs independently of RAM reuse.
16
+ // put() supersedes same-ns prefix-ancestors when the new entry is trimmable.
16
17
  //
17
18
  // TIERING (Layer 0, unified-engine plan): when a ColdTier is attached,
18
19
  // take() itself runs the two-tier dance — RAM peek vs cold find, restore
@@ -25,6 +26,7 @@
25
26
  // snapshot for both lanes.
26
27
 
27
28
  import type { Cache } from "./model/gemma4";
29
+ import type { PrefixCache, PrefixCacheHit } from "./contracts/prefix-cache";
28
30
  import { cloneKvCaches } from "./kv-store";
29
31
 
30
32
  /** Reference-counted release: wraps an entry's `retain` (e.g. an mmap
@@ -55,8 +57,9 @@ function makeSharedRetain(retain: (() => void) | undefined): { acquire(): () =>
55
57
 
56
58
  /** The cold (SSD) tier the RAM cache tiers over. Structural — this module
57
59
  * never imports ssd-cache (which imports us); the server binds
58
- * SsdCacheStore + the model into this shape (src/server.ts). All methods
59
- * must be failure-proof: any error degrades to "no hit"/"not stored". */
60
+ * SsdCacheStore + the model into this shape (src/server.ts). Lookup and
61
+ * restore failures return null; store returns false on failure. Operations
62
+ * that require persistence retain their donor if storing fails. */
60
63
  export interface ColdTier {
61
64
  /** Longest stored usable prefix for prompt/ns — index-only, no I/O.
62
65
  * `handle` is the tier's opaque entry token, passed back to restore. */
@@ -64,8 +67,10 @@ export interface ColdTier {
64
67
  /** Materialize a found entry as GPU-visible caches (zero-copy COW mmap;
65
68
  * pages fault in lazily). `retain` must run after the caches are
66
69
  * disposed (it unmaps the backing file). Null on any failure. */
67
- restore(handle: unknown): { tokens: number[]; caches: Cache[]; retain: () => void } | null;
68
- store(tokens: number[], caches: Cache[], ns: string): void;
70
+ restore(handle: unknown): { tokens: number[]; caches: Cache[]; attachments?: CheckpointAttachment[]; retain: () => void } | null;
71
+ /** Borrow live caches and finish persistence before returning. A false
72
+ * result prevents a required demotion. */
73
+ store(tokens: number[], caches: Cache[], ns: string, attachments?: CheckpointAttachment[]): boolean | void;
69
74
  }
70
75
 
71
76
  /** Spill sink for eviction/demotion (write-behind, 2026-07-06).
@@ -89,9 +94,7 @@ export interface SpillSink {
89
94
  spillSync?: (entry: PromptCacheEntry) => void;
90
95
  }
91
96
 
92
- export interface PromptCacheEntry {
93
- tokens: number[];
94
- caches: Cache[];
97
+ export interface PromptCacheEntry extends PrefixCacheHit<Cache[], CheckpointAttachment[]> {
95
98
  /** Namespace key — adapter spec for LoRA requests ("" = base model).
96
99
  * KV computed under one adapter must never seed another's prefill. */
97
100
  ns: string;
@@ -105,14 +108,7 @@ export interface PromptCacheEntry {
105
108
  export function cacheBytes(caches: Cache[]): number {
106
109
  let total = 0;
107
110
  for (const c of caches) {
108
- const state = c.state();
109
- for (const a of state) total += a.nbytes;
110
- // Most Cache kinds' state() returns their own live-owned arrays (safe
111
- // to just read), but TurboQuantKVCache allocates fresh trimmed slice
112
- // views per call (kv-store.ts snapshotCache/cloneKvCaches contract) —
113
- // those must be disposed here or they leak (see generate.ts
114
- // evalCacheState for the same hazard on the prefill path).
115
- if (c.stateNeedsDispose) for (const a of state) a.dispose();
111
+ total += withResource(leaseCacheState(c), (state) => state.reduce((bytes, a) => bytes + a.nbytes, 0));
116
112
  }
117
113
  return total;
118
114
  }
@@ -135,7 +131,7 @@ interface EntryRecord {
135
131
  share: { acquire(): () => void };
136
132
  }
137
133
 
138
- export class PromptCache {
134
+ export class PromptCache implements PrefixCache<Cache[], CheckpointAttachment[]> {
139
135
  readonly maxBytes: number;
140
136
  #entries: EntryRecord[] = [];
141
137
  #clock = 0;
@@ -162,6 +158,7 @@ export class PromptCache {
162
158
  spill: SpillSink | ((entry: PromptCacheEntry) => void) | null = null,
163
159
  cold: ColdTier | null = null,
164
160
  clone: (caches: Cache[]) => Cache[] = cloneKvCaches,
161
+ private readonly materialize: (caches: Cache[], attachments?: CheckpointAttachment[]) => void = materializeCheckpoint,
165
162
  ) {
166
163
  this.maxBytes = maxBytes;
167
164
  this.#spillOwned = typeof spill === "function" ? null : spill?.spillOwned ?? null;
@@ -186,24 +183,27 @@ export class PromptCache {
186
183
  // no backing mmap for retain to unmap, so nothing the clones
187
184
  // could alias goes away.
188
185
  let clones: Cache[] | null = null;
186
+ let attachments: CheckpointAttachment[] | undefined;
189
187
  try {
190
188
  clones = this.#clone(entry.caches);
191
- this.#spillOwned({ tokens: [...entry.tokens], caches: clones, ns: entry.ns });
189
+ attachments = cloneAttachments(entry.attachments);
190
+ this.#spillOwned({ tokens: [...entry.tokens], caches: clones, ns: entry.ns, attachments });
192
191
  } catch {
193
192
  // Failure degrades to no-spill; eviction/demotion never unwinds.
194
193
  if (clones) for (const c of clones) try { c.dispose(); } catch {}
194
+ try { disposeAttachments(attachments); } catch {}
195
195
  }
196
196
  } else {
197
197
  const spill =
198
198
  this.#spillSync ??
199
199
  (this.#cold
200
- ? (e: PromptCacheEntry) => this.#cold!.store(e.tokens, e.caches, e.ns)
200
+ ? (e: PromptCacheEntry) => this.#cold!.store(e.tokens, e.caches, e.ns, e.attachments)
201
201
  : null);
202
202
  if (spill) try { spill(entry); } catch {}
203
203
  }
204
204
  }
205
- for (const c of entry.caches) c.dispose();
206
- entry.retain?.();
205
+ disposeResources([...entry.caches, { dispose: () => disposeAttachments(entry.attachments) }]);
206
+ entry.retain?.(); // backing release requires successful cache disposal
207
207
  }
208
208
 
209
209
  get totalBytes(): number {
@@ -214,14 +214,36 @@ export class PromptCache {
214
214
  return this.#entries.length;
215
215
  }
216
216
 
217
+ /** Release LRU entries until the caller's live-memory check is satisfied.
218
+ * Unlike background eviction, pressure relief must finish the SSD write
219
+ * and release the buffers now, not enqueue clones that keep them alive.
220
+ * Call under the engine lock, after taking the request's reusable prefix. */
221
+ relievePressure(overBudget: () => boolean): number {
222
+ let count = 0;
223
+ while (this.#entries.length && overBudget()) {
224
+ let oldest = 0;
225
+ for (let i = 1; i < this.#entries.length; i++)
226
+ if (this.#entries[i]!.lastUsed < this.#entries[oldest]!.lastUsed) oldest = i;
227
+ const { entry } = this.#entries[oldest]!;
228
+ // Keep the entry resident if persistence throws. A failed SSD write
229
+ // must not be presented as a successful demotion.
230
+ if (this.#cold) {
231
+ if (this.#cold.store(entry.tokens, entry.caches, entry.ns, entry.attachments) === false) break;
232
+ }
233
+ else this.#spillSync?.(entry);
234
+ this.#entries.splice(oldest, 1);
235
+ this.#disposeEntry(entry, false);
236
+ this.demotions++;
237
+ count++;
238
+ }
239
+ return count;
240
+ }
241
+
217
242
  /** Find the entry with the longest usable common prefix of `prompt`
218
- * across BOTH tiers and serve it NON-CONSUMINGLY (prefix sharing,
219
- * 2026-07-05): the caller receives zero-copy CLONES trimmed to the
220
- * matched prefix (plus a ref-counted retain share); the donor entry
221
- * stays in the cache, ready for the next agent/session with the same
222
- * prefix. The caller owns the returned caches — dispose them or put()
223
- * an extended entry (which supersedes prefix-ancestors), honoring
224
- * `retain` either way.
243
+ * across BOTH tiers. Every RAM entry lends zero-copy views and retains its
244
+ * donor, including exact-boundary recurrent state and method attachments.
245
+ * The caller owns the returned views —
246
+ * dispose them or put() an extended entry, honoring `retain` either way.
225
247
  *
226
248
  * Usable prefix = common prefix capped at prompt.length - 1 (at least
227
249
  * one token must be forwarded to produce logits). Entries longer than
@@ -241,9 +263,9 @@ export class PromptCache {
241
263
  const e = this.#entries[i]!.entry;
242
264
  if (e.ns !== ns) continue;
243
265
  const p = Math.min(commonPrefixLength(e.tokens, prompt), prompt.length - 1);
244
- if (p <= bestLen) continue;
266
+ if (p <= bestLen || p < minimumReusableOffset(e.caches)) continue;
245
267
  const trimNeeded = e.tokens.length - p;
246
- if (trimNeeded > 0 && !e.caches.every((c) => c.isTrimmable())) continue;
268
+ if (trimNeeded > 0 && (!!e.attachments?.length || !e.caches.every((c) => c.isTrimmable()))) continue;
247
269
  bestLen = p;
248
270
  bestIdx = i;
249
271
  }
@@ -258,27 +280,23 @@ export class PromptCache {
258
280
  if (hit && hit.prefixLen > bestLen) {
259
281
  const loaded = this.#cold.restore(hit.handle);
260
282
  if (loaded) {
261
- const trimNeeded = loaded.tokens.length - hit.prefixLen;
262
- if (trimNeeded > 0 && !loaded.caches.every((c) => c.isTrimmable())) {
263
- // Divergent tail on an untrimmable kind: this file can't seed
264
- // the prompt — fall back to the RAM candidate. Loud: this used
265
- // to be the silent 84 s "restore-then-re-prefill" path (the
266
- // whole cold tier degrading with zero observables, 2026-07-06).
267
- console.warn(
268
- `[prompt-cache] cold entry unusable: ${loaded.tokens.length} tokens, ` +
269
- `needs trim ${trimNeeded} but untrimmable (wrapped ring/SSM) — re-prefilling`,
270
- );
271
- for (const c of loaded.caches) c.dispose();
272
- loaded.retain();
273
- } else {
274
- if (trimNeeded > 0) for (const c of loaded.caches) c.trim(trimNeeded);
275
- return {
276
- tokens: loaded.tokens.slice(0, hit.prefixLen),
277
- caches: loaded.caches,
278
- ns,
279
- retain: loaded.retain,
280
- };
281
- }
283
+ const owner = ownResource(loaded, (entry) =>
284
+ this.#disposeEntry({ ...entry, ns }, false));
285
+ const result = withResource(owner, (entry) => {
286
+ const trimNeeded = entry.tokens.length - hit.prefixLen;
287
+ if (hit.prefixLen < minimumReusableOffset(entry.caches)) return null;
288
+ if (trimNeeded > 0 && (!!entry.attachments?.length || !entry.caches.every((cache) => cache.isTrimmable()))) {
289
+ console.warn(
290
+ `[prompt-cache] cold entry unusable: ${entry.tokens.length} tokens, ` +
291
+ `needs trim ${trimNeeded} but untrimmable (wrapped ring/SSM) — re-prefilling`,
292
+ );
293
+ return null;
294
+ }
295
+ if (trimNeeded > 0) for (const cache of entry.caches) cache.trim(trimNeeded);
296
+ const tokens = entry.tokens.slice(0, hit.prefixLen);
297
+ return { ...owner.transfer(), tokens, ns };
298
+ });
299
+ if (result) return result;
282
300
  }
283
301
  }
284
302
  }
@@ -296,12 +314,22 @@ export class PromptCache {
296
314
  const rec = this.#entries[bestIdx]!;
297
315
  rec.lastUsed = ++this.#clock;
298
316
  rec.lastUsedMs = Date.now();
317
+ // Lend immutable views for every backend state. RAM retention and SSD
318
+ // durability remain cache responsibilities while the caller extends its
319
+ // own views. This keeps synchronous persistence out of a RAM hit.
299
320
  const clones = this.#clone(rec.entry.caches);
321
+ let attachments: CheckpointAttachment[] | undefined;
300
322
  const trimNeeded = rec.entry.tokens.length - bestLen;
301
- if (trimNeeded > 0) for (const c of clones) c.trim(trimNeeded);
323
+ try {
324
+ attachments = cloneAttachments(rec.entry.attachments);
325
+ if (trimNeeded > 0) for (const c of clones) c.trim(trimNeeded);
326
+ } catch (error) {
327
+ cleanupFailure(error, () => disposeResources([...clones, { dispose: () => disposeAttachments(attachments) }]));
328
+ }
302
329
  return {
303
330
  tokens: rec.entry.tokens.slice(0, bestLen),
304
331
  caches: clones,
332
+ attachments,
305
333
  ns,
306
334
  retain: rec.share.acquire(),
307
335
  };
@@ -314,9 +342,9 @@ export class PromptCache {
314
342
  for (const { entry: e } of this.#entries) {
315
343
  if (e.ns !== ns) continue;
316
344
  const p = Math.min(commonPrefixLength(e.tokens, prompt), prompt.length - 1);
317
- if (p <= best) continue;
345
+ if (p <= best || p < minimumReusableOffset(e.caches)) continue;
318
346
  const trimNeeded = e.tokens.length - p; // same usability rule as take()
319
- if (trimNeeded > 0 && !e.caches.every((c) => c.isTrimmable())) continue;
347
+ if (trimNeeded > 0 && (!!e.attachments?.length || !e.caches.every((c) => c.isTrimmable()))) continue;
320
348
  best = p;
321
349
  }
322
350
  return best;
@@ -336,11 +364,23 @@ export class PromptCache {
336
364
  /** Insert (or reinsert) an entry; evicts LRU entries over the byte cap
337
365
  * (spilling each to the cold tier first, when one is attached). If the
338
366
  * entry itself exceeds the cap it is spilled + disposed, not stored. */
339
- put(tokens: number[], caches: Cache[], ns = "", retain?: () => void): void {
340
- const bytes = cacheBytes(caches);
341
- const entry: PromptCacheEntry = { tokens, caches, ns, retain };
367
+ put(tokens: number[], caches: Cache[], ns = "", retain?: () => void, attachments?: CheckpointAttachment[]): void {
368
+ // All cache-provided validation runs before ownership is adopted.
369
+ const bytes = cacheBytes(caches) + attachmentBytes(attachments);
370
+ const trimmable = !attachments?.length && caches.every((cache) => cache.isTrimmable());
371
+ // Storage takes resolved snapshots, independently of their producer.
372
+ this.materialize(caches, attachments);
373
+ const discard = (entry: PromptCacheEntry, spill: boolean) => {
374
+ try { this.#disposeEntry(entry, spill); }
375
+ catch (error) {
376
+ // The new entry is already owned here. Throwing back to its previous
377
+ // owner would invite disposal of state still held by this store.
378
+ console.warn(`[prompt-cache] entry cleanup failed: ${error}`);
379
+ }
380
+ };
381
+ const entry: PromptCacheEntry = { tokens, caches, ns, retain, attachments };
342
382
  if (bytes > this.maxBytes) {
343
- this.#disposeEntry(entry, true);
383
+ discard(entry, true);
344
384
  return;
345
385
  }
346
386
  // The donor's retain becomes ref-counted so take()'s clones can hold
@@ -359,7 +399,7 @@ export class PromptCache {
359
399
  if (old.entry.tokens.length !== tokens.length) continue;
360
400
  if (commonPrefixLength(old.entry.tokens, tokens) !== tokens.length) continue;
361
401
  this.#entries = this.#entries.filter((r) => r !== old);
362
- this.#disposeEntry(old.entry, false);
402
+ discard(old.entry, false);
363
403
  }
364
404
  // SUPERSEDE strict prefix-ancestors (the SSD store's rule, brought to
365
405
  // RAM — prefix sharing would otherwise grow an entry per turn): same-ns
@@ -370,13 +410,13 @@ export class PromptCache {
370
410
  // can only serve exact-length matches, so shorter ancestors — e.g.
371
411
  // the prompt-boundary snapshot that makes drifted multi-turn agents
372
412
  // hit — must survive.
373
- if (caches.every((c) => c.isTrimmable())) {
413
+ if (trimmable) {
374
414
  for (const old of [...this.#entries]) {
375
415
  if (old === rec || old.entry.ns !== ns) continue;
376
- if (old.entry.tokens.length >= tokens.length) continue;
416
+ if (old.entry.tokens.length >= tokens.length || old.entry.tokens.length < minimumReusableOffset(caches)) continue;
377
417
  if (commonPrefixLength(old.entry.tokens, tokens) !== old.entry.tokens.length) continue;
378
418
  this.#entries = this.#entries.filter((r) => r !== old);
379
- this.#disposeEntry(old.entry, false);
419
+ discard(old.entry, false);
380
420
  }
381
421
  }
382
422
  while (this.totalBytes > this.maxBytes && this.#entries.length > 1) {
@@ -384,7 +424,7 @@ export class PromptCache {
384
424
  for (let i = 1; i < this.#entries.length; i++)
385
425
  if (this.#entries[i]!.lastUsed < this.#entries[lruIdx]!.lastUsed) lruIdx = i;
386
426
  const [evicted] = this.#entries.splice(lruIdx, 1);
387
- this.#disposeEntry(evicted!.entry, true);
427
+ discard(evicted!.entry, true);
388
428
  }
389
429
  try { this.onPut?.(tokens, ns); } catch {}
390
430
  }
@@ -413,7 +453,8 @@ export class PromptCache {
413
453
  }
414
454
 
415
455
  clear(): void {
416
- for (const e of this.#entries) this.#disposeEntry(e.entry, false);
456
+ const entries = this.#entries;
417
457
  this.#entries = [];
458
+ disposeResources(entries.map(({ entry }) => ({ dispose: () => this.#disposeEntry(entry, false) })));
418
459
  }
419
460
  }
@@ -11,7 +11,7 @@
11
11
  // - NaN-sensitivity handling (treat as maximally sensitive)
12
12
  // - post-greedy block-run guard
13
13
  //
14
- // Verified bit-for-bit against the Python via tests/quantize-allocator.test.ts.
14
+ // Verified bit-for-bit against the Python via tests/parity/quantize-allocator.test.ts.
15
15
  //
16
16
  // The latency-aware variants (`optimize_latency_aware`,
17
17
  // `optimize_for_latency_budget`) are intentionally NOT ported — they pull in
@@ -13,7 +13,9 @@ import { existsSync } from "node:fs";
13
13
  import { join } from "node:path";
14
14
 
15
15
  /** A per-module quantization override. `false` means "left unquantized". */
16
- export type PerLayerEntry = { bits: number; groupSize: number } | false;
16
+ export type PerLayerEntry =
17
+ | { bits: number; groupSize: number; mode?: string; trellis?: { L: number; code: string; axis: 0 | 1 } }
18
+ | false;
17
19
 
18
20
  /** The default quantization definition for the model. */
19
21
  export interface QuantDef {
@@ -28,7 +30,7 @@ export interface QuantizationBlock {
28
30
  bits: number;
29
31
  mode: string;
30
32
  // plus per-module entries: { [modulePath]: {bits, group_size} | false }
31
- [modulePath: string]: number | string | { bits: number; group_size: number } | false;
33
+ [modulePath: string]: number | string | { bits: number; group_size: number; mode?: string; trellis?: { L: number; code: string; axis: 0 | 1 } } | false;
32
34
  }
33
35
 
34
36
  /**
@@ -47,7 +49,12 @@ export function buildQuantizationBlock(
47
49
  mode: def.mode ?? "affine",
48
50
  };
49
51
  for (const [path, entry] of perLayer) {
50
- block[path] = entry === false ? false : { bits: entry.bits, group_size: entry.groupSize };
52
+ if (entry === false) { block[path] = false; continue; }
53
+ const v: { bits: number; group_size: number; mode?: string; trellis?: { L: number; code: string; axis: 0 | 1 } } =
54
+ { bits: entry.bits, group_size: entry.groupSize };
55
+ if (entry.mode) v.mode = entry.mode;
56
+ if (entry.trellis) v.trellis = entry.trellis;
57
+ block[path] = v;
51
58
  }
52
59
  return block;
53
60
  }
@@ -3,7 +3,7 @@
3
3
  // Folds an orthogonal rotation offline into producer/consumer weight pairs so
4
4
  // weights are quantized in a basis where outlier channels are smeared into
5
5
  // near-Gaussian marginals. Recipe, fold table, and the decided deviations from
6
- // the QuaRot/SpinQuant references live in docs/design/turboquant-weights.md —
6
+ // the QuaRot/SpinQuant references live in docs/design/turboquant.md —
7
7
  // notably: γ-fold FIRST (R1 only commutes with gain-free RMSNorm), SpinQuant's
8
8
  // fully-offline per-head R2 (NOT QuaRot's, which needs a runtime op), NO R4
9
9
  // half-fold on down_proj's input, NO embedding mean-centering (not an exact
@@ -47,7 +47,7 @@ function assertPow2(n: number, what: string): void {
47
47
  if (n < 2 || (n & (n - 1)) !== 0)
48
48
  throw new Error(
49
49
  `rotation fold: ${what}=${n} is not a power of two — the Kronecker ` +
50
- `Hadamard path is not implemented (docs/design/turboquant-weights.md)`,
50
+ `Hadamard path is not implemented (docs/design/turboquant.md)`,
51
51
  );
52
52
  }
53
53
 
@@ -323,7 +323,7 @@ export function foldLlamaWeights(
323
323
  // elementwise in head space) does not commute with a per-head rotation, so R2
324
324
  // is architecturally off for this family — recorded in the design doc.
325
325
  //
326
- // Residual corridors (docs/design/turboquant-weights.md, W1 map):
326
+ // Residual corridors (docs/design/turboquant.md, W1 map):
327
327
  // readers (@R1 input dim, γ premultiplied): q/k/v_proj,
328
328
  // linear_attn.in_proj_{qkv,z,b,a}, mlp.gate/up_proj, lm_head
329
329
  // writers (R1ᵀ output dim): self_attn.o_proj, linear_attn.out_proj,
@@ -370,7 +370,7 @@ export interface QwenFoldPlan {
370
370
  * FoldOp — pure name analysis, no arrays. R1-ONLY (+γ): the attention output
371
371
  * gate (`o_proj(out · σ(gate))`, elementwise in head space) does not commute
372
372
  * with a per-head rotation, so R2 is architecturally off for this family.
373
- * Corridor map: docs/design/turboquant-weights.md §W1.
373
+ * Corridor map: docs/design/turboquant.md §W1.
374
374
  */
375
375
  export function planQwen35Fold(names: readonly string[], prefix = "language_model."): QwenFoldPlan {
376
376
  const P = prefix;