mlx-bun 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/README.md +71 -588
  2. package/docs/README.md +94 -0
  3. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  4. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  5. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  6. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  7. package/docs/archive/investigations/openjarvis-fit.md +198 -0
  8. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  9. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  10. package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
  11. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  12. package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
  13. package/docs/design/batching.md +1841 -0
  14. package/docs/design/decode-speed-program.md +2346 -169
  15. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  16. package/docs/design/generic-model-support.md +655 -334
  17. package/docs/design/kv-cache.md +824 -0
  18. package/docs/design/orpo-training.md +673 -1239
  19. package/docs/design/speculative-decoding.md +1990 -0
  20. package/docs/design/turboquant.md +2212 -0
  21. package/docs/design/unified-engine-frontier-plan.md +1833 -727
  22. package/docs/design/web-chat-redesign.md +666 -1083
  23. package/docs/planning/PRODUCT_ROADMAP.md +50 -1
  24. package/docs/planning/release-notes-v0.4.0.md +45 -0
  25. package/docs/planning/video-series.md +2 -2
  26. package/docs/reference/benchmarks.md +3613 -0
  27. package/docs/reference/cli.md +434 -160
  28. package/docs/reference/distribution.md +328 -182
  29. package/docs/reference/environment.md +398 -0
  30. package/docs/reference/glossary.md +39 -0
  31. package/docs/reference/library-api.md +566 -168
  32. package/docs/reference/memory.md +227 -64
  33. package/docs/reference/models.md +113 -6
  34. package/docs/reference/server-api.md +944 -429
  35. package/docs/reference/server-config.md +740 -338
  36. package/docs/reference/training.md +393 -254
  37. package/docs/reference/troubleshooting.md +158 -0
  38. package/package.json +9 -4
  39. package/src/audio/decode.ts +2 -2
  40. package/src/audio/features.ts +2 -2
  41. package/src/backends/mlx/assistant-target.ts +46 -0
  42. package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
  43. package/src/backends/mlx/autoregressive.ts +108 -0
  44. package/src/backends/mlx/batch-group.ts +1790 -0
  45. package/src/backends/mlx/cache-attachment.ts +67 -0
  46. package/src/backends/mlx/cache-layout.ts +31 -0
  47. package/src/backends/mlx/checkpoint-state.ts +53 -0
  48. package/src/backends/mlx/continuation-persistence.ts +106 -0
  49. package/src/backends/mlx/continuation-request.ts +43 -0
  50. package/src/backends/mlx/continuation.ts +77 -0
  51. package/src/backends/mlx/diffusion.ts +39 -0
  52. package/src/backends/mlx/draft-target.ts +32 -0
  53. package/src/backends/mlx/evaluation.ts +105 -0
  54. package/src/backends/mlx/fill-append.ts +45 -0
  55. package/src/backends/mlx/full-kv-row-append.ts +32 -0
  56. package/src/backends/mlx/full-kv-row-donor.ts +54 -0
  57. package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
  58. package/src/backends/mlx/gateway-binding.ts +130 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/kv-codec.ts +9 -0
  61. package/src/backends/mlx/kv-maintenance.ts +133 -0
  62. package/src/backends/mlx/kv-tensor-rows.ts +212 -0
  63. package/src/backends/mlx/memory-client.ts +189 -0
  64. package/src/backends/mlx/methods.ts +90 -0
  65. package/src/backends/mlx/model-prompt.ts +164 -0
  66. package/src/backends/mlx/model-serving.ts +79 -0
  67. package/src/backends/mlx/prefill-cohort.ts +89 -0
  68. package/src/backends/mlx/prefill-rows.ts +200 -0
  69. package/src/backends/mlx/prefill.ts +33 -0
  70. package/src/backends/mlx/projected-context-rows.ts +72 -0
  71. package/src/backends/mlx/request-policy.ts +20 -0
  72. package/src/backends/mlx/request-state-policy.ts +41 -0
  73. package/src/backends/mlx/rollback.ts +89 -0
  74. package/src/backends/mlx/row-sampling.ts +49 -0
  75. package/src/backends/mlx/serial-executor.ts +242 -0
  76. package/src/backends/mlx/speculative-group.ts +359 -0
  77. package/src/backends/mlx/speculative-round.ts +161 -0
  78. package/src/backends/mlx/speculative.ts +114 -0
  79. package/src/backends/mlx/state-rows.ts +104 -0
  80. package/src/backends/mlx/state-views.ts +46 -0
  81. package/src/backends/mlx/target-layout-capability.ts +35 -0
  82. package/src/backends/mlx/text-engine.ts +73 -0
  83. package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
  84. package/src/cli.ts +66 -58
  85. package/src/client.ts +66 -0
  86. package/src/config.ts +21 -4
  87. package/src/contracts/completion.ts +16 -0
  88. package/src/contracts/execution.ts +60 -0
  89. package/src/contracts/generation.ts +103 -0
  90. package/src/contracts/host.ts +7 -0
  91. package/src/contracts/jobs.ts +66 -0
  92. package/src/contracts/pi-provider.ts +30 -0
  93. package/src/contracts/pi.ts +259 -0
  94. package/src/contracts/prefix-cache.ts +23 -0
  95. package/src/contracts/resources.ts +25 -0
  96. package/src/contracts/sampling.ts +23 -0
  97. package/src/contracts/scheduling.ts +45 -0
  98. package/src/contracts/tsconfig.json +14 -0
  99. package/src/diffusion/diffusion-generate.ts +218 -153
  100. package/src/embed.ts +1 -1
  101. package/src/engine/admission.ts +59 -0
  102. package/src/engine/cancellation.ts +38 -0
  103. package/src/engine/engine.ts +56 -0
  104. package/src/engine/execution-coordinator.ts +70 -0
  105. package/src/engine/execution-plan.ts +53 -0
  106. package/src/engine/resources.ts +53 -0
  107. package/src/engine/scheduler.ts +72 -0
  108. package/src/engine/session.ts +247 -0
  109. package/src/eval/README.md +44 -1
  110. package/src/eval/kl.ts +236 -3
  111. package/src/eval/reference-logits.ts +207 -0
  112. package/src/eval/runner.ts +8 -96
  113. package/src/fill/echo-index.ts +188 -0
  114. package/src/fill/fill-session.ts +452 -0
  115. package/src/fill/proposal.ts +68 -0
  116. package/src/fill/schema-rows.ts +506 -0
  117. package/src/fill/tool-boundary.ts +103 -0
  118. package/src/fit.ts +30 -16
  119. package/src/generate.ts +709 -417
  120. package/src/grammar.ts +12 -7
  121. package/src/harness-pi.ts +14 -33
  122. package/src/hub-rest.ts +4 -4
  123. package/src/index.ts +7 -0
  124. package/src/inference/denoising.ts +17 -0
  125. package/src/inference/draft-acceptance.ts +41 -0
  126. package/src/inference/draft-output.ts +49 -0
  127. package/src/inference/graph.ts +33 -0
  128. package/src/inference/prefill.ts +39 -0
  129. package/src/inference/rollback.ts +7 -0
  130. package/src/jobs/db.ts +4 -0
  131. package/src/jobs/index.ts +2 -0
  132. package/src/jobs/job-entry.ts +12 -12
  133. package/src/jobs/runner.ts +98 -13
  134. package/src/jobs/task-client.ts +19 -0
  135. package/src/jobs/types.ts +2 -58
  136. package/src/kv-scheme.ts +70 -12
  137. package/src/kv-store.ts +177 -63
  138. package/src/lab/README.md +18 -0
  139. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  140. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  141. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +5 -5
  142. package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
  143. package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
  144. package/src/library.ts +40 -0
  145. package/src/lora.ts +18 -0
  146. package/src/media-fetch.ts +1 -1
  147. package/src/memory/article.ts +1 -1
  148. package/src/memory/chunk.ts +1 -1
  149. package/src/memory/model.ts +30 -169
  150. package/src/memory/prompts.ts +1 -1
  151. package/src/memory/rest.ts +1 -1
  152. package/src/memory/schedule.ts +1 -1
  153. package/src/memory/stages.ts +4 -1
  154. package/src/memory/vault.ts +1 -3
  155. package/src/mlx/array.ts +11 -11
  156. package/src/mlx/compile.ts +12 -2
  157. package/src/mlx/ffi.ts +58 -11
  158. package/src/mlx/materialize.ts +23 -0
  159. package/src/mlx/metal-kernel.ts +10 -11
  160. package/src/mlx/ops.ts +33 -13
  161. package/src/mlx/quantized-rows.ts +36 -0
  162. package/src/mlx/token-bitmask.ts +52 -0
  163. package/src/mlx/turboquant-kv-decode.ts +82 -0
  164. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  165. package/src/mlx/turboquant-ops.ts +33 -3
  166. package/src/mlx/turboquant-tables.ts +2 -2
  167. package/src/model/artifact-identity.ts +73 -0
  168. package/src/model/batched-kv.ts +235 -0
  169. package/src/model/batched-mask.ts +20 -6
  170. package/src/model/batched-quant.ts +9 -3
  171. package/src/model/batched-quantized-kv.ts +144 -0
  172. package/src/model/batched-rotating-quant.ts +78 -17
  173. package/src/model/batched-rotating-state.ts +76 -0
  174. package/src/model/batched-rotating.ts +65 -23
  175. package/src/model/batched-row-storage.ts +52 -0
  176. package/src/model/batched-ssm.ts +52 -0
  177. package/src/model/batched-turboquant-kv.ts +93 -0
  178. package/src/model/compiled-decode.ts +8 -2
  179. package/src/model/decoded-kv-donor.ts +12 -0
  180. package/src/model/delayed-quantized-kv.ts +72 -0
  181. package/src/model/delayed-rotating-quantized-kv.ts +93 -0
  182. package/src/model/delayed-turboquant-kv.ts +55 -0
  183. package/src/model/diffusion-gemma.ts +8 -8
  184. package/src/model/factory.ts +76 -33
  185. package/src/model/fingerprint.ts +1 -1
  186. package/src/model/flash-attention.ts +3 -3
  187. package/src/model/full-prefill-padding.ts +56 -0
  188. package/src/model/full-prefill-row.ts +105 -0
  189. package/src/model/gemma4-base.ts +179 -80
  190. package/src/model/gemma4.ts +40 -32
  191. package/src/model/generated/gemma4-12b.ts +6 -3
  192. package/src/model/generated/gemma4-26b.ts +6 -3
  193. package/src/model/generated/gemma4-e4b.ts +6 -3
  194. package/src/model/glm52-cache.ts +80 -4
  195. package/src/model/glm52-dsa.ts +13 -9
  196. package/src/model/glm52-memory.ts +1 -1
  197. package/src/model/glm52-mla.ts +12 -6
  198. package/src/model/glm52.ts +19 -40
  199. package/src/model/implementation.ts +69 -0
  200. package/src/model/kv-attention-view.ts +67 -0
  201. package/src/model/minicpm5.ts +17 -15
  202. package/src/model/profile.ts +12 -2
  203. package/src/model/qwen-append.ts +12 -0
  204. package/src/model/qwen-conv.ts +52 -0
  205. package/src/model/qwen3-delta-state.ts +74 -0
  206. package/src/model/qwen3-delta.ts +59 -36
  207. package/src/model/qwen3_5-checkpoint.ts +164 -0
  208. package/src/model/qwen3_5.ts +202 -78
  209. package/src/model/rotating-kv-donor.ts +35 -0
  210. package/src/model/rotating-kv-layout.ts +262 -0
  211. package/src/model/rotating-row-transaction.ts +35 -0
  212. package/src/model/speculative-rotating-kv.ts +101 -0
  213. package/src/model/ssm-prefill-padding.ts +39 -0
  214. package/src/model/support.ts +1 -1
  215. package/src/model/trellis-balanced-scatter.ts +51 -0
  216. package/src/model/trellis-linear.ts +672 -0
  217. package/src/model/trellis-shared-m.ts +151 -0
  218. package/src/model/trellis-shared-scatter.ts +144 -0
  219. package/src/model/trellis-splitk-prefill.ts +158 -0
  220. package/src/model/trellis-tiled-prefill.ts +136 -0
  221. package/src/model/trellis-vector-expand.ts +62 -0
  222. package/src/model/trellis-wide-prefill.ts +94 -0
  223. package/src/model/turboquant-codec.ts +83 -0
  224. package/src/model/universal/dense.ts +15 -14
  225. package/src/model/universal/modules.ts +8 -1
  226. package/src/native-pack.ts +6 -5
  227. package/src/pi-provider.ts +6 -64
  228. package/src/pi-web.ts +8 -315
  229. package/src/preflight.ts +31 -15
  230. package/src/prompt-cache.ts +110 -69
  231. package/src/quantize/allocator.ts +1 -1
  232. package/src/quantize/config-writer.ts +10 -3
  233. package/src/quantize/rotate.ts +4 -4
  234. package/src/quantize/trellis.ts +586 -0
  235. package/src/responses.ts +28 -1
  236. package/src/runtime-config.ts +18 -4
  237. package/src/sampler.ts +40 -29
  238. package/src/serve/batch-scheduler.ts +8 -1671
  239. package/src/serve/chat-request.ts +391 -0
  240. package/src/serve/chat-stage.ts +195 -0
  241. package/src/serve/checkpoint-identity.ts +64 -0
  242. package/src/serve/completion-executor.ts +15 -7
  243. package/src/serve/discovery-routes.ts +12 -13
  244. package/src/serve/generation-gateway.ts +183 -213
  245. package/src/serve/http.ts +159 -0
  246. package/src/serve/inference-request.ts +79 -0
  247. package/src/serve/isolate.ts +297 -105
  248. package/src/serve/lab-routes.ts +3 -0
  249. package/src/serve/lane-registry.ts +2 -1
  250. package/src/serve/model-admin-routes.ts +7 -5
  251. package/src/serve/model-binding.ts +43 -0
  252. package/src/serve/model-host.ts +511 -0
  253. package/src/serve/openai-wire.ts +103 -0
  254. package/src/serve/parent-application.ts +56 -0
  255. package/src/serve/pipeline.ts +33 -0
  256. package/src/serve/preparation.ts +33 -0
  257. package/src/serve/request-plan.ts +23 -18
  258. package/src/serve/request-prep.ts +344 -0
  259. package/src/serve/response-lease.ts +24 -0
  260. package/src/serve/responses-client.ts +69 -0
  261. package/src/serve/session-completion-engine.ts +110 -0
  262. package/src/serve/session-search.ts +1 -1
  263. package/src/serve/static-routes.ts +5 -5
  264. package/src/serve/text-completion-stage.ts +104 -0
  265. package/src/serve/token-streams.ts +519 -0
  266. package/src/server.ts +335 -2711
  267. package/src/spec/assistant-rows.ts +92 -0
  268. package/src/spec/assistant-source.ts +31 -55
  269. package/src/spec/cache-identity.ts +22 -0
  270. package/src/spec/deepspec-rows.ts +29 -0
  271. package/src/spec/deepspec-source.ts +16 -14
  272. package/src/spec/dflash-source.ts +36 -12
  273. package/src/spec/drafter.ts +153 -142
  274. package/src/spec/dspark/ab-stats.ts +3 -3
  275. package/src/spec/dspark/calibration.ts +2 -2
  276. package/src/spec/dspark/deepspec-module.ts +97 -122
  277. package/src/spec/dspark/generate-dflash.ts +2 -2
  278. package/src/spec/dspark/generate.ts +2 -2
  279. package/src/spec/dspark/loader.ts +1 -1
  280. package/src/spec/dspark/module-dflash.ts +129 -172
  281. package/src/spec/dspark/module.ts +3 -3
  282. package/src/spec/dspark/quantize-drafter.ts +1 -1
  283. package/src/spec/generate.ts +1 -1
  284. package/src/spec/glm52-mtp-graph.ts +29 -0
  285. package/src/spec/glm52-mtp-rows.ts +132 -0
  286. package/src/spec/glm52-mtp-source.ts +54 -137
  287. package/src/spec/glm52-mtp-state.ts +33 -0
  288. package/src/spec/ngram-source.ts +93 -21
  289. package/src/spec/projected-draft-rows.ts +73 -0
  290. package/src/spec/qwen-mtp-module.ts +171 -0
  291. package/src/spec/qwen-mtp-rows.ts +219 -0
  292. package/src/spec/qwen-mtp-source.ts +147 -195
  293. package/src/spec/qwen-mtp-state.ts +30 -0
  294. package/src/spec/serve-loop.ts +201 -201
  295. package/src/spec/source.ts +110 -13
  296. package/src/spec/two-model-rows.ts +61 -0
  297. package/src/spec/two-model.ts +44 -102
  298. package/src/ssd-cache.ts +99 -19
  299. package/src/ssd-durability.ts +36 -20
  300. package/src/tool-call.ts +51 -14
  301. package/src/train/flash-cce.ts +2 -2
  302. package/src/train/forward.ts +6 -0
  303. package/src/train/loss.ts +1 -1
  304. package/src/train/prefix-shared.ts +5 -1
  305. package/src/train/segmented.ts +5 -3
  306. package/src/train/trainer.ts +6 -6
  307. package/src/vision/prompt.ts +1 -1
  308. package/src/vision/qwen3vl-tower.ts +52 -10
  309. package/src/web/app.html +1 -1
  310. package/src/web/app.js +62 -60
  311. package/src/web/src/adapters-panel.ts +3 -3
  312. package/src/web/src/assistant.ts +2 -36
  313. package/src/web/src/chat.ts +4 -4
  314. package/src/web/src/composer.ts +4 -4
  315. package/src/web/src/hub.ts +1 -1
  316. package/src/web/src/markdown.ts +0 -0
  317. package/src/web/src/memory-panel.ts +1 -1
  318. package/src/web/src/model-picker.ts +1 -1
  319. package/src/web/src/palette.ts +1 -1
  320. package/src/web/src/protocol.ts +3 -39
  321. package/src/web/src/sessions.ts +1 -1
  322. package/src/web/src/ui-catalog.ts +4 -18
  323. package/src/web-assets.ts +47 -0
  324. package/src/weights.ts +55 -9
  325. package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
  326. package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
  327. package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
  328. package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
  329. package/docs/archive/investigations/hlg-ab.html +0 -34
  330. package/docs/archive/investigations/hlg-explorer.html +0 -238
  331. package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
  332. package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
  333. package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
  334. package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
  335. package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
  336. package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
  337. package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
  338. package/docs/archive/investigations/hlg-report.html +0 -262
  339. package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
  340. package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  341. package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
  342. package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
  343. package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
  344. package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
  345. package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
  346. package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
  347. package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
  348. package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
  349. package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  350. package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
  351. package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
  352. package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
  353. package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  354. package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  355. package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  356. package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  357. package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  358. package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  359. package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  360. package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
  361. package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
  362. package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
  363. package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
  364. package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
  365. package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  366. package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
  367. package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
  368. package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
  369. package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
  370. package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
  371. package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  372. package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
  373. package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  374. package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  375. package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  376. package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  377. package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  378. package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  379. package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
  380. package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  381. package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
  382. package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  383. package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  384. package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  385. package/docs/archive/mlx-bun-lab-report.html +0 -275
  386. package/docs/archive/wwdc-mlx-bun.html +0 -848
  387. package/docs/design/adapters-end-to-end.md +0 -205
  388. package/docs/design/batching-perf-path.md +0 -255
  389. package/docs/design/batching-v2-plan.md +0 -529
  390. package/docs/design/bucketing-stage.md +0 -197
  391. package/docs/design/compat-cli-surface-design.md +0 -230
  392. package/docs/design/docs-reorg-plan.md +0 -165
  393. package/docs/design/dspark-serving-program.md +0 -371
  394. package/docs/design/dspark-speculative-decoding.md +0 -318
  395. package/docs/design/grammar-spec-batching-integration.md +0 -301
  396. package/docs/design/memory-inference-path.md +0 -422
  397. package/docs/design/memory-synthesis.md +0 -287
  398. package/docs/design/memory-system.md +0 -237
  399. package/docs/design/mlx-lm-serving-execution-seam.md +0 -81
  400. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  401. package/docs/design/omlx-adoption-map.md +0 -98
  402. package/docs/design/orpo-dynamic-lambda.md +0 -220
  403. package/docs/design/orpo-future-enhancements.md +0 -340
  404. package/docs/design/paged-kv-cache.md +0 -214
  405. package/docs/design/parallel-slots.md +0 -567
  406. package/docs/design/parity-tier-dag.md +0 -161
  407. package/docs/design/repo-cleanup-plan.md +0 -231
  408. package/docs/design/runtime-isolation.md +0 -263
  409. package/docs/design/segmented-backward-training.md +0 -543
  410. package/docs/design/spec-decode-larger-targets.md +0 -229
  411. package/docs/design/ssd-kv-cold-tier.md +0 -415
  412. package/docs/design/structured-output.md +0 -484
  413. package/docs/design/tauri-desktop-app.md +0 -127
  414. package/docs/design/the-dreaming-master-plan.md +0 -445
  415. package/docs/design/turboquant-kv.md +0 -235
  416. package/docs/design/turboquant-weights.md +0 -467
  417. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  418. package/docs/design/web-chat-beat-matrix.md +0 -315
  419. package/docs/design/write-pipeline-entity.md +0 -468
  420. package/docs/planning/IDEAS.md +0 -69
  421. package/docs/reference/embedding.md +0 -197
  422. package/docs/reference/features-matrix.md +0 -101
  423. package/docs/reference/orpo-quickstart.md +0 -135
  424. package/src/flags.ts +0 -11
  425. /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
  426. /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
  427. /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
  428. /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
  429. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  430. /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
  431. /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
  432. /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
  433. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -0,0 +1,3613 @@
1
+ # mlx-bun benchmark results (curated)
2
+
3
+ The durable, hand-maintained benchmark record. Raw per-run files
4
+ (`benchmarks-h2h-<date>-<machine>.md/.html`) are gitignored ephemera; the
5
+ structured backing record is the user-local eval DB
6
+ (`~/.cache/mlx-bun/evals.sqlite`). Promote a run into this file
7
+ deliberately when it becomes the new reference.
8
+
9
+ New raw request records also retain the server's final `usage` object,
10
+ including execution lane and speculative counters when supplied. The reader
11
+ captures these already-parsed fields after timing finishes; older reports may
12
+ lack them. This lets settings comparisons verify which method actually ran.
13
+
14
+ The optional `mlx-bun-isolated` arm runs the same CLI/model/request cells through
15
+ `--isolate`; select it alongside `mlx-bun` to compare transport cost. Its RSS
16
+ column sums the parent and descendant processes. This is aggregate process RSS,
17
+ not deduplicated physical memory; shared runtime pages may appear in both.
18
+
19
+ The current closeout candidate follows Josh's advisory-memory policy: requests
20
+ are attempted without fit-based refusal or completion clamping by default.
21
+ Earlier reservation variants remain diagnostics, including successful trials;
22
+ they are not the product policy. Explicit budgets/context caps still apply.
23
+ No speed default has been promoted by these memory experiments.
24
+
25
+ The advisory candidate's M4 Pro replay (`m4-advisory-short.md.json`) retains
26
+ all 23 comparable successful request outputs and usage/cache counts from
27
+ the earlier R0 run. Five-sample decode medians are 14.812 tok/s serial and
28
+ 14.677 tok/s continuous; this is one diagnostic run, not a paired speed win.
29
+ Both lanes complete decode and cold/warm 1K prefill. The aggregate retained
30
+ history hits actual Metal insufficient-memory errors: serial recovers on the
31
+ harness retry; continuous fails both attempts. These are runtime failures,
32
+ not predictive refusals. Local regression tests deliberately give the live
33
+ model an impossible accounting estimate and verify both lanes still execute.
34
+ Review: `reports/qwen38-closeout/m4-advisory-short-review.json`.
35
+
36
+ ## Rotating target speculation through shared execution
37
+
38
+ M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2. Gemma 4 12B OptiQ, prompt lookup
39
+ at its default depth ten, bf16 KV, 2 GiB RAM cache plus temporary SSD,
40
+ 192 decode tokens, four concurrent requests and default capacity eight.
41
+ Production `bench-serve.ts all`, context sweep skipped, seed `rotating-spec-0`,
42
+ diagnostic mode under Josh's machine policy. Final comparison order is
43
+ control-1, candidate-2, control-2, candidate-3; an earlier candidate-1 predates
44
+ the final singleton boundary correction and is excluded from these means.
45
+
46
+ | Metric (mean of two arms) | Previous serial placement | Shared rotating placement | Change |
47
+ |---|---:|---:|---:|
48
+ | Single-request decode | 16.928 tok/s | 16.894 tok/s | −0.2% |
49
+ | Four-request throughput | 17.269 tok/s | 22.130 tok/s | +28.1% |
50
+ | Four-request wall time | 29,648.128 ms | 23,139.278 ms | −22.0% |
51
+ | Repeated-prompt TTFT | 2,505.201 ms | 199.600 ms | −92.0% |
52
+ | Cold prefill TTFT | 2,515.753 ms | 2,524.302 ms | +0.3% |
53
+ | Launch to first output | 1,571.428 ms | 1,631.817 ms | +3.8% |
54
+
55
+ All 60 recorded requests complete with matching bodies and token budgets.
56
+ Single-request text and raw completion/chat probes match. All four concurrent
57
+ responses differ across implementations, while each implementation's repeats
58
+ are exact. This measures fixed output budgets with different concurrent
59
+ trajectories. The shared cache reuses 671 tokens versus zero in the control.
60
+ Startup spans roughly 1.1–2.2 seconds in both arms; its mean does not establish
61
+ strict dominance. This closes the bf16 rotating transaction implementation,
62
+ not all speculative compositions or strict serial-removal acceptance.
63
+
64
+ Control source: `20c21f2f62383b9878966f8ea1bf74c98d58942d33351430042ff7801cb929c4`.
65
+ Final candidate: `c8213540beb87f438fbafad7115b49f494e92526c28acca930f134883d5cfdcf`.
66
+ The change is integrated in the unreleased tree. Evidence:
67
+ `reports/qwen38-closeout/composition-baseline/rotating-speculation/`, including
68
+ `benchmark-comparison.json` and all raw M4 reports.
69
+
70
+ ## Full-attention speculation through shared execution
71
+
72
+ M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2. Llama 3.2 3B target and 1B
73
+ standalone drafter (4-bit weights), draft depth two, bf16 KV, 2 GiB RAM
74
+ plus temporary SSD. Production `bench-serve.ts all`, 192 decode tokens,
75
+ four concurrent requests, default capacity eight, seed `full-kv-spec-0`,
76
+ context sweep skipped, diagnostic mode under Josh's machine policy.
77
+ The same draft engine runs in both arms; target placement and paired cache
78
+ reuse change. Order: control, candidate, candidate, control.
79
+
80
+ | Metric (mean of two arms) | Previous serial placement | Shared placement | Change |
81
+ |---|---:|---:|---:|
82
+ | Single-request decode | 120.890 tok/s | 129.319 tok/s | +7.0% |
83
+ | Four-request throughput | 108.167 tok/s | 162.331 tok/s | +50.1% |
84
+ | Four-request wall time | 4,733.455 ms | 3,154.056 ms | −33.4% |
85
+ | Repeated-prompt TTFT | 891.394 ms | 44.685 ms | −95.0% |
86
+ | Cold prefill TTFT | 893.065 ms | 919.492 ms | +3.0% |
87
+ | Launch to first output | 1,070.260 ms | 978.795 ms | −8.5% |
88
+
89
+ All 60 requests complete, with identical request bodies and token counts.
90
+ Single-request text and raw completion/chat probes match. One of four
91
+ concurrent responses changes across implementations; each implementation's
92
+ repeats are exact. Usage differs by execution lane, repeated-prefix reuse
93
+ (752 tokens versus zero), and the changed response's speculative counters.
94
+ Thus aggregate timing holds token budgets fixed, with one changed trajectory.
95
+ The control launch times span 970–1,171 ms; this is not strict startup
96
+ acceptance. Cold-prefill latency still regresses. The change is integrated
97
+ in the unreleased tree; defaults remain unchanged.
98
+
99
+ Control source: `3a420497bf8a8c6be5896050b45773d541515a22e737d8775522d742221a8d41`.
100
+ Candidate source: `20c21f2f62383b9878966f8ea1bf74c98d58942d33351430042ff7801cb929c4`.
101
+ Evidence: `reports/qwen38-closeout/composition-baseline/full-kv-speculation/`,
102
+ including four raw M4 reports and `benchmark-comparison.json`.
103
+
104
+ ## Standalone drafting: first shared-executor comparison
105
+
106
+ M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2. Qwen3.8 packed 27B target plus
107
+ Qwen3.5 0.8B OptiQ standalone drafter, depth two, KV4 from token zero,
108
+ 4 GiB RAM cache plus temporary SSD, 192 decode tokens and four concurrent
109
+ requests. Production `bench-serve.ts all`, seed `standalone-serving-0`,
110
+ context sweep skipped; advisory diagnostic mode under Josh's machine policy.
111
+
112
+ | First run | Single-request decode | Repeated-prompt TTFT | Reused tokens | Four-request throughput |
113
+ |---|---:|---:|---:|---:|
114
+ | Previous standalone provider | 8.936 tok/s | 5,987.688 ms | 0 | 8.617 tok/s |
115
+ | Shared standalone candidate | 13.945 tok/s | 122.100 ms | 756 | GPU allocation failure |
116
+
117
+ The initial candidate's aggregate phase failed both attempts with native Metal
118
+ insufficient-memory errors. A complete-sequence profile reproduces the failure
119
+ with 4,005 MiB of accounted cache entries and an observed 17,987 MiB peak;
120
+ a fresh aggregate completes. Retained RAM entries consume batch headroom.
121
+
122
+ A second matched comparison uses **2 GiB RAM plus SSD in both arms**, in
123
+ candidate/control/control/candidate order. Other settings are unchanged;
124
+ default capacity is eight, with four concurrent requests. All 60 recorded
125
+ requests complete without failures. Means of the per-arm measurements:
126
+
127
+ | Metric | Previous standalone provider | Shared standalone provider | Change |
128
+ |---|---:|---:|---:|
129
+ | Single-request decode | 8.882 tok/s | 13.970 tok/s | +57.3% |
130
+ | Four-request throughput | 8.614 tok/s | 9.343 tok/s | +8.5% |
131
+ | Four-request wall time | 59.437 s | 54.807 s | −7.8% |
132
+ | Repeated-prompt TTFT | 5,989.823 ms | 122.527 ms | −98.0% |
133
+ | Cold prefill TTFT | 5,993.083 ms | 6,153.492 ms | +2.7% |
134
+ | Launch to first output | 4,332.735 ms | 4,537.720 ms | +4.7% |
135
+
136
+ All request bodies, token counts and single-request text match; raw completion
137
+ and chat probes also match. Candidate repeats preserve single-request text and
138
+ usage. Concurrent text and acceptance counters differ both across implementations
139
+ and between candidate repeats as admission geometry changes; throughput is a
140
+ fixed-token-budget serving measurement, not identical generated content.
141
+ The new provider retains recurrent draft history after rejection; the old
142
+ provider discarded that history. It also retains paired cache state, with
143
+ 756 tokens reused on the repeated prompt versus zero in the control.
144
+
145
+ The provider is integrated in the unreleased working tree. The cold/startup
146
+ cost and the 4 GiB failure remain; this does not close strict serial dominance
147
+ or select application defaults. MTP comparisons use a different drafter and
148
+ must remain separate. Control source is
149
+ `0a7e65986e57b493e7ab30a2e328a1eb591b03b029f59e342fd8a01471538613`;
150
+ candidate source
151
+ `3a420497bf8a8c6be5896050b45773d541515a22e737d8775522d742221a8d41`.
152
+ Evidence: `reports/qwen38-closeout/composition-baseline/two-model-batch/`,
153
+ including `ram2/benchmark-comparison.json` and raw request records.
154
+
155
+ ## Current serial versus shared execution: staggered Gemma requests
156
+
157
+ M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0, unreleased source
158
+ `0a7e65986e57b493e7ab30a2e328a1eb591b03b029f59e342fd8a01471538613`.
159
+ Gemma 4 12B OptiQ, ordinary KV4, 4 GiB RAM prompt cache and temporary SSD.
160
+ `bench-serve.ts all` uses 192 decode tokens, skipped context sweep,
161
+ `--aggregate-context 2048 --aggregate-stagger-ms 25`, seed `prefill-long-0`.
162
+ The serial arm pins `--batch 1`; the shared arm uses the default capacity eight. The four aggregate prompts contain 1,289/1,281/1,287/1,287
163
+ tokens with 13/12/14/12 cached, and each emits 128 tokens. Diagnostic mode
164
+ follows Josh's retained-swap policy; no competing GPU job runs during timing.
165
+
166
+ | run order | median decode tok/s | cached first-token ms | aggregate tok/s | aggregate wall ms | first request TTFT ms | mean TTFT ms |
167
+ |---|---:|---:|---:|---:|---:|---:|
168
+ | serial 0 | 26.3177 | 155.205 | 11.4938 | 44545.58 | 10037.72 | 24644.60 |
169
+ | shared 0 | 26.0648 | 155.797 | 19.7660 | 25903.03 | 9287.39 | 16360.50 |
170
+ | shared 1 | 26.2129 | 154.351 | 20.1601 | 25396.75 | 9031.62 | 15985.86 |
171
+ | serial 1 | 25.9724 | 156.207 | 13.0064 | 39365.23 | 4776.07 | 19477.02 |
172
+
173
+ Mean aggregate throughput increases **62.96%**, total aggregate time falls
174
+ **38.86%**, and mean first-token latency falls **26.69%**. Single-request
175
+ decode is effectively equal, −0.024% in throughput or +0.056% in summed
176
+ request time; cached latency falls 0.406%. First-request latency does not
177
+ dominate: the second serial sample starts in 4.78 s versus shared samples
178
+ near 9.1 s. Startup also has an initial serial outlier, so it is not a settled
179
+ comparison. These limits keep strict serial deletion acceptance open.
180
+
181
+ All 60 requests complete without failure. Request bodies, usage excluding
182
+ the expected lane label, token/cache counts and finish markers match. All
183
+ single-request texts match; all four concurrent texts differ between serial
184
+ and shared. Repeated runs of each arm produce identical text. This measures
185
+ throughput for the same submitted workload and output-token budgets, not
186
+ identical generated content. Same-B model oracle checks remain separate.
187
+ Source hashes stay fixed throughout both blocks. Raw reports and comparison:
188
+ `reports/qwen38-closeout/composition-baseline/current-serial-dominance/`.
189
+
190
+ ## Delayed full-attention padding: M4 comparison
191
+
192
+ The unreleased cache implementation now supports padded prefill while full
193
+ attention rows transition independently from BF16 to affine or TurboQuant.
194
+ Shared row positions and codec ownership replace separate padding logic.
195
+ The existing uniform KV4 decode still uses the same packed attention code.
196
+
197
+ M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0. Qwen3.8-27B packed
198
+ interleave2 target and folded RTN4 MTP companion, depth 2, KV4 from token zero,
199
+ 4 GiB RAM prompt cache, temporary SSD cache, configured batch capacity 8,
200
+ four concurrent requests. Production `bench-serve.ts all`, 192 decode tokens,
201
+ `--skip-context`, workload seed `mtp-serving-block-0`, async expansion off and
202
+ fused TQ decode enabled. Diagnostic mode follows Josh's retained-swap policy;
203
+ free memory starts at 90–93%, retained swap at 1.6–2.8 GiB. No other GPU job
204
+ runs during timing. The audio-daemon allowance is explicit.
205
+
206
+ | arm, in order | median decode tok/s | aggregate tok/s | cached first-token ms | ready ms | cold start ms |
207
+ |---|---:|---:|---:|---:|---:|
208
+ | control 1 | 19.2267 | 16.4810 | 98.186 | 610.78 | 4085.57 |
209
+ | candidate 1 | 19.1023 | 16.4524 | 98.070 | 821.10 | 4167.10 |
210
+ | candidate 2 | 19.1224 | 16.4746 | 99.601 | 614.60 | 4009.12 |
211
+ | control 2 | 19.3181 | 16.5351 | 99.174 | 621.53 | 3982.93 |
212
+
213
+ Candidate/control means change decode throughput by −0.831%, aggregate
214
+ throughput by −0.270%, cached latency by +0.157%, and cold start by +1.335%.
215
+ One candidate readiness sample is about 200 ms higher; the other overlaps
216
+ controls. These measurements establish no speed improvement or strict serial
217
+ performance dominance. The feature is integrated with these limits recorded;
218
+ long-prefill and B1 performance acceptance remain open.
219
+
220
+ All 60 request bodies, responses, usage/speculation counters, token counts,
221
+ finish reasons and completion markers match. No requests fail. Each source
222
+ snapshot stays fixed: control `7f06df944eb062703711f29b086879718868803c00367dd992b3a5bb8d0fac8e`,
223
+ candidate `0a7e65986e57b493e7ab30a2e328a1eb591b03b029f59e342fd8a01471538613`.
224
+ Both-machine cache/model and seeded delayed-conversion gates accompany this
225
+ comparison. Evidence: `reports/qwen38-closeout/composition-baseline/full-delayed-prefill/`,
226
+ including `benchmark-comparison.json`, `manifest.json`, and `m4/` raw reports.
227
+
228
+ ## Shared MTP prefill: M4 comparison and scheduling attribution
229
+
230
+ Apple M4 Pro, 24 GB; Bun 1.4.2, MLX 0.32.2. Packed interleave2
231
+ Qwen3.8-27B, affine KV4, folded MTP2, four concurrent requests (configured
232
+ maximum batch 8), 4 GiB prompt cache,
233
+ 192 output tokens per decode request, five decode samples, context sweep off.
234
+ `bench-serve.ts all` uses workload seed `mtp-serving-block-0`, fused TQ enabled
235
+ and async Trellis expansion disabled. Four balanced runs use
236
+ control/candidate/candidate/control order. The first control started with zero
237
+ swap; subsequent runs used `--diagnostic` after swap returned. All runs finished
238
+ without request failures and retained stable source hashes within each run.
239
+
240
+ | Preparation policy | Runs | Mean decode median tok/s | Mean concurrent tok/s |
241
+ |---|---:|---:|---:|
242
+ | Control: existing MTP preparation | 2 | 19.331 | 15.194 |
243
+ | Common driver, shared prefill | 2 | 19.069 | 14.076 |
244
+ | Common driver, individual preparation | 2 | 19.158 | 15.508 |
245
+ | Common driver, finish resumed final step first | 1 | 19.3 | 14.099 |
246
+
247
+ Shared prefill loses **1.35%** single-request decode rate and **7.36%** concurrent
248
+ throughput relative to the balanced control means. Mean concurrent wall time
249
+ rises from 33.718 to 36.374 seconds. Cached first-output latency is 98.23 versus
250
+ 99.85 ms; cold 1K first-output latency is 5844.61 versus 5997.68 ms.
251
+
252
+ All 60 requests in the balanced comparison preserve request hashes,
253
+ prompt/output/cache counts, finish reasons and completion markers. Single-request
254
+ text and usage are exact. Three of four concurrent responses change between
255
+ control and candidate; each arm reproduces its own text and full usage exactly.
256
+ Thus this is a serving comparison with changed concurrent numerical trajectories,
257
+ not an identical-work kernel timing. Total concurrent speculative rounds fall
258
+ from 234 to 232, so an increase in round count does not explain the slowdown.
259
+
260
+ The individual-preparation control changes only the scheduler admission budget
261
+ from 2048 to zero and retains B4 decode and the same common driver. Both runs
262
+ reproduce every control response and full usage record. The clean repeat
263
+ confirmed that this is the only source difference. Finishing resumed final
264
+ steps first instead leaves concurrent responses/usage identical to shared
265
+ prefill and does not recover its throughput. None of these isolated candidates
266
+ is adopted. The next investigation is preparation-to-decode cache state and
267
+ actual work per round.
268
+
269
+ Two instrumented follow-ups locate the sustained cost in target verification.
270
+ Across 53 B4 rounds per arm, median complete-round time is 540.64 ms with
271
+ shared preparation versus 459.01 ms with individual preparation. The target
272
+ forward interval is 510.50 versus 430.34 ms; draft generation is 12.11 versus
273
+ 12.15 ms. These are lazy-execution phase timings, so the target interval includes
274
+ any work it forces; layer-level attribution is still needed. Independent saved
275
+ SSE timestamps reproduce the uninstrumented gap (about 542 versus 459 ms
276
+ between output bursts during seconds 10–25).
277
+
278
+ Further probes run three B4 rounds with layer synchronization. Both arms use
279
+ 128 packed gate/up calls and 64 expanded down-projection calls, with identical
280
+ M=12 and bf16 geometry. The down-projection evaluation interval, which also
281
+ forces the preceding lazy packed gate/up work, is 412.68 versus 355.75 ms.
282
+ This narrows the cost to MLP evaluation but does not distinguish its packed
283
+ kernels from weight expansion/native matmul. Phase/layer probes preserve their
284
+ respective control responses and usage. A separate candidate evaluates target
285
+ state and clears the temporary buffer pool after preparation; it completes
286
+ without failures at 14.3 concurrent tok/s, still below individual preparation.
287
+ It is not adopted. Profiles: `mtp-cohort-layer-profile.json` and
288
+ `mtp-cohort-trellis-profile.json`; drain result: `mtp-cohort-drain-manifest.json`.
289
+
290
+ A subsequent split probe evaluates inputs, packed projections, expanded weights
291
+ and matrix products separately. Across three instrumented B4 rounds, median
292
+ expansion time is 157.92 ms after shared preparation versus 85.55 ms after
293
+ individual preparation. Packed gate/up evaluation is 232.03 versus 229.83 ms;
294
+ expanded-weight matrix multiplication is 88.75 versus 84.07 ms. These inserted
295
+ synchronization points change absolute latency and serve only to locate work.
296
+ The separate input-evaluation candidate passes M1 native MTP serving but reaches
297
+ 13.8 concurrent tok/s on the M4, so it is not adopted. Evidence:
298
+ `mtp-cohort-split-profile.json`, `split-profile-*.md.json`, `input-eval-1.md.json`.
299
+
300
+ Smaller vector expansion tiles (32, 64 and untiled) reach 14.15–14.22
301
+ concurrent tok/s; variant 12 reaches 13.30; a residency refresh reaches 14.00.
302
+ All preserve their shared-prefill reference responses and usage, and none is
303
+ adopted. Memory instrumentation observes 16.823 GiB active after shared
304
+ preparation versus 16.534 GiB after individual preparation. A native ownership
305
+ probe confirms that a deferred compact row copy retains its larger parent
306
+ allocation until evaluated.
307
+
308
+ Evaluating target snapshots before RAM retention recovers concurrent throughput
309
+ in two M4 runs: **16.268 and 16.299 tok/s**, averaging 16.283, versus 14.076
310
+ for the original shared-preparation pair (**+15.68%**) and 15.508 for the two
311
+ individual-preparation controls (**+5.00%**). Concurrent wall time falls to
312
+ 31.473 and 31.414 seconds. Single-request decode medians are 19.277 and 19.108
313
+ tok/s; cached first output is 100.66 and 100.76 ms. All 30 requests preserve
314
+ request hashes, output text and full usage exactly against shared preparation.
315
+ Source is stable in both runs. The M1 native serving test passes 229 assertions.
316
+ The final implementation below moves this behavior from method-local capture
317
+ to the common cache ownership boundary for every producer.
318
+ Evidence: `mtp-cohort-snapshot-eval-review.json`,
319
+ `mtp-cohort-expansion-screen-review.json`, `mtp-cohort-memory-profile.json`.
320
+
321
+ Moving materialization into the shared RAM cache, including companion tensors,
322
+ preserves all 30 responses and usage records in two further M4 runs. Concurrent
323
+ throughput is **16.477 and 16.384 tok/s**; single-request decode is 19.127 and
324
+ 19.205 tok/s; cached first output is 97.62 and 98.79 ms. The common implementation
325
+ passes 2,150 M1 tests (14 skipped), all typechecks, and the generated TurboQuant
326
+ RAM/SSD continuation test at MTP3/B4. M1 native lookup passes 228 assertions and the ordinary 4096-token TQ prefix
327
+ ownership test passes 40. A fresh current-tree control reaches 19.245 decode
328
+ and 15.539 concurrent tok/s, with 99.02 ms cached first output. Against that
329
+ control, the common-cache pair averages **5.74% higher concurrent throughput**,
330
+ 0.41% lower single-request decode and 0.83% lower cached first-output latency.
331
+ This is a two-candidate/one-control comparison; the older balanced control
332
+ pair remains above. The M4 suite passes 2,154 tests (10 skipped), both-machine typechecks pass, and
333
+ M4 native TQ MTP serving passes 229 assertions. The shared driver and common
334
+ cache fix are adopted in the unreleased working tree; main integration
335
+ suite, typechecks and hygiene pass. Strict serial dominance remains open. Review:
336
+ `mtp-cohort-cache-boundary-review.json`; source/validation:
337
+ `mtp-cohort-cache-boundary-manifest.json`.
338
+
339
+ The final memory profile differs from the original shared-preparation profile
340
+ only in the two cache implementation files. Active GPU allocation falls from
341
+ 16.823 to **16.458 GiB**, releasing **373.37 MiB**. Median weight-expansion time
342
+ falls from **147.57 to 86.17 ms** across three instrumented B4 rounds, matching
343
+ the individual-preparation profile's 87.99 ms. Routes, geometry and call counts
344
+ are unchanged; all 15 responses and full usage remain exact. The retained-memory
345
+ regression passes with materialization and fails when it is disabled. Profile
346
+ latencies locate the cost; the uninstrumented runs above measure serving speed.
347
+ Evidence: `mtp-cohort-memory-profile.json` and
348
+ `memory-profile-cache-boundary.md.json`.
349
+
350
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`:
351
+ `mtp-cohort-benchmark-comparison.json`, `mtp-cohort-admission-comparison.json`,
352
+ source manifests/patches, seven comparison runs and instrumented follow-ups in
353
+ `mtp-cohort-m4/*.md.json`; phase timing is in `mtp-cohort-phase-profile.json`.
354
+
355
+ ## Delayed affine row composition: fixed-settings M4 regression
356
+
357
+ Apple M4 Pro, 24 GB, macOS 27.0.0, Bun 1.4.2, MLX 0.32.2/native pack
358
+ 0.4.0. The existing `bench-serve.ts all` suite ran control/candidate/candidate/control
359
+ on the packed interleave2 Qwen3.8-27B artifact with KV4, MTP2, 192 output tokens,
360
+ five decode requests, prompt cache 4 and context sweep disabled. Workload seed
361
+ `mtp-serving-block-0`; fused TQ enabled, async Trellis expansion disabled.
362
+ All preflights passed with Josh's audio-daemon allowance. Source stayed fixed:
363
+ control `88da0dca100cdb012cbd4330638cc43b727dbb853a5b1ef6aded60bc6fe1eb0d`,
364
+ candidate `eacbb8c7d9e1a2f06c4235f71dc7db51f29b8bd27a9940a5e802a056220ff336`.
365
+ Remote checkout HEAD was `0c355f4`; source hashes include the unreleased changes.
366
+
367
+ | Arm | Five decode requests, total ms | Cached TTFT ms | Concurrent aggregate tok/s |
368
+ |---|---:|---:|---:|
369
+ | Control 1 | 55,730.95 | 97.33 | 15.9259 |
370
+ | Candidate 1 | 55,585.20 | 97.57 | 15.8891 |
371
+ | Candidate 2 | 55,678.22 | 99.36 | 15.7890 |
372
+ | Control 2 | 55,682.47 | 99.41 | 15.7812 |
373
+
374
+ All 60 request records retain identical request hashes, response text, complete
375
+ usage, token counts and finish reasons. Combined candidate/control changes are
376
+ −0.135% decode wall time, +0.099% cached latency and −0.091% aggregate throughput.
377
+ Peak RSS is effectively unchanged. Startup was less stable: the initial control
378
+ reached readiness in 608 ms versus about 800 ms in the later arms, and its cold
379
+ start was 3,443 ms versus about 4,200–4,300 ms afterward. The candidate overlaps
380
+ the final control, but this screen does not establish startup equivalence.
381
+ The decode and cached-latency changes overlap the observed
382
+ control variation: the existing default path is effectively flat. This is a
383
+ regression check for integrating delayed-affine support and the shared transition
384
+ lifecycle, not a measurement of delayed conversion speed or serial dominance.
385
+ Both-machine native/serving/SSD correctness gates qualify the new composition.
386
+ Raw records and comparison: `reports/qwen38-closeout/composition-baseline/delayed-affine/`.
387
+
388
+ ## Captured attention views: M4 regression
389
+
390
+ Same M4 Pro 24 GB/toolchain, packed Qwen artifact and 192-token KV4/MTP2
391
+ protocol as the delayed-affine comparison above. Order is again
392
+ control/candidate/candidate/control, with unchanged requests and initial cache
393
+ settings. Control source is
394
+ `eacbb8c7d9e1a2f06c4235f71dc7db51f29b8bd27a9940a5e802a056220ff336`;
395
+ candidate source is
396
+ `f94a8212be222056a0d1cdc70c45c3d7f2e50a937eb89560a719ee4bf21c61f7`.
397
+ Both sources remain fixed throughout their runs.
398
+
399
+ | Arm | Five decode requests, total ms | Cached TTFT ms | Concurrent aggregate tok/s |
400
+ |---|---:|---:|---:|
401
+ | Control 1 | 55,784.51 | 97.57 | 15.8553 |
402
+ | Candidate 1 | 55,656.05 | 97.18 | 15.9355 |
403
+ | Candidate 2 | 55,687.98 | 97.26 | 15.9648 |
404
+ | Control 2 | 55,680.16 | 97.45 | 15.9668 |
405
+
406
+ All 60 request records match in input hash, output text, complete usage, token
407
+ counts and finish reason. Combined decode wall time changes −0.108%, cached
408
+ latency −0.298%, and aggregate throughput +0.246%; peak RSS is unchanged.
409
+ These are effectively flat regression results, not a general speedup or serial
410
+ dominance result. Initial-control startup was faster than every subsequent
411
+ arm: readiness 607 ms versus 817–818 ms; cold start 3,487 ms versus 4,210–4,254 ms.
412
+ Startup equivalence remains unproven.
413
+
414
+ All start checks pass with the audio-daemon allowance. The final control's raw
415
+ end check flags `/usr/libexec/mobileassetd` at 84% CPU and 23 MB RSS, while free
416
+ memory remains 92%. That flag remains in the raw result. Under Josh's policy
417
+ allowing isolated background CPU activity, the stable paired decode/cached
418
+ measurements support feature integration; this is not an entirely unflagged
419
+ four-arm run. The initial wrapper's separate oracle-path error occurred before
420
+ inference and is retained as a failed launch, not a timing sample.
421
+
422
+ The changed attention-view operations are qualified by both-machine full-model
423
+ Gemma/MiniCPM state/logit checks, Qwen rollback/MTP/lookup checks and exact SSD
424
+ continuations. This default-settings screen does not measure delayed conversion
425
+ speed. Evidence: `reports/qwen38-closeout/composition-baseline/kv-attention-view/`.
426
+
427
+ ## Delayed rotating affine composition: M4 regression
428
+
429
+ Same M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0 and packed
430
+ Qwen KV4/MTP2 protocol as the preceding comparisons: 192 output tokens,
431
+ five decode requests, prompt cache 4, workload seed `mtp-serving-block-0`,
432
+ context sweep disabled, fused TQ enabled and async expansion disabled.
433
+ The four arms ran control/candidate/candidate/control with stable sources:
434
+ control `1b1ededa649088e8338a2930b4ae152e66edf7e4048e2dc8d0b7a3859691800c`,
435
+ candidate `c7d58f7ec867015eff7bbc9a7f02d13baea28173dd312bd504e9b880659278eb`.
436
+ Every start/end preflight passed with the recorded audio-daemon allowance;
437
+ there were no request or phase failures.
438
+
439
+ | Arm | Five decode requests, total ms | Cached TTFT ms | Concurrent aggregate tok/s |
440
+ |---|---:|---:|---:|
441
+ | Control 1 | 55,775.68 | 97.24 | 15.9569 |
442
+ | Candidate 1 | 55,608.34 | 97.49 | 16.0176 |
443
+ | Candidate 2 | 55,692.19 | 97.55 | 15.8421 |
444
+ | Control 2 | 55,661.04 | 99.17 | 15.8041 |
445
+
446
+ All 60 records match in request hash, response text, complete usage including
447
+ speculation counters, token counts and finish reason. These HTTP records do
448
+ not contain emitted token IDs; native tests provide the numerical evidence.
449
+ Candidate versus control means change decode wall time by −0.122%, cached
450
+ latency by −0.696% and aggregate throughput by +0.311%. Peak RSS spans
451
+ 12,208–12,224 MB. These are effectively flat regression results. The first
452
+ control reaches readiness in 609 ms and cold start in 3,610 ms; the remaining
453
+ arms take 817–818 ms and 4,235–4,288 ms. Startup equivalence remains unproven.
454
+
455
+ This checks the shared lifecycle on the existing default Qwen path. It does
456
+ not measure positive-threshold Gemma conversion speed or establish serial
457
+ dominance. Both-machine Gemma KV4/KV8 and per-layer native state/logit,
458
+ RAM/SSD continuation and seeded serving tests cover the new composition;
459
+ fresh-process Gemma and long-pressure acceptance remain open.
460
+ Evidence: `reports/qwen38-closeout/composition-baseline/delayed-rotating/`.
461
+
462
+ ## Singleton admission attribution on M4 Pro
463
+
464
+ A synthetic Qwen-shaped MLX 0.32.2 probe compares singleton `copyOf` with
465
+ `contiguous`, using evaluated donors: 48 recurrent states, 16 KV4 layers at
466
+ 757 logical tokens with 768-token capacity, and their combination. Each arm
467
+ has four warmups and twenty samples; order is control/candidate/candidate/control.
468
+ The combined logical storage is 168,099,840 bytes. Both implementations add
469
+ **zero live GPU allocation** during admission. Combined median admission times
470
+ are 0.1463/0.1435/0.1470/0.1464 ms in execution order. There is no demonstrated
471
+ physical-copy saving; `copyOf` already shares storage in this runtime.
472
+ These synthetic measurements do not establish complete-request speed. The
473
+ initial probe launch omitted the required stream argument to `synchronize`;
474
+ its failure is retained separately and supplied no timing sample.
475
+
476
+ The completed four-arm `bench-serve.ts all` comparison uses the same M4
477
+ Qwen KV4/MTP2, 192-token protocol as above. Control source is
478
+ `c7d58f7ec867015eff7bbc9a7f02d13baea28173dd312bd504e9b880659278eb`;
479
+ candidate is `b7361d962c70f0efbb5c55c32f06996103015477095833c98d83928cc23ddd52`.
480
+ All source snapshots and start/end preflights pass. All 60 request hashes,
481
+ response texts, complete usage/speculation counters, token counts and finish
482
+ reasons match, with no request or phase failures.
483
+
484
+ | Arm | Five decode requests, total ms | Cached TTFT ms | Concurrent aggregate tok/s |
485
+ |---|---:|---:|---:|
486
+ | Control 1 | 56,033.78 | 99.64 | 15.8719 |
487
+ | Candidate 1 | 55,590.06 | 97.28 | 15.9511 |
488
+ | Candidate 2 | 55,682.16 | 97.35 | 15.9217 |
489
+ | Control 2 | 55,725.68 | 99.44 | 15.9324 |
490
+
491
+ Candidate/control means change decode wall time −0.436%, cached latency
492
+ −2.230% and aggregate throughput +0.216%. Both candidate cached samples are
493
+ lower than both controls, although the physical-copy hypothesis is disproven
494
+ and MTP group admission follows its first published token. The latency result
495
+ needs attribution/repetition before treating this replacement as an accepted
496
+ optimization. Controls report readiness at 608 ms and candidates at 816 ms;
497
+ the readiness probe polls every 200 ms, so these observations have coarse
498
+ resolution. Cold starts are 3,414/4,114/4,224/4,017 ms in execution order.
499
+ Startup equivalence and direct serial dominance remain unproven. Both-machine
500
+ native, serving, full-suite and typecheck checks pass; the candidate is isolated.
501
+ Evidence: `reports/qwen38-closeout/composition-baseline/singleton-state/`.
502
+
503
+ ## Recurrent row retention diagnostic on M1 Max
504
+
505
+ Apple M1 Max 32 GB, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0. A synthetic
506
+ Qwen-shaped recurrent layer contains 3,207,168 logical bytes per row. After
507
+ extracting one row and disposing its source, the existing implementation keeps
508
+ 3,211,264 / 6,422,528 / 12,828,672 / 25,657,344 live allocator bytes for source
509
+ B=1/2/4/8. A proper-subset compact copy retains 3,211,264 bytes in every case,
510
+ including allocator rounding. B1 continues to share its whole allocation.
511
+ This measures one layer, not full-model RSS or request time. The allocation
512
+ regression fails against unchanged source and passes with exact values on the
513
+ isolated fix. Both-machine MTP and bf16/KV4/TQ generated RAM/SSD continuation,
514
+ complete-suite and typecheck checks pass. The allocation regression also passes
515
+ on M4. The reviewed extraction fix is adopted in the unreleased working tree.
516
+
517
+ The M4 Pro 24 GB `bench-serve.ts all` check uses the same packed Qwen KV4/MTP2,
518
+ 192-token protocol above, in control/candidate/candidate/control order. Sources
519
+ remain fixed: control
520
+ `c7d58f7ec867015eff7bbc9a7f02d13baea28173dd312bd504e9b880659278eb`, candidate
521
+ `bdc1241596526f42d68ba0988fc63cd90dce73ce8d048b45d9bfa1cc0c5872c7`.
522
+ All start/end preflights pass; all 60 request hashes, response texts, full usage
523
+ and speculation counters, token counts and finish reasons match. No failures.
524
+
525
+ | Arm | Five decode requests, total ms | Cached TTFT ms | Concurrent aggregate tok/s |
526
+ |---|---:|---:|---:|
527
+ | Control 1 | 56,548.78 | 99.48 | 15.7814 |
528
+ | Candidate 1 | 55,608.23 | 99.02 | 15.9869 |
529
+ | Candidate 2 | 55,785.82 | 97.41 | 15.8657 |
530
+ | Control 2 | 55,636.97 | 99.47 | 15.9106 |
531
+
532
+ Candidate/control means change decode wall time −0.706%, cached latency
533
+ −1.264% and aggregate throughput +0.507%. The initial control is slower than
534
+ the remaining arms; candidate throughput overlaps the control range, and the
535
+ second candidate decode total is slightly above the second control. Treat
536
+ these as a regression check for the storage fix, not a broad speedup or serial
537
+ dominance result. Peak RSS spans 12,208–12,240 MB. Startup remains unresolved:
538
+ readiness is 608/816/816/817 ms and cold start 3,704/4,177/4,240/4,181 ms.
539
+ The short workload does not establish long-context pressure acceptance.
540
+ Evidence: `reports/qwen38-closeout/composition-baseline/ssm-extraction/`.
541
+
542
+ ## Batched prefill cohorts: M4 regression before projection correction
543
+
544
+ Unreleased isolated candidate against the previously validated delayed-padding
545
+ checkout. Apple M4 Pro, 24 GB; Bun 1.4.2, MLX 0.32.2/native pack 0.4.0.
546
+ Gemma 4 12B OptiQ, ordinary generation, KV4, RAM prompt cache 4 GB, default
547
+ batch capacity 4. Both checkouts have HEAD `0c355f4` plus frozen source changes.
548
+ Control source SHA-256 `89d209400c1f683143ee9afea30e8a440ee00159fe96ba8e1c3bbe5893c744ac`;
549
+ candidate `2431d0395ad7e752991bc47817cf8c6f54a6d74fb6e0f6fc08598e314ce6d937`.
550
+
551
+ Protocol: `bun scripts/bench-serve.ts all --model-path <Gemma-12B-OptiQ>
552
+ --arms mlx-bun --tokens 192 --skip-context --kv-quant 4 --prompt-cache 4
553
+ --workload-seed delayed-padding-0 --allow-cpu-process /usr/libexec/audiomxd`.
554
+ Run order is control, candidate, candidate, control. All preflights and saved
555
+ machine checks pass, with 217 MB swap and the explicitly allowed audio daemon.
556
+ Source hashes remain fixed throughout all four arms; no request failures.
557
+
558
+ | arm | five decode requests, total ms ↓ | cached first-token ms ↓ | B4 aggregate tok/s ↑ | ready ms | cold-start ms | peak RSS MiB |
559
+ |---|---:|---:|---:|---:|---:|---:|
560
+ | control 1 | 38,010.26 | 154.517 | 72.966 | 609.34 | 2,150.35 | 8,985.45 |
561
+ | candidate 1 | 38,063.00 | 154.884 | 72.965 | 608.25 | 1,026.27 | 8,990.06 |
562
+ | candidate 2 | 37,950.08 | 154.601 | 73.024 | 608.52 | 1,024.44 | 8,985.66 |
563
+ | control 2 | 37,906.38 | 154.930 | 73.032 | 609.03 | 1,029.51 | 8,967.28 |
564
+
565
+ Candidate means: decode wall **+0.127%**, cached latency **+0.012%**, aggregate
566
+ throughput **−0.006%**. These results establish no speed win or strict serial
567
+ dominance. The first control's cold-start outlier does not establish a startup
568
+ improvement. This short-prompt workload does not measure long-prefill scaling.
569
+
570
+ All request bodies, token counts, usage, finish reasons and completion markers
571
+ match. Both candidates change the text of concurrent rows 1–3; candidate repeats
572
+ are identical to each other, as are control repeats. Other responses and parity
573
+ probes match. This is not an all-responses-identical regression result. Same-B
574
+ model checks pass on Qwen 27B and Gemma 12B on both Macs, and an admission-only diagnostic restores all
575
+ baseline responses, tying the text changes to shared prefill. An added M4 token-zero check subsequently
576
+ found a sampler-logit mismatch when finished rows project separately. A follow-up
577
+ candidate projects the batch before selecting sampler rows; these timing numbers
578
+ do not measure that fix. The corrected projection passes the M4 model/sampler
579
+ checks. Its fresh comparison is recorded below; the earlier measured candidate is not adopted.
580
+
581
+ Raw evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`,
582
+ including source manifest/patch, native checks and the four complete reports.
583
+
584
+ ## Batched prefill cohorts: corrected M4 comparison
585
+
586
+ The benchmark now also accepts `--aggregate-context <approximate tokens>` and
587
+ `--aggregate-stagger-ms <milliseconds>` for long, staggered HTTP requests.
588
+ Zero preserves the original short-prompt/simultaneous workload. Reports record
589
+ these settings, actual submission offsets, prompt/cache counts, first-token
590
+ latencies and total aggregate wall time. These workload changes must match
591
+ between comparison arms; the historical short-prompt numbers below use zeros.
592
+
593
+ The corrected candidate projects the forward batch before selecting each
594
+ sampler's logits. It is adopted in the unreleased working tree. Same machine,
595
+ model, protocol, settings and control as the preceding comparison, with fresh
596
+ control/candidate/candidate/control runs. Candidate source SHA-256
597
+ `84abd86ac44155298ec14cc59eeb0b51a0f1862d45e199b3597ef8a22d24a31f`.
598
+ All source hashes remain fixed, all preflight/save checks pass, and every arm
599
+ reports zero failures. Retained swap is 215 MB; the audio daemon allowance is
600
+ explicit, as in the preceding run.
601
+
602
+ | arm | five decode requests, total ms ↓ | cached first-token ms ↓ | B4 aggregate tok/s ↑ | ready ms | cold-start ms | peak RSS MiB |
603
+ |---|---:|---:|---:|---:|---:|---:|
604
+ | control 1 | 37,975.15 | 155.060 | 73.009 | 608.52 | 1,033.49 | 8,977.16 |
605
+ | candidate 1 | 37,989.93 | 154.810 | 73.042 | 608.63 | 1,029.35 | 8,980.83 |
606
+ | candidate 2 | 37,971.84 | 154.802 | 73.071 | 608.51 | 1,030.21 | 8,974.33 |
607
+ | control 2 | 37,974.80 | 154.991 | 73.003 | 609.87 | 1,027.01 | 8,954.62 |
608
+
609
+ Candidate means: decode wall **+0.016%**, cached latency **−0.142%**, aggregate
610
+ throughput **+0.069%**. Ready time changes by −0.102%, cold-start time by
611
+ −0.045%, and peak RSS by +0.130%. This is effectively flat performance for the
612
+ short-prompt workload, with no established speed win or strict serial dominance.
613
+ Long-prefill scaling remains unmeasured by this workload.
614
+
615
+ All 60 requests complete. Request bodies, token counts, usage, finish reasons
616
+ and completion markers match the baseline. The two candidate repeats produce
617
+ identical responses; the two controls do too. Three concurrent responses differ
618
+ between candidate and control, as in the earlier admission-only attribution.
619
+ Other responses match. These cross-shape text differences do not establish
620
+ an engine-only coding-task speedup or an all-responses-identical result.
621
+ The corrected same-B Qwen 27B and Gemma 12B checks include full logits,
622
+ token-zero sampler logits and restored continuation on both Macs.
623
+
624
+ Raw evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`,
625
+ particularly `projection-m4/`, `projection-benchmark-comparison.json`, and
626
+ `projection-manifest.json`. Main integration results are recorded in the manifest.
627
+
628
+ ## Staggered long prefill: M4 regression
629
+
630
+ Gemma 4 12B OptiQ, M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0.
631
+ Same ordinary KV4/cache settings as the preceding corrected comparison.
632
+ The benchmark adds `--aggregate-context 2048 --aggregate-stagger-ms 25` and
633
+ uses `--workload-seed prefill-long-0`. Actual aggregate prompt counts are
634
+ 1,289/1,281/1,287/1,287, with matching cache hits of 13/12/14/12 across all arms.
635
+ The target length is a character-based estimate, not a measured token count.
636
+ Client submission offsets are approximately 0/26/51/76 ms. Each request
637
+ produces 128 completion tokens. The existing prefill chunk default is 2,048.
638
+
639
+ Control source SHA-256
640
+ `4ab50112e6464d0d778f80398d8f61e3740c9a6dd5c3c9725f34b255c26b7711`;
641
+ candidate `003827c79e0bcefd65c33fe7366faa28ca60d7fd428063f6c3a159efd7a60991`.
642
+ Both include the same benchmark extension; inference code matches the preceding
643
+ control/corrected candidate respectively. All source hashes stay fixed, all
644
+ preflight/save checks pass, and all requests complete without failure. The
645
+ explicit audio allowance applies; retained swap remains 215 MB.
646
+
647
+ | arm | aggregate wall ms ↓ | aggregate tok/s ↑ | first request TTFT ms ↓ | mean request TTFT ms ↓ | peak RSS MiB |
648
+ |---|---:|---:|---:|---:|---:|
649
+ | control 1 | 25,278.61 | 20.254 | 9,007.88 | 15,911.29 | 8,947.95 |
650
+ | candidate 1 | 26,328.98 | 19.446 | 18,696.52 | 19,042.67 | 8,997.20 |
651
+ | candidate 2 | 26,543.42 | 19.289 | 18,849.50 | 19,193.88 | 9,013.50 |
652
+ | control 2 | 26,388.15 | 19.403 | 9,493.52 | 16,771.75 | 8,949.66 |
653
+
654
+ Candidate means show **2.333% longer aggregate wall time**, **2.324% lower
655
+ throughput**, **102.936% higher first-request TTFT**, and **16.992% higher mean
656
+ TTFT**. The controls' aggregate wall times differ by 4.4%, so the exact small
657
+ throughput penalty is not stable enough to generalize. The large first-request
658
+ latency penalty repeats clearly. Short decode request wall time changes by
659
+ −0.066%, and cached TTFT by −0.036%. Shared prefill has not passed long-request
660
+ performance acceptance. No serial deletion or default promotion follows.
661
+
662
+ Requests, usage, counts, finish reasons and completion markers match. Concurrent
663
+ rows 1–3 change text; other responses match, and each pair of repeated arms is
664
+ internally identical. This remains a comparison of identical submitted work,
665
+ not an all-responses-identical result or a coding-task quality assessment.
666
+
667
+ An M1 diagnostic with `MLX_BUN_P2R_TRACE=1` records the first request's internal
668
+ token-zero completion at about 6.25 s, but its first response write at 25.94 s.
669
+ The following B3 prefill chunk spans 18.25 s. This points to long preparation
670
+ work delaying active output, rather than admission waiting alone. It is
671
+ instrumented M1 attribution, not an M4 performance claim. A bounded M4 screen
672
+ with prefill chunks of 256 completes at 26,526.13 ms aggregate wall time and
673
+ 19.302 tok/s, with first-request TTFT 13,235.29 ms. It improves first output
674
+ relative to the candidate's 2,048-token chunks but still trails the earlier
675
+ control. The matching 256-token control completes at 26,011.10 ms and
676
+ 19.684 tok/s, with first-request TTFT 7,232.19 ms. The candidate therefore
677
+ still has 1.980% longer wall time and 83.005% higher first-request TTFT at
678
+ matching chunk size. Source/preflight/save checks pass with no failures.
679
+ Requests, usage/counts and completion markers match, but all four concurrent
680
+ texts differ. This one-pair screen does not qualify a default. Smaller chunks
681
+ change KV conversion boundaries and do not resolve the admission/work-unit
682
+ performance problem. Raw comparison: `long-chunk256-comparison.json` in the
683
+ evidence directory below.
684
+
685
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`,
686
+ including `long-m4/`, `long-benchmark-comparison.json`, and
687
+ `long-m1-prefill-traces.json`.
688
+
689
+ ## Prefill admission work budget: M4 comparison
690
+
691
+ The isolated scheduler candidate limits admission to an existing prefill cohort
692
+ using initial uncached token work. Its internal budget is 2,048 tokens; a larger
693
+ request still enters alone and runs through the same preparation method. An
694
+ earlier shrinking-weight screen restored first TTFT to 9,538.63 ms but completed
695
+ the group in 26,797.77 ms, versus 9,012.73/25,295.58 ms in the first control,
696
+ and still changed three responses. The fixed-weight candidate below avoids
697
+ attaching another long prompt to a nearly completed request.
698
+
699
+ M4 Pro 24 GB, Gemma 4 12B OptiQ, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0.
700
+ Same protocol and exact inputs as the preceding staggered-long comparison,
701
+ including KV4, prompt cache 4 GB, chunk default 2,048, 25 ms arrival spacing,
702
+ and `prefill-long-0`. Actual prompt/cache/output counts match. Control source
703
+ SHA-256 `4ab50112e6464d0d778f80398d8f61e3740c9a6dd5c3c9725f34b255c26b7711`;
704
+ fixed candidate `2dcee8a99708c66facd8aa296fe8b990de92eca5031453888947e9f9f35dfd72`.
705
+ Run order was control 1, the earlier shrinking-weight screen, fixed candidate 1,
706
+ fixed candidate 2, control 2. All source hashes remain fixed within their runs;
707
+ all preflight/save checks pass under the explicit audio-daemon allowance, with
708
+ 215 MB retained swap and no failed requests.
709
+
710
+ | arm | aggregate wall ms ↓ | aggregate tok/s ↑ | first request TTFT ms ↓ | mean TTFT ms ↓ | five decode requests, total ms ↓ | cached TTFT ms ↓ |
711
+ |---|---:|---:|---:|---:|---:|---:|
712
+ | control 1 | 25,295.58 | 20.241 | 9,012.73 | 15,955.67 | 37,922.95 | 154.872 |
713
+ | candidate 1 | 25,550.88 | 20.038 | 9,031.34 | 16,089.03 | 37,960.58 | 154.755 |
714
+ | candidate 2 | 26,390.25 | 19.401 | 9,526.85 | 16,783.75 | 38,091.45 | 155.456 |
715
+ | control 2 | 26,122.33 | 19.600 | 9,289.83 | 16,519.82 | 37,973.20 | 155.051 |
716
+
717
+ All 60 responses in the four fixed-candidate/control arms match exactly, including
718
+ request bodies, usage/counts, finish reasons and completion markers. Candidate
719
+ means are +1.018% aggregate wall time, −1.007% throughput, +1.397% first-request
720
+ TTFT, +1.223% mean TTFT, +0.205% short decode wall and +0.093% cached TTFT.
721
+ This restores the large latency regression from unrestricted cohorts, but does
722
+ not establish strict performance dominance. Aggregate timings vary by about
723
+ 3.3% within both candidate and control pairs. No default-speed win is claimed.
724
+
725
+ The policy is adopted in the unreleased working tree. Complete suites/types
726
+ and long-prefix Qwen/TurboQuant and Gemma/KV4 ownership checks pass on both
727
+ Macs. Main integration suite/typecheck pass.
728
+ A separate lifetime review found that the new loop retains unused hidden output
729
+ through cache maintenance, unlike the existing shared prefill primitive. Its
730
+ release-order screen is complete and is not adopted, as recorded below.
731
+
732
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`,
733
+ including `budget-m4/`, `budget-fixed-benchmark-comparison.json`, the earlier
734
+ `budget-remaining.patch`, and `budget-fixed-manifest.json`.
735
+
736
+ ## Prefill early-release lifetime screen: no measured win
737
+
738
+ The candidate disposes input IDs immediately after prefill forward and unused
739
+ hidden output before cache maintenance. Its control is the adopted fixed-work
740
+ admission policy above. Same M4 Pro 24 GB, Gemma 4 12B OptiQ snapshot, Bun 1.4.2,
741
+ MLX 0.32.2/native pack 0.4.0 and production `bench-serve.ts all` protocol:
742
+ KV4, prompt cache 4 GB, 192 decode tokens, skipped context sweep,
743
+ `prefill-long-0`, aggregate context target 2,048 and stagger 25 ms.
744
+ Actual aggregate prompts/cache hits remain 1,289/13, 1,281/12, 1,287/14,
745
+ 1,287/12, with 128 output tokens each. Control source SHA-256
746
+ `2dcee8a99708c66facd8aa296fe8b990de92eca5031453888947e9f9f35dfd72`;
747
+ candidate `46b351c3a4f4ed1442c946de388638b01611419fcc5a060c407f7a9da9584a80`.
748
+
749
+ | arm, in run order | aggregate wall ms ↓ | aggregate tok/s ↑ | first request TTFT ms ↓ | five decode requests, total ms ↓ | cached TTFT ms ↓ |
750
+ |---|---:|---:|---:|---:|---:|
751
+ | control 1 | 25,394.38 | 20.162 | 9,020.58 | 38,018.88 | 154.911 |
752
+ | candidate 1 | 25,537.82 | 20.049 | 9,033.96 | 37,966.96 | 154.710 |
753
+ | candidate 2 | 26,290.25 | 19.475 | 9,402.95 | 38,027.90 | 154.732 |
754
+ | control 2 | 25,888.99 | 19.777 | 9,164.43 | 38,000.93 | 154.781 |
755
+
756
+ All 60 responses, request bodies, usage/counts, finish reasons and completion
757
+ markers match exactly. All source/preflight/save checks pass; retained swap
758
+ stays at 208.25 MB under the explicit audio-daemon CPU allowance. No requests
759
+ fail. Candidate means are +1.062% aggregate wall time, −1.039% throughput,
760
+ +1.385% first TTFT, +1.366% mean TTFT, −0.033% short decode wall and
761
+ −0.081% cached TTFT. Aggregate run spread is 1.95% in controls and 2.95% in
762
+ candidates, so these small differences do not establish a causal slowdown.
763
+ Mean peak RSS differs by only −1.95 MB, or −0.022%, with no pressure test.
764
+ Cold start has a 2,132 ms first-control outlier versus roughly 1,095–1,100 ms
765
+ in the other three arms; its mean ratio is not evidence of a startup gain.
766
+
767
+ No speed or material measured-memory benefit is established. The candidate
768
+ remains isolated and is not adopted. M1 full suite/typecheck and Qwen 27B
769
+ same-B model/sampler/continuation checks on both Macs pass; M4 full suite and
770
+ typecheck were not run for this unadopted screen.
771
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`,
772
+ including `drain-m4/`, `drain-benchmark-comparison.json` and `drain-manifest.json`.
773
+
774
+ ## MTP preparation port and compiled activation: M4 comparison
775
+
776
+ This seven-file change adds provider-owned draft prefill using the existing
777
+ Qwen row state and replaces the companion's unfused MLP activation with the
778
+ compiled SwiGLU already used by the target. The new prefill port is not yet
779
+ connected to shared target preparation. This HTTP comparison therefore covers
780
+ the activation and row-lifecycle changes, not batched MTP prefill performance.
781
+ The same-B pinned companion check found 11 differing bf16 output values out of
782
+ 10,240 in one decoder continuation with the old activation, maximum absolute
783
+ difference 0.0078125; KV already matched. The shared compiled activation passes
784
+ all tested KV/full-decoder continuations at B1/B2/B3/B4 on both Macs, including
785
+ a 2,051-token prefix and cold/restored joins.
786
+
787
+ M4 Pro 24 GB, packed Qwen 27B Trellis interleave2 artifact and folded RTN4/g64
788
+ MTP companion, Bun 1.4.2, MLX 0.32.2/native pack 0.4.0. Production
789
+ `bench-serve.ts all`, explicit `mlx-bun` arm, MTP2, KV4, prompt cache 4 GB,
790
+ 192 decode tokens, five decode requests, context sweep disabled, original
791
+ short aggregate prompts at concurrency four, seed `mtp-serving-block-0`.
792
+ `MLX_BUN_TURBOQUANT_FUSED_DECODE=1` and
793
+ `MLX_BUN_TRELLIS_ASYNC_EXPAND=0` match the preceding MTP controls.
794
+ Control source SHA-256
795
+ `2dcee8a99708c66facd8aa296fe8b990de92eca5031453888947e9f9f35dfd72`;
796
+ candidate `69f3f37388ca0fdda2dd836786a20cb588c947fdc476b6206d617d7312d366fa`.
797
+
798
+ | arm, in run order | five decode requests, total ms ↓ | concurrent aggregate tok/s ↑ | cached TTFT ms ↓ |
799
+ |---|---:|---:|---:|
800
+ | control 1 | 55,546.48 | 15.7645 | 99.415 |
801
+ | candidate 1 | 55,705.24 | 15.6455 | 99.348 |
802
+ | candidate 2 | 55,931.24 | 15.7543 | 96.942 |
803
+ | control 2 | 55,905.67 | 15.7074 | 97.644 |
804
+
805
+ All 60 request bodies, response texts, prompt/output/cache token counts,
806
+ finish reasons and completion markers match. Five records per candidate arm
807
+ have different speculation statistics; candidate repeats agree exactly, as do
808
+ the controls. Four of the five decode requests have changed acceptance traces,
809
+ and one concurrent response has changed draft/acceptance counts. This follows
810
+ the corrected draft arithmetic and is not identical internal work. The targets
811
+ still return the same text and token counts.
812
+
813
+ Descriptive candidate/control means change decode wall by +0.165%, aggregate
814
+ throughput by −0.229%, aggregate wall by +0.230% and cached TTFT by −0.390%.
815
+ Readiness and cold-start means change by +0.059% and +0.051%. Mean peak RSS is
816
+ 14.82 MB lower, without a pressure test. All source/preflight/save checks pass
817
+ under the audio-daemon allowance, with no request or phase failures. Retained
818
+ swap grows across the runs, from 200.25 MB before the first control to 297.88 MB
819
+ after the final control; the environment is not a fixed zero-swap control.
820
+
821
+ No speed win, identical-work ratio or serial dominance is established. The
822
+ provider port and numerical correction are adopted in the unreleased working
823
+ tree after both-machine companion-oracle, native MTP, full-suite and typecheck
824
+ checks. Main integration suite/typecheck pass. Shared target/MTP prefill integration,
825
+ its serving/caching gates and a combined performance comparison remain open.
826
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`, including
827
+ `mtp-prefill-m4/`, `mtp-prefill-benchmark-comparison.json`,
828
+ `mtp-prefill-manifest.json`, and `mtp-prefill.patch`.
829
+
830
+ ## Delayed rotating prefill: M4 regression
831
+
832
+ Gemma 4 12B OptiQ 4-bit, snapshot
833
+ `5b1101065d2094c8f12aa87fee80e0afa5b292b7`, on the **M4 Pro / 24 GB**.
834
+ Bun 1.4.2, MLX 0.32.2, native pack 0.4.0. The control is
835
+ `padded-partial-validation`; the candidate is `delayed-padding-validation`.
836
+ Both use remote HEAD `0c355f4` plus their recorded working-tree changes.
837
+ The production snapshots are respectively
838
+ `27b65281f031a4ffc4f7db057a264f32aa8bbfab70bf4c2acb357176148f38b2` and
839
+ `89d209400c1f683143ee9afea30e8a440ee00159fe96ba8e1c3bbe5893c744ac`.
840
+
841
+ Four alternating runs use `bun scripts/bench-serve.ts all`, the exact artifact
842
+ above, `--arms mlx-bun --tokens 192 --skip-context --kv-quant 4 --prompt-cache 4
843
+ --workload-seed delayed-padding-0 --allow-cpu-process /usr/libexec/audiomxd`.
844
+ All preflights pass under the authorized audio-daemon CPU allowance, with fixed
845
+ source in each arm and identical workload/runtime settings. All 60 request
846
+ bodies, response texts, usage records, token counts and finish reasons match;
847
+ the separate parity probes also match. No request or phase failed.
848
+
849
+ | Arm | Five decode requests, total wall ms | Cached TTFT ms | B4 aggregate tok/s | Ready ms | Cold start ms | Peak RSS MiB |
850
+ |---|---:|---:|---:|---:|---:|---:|
851
+ | Control 1 | 37,952.57 | 154.73 | 72.98 | 608.63 | 1,022.52 | 8,992.91 |
852
+ | Candidate 1 | 37,969.02 | 155.03 | 72.85 | 607.89 | 1,024.32 | 8,971.34 |
853
+ | Candidate 2 | 38,284.21 | 155.46 | 72.54 | 608.21 | 1,021.92 | 8,982.78 |
854
+ | Control 2 | 38,207.34 | 155.07 | 72.90 | 608.12 | 1,023.51 | 8,990.95 |
855
+
856
+ Candidate means are **0.123% higher decode wall time**, **0.222% higher cached
857
+ TTFT** and **0.339% lower aggregate throughput**. Both candidate aggregate
858
+ observations are below both controls. These are small unfavorable differences,
859
+ not evidence of a speed win. Readiness is in the same 200 ms polling interval;
860
+ this Gemma block does not resolve the separate Qwen startup/cached-latency debt.
861
+
862
+ The change adds delayed rotating-cache preparation and is retained as feature
863
+ work. This benchmark exercises current serving, which still prefills requests
864
+ separately; it does not measure the future batched-prefill path or establish
865
+ serial dominance. Native preparation tests cover mixed-format attention and
866
+ encoded state through B8, with the numerical scope documented in batching.md.
867
+ Raw records and comparison: `reports/qwen38-closeout/composition-baseline/delayed-padding/`.
868
+
869
+ ## Recurrent padded prefill: M4 regression
870
+
871
+ Joshs-MBP-2025.local, Apple M4 Pro 24 GB, Bun 1.4.2, MLX 0.32.2/native
872
+ pack 0.4.0. Four alternating `bench-serve.ts all` arms use the same packed
873
+ Qwen KV4/MTP2, 192-token protocol above. The control includes the adopted
874
+ full/rotating KV padding interfaces. Sources remain fixed: control
875
+ `5431fdd0f20225e0493b12fb251db0b773f93d6ca92a2a5d09d64882a1161d04`,
876
+ candidate `98f5fb5038e3b63f3d1e28a3084f5d1da0a475aa28307761defd26f681e4eb82`.
877
+ Every start/end preflight passes with the audio-daemon allowance. All 60
878
+ requests match in request hash/body, text, complete usage/speculation counters,
879
+ token counts and finish reason. The separate parity probes also match. There
880
+ are no request or phase failures.
881
+
882
+ | Arm | Five decode requests, total ms | Cached TTFT ms | Concurrent aggregate tok/s |
883
+ |---|---:|---:|---:|
884
+ | Control 1 | 55,951.11 | 97.49 | 15.7960 |
885
+ | Candidate 1 | 55,713.07 | 97.38 | 15.8332 |
886
+ | Candidate 2 | 55,628.97 | 97.20 | 15.9066 |
887
+ | Control 2 | 55,639.46 | 98.99 | 15.9824 |
888
+
889
+ Candidate/control means change decode wall time by −0.223%, cached latency
890
+ by −0.964% and aggregate throughput by −0.122%. Candidate aggregate throughput
891
+ falls within the control range; cached latency is lower in both candidate arms.
892
+ This supports integration as a feature addition with
893
+ roughly flat decode/request performance, not a speedup or serial-dominance
894
+ claim. Peak RSS ranges from 12,161 to 12,227 MB. Readiness is
895
+ 608/817/813/612 ms; both candidate observations fall one 200-ms polling
896
+ interval later. Cold start is 3,726/4,207/4,200/4,006 ms. Startup equivalence
897
+ remains unproven and is not covered by the flat decode conclusion.
898
+
899
+ This checks existing unpadded serving behavior. Actual padded behavior passes
900
+ same-B 27B logit and convolution/recurrent-state oracles on both machines,
901
+ including B1 and uniform/unequal B3. MTP, TurboQuant, generated RAM/SSD reuse,
902
+ complete suites and typechecks also pass on both Macs. True batched serving
903
+ prefill, delayed-codec preparation and long-pressure acceptance remain open.
904
+ The recurrent-padding change is adopted in the unreleased working tree.
905
+ Evidence: `reports/qwen38-closeout/composition-baseline/padded-ssm/`.
906
+
907
+ ## Packed Qwen serial closeout on M4 Pro
908
+
909
+ Six balanced v6/v13 pairs on **Joshs-MBP-2025.local, Apple M4 Pro 24 GB**
910
+ complete with **114 matching paired requests and no failures**. This uses
911
+ Bun 1.4.0, MLX 0.32.2 and the advisory-memory candidate on `0c355f4` plus
912
+ its recorded patch. Source snapshot
913
+ `e0ebcb3fd1be6024623ffb4db08cdb5b7322a823d43df7ef1e803d11b37131b7`
914
+ is unchanged across all twelve runs. The packed interleaved artifact's
915
+ 20-file manifest hashes to
916
+ `24c56033e1ae4c816747f763b76a7420b6327236a3736c2a89462a22e4e512ce`.
917
+ Preflight passes under Josh's explicit `/usr/libexec/audiomxd` CPU allowance;
918
+ all blocks retain their memory, swap and thermal observations.
919
+
920
+ | Metric | v6 → v13 or paired factor | 95% block interval |
921
+ |---|---|---|
922
+ | Decode request wall time | 20.507 → 17.826 seconds pooled median; **1.1504×**, or **13.08% less time** | 1.1493–1.1514× |
923
+ | Decode SSE-window rate | 10.026 → 11.593 tok/s pooled median; 1.1562× | 1.1557–1.1568× |
924
+ | Cold 1K TTFT | 1.0145× | 0.9997–1.0292×; inconclusive |
925
+ | Warm 1K TTFT | 1.0889× | 1.0710–1.1083× |
926
+ | Long-prompt TTFT | 1.0039× | 0.9995–1.0083×; inconclusive |
927
+ | Four queued requests, aggregate rate | 1.1464× | 1.1457–1.1470× |
928
+ | Peak process RSS, inverse ratio | 0.9948× | 0.9755–1.0107×; no demonstrated reduction |
929
+
930
+ Factors above one favor v13. Intervals resample the six block log-ratios of
931
+ within-run summaries, not the individual requests. These describe this
932
+ controlled session, not variation across days or p99 latency. Each run has
933
+ five 192-token decode requests, cold/warm prefix requests, restart restoration
934
+ and the four-request aggregate leg. Actual long prompts contain
935
+ 10,397–10,399 tokens despite the synthetic `--context 16384` target. Both arms
936
+ use serial serving and bf16 KV; output hashes, prompt/output/reused-token
937
+ counts and finish reasons match throughout. The aggregate leg is queued
938
+ serial throughput, not evidence of simultaneous batch execution.
939
+
940
+ Final-source native checks also preserve full logits, cache state and
941
+ continuation at eight input lengths. Paired MTP-prefix restoration passes with
942
+ both bf16 and KV4 storage. Continuous and combined paired results follow below;
943
+ broader composed/pressure acceptance remains open; **no default is promoted by this serial result alone**.
944
+ Raw bundle: `reports/qwen38-closeout/m4-v6-v13-b{0..5}-v{6,13}.md.json`;
945
+ review and offline HTML: `m4-v6-v13-review.json`,
946
+ `m4-v6-v13-comparison.html`. Native evidence: `m4-final-native-runner.json`
947
+ and `m4-final-v13-*.log` in the same directory.
948
+
949
+ Six balanced longer-context continuous-serving pairs now pass on the same
950
+ M4 Pro, artifact, Bun/MLX versions and CPU allowance above. All 114 paired
951
+ requests match with no failures. Each run uses 256-token decode requests and
952
+ actual long prompts of about 20,717 tokens. The frozen source snapshot is
953
+ `363f74acc1e432677bfe333eec001c9111a1fb2c10128603409568f86dad58bb`.
954
+ The paired decode request-time factor is 1.15235×, or 13.22% less time,
955
+ with a 95% block interval of 1.15164–1.15316×. Four-request aggregate
956
+ throughput improves 2.37742×, with a 95% block interval of 2.37615–2.37856×.
957
+ These are same-session intervals, not across-day or sustained-load results.
958
+ Raw reports and review are
959
+ `reports/qwen38-closeout/m4-final-continuous-b{0..5}-v{6,13}.md.json`
960
+ and `m4-final-continuous-review.json`.
961
+
962
+ All six serial KV4 plus two-token MTP pairs with paired RAM prefixes now
963
+ pass, with all 114 paired requests matching and no failures. Source, host,
964
+ artifact and qualification match the longer-context continuous series above.
965
+ The paired decode request-time factor is 2.15832×, or 53.67% less time,
966
+ with a 95% block interval of 2.15467–2.16129×. Aggregate queued throughput
967
+ improves 2.07990×, with a 95% block interval of 2.07838–2.08162×. At long
968
+ context, decode SSE-window throughput improves 2.03668× and first-token time
969
+ improves 1.03885×. These compare kernel variant 13 with variant 6 while keeping
970
+ KV4 and MTP enabled in both arms; they do not isolate the benefit of MTP or
971
+ compare KV formats. All twelve restart requests reuse zero tokens: paired MTP
972
+ prefixes are RAM-only, so this is fresh-prefill restart measurement, not SSD
973
+ restoration. Raw reports and review are
974
+ `reports/qwen38-closeout/m4-final-kv4-mtp-b{0..5}-v{6,13}.md.json`
975
+ and `m4-final-kv4-mtp-review.json`. These measured settings are now selected in
976
+ the unreleased candidate source as documented in server-config.md; changing
977
+ default selection does not complete output-cache or execution consolidation.
978
+
979
+ The saved Kanban first-turn audit finds 50,479 reasoning tokens shared with
980
+ the next request beyond the original 2,550-token prompt. The following prompt
981
+ has 53,175 tokens. This is an offline tokenizer/template comparison, not a
982
+ performance measurement: no generated-state checkpoint has yet been accepted
983
+ for this saved long turn, and no saved time is claimed for it. Evidence:
984
+ `reports/qwen38-closeout/r17-first-tool-prefix-opportunity.json`.
985
+
986
+ ## Running the benchmark
987
+
988
+ `bun scripts/bench-serve.ts all` is THE benchmark — one pass, real servers,
989
+ real paths, every number that matters. Per model × arm (mlx-bun@defaults ·
990
+ mlx-bun `--batch 1` [the control arm — `--no-serial` skips] · mlx-lm ·
991
+ mlx-bun-mixed · optiq-mixed) it measures decode tok/s (five fixed samples,
992
+ all retained; unstable runs flagged), TTFT cold (~1k, nonce-busted) and warm/cached (each stack's own
993
+ prompt cache), prefill tok/s, long-context prefill/TTFT/decode (ONE measured
994
+ prefill; decode sampled on 64 tok + 2 cached repeats), aggregate tok/s at 4
995
+ concurrent streams, peak RSS (sampled; undercounts GPU), and load→ready time.
996
+ The same cells compare decoded text from greedy probes of up to 64 tokens
997
+ between stacks of the same scheme, including the serial control vs mlx-lm.
998
+ Prompt-count inequality rejects a comparison as template/tokenizer drift;
999
+ matching counts and text are a smoke check, not proof of identical token IDs
1000
+ or logits. Missing usage cannot produce a passing verdict. The engine's
1001
+ pinned logit oracle remains the correctness gate.
1002
+
1003
+ ```sh
1004
+ bun scripts/bench-serve.ts all # cpm5 + e4b + 12B + Qwen3.8-27B, all arms
1005
+ bun scripts/bench-serve.ts all --no-serial # skip the --batch 1 control arm
1006
+ bun scripts/bench-serve.ts all --models cpm5,qwen27b # subset
1007
+ bun scripts/bench-serve.ts all --skip-context # drop the long-context leg
1008
+ bun scripts/bench-serve.ts all --context 8192 # shorter context leg
1009
+ ```
1010
+
1011
+ For an exact local quant use `--model-path <dir>` and optionally `--label`.
1012
+ It replaces the registry selection and cannot be combined with `--models`.
1013
+ `--dry-run` prints artifact metadata and server commands, with no preflight,
1014
+ model load, database write or server process. Packed trellis skips stock
1015
+ mlx-lm/optiq arms; explicitly requesting those arms fails before starting a
1016
+ server. A fake-quant/8-bit carrier is a separate artifact and cannot establish
1017
+ same-artifact packed performance or decode parity.
1018
+
1019
+ ```sh
1020
+ bun scripts/bench-serve.ts all --model-path /path/to/quant --label qwen38-quant --dry-run
1021
+ bun scripts/bench-serve.ts all --model-path /path/to/affine --arms mlx-bun-serial,mlx-lm --context 4096 --out reports/affine-h2h.md
1022
+ bun scripts/bench-serve.ts all --model-path /path/to/packed --arms mlx-bun-serial --context 4096 --out reports/packed-baseline.md
1023
+ bun scripts/bench/model-inventory.ts /path/to/affine /path/to/packed > reports/model-inventory.json
1024
+ ```
1025
+
1026
+ `--workload-seed <block-id>` generates identical nonce-prefixed prompts for
1027
+ every engine and artifact in that block, with distinct nonces for retries.
1028
+ `--logprobs` and `--top-logprobs N` apply capture settings to every timed
1029
+ request, including concurrent requests, and record them in the workload and
1030
+ request hashes. SSE timing measures capture cost; wire-level logprob values
1031
+ are checked separately by the native/HTTP composition tests.
1032
+ Thinking is pinned on for all chat measurements. Long-context filler uses a
1033
+ fixed character estimate so token-count drift cannot silently change the
1034
+ input on one engine. Record actual token counts and compare raw request hashes.
1035
+ Use phase/attempt/index to distinguish a cold request from its identical warm
1036
+ repeat; request hashes alone do not identify cache state.
1037
+ For paired trials, alternate `--arms mlx-bun-serial,mlx-lm` and the reversed
1038
+ order across blocks; give every block its own seed and `--out` path.
1039
+
1040
+ Configured engine experiments accept `--draft-model`, `--draft-kind`,
1041
+ `--num-draft-tokens`, `--kv-quant`, `--prompt-cache` and `--adapter`. These options
1042
+ require explicit `--arms mlx-bun-serial,mlx-bun` (or either engine arm); run
1043
+ oracle controls separately. Both selected engine arms receive identical overrides.
1044
+ The dry-run, raw JSON and Markdown report retain the settings and relevant
1045
+ runtime overrides. No script under `reports/` is required to launch them.
1046
+ For the current packed Qwen artifact on the M4 Pro, run this after closing
1047
+ other workloads. It exercises the opt-in KV4/MTP/paired-prefix configuration
1048
+ through the current checkout and writes a new dated report under `reports/`.
1049
+
1050
+ ```sh
1051
+ MLX_BUN_TRELLIS_VARIANT=13 MLX_BUN_QWEN_SPEC_KV4=1 MLX_BUN_MTP_PROMPT_CACHE=1 MLX_BUN_RD_PREFILL_CHUNK=256 \
1052
+ bun scripts/bench-serve.ts all \
1053
+ --model-path "$HOME/models/Qwen3.8-27B-q3-trellis-ldlq-k300-packed-interleave2-rd" \
1054
+ --arms mlx-bun-serial \
1055
+ --draft-model "$HOME/models/Qwen3.8-27B-MTP-folded-rtn4-g64-rd" \
1056
+ --draft-kind mtp --num-draft-tokens 2 --kv-quant 4 --prompt-cache 4 \
1057
+ --context 4096 --tokens 192 --workload-seed pr47-block-0
1058
+ ```
1059
+
1060
+ Append `--dry-run` to inspect the command first. This serving suite is separate
1061
+ from the Luke Kanban task and does not establish its task-time speedup. This
1062
+ entry point writes Markdown plus the `<report>.md.json` companion; the offline
1063
+ HTML comparison report renders from saved companions:
1064
+
1065
+ ```sh
1066
+ bun scripts/bench/report.ts reports/a.md.json reports/b.md.json --out reports/compare.html
1067
+ bun scripts/bench/report.ts reports/a.md.json reports/native-bun.json --out reports/compare.html --baseline mlx-bun-serial
1068
+ ```
1069
+
1070
+ Use `--baseline mlx-bun-serial --baseline-env MLX_BUN_TRELLIS_VARIANT=6`
1071
+ to compare environment-selected variants of that same arm. The selected
1072
+ setting stays visible in both serving tables; the usual identity and workload
1073
+ requirements still apply.
1074
+
1075
+ Inputs are auto-detected: bench-serve schema-4 `<report>.md.json` files and
1076
+ `scripts/bench/native.ts` `native-inference-diagnostic` JSON. Rendering reads
1077
+ the saved JSON only — no weights, server, GPU, Python or network. The single
1078
+ self-contained file shows a provenance panel per input (file sha256, machine
1079
+ string, commit, Bun, runtime overrides, source snapshot hashes, server
1080
+ commands, workload seed, thinking mode), a per-machine serving matrix with a
1081
+ status on every cell (measured, recovered on retry, failed with the phase
1082
+ error, not-measured, or unsupported with the reason), correctness flags beside
1083
+ the timings (finish-reason mix, actual vs requested output counts, early EOS,
1084
+ warm/restart cached-token counts, durability, request errors, retries, parity
1085
+ verdicts), ratios only against a baseline arm on the same machine key,
1086
+ artifact and workload (`--baseline mlx-lm|mlx-bun-serial|mlx-bun`; default
1087
+ mlx-lm when present), per-machine comparison columns, decode-sample strips,
1088
+ an RSS-versus-decode plot, a native token-identity table, and the retained
1089
+ failures, stderr tails and raw request table. "decode" stays the SSE-window
1090
+ rate and "actual output / wall" the completion-token rate; RSS is process
1091
+ RSS from `ps`. The paired uncertainty table groups fixed-source trials across
1092
+ workload seeds and gives a 95% percentile-bootstrap interval for the geometric
1093
+ mean of block ratios. It resamples block log-ratios, requires at least five
1094
+ distinct seeds and ignores duplicate seeds. Its baseline is fixed when the
1095
+ report is generated. Quality-versus-size renders "not measured" until a quality
1096
+ input exists.
1097
+
1098
+ Request-derived speed ratios require matching request hashes, attempts, full
1099
+ output hashes, prompt/output and reused-token counts, and finish reasons. A mismatch keeps the
1100
+ absolute timings visible and suppresses the ratio. Full output hashes survive
1101
+ fixture trimming. Retry summaries use the final attempt; earlier samples and
1102
+ failures remain in the raw table. Diagnostic, nonquiet and changing-source
1103
+ runs cannot earn speed ratios. Cross-file comparisons require a recorded
1104
+ hostname, matching artifact path/config and the complete workload definition;
1105
+ matching config files alone do not establish matching weights. New serving
1106
+ companions record hostname and OS. Old files with no hostname compare only
1107
+ within their own file. Displayed ratios are ratios of medians, not paired
1108
+ confidence intervals or default-promotion evidence.
1109
+
1110
+ The bounded M1 Max smoke of this path uses MiniCPM, 16 requested decode
1111
+ tokens, `--skip-context`, and the unsplit reference. Both real-server arms
1112
+ complete without failed phases on fixed source. Warmup, the parity chat,
1113
+ five decode requests and the cold/warm 1K requests match full output hashes
1114
+ and reused-token counts. Concurrent four-request outputs still differ.
1115
+ Short decode timings are unstable; the run is explicitly diagnostic and
1116
+ cannot supply speed ratios or M4 acceptance. Raw data and review:
1117
+ `reports/qwen38-closeout/serve-smoke.md.json` and `serve-smoke-review.json`.
1118
+ The offline `comparison.html` includes this run beside both machines' saved
1119
+ evidence. Automated rendering/escaping checks pass; browser URL policy
1120
+ blocked visual inspection of the local HTML file.
1121
+
1122
+ `--reference-prefill server` keeps stock MLX-LM system/thinking segmentation
1123
+ and is the default. `--reference-prefill unsplit` selects an explicit Python
1124
+ reference control that passes one whole-prompt segment to BatchGenerator,
1125
+ which still reserves the final token. Tokenization, model operations,
1126
+ sampling and HTTP handling remain in the pinned reference. This changes
1127
+ prefill and cache policy and is recorded in commands, workload identity and
1128
+ the Markdown report. It applies to the `mlx-lm` arm, including models that
1129
+ need OptiQ registration. Use it only where it matches the Bun request's
1130
+ boundaries; it does not promise matching arbitrary multi-turn snapshots.
1131
+
1132
+ ```sh
1133
+ bun scripts/bench-serve.ts all --models cpm5,qwen27b --arms mlx-bun,mlx-bun-serial,mlx-lm --reference-prefill unsplit --out reports/matched-prefill.md
1134
+ ```
1135
+
1136
+ For an exclusively allocated GPU, `--allow-cpu-process /absolute/command`
1137
+ permits one explicitly reviewed background command to exceed the CPU
1138
+ threshold. The exact command and observed activity remain in the raw
1139
+ preflight snapshots and the report names the allowance. RSS, swap, thermal
1140
+ and overall-load checks still apply. This is not proof of an idle GPU or
1141
+ stable timing: verify GPU ownership and compare alternating repeated runs.
1142
+ Josh authorized this policy for `/usr/libexec/audiomxd` on the M4 Pro;
1143
+ CPU activity alone no longer blocks this campaign. Earlier diagnostic
1144
+ runs keep their original classification.
1145
+
1146
+ `--diagnostic` explicitly permits a loaded-machine serving run. It records
1147
+ the preflight snapshot and writes `*-serve-diagnostic` DB rows, which cannot
1148
+ serve as canonical results. Server children use the invoking Bun executable,
1149
+ so an isolated runtime comparison actually changes the server runtime too.
1150
+
1151
+ The Markdown report has a `<report>.md.json` companion containing all chat
1152
+ requests, results, failures and retries, plus config/source-diff hashes and
1153
+ server commands. Schema 4 also hashes a sorted manifest of tracked and
1154
+ untracked source files at startup and save time, so new local kernels cannot
1155
+ escape source identity. External native libraries and weights need their own
1156
+ manifests. Failed attempts include the child's stderr tail and process
1157
+ status; a successful retry keeps the recovered failure visible. It is saved
1158
+ after each completed or failed cell. The report
1159
+ separately records total request wall time and actual-output throughput.
1160
+ The decode columns use the first-to-last visible SSE interval: bursty chunks
1161
+ can distort that interval, so it is not a GPU timing. Token throughput requires
1162
+ valid server usage; chunk counting is no longer a fallback. Raw results also
1163
+ record response-header, first-byte and first-SSE-event latency, then every
1164
+ content/reasoning/tool-output event arrival. Event gaps measure stream
1165
+ delivery, not individual token latency. Tool-only streams have an output TTFT.
1166
+ Malformed/error SSE and responses without a finish reason or `[DONE]` fail
1167
+ the measurement. Match output counts, finish reasons and text before
1168
+ interpreting a speed difference. The exported `measureCompletionRequest`
1169
+ helper applies the same timing and stream-validation contract to raw
1170
+ `/v1/completions` requests, without chat-template preparation.
1171
+
1172
+ The inventory reads shard headers and config only, reconstructs matrix
1173
+ shapes including trellis axis-0 storage, and counts actual tensors rather
1174
+ than duplicate config aliases. Its matrix effective-bpw figure includes
1175
+ scales/biases but excludes norms, convolutions and sidecars; it is explicitly
1176
+ not whole-model bpw or peak memory. Config/index/layout hashes do not hash
1177
+ weight payloads. Use existing shard hashes or hash weights outside timed runs
1178
+ when certifying artifact identity. The complete Qwen campaign is in
1179
+ [the performance program](../design/decode-speed-program.md#7-qwen38-27b-research-program).
1180
+
1181
+ For native engine isolation, `scripts/bench/native.ts` runs dense Qwen3.5/3.8
1182
+ with bf16 attention KV, f32 recurrent state and greedy decoding. Supply a
1183
+ frozen JSON array of prompt token IDs and the exact local artifact to both
1184
+ stacks. Each request starts with a fresh cache; warmups and every measured
1185
+ sample are retained. Reports include actual output IDs, EOS policy, TTFT,
1186
+ wall time through cache cleanup/GPU synchronization, memory and source pins.
1187
+ They record the effective wiring policy and active/cached memory around each
1188
+ request. The oracle worker enters mlx-lm's normal scoped wired limit; compare
1189
+ that policy with Bun's model-sized scope before interpreting a ratio.
1190
+ `--clear-before-request` is a separate allocator-cache experiment on both
1191
+ stacks, with cleanup included in wall time. Keep it fixed within a pair;
1192
+ it does not clear model weights or substitute for a fresh inference cache.
1193
+ Stock mlx-lm rejects packed trellis. This worker uses the pinned oracle
1194
+ environment and never starts a server or downloads a model.
1195
+
1196
+ ```sh
1197
+ bun scripts/bench/native.ts --model-path /path/to/affine --prompt-ids reports/prompt-ids.json --stack mlx-bun --json reports/native-bun.json --dry-run
1198
+ bun scripts/bench/native.ts --model-path /path/to/affine --prompt-ids reports/prompt-ids.json --stack mlx-lm --json reports/native-oracle.json
1199
+ ```
1200
+
1201
+ Alternate stack order across predeclared process pairs. Check token IDs,
1202
+ output counts and finish reasons before comparing request wall times.
1203
+ `--diagnostic` permits a failed quiet-machine preflight and records that
1204
+ failure. Native results remain diagnostic, including on a quiet machine;
1205
+ they do not establish HTTP throughput, task quality or full logit parity.
1206
+ The repaired legacy `bench-h2h.ts direct` command delegates to this worker,
1207
+ requires `--models` and bf16 KV, and writes only `*-native-diagnostic` DB
1208
+ rows with raw report paths. Its rates use actual emitted tokens and all
1209
+ fixed samples. Use the worker directly to avoid registry ambiguity.
1210
+
1211
+ `all` runs the clean-machine preflight first (refuses headline numbers from
1212
+ a loaded or swapped box) and holds `caffeinate` for the pass. Quotable
1213
+ numbers and ratios need a quiet machine; loaded runs are diagnostic only.
1214
+ Results land in the eval DB (`~/.cache/mlx-bun/evals.sqlite`) plus dated
1215
+ Markdown and JSON reports under `reports/` by default. Developer lever A/Bs are NOT benchmarks — run
1216
+ `scripts/bench-levers.ts <faithful-matrix|fused-prefill|compiled-decode>` or
1217
+ `scripts/bench-matrix.ts <modes|features>` directly when touching those paths.
1218
+
1219
+ There are **three categorically different kinds of measurement** — kept in
1220
+ separate sections because they answer different questions:
1221
+
1222
+ 1. **Parity** — are we *bit-exact* with the upstream oracle? (pass/fail)
1223
+ 2. **Performance** — *numbers* under like-for-like config (tok/s, memory…).
1224
+ 3. **Quality** — for non-bit-exact optimizations, what does the speed cost
1225
+ in output quality? (6-test mean + KL)
1226
+
1227
+ **Default machine for older rows:** Apple M4 Pro, 24 GB unified
1228
+ (`Joshs-MBP-2025`), ~273 GB/s. Newer subsections name their machine explicitly.
1229
+ **Oracle toolchain:** Bun 1.3.14; Python 3.13.5 with mlx 0.31.2,
1230
+ mlx-lm 0.31.3, mlx-optiq 0.2.1. Numbers below are the 2026-06-14
1231
+ cleared-machine run (commits `97457e4` / `d1e0296`), preflight-gated,
1232
+ median-of-N with warmups discarded.
1233
+
1234
+ **Model legend** (registry hash → repo):
1235
+
1236
+ | hash | model |
1237
+ |---|---|
1238
+ | `664aabaed233` | `MiniCPM5-1B-OptiQ-4bit` (sub-GB starter) |
1239
+ | `fcdb12d740cd` | `gemma-4-e4b-it-OptiQ-4bit` |
1240
+ | `5b1101065d20` | `gemma-4-12B-it-OptiQ-4bit` |
1241
+ | `dbfd2a779b03` | `gemma-4-26B-A4B-it-OptiQ-4bit` (MoE) |
1242
+
1243
+ > **Legend corrected 2026-06-15.** An earlier revision had the gemma
1244
+ > hashes cycled (`5b…`→e4b, `dbfd…`→12B, `fcdb…`→26B). The mapping above is
1245
+ > the authoritative one from `tests/support/paths.ts` (`SNAPSHOT`=`5b…`=12B,
1246
+ > `SNAPSHOT_26B`=`dbfd…`=26B) and the e4b snapshot hash used across
1247
+ > `tests/*.test.ts` (`fcdb…`=e4b), corroborated by on-disk weight size
1248
+ > (e4b 7.0G · 12B 8.4G · 26B 18G). The **Performance** rows below were
1249
+ > labeled by the old legend; each gemma row has been relabeled to its true
1250
+ > model, re-identified by its gen-peak / steady-RSS fingerprint —
1251
+ > e4b≈6.6 GB, 12B≈9.0 GB, 26B≈17.7 GB — which is stable across runs. The
1252
+ > row *data* was correct; only the model labels moved.
1253
+
1254
+ ---
1255
+
1256
+ ## 1. Parity (porting correctness) — bit-exact vs the oracle
1257
+
1258
+ The correctness oracle. Each cell is **bit-for-bit** logit parity against
1259
+ the upstream reference under matched config, proven by the test suite
1260
+ (regenerated only by `scripts/regen-*.ts` against the oracle venv). This
1261
+ is the gate the Performance/Quality numbers are only meaningful *under*.
1262
+
1263
+ | model | L1: mlx-lm, standard (bf16) KV | L2: mlx-optiq, mixed-precision KV | proof |
1264
+ |---|---|---|---|
1265
+ | MiniCPM5-1B | ✓ 100/100 logit vectors | ✓ 100/100 logit vectors | `tests/parity/minicpm5-parity.test.ts`, `tests/parity/minicpm5-kv-parity.test.ts` |
1266
+ | gemma-4-e4b | ✓ | ✓ | `tests/parity/parity.test.ts`, `tests/parity/kv-quant.test.ts` |
1267
+ | gemma-4-12B | ✓ | ✓ | `tests/parity/parity.test.ts`, `tests/parity/kv-quant.test.ts` |
1268
+ | gemma-4-26B | ✓ | ✓ (mixed per-layer scheme) | `tests/parity/parity-26b.test.ts`, `tests/parity/rotating-kvq.test.ts` |
1269
+
1270
+ Fused quantized-attention prefill is separately bit-exact against
1271
+ optiq's reference (`tests/parity/fused-sdpa.test.ts`).
1272
+
1273
+ ### GLM-5.2 direct-Colibri oracle closure — M1 Max 32 GB
1274
+
1275
+ The direct-container port uses pinned Colibri, rather than mlx-lm, as its
1276
+ implementation oracle. The public artifact is
1277
+ `mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp@3cc8db9`; direct component and
1278
+ G0 controls use Colibri `44e489b`, while the later official DSA replay is
1279
+ pinned to `ecade075` with indexers sourced from
1280
+ `zai-org/GLM-5.2-FP8@ba978f7d`.
1281
+
1282
+ | gate | result | durable proof |
1283
+ |---|---|---|
1284
+ | tiny converted Q4 trajectory | 32/32 greedy tokens exact with `IDOT=0`; all 8,192 logits max abs `1.3113e-6`, RMSE `2.7423e-7` | `fixtures/colibri-glm52/tiny-teacher-forcing.json` |
1285
+ | production Q4/router cells | layer-0 SwiGLU max abs `5.2387e-9`; layers 3/77 exact ordered top-8 | `fixtures/colibri-glm52/production-probe.json` |
1286
+ | real-model oracle | 140 GLM/MLA/router/MTP/KV records reproduced byte-for-byte twice; both heads predict teacher token 16 | `fixtures/colibri-glm52/real-model-oracle.json` |
1287
+ | full target trajectory | all 128 cold/warm, MTP-on/off target token IDs identical; first 64 also match direct Colibri | machine-local `runs/colibri-g5/summary.json` |
1288
+ | first-sparse DSA | all 21 official score rows replay to exact ordered positions and float32 thresholds at context 2,049; both engines emit `[264,264]` | `~/.cache/mlx-bun/evidence/glm52-dsa-stage0-2026-08-17/` |
1289
+
1290
+ These are quality-preserving gates: checkpoint precision, true top-8 routing,
1291
+ and the 21-full/57-shared DSA schedule remain unchanged. Consequently there is
1292
+ no KL/eval tradeoff row in section 3 for this path.
1293
+
1294
+ **Served-surface parity (2026-07-07, prefill tail-split fix):** the two
1295
+ serve-bench parity residuals (cpm5 + 12B `/v1/completions` probe ✗ on the
1296
+ 07-07 run) are closed — with the oracle's step-0 prefill convention
1297
+ adopted (drain to len−1, step 0 from an L=1 forward of the last prompt
1298
+ token; `MLX_BUN_PREFILL_TAIL_SPLIT`), live HTTP probes are
1299
+ **byte-identical** to `mlx_lm.server`/optiq serve for MiniCPM5-1B,
1300
+ gemma-4-e4b, AND gemma-4-12B, on completion + chat probes, in both the
1301
+ unified (`--batch 8` default) and `--batch 1` lanes; script-level A/B
1302
+ shows 64/64 token ids + top-2 logprob values identical per step
1303
+ (`serve-parity-probe.ts (deleted; git history)`,
1304
+ `step0-top2-dump.ts (deleted; git history)`).
1305
+
1306
+ ---
1307
+
1308
+ ## Methodology change (2026-07-05)
1309
+
1310
+ The primary benchmark is now **`bun scripts/bench-serve.ts all` → `scripts/bench-serve.ts`**:
1311
+ real servers on real paths — the mlx-bun arms spawn the ACTUAL CLI at its
1312
+ actual defaults (the old harness used a bench-local wrapper, since deleted),
1313
+ and every metric arrives over HTTP as a user would see it. One server per
1314
+ cell yields: decode tok/s, cold TTFT (~1k, nonce-busted), warm/cached TTFT
1315
+ (each stack's own prompt cache), prefill tok/s, long-context
1316
+ prefill/TTFT/decode (ONE measured prefill; decode sampled on 64 tokens),
1317
+ aggregate tok/s at 4 concurrent streams, and load→ready time. Context
1318
+ lengths are recorded from usage.prompt_tokens (measured, not requested).
1319
+ Engine-level questions (in-process kernel parity, gen-peak memory,
1320
+ kill-switch A/Bs) live behind `bun scripts/bench-serve.ts all --engine`. Numbers below this
1321
+ note predate the redesign; the next quiet-machine pass supersedes them.
1322
+
1323
+ ## 2. Performance — like-for-like numbers
1324
+
1325
+ Two comparison axes: **vs the oracles**, and **our optimized path vs our
1326
+ own bit-exact compat path** (does an optimization beat the baseline it
1327
+ diverges from). Within mlx-bun, `bf16` is the L1-compatible path and
1328
+ `mixed` is the L2-compatible path; both are bit-exact, so the bf16↔mixed
1329
+ delta is the first "our-vs-our" axis. Lab experiment rows (no external
1330
+ oracle; KL/eval-gated) land here once one beats the L1 baseline in a
1331
+ paired A/B — none recorded yet (the 2026-07-05 candidates were deleted).
1332
+
1333
+ ### Standard serve matrix — M4 Pro 24 GB (2026-09-08, incomplete acceptance)
1334
+
1335
+ Josh ran `bun scripts/bench-serve.ts all` at clean commit `86738ac` on
1336
+ `Joshs-MBP-2025.local`, Apple M4 Pro, 24 GB, Bun 1.4.0, with the matching
1337
+ MLX 0.32.2 reference. Quiet preflight passed. There were no runtime overrides;
1338
+ the workload used `bench-serve-v2`, thinking enabled, five 192-token decode
1339
+ requests and a requested context target of 16,384. The actual context probes
1340
+ contained 9,062 MiniCPM tokens and 9,589 Gemma tokens. This is one ordered
1341
+ suite, not an alternating before/after optimization comparison.
1342
+
1343
+ | Model | Default mlx-bun decode tok/s | mlx-lm decode tok/s | Default mlx-bun request time | mlx-lm request time | Request-time reduction |
1344
+ |---|---:|---:|---:|---:|---:|
1345
+ | MiniCPM5-1B | 278.65 | 223.55 | 0.710 s | 0.936 s | 24.2% — output mismatch |
1346
+ | Gemma4-e4b | 57.86 | 53.63 | 3.402 s | 3.810 s | 10.7% |
1347
+ | Gemma4-12B | 26.14 | 25.40 | 7.576 s | 7.969 s | 4.9% |
1348
+ | Qwen3.8-27B 4/8-bit winner | 14.75 | 14.19 | 13.814 s | 14.523 s | 4.9% — output mismatch |
1349
+
1350
+ The table uses medians of the same five requests, all with exactly 192 output
1351
+ tokens. Request hashes, input/output counts and cached-token counts match
1352
+ between these arms. Both Gemma models also match all five timed output texts
1353
+ and both short parity probes. MiniCPM and Qwen differ on all five timed
1354
+ outputs despite matching counts; Qwen's separate 64-token probes match, while
1355
+ MiniCPM's chat probe diverges. Their timing rows remain observations pending
1356
+ the exact-token/logit investigation. The Gemma12B reference command invokes
1357
+ OptiQ's model registration before its mlx-lm serving path.
1358
+
1359
+ For Gemma e4b, cold/cached TTFT is 559/72 ms versus 707/212 ms in the
1360
+ reference, and the approximately 1K prefill estimate is 1,199 versus 947
1361
+ tok/s. For Gemma 12B those values are 2,531/157 ms versus 2,677/333 ms and
1362
+ 265 versus 250 tok/s. The serial controls finish the same short requests in
1363
+ 3.360 s and 7.514 s, respectively. Cached TTFT is one warm sample per cell.
1364
+
1365
+ Acceptance is incomplete. Qwen hits Metal out-of-memory errors in both the
1366
+ approximately 1K and context phases, in default and serial serving. Its
1367
+ reference recovers an initial 1K timeout, then fails the context phase and
1368
+ skips concurrency. MiniCPM and Gemma12B each report missing SSD snapshots on
1369
+ the first restart-flush attempt in default and mixed serving; retries succeed.
1370
+ Mixed-KV rows are not compared for L1 identity against bf16 KV. The complete
1371
+ report retains eleven phase-failure records, including recovered failures.
1372
+
1373
+ The Qwen artifact is the registry's 4/8-bit winner, not the required 12.14 GiB
1374
+ packed Trellis target. No MTP draft was configured. These numbers neither
1375
+ replace the Trellis/KV4/MTP measurements nor establish a Kanban task-time gain.
1376
+ Raw evidence: `reports/benchmarks-serve-2026-09-08-Joshs-MBP-2025.md` and its
1377
+ `.md.json` companion; source hashes are unchanged across the run.
1378
+
1379
+ The SSD follow-up at `f144516` fixes flush ordering: an ancestor removed from
1380
+ RAM can be covered by a longer trimmable snapshot written later in that same
1381
+ flush. After all writes settle, the coordinator checks committed coverage
1382
+ again and keeps uncovered prefixes dirty. The regression fails before the
1383
+ change and all 29 SSD tests pass afterward. The same M4 Pro repeats pass all
1384
+ phases on the first attempt for MiniCPM and Gemma12B in both default and mixed
1385
+ serving, restoring 9,061 and 9,588 tokens after restart. Source hashes stay
1386
+ fixed in both repeats. Default-arm timed request hashes and all ten output
1387
+ texts match the original run. The original failure records remain intact;
1388
+ this follow-up does not resolve their separate cross-oracle output differences.
1389
+ Evidence: `reports/qwen38-rd/pr47-ssd-followup.md.json` and
1390
+ `reports/qwen38-rd/pr47-ssd-followup-mixed.md.json`.
1391
+
1392
+ The subsequent boundary investigation identifies the timed-output difference
1393
+ on MiniCPM and Qwen. For each model's first saved request, Bun and Python match all 192
1394
+ complete native logit vectors. Stock Python HTTP instead splits at the
1395
+ thinking marker: MiniCPM uses prefill lengths 29, 1, 1 instead of 30, 1;
1396
+ Qwen uses 75, 1, 1 instead of 76, 1. Those segmented native Python runs
1397
+ reproduce the original reference responses after HTTP thinking-tag removal.
1398
+ The explicit unsplit reference control then reproduces all ten saved Bun
1399
+ decode responses, with identical output counts and finish reasons. Request
1400
+ hashes match. The first MiniCPM replay reuses zero tokens versus four in the
1401
+ original run; the other nine cache counts match. These are M4 Pro correctness
1402
+ diagnostics, not a replacement timing cohort or a speed claim. Qwen's Metal
1403
+ prefill failures and quiet paired timing acceptance remain open. Evidence:
1404
+ `reports/qwen38-closeout/prefill-segmentation-review.json` and its hashed
1405
+ native/HTTP companions. The initial invalid-model-ID replay is retained on
1406
+ the M4 Pro as `cpm5-replay-invalid-model-id.json`.
1407
+
1408
+ The Qwen memory follow-up on the same M4 Pro distinguishes a fresh-process
1409
+ control from the suite's retained state. The saved “1K” request actually has
1410
+ 757 prompt tokens and succeeds after a fresh warmup. Replaying the preceding
1411
+ warmup, completion/chat parity probes and five decode requests with SSD cache
1412
+ enabled reproduces the Metal OOM on the original source. An isolated
1413
+ per-layer prefill-evaluation prototype passes the fresh control; its full
1414
+ history replay completes warmup and the raw completion probe, then times
1415
+ out before the parity chat finishes. SSH subsequently became unavailable
1416
+ and recovered without a reboot. The timeout has no resolved cause, and the
1417
+ prototype is not integrated. Raising the fit estimate alone does not resolve
1418
+ the observed OOM. Local fresh controls and recovered history trials are
1419
+ `reports/qwen38-closeout/qwen27b-memory-{server,barrier}-{fresh,history}.json`;
1420
+ the M4 keeps the history trials under the unsuffixed names. Preflight still
1421
+ rejects retained swap. No speed or memory improvement is accepted from
1422
+ these trials.
1423
+
1424
+ After the M4 reboot and unlock, the frozen candidate still fails the 1K
1425
+ prefill phase on both attempts. Layer evaluation gets all four cold/warm 1K
1426
+ requests through with the seven preceding outputs and usage unchanged, but
1427
+ four-request serving then fails with a Metal OOM. Reserving successor state
1428
+ for all batch rows gets all 15 requests through. Both changes are now in the
1429
+ working candidate. Twelve same-version oracle cases (prefix lengths 0/64,
1430
+ forward lengths 1/4/8/16/128/757) preserve complete logits, recurrent state
1431
+ and continuation exactly. A longer replay completes 38 requests across
1432
+ continuous and serial serving, including a 2,679-token context and SSD
1433
+ restart restoring 2,678 tokens. All 15 individually issued requests match
1434
+ across lanes in output and usage; the four concurrent responses differ and
1435
+ are excluded from cross-lane speed comparisons.
1436
+
1437
+ These remain correctness diagnostics under their original run policy.
1438
+ A subsequent control removes per-token memory polling from continuous
1439
+ decode and reserves at batch joins. It completes 19 requests with a
1440
+ 5,239-token context and restores 5,238 tokens from SSD. The integrated
1441
+ reservation also accounts for cache growth to the requested output caps;
1442
+ its repeat preserves all 19 request identities, outputs and usage counts.
1443
+ Josh then clarified that the isolated audio CPU load is acceptable with
1444
+ memory and GPU availability; new acceptance runs record the explicit
1445
+ allowance described above. Earlier diagnostics are not relabeled.
1446
+ Evidence under `reports/qwen38-closeout/`:
1447
+ `m4-{candidate,layer-eval,layer-batch}-memory.md.json`,
1448
+ `m4-memory-review.json`, `m4-layer-state-{bun,reference,review}.json`,
1449
+ `m4-memory-context{.md,-review}.json`,
1450
+ `m4-{join-only,reserved-growth}-memory.md.json` and
1451
+ `m4-join-reservation-review.json`; artifact hashes are in
1452
+ `m4-candidate-preparation.json`. No speed default is promoted.
1453
+
1454
+ The first CPU-allowance R0 block (same M4 Pro, candidate on `0c355f4`,
1455
+ Bun 1.4.0, MLX 0.32.2, stock GPU ceiling, explicit unsplit reference)
1456
+ passes preflight before and after on fixed source. All five decode requests
1457
+ match across continuous Bun, serial Bun and Python in complete output,
1458
+ prompt/generated/reused tokens and finish reason. Within-arm decode spread
1459
+ is 0.49%, 1.05% and 0.78%, respectively; this is one block, not a paired
1460
+ speed verdict. Continuous serving completes all phases. Without the earlier
1461
+ context leg's server restart, serial serving fails the fourth queued request
1462
+ with Metal OOM. Python's 1K timeout and final aggregate failure also contain
1463
+ Metal OOM tracebacks, at prompt-state evaluation and pipelined decode.
1464
+ The earlier longer replay therefore does not close retained-history pressure.
1465
+ A focused allocation trace reproduces the fourth-request failure with
1466
+ 18,783,888,604 active bytes, a four-byte allocator pool, 2,485,518,336 bytes
1467
+ of RAM prefixes and a 199,133,984-byte reservation against the
1468
+ 19,069,665,280-byte GPU ceiling. The pool is not the missing memory; the
1469
+ remaining 86,642,692 bytes do not establish room for overlapping asynchronous
1470
+ state updates. A two-successor boundary reservation then completes all 30
1471
+ requests across both Bun lanes without failures. The 29 successful requests
1472
+ from R0 match output and usage; the formerly failed serial request matches
1473
+ the earlier context/restart control. Full-output reservation and longer
1474
+ generation are the next gates. Evidence:
1475
+ `m4-serial-allocation-probe.md.json`, `m4-serial-allocation-review.json`,
1476
+ `m4-two-state-memory.md.json` and `m4-two-state-memory-review.json` in
1477
+ `reports/qwen38-closeout/`.
1478
+ Raw: `reports/qwen38-closeout/m4-r0-audio-allowed-01.md.json` and
1479
+ `m4-r0-audio-allowed-01-review.json`.
1480
+
1481
+ ### Fresh Kanban candidate generation — M4 Pro (2026-09-09)
1482
+
1483
+ The frozen optimized candidate completed the pinned Luke Kanban prompt on
1484
+ Joshs-MBP-2025.local (M4 Pro 24 GB, Bun 1.4.0, MLX 0.32.2, Pi 0.85.1)
1485
+ in **5,085.387 seconds (1h 24m 45.387s)** from prompt submission to completion.
1486
+ It generated 68,958 output tokens across 15 requests, with zero Pi retries,
1487
+ compactions or tool errors. Pi and the server exited zero; the outcome parser
1488
+ confirmed completion, profile requests were valid, and source hashes stayed fixed.
1489
+ The run used packed interleave2, variant 13, KV4, MTP depth 2 and paired RAM
1490
+ prefixes, with the authorized audio CPU allowance. R17 generated-history
1491
+ checkpointing was not implemented in this candidate.
1492
+
1493
+ The untouched generated app passes all 18 required browser acceptance categories,
1494
+ including native card/column dragging, combined filters, archive/restore,
1495
+ keyboard operation and persistence in both themes. Source hashes are unchanged. The earlier successful task generated a different number of tokens
1496
+ and tool turns, so this duration does not establish an engine-only speedup.
1497
+ The first/new runs used 75/21 tool calls, 7/0 tool errors and 1/0 compactions.
1498
+ Summed pre-first-output time is 3,399.895/814.988 seconds. New task time is
1499
+ 60.2% lower and output count 47.2% lower, without an engine-only attribution.
1500
+ The sole initial-request difference is Pi's working-directory suffix:
1501
+ `kanban-final-workspace` versus `kanban-closeout-candidate-r1-workspace`,
1502
+ verified as five additional tokens by the model tokenizer. Both used batch 1
1503
+ and MTP depth 2. Detailed acceptance and comparison:
1504
+ `reports/qwen38-closeout/kanban-run-comparison.md`; raw evidence:
1505
+ `reports/qwen38-closeout/kanban-final-candidate-r1/`.
1506
+
1507
+ ### Direct scheduler B=1 versus serial — both machines (2026-09-08)
1508
+
1509
+ Josh's September 8 standard suites include both default scheduling and strict
1510
+ serial controls. M1 Max 32 GB used clean commit `1ac8f61`; M4 Pro 24 GB used
1511
+ clean commit `86738ac`. Both used Bun 1.4.0, no runtime overrides, and passed
1512
+ quiet preflight. Compare arms within each machine; the machines have different
1513
+ source commits. These are single ordered suites, not alternating repeat blocks.
1514
+
1515
+ Median short-decode SSE rates from five 192-token requests per arm:
1516
+
1517
+ | Model | M1 default / serial tok/s | M4 default / serial tok/s |
1518
+ |---|---:|---:|
1519
+ | MiniCPM5-1B | 268.79 / 267.81 | 278.65 / 275.86 |
1520
+ | Gemma4-e4b | 63.85 / 64.01 | 57.86 / 59.03 |
1521
+ | Gemma4-12B | 30.33 / 30.33 | 26.14 / 26.44 |
1522
+ | Qwen3.8-27B 4/8-bit winner | 18.58 / 18.56 | 14.75 / 14.66 |
1523
+
1524
+ All 40 paired timed responses match between default and serial in request hash,
1525
+ output text, prompt/cached/generated token counts, finish reason and DONE status.
1526
+ Completion and chat parity probes also match for all eight model/machine cells.
1527
+ This comparison is between our two executors; it does not erase the separate
1528
+ Python-reference differences recorded in the M4 section above. Default B=1
1529
+ short-decode rates are within 0.4% of serial on M1 and within 2.0% on M4.
1530
+ The M1 suite has no phase failures. The M4 suite retains its recorded SSD retry
1531
+ and Qwen prefill OOM failures; short-decode agreement is not whole-suite acceptance.
1532
+
1533
+ The M1 four-request aggregate rates, default versus serial, are 408.12/243.14
1534
+ (MiniCPM), 101.60/60.91 (e4b), 41.32/27.95 (12B), and 20.08/15.72 (Qwen),
1535
+ in tok/s. These measure aggregate throughput, not single-request latency.
1536
+ The results support sharing a scheduler with a B=1 case; they do not establish
1537
+ feature completeness for replacing the dedicated executor, including MTP.
1538
+ Raw reports: `reports/benchmarks-serve-2026-09-08-Joshs-MacBook-Pro.md.json`
1539
+ and the M4's `reports/benchmarks-serve-2026-09-08-Joshs-MBP-2025.md.json`
1540
+ (local preserved copy: `reports/qwen38-closeout/m4-standard-20260908-original.json`).
1541
+
1542
+ ### Batched logprob composition — M4 Pro, acceptance open (2026-09-09)
1543
+
1544
+ Two ordered/reversed `bench-serve.ts all` blocks use the packed interleave2
1545
+ Qwen artifact on Joshs-MBP-2025.local, M4 Pro 24 GB, Bun 1.4.0 and MLX
1546
+ 0.32.2. Both pass preflight with the authorized audio CPU allowance. The
1547
+ frozen sampler candidate uses selected logprobs plus top-3 capture, unchanged
1548
+ kernels, five 192-token decode requests and the short-context suite with SSD
1549
+ caching. Its source predates the subsequent explicit-seed placement change;
1550
+ these benchmark requests have no explicit seed. Neither block has a failure.
1551
+
1552
+ | Block/order | Median decode request ms, serial / batch B=1 | Cached TTFT ms, serial / batch B=1 | Cached request ms, serial / batch B=1 |
1553
+ |---|---:|---:|---:|
1554
+ | 0, serial then batch | 17,833.47 / 17,785.57 | 261.16 / 307.45 | 800.68 / 846.69 |
1555
+ | 1, batch then serial | 17,840.70 / 17,771.87 | 272.90 / 319.81 | 812.66 / 858.99 |
1556
+
1557
+ All 22 single-request pairs match request/output hashes, token counts, finish
1558
+ reason and DONE status. Only three of eight concurrent pairs match complete
1559
+ outputs across serial and batch execution, so their timing does not establish
1560
+ an identical-work speedup. The cached response regression keeps performance
1561
+ acceptance open. Existing ordinary-execution M1/M4 baselines above remain valid.
1562
+
1563
+ Raw reports and review: `reports/qwen38-closeout/composition-baseline/`
1564
+ `logprobs-composition-{0,1}.md.json` and `logprobs-performance-review.json`.
1565
+ A third block enables `MLX_BUN_EARLY_FIRST_TOKEN=1` in both arms using
1566
+ block 0's requests. Source hashes remain fixed and no phase fails. Serial /
1567
+ batch B=1 median decode request time is 17,847.38 / 17,782.37 ms, cached
1568
+ TTFT 194.87 / 242.19 ms, and cached request time 809.63 / 860.77 ms. All
1569
+ 15 within-block response pairs match, including the four concurrent requests.
1570
+ All 11 single-request outputs also match block 0; two concurrent batch outputs
1571
+ change with the different admission timing. Early output improves delivery in
1572
+ both arms but leaves the cached-request regression open. It is not a default
1573
+ promotion. Raw: `logprobs-early-composition-0.md.json` and
1574
+ `logprobs-early-performance-review.json` in the same directory.
1575
+
1576
+ Bounded P2R diagnostics there separate recurrent-boundary SSD persistence
1577
+ from output-delivery delay. Traced timings are diagnostic only.
1578
+
1579
+ ### Shared uniform KV4 composition — M4 Pro, acceptance open (2026-09-09)
1580
+
1581
+ One ordered serial/default block uses the packed interleave2 artifact with
1582
+ uniform KV4, selected logprobs and top-3 capture on M4 Pro 24 GB, Bun 1.4.0,
1583
+ MLX 0.32.2. Both commands receive identical KV options. Preflight passes with
1584
+ the authorized audio allowance, source hashes stay fixed, and no phase fails.
1585
+ Serial / shared B=1 median decode request time is 17,866.95 / 17,814.16 ms;
1586
+ median SSE decode rate is 11.5556 / 11.5569 tok/s. Cached TTFT is 271.67 /
1587
+ 292.97 ms and cached request time 813.85 / 834.49 ms. The cached latency gap
1588
+ keeps acceptance open; this single ordered block cannot establish stability.
1589
+ All 11 single-request pairs match complete responses. Only one of four
1590
+ concurrent pairs matches, so the aggregate timings do not establish an
1591
+ identical-work speedup. The frozen candidate includes the shared KV conversion
1592
+ and uniform placement change; later removal of an obsolete startup warning is
1593
+ not part of this source snapshot.
1594
+
1595
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1596
+ `uniform-kv4-composition-0.md.json` and `uniform-kv4-performance-review.json`.
1597
+
1598
+ ### Immutable RAM prefix prototype — M4 Pro (2026-09-09)
1599
+
1600
+ The first borrowed-prefix prototype uses the same packed artifact, selected
1601
+ logprobs/top-3, SSD cache and workload as logprob block 0 above. On M4 Pro
1602
+ 24 GB, Bun 1.4.0, MLX 0.32.2, preflight passes with the authorized audio CPU
1603
+ allowance. Source hashes remain fixed and no phase fails. Serial / shared
1604
+ B=1 median decode request time is 17,874.77 / 17,758.63 ms, cached TTFT
1605
+ 256.93 / 168.77 ms and cached request time 796.78 / 707.51 ms.
1606
+
1607
+ All 11 single-request pairs match. Every output within each arm also matches
1608
+ that arm in original logprob block 0. Two of four concurrent pairs match
1609
+ across arms; aggregate timings do not establish identical-work performance.
1610
+ This prototype still makes serial requests flush durability before generation.
1611
+ The later removal of that flush must be measured in both arms before claiming
1612
+ that shared B=1 dominates the best serial implementation.
1613
+
1614
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1615
+ `borrowed-prefix-composition-0.md.json` and
1616
+ `borrowed-prefix-performance-review.json`.
1617
+
1618
+ ### Eventual SSD persistence — M4 Pro, acceptance open (2026-09-09)
1619
+
1620
+ The next frozen candidate retains immutable RAM prefixes and removes the
1621
+ serial request-time durability flush. It uses the same machine, toolchain,
1622
+ artifact, capture settings and block-0 workload as the prototype above.
1623
+ Preflight passes with the audio allowance, source hashes remain fixed and
1624
+ there are no failures. Serial / shared B=1 median decode request time is
1625
+ 17,768.44 / 17,787.02 ms, cached TTFT 163.57 / 168.03 ms and cached request
1626
+ time 703.55 / 706.67 ms. All 11 single-request pairs match, and every output
1627
+ within each arm matches original logprob block 0. Two of four concurrent
1628
+ pairs match across arms.
1629
+
1630
+ This removes the large cached-request regression in the earlier logprob
1631
+ comparisons. One ordered block does not establish that the remaining small
1632
+ difference is stable or that shared B=1 dominates serial. A subsequent change
1633
+ makes background writes acquire idle ownership without requesting a batch
1634
+ drain; its balanced serving comparisons are separate acceptance work.
1635
+
1636
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1637
+ `eventual-cache-composition-0.md.json` and
1638
+ `eventual-cache-performance-review.json`.
1639
+
1640
+ ### Idle persistence queue on Bun 1.4.2 — M4 Pro (2026-09-09)
1641
+
1642
+ Two ordered/reversed blocks measure immutable RAM reuse, removal of the
1643
+ request-time flush, and background writes that acquire the engine only when
1644
+ idle. Both use the packed Qwen artifact, bf16 KV, selected logprobs/top-3,
1645
+ SSD caching and the same block-0 requests. M4 Pro 24 GB, Bun 1.4.2, MLX
1646
+ 0.32.2; preflight passes under the audio allowance. The source hash is identical
1647
+ across both blocks and remains fixed; neither block has a failure.
1648
+
1649
+ | Order | Median decode request ms, serial / shared B=1 | Cached TTFT ms, serial / shared B=1 | Cached request ms, serial / shared B=1 |
1650
+ |---|---:|---:|---:|
1651
+ | Serial then batch | 17,772.00 / 17,750.51 | 163.13 / 167.44 | 703.25 / 706.08 |
1652
+ | Batch then serial | 17,746.81 / 17,757.96 | 162.87 / 167.51 | 701.86 / 706.03 |
1653
+
1654
+ All 22 single-request pairs match complete response identity. Every output
1655
+ within each arm also matches original logprob block 0. Four of eight concurrent
1656
+ pairs match across arms, so aggregate timing does not establish identical-work
1657
+ performance. Decode request time differs by less than 0.13%, while shared B=1
1658
+ retains a consistent 4.3–4.6 ms cached first-output gap. Strict dominance is
1659
+ still unproven. The later correction to the batch's reported first-token
1660
+ clock is not included; these numbers come from client-observed timings.
1661
+
1662
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1663
+ `idle-persistence-bun142-composition-{0,1}.md.json` and
1664
+ `idle-persistence-bun142-performance-review.json`.
1665
+
1666
+ ### First-admission device pipeline — M4 Pro (2026-09-09)
1667
+
1668
+ The first ordinary row now enters the existing pending GPU-token register,
1669
+ allowing the next forward to overlap its first readback. This also includes
1670
+ the corrected first-token metric timestamp. The frozen candidate was measured
1671
+ in both arm orders on M4 Pro 24 GB, Bun 1.4.2 and MLX 0.32.2, using the same
1672
+ packed artifact, bf16 KV, logprobs/top-3, SSD and block-0 requests as the
1673
+ idle-persistence comparison. Both preflights pass with the audio allowance,
1674
+ source stays fixed across both blocks and no phase fails.
1675
+
1676
+ | Arm order | Decode request median ms, serial / shared B=1 | Cached TTFT ms, serial / shared B=1 | Cached request ms, serial / shared B=1 |
1677
+ |---|---:|---:|---:|
1678
+ | Serial first | 17,759.74 / 17,745.59 | 163.25 / 163.38 | 703.29 / 701.71 |
1679
+ | Shared first | 17,754.03 / 17,746.97 | 162.61 / 163.53 | 701.91 / 702.64 |
1680
+
1681
+ All 22 single-request pairs match, and every output within each arm matches
1682
+ the idle-persistence baseline. Four of eight concurrent pairs match across
1683
+ arms; these do not support an identical-work aggregate speed claim. The
1684
+ change reduces the prior cached-TTFT gap to 0.12–0.91 ms and is adopted in
1685
+ the working tree. Shared B=1 does not strictly dominate every measured
1686
+ latency, and this composition does not close the full feature matrix.
1687
+
1688
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1689
+ `first-row-pipeline-composition-{0,1}.md.json` and corresponding
1690
+ `first-row-pipeline-composition-{0,1}-review.json`. Both blocks identify source
1691
+ `5cd1cb0668b743303cd6b05ba8779fd9075280d97585b008ac2da9d03f462c7f`.
1692
+
1693
+ ### Batched sliding-window correctness — M1 Max and M4 Pro (2026-09-09)
1694
+
1695
+ The shared executor passes the live, pinned same-B MLX-LM oracle on Gemma
1696
+ 12B and e4b on both M1 Max 32 GB and M4 Pro 24 GB, with Bun 1.4.2 and
1697
+ MLX 0.32.2. Each cell compares 48 complete float32 logit vectors exactly.
1698
+ Three unequal prompt lengths straddle the configured sliding window: two
1699
+ cross it during decode and one starts beyond it. The two arrival schedules
1700
+ include staggered retirement and a late join. This closes Phase 18's ordinary
1701
+ Gemma ring-wrap gate; it does not qualify quantized layouts or other methods.
1702
+
1703
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1704
+ `m1-gemma12b-batch-ring-wrap.log`,
1705
+ `m4-gemma12b-batch-ring-wrap-complete-inputs.log`,
1706
+ `m1-gemmae4b-batch-ring-wrap.log`, and
1707
+ `m4-gemmae4b-batch-ring-wrap.log`. The first M4 launch failed before model
1708
+ loading because its scratch checkout lacked test support files; the complete
1709
+ input rerun is the accepted result. No performance conclusion uses test time.
1710
+
1711
+ ### Compatible adapter groups — M4 Pro (2026-09-09)
1712
+
1713
+ Gemma e4b OptiQ snapshot `98d7dc6`, `fixtures/adapters/upper`, bf16 KV and
1714
+ SSD cache, on M4 Pro 24 GB with Bun 1.4.2 and MLX 0.32.2. The configured
1715
+ adapter and block-0 requests are identical across the serial and shared arms.
1716
+ Both arm orders pass preflight with the recorded audio allowance, retain a
1717
+ fixed source, and finish every phase.
1718
+
1719
+ | Arm order | Decode request median ms, serial / shared B=1 | Cached TTFT ms, serial / shared B=1 | Cached request ms, serial / shared B=1 | Observed four-request throughput tok/s, serial / shared |
1720
+ |---|---:|---:|---:|---:|
1721
+ | Serial first | 3,654.29 / 3,671.12 | 36.88 / 37.66 | 162.18 / 161.73 | 51.76 / 161.42 |
1722
+ | Shared first | 3,678.68 / 3,675.22 | 37.58 / 37.96 | 162.13 / 161.98 | 51.82 / 161.27 |
1723
+
1724
+ All 22 single-request output/usage pairs match. Six of eight concurrent
1725
+ pairs match across arms; every output is stable within its own arm across
1726
+ orders. The concurrent throughput figures therefore are observed workload
1727
+ results, not an identical-output speedup. Single-request decode changes winner
1728
+ with order; cached first output remains slightly slower on the shared path.
1729
+ Strict serial-dominance acceptance remains open.
1730
+
1731
+ Native adapter B=1 control, compatible B=2, mixed queues, callback failure,
1732
+ separate prefix reuse and queued adapter replacement pass on M1/M4. Both
1733
+ machines match 48 full logit vectors against the pinned same-B adapter oracle.
1734
+ KV4 plus logprobs also passes the native composition checks on both machines;
1735
+ this is not an external quantized-batch oracle claim.
1736
+
1737
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1738
+ `adapter-composition-{0,1}.md.json` and
1739
+ `adapter-composition-performance-review.json`. Frozen source:
1740
+ `e92487827cbb4755f5bd0cb4880999b2aa1d1aba64a86b7bfc6042b0b458723c`.
1741
+ Native logs: `m1-batch-adapters-replacement.log`,
1742
+ `m1-batch-adapter-oracle.log`, `m4-batch-adapters-oracle.log`, and
1743
+ `{m1,m4}-batch-adapters-kv4-logprobs.log`.
1744
+
1745
+
1746
+ ### State-only recurrent replay experiment — M4 Pro (2026-09-09)
1747
+
1748
+ Packed Qwen 27B with its folded RTN4 MTP companion, depth four and KV4,
1749
+ Bun 1.4.2 and MLX 0.32.2 on the M4 Pro 24 GB. Both versions use the same
1750
+ serial serving control and shared prefill cache. Only recurrent prefix replay
1751
+ changes. The existing serving suite ran reference/candidate, then
1752
+ candidate/reference, with matched requests within each block. Preflight passed
1753
+ under Josh's audio-daemon CPU allowance; raw reports retain `canonical:false`.
1754
+
1755
+ | Block/order | Five decode requests, reference → candidate | Sum of four queued request times, reference → candidate | Cached TTFT, reference → candidate |
1756
+ |---|---:|---:|---:|
1757
+ | 0, reference/candidate | 135,674.99 → 135,614.72 ms | 176,655.25 → 176,192.41 ms | 94.03 → 94.10 ms |
1758
+ | 1, candidate/reference | 130,083.45 → 129,893.97 ms | 189,279.10 → 189,066.15 ms | 93.98 → 93.78 ms |
1759
+
1760
+ All 30 recorded responses match in text, counts, cached coverage and finish
1761
+ reason; both completion/chat probes match and no phase failed. The five-request
1762
+ decode totals improve by only 0.044% and 0.146%. Warmup complete time regresses
1763
+ in both blocks, by 8.41% and 0.32%. This is **inconclusive for default promotion**.
1764
+ The independently required batched recurrence can use its row-length-aware
1765
+ kernel; uniform replay retains its existing kernel pending a demonstrated win.
1766
+
1767
+ Raw files: `reports/qwen38-closeout/composition-baseline/`
1768
+ `state-replay-{reference,candidate}-{0,1}.md.json` and
1769
+ `state-replay-performance-review.json`. Both sources stay fixed across blocks:
1770
+ reference `a01bee0b7e1962c8211f1ffd845d95f7923d6c04bddb18cf06f07483cab9e7e8`,
1771
+ candidate `9ea170f63a70b143a978fd2f8519c265a363760fcc5921ab7fe7c51f6ff2a173`.
1772
+ These reports measure the isolated replay experiment, not the subsequent
1773
+ attention-cache and draft-interface work.
1774
+
1775
+
1776
+ ### Shared MTP drafting candidate — M4 Pro (2026-09-09)
1777
+
1778
+ Packed Qwen 27B, folded RTN4 companion, MTP depth two, KV4, Bun 1.4.2 and
1779
+ MLX 0.32.2 on the M4 Pro 24 GB. The candidate replaces the request-local
1780
+ draft/commit loop with the shared row method at B=1. Both use the existing
1781
+ serving control and shared prefill cache. The official serving suite ran in
1782
+ both orders with 192-token decode requests. Preflight passed under Josh's
1783
+ audio-daemon CPU allowance; reports retain `canonical:false`.
1784
+
1785
+ | Block/order | Five decode requests, reference → candidate | Sum of four queued request times, reference → candidate |
1786
+ |---|---:|---:|
1787
+ | 0, reference/candidate | 53,764.24 → 53,884.42 ms | 80,319.89 → 81,191.39 ms |
1788
+ | 1, candidate/reference | 56,025.69 → 56,363.44 ms | 78,935.80 → 81,001.15 ms |
1789
+
1790
+ All 30 recorded request hashes, response hashes, token counts, cached coverage
1791
+ and finish reasons match, with no failures and unchanged source snapshots.
1792
+ Decode complete time regresses by 0.22% and 0.60%; summed queued-request time
1793
+ regresses by 1.09% and 2.62%. The four-request 1k-context phase also regresses,
1794
+ by 2.09% and 3.04%. This candidate has not established equal-or-better serving
1795
+ performance and is not adopted. Native before/after prefix continuations match
1796
+ on both Macs; those correctness results do not close the timing gate.
1797
+
1798
+ Raw: `reports/qwen38-closeout/composition-baseline/`
1799
+ `mtp-row-{reference,candidate}-{0,1}.md.json` and
1800
+ `mtp-shared-draft-performance-review.json`. Frozen source hashes:
1801
+ reference `a0f66ee4bbf357cdd7ace981e31c4f21d8e1705b7f052e5bd6ce0b8bccf68ab5`,
1802
+ candidate `dcaf122ce30b38e60847af6c0fd4df59232ccb2552ec7fb98019d231e1757b75`.
1803
+ Four queued requests here still execute one at a time; this is not B=4 MTP
1804
+ serving acceptance.
1805
+
1806
+ The subsequent candidate replaces the B=1 hidden gather with a slice of the
1807
+ same verification context. On the same machine/toolchain and settings, two
1808
+ new matched blocks preserve all 30 responses, counts, cached coverage and
1809
+ finish reasons, plus both parity probes, with no failures or source changes.
1810
+
1811
+ | Block/order | Five decode requests, reference → slice candidate | Sum of four queued request times, reference → slice candidate | Cached TTFT, reference → slice candidate |
1812
+ |---|---:|---:|---:|
1813
+ | 0, candidate/reference | 56,802.25 → 56,806.30 ms | 83,579.51 → 82,931.12 ms | 93.85 → 93.78 ms |
1814
+ | 1, reference/candidate | 55,672.47 → 56,315.67 ms | 80,785.87 → 82,545.85 ms | 93.54 → 94.80 ms |
1815
+
1816
+ The first block's decode time is essentially flat; the reverse-order block
1817
+ regresses by 1.16%. Queued-request gains also reverse, and the 1k-context phase
1818
+ changes by -0.57% then +2.34%. This does not close the performance gate. The
1819
+ source replacement and slice specialization remain isolated. Do not attribute
1820
+ the full variation to the gather or claim a speedup from the first block.
1821
+
1822
+ Raw: `mtp-slice-{reference,candidate}-{0,1}.md.json` and
1823
+ `mtp-slice-performance-review.json` in the same report directory. Reference
1824
+ hash is unchanged; slice candidate hash is
1825
+ `665acf5432f5cde64207a475edff0f999215f2fb9df014fce8db295e6cc20bd9`.
1826
+
1827
+ ### Concurrent MTP serving candidate — M4 Pro (2026-09-09)
1828
+
1829
+ Packed Qwen 27B, folded RTN4 companion, MTP depth two and KV4, Bun 1.4.2
1830
+ and MLX 0.32.2 on the M4 Pro 24 GB. The existing serving suite compares
1831
+ strict serial with shared execution in both arm orders. Each block uses
1832
+ matched requests and a fixed source, with 192-token decode requests and no
1833
+ long-context leg. Preflight passes under the recorded audio CPU allowance.
1834
+
1835
+ | Arm order | Five decode requests, serial / shared | Cached TTFT, serial / shared | Observed four-request throughput, serial / shared |
1836
+ |---|---:|---:|---:|
1837
+ | Serial first | 56,130.19 / 55,549.00 ms | 93.58 / 214.00 ms | 15.88 / 16.18 tok/s |
1838
+ | Shared first | 54,137.25 / 53,914.05 ms | 93.63 / 218.90 ms | 16.08 / 16.41 tok/s |
1839
+
1840
+ All 22 single-request output/usage pairs and both parity probes match, with
1841
+ no phase failures. Single-request decode totals improve by 1.04% and 0.41%,
1842
+ but cached first output regresses in both orders. This does not meet serial
1843
+ dominance and is not adopted. Seven of eight concurrent outputs differ across
1844
+ arms, so aggregate throughput is an observed result, not an identical-output
1845
+ speed ratio. The separate native/HTTP gate confirms real B=4 MTP verification.
1846
+
1847
+ The next revision exposes preparation output through the shared scheduling
1848
+ readiness interface. Scheduling yields after admission completes, before the
1849
+ next graph. The same two arm orders give:
1850
+
1851
+ | Arm order | Five decode requests, serial / shared | Cached TTFT, serial / shared | Observed four-request throughput, serial / shared |
1852
+ |---|---:|---:|---:|
1853
+ | Serial first | 56,583.61 / 55,563.91 ms | 93.64 / 98.28 ms | 15.52 / 16.21 tok/s |
1854
+ | Shared first | 54,175.23 / 53,514.51 ms | 93.48 / 99.70 ms | 16.09 / 16.19 tok/s |
1855
+
1856
+ All 22 single-request pairs match, with no phase failures. Decode totals
1857
+ improve by 1.80% and 1.22%. The remaining cached TTFT gap is 4.64 and 6.22 ms,
1858
+ so strict serial dominance remains open. Seven of eight concurrent outputs
1859
+ again differ, preventing an identical-output aggregate speed claim.
1860
+ Moving publication ahead of the remaining state admission gives these results:
1861
+
1862
+ | Arm order | Five decode requests, serial / shared | Cached TTFT, serial / shared | Observed four-request throughput, serial / shared |
1863
+ |---|---:|---:|---:|
1864
+ | Serial first | 56,139.21 / 55,564.02 ms | 93.64 / 97.75 ms | 15.76 / 16.24 tok/s |
1865
+ | Shared first | 54,122.55 / 54,352.40 ms | 93.60 / 100.76 ms | 16.09 / 15.89 tok/s |
1866
+
1867
+ All 22 single-request pairs still match, with no failures. Decode totals change
1868
+ by -1.02% and +0.42%; the cached first-output gap remains. Seven concurrent
1869
+ outputs differ. This revision also does not establish dominance. The next
1870
+ candidate removes allocator cache clearing from shared output delivery while
1871
+ preserving the methods' own maintenance. It also fixes cleanup after state
1872
+ admission. Its two arm orders produce:
1873
+
1874
+ | Arm order | Five decode requests, serial / shared | Cached TTFT, serial / shared | Observed four-request throughput, serial / shared |
1875
+ |---|---:|---:|---:|
1876
+ | Serial first | 56,857.65 / 55,535.73 ms | 94.48 / 99.33 ms | 15.50 / 16.24 tok/s |
1877
+ | Shared first | 54,107.37 / 53,587.76 ms | 93.70 / 98.99 ms | 16.09 / 16.16 tok/s |
1878
+
1879
+ All 22 single-request pairs and parity probes match, with no failures. Decode
1880
+ totals improve by 2.32% and 0.96%, but cached TTFT trails serial by 4.85 and
1881
+ 5.28 ms. Seven concurrent outputs differ. Allocator maintenance separation
1882
+ therefore does not resolve the latency gap or qualify serial removal.
1883
+
1884
+ Raw reports and reviews in
1885
+ `reports/qwen38-closeout/composition-baseline/`:
1886
+ `mtp-serving-serial-shared-0.md.json`, `mtp-serving-shared-serial-1.md.json`,
1887
+ `mtp-serving-performance-review.json`, `mtp-serving-output-yield-0.md.json`,
1888
+ `mtp-serving-output-yield-1.md.json` and
1889
+ `mtp-serving-output-yield-performance-review.json`, `mtp-serving-staged-0.md.json`,
1890
+ `mtp-serving-staged-1.md.json`, `mtp-serving-staged-performance-review.json`,
1891
+ `mtp-serving-method-maintenance-0.md.json`, `mtp-serving-method-maintenance-1.md.json`
1892
+ and `mtp-serving-method-maintenance-performance-review.json`.
1893
+ Initial frozen source:
1894
+ `4799c307be193a2cd53c91d95940c40e7294f41b13a07693ab4a45097be60d25`.
1895
+ First readiness revision:
1896
+ `e7d6955ea0ae8133b6445a5180fd68a784c8913072a13579f08392896cff8904`.
1897
+ Staged admission revision:
1898
+ `309d671bdcdd4830765d6af2341fe3b68a04c2eb9795929f9d6bcfb12f55e04d`.
1899
+ Method-owned maintenance revision:
1900
+ `311043d3a1add4bebffffc820a96f83dc415ad3ac6d6a17133e75540909ff273`.
1901
+
1902
+ The subsequent combined source includes the TurboQuant codec/row components.
1903
+ The first matched block keeps KV4/MTP2, so it measures overhead in the existing
1904
+ workload rather than TurboQuant serving. Compared directly with the previous
1905
+ method-maintenance block on the same M4:
1906
+
1907
+ | Metric | Previous shared | Combined shared |
1908
+ |---|---:|---:|
1909
+ | Five decode requests, complete time | 55,535.73 ms | 55,560.29 ms |
1910
+ | Median decode | 19.211 tok/s | 19.196 tok/s |
1911
+ | Cached TTFT | 99.33 ms | 99.55 ms |
1912
+ | Four concurrent requests | 16.238 tok/s | 16.241 tok/s |
1913
+
1914
+ All 15 shared request/output/usage pairs match, as do all 15 serial-control
1915
+ pairs. Shared decode time changes by +0.044%; this is effectively unchanged,
1916
+ not a demonstrated speed gain. The serial control changes by -0.94%. No phase
1917
+ fails and the combined source stays fixed. This is one arm-order block;
1918
+ the reverse-order repeat remains open. The first settings sweep follows.
1919
+ Raw report: `decode-composition-combined-0.md.json`; review:
1920
+ `decode-composition-previous-run-review.json`, in the same reports directory.
1921
+ Combined source:
1922
+ `2b7b258c983729be4dc723493ad6a14eea853c0166df9f2a36a4a3b27344f51c`.
1923
+
1924
+ The first settings sweep uses that same frozen source, the same block-0
1925
+ requests and the shared server. Each row includes five 192-token decode
1926
+ requests, short cold/cached prompts and four concurrent requests. Long-context
1927
+ and restart benchmark legs are excluded. Every report has zero failed phases
1928
+ and a stable source snapshot; the audio CPU allowance remains recorded.
1929
+
1930
+ | KV / draft depth | Five decode requests | Median decode | Cached TTFT | Four concurrent requests |
1931
+ |---|---:|---:|---:|---:|
1932
+ | Affine 4 / MTP2 | 55.560 s | 19.196 tok/s | 99.55 ms | 16.241 tok/s |
1933
+ | Affine 8 / MTP2 | 55.067 s | 19.442 tok/s | 98.96 ms | 16.329 tok/s |
1934
+ | Affine 4 / MTP4 | 136.714 s | 7.493 tok/s | 97.23 ms | 14.522 tok/s |
1935
+ | Affine 8 / MTP4 | 131.855 s | 7.683 tok/s | 97.48 ms | 15.170 tok/s |
1936
+
1937
+ MTP2 leads this first sweep. Changing precision or draft depth can change the
1938
+ continuation; these are observed configuration rates, not identical-output
1939
+ engine speedup ratios. The small KV8/MTP2 lead needs repetition. The expanded
1940
+ screen below adds async weight expansion, no-MTP controls and TurboQuant
1941
+ serving. No default changes are justified by this single block. Raw settings reports are
1942
+ `decode-settings-{kv8-mtp2,kv4-mtp4,kv8-mtp4}-0.md.json`; the summary is
1943
+ `decode-settings-first-sweep-review.json` in the same reports directory.
1944
+
1945
+ ### Integrated settings screen and context repeat — M4 Pro (2026-09-09)
1946
+
1947
+ The isolated shared-serving candidate now includes TurboQuant ordinary/MTP
1948
+ groups. All 20 reports below use stable source
1949
+ `6e293a0efeb2f22e2557bf0e39373774545dc0737496c07e7bbe8cfbf6cd3939`,
1950
+ the same packed Qwen artifact and folded RTN4 companion, Bun 1.4.2,
1951
+ MLX 0.32.2 and the M4 Pro 24 GB. Preflight passes with Josh's audio-CPU
1952
+ allowance. The server's batch capacity is eight; the aggregate leg submits
1953
+ four requests. Separate native serving gates establish actual four-row MTP
1954
+ verification. These reports retain `canonical:false`.
1955
+
1956
+ Short-context block 0 uses matching requests and five 192-token decode
1957
+ samples. Fused TurboQuant decode is enabled; async Trellis expansion is off
1958
+ unless labeled. No report has a failed phase.
1959
+
1960
+ | KV / method | Five requests, complete ms | Median decode tok/s | Cached TTFT ms | Aggregate ×4 tok/s |
1961
+ |---|---:|---:|---:|---:|
1962
+ | bf16 / ordinary | 88,763.10 | 11.593 | 163.76 | 25.776 |
1963
+ | bf16 / MTP2 | 54,064.81 | 19.793 | 96.49 | 16.822 |
1964
+ | bf16 / MTP3 | 53,904.19 | 20.089 | 98.79 | 16.952 |
1965
+ | Affine 4 / ordinary | 89,551.02 | 11.521 | 164.78 | 25.689 |
1966
+ | Affine 4 / MTP1 | 61,737.80 | 17.170 | 96.91 | 15.695 |
1967
+ | Affine 4 / MTP2 | 55,544.22 | 19.200 | 99.49 | 16.247 |
1968
+ | Affine 4 / MTP3 | 61,344.01 | 17.198 | 98.07 | 16.208 |
1969
+ | Affine 4 / MTP2, async | 55,282.33 | 19.167 | 99.02 | 16.243 |
1970
+ | Affine 4 / MTP4, async | 136,386.37 | 7.487 | 97.26 | 14.559 |
1971
+ | Affine 8 / ordinary | 88,955.50 | 11.571 | 167.18 | 25.679 |
1972
+ | Affine 8 / MTP1 | 62,207.00 | 17.003 | 97.45 | 15.510 |
1973
+ | Affine 8 / MTP3 | 56,289.15 | 18.991 | 99.90 | 16.664 |
1974
+ | TQ K8V3 / ordinary | 90,881.00 | 11.403 | 174.53 | 25.308 |
1975
+ | TQ K8V3 / MTP2 | 56,578.08 | 19.242 | 102.53 | 16.429 |
1976
+ | TQ K8V3 / MTP3 | 56,923.87 | 19.065 | 102.78 | 16.046 |
1977
+ | TQ K8V3 / MTP4 | 131,849.48 | 7.593 | 101.34 | 14.481 |
1978
+
1979
+ The affine-4/MTP2 integration control preserves all 15 request/output pairs
1980
+ against the preceding `2b7b…` source; complete decode time changes by -0.029%,
1981
+ effectively unchanged. Its async arm also preserves all 15 outputs, with
1982
+ complete time -0.47% in this one block. Async expansion does not remove the
1983
+ MTP4 decode cliff. MTP3 uses its third proposal: affine-4 accepts 109 of 386
1984
+ third-position drafts, affine-8 accepts 114 of 373. Acceptance alone does not
1985
+ make the extra work profitable.
1986
+
1987
+ The four leading comparison profiles then run full `bench-serve all` with
1988
+ block-1 inputs and `--context 16384`. The rendered prompt actually contains
1989
+ **10,398 tokens**. Each context leg has a cold request and two RAM-cached
1990
+ repeats, followed by an explicit durable flush and SSD restart.
1991
+
1992
+ | KV / method | Five short requests, complete ms | Short decode tok/s | Context decode tok/s | Cold context TTFT ms | SSD restart TTFT ms |
1993
+ |---|---:|---:|---:|---:|---:|
1994
+ | bf16 / MTP3 | 56,107.03 | 19.179 | 23.130 | 80,060.42 | 2,026.44 |
1995
+ | TQ K8V3 / MTP3 | 58,195.34 | 18.350 | 19.580 | 79,777.84 | 1,936.05 |
1996
+ | Affine 4 / MTP2 | 53,548.41 | 20.133 | 22.184 | 79,860.36 | 1,919.74 |
1997
+ | Affine 4 / MTP3 | 56,923.65 | 18.999 | 22.826 | 79,912.94 | 1,930.17 |
1998
+
1999
+ Within each profile the three context responses match exactly. Every restart
2000
+ restores 10,397 cached tokens, with zero pending, dropped or failed spills
2001
+ after flush. Across settings, continuations can differ; these rates do not
2002
+ establish an identical-output engine speedup. MTP2 leads affine-4 short
2003
+ requests, while MTP3 has a small context-decode lead. Ordinary batching has
2004
+ the strongest aggregate throughput in the short screen. The choice of one
2005
+ default for typical single-user multi-turn/tool use remains open pending
2006
+ late-task context measurements and balanced repeats; user overrides remain.
2007
+
2008
+ Raw files in `reports/qwen38-closeout/composition-baseline/`:
2009
+ `decode-integrated-*-0.md.json`, `decode-default-*-context-1.md.json` and
2010
+ `decode-integrated-settings-review.json`. Source archives remain frozen on
2011
+ the M4; no candidate default has been promoted.
2012
+
2013
+ The subsequent late-context control uses the same frozen source and
2014
+ `--context 125000`. KV4/MTP2 fails the context phase, including its retry,
2015
+ with Metal command-buffer out-of-memory at the default 2,048-token prefill
2016
+ chunk. It supplies no context decode or restart result. Preflight passed
2017
+ with 96 MB retained swap and 93% free memory; swap remained 96 MB afterward.
2018
+ Raw: `decode-default-kv4-mtp2-late-context-0.md.json` in the same directory.
2019
+ The next depth-3 attempt was stopped before the context leg to avoid repeating
2020
+ the same oversized configuration. A separate depth-2/3/1 comparison uses
2021
+ `MLX_BUN_RD_PREFILL_CHUNK=256`, matching the published Kanban prefill profile;
2022
+ depth 2 now completes at **78,678 actual prompt tokens**. Cold first-output time
2023
+ is 884.14 seconds, context decode median is 12.828 tok/s, cached repeat
2024
+ first-output time is 237.45 ms and fresh-process SSD restart first-output time
2025
+ is 2,229.68 ms with 78,677 cached tokens. All three context outputs match;
2026
+ the eight-token restart output matches their beginning. Flush is durable with
2027
+ zero pending, dropped or failed writes, and the source hash remains unchanged.
2028
+ Depth 3 also completes on unchanged source. Its cold first-output time is
2029
+ 884.68 seconds, context decode median 11.718 tok/s, cached first-output time
2030
+ 187.75 ms and SSD restart first-output time 2,235.34 ms with 78,677 tokens
2031
+ restored. Its three context outputs match each other, but differ from depth 2;
2032
+ these are settings comparisons, not identical-output engine comparisons.
2033
+ Durability also passes with no pending, dropped or failed writes. Depth 1
2034
+ completes at 10.582 tok/s context decode, with 884.59 seconds cold first-output
2035
+ time, 189.69 ms cached first-output time and 2,243.35 ms after SSD restart.
2036
+ It restores 78,677 tokens; all three context outputs match depth 2. Source
2037
+ hashes are stable, both preflights pass and there are no phase failures or
2038
+ pending, dropped or failed writes. These single profiles do not select a
2039
+ default. Raw: `decode-default-kv4-mtp{1,2,3}-late-context-chunk256-0.md.json`.
2040
+ Ordinary shared prefill in the frozen benchmark source does not read that
2041
+ control. The adopted policy fix makes ordinary and speculative prefill use the group's
2042
+ captured default and preserves the library request override. Its M1 seeded
2043
+ native and MTP RAM/SSD gates, complete model-free suite and typecheck pass; a matched M4
2044
+ ordinary late-context arm remains open.
2045
+
2046
+ The composed ownership/prefill-policy short control is complete on the M4
2047
+ Pro, with source `04f518534d568d10cd570e3ecd671a69ccbe97513f803d3a29ac250269416a0d`.
2048
+ It uses the same block-0 requests, KV4/MTP2, default prefill chunk and runtime
2049
+ settings as the frozen `6e293a0...` arm. All 14 measured request hashes,
2050
+ response texts, generated counts and cached counts match. Five decode requests
2051
+ take 55,619.41 ms versus 55,544.22 ms, a 0.14% increase; median decode is
2052
+ 19.195 versus 19.200 tok/s. Cached first-output time is 97.56 versus 99.49 ms,
2053
+ and four-request aggregate throughput is 16.203 versus 16.247 tok/s. This
2054
+ single comparison is effectively unchanged, with no performance win claimed.
2055
+ There are no phase failures and source hashes remain stable. The arm includes
2056
+ the Gemma ownership fix and captured prefill policy, but not generated-output
2057
+ publication. Raw: `composition-baseline/decode-prefill-policy-kv4-mtp2-short-0.md.json`
2058
+ under `reports/qwen38-closeout/`.
2059
+
2060
+ The same composed source also completes the 78,678-token KV4/MTP2 context
2061
+ control with 256-token chunks. All 19 request hashes, response texts,
2062
+ generated counts and cached counts match the frozen arm. Cold first-output
2063
+ time is 884.12 versus 884.14 seconds; context decode median is 12.918 versus
2064
+ 12.828 tok/s. Cached first-output time is 188.35 versus 237.45 ms and restart
2065
+ time is 2,230.56 versus 2,229.68 ms, with 78,677 tokens restored. Durability
2066
+ has no pending, dropped or failed writes; source hashes and both preflights
2067
+ pass. This single comparison does not establish a latency or throughput win.
2068
+ Raw: `composition-baseline/decode-prefill-policy-kv4-mtp2-late-context-chunk256-0.md.json`.
2069
+ The wrapper failed before launching the ordinary arm because macOS Bash 3
2070
+ rejects its empty-array expansion under `set -u`. That arm was resumed alone;
2071
+ the completed MTP report was preserved.
2072
+
2073
+
2074
+ The subsequent ordinary KV4 late-context arm on the same M4 Pro source did
2075
+ **not** pass clean acceptance. Its first 78,678-token cold request completed
2076
+ with 881,941 ms to first output, but the cached repeat failed with Metal
2077
+ `kIOGPUCommandBufferCallbackErrorOutOfMemory`. The benchmark's built-in retry
2078
+ restarted the phase with a different request hash and 78,677 prompt tokens.
2079
+ That retry completed at 7.319 tok/s median context decode, 292.54 ms cached
2080
+ first output and 2,262.76 ms after SSD restart, reusing 78,676 tokens. These
2081
+ are recovery diagnostics, not a matched successful ordinary/MTP comparison.
2082
+ Both machine checks passed and source stayed fixed; final swap was 294.69 MB.
2083
+ The final flush retained 17 entries with no pending, dropped or failed spills.
2084
+ The initial failure and both attempts remain in
2085
+ `reports/qwen38-closeout/composition-baseline/decode-prefill-policy-kv4-plain-late-context-chunk256-0.md.json`.
2086
+ The cached-repeat allocation failure needs investigation before repeating
2087
+ ordinary late-context acceptance. Independent output-cache/prefill correctness
2088
+ resumed without rerunning or reclassifying this failed benchmark.
2089
+
2090
+
2091
+ The final generated-output/prefill composition also passes M4 native and
2092
+ HTTP bf16/KV4/fused-TQ cache continuation, parser/template replay, full-suite
2093
+ and typecheck gates. Its short KV4/MTP2 block-0 benchmark uses source
2094
+ `af91e6a64649df5af9eb73e4a35739109f6799a5c8ba7ddc47c3543876cb19c0`.
2095
+ All 14 measured requests plus warmup match the prefill-policy control's
2096
+ request hashes, response text, prompt/generated counts and cached counts.
2097
+ Five decode requests take 55,636.28 versus 55,619.41 ms, a 0.03% increase;
2098
+ median decode is 19.171 versus 19.195 tok/s. Cached first output is 99.06
2099
+ versus 97.56 ms, and aggregate throughput is 15.859 versus 16.203 tok/s.
2100
+ Source and preflights are stable with no failures. This is one matched
2101
+ composition check with flat decode; it establishes no overall speed win or
2102
+ strict serial-domination result. Long Kanban and pressure acceptance remain.
2103
+ Raw: `composition-baseline/decode-output-prefill-kv4-mtp2-short-0.md.json`.
2104
+
2105
+
2106
+ The isolated variable-proposal verifier passes M4 uniform/variable bf16/KV4
2107
+ native controls, the full suite and typecheck. Its first short KV4/MTP2
2108
+ block-0 comparison is slower: five decode requests take 58,907.66 versus
2109
+ 55,636.28 ms, a 5.88% increase; median decode is 17.936 versus 19.171 tok/s.
2110
+ Cached first output is 97.51 versus 99.06 ms and aggregate throughput is
2111
+ 15.911 versus 15.859 tok/s. All measured requests plus warmup preserve
2112
+ request hashes, responses, prompt/generated/cache counts and speculation
2113
+ statistics. Source `885f542f07ea48e119a6bdaf533b4e2605ff293c3d7eb373ac202410032e24dd`
2114
+ and both preflights are stable, with no failures. This single ordered
2115
+ comparison does not distinguish a code regression from machine drift.
2116
+ Alternating frozen control/candidate repeats below test whether that slowdown
2117
+ follows the source.
2118
+ Raw: `composition-baseline/decode-variable-proposals-kv4-mtp2-short-0.md.json`.
2119
+
2120
+ The subsequent M4 Pro 24 GB A/B/B/A repeats use the same two frozen sources,
2121
+ KV4, MTP2, 192-token limit, block-0 workload and runtime environment. All 15
2122
+ requests per arm, including warmup, match request/output hashes, token counts,
2123
+ finish reasons and complete usage/speculation records. Both preflights pass
2124
+ and each source remains unchanged, with no request or phase failures.
2125
+
2126
+ | Arm | Five decode requests, total ms | Median decode tok/s | Cached first output ms | Aggregate tok/s |
2127
+ |---|---:|---:|---:|---:|
2128
+ | Control 1 | 55,559.96 | 19.154 | 98.90 | 15.853 |
2129
+ | Candidate 1 | 55,618.37 | 19.152 | 97.29 | 15.674 |
2130
+ | Candidate 2 | 55,566.01 | 19.189 | 97.23 | 15.880 |
2131
+ | Control 2 | 55,604.33 | 19.166 | 99.06 | 15.917 |
2132
+
2133
+ Combined candidate decode wall time is **0.018% higher**. The initial 5.88%
2134
+ slowdown does not reproduce; this screen supports preserving fixed-MTP decode
2135
+ performance while adding variable proposals. Aggregate throughput varies and
2136
+ establishes no gain. This does not qualify actual prompt-lookup performance,
2137
+ long contexts or serial deletion. The verifier patch is adopted in the working
2138
+ tree after the both-machine correctness gates; the main suite and typecheck pass.
2139
+ Raw reports and derived identity/timing comparison:
2140
+ `composition-baseline/variable-proposals/decode-variable-alternating-*.md.json`
2141
+ and `composition-baseline/variable-proposals/alternating-comparison.json`.
2142
+
2143
+ The prompt-lookup integration's fixed-MTP regression screen uses the same M4
2144
+ Pro 24 GB, KV4/MTP2, block-0 requests and runtime settings. Frozen source
2145
+ `3df52152aac2289b9ed860c2789141acb5e8d6ce7a6170899f34bd9ef1ac9a39`
2146
+ retains all 15 request/output hashes and complete usage/speculation records
2147
+ against variable-verifier candidate2 above. Five decode requests take
2148
+ 55,620.03 versus 55,566.01 ms, a 0.097% increase; median decode is 19.176
2149
+ versus 19.189 tok/s, cached first output 97.56 versus 97.23 ms, and aggregate
2150
+ throughput 15.778 versus 15.880 tok/s. Source/preflights are stable with no
2151
+ request or phase failures. This one short screen establishes no speedup;
2152
+ actual prompt-lookup serial/shared comparisons remain separate.
2153
+ Raw and comparison: `composition-baseline/ngram-group/decode-ngram-group-kv4-mtp2-short-0.md.json`
2154
+ and `composition-baseline/ngram-group/fixed-mtp-comparison.json`.
2155
+
2156
+ The subsequent delayed-TQ/method composition passes M4 fused/unfused native,
2157
+ SSD, complete-suite, typecheck and hygiene checks. Its short fixed-KV4/MTP2
2158
+ screen, source `88da0dca100cdb012cbd4330638cc43b727dbb853a5b1ef6aded60bc6fe1eb0d`,
2159
+ preserves all 15 request/output hashes and complete usage/speculation records
2160
+ against the frozen lookup base. Five decode requests take 55,812.61 versus
2161
+ 55,620.03 ms, a 0.35% increase. Median decode is 19.123 versus 19.176 tok/s,
2162
+ cached first output 98.72 versus 97.56 ms, and aggregate throughput 15.724
2163
+ versus 15.778 tok/s. Source/preflights pass with no failures. This single
2164
+ short composition screen establishes no gain and does not measure delayed
2165
+ TurboQuant performance, since the workload uses KV4.
2166
+ Raw: `composition-baseline/method-composed/decode-tq-method-composed-kv4-mtp2-short-0.md.json`
2167
+ and `composition-baseline/method-composed/fixed-mtp-comparison.json`.
2168
+
2169
+ Two M4 Pro 24 GB prompt-lookup comparisons use KV4, draft depth 3,
2170
+ 192-token decode requests, and reversed arm order on two workload seeds.
2171
+ Source is the same frozen lookup candidate above; both preflights and source
2172
+ checks pass with no request or phase failures. All single-request response
2173
+ pairs match, including their generated counts and finish reasons.
2174
+
2175
+ | Arm order | Five decode requests, serial / shared ms | Cached first output, serial / shared ms | Observed aggregate tok/s, serial / shared |
2176
+ |---|---:|---:|---:|
2177
+ | Serial first | 92,140.46 / 91,472.96 | 5,843.26 / 126.77 | 10.213 / 9.430 |
2178
+ | Shared first | 89,953.79 / 89,279.30 | 5,863.21 / 126.66 | 10.798 / 9.608 |
2179
+
2180
+ Single-request decode totals improve by 0.72% and 0.75%. Shared prompt lookup
2181
+ restores 758 and 757 tokens on the cached repetitions; serial restores zero.
2182
+ That is an actual new cache benefit, with different prefill work. All eight
2183
+ concurrent output pairs differ, and observed shared throughput is lower in
2184
+ both orders. An identical-output aggregate comparison and shared-execution
2185
+ dominance remain unproven. Wider verification cost and acceptance need further
2186
+ measurement; the result does not qualify deleting serial. Default-depth-10
2187
+ KV4 serving correctness subsequently passes 219 assertions on each Mac, with
2188
+ all ten proposal positions exercised; this is not depth-10 timing acceptance.
2189
+ Raw: `composition-baseline/ngram-group/decode-ngram-group-kv4-serial-shared-{0,1}.md.json`
2190
+ and `composition-baseline/ngram-group/lookup-paired-comparison.json`.
2191
+
2192
+ A separate M1 Max first-output diagnostic uses a 758-token prompt, KV4/MTP2
2193
+ and eight generated tokens through direct serial/shared execution. All eight
2194
+ outputs match and warm requests restore 757 tokens. Draft seeding accounts
2195
+ for roughly 93 ms on the warm traces; cache lookup is about 0.3–0.6 ms.
2196
+ Instrumenting the native allocator cleanup then identifies 0–6.8 ms inside
2197
+ `clearCache()` after the one-token target forward, on both execution paths.
2198
+ The shared path does not consistently trail serial in this loaded diagnostic;
2199
+ it does not explain the M4 gap by itself. A bounded candidate will skip this
2200
+ cleanup for one-token prefill work while retaining larger-chunk cleanup, with
2201
+ numerical, allocation and M4 request-time checks before adoption. Raw traces:
2202
+ `composition-baseline/mtp-first-output-diagnostic-m1.jsonl` and
2203
+ `composition-baseline/mtp-clear-diagnostic-m1.jsonl`.
2204
+
2205
+ The one-token maintenance candidate also completes a separate-process M1 Max
2206
+ allocation comparison at 8,195 prompt tokens, MTP2/KV4, chunk256, eight output
2207
+ tokens and a 4 GiB RAM cache without SSD. All three paired outputs, cache counts
2208
+ and speculation records match. Both warm repeats restore 8,194 tokens.
2209
+ Warm peak live allocation above the starting live state is 544.717 MiB for
2210
+ control and 544.732 MiB for candidate, a 16,208-byte increase. Final live
2211
+ allocation is effectively unchanged; the candidate's final allocator pool is
2212
+ 845.54 versus 709.29 MiB, so it retains about 136 MiB more unused capacity in
2213
+ this run. This loaded M1 diagnostic establishes no speedup and does not replace
2214
+ M4 long-context/SSD pressure coverage. Raw and derived records:
2215
+ `composition-baseline/single-token-maintenance/m1-allocation-{control,candidate}.jsonl`
2216
+ and `composition-baseline/single-token-maintenance/m1-allocation-comparison.json`.
2217
+
2218
+ Four alternating M4 Pro 24 GB fixed-MTP2/KV4 short runs compare the one-token
2219
+ maintenance candidate against the composed source above. Bun is 1.4.2,
2220
+ MLX is 0.32.2, fused TQ decode is enabled and asynchronous Trellis expansion
2221
+ is disabled. Both arms use seed `mtp-serving-block-0`, 192 output tokens,
2222
+ a 4 GiB prompt cache and the same packed target/RTN4 companion. Control source
2223
+ is `88da0dca100cdb012cbd4330638cc43b727dbb853a5b1ef6aded60bc6fe1eb0d`;
2224
+ candidate is `c12b60c1c7f39bf4ccdeaa7cdd16795a04d6ca2246eeb7609ec97cb9eee65315`.
2225
+ All four source snapshots and preflights pass under the recorded audio-CPU
2226
+ allowance. All 60 requests preserve request hashes, output text, complete
2227
+ usage/acceptance records and finish reasons, with no failures.
2228
+
2229
+ | Order | Five decode requests, total ms | Cached first output, ms | Median decode, tok/s | Aggregate tok/s |
2230
+ |---|---:|---:|---:|---:|
2231
+ | Control 1 | 56,424.69 | 98.097 | 18.722 | 15.591 |
2232
+ | Candidate 1 | 55,595.29 | 96.483 | 19.198 | 15.799 |
2233
+ | Candidate 2 | 55,588.63 | 96.517 | 19.171 | 15.916 |
2234
+ | Control 2 | 55,581.64 | 98.214 | 19.174 | 15.959 |
2235
+
2236
+ Cached latency averages 98.156 versus 96.500 ms, a 1.69% reduction. The
2237
+ first control also has slower cold prefill and decode; both candidate decode
2238
+ totals are effectively flat against the second control. This screen supports
2239
+ the narrow cached-latency improvement, not a general throughput gain or
2240
+ serial/shared dominance. The candidate remains isolated pending the direct
2241
+ serial/shared comparison and pressure review. Raw and derived records:
2242
+ `composition-baseline/single-token-maintenance/decode-single-token-maintenance-{control1,candidate1,candidate2,control2}.md.json`
2243
+ and `composition-baseline/single-token-maintenance/alternating-comparison.json`.
2244
+
2245
+ The direct M4 Pro serial/shared follow-up uses that same candidate source,
2246
+ MTP2/KV4 and two seeds with reversed arm order. All 22 single-request pairs
2247
+ preserve output, usage except the lane label, and cache coverage; all request
2248
+ hashes and generated budgets match. Source/preflights pass with no failures.
2249
+
2250
+ | Arm order | Five decode requests, serial / shared ms | Cached first output, serial / shared ms | Observed aggregate tok/s, serial / shared |
2251
+ |---|---:|---:|---:|
2252
+ | Serial first | 56,220.90 / 55,568.01 | 93.761 / 96.858 | 15.734 / 16.003 |
2253
+ | Shared first | 54,119.93 / 54,093.31 | 93.782 / 95.060 | 16.111 / 15.925 |
2254
+
2255
+ The allocator change does not remove the B1 cached-latency regression. Seven
2256
+ of eight concurrent output pairs differ, and observed aggregate throughput
2257
+ moves in opposite directions across the two orders. These results do not
2258
+ qualify shared dominance or serial deletion. The cleanup candidate remains
2259
+ isolated; its narrow improvement against the prior shared implementation is
2260
+ recorded separately above. Raw and derived records:
2261
+ `composition-baseline/single-token-maintenance/decode-maintenance-serial-shared-{0,1}.md.json`
2262
+ and `composition-baseline/single-token-maintenance/serial-shared-comparison.json`.
2263
+
2264
+ Four alternating M4 Pro 24 GB prompt-lookup runs compare wider packed
2265
+ down-projection eligibility against the unchanged operation. Settings are
2266
+ KV4, lookup depth3, 192 output tokens, seed `ngram-serving-block-0`, Bun 1.4.2
2267
+ and MLX 0.32.2. Control source is
2268
+ `88da0dca100cdb012cbd4330638cc43b727dbb853a5b1ef6aded60bc6fe1eb0d`;
2269
+ candidate is `c399a3e7fa4d8e61d720476a53a3abb5055944dccfd32684a99157373a288343`.
2270
+ All 60 requests preserve request hashes, response text, complete usage and
2271
+ finish reasons. Source/preflights pass under the audio-CPU allowance, with no
2272
+ failures. Both-machine projection and full-model B1/B2/B4/B8 state checks pass,
2273
+ including every new projection width and the artifact's three bit widths.
2274
+
2275
+ | Order | Five decode requests, total ms | Cached first output, ms | Aggregate tok/s |
2276
+ |---|---:|---:|---:|
2277
+ | Control 1 | 91,973.51 | 126.671 | 9.456 |
2278
+ | Candidate 1 | 92,261.32 | 129.677 | 9.305 |
2279
+ | Candidate 2 | 91,413.34 | 126.650 | 9.324 |
2280
+ | Control 2 | 91,750.52 | 126.872 | 9.473 |
2281
+
2282
+ Combined single-request time is effectively unchanged, decreasing 0.027%,
2283
+ while aggregate throughput decreases 1.58%. Both candidate aggregate results
2284
+ trail both controls. The wider eligibility is not adopted: exact arithmetic
2285
+ and avoiding dense weight expansion do not establish a serving benefit.
2286
+ Any further kernel tuning needs workload dispatch/cost attribution first.
2287
+ Raw and comparison:
2288
+ `composition-baseline/trellis-batch-width/decode-trellis-width-ngram-{control1,candidate1,candidate2,control2}.md.json`
2289
+ and `composition-baseline/trellis-batch-width/alternating-comparison.json`.
2290
+
2291
+ A bounded M1 Max allocation diagnostic follows the ordinary M4 cached-repeat
2292
+ OOM. At 8,195 prompt tokens, KV4, 12 generated tokens and a 4 GiB RAM cache
2293
+ without SSD, normal pipelining, early first output and disabled pipelining
2294
+ all retain two entries and add the same 375.28 MiB peak allocator demand
2295
+ above the pre-request live allocation on warm repeats. All nine outputs
2296
+ match. This loaded-machine native probe is not a speed benchmark, does not
2297
+ reproduce the 78k failure, and supplies no evidence that pipeline overlap is
2298
+ its allocation cause. Large-context retention and concurrent SSD persistence
2299
+ remain untested by this probe.
2300
+ Raw: `composition-baseline/ordinary-cached-allocation-m1.jsonl`.
2301
+
2302
+ ### Current MTP depth two versus four — M4 Pro (2026-09-09)
2303
+
2304
+ Same packed artifact, RTN4 companion, KV4, Bun 1.4.2, MLX 0.32.2 and frozen
2305
+ reference source as the replay experiment above. The source hash is
2306
+ `a01bee0b7e1962c8211f1ffd845d95f7923d6c04bddb18cf06f07483cab9e7e8`.
2307
+ Only the draft depth changes. Each block uses matching request hashes and
2308
+ 192 output tokens. Both depth-four blocks precede both depth-two blocks, so
2309
+ this depth comparison is not balanced in execution order. Preflight passes
2310
+ with the recorded audio-CPU allowance; reports retain `canonical:false`.
2311
+
2312
+ | Block | Depth two median decode | Depth four median decode | Five-request complete time, depth two / four | Matching responses |
2313
+ |---|---:|---:|---:|---:|
2314
+ | 0 | 19.33 tok/s | 7.36 tok/s | 56,275.71 / 135,674.99 ms | 6 / 15 |
2315
+ | 1 | 18.31 tok/s | 7.60 tok/s | 57,859.37 / 130,083.45 ms | 6 / 15 |
2316
+
2317
+ Counts, cached coverage and finish reasons match for every request. All five
2318
+ decode and four queued-concurrency responses differ in each block; no phase
2319
+ fails. These are observed results from different continuations, not an
2320
+ identical-output speed ratio or a depth-four acceptance. Depth two remains the
2321
+ current choice. A depth-four verify processes five tokens including the pending
2322
+ token, crossing the existing four-row packed-kernel boundary. R7 already records
2323
+ that boundary's cost and arithmetic difference; the current runs do not isolate
2324
+ its contribution from the changed continuation/acceptance trajectory.
2325
+
2326
+ Raw: `reports/qwen38-closeout/composition-baseline/mtp-depth2-{0,1}.md.json`,
2327
+ `state-replay-reference-{0,1}.md.json` and `mtp-depth-performance-review.json`.
2328
+ All requests here use the one-active-request control; four queued requests do
2329
+ not establish actual batched MTP. Compare fixed-input verification at both
2330
+ window sizes before changing the dispatch policy or promoting depth four.
2331
+
2332
+ ### Current standard serve matrix — M1 Max 32 GB (2026-08-22)
2333
+
2334
+ Real-server HTTP matrix on commit `4103ae1`, with the canonical preflight
2335
+ passing at the start of both runs: zero swap, ample free memory, and no large
2336
+ foreign process. The Qwen extension ended with 944 MiB of inactive swap,
2337
+ below the harness's 3 GiB mid-run rejection threshold. No benchmark phase
2338
+ failed. Raw gitignored reports:
2339
+ `benchmarks-serve-2026-08-22-Joshs-MacBook-Pro-2.md` and
2340
+ `benchmarks-serve-2026-08-22-Joshs-MacBook-Pro-2-qwen27b.md`.
2341
+
2342
+ | model | arm | short decode tok/s | decode @ ~15.8k tok/s | aggregate ×4 tok/s | restart TTFT ms (cached tokens) |
2343
+ |---|---|---:|---:|---:|---:|
2344
+ | MiniCPM5-1B | mlx-bun | **267.7** | 122.0 | **420.1** | 207 (15,817) |
2345
+ | | mlx-bun serial | 266.4 | 124.6 | 245.9 | 182 (15,889) |
2346
+ | | mlx-lm | 179.7 | 96.2 | 181.4 | 10,355 (0) |
2347
+ | | mlx-bun mixed | 194.2 | **127.0** | 397.5 | **130 (15,815)** |
2348
+ | gemma-4-e4b | mlx-bun | **61.5** | 43.7 | 20.7 | 18,863 (4) |
2349
+ | | mlx-bun serial | **61.5** | 43.1 | 59.7 | **661 (15,940)** |
2350
+ | | mlx-lm | 52.8 | 42.8 | 72.3 | 20,187 (0) |
2351
+ | | mlx-bun mixed | 57.3 | **49.0** | **97.4** | 20,510 (0) |
2352
+ | gemma-4-12B | mlx-bun | **29.6** | 28.3 | 5.6 | 85,180 (4) |
2353
+ | | mlx-bun serial | **29.6** | **28.4** | 27.5 | **1,338 (15,866)** |
2354
+ | | mlx-lm | 27.1 | 25.8 | 32.5 | 89,504 (0) |
2355
+ | | mlx-bun mixed | 28.7 | 24.4 | **38.7** | 93,068 (6) |
2356
+ | Qwen3.8-27B winner | mlx-bun | **18.5** | 16.5 | 19.3 | 173,215 (0) |
2357
+ | | mlx-bun serial | **18.5** | **16.7** | 15.8 | 172,400 (0) |
2358
+ | | mlx-lm | 16.5 | 14.9 | 18.3 | 177,066 (0) |
2359
+ | | mlx-bun mixed | 18.1 | 14.9 | **19.4** | **3,328 (15,112)** |
2360
+
2361
+ - All four models passed 64-token greedy completion and chat parity for
2362
+ mlx-bun bf16 versus mlx-lm, and unified scheduling versus `--batch 1`.
2363
+ - Qwen's standard mlx-bun arm beat mlx-lm by 12.1% at short decode and
2364
+ 10.7% at long-context decode. The mixed arm did not beat bf16 on decode;
2365
+ its useful result was restoring the full 15,112-token cache after restart.
2366
+ - The e4b and 12B unified arms restored only four cached tokens after restart,
2367
+ while their serial controls restored the full cache. This is a real
2368
+ scheduler/SSD-persistence regression and explains their poor aggregate rows.
2369
+ Qwen bf16 restored no cache in either scheduler mode.
2370
+ - Qwen mixed KV is a Lab characterization, not an L2 correctness claim. Its
2371
+ policy is copied from the official same-topology Qwen3.6 OptiQ artifact;
2372
+ Qwen3.8 has no model-specific mixed-KV oracle yet. Its 15,278 MB sampled peak
2373
+ RSS also failed the harness's `mixed < bf16` diagnostic, so the run proves
2374
+ that the policy loads and serves, but not that KV quantization was effective.
2375
+
2376
+ #### Bun 1.4.0 repeat
2377
+
2378
+ The full matrix repeated after upgrading from Bun 1.3.14 to 1.4.0. Starting
2379
+ state was 401 MiB inactive swap, 93% free memory, load 3.7, and no large
2380
+ foreign process, which passed the canonical preflight. All completion, chat,
2381
+ and unified-versus-serial parity probes passed again. Core mlx-bun performance
2382
+ was stable; the largest one-run movements were MiniCPM aggregate +5.0% and
2383
+ Qwen long-context decode +3.0%, neither promoted as a Bun speed claim without
2384
+ repeats.
2385
+
2386
+ | model | engine | short decode tok/s | short prefill tok/s | long decode tok/s | warm TTFT ms | aggregate ×4 tok/s |
2387
+ |---|---|---:|---:|---:|---:|---:|
2388
+ | MiniCPM5-1B | mlx-bun | **265.8** | **2,576** | **124.2** | **26** | **441.3** |
2389
+ | | mlx-lm | 177.0 | 1,907 | 96.5 | 86 | 185.8 |
2390
+ | gemma-4-e4b | mlx-bun | **61.7** | **868** | **43.1** | **39** | 21.2 |
2391
+ | | mlx-lm | 52.4 | 676 | 42.5 | 268 | **72.4** |
2392
+ | gemma-4-12B | mlx-bun | **29.7** | **191** | **28.4** | **77** | 6.0 |
2393
+ | | mlx-lm | 26.7 | 181 | 25.3 | 388 | **33.4** |
2394
+ | Qwen3.8-27B winner | mlx-bun | **18.6** | 64 | **17.0** | **116** | **19.5** |
2395
+ | | mlx-lm | 16.5 | **85** | 14.8 | 284 | 18.6 |
2396
+
2397
+ The e4b and 12B aggregate losses remain contaminated by the SSD durability
2398
+ race. Their unified arms restored 2 and 4 tokens; serial restored 15,939 and
2399
+ 15,794. Qwen's short-prefill loss is different: both mlx-bun schedulers lose
2400
+ at the roughly 754-token shape, while sustained prefill reaches 87 tok/s at
2401
+ 15.1k versus mlx-lm's 88. This points to fixed graph-build or shape overhead,
2402
+ not a slower sustained prefill kernel. Split timing is still required before
2403
+ assigning the cause.
2404
+
2405
+ ### Colibri G1/G3 component matrix — M1 Max 32 GB
2406
+
2407
+ Cleared-machine run on 2026-07-30, commit `47c4d6d`, Bun 1.3.14, pinned
2408
+ Colibri `44e489b`, public artifact revision `3cc8db9`, ten warmups and fifteen
2409
+ measured samples. Values are synchronized median milliseconds at identical
2410
+ production shapes; every arm passed its correctness oracle. These are
2411
+ component timings, not end-to-end generation claims.
2412
+
2413
+ | production-shape cell | direct Colibri Metal | selected mlx-bun path | decision |
2414
+ |---|---:|---:|---|
2415
+ | Q4 dense decode M=1 | 0.302 | 1.372 stock MLX | stock MLX (only mlx-bun dense candidate) |
2416
+ | Q4 dense prefill M=32 | 1.286 | **1.030 stock MLX** | stock MLX |
2417
+ | routed SwiGLU decode, top-8 M=1 | **1.401** | 4.282 custom Metal | custom Metal; 16.0% faster than stock MLX's 5.099 ms |
2418
+ | routed SwiGLU ragged M=11/23 experts | **10.851** | 18.100 stock MLX | stock MLX |
2419
+ | routed SwiGLU prefill M=32/64 experts | **32.906** | 45.558 stock MLX | stock MLX |
2420
+ | absorbed MLA decode, position 128 | **1.014** | 11.506 stock MLX | stock MLX; largest remaining component gap |
2421
+
2422
+ For the selected custom decode path, max absolute delta versus stock is
2423
+ `2.33e-9`, relative RMSE `5.56e-7`, and cosine
2424
+ `0.9999999999998354`. A separate three-warmup/eleven-sample run also selected
2425
+ custom Metal by 5.4%. Swap was unchanged at 339.25 MiB. Matched idle-power
2426
+ arms (baseline, 1, 2, and 4 native workers, repeated in reverse order) show no
2427
+ monotonic CPU/GPU/package-power increase, proving the condition-variable
2428
+ workers are passive; two workers remain the default. Raw gitignored reports:
2429
+ `runs/colibri-g1/*matrix*-2026-07-30.json` and
2430
+ `runs/colibri-g1/passive-worker-power*-2026-07-30.json`.
2431
+
2432
+ ### Colibri G4 serial native MTP — M1 Max 32 GB
2433
+
2434
+ Production-artifact separate-process A/B on 2026-07-30, Bun 1.3.14, pinned
2435
+ Colibri `44e489b`, public artifact revision `3cc8db9`, greedy gamma=3, 32-token
2436
+ prompt and 64 generated tokens. Both arms reproduced the same direct-Colibri
2437
+ 64/64 target-token trajectory. Generation wall time is the comparison metric;
2438
+ the probe's prefill/decode sub-buckets place the first sample on different
2439
+ sides of that boundary and are therefore not compared.
2440
+
2441
+ | arm | generation wall | wall throughput | target/verify forwards | draft acceptance |
2442
+ |---|---:|---:|---:|---:|
2443
+ | MTP off | 834.172 s | 0.0767 tok/s | 63 continuation | — |
2444
+ | MTP on | **675.654 s** | **0.0947 tok/s (1.235x)** | **31 verify (32 saved)** | 32/92 |
2445
+
2446
+ MTP-on emitted 2.065 tokens per verify forward and reduced end-to-end
2447
+ generation time by 19.0%. Its direct-oracle acceptance prefix was exact for
2448
+ the tie-free first four rounds `[1,1,1,0]` (eight emitted tokens; minimum
2449
+ first-draft margin 3.5675). Later acceptance is intentionally non-gating
2450
+ across engines because direct Colibri's float64 RMSNorm reduction and MLX's
2451
+ float32 graph produce different recurrent MTP hidden states while preserving
2452
+ all target tokens. The machine was not swap-cleared, so the
2453
+ 14,679,224,320-byte completed MTP-on physical footprint is not a G5 memory
2454
+ claim. Stable record:
2455
+ `fixtures/colibri-glm52/g4-native-mtp-e2e.json`.
2456
+
2457
+ ### Colibri G5–G7 full-model productization — M1 Max 32 GB
2458
+
2459
+ Final curated result for the streamed runtime. Bun 1.3.14, 32 GiB unified
2460
+ memory, 25 GiB process ceiling, batch 1, 4,096-token supported context, 128
2461
+ generated tokens, greedy decoding, true top-8, and quality-preserving defaults.
2462
+ The G5 before/after run is 2026-08-15; G6 learning telemetry is a three-repeat
2463
+ paired run on 2026-08-16; the DSA and API gates are 2026-08-17.
2464
+
2465
+ #### Resource contract
2466
+
2467
+ The current artifact-aware preflight, including the locally installed stock
2468
+ DSA indexer overlay, reports:
2469
+
2470
+ | resource | bytes | GiB |
2471
+ |---|---:|---:|
2472
+ | full artifact on disk (streamed, not resident) | 383,739,826,712 | 357.39 |
2473
+ | resident non-expert weights + DSA indexers | 11,074,469,760 | 10.31 |
2474
+ | main Q4 expert slab (139 slots) | 2,632,646,656 | 2.45 |
2475
+ | MTP Q8 expert slab (25 slots) | 945,356,800 | 0.88 |
2476
+ | target + MTP compressed KV | 789,577,728 | 0.74 |
2477
+ | reconstructed KV + verify + allocator/Bun/safety reserves | 5,910,612,992 | 5.50 |
2478
+ | **planned process** | **21,352,663,936** | **19.89 / 25.00** |
2479
+ | **process/macOS headroom** | **5,490,881,664** | **5.11** |
2480
+
2481
+ The original G5 measurement preceded the 197,202,400-byte stock indexer
2482
+ overlay and planned 21,111,440,128 bytes. The overlay raises the current
2483
+ preflight by 241,223,808 bytes but does not alter the short-context trajectory
2484
+ or the observed G5 footprints below.
2485
+
2486
+ > **Measurement outcome:** the requested before/after observation closed the
2487
+ > 32 GB fit question, but did **not** satisfy the harness's stricter
2488
+ > zero-compression/zero-swap contract. Peak physical footprint stayed at or
2489
+ > below 14,807,789,616 bytes (13.791 GiB), while maximum system/task compressor
2490
+ > growth was 4,402,905,088 / 1,939,537,920 bytes; MTP-off observed 7,143,424
2491
+ > bytes of swapout and MTP-on observed zero. The source result is correctly
2492
+ > labeled `observed`, not `pass`.
2493
+
2494
+ #### Cold/warm MTP and memory
2495
+
2496
+ | arm / turn | decode tok/s | end-to-end tok/s | final physical footprint |
2497
+ |---|---:|---:|---:|
2498
+ | MTP off · cold | 0.1330 | 0.1274 | 13,490,515,008 B |
2499
+ | MTP off · warm | 0.1190 | 0.1139 | 13,510,634,560 B (+19.2 MiB) |
2500
+ | MTP on · cold | 0.1557 | 0.1456 | 14,673,342,512 B |
2501
+ | MTP on · warm | **0.1577** | **0.1487** | 14,697,574,448 B (+23.1 MiB) |
2502
+
2503
+ MTP-on accepted 72/166 drafts over 56 verify forwards on each turn. Warm
2504
+ end-to-end throughput was 1.306x MTP-off. It is also only 55% of the rounded
2505
+ same-machine direct-Colibri MTP-on control (0.27 tok/s), and 0.1487 tok/s is
2506
+ 7.43% of the aspirational 2 tok/s target—a **13.45x** remaining gap. The
2507
+ aspiration is not a release gate or a `fit` prediction.
2508
+
2509
+ #### Expert delivery and policy decisions
2510
+
2511
+ The replicated G6 control's median warm turn read exactly
2512
+ 1,974,949,363,712 logical bytes from the expert artifact, or
2513
+ 15.429291904 decimal GB per generated token. Its hit rate was 1.6597%; median
2514
+ main-tier disk-service p95 was 90.98 ms, foreground-wait p95 92.66 ms, and
2515
+ expert-layer-forward p95 167.84 ms. This is the measured reason the runtime is
2516
+ disk/serialization-bound rather than compute-bound.
2517
+
2518
+ | MTP-on policy (three paired repeats) | warm hit rate | disk GB/token | warm e2e tok/s | decision |
2519
+ |---|---:|---:|---:|---|
2520
+ | control | 1.66% | 15.429 | **0.149** | default |
2521
+ | startup auto-pin | 9.62% | 14.191 | 0.143 | off: 4.06% slower, +3.337 GiB footprint |
2522
+ | auto-pin + live LFRU | 9.62% | 14.191 | 0.148 | off: zero swaps; no benefit beyond run-order noise |
2523
+
2524
+ PILOT measurement found 69.90% next-layer top-8 precision/recall, but advisory
2525
+ `PILOT_K=4` left demand bytes unchanged and reduced warm throughput to 0.9746x.
2526
+ Two-step correction improved recall to 73.01% while reducing warm throughput
2527
+ 10.13%. All learning/prediction/hint policies therefore remain off by default.
2528
+
2529
+ #### DSA and served API
2530
+
2531
+ The paired DSA matrix measured 24 eligible fresh-process cells (2K/8K × DSA
2532
+ off/on × MTP off/on × three repeats), all with exact cold/warm/repeat/MTP
2533
+ tokens. Positive decode delta means DSA was faster; negative wall delta means
2534
+ less total time.
2535
+
2536
+ | context | MTP | paired median decode delta | paired median wall delta | decision |
2537
+ |---:|---|---:|---:|---|
2538
+ | 2,048 | off | -2.80% | +4.14% | no speed claim |
2539
+ | 2,048 | on | -32.90% | +20.95% | regression |
2540
+ | 8,192 | off | +12.38% | -1.89% | below 5% total-wall win gate |
2541
+ | 8,192 | on | -34.33% | +8.19% | regression |
2542
+ | 32,768 | off/on | not run | not run | ineligible: 27.320/28.540 GiB exceeds 25 GiB |
2543
+
2544
+ The checkpoint's 21-full/57-shared schedule remains a semantic requirement,
2545
+ but no DSA product-speed claim is made. Stage-2 manifest SHA-256:
2546
+ `90b3fe4ed53714604b7a747991b3bb1b87aedbf57a139915065f5b4be42cda38`.
2547
+
2548
+ Finally, the fresh real-artifact G7 smoke returned HTTP 200 with correct
2549
+ envelopes for chat completions, text completions, Anthropic Messages, and
2550
+ OpenAI Responses; SSE used `text/event-stream`, emitted four events, ended in
2551
+ `[DONE]`, and reported the truthful `serial+spec` lane. Health, discovery,
2552
+ exact-plan stats, and post-run idle rows also passed. This is protocol/API
2553
+ evidence, not a throughput benchmark.
2554
+
2555
+ Primary raw records: machine-local `runs/colibri-g5/{summary,mtp-on,mtp-off}.json`,
2556
+ `runs/colibri-g6-learning-shakeout-2026-08-15/summary.json`, and
2557
+ `~/.cache/mlx-bun/evidence/glm52-dsa-stage2-2026-08-17/`.
2558
+
2559
+ ### Served (warm) — the path agents actually use
2560
+
2561
+ decode tok/s · TTFT ms · server-ready s · steady RSS GB
2562
+
2563
+ | model | mlx-bun (mixed) | mlx-bun (bf16) | mlx-lm (bf16) | optiq (mixed)† |
2564
+ |---|---|---|---|---|
2565
+ | MiniCPM5-1B | **252.9** · 34 · 0.17 · 1.22 | — | — | 223.6 · 64 · 0.84 · 1.82 |
2566
+ | gemma-4-e4b | 55.7 · 44 · 0.36 · 7.14 | **57.3** · 48 · 0.36 | 53.5 · 218 · 0.98 · 7.55 | 53.4 · 221 · 0.78 · 7.53 |
2567
+ | gemma-4-12B | **25.9** · 85 · 0.38 · 9.46 | — | — | 25.5 · 326 · 1.24 · 9.86 |
2568
+ | gemma-4-26B | 54.2 · **45** · 0.47 · 18.25 | **55.0** · 44 · 0.47 | 52.3 · 228 · 0.77 · 4.87 | — |
2569
+
2570
+ † **The served `optiq (mixed)` cells are effectively bf16** — optiq's
2571
+ KV-quant patch is inert on mlx-lm 0.31.3's batched server path:
2572
+ `install_mixed_kv` hooks `mlx_lm.generate.maybe_quantize_kv_cache` and
2573
+ `mlx_lm.server.stream_generate`, but the server routes every *seedless*
2574
+ text chat request through `BatchGenerator`, which calls neither hook, and
2575
+ the h2h harness's server requests carry no `seed`. See
2576
+ `lab/repro/optiq-mixed-kv-inert/` for the mechanism + repro. The data
2577
+ fingerprint agrees: e4b optiq-mixed served 53.4 tok/s · 7.53 GB RSS ≡
2578
+ mlx-lm bf16's 53.5 · 7.55. Same caveat applies to any serve-mode
2579
+ optiq-mixed cell in raw `benchmarks-serve-*` artifacts dated ≤ 2026-07-06.
2580
+ The **Direct** and **Long context** optiq (mixed) rows below DID measure
2581
+ real quantized-KV execution (the legs passed `kv_bits=8` straight into
2582
+ `mlx_lm.generate.stream_generate` — old `bench.ts --baseline-kv config` —
2583
+ so the 64k collapse and the lower peaks are genuine quantized-KV
2584
+ behavior), but a second installer defect means the scheme was **uniform
2585
+ 8-bit, not the per-layer map**: `install_mixed_kv`'s hook patch lands on
2586
+ the `generate` *function* that shadows `mlx_lm.generate` in mlx-lm's
2587
+ package namespace, never on the module, so mlx-lm's stock uniform
2588
+ `maybe_quantize_kv_cache` is what ran (empirically proven in the repro
2589
+ dir). Read "optiq (mixed)" in those two tables as "optiq (uniform kv8)".
2590
+ mlx-bun (mixed) columns are unaffected — our engine implements the
2591
+ per-layer scheme natively — and the L2 parity goldens stay valid: every
2592
+ `regen-*` oracle script applies the scheme explicitly (direct per-layer
2593
+ `to_quantized`, or calling optiq's patched hook by name), never through
2594
+ the dead serve-path indirection.
2595
+
2596
+ Across every served model: mlx-bun has the fastest decode and the fastest
2597
+ TTFT/startup (2–5×), at ~0% server tax vs its own direct engine.
2598
+
2599
+ ### Served h2h post-consolidation (2026-08-22, e4b, single pass — directional)
2600
+
2601
+ Real servers via `bench-serve.ts` on merged main `4103ae1`; loaded machine
2602
+ (ambient loadavg ~3), so treat as directional until a quiet-box pass. Full
2603
+ findings + root-cause sweep: PLAN.md "Prefill vs mlx-lm (2026-08-22)".
2604
+
2605
+ | arm | prefill@1k tok/s | ttft cold/warm ms | decode tok/s | parity |
2606
+ |---|---:|---|---:|---|
2607
+ | mlx-bun | **1143** | 578 / **39** | **53.9** | ✓✓ byte-identical |
2608
+ | mlx-lm | 866 | 772 / 230 | 50.3 | (oracle) |
2609
+
2610
+ Served prefill stays a decisive mlx-bun win (+32% @1k, warm TTFT 5.9×)
2611
+ after the serving-architecture merge. Engine-direct prefill is
2612
+ parity-within-noise elsewhere (cpm5/12B/26B; e4b@256 fresh-process −12%
2613
+ is the one reproducible engine-level residual). Chunk-size tuning below
2614
+ the 2048 convention is NOT L1-safe: logits are convention-pinned in BOTH
2615
+ stacks (mlx reduction-order sensitivity; python drifts more than we do).
2616
+ Open lead from this pass: e4b agg×4 read 26.6 vs mlx-lm 107.3 — RESOLVED
2617
+ same day as a `443f333` regression (bf16 BatchedRotatingCache lost its
2618
+ signature-based route in the join merge → whole-batch drop on joiners;
2619
+ PLAN.md "agg×4 regression"). Post-fix: 122-126 tok/s aggregate, matching
2620
+ pre-merge.
2621
+
2622
+ ### Direct (engine only)
2623
+
2624
+ decode tok/s · prefill tok/s · gen-peak GB
2625
+
2626
+ | model | mlx-bun (bf16) | mlx-bun (mixed) | mlx-lm (bf16) | optiq (mixed) |
2627
+ |---|---|---|---|---|
2628
+ | MiniCPM5-1B | 268.6 · 1817 · 1.01 | 241.9 · 1651 · 1.01 | **271.0** · 800 · 1.03 | 249.5 · 706 · 1.03 |
2629
+ | gemma-4-e4b | **57.1** · 304 · 6.61 | 55.7 · 283 · 6.61 | 56.5 · 373 · 6.65 | 56.1 · 368 · 6.65 |
2630
+ | gemma-4-12B | **26.0** · 168 · 8.99 | 25.8 · 166 · 8.99 | 25.9 · 141 · 9.10 | 25.7 · 137 · 9.00 |
2631
+ | gemma-4-26B | 55.0 · 206 · 17.71 | 53.9 · 208 · 17.71 | **55.6** · 187 · 17.78 | 55.0 · 190 · 17.72 |
2632
+
2633
+ Direct decode is at parity-to-slightly-behind mlx-lm (the residual host
2634
+ overhead per step); prefill leads on the larger models. See PLAN.md
2635
+ "Decode gap RESOLVED" for the root-cause/fix history.
2636
+
2637
+ ### Logprob metadata readback (2026-07-29)
2638
+
2639
+ Paired internal before/after measurement on the M1 Max 32 GB,
2640
+ Qwen2.5-0.5B-Instruct-4bit, Bun 1.3.14: 256 generated tokens, two warmups,
2641
+ five randomized measured rounds. This isolates mlx-bun's API metadata
2642
+ readback; it is **not** a Bun-versus-Python FFI comparison.
2643
+
2644
+ | arm | before total / decode | after total / decode | overhead vs off, before → after |
2645
+ |---|---:|---:|---:|
2646
+ | off | 802.75 ms / 328.92 tok/s | 803.94 ms / 328.81 tok/s | control |
2647
+ | `logprobs` | 1,185.89 ms / 220.52 tok/s | 802.77 ms / 329.18 tok/s | +47.7% → −0.1% |
2648
+ | `top_logprobs=5` | 1,354.21 ms / 192.69 tok/s | 856.24 ms / 307.63 tok/s | +68.7% → +6.5% |
2649
+
2650
+ The fix reads uint32 IDs directly and expands the few bf16/f16 values on the
2651
+ host instead of queueing `astype(float32)` behind the already-dispatched next
2652
+ decode step. The off control stayed flat; all 40 parity checks and all 1,280
2653
+ selected/top-k comparisons were exact. Clean commits: before `00e597e`, after
2654
+ `b1cb7cb`. Raw artifacts are recorded in the Phase 22 ledger in
2655
+ `docs/archive/investigations/pre-colibri-stabilization.md`.
2656
+
2657
+ ### Long context (gemma-4-12B) — where the gap opens
2658
+
2659
+ decode tok/s · gen-peak GB
2660
+
2661
+ | context | mlx-bun (bf16) | mlx-bun (mixed) | mlx-lm (bf16) | optiq (mixed) |
2662
+ |---|---|---|---|---|
2663
+ | 16k | 23.9 · 11.82 | 23.5 · 10.61 | 23.9 · 11.72 | 21.6 · 11.19 |
2664
+ | 64k | **20.9** · 15.77 | 18.7 · 10.46 | 20.9 · 15.91 | 12.3 · 14.89 |
2665
+
2666
+ At 64k mlx-bun holds parity with mlx-lm on bf16 while optiq collapses to
2667
+ 12.3 tok/s; mlx-bun's mixed-KV trades ~2 tok/s for ~5 GB lower peak.
2668
+
2669
+ ### Attempted but failed (2026-06-14)
2670
+
2671
+ - `gemma-4-12B/optiq/kv=config`: `quantized_matmul` weight/scales
2672
+ shape mismatch (upstream optiq bug; tracked). _(Relabeled from the
2673
+ old-legend name "e4b" = hash `5b…` = 12B; no gen-peak was recorded for
2674
+ this failed run, so the model id here is inferred from the legend, not
2675
+ fingerprinted.)_
2676
+
2677
+ ---
2678
+
2679
+ ## 3. Quality — for non-bit-exact (Lab) optimizations only
2680
+
2681
+ When a custom path trades bit-exactness for speed, quantify the cost so a
2682
+ perf win is only claimed with its quality delta — e.g. *"+23% tok/s while
2683
+ holding ±5% on the 6-test mean."*
2684
+
2685
+ - **6-test mean** — mean score across `src/eval/tasks/`: bfcl, gsm8k,
2686
+ hashhop, humaneval, ifeval, mmlu — optimized path vs the compatible
2687
+ upstream.
2688
+ - **KL divergence** — optimized vs compatible token distribution.
2689
+
2690
+ This section is the home for a Lab experiment's quality measurements
2691
+ when it's promoted (the bar: paired-A/B win vs L1 on a stable pass +
2692
+ KL PASS — see docs/design/unified-engine-frontier-plan.md §6-7).
2693
+
2694
+ ### TurboQuant KV quality-vs-bpw (2026-07-06, M1 Max 32 GB, MiniCPM5-1B)
2695
+
2696
+ > Note: measured on an M1 Max 32 GB, not this file's M4 Pro reference
2697
+ > box — valid as a paired quality/KL measurement (machine-independent),
2698
+ > not as a perf number.
2699
+
2700
+ Opt-in memory/context scheme (`--kv-quant turbo[:k<bits>v<bits>]`), not a
2701
+ speed lever. Teacher-forced serving-decode KL vs bf16 KV (8×128 tokens, 32
2702
+ decode steps, `eval-turboquant-curve.ts (deleted; git history)`); affine rows same harness:
2703
+
2704
+ | scheme | effective KV bits | KV compression | mean KL vs bf16 |
2705
+ |---|---|---|---|
2706
+ | uniform kv8 (g64) | 8.50 | 1.88× | 0.00246 |
2707
+ | turbo k8v8 | 8.75 | 1.83× | 0.00214 |
2708
+ | turbo k8v4 | 6.75 | 2.37× | 0.00936 |
2709
+ | **turbo k8v3 (default)** | **6.25** | **2.56×** | **0.0325** |
2710
+ | uniform kv4 (g64) | 4.50 | 3.56× | 0.0516 |
2711
+ | turbo k4v3 | 4.25 | 3.76× | 0.0622 |
2712
+ | turbo k4v2 | 3.75 | 4.27× | 0.205 |
2713
+
2714
+ Read: turbo k8v3 beats uniform kv4's KL at 2.56× compression; k4v3 is
2715
+ on-curve with affine at matched bits; 2-bit values are the cliff (matches
2716
+ the TurboQuant paper's law). Codec is bit-exact vs the vendored vllm-metal
2717
+ reference (goldens/turboquant.json); details in
2718
+ docs/design/turboquant.md.
2719
+
2720
+ ## 4. Composition — feature-default decisions (measured, per pair)
2721
+
2722
+ The doctrine (docs/design/speculative-decoding.md Phase 4e): a feature is ON by
2723
+ default for a (model, config) pair only when it WINS a clean-machine
2724
+ paired A/B on that pair; losing configs stay documented default-off
2725
+ levers. This section records the decisions and the numbers behind them.
2726
+
2727
+ ### Packed Trellis with KV4/MTP and paired prefixes, M4 Pro, 2026-09-08
2728
+
2729
+ The configured serial suite passes every phase on the required 12.14 GiB
2730
+ packed Trellis artifact at clean commit `1a80401`, with unchanged source
2731
+ hashes throughout. Machine: `Joshs-MBP-2025.local`, Apple M4 Pro, 24 GB,
2732
+ Bun 1.4.0, bundled MLX 0.32.2. Quiet preflight passes. This is one run,
2733
+ not a matched original/final performance claim or a new Kanban task.
2734
+
2735
+ | Metric | Result |
2736
+ |---|---:|
2737
+ | Short-prompt decode, median of five 192-token samples | **18.806 tok/s** |
2738
+ | Short complete-request time, median | **11.389 s** |
2739
+ | Output / complete-request time, median | 16.859 tok/s |
2740
+ | Cold TTFT, median of three approximately 1K probes | 6.537 s |
2741
+ | Warm TTFT, 754 cached tokens | **94.586 ms** |
2742
+ | Approximately 1K prefill estimate, median | 115.747 tok/s |
2743
+ | Context probe, actual input tokens | 2,677 |
2744
+ | Context prefill estimate | 116.808 tok/s |
2745
+ | Context decode, median of three samples | 22.763 tok/s |
2746
+ | Cached context TTFT | 95.434 ms |
2747
+ | Peak sampled process RSS | 11,973.656 MiB (11.693 GiB) |
2748
+ | Phase failures | 0 |
2749
+
2750
+ Arguments are `--draft-kind mtp --num-draft-tokens 2 --kv-quant 4
2751
+ --prompt-cache 4`, with the folded RTN4 MTP draft. Runtime overrides select
2752
+ Trellis variant 13, uniform KV4 speculation, paired MTP prefixes and prefill
2753
+ chunks of 256. Async Trellis expansion, early-first-token and structural fill
2754
+ are off. Workload seed is `pr47-block-0`, thinking is enabled, and the
2755
+ requested context target is 4,096; the table reports the actual token count.
2756
+ All five short samples emit exactly 192 tokens with no reused prefix.
2757
+
2758
+ The speculative prefix store is RAM-only. Restarting restores zero cached
2759
+ tokens and the context request takes 24.404 seconds to first output. The
2760
+ ordinary SSD flush returns durable with zero entries; this is not proof of
2761
+ speculative SSD persistence. No stock mlx-lm arm supports this packed artifact.
2762
+ The faster context decode sample reflects a different prompt and MTP acceptance
2763
+ workload; it does not establish that increasing context makes inference faster.
2764
+
2765
+ Raw evidence: `reports/qwen38-rd/pr47-trellis-kv4-mtp-serve.md` and its `.md.json`
2766
+ companion. These serving timings are separate from the completed fresh Pi
2767
+ Kanban measurement below.
2768
+
2769
+ ### Original and optimized serving diagnostics, M4 Pro, 2026-09-07
2770
+
2771
+ Machine: `Joshs-MBP-2025.local`, Apple M4 Pro, 24 GB, Bun 1.4.0.
2772
+ `bench-serve.ts all` used workload seed `kanban-final-0`, thinking enabled,
2773
+ 192 requested output tokens and five decode samples. These are earlier
2774
+ diagnostic runs, with existing swap, rather than final-PR quiet acceptance.
2775
+ All columns below use the serial serving lane and the required packed target
2776
+ weights. Baseline uses `673b43f`, Trellis variant 6 and the older native library;
2777
+ optimized arms use variant 13, the lossless interleaved artifact and the local
2778
+ MLX 0.32.2 candidate. Each run's source stayed fixed.
2779
+
2780
+ All three serving arms use **bf16 KV**, with `--kv-quant off`. The MTP arm
2781
+ adds two drafts and paired RAM prefixes. This differs from the completed
2782
+ long Kanban task's KV4 configuration. These runs predate the later ownership
2783
+ and bounded-range fixes, so they do not measure the exact final task revision.
2784
+
2785
+ | Serial serving metric | Original | Optimized, ordinary decode | Optimized, MTP + RAM cache |
2786
+ |---|---:|---:|---:|
2787
+ | Median decode, tok/s | 10.140 | 11.712 | 19.426 |
2788
+ | Cold-request TTFT, ms | 5,923.576 | 6,164.498 | 5,801.504 |
2789
+ | Cached TTFT, ms | 190.841 | 436.308 | 91.916 |
2790
+ | 1K prefill, tok/s | 127.963 | 122.962 | 130.522 |
2791
+ | Peak process RSS, reported MB | 11,958.984 | 13,859.828 | 12,061.219 |
2792
+
2793
+ Ordinary decode improves **15.5%**. The MTP configuration improves decode
2794
+ **91.6%** relative to the original, with cached TTFT **51.8% lower**.
2795
+ Its cold TTFT changes by -2.1%, prefill by +2.0%, and sampled RSS by +0.9%.
2796
+ Ordinary decode's gain does not extend to every metric: its cached TTFT and
2797
+ RSS regress in this diagnostic. The percentages describe these specific
2798
+ serving configurations; they are not a measured Kanban task-time reduction.
2799
+
2800
+ The baseline context phase crashed and recovered on retry; no context-phase
2801
+ speedup is claimed here. MTP prefix state is RAM-only: the restart probe
2802
+ restored zero tokens and does not establish SSD persistence. Stock mlx-lm
2803
+ cannot read this packed Trellis artifact, so it supplies no same-artifact
2804
+ serving baseline for these rows.
2805
+
2806
+ Raw evidence: `reports/qwen38-rd/kanban-final/suite-driver.json`,
2807
+ `baseline-suite.md.json`, `optimized-ordinary-suite.md.json`, and
2808
+ `optimized-mtp-cache-suite.md.json`. The driver records all commands,
2809
+ environments, source hashes and exits. The completed task and its separate
2810
+ acceptance are recorded below.
2811
+
2812
+ ### Fresh Pi kanban diagnostic, M4 Pro, 2026-09-07
2813
+
2814
+ Machine: `Joshs-MBP-2025.local`, M4 Pro, 24 GB; Bun 1.4.0, Pi 0.85.1,
2815
+ MLX 0.32.2. These are task diagnostics with existing swap. The first attempt
2816
+ also had a brief background browser-test CPU burst. Neither is a quiet-machine
2817
+ speed claim.
2818
+ The model is the required 12.14 GiB packed Qwen3.8-27B Trellis artifact with
2819
+ lossless interleaving. The selected Luke profile is
2820
+ `qwen3.8-27b-q3_k_xl-coding-128k`, pinned at repository commit
2821
+ `3288d1918fa6140c10f3b2de2d37f9d717a5ab75`. It uses the unchanged prompt,
2822
+ xhigh thinking, temperature 0.6, seed 42 and 131072 context. The MLX mapping
2823
+ uses target affine KV4 group64, two MTP drafts, paired RAM prompt prefixes
2824
+ and 256-token prefill chunks.
2825
+
2826
+ | Attempt | Time until Pi stopped | Output tokens | Overall tok/s | First-turn tok/s, including prefill | First reasoning TTFT | Peak server + Pi RSS | Result |
2827
+ |---|---:|---:|---:|---:|---:|---:|---|
2828
+ | History fixed; original tool-value parser | 65m 30.245s | 53,631 | 13.646 | 15.965 | 22.869s | 12.042 GiB | Failed: only HTML and two JS modules; final edit call remained assistant text |
2829
+ | History and tool-value parsing fixed | 106m 6.531s | 82,015 confirmed | 12.882 | 16.154 | 22.892s | 13.795 GiB | Failed inference: Metal out of memory at the 85,238-token request; Pi did not finish |
2830
+
2831
+ All four request prompt counts matched independent renders. Later requests
2832
+ reused 2,549, 53,174 and 54,859 prompt tokens, with MTP active. Pi had no
2833
+ automatic retries or compactions. Its clean process exit did not mean the
2834
+ app was complete: the mandatory README was absent and most app files were
2835
+ never written. The untouched output fails acceptance. No successful task
2836
+ completion time or matched task-time speedup is established by this row.
2837
+
2838
+ The saved final edit parameter is valid JSON. The engine decoded XML
2839
+ entities before JSON parsing and its repair pass misidentified the nested
2840
+ array as the outer call. The corrected parser preserves the complete argument
2841
+ array through the actual tokenizer and streaming path.
2842
+
2843
+ The fresh attempt with both fixes completed ten requests. Every completed
2844
+ prompt count matched the independent render and every response used MTP.
2845
+ The aggregate accepted/drafted ratio was 80.038%. The first tool transition
2846
+ took 524.244 seconds to first output while processing newly generated history.
2847
+ Later requests reused progressively longer prompt prefixes. The cache still
2848
+ captures prompt boundaries rather than the newly generated history.
2849
+
2850
+ The eleventh request reached a Metal allocation failure after its first
2851
+ reasoning fragment. Its terminal usage was unavailable, so the output total
2852
+ counts only completed responses. The wall-clock interval includes that failed
2853
+ request, prefill, tools and agent overhead. Ten completed response intervals,
2854
+ excluding TTFT, average 15.270 output tokens/s. This is distinct from both
2855
+ overall task throughput and the short-context serving-suite decode rate.
2856
+ There were no retries, compactions or tool errors. Engine source hashes stayed
2857
+ fixed. All inference processes exited during bounded cleanup.
2858
+
2859
+ The untouched app has HTML, CSS, twelve JavaScript modules and package.json,
2860
+ but no README. Syntax checks pass. A separate browser smoke test after server
2861
+ shutdown shows the default columns and keyboard card creation work, but opening
2862
+ the editor throws `ReferenceError: renderLabels is not defined`. Remaining UI
2863
+ checks were not run after that blocking failure. No app edits or repair prompts
2864
+ were supplied. These are findings about an incomplete artifact, not a completed
2865
+ model submission. No successful completion time or matched task-time gain exists.
2866
+
2867
+ Process RSS does not measure all Metal allocations. The out-of-memory failure
2868
+ does not establish the model's architectural context limit; the tested KV4,
2869
+ MTP and retained-prefix combination needs a separate memory diagnosis.
2870
+
2871
+ Protocol and design: [decode-speed-program §7.7](../design/decode-speed-program.md#77-gates-scheduling-and-completion).
2872
+ Raw evidence: `reports/qwen38-rd/kanban-final/luke-q3-128k-xhigh-history-fixed/`
2873
+ and `luke-q3-128k-xhigh-tool-values-fixed/`, including `quality-static.json`,
2874
+ `quality-browser.json` and screenshots. Portable report:
2875
+ `reports/qwen38-rd/kanban-final/comparison.html`.
2876
+
2877
+ ### Kanban capacity diagnosis, M4 Pro, 2026-09-08
2878
+
2879
+ Native Bun screen on `Joshs-MBP-2025.local`, Apple M4 Pro, 24 GB, using the
2880
+ same 12.14 GiB target, MTP head, MLX 0.32.2 candidate and KV4/prefix settings
2881
+ as the failed Pi attempt above. The saved failing history renders to 85,238
2882
+ tokens. Fixed text tokens extend it to 110,000 for this capacity screen.
2883
+ No Pi task runs in this screen. Sampling follows the selected profile, but
2884
+ EOS stopping is disabled to require a short continuation. This is neither
2885
+ a fresh task result nor a quiet-machine performance claim.
2886
+
2887
+ The unchanged control finished target prefill and emitted one token, then
2888
+ failed with Metal out of memory in the first MTP draft round. Its wall time
2889
+ was 1,482.497 seconds. Peak active Metal allocation reached 19,451,721,310
2890
+ bytes against a recommended working set of 19,069,665,280 bytes. Immediately
2891
+ before draft prefill, active allocation was 14,593,938,440 bytes; at the
2892
+ first emitted token it was 17,494,527,842 bytes. The retained prefix reported
2893
+ 2,633,836,544 logical bytes. These counters measure different things from
2894
+ process RSS and do not establish a model context limit. Source hashes stayed
2895
+ fixed; the worker exited with failure and bounded cleanup completed.
2896
+
2897
+ Raw control: `reports/qwen38-rd/kanban-capacity-110k-control.json` and its
2898
+ allocation event log. A focused small ownership regression retains 8,405,016
2899
+ bytes before the fix, despite requiring only small KV state and one hidden
2900
+ row. The isolated candidate now evaluates draft KV at each existing prefill
2901
+ chunk and materializes the retained final hidden row. The ownership,
2902
+ prefix-position and provider-disposal tests pass. Full-model exactness and
2903
+ large-context acceptance are checked separately. A sampling-failure
2904
+ regression retains 524,288 bytes before scoped disposal; it now passes the
2905
+ under-4-KiB cleanup guard without running GC after the failure.
2906
+
2907
+ The final-source small native comparison uses the same first 8,192 history
2908
+ tokens and generates 32 tokens twice. Before and after the ownership changes,
2909
+ both responses and all MTP acceptance decisions match exactly. Each process
2910
+ first prefills from zero, then restores 8,191 cached tokens. Peak active
2911
+ allocation is 13,330,783,014 bytes before and 13,105,695,458 after. Both source
2912
+ manifests stay fixed. This is one correctness/allocation comparison, not a
2913
+ request-time speed claim. Typechecks pass. Evidence: `kanban-capacity-8k-final-comparison.json`
2914
+ and its two referenced control/candidate reports in `reports/qwen38-rd/`.
2915
+
2916
+ The final native capacity screen passes at 110,000 prompt tokens. It completes
2917
+ three identical 256-token continuations, with 109,999 tokens restored on each
2918
+ cached request. Between the latter two, an intentional output-sink error after
2919
+ eight emitted tokens exercises request cleanup. Retained active allocation is
2920
+ 14,911,641,794 bytes after every completed or intentionally failed request.
2921
+ The next request recovers in the same process and reproduces the continuation.
2922
+ Peak active allocation is 17,981,018,362 bytes, 1,470,702,948 bytes below the
2923
+ failing control, despite the longer continuation. The first request takes
2924
+ 1,525.095 seconds including full prefill; the two complete cached requests take
2925
+ 33.148 and 33.175 seconds. Instrumented synthetic-context timings are not
2926
+ Kanban completion estimates. Final provider/weight disposal leaves 101,892,102
2927
+ active bytes; the equal per-request counters establish no incremental retention
2928
+ from the injected failure, not zero global runtime allocation. The worker exits
2929
+ successfully, its source hashes stay fixed and its deadline is not reached.
2930
+
2931
+ The main source has the same ownership fixes. Its focused memory/provider tests
2932
+ and a real-target MTP/non-MTP short greedy identity gate pass, as do all
2933
+ typechecks.
2934
+ Native evidence: `reports/qwen38-rd/kanban-capacity-110k-owned-final.json`.
2935
+
2936
+ The saved-history HTTP gate also passes on the isolated candidate. It first
2937
+ replays the exact failed request, then appends that response and synthetic
2938
+ tool/user history to test growth. Tool calls are recorded but never executed
2939
+ by this diagnostic. Each response allows up to 512 output tokens and stops
2940
+ naturally. Both repeated responses preserve all text, tool arguments, output
2941
+ counts and MTP acceptance decisions.
2942
+
2943
+ | Prompt tokens | Cached tokens | Output tokens | Complete request, s | TTFT, s |
2944
+ |---:|---:|---:|---:|---:|
2945
+ | 85,238 | 0 | 42 | 988.103 | 984.951 |
2946
+ | 85,238 | 85,237 | 42 | 3.283 | 0.225 |
2947
+ | 110,014 | 85,237 | 92 | 401.843 | 393.126 |
2948
+ | 110,014 | 110,013 | 92 | 8.931 | 0.255 |
2949
+
2950
+ Source hashes stay fixed and server cleanup exits successfully. This validates
2951
+ serving capacity and cache reuse, not a completed Kanban task. Raw evidence:
2952
+ `reports/qwen38-rd/kanban-memory-http-owned.json` and the saved request/response
2953
+ files beside it. These checks exercise short continuations. The fresh Pi
2954
+ retry below still fails during sustained generation.
2955
+
2956
+ During the saved-history HTTP prefill, simultaneous read-only `/health` and
2957
+ `/stats` requests both returned 200, taking 4,776.475 and 4,776.682 ms. This
2958
+ single busy-server observation does not establish an idle baseline or latency
2959
+ distribution. It identifies responsiveness during native prefill for a separate
2960
+ serving check. Evidence: `reports/qwen38-rd/kanban-memory-http-responsiveness.json`.
2961
+
2962
+ ### Fresh Pi Kanban after MTP ownership fixes, M4 Pro, 2026-09-08
2963
+
2964
+ The fresh retry on `Joshs-MBP-2025.local`, Apple M4 Pro, 24 GB, failed with
2965
+ Metal out of memory after **106m 5.416s**. It used the same 12.14 GiB target,
2966
+ published Luke Q3 128K xhigh profile and unchanged prompt as the preceding
2967
+ attempt. The source and every saved request's profile pass the post-run audit.
2968
+ The first request body is byte-identical to the preceding attempt; its entire
2969
+ response and MTP acceptance trace also match. Later history includes actual
2970
+ tool results, including changed directory timestamps.
2971
+
2972
+ Eight requests completed, reporting **73,831 output tokens**. The ninth
2973
+ request started with **77,077 prompt tokens**, emitted its first output after
2974
+ 26.415 seconds and failed after 780.891 seconds, during sustained decode.
2975
+ Its terminal usage is missing. Retokenizing delivered reasoning estimates
2976
+ another 5,659 tokens, but excludes buffered tool arguments, so the full
2977
+ generation count is unknown. The completed-response rate after first output
2978
+ is 15.658 tok/s; this excludes prefill, tool time and the failed response.
2979
+ Peak combined server/Pi RSS is **13.836 GiB**. Completed requests report
2980
+ 79.911% MTP acceptance. There were no retries, compactions or tool execution
2981
+ errors. Pi exited with code zero but reported a terminal error; the task
2982
+ therefore failed. No successful completion time or task-time speedup is
2983
+ established.
2984
+
2985
+ The untouched app supplies its README and passes syntax, basic card creation,
2986
+ board/theme persistence, column creation/rename and between-column card drag
2987
+ checks. The card editor throws `ReferenceError: renderLabels is not defined`;
2988
+ the archive panel throws `TypeError: K.render.renderArchive is not a function`.
2989
+ Required functional acceptance fails. Reorder interaction probes remain
2990
+ unconfirmed because their input simulation needs validation. Independent UI
2991
+ checks ran only after inference exited. No app code was edited and no repair
2992
+ prompts were supplied.
2993
+
2994
+ The short native and HTTP capacity checks above did not reproduce this long
2995
+ decode failure. It motivated the sustained allocation check below. Raw result,
2996
+ source/profile audit and untouched
2997
+ app checks: `reports/qwen38-rd/kanban-final/luke-q3-128k-xhigh-mtp-memory-fixed/`
2998
+ contains `result.json`, `measurement-audit.json`, `quality.json` and its
2999
+ referenced evidence.
3000
+
3001
+ ### Sustained Kanban decode allocation diagnosis, M4 Pro, 2026-09-08
3002
+
3003
+ A fresh native process loaded the failed task's saved **77,077-token** request
3004
+ and generated **12,288 tokens** with the same model, MTP, KV and sampling
3005
+ settings. EOS stopping was disabled for this bounded diagnostic; no tools
3006
+ were executed. The unchanged control completed in 2,408.753 seconds including
3007
+ 923.348 seconds to first output. Decode was 8.272 tok/s. Peak active MLX
3008
+ allocation was **18,204,808,450 bytes**; **1,593,360,390 bytes** remained active
3009
+ after provider/weights disposal and allocator-cache clearing. Source hashes
3010
+ stayed fixed. This is a saved-history diagnostic, not a fresh task result or
3011
+ a quiet-machine speed claim.
3012
+
3013
+ The large-range cache retained every distinct causal-mask range above 65,536
3014
+ elements. Early comparable rounds each added **311,296 bytes**, matching the
3015
+ page-rounded int32 range allocation. A focused regression with 256 changing
3016
+ context lengths retained **79,790,080 bytes** in the old implementation and
3017
+ **7,258,112 bytes** after bounding cached array data to 8 MiB. Three oversized
3018
+ ranges retained **37,748,736 bytes** before and **zero additional bytes** after.
3019
+ The regression fails before the change and passes after it, including exact
3020
+ range values, vocabulary reuse and lazy-view ownership after eviction. Eight
3021
+ focused main-source tests, the candidate regression and both workspace
3022
+ typechecks pass.
3023
+
3024
+ Reconstructing the target prefill lengths and verification windows from the
3025
+ control's acceptance trace predicts 4,685 distinct large mask ranges occupying
3026
+ 1,592,344,576 page-rounded bytes. That accounts for more than 99.9% of the
3027
+ observed allocation left after model disposal. This is allocation attribution
3028
+ from the recorded execution and source, not a measurement of every cache entry.
3029
+
3030
+ The bounded-cache full-model repeat passes: all **12,288 output tokens** and
3031
+ all **4,638 MTP acceptance decisions** are identical. Source and harness hashes
3032
+ stay fixed, with `src/mlx/ops.ts` the only engine difference between arms.
3033
+ Both runs exit normally without cleanup errors.
3034
+
3035
+ | Native diagnostic metric | Unbounded cache | Bounded cache |
3036
+ |---|---:|---:|
3037
+ | Complete request time | 2,408.753 s | 2,461.051 s |
3038
+ | Time to first output | 923.348 s | 939.902 s |
3039
+ | Decode rate | 8.272 tok/s | 8.078 tok/s |
3040
+ | Peak active MLX allocation | 18,204,808,450 B | 16,622,195,970 B |
3041
+ | Active MLX allocation after model disposal | 1,593,360,390 B | 8,224,774 B |
3042
+ | Observed peak process RSS | 14,324,711,424 B | 12,745,523,200 B |
3043
+ | OS lifetime peak process footprint | 18,969,882,768 B | 18,826,963,720 B |
3044
+
3045
+ Peak active allocation falls by **1,582,612,480 bytes**. The single diagnostic
3046
+ pair takes **2.171% longer**, so it establishes a memory/ownership correction,
3047
+ not a throughput gain. RSS, active allocation and physical footprint remain
3048
+ distinct measurements. The process monitor started during control prefill
3049
+ and before candidate prefill; native allocation instrumentation is identical.
3050
+ The fresh Pi task with this correction completed; its separate task result
3051
+ and functional acceptance are recorded below.
3052
+
3053
+ Raw evidence: `reports/qwen38-rd/kanban-sustained-77k-owned-control.json`, its
3054
+ allocation/process-memory traces, `kanban-arange-allocation-evidence.json`,
3055
+ `kanban-arange-regression.json`, `kanban-arange-micro-memory.json` and
3056
+ `kanban-arange-reconstruction.json`. Full-model comparison:
3057
+ `kanban-sustained-arange-comparison.json`, with both raw runs and their traces.
3058
+
3059
+ ### Completed fresh Pi Kanban with bounded range cache, M4 Pro, 2026-09-08
3060
+
3061
+ The untouched app passes the required functional checks after a fresh Pi run
3062
+ on `Joshs-MBP-2025.local`, Apple M4 Pro, 24 GB, using the required 12.14 GiB
3063
+ Trellis target. The published Luke Q3 coding 128K profile, unchanged prompt,
3064
+ xhigh thinking, sampling and seed 42 remain fixed. The candidate uses MLX
3065
+ 0.32.2, target KV4, MTP depth 2 and paired RAM prefixes. Processes, application
3066
+ caches, Pi session and task workspace started fresh; OS file cache was not purged.
3067
+
3068
+ | Completed task metric | Result |
3069
+ |---|---:|
3070
+ | Prompt submitted to Pi settled | **3h 33m 7.685s** |
3071
+ | Including server startup | 3h 33m 8.581s |
3072
+ | First request time to first output | 23.145 s |
3073
+ | Reported output tokens, including reasoning and compaction | **130,494** |
3074
+ | Completed inference requests | 62 |
3075
+ | Output / whole task elapsed time | 10.205 tok/s |
3076
+ | Completed-response rate after first output | 13.904 tok/s |
3077
+ | Sum of request time before first output | 56.665 min |
3078
+ | MTP draft-token acceptance | 79.706% |
3079
+ | Peak sampled combined server/Pi RSS | 11.916 GiB |
3080
+
3081
+ All 443 source, profile, request, usage and timing audit checks pass. Every
3082
+ response has terminal usage; the output total is exact. Pi and the server
3083
+ exit normally, with no inference error or automatic retry. Pi encounters
3084
+ seven tool execution errors during its own debugging and completes the task
3085
+ without external repair prompts.
3086
+
3087
+ One context compaction is included in the total. Its summary request uses
3088
+ 90,214 input tokens, reports 1,404 output tokens, and takes **19m 42.705s**,
3089
+ including 17m 37.551s before first output. The following coding request has
3090
+ 28,126 input tokens and takes another 4m 22.552s before first output.
3091
+ Both prompts have zero cached tokens because the summary changes the exact
3092
+ serialized prefix. The first ordinary tool turn separately takes 8m 53.415s
3093
+ before first output after the initial 50,533-token response; its cached prefix
3094
+ contains only 2,549 tokens. These are measured targets for reducing repeated
3095
+ prefill, not claimed savings. The frozen outcome helper recorded zero
3096
+ compactions because it recognized only `auto_compaction_start`; derived
3097
+ reports count the observed `compaction_start` while preserving the raw result.
3098
+
3099
+ The server's last observed OS lifetime peak physical footprint is
3100
+ **18,913,094,336 bytes**. The external monitor began during the task and
3101
+ sampled through five seconds before exit; lifetime counters include earlier
3102
+ process history but may miss the final interval. Physical footprint and the
3103
+ runner's sampled combined RSS are different measurements. Separate process
3104
+ lifetime peaks are not added as though they were concurrent.
3105
+
3106
+ After inference exited, independent browser checks passed card creation,
3107
+ required-title editing, description/labels/assignee fields, combined filters,
3108
+ archive/restore, column creation/rename/safe deletion/restore, native card
3109
+ and column reordering, the Done indicator, and persisted theme/board/order.
3110
+ The app supplies run instructions and modular vanilla code. No generated
3111
+ source was edited. Earlier automated reorder probes remain recorded; native
3112
+ mouse motion with dragover before release confirms both reorder operations.
3113
+
3114
+ This establishes a completed task on the frozen candidate. There is no
3115
+ matched successful original baseline, so it establishes no task-time speedup
3116
+ percentage. The complete first response and every MTP acceptance decision
3117
+ match the preceding failed attempt; its time changes from 3,152.595 to
3118
+ 3,147.633 seconds, effectively flat in one pair. The bounded range cache's
3119
+ measured benefit remains retained-memory correction and successful completion.
3120
+
3121
+ Raw evidence: `reports/qwen38-rd/kanban-final/luke-q3-128k-xhigh-arange-bounded/`
3122
+ contains `result.json`, `measurement-audit.json`, `quality.json`, referenced
3123
+ browser evidence, `memory-summary.json`, the untouched app and saved sources.
3124
+ The derived HTML report is `reports/qwen38-rd/kanban-final/comparison.html`.
3125
+
3126
+ Offline analysis of this successful trace reconciles all 62 terminal usage
3127
+ records to 130,494 output tokens, including the 1,404-token compaction. The
3128
+ server reports 3,980,688 cumulative prompt tokens and 3,701,542 cached tokens
3129
+ through the enabled paired target/draft RAM prefix cache; these are repeated
3130
+ request counts, not unique text or a measured time-saving percentage. An
3131
+ exact-substring analysis of 593,994 Unicode characters from 380 original
3132
+ input/output segments finds 2,830 maximal repeats of at least 32 characters
3133
+ (after excluding separator noise). The longest is 10,304 characters, a file
3134
+ write followed by a read. Replayed history and duplicated log events are
3135
+ excluded; nested/overlapping repeat families remain, so counts do not imply
3136
+ removable work. Local derived evidence and methodology:
3137
+ `~/.cache/mlx-bun/analysis/kanban-success/{analysis,duplicates}/report.md`,
3138
+ with the hashed source snapshot, per-request counts and repeat locations.
3139
+ Token-ID analysis of those same independently retokenized segments contains
3140
+ 160,352 tokens and 2,756 maximal repeats of at least eight tokens after the
3141
+ same noise filter; the longest is 2,732 tokens, occurring twice. This is
3142
+ reconstructed-text tokenization, not the sampled-token stream. Methodology,
3143
+ source/tokenizer hashes, all matches and histogram are retained alongside
3144
+ that evidence under `kanban-success/token-duplicates/`.
3145
+ Counting only later generated positions matching earlier generated content,
3146
+ with first occurrences retained and overlapping intervals merged, gives
3147
+ 48,932 duplicated retokenized positions at the eight-token cutoff, including
3148
+ 26,965 tool-argument positions matching prior reasoning. At a 32-token cutoff
3149
+ the total is 26,602. These are approximate 37.50%/20.39% shares of the 130,494
3150
+ reported output tokens: the normalized generated corpus has 127,905 tokens
3151
+ and excludes wire framing/escaping. They are not measured time savings.
3152
+ Method and interval evidence: `generated-duplicate-report.md` and its JSON
3153
+ companions in the same token-analysis directory.
3154
+
3155
+ A narrative reconstruction with an embedded source browser is saved at
3156
+ `~/.cache/mlx-bun/analysis/kanban-success/timeline/kanban-story.html`.
3157
+ Its clock uses cumulative completion tokens and places external actions at
3158
+ completed assistant-response boundaries: the first tool action follows
3159
+ 50,533 generated tokens. The account distinguishes code drafted in reasoning, file writes,
3160
+ repairs to the synthetic DOM test harness, and concrete application fixes.
3161
+ The trace identifies candidates for shortening the run; it does not establish
3162
+ which reasoning could be removed while preserving the successful outcome.
3163
+
3164
+ ### Speculative decoding — "should spec be on?" (decision pending Phase 0/1 runs)
3165
+
3166
+ Decision rule: spec defaults ON for a (target, drafter) pair iff
3167
+ serve-path decode ≥ 1.3× serial at the recommended γ, clean-machine
3168
+ paired (`scripts/bench-serve.ts all` preflight, `bench-feature-matrix.ts --cells
3169
+ serial,spec`), with acceptance within 3 pts of the bf16-drafter baseline
3170
+ (`scripts/dspark.ts ab`). Prediction to test: ON for
3171
+ 12B + quantized DeepSpec drafter, OFF for e4b + anything.
3172
+
3173
+ | target | drafter | γ | acceptance | τ | spec tok/s | serial tok/s | verdict |
3174
+ |---|---|---|---|---|---|---|---|
3175
+ | 12B-OptiQ-4bit | DeepSpec bf16 (6.9 GB) | 7 | 26–33% | ≈2.8 | 14.6 agg | 49.8 agg | **OFF** — drafter tax −3.4× (2026-07-07 first live run, loaded box, conc-4; directional) |
3176
+ | 12B-OptiQ-4bit | DeepSpec affine-q4-g64 (1.8 GB, built 2026-07-07) | best-of-0b | _1d run_ | _1d run_ | _0b/6 run_ | _0b/6 run_ | _pending_ |
3177
+ | e4b-OptiQ-4bit | (expected-negative control) | — | — | — | — | — | _pending_ |
3178
+
3179
+ Runbook (Josh's shell; directional passes fine loaded, the FINAL pair
3180
+ clean-machine per the house rule):
3181
+ 1. **1d acceptance A/B** (no server): `bun scripts/dspark.ts ab
3182
+ --target gemma-4-12B-it-OptiQ-4bit --drafter-a <bf16-snap>
3183
+ --drafter-b <q4-snap> --json ab-q4.json` — gate: drop ≤ 3 pts AND
3184
+ wall-clock strictly improves.
3185
+ 2. **0b γ sweep** (server): serve 12B `--draft-model <q4-snap>
3186
+ --num-draft-tokens {2,3,5,7}` × `bun scripts/bench-matrix.ts features
3187
+ --concurrency 1 --cells serial,spec` — pick best-γ by per-request tok/s.
3188
+ 3. **Phase 6 decision pair** (clean machine: reboot + `sudo purge`):
3189
+ best-γ config, `--cells serial,spec` at conc 1 AND agg×4 — fill the
3190
+ table, flip the features-matrix default cell if ≥ 1.3×.
3191
+
3192
+ ### TurboQuant KV — decided OFF (2026-07-06, re-affirmed post-leak-fix)
3193
+
3194
+ Opt-in memory/context lever, not a speed feature (v1 dequant-on-fetch is
3195
+ slower per step at long context; no speed claim made). The KL-vs-bpw
3196
+ curve above is the quality evidence. NOTE: any turbo perf/RSS impression
3197
+ formed before 2026-07-07 is invalid — the pre-fix build leaked
3198
+ window-scale buffers per decode step (PLAN Phase 13 post-merge fix).
3199
+
3200
+
3201
+ ### Shared Gemma assistant drafting, M4 Pro 24 GB, 2026-09-10
3202
+
3203
+ Four `bench-serve.ts all` arms in control/candidate/candidate/control order,
3204
+ Bun 1.4.2, MLX 0.32.2. Gemma4 12B OptiQ4 target with its bf16 assistant,
3205
+ draft depth 2, bf16 target KV, 2 GiB RAM cache plus temporary SSD, 192 decode
3206
+ tokens, four concurrent requests and default capacity eight. Workload seed
3207
+ `assistant-spec-0`; diagnostic mode under Josh's CPU/swap policy. Source snapshots
3208
+ `c8213540beb87f438fbafad7115b49f494e92526c28acca930f134883d5cfdcf`
3209
+ → `db38e64dbc3421ba5750485d8d6328afad63b64883bae8b945ff76e0ae6f1f21`.
3210
+ The candidate includes the shared assistant graph/provider, hidden companions,
3211
+ donor validity ports and the oracle-aligned strided weight views.
3212
+
3213
+ | Metric, mean of two arms | Previous implementation | Shared assistant | Change |
3214
+ |---|---:|---:|---:|
3215
+ | Median single-request decode, tok/s | 25.637 | 26.583 | +3.69% |
3216
+ | Four-request aggregate, tok/s | 24.815 | 34.129 | +37.53% |
3217
+ | Four-request wall time, ms | 20,632.8 | 15,002.1 | −27.29% |
3218
+ | Cached prefill, ms | 2,573.4 | 116.7 | −95.47% |
3219
+ | Cold prefill, ms | 2,581.1 | 2,527.6 | −2.08% |
3220
+ | Server readiness, ms | 723.5 | 1,016.1 | +40.45% |
3221
+ | Cold start, ms | 2,244.1 | 2,094.7 | −6.66% |
3222
+ | Peak RSS, MiB | 9,744.6 | 10,042.8 | +3.06% |
3223
+
3224
+ All 60 requests complete without failures with matching request bodies and token
3225
+ budgets. Single-request text and raw completion/chat probes match. Three of four
3226
+ concurrent responses differ across implementations; each implementation repeats
3227
+ exactly, including usage. Shared cached requests reuse 668 tokens, versus zero.
3228
+ Mean cold-start improvement is within substantial variation: candidate arms are
3229
+ 1.712 and 2.478 seconds. Readiness regresses by 293 ms; strict startup dominance
3230
+ remains open. These numbers compare implementations with the same assistant,
3231
+ not assistant speculation versus ordinary decoding. Defaults are unchanged.
3232
+
3233
+ Both-machine e4b/12B graph and serving/cache tests pass; e4b matches unmodified
3234
+ optiq `spec_generate` end to end. The pinned 12B loader lacks tensor-presence head
3235
+ detection, so its numerical test explicitly binds the artifact's tied embedding
3236
+ head while retaining upstream layers. Both-machine Qwen MTP/TQ regressions, full
3237
+ suites and all typechecks pass. Evidence:
3238
+ `reports/qwen38-closeout/composition-baseline/assistant-batch/`.
3239
+
3240
+
3241
+ ### Shared DeepSpec drafting, M4 Pro 24 GB, 2026-09-10
3242
+
3243
+ Four `bench-serve.ts all` arms in control/candidate/candidate/control order,
3244
+ Bun 1.4.2, MLX 0.32.2. Gemma4 12B OptiQ4 target with the DeepSpec affine-q4-g64
3245
+ drafter, trained depth seven, bf16 target KV, 2 GiB RAM cache plus temporary SSD,
3246
+ 192 decode tokens, four concurrent requests and default capacity eight. Seed
3247
+ `deepspec-spec-0`; diagnostic mode under Josh's CPU/swap policy. Frozen sources
3248
+ `db38e64dbc3421ba5750485d8d6328afad63b64883bae8b945ff76e0ae6f1f21`
3249
+ → `39b289a30244e8f37bc8457c7e8f4e36deae428340157cd90c3a4c2287610dda`.
3250
+ The candidate adds shared context projections, batched proposals and persisted
3251
+ method companions. Both arms use the same target, drafter and settings.
3252
+
3253
+ | Metric, mean of two arms | Previous implementation | Shared DeepSpec | Change |
3254
+ |---|---:|---:|---:|
3255
+ | Median single-request decode, tok/s | 25.288 | 25.950 | +2.62% |
3256
+ | Four-request aggregate, tok/s | 25.191 | 53.187 | +111.14% |
3257
+ | Four-request wall time, ms | 20,326.0 | 9,626.5 | −52.64% |
3258
+ | Cached prefill, ms | 2,724.6 | 345.1 | −87.33% |
3259
+ | Cold prefill, ms | 2,715.1 | 2,737.0 | +0.81% |
3260
+ | Server readiness, ms | 612.5 | 1,319.1 | +115.37% |
3261
+ | Cold start, ms | 2,509.8 | 2,918.0 | +16.26% |
3262
+ | Peak RSS, MiB | 10,772.8 | 11,057.6 | +2.64% |
3263
+
3264
+ All 60 requests complete without failures and use matching request bodies and
3265
+ budgets. Single-request text and raw completion/chat probes match. One of four
3266
+ concurrent responses differs; both implementations repeat exactly, including
3267
+ usage. Cached requests reuse 671 tokens versus zero. Decode samples within each
3268
+ arm span roughly 15–16%, although the repeated medians agree. The small B1 gain
3269
+ should be read with that variation. Readiness regresses by 707 ms and cold start
3270
+ by 408 ms on average; strict startup dominance remains open. Defaults are unchanged.
3271
+
3272
+ Both-machine bf16/4-bit graph controls, depth-seven serving/generated RAM/SSD,
3273
+ regression suites and all typechecks pass. The graph comparisons preserve the
3274
+ frozen implementation; they are not a new external DeepSpec oracle. Real-window
3275
+ checks confirm active shared speculation across wrap. Evidence:
3276
+ `reports/qwen38-closeout/composition-baseline/deepspec-batch/`.
3277
+
3278
+
3279
+ ### Shared projected-context extraction, M4 Pro 24 GB, 2026-09-10
3280
+
3281
+ Four `bench-serve.ts all` arms, control/candidate/candidate/control, use the same
3282
+ Gemma4 12B OptiQ4 target, trained DeepSpec q4-g64 drafter, depth seven, bf16 target
3283
+ KV, 2 GiB RAM plus temporary SSD, 192 decode tokens, four concurrent requests,
3284
+ default capacity eight and seed `deepspec-spec-0`. Bun 1.4.2, MLX 0.32.2,
3285
+ diagnostic mode under Josh's CPU/swap policy. Frozen sources
3286
+ `39b289a30244e8f37bc8457c7e8f4e36deae428340157cd90c3a4c2287610dda`
3287
+ → `9f8484fa9dca140b31ad685a2701563ed5a1e0a2638d27f48e31d1df4160f4ab`.
3288
+ The candidate extracts context ownership for reuse by DSpark/DFlash and DeepSpec.
3289
+ This measures the extraction with a trained DeepSpec drafter; no trained DSpark
3290
+ checkpoint was available for its own performance comparison.
3291
+
3292
+ | Metric, mean of two arms | DeepSpec-specific owner | Shared context owner | Change |
3293
+ |---|---:|---:|---:|
3294
+ | Median single-request decode, tok/s | 25.800 | 25.695 | −0.41% |
3295
+ | Four-request aggregate, tok/s | 53.597 | 52.229 | −2.55% |
3296
+ | Four-request wall time, ms | 9,552.8 | 9,805.0 | +2.64% |
3297
+ | Cached prefill, ms | 342.2 | 348.3 | +1.79% |
3298
+ | Cold prefill, ms | 2,722.4 | 2,778.2 | +2.05% |
3299
+ | Server readiness, ms | 1,318.4 | 1,421.7 | +7.84% |
3300
+ | Cold start, ms | 2,943.2 | 3,321.3 | +12.85% |
3301
+ | Peak RSS, MiB | 11,070.5 | 11,068.2 | −0.02% |
3302
+
3303
+ All 60 requests complete without failures; every request body, response and usage
3304
+ record matches across all four arms. Cached requests reuse 671 tokens in both.
3305
+ The first control cold start is 2.615 seconds; the other three arms range from
3306
+ 3.272 to 3.337 seconds. Candidate aggregate arms are 52.99 and 51.47 tok/s versus
3307
+ 53.75 and 53.44 controls. The measured cost is retained; this is not a speed win
3308
+ or strict dominance. Defaults are unchanged. Both-machine pinned Markov/RNN and
3309
+ independent confidence/sampling tests, seeded real-Gemma serving/generated RAM/SSD,
3310
+ trained DeepSpec regressions, full suites and typechecks pass. Evidence:
3311
+ `reports/qwen38-closeout/composition-baseline/dflash-batch/`.
3312
+
3313
+
3314
+ ### Reused artifact identity, M4 Pro 24 GB, 2026-09-10
3315
+
3316
+ Four `bench-serve.ts all` arms, control/candidate/candidate/control, use Gemma4 12B
3317
+ OptiQ4, trained DeepSpec q4-g64, depth seven, bf16 target KV, 2 GiB RAM plus temporary
3318
+ SSD, 192 decode tokens, four concurrent requests, default capacity eight and seed
3319
+ `deepspec-spec-0`. Bun 1.4.2, MLX 0.32.2, diagnostic mode under Josh's CPU/swap
3320
+ policy. Frozen sources `9f8484fa9dca140b31ad685a2701563ed5a1e0a2638d27f48e31d1df4160f4ab`
3321
+ → `e17613b8496e5820bb8f4a193e735a4d9129b5333c851886bb22cbd0c9c41bed`.
3322
+ The candidate resolves the same full configuration/name/byte SHA-256 through a
3323
+ shared artifact-identity store. Its unchanged-file memo was populated during
3324
+ native validation. These fresh server starts hit the identity memo; first-ever
3325
+ identity calculation still reads all shard bytes. Memo writes are queued.
3326
+
3327
+ | Metric, mean of two arms | Rehash each load | Reuse unchanged identity | Change |
3328
+ |---|---:|---:|---:|
3329
+ | Median single-request decode, tok/s | 25.881 | 25.975 | +0.37% |
3330
+ | Four-request aggregate, tok/s | 52.449 | 52.831 | +0.73% |
3331
+ | Four-request wall time, ms | 9,761.8 | 9,691.3 | −0.72% |
3332
+ | Cached prefill, ms | 350.0 | 346.1 | −1.12% |
3333
+ | Cold prefill, ms | 2,783.3 | 2,763.5 | −0.71% |
3334
+ | Server readiness, ms | 1,422.2 | 713.1 | −49.86% |
3335
+ | Cold start, ms | 3,332.1 | 2,709.7 | −18.68% |
3336
+ | Peak RSS, MiB | 11,072.1 | 10,784.0 | −2.60% |
3337
+
3338
+ All 60 requests complete without failures; every request body, response and usage
3339
+ record matches across all four arms. Cached requests reuse 671 tokens in both.
3340
+ Candidate readiness is 610/816 ms versus 1,422/1,422 ms; cold start is 2,590/2,829 ms
3341
+ versus 3,345/3,319 ms. Peak RSS decreases by 288.1 MiB on average. Throughput changes
3342
+ are small; the material gain is repeat loading. Sampling, draft-depth and KV
3343
+ defaults are unchanged. Both-machine Qwen MTP/TurboQuant and DeepSpec serving and
3344
+ generated RAM/SSD, complete suites and typechecks pass. Identity tests cover the
3345
+ previous digest, zero weight reads on memo hits, file/config/symlink mutation and
3346
+ failed persistence. Existing KV namespaces remain compatible. Evidence:
3347
+ `reports/qwen38-closeout/composition-baseline/artifact-identity/`.
3348
+
3349
+
3350
+ ### Affine rotating speculation, M4 Pro 24 GB, 2026-09-11
3351
+
3352
+ Six `bench-serve.ts all` arms run control/candidate/KV4/KV4/candidate/control.
3353
+ All use Gemma4 12B OptiQ4 weights, trained DeepSpec q4-g64 at depth seven,
3354
+ 2 GiB RAM plus temporary SSD, 192 decode tokens, four concurrent requests,
3355
+ default capacity eight and seed `deepspec-spec-0`. Bun 1.4.2 and MLX 0.32.2;
3356
+ diagnostic mode follows Josh's background-CPU/swap policy. Control and candidate
3357
+ use bf16 target KV; KV4 changes only that setting on the candidate source.
3358
+ Frozen source hashes are
3359
+ `e17613b8496e5820bb8f4a193e735a4d9129b5333c851886bb22cbd0c9c41bed`
3360
+ and `9f8819cce7c759eab2e86f5ba35e20d99e436491fd46c39966c59048ab44e60d`.
3361
+ Every arm retains its source hash through completion.
3362
+
3363
+ | Metric, mean of two arms | Control bf16 | Candidate bf16 | Candidate KV4 |
3364
+ |---|---:|---:|---:|
3365
+ | Median single-request decode, tok/s | 25.778 | 25.895 | 25.880 |
3366
+ | Four-request aggregate, tok/s | 52.947 | 52.995 | 55.398 |
3367
+ | Four-request wall time, ms | 9,671.7 | 9,661.4 | 9,242.3 |
3368
+ | Cached prefill, ms | 345.7 | 346.5 | 352.9 |
3369
+ | Cold prefill, ms | 2,749.7 | 2,748.8 | 2,814.0 |
3370
+ | Server readiness, ms | 611.5 | 611.7 | 612.1 |
3371
+ | Cold start, ms | 2,600.5 | 2,427.5 | 2,424.3 |
3372
+ | Peak RSS, MiB | 10,775.3 | 10,767.2 | 10,802.8 |
3373
+
3374
+ The source-only comparison is effectively flat: decode +0.45%, aggregate +0.09%,
3375
+ cached prefill +0.22%, cold prefill −0.03%. All 60 bf16 requests have identical
3376
+ request bodies, responses and usage records. Each setting repeats exactly.
3377
+ All 90 requests complete without benchmark failures and reuse 671 cached tokens.
3378
+
3379
+ KV4 reaches +4.63% aggregate throughput versus the bf16 control, with +2.07%
3380
+ cached and +2.34% cold prefill time. Ten of fifteen responses per KV4 arm differ
3381
+ from bf16, and accepted draft tokens total 1,042 versus 1,032. This is a measured
3382
+ precision/configuration tradeoff, not an isolated engine speed gain. Short-run
3383
+ RSS does not establish a memory saving; startup varies within the candidate
3384
+ arms. Defaults remain unchanged. Context/pressure and strict serial-dominance
3385
+ acceptance are not covered by this short comparison. Native tests separately
3386
+ cover generated RAM/SSD restoration, real-window rollback and KV4/KV8 provider
3387
+ composition on both Macs. Evidence:
3388
+ `reports/qwen38-closeout/composition-baseline/rotating-spec-quant/`.
3389
+
3390
+
3391
+ ### TurboQuant provider composition and centroid correction, M4 Pro 24 GB, 2026-09-11
3392
+
3393
+ Two six-arm `bench-serve.ts all` comparisons use
3394
+ control/candidate/TQ/TQ/candidate/control. Both use Bun 1.4.2, MLX 0.32.2,
3395
+ 192 decode tokens, four concurrent requests, capacity eight, 2 GiB RAM plus
3396
+ temporary SSD and fused TQ decoding enabled. Control/candidate target KV is
3397
+ bf16; the TQ arms select K8/V3 on the candidate. The CLI keeps start zero;
3398
+ sliding layers remain bf16. Diagnostic mode follows Josh's CPU/swap policy.
3399
+ Sources stay fixed through every arm:
3400
+ `9f8819cce7c759eab2e86f5ba35e20d99e436491fd46c39966c59048ab44e60d`
3401
+ → `f4c9fe17c9f0a691907ded7777e7814cc5eaed7811ac9941b4d1528ad75070bd`.
3402
+
3403
+ The candidate adds owned TQ donor attention and capability-based grouped draft
3404
+ selection, captures immutable numerical options and distinct per-layer cache
3405
+ identities, and corrects the small assistant's centroid head to the pinned
3406
+ bf16 multiply/sum arithmetic and lowest-token-ID tie rule. The independent M1
3407
+ oracle exposed the previous matmul shortcut; its decoded KV and hidden state
3408
+ were exact but its selected token differed. This correction applies at every B.
3409
+
3410
+ #### Gemma4 12B + trained DeepSpec
3411
+
3412
+ OptiQ4 target weights, q4-g64 DeepSpec block7, draft depth seven and seed `deepspec-spec-0`.
3413
+
3414
+ | Metric, mean of two arms | Control bf16 | Candidate bf16 | Candidate K8/V3 |
3415
+ |---|---:|---:|---:|
3416
+ | Median single-request decode, tok/s | 25.912 | 25.428 | 26.749 |
3417
+ | Four-request aggregate, tok/s | 53.635 | 51.962 | 54.258 |
3418
+ | Four-request wall time, ms | 9,546.956 | 9,854.496 | 9,436.373 |
3419
+ | Cached prefill, ms | 341.823 | 343.041 | 352.446 |
3420
+ | Cold prefill, ms | 2,688.505 | 2,758.072 | 2,772.306 |
3421
+ | Server readiness, ms | 616.147 | 616.509 | 610.971 |
3422
+ | Cold start, ms | 2,604.734 | 2,604.987 | 2,612.562 |
3423
+ | Peak RSS, MiB | 10,784.125 | 10,762.719 | 10,780.617 |
3424
+
3425
+ Source-only bf16 decode decreases 1.87% and aggregate throughput decreases
3426
+ 3.12%; cached prefill is +0.36%, cold prefill +2.59%. All 60 bf16 requests have
3427
+ identical bodies, responses and usage. The cost remains recorded and is under
3428
+ separate attribution testing. It is not a refactor speed win.
3429
+
3430
+ K8/V3 increases decode 3.23% and aggregate throughput 1.16% versus the old bf16
3431
+ control, with cached and cold prefill each about 3.1% slower. Nine of fifteen
3432
+ responses per TQ arm differ from bf16. Accepted draft tokens total 1,044 versus
3433
+ 1,032. Each TQ repeat matches its own responses and usage exactly.
3434
+
3435
+ #### Gemma4 e4b + assistant
3436
+
3437
+ OptiQ4 target weights, bf16 assistant, draft depth three and seed `assistant-spec-0`.
3438
+
3439
+ | Metric, mean of two arms | Control bf16 | Candidate bf16 | Candidate K8/V3 |
3440
+ |---|---:|---:|---:|
3441
+ | Median single-request decode, tok/s | 55.374 | 55.106 | 57.532 |
3442
+ | Four-request aggregate, tok/s | 94.152 | 93.340 | 91.267 |
3443
+ | Four-request wall time, ms | 5,438.005 | 5,485.344 | 5,609.896 |
3444
+ | Cached prefill, ms | 88.692 | 89.947 | 92.351 |
3445
+ | Cold prefill, ms | 962.402 | 960.880 | 967.007 |
3446
+ | Server readiness, ms | 621.475 | 610.243 | 611.252 |
3447
+ | Cold start, ms | 1,309.033 | 894.498 | 906.810 |
3448
+ | Peak RSS, MiB | 6,880.625 | 6,889.672 | 6,929.180 |
3449
+
3450
+ The centroid correction and interface changes decrease bf16 decode 0.49%
3451
+ and aggregate throughput 0.86%. All bf16 response text is unchanged, while
3452
+ draft-acceptance usage changes: 530 accepted tokens per candidate arm versus
3453
+ 532 in each control. Each arm repeats its own response and usage exactly.
3454
+ The first control cold start is 1,726 ms; all later arms are 888–914 ms, so
3455
+ the mean startup difference is not attributed to this change.
3456
+
3457
+ K8/V3 increases decode 3.90% versus the old bf16 control but decreases aggregate
3458
+ throughput 3.06%; cached prefill is +4.13%, cold prefill +0.48%. Nine of fifteen
3459
+ responses per TQ arm differ from bf16, and draft acceptance totals 557.
3460
+ The TQ arms repeat exactly. This setting benefits single-request decode on
3461
+ this workload and loses concurrent throughput.
3462
+
3463
+ All 180 requests complete without benchmark failures. Cached requests retain
3464
+ 671 tokens for 12B and 668 for e4b. These are short configuration tradeoffs, not
3465
+ long-context memory or pressure acceptance. Defaults remain unchanged and strict
3466
+ serial dominance stays open. Both-machine native coverage includes assistant,
3467
+ DeepSpec, standalone and lookup serving/generated RAM/SSD, delayed conversion,
3468
+ independent assistant codec/graph controls, seeded DSpark heads and Qwen MTP
3469
+ regressions; the final suites and typechecks pass. Evidence and source manifests:
3470
+ `reports/qwen38-closeout/composition-baseline/turboquant-donor/`.
3471
+
3472
+ ### TurboQuant option-capture attribution (M4 Pro, 2026-09-11)
3473
+
3474
+ Same Gemma4-12B/DeepSpec7 workload and settings as the TurboQuant composition comparison above, all using bf16 KV. The sequence isolates request-option capture from numerical kernels. Frozen integrated source `f4c9fe17…` is unchanged; the key-restored variant is `cb063841…`, and the shallow-clone/conditional-assignment variant is `09e02ca6…`.
3475
+
3476
+ | Arm, in execution order | Decode median tok/s | Aggregate tok/s | Cached TTFT ms | Cold TTFT ms |
3477
+ |---|---:|---:|---:|---:|
3478
+ | deep-key-ablation-1 | 25.898 | 53.222 | 343.92 | 2728.18 |
3479
+ | deep-candidate-attribution-1 | 25.899 | 52.984 | 346.27 | 2748.01 |
3480
+ | deep-options-capture-1 | 25.910 | 53.942 | 339.04 | 2640.71 |
3481
+ | deep-candidate-attribution-2 | 25.897 | 53.063 | 346.38 | 2752.70 |
3482
+ | deep-options-capture-2 | 25.895 | 52.690 | 350.81 | 2769.67 |
3483
+
3484
+ The unchanged integrated build recovered the original decode rate on both repeats. Neither key restoration nor the option-copy variant establishes a repeatable speed benefit; retain the integrated implementation. The earlier measured source-only costs remain recorded, but attributing them to a code regression is not supported by these repeats. All five arms retain five distinct decode samples (reported within-arm spread about 1.15–1.16); these medians are comparisons of that fixed workload, not five identical requests. Raw requests, source identities and comparison: `reports/qwen38-closeout/composition-baseline/turboquant-donor/{m4,performance-attribution.json}`.
3485
+
3486
+ ### Delayed/per-layer affine rotating speculation (M4 Pro, 2026-09-11)
3487
+
3488
+ Gemma4-12B OptiQ-4bit with the q4 DeepSpec block-7 drafter, depth seven, Bun 1.4.2/MLX 0.32.2, 192 decode tokens, four concurrent requests, scheduler capacity eight, 2 GiB RAM prompt cache plus temporary SSD. Same `deepspec-spec-0` workload as the previous composition comparison. Order: control bf16, candidate bf16, candidate per-layer, candidate per-layer, candidate bf16, control bf16. The control source is `f4c9fe17…`; candidate `072bf3ca…`. All six source snapshots remain fixed through completion.
3489
+
3490
+ | Setting (mean of two arms) | Decode tok/s | Aggregate tok/s | Aggregate wall ms | Cached TTFT ms | Cold TTFT ms | Ready ms | Startup ms | Peak RSS MiB |
3491
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
3492
+ | control | 25.898 | 53.455 | 9579.865 | 344.315 | 2696.925 | 616.786 | 2603.127 | 10795.445 |
3493
+ | candidate | 25.713 | 53.643 | 9545.352 | 339.185 | 2680.571 | 614.743 | 2544.107 | 10775.914 |
3494
+ | per-layer | 27.430 | 52.456 | 9760.580 | 353.531 | 2655.698 | 616.945 | 2544.832 | 10816.516 |
3495
+
3496
+ Source-only bf16 comparison: decode −0.716%, aggregate +0.353%, cached TTFT −1.490%, cold TTFT −0.606%. Every bf16 request, response and usage record matches. The first candidate decode median is lower than its second repeat; the small source-only cost remains recorded and does not satisfy strict B1 dominance.
3497
+
3498
+ Model-defined mixed per-layer affine KV versus control bf16: decode +5.916%, aggregate −1.868%, cached TTFT +2.677%, cold TTFT −1.529%. Ten of fifteen responses differ from bf16; each configuration repeats exactly, including usage. All ninety requests complete with no phase failures. Precision changes affect the numerical trajectory and draft acceptance, so this setting comparison is not an engine-only same-output speedup. Defaults remain unchanged.
3499
+
3500
+ Both-machine native serving/generated RAM/SSD, delayed transition and real-window hidden/logit controls pass for the qualified providers. Seeded DSpark fixtures establish Markov/RNN execution and state contracts, not trained quality or acceptance. Raw arms and exact pair comparisons: `reports/qwen38-closeout/composition-baseline/delayed-rotating-spec/{m4,benchmark-comparison.json}`.
3501
+
3502
+
3503
+ ### Paged storage in the shared executor (M4 Pro, 2026-09-11)
3504
+
3505
+ Gemma4-12B OptiQ-4bit, bf16 KV, Bun 1.4.2/MLX 0.32.2, 192 decode tokens, four concurrent requests, 2 GiB RAM cache plus temporary SSD, workload `paged-compose-0`. Paged storage uses 256-token blocks and bypasses both cache tiers. The ordinary source comparison keeps continuous scheduling on both sides. The paged comparison uses the old serial executor versus the candidate shared executor (capacity eight). Frozen source: control `db451918…`, candidate `a9fe941c…`; both include identical benchmark argument plumbing. Each configuration runs twice, with reversed control/candidate order. All source snapshots remain fixed.
3506
+
3507
+ | Configuration (mean of two arms) | Decode tok/s | Aggregate tok/s | Aggregate wall ms | Repeated-prompt TTFT ms | Cold TTFT ms | Ready ms | Startup ms | Peak RSS MiB |
3508
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
3509
+ | Ordinary control | 26.455 | 72.894 | 7023.933 | 153.036 | 2436.522 | 616.814 | 1452.364 | 8936.141 |
3510
+ | Ordinary candidate | 26.480 | 72.913 | 7022.101 | 154.218 | 2437.542 | 613.202 | 1588.357 | 8946.594 |
3511
+ | Paged serial control | 26.310 | 24.832 | 20618.569 | 2462.690 | 2443.653 | 613.156 | 1425.283 | 8915.117 |
3512
+ | Paged shared candidate | 26.289 | 70.240 | 7289.413 | 2490.439 | 2479.725 | 611.401 | 1218.411 | 8940.664 |
3513
+
3514
+ Ordinary source cost is effectively flat: decode +0.094%, aggregate +0.026%, cold TTFT +0.042% and cached TTFT +0.772%. Every paired response and usage record is identical. Startup varies more (+9.36% in the two-arm mean); this short comparison does not establish startup dominance.
3515
+
3516
+ Shared paged execution increases four-request throughput **182.86% (2.83×)** and reduces task wall time **64.65%**. Single-request decode changes −0.081%; cold TTFT increases 1.48% and repeated-prompt TTFT 1.13%. The first concurrent request reaches output in 365.84 versus 365.86 ms. Peak RSS increases 25.55 MiB. Two concurrent responses differ from serial in each pair; all single-request responses and token counts match. Every configuration repeats its own text and usage exactly. The repeated paged prompt restores zero tokens, as expected; ordinary restores 669. This is concurrent execution scaling, not a single-request decode-kernel speedup.
3517
+
3518
+ Eight successful arms complete 120 requests without phase failures. Four earlier paged setup attempts failed before readiness because the harness enables SSD while `--prompt-cache 0` disables its required RAM tier; those reports remain in the evidence, and both paged sides were rerun with the same 2 GiB setting. The machine retained about 1.65 GiB swap with 91% free memory and no competing GPU job; diagnostic mode follows Josh's campaign policy.
3519
+
3520
+ The long native comparison initially allowed ordinary cache snapshots to change prefill cohort/query boundaries while paging bypassed them. Holding arrivals alone did not equalize that graph. The corrected storage comparison holds arrivals and disables snapshot splitting on both sides; it checks full logits and tokens beyond the default block boundary. Separate HTTP coverage checks sampling, logprobs and grammar. Raw arms, source manifest, setup failures and exact request comparisons: `reports/qwen38-closeout/composition-baseline/paged-rows/`. Direct paged attention, block sharing and composed quantized/speculative paging remain open; defaults are unchanged.
3521
+
3522
+
3523
+ ### Adapter-qualified prompt lookup (M4 Pro, 2026-09-11)
3524
+
3525
+ Gemma4 e4b OptiQ-4bit with the existing `upper` LoRA adapter (weights SHA-256 `94f83569ba85df9e05557238809101cd19f9eabd0149c7931904e2a58774a05b`), bf16 KV, Bun 1.4.2/MLX 0.32.2, scheduler capacity eight, 192 decode tokens, four concurrent requests, 2 GiB RAM cache plus temporary SSD. Same `adapter-lookup-0` request bodies in every arm. Frozen control `a9fe941c…` and candidate `cce6e1e6…`; two repetitions per configuration in reversed control/candidate order.
3526
+
3527
+ The ordinary arms omit draft flags and isolate source cost. The lookup arms request ngram depth three: the old control disables speculation for adapters, while the candidate honors it through the grouped provider capability. This second comparison therefore measures newly enabled behavior.
3528
+
3529
+ | Configuration (mean of two arms) | Decode tok/s | Aggregate tok/s | Aggregate wall ms | Cached TTFT ms | Cold TTFT ms | Ready ms | Startup ms | Peak RSS MiB |
3530
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
3531
+ | ordinary-control | 53.888 | 159.078 | 3218.551 | 38.040 | 526.635 | 610.894 | 893.690 | 6751.648 |
3532
+ | ordinary-candidate | 53.800 | 158.943 | 3221.290 | 38.246 | 523.882 | 610.938 | 893.021 | 6763.688 |
3533
+ | lookup-control | 53.746 | 159.064 | 3218.837 | 38.244 | 524.087 | 611.516 | 951.899 | 6731.523 |
3534
+ | lookup-candidate | 53.136 | 78.537 | 6519.231 | 30.925 | 518.250 | 611.589 | 945.210 | 6766.641 |
3535
+
3536
+ Ordinary source cost is effectively flat: decode −0.163%, aggregate −0.085%, cold TTFT −0.523% and cached TTFT +0.543%. Every ordinary response and usage record matches across source versions.
3537
+
3538
+ Enabling lookup decreases single-request decode 1.14% and four-request throughput **50.63%**, increasing aggregate wall time **102.53%**. It lowers cached TTFT 19.14%. Each concurrent block accepts only 26 of 444 proposed tokens (5.86%); repeated rejection makes this configuration a poor throughput choice. Concurrent cached prefixes also change from 11 tokens under ordinary execution to zero under the paired lookup namespace. That small prefill difference does not establish the cause of the decode cost.
3539
+
3540
+ Eight of fifteen responses change with the enabled method, including five single-request decode probes and three concurrent responses; token counts and finish reasons match. Each configuration repeats its own responses and usage exactly. All 120 requests complete without phase failures. This is not a same-output speed gain and does not justify a default change. A stricter ngram-match screen follows separately.
3541
+
3542
+ Native composition checks cover bf16/KV4 and TurboQuant, compatible adapter cohorts, seeded logprobs, namespace replacement, callback failure and generated RAM/SSD restart identity on both Macs. The HTTP fixture explicitly checks token alignment with the generated SSD header: appending an extra newline changes the M4 KV4 boundary, so the original fixture correctly reused an earlier prompt checkpoint. Preserving the generated newline restores the complete generated boundary; no cache assertion was relaxed. Raw arms, source manifest and request comparison: `reports/qwen38-closeout/composition-baseline/adapter-lookup/`.
3543
+
3544
+
3545
+ ### Ngram match-length screen with the upper adapter (M4 Pro, 2026-09-11)
3546
+
3547
+ Same e4b/upper-adapter artifact, bf16 KV, depth three, cache settings and `adapter-lookup-0` workload as above. Source `ef832276…` differs only by adding benchmark forwarding for the existing `--ngram-min`/`--ngram-max` flags. Order is 1–3, 2–3, 3–3, 5–5, then the reverse. Each arm retains five decode samples; table values are means of the two arm medians for decode and means for other timings.
3548
+
3549
+ | Minimum–maximum match | Decode tok/s | Aggregate tok/s | Aggregate wall ms | Cached TTFT ms | Cold TTFT ms | Aggregate accepted/proposed, arm A |
3550
+ |---|---:|---:|---:|---:|---:|---:|
3551
+ | min1-max3 | 53.949 | 78.566 | 6516.923 | 30.535 | 529.999 | 39/455 |
3552
+ | min2-max3 | 56.532 | 115.274 | 4442.253 | 47.959 | 537.508 | 26/90 |
3553
+ | min3-max3 | 53.552 | 130.850 | 3913.573 | 47.439 | 533.417 | 17/30 |
3554
+ | min5-max5 | 50.495 | 134.898 | 3796.100 | 47.561 | 525.433 | 20/24 |
3555
+
3556
+ Requiring longer matches avoids many rejected proposals. Minimum two has the highest single-request decode in this screen; minimum five has the highest aggregate throughput. Neither dominates ordinary execution from the adjacent matched campaign (about 53.8 decode and 159 aggregate tok/s). Minimum two improves single-request decode but still gives up concurrent throughput; minimum five lowers both decode and aggregate throughput versus ordinary. Lookup stays opt-in; these results do not establish a global match-length default.
3557
+
3558
+ Three concurrent responses/usage records differ between the minimum-one repeats (39/455 versus 26/444 accepted/proposed); their aggregate timings remain close. The other settings repeat their own responses and usage exactly. Different match thresholds change response trajectories, so the timing differences are configuration results, not same-output engine speedups. All eight arms complete 120 requests without phase failures. Raw commands, request hashes, source identity and comparisons: `reports/qwen38-closeout/composition-baseline/ngram-settings/`.
3559
+
3560
+
3561
+ ### Independent greedy sampling across verification positions (M4 Pro, 2026-09-11)
3562
+
3563
+ Apple M4 Pro, 24 GB, Bun 1.4.2, MLX 0.32.2. Twelve matched `bench-serve.ts all` arms compare frozen control `ef832276f7a43d2a203e8d8e4b41c362459bf55d7389803af18ca8e995c83838` with candidate `22d1a38a761ea28c0dcd3ec90374a6a6931bbd9d2965bb7c64a65458aae45398`. Gemma e4b OptiQ with the upper adapter, bf16 KV, scheduler capacity eight, four concurrent requests, 192 decode tokens, 2 GiB prompt cache plus SSD, workload seed `adapter-lookup-0`. Each setting runs control/candidate/candidate/control. Diagnostic mode follows Josh's CPU/swap policy; retained swap and background App Store CPU activity are recorded in raw reports.
3564
+
3565
+ The sampler exposes a stateless operation for compatible greedy rows. Ordinary decode and speculative verification share normalized-score argmax; verification reads its independent token rectangle once. Grammar, processors, stochastic sampling, logprobs and custom sampler functions retain request-local sampling. Tests include rounding-created ties where raw-logit argmax would choose a different token.
3566
+
3567
+ Means of the two arm medians for single-request decode/cold latency; means of the two measured aggregate/cached values:
3568
+
3569
+ | Method | Decode control → candidate, tok/s | Aggregate control → candidate, tok/s | Aggregate change | Cached TTFT control → candidate, ms | Cold TTFT control → candidate, ms |
3570
+ |---|---:|---:|---:|---:|---:|
3571
+ | Ordinary | 54.198 → 54.278 | 162.724 → 162.721 | −0.002% | 38.378 → 37.283 | 530.258 → 522.210 |
3572
+ | Lookup depth 3, min/max 1/3 | 55.101 → 54.898 | 79.716 → 80.779 | +1.334% | 30.760 → 30.517 | 518.664 → 516.427 |
3573
+ | Lookup depth 3, min/max 5/5 | 51.405 → 51.712 | 136.141 → 138.956 | +2.067% | 47.652 → 47.348 | 539.549 → 536.417 |
3574
+
3575
+ Ordinary decode changes +0.148%; lookup 1/3 changes −0.368%, and lookup 5/5 changes +0.598%. Aggregate wall time changes +0.002%, −1.319% and −2.025%, respectively. Startup changes +0.045%, +10.505% and −7.777%, while ready time stays within 0.3%; the small source change does not establish startup dominance. Peak RSS changes −0.321%, −0.248% and +0.413%.
3576
+
3577
+ All 180 requests succeed and every arm retains its source hash. The first paired comparisons preserve every response and usage record. Ordinary and 5/5 repeats are exact, as are both candidate 1/3 runs. The 1/3 control repeat changes three concurrent responses and speculation usage; it is not an exact repeated trajectory. The stricter lookup setting still loses aggregate throughput to ordinary decoding, so no lookup default changes. Both-machine numerical, full-suite/typecheck and adapter native/generated RAM/SSD checks pass. Raw commands, source inventories, results and response comparisons are under `reports/qwen38-closeout/composition-baseline/independent-sampling/`.
3578
+
3579
+
3580
+ ### Shared ordinary checkpoints and queued persistence (M4 Pro, 2026-09-11)
3581
+
3582
+ Apple M4 Pro, 24 GB, Bun 1.4.2, MLX 0.32.2. Ten matched `bench-serve.ts all` arms compare frozen control `6ab45ad7bda4adf9760eb69312bbf1dacdb8fe17592df9bc8f5699e7c8b692a9` with candidate `4dcf90668b7a319538ba648de196b72d81a8a26aa1bcef7d45ba5ce4f393c6e8`. Gemma e4b OptiQ, bf16 KV, no adapter, 192 decode tokens, four concurrent requests, 2 GiB prompt cache plus SSD, workload seed `ordinary-continuation-0`. Shared scheduler capacity is eight. Ordinary arms run control/candidate/candidate/control; checkpoint interval 64 runs old serial/new serial/new shared/new shared/new serial/old serial. Diagnostic mode follows Josh's CPU/swap policy; retained swap and background App Store CPU activity are recorded.
3583
+
3584
+ The candidate shares ordinary restore/capture through a checkpoint-policy interface and queues owned SSD snapshots through the existing idle gate. Completion invalidates the checkpoint immediately and queues ordered disk cleanup. Means of the two arm medians for decode/cold latency; means of aggregate/cached measurements:
3585
+
3586
+ | Execution | Decode tok/s | Aggregate tok/s | Aggregate wall ms | Cached TTFT ms | Cold TTFT ms |
3587
+ |---|---:|---:|---:|---:|---:|
3588
+ | Ordinary control | 59.401 | 169.043 | 3028.808 | 67.649 | 551.692 |
3589
+ | Ordinary candidate | 59.258 | 168.873 | 3031.856 | 67.720 | 553.158 |
3590
+ | Checkpoint, old serial | 58.702 | 57.265 | 8940.938 | 67.800 | 559.996 |
3591
+ | Checkpoint, queued serial | 59.011 | 57.458 | 8910.919 | 67.758 | 565.658 |
3592
+ | Checkpoint, queued shared | 58.905 | 168.159 | 3044.730 | 67.975 | 566.320 |
3593
+
3594
+ The ordinary source comparison changes decode −0.241%, aggregate throughput −0.101%, cached TTFT +0.105%, cold TTFT +0.266%, startup +0.480% and peak RSS +0.084%. Queuing serial persistence changes decode +0.526%, aggregate +0.337%, cold TTFT +1.011% and peak RSS −1.141% versus old serial. Moving checkpoint-enabled requests from queued serial to shared execution raises aggregate throughput **192.667% (2.927×)** and reduces aggregate wall time **65.831%**; single-request decode changes −0.179%, cached TTFT +0.321%, cold TTFT +0.117%, startup +0.648% and peak RSS +0.239%. This establishes concurrent throughput improvement on this workload, with the small single-request costs recorded.
3595
+
3596
+ All 150 requests succeed, source hashes stay fixed, and each arm repeats its own response/usage records exactly. Ordinary source and queued-serial comparisons preserve all responses and usage. Shared versus queued serial changes one concurrent response; all 15 usage records report the different execution lane and three concurrent requests reuse 11 rather than 13 prompt tokens. Other usage fields match. These timed requests complete normally; separate both-machine native and HTTP interruption/flush/fresh-server checks establish exact checkpoint restoration at matching batch geometry, including compiled and mixed-grammar bf16 controls. Those checks found a resumed shared cached-token counter could include replayed output; its clamp is under validation in the subsequent quantized candidate and is not part of this frozen timing source. This is not a process-crash durability or full Kanban acceptance result. Raw commands, source inventory and comparisons: `reports/qwen38-closeout/composition-baseline/ordinary-continuation-composition/`.
3597
+
3598
+ ### Shared ordinary continuation composition (M4 Pro, 2026-09-11)
3599
+
3600
+ Eight completed `bench-serve.ts all` arms on the Apple M4 Pro, 24 GB, Bun 1.4.2 and MLX 0.32.2. Gemma e4b OptiQ, no adapter, 192 decode tokens, four concurrent requests, scheduler capacity eight, 2 GiB RAM cache plus temporary SSD, checkpoint interval 64 and workload seed `ordinary-continuation-0`. Diagnostic mode follows Josh's campaign policy. Frozen control `4dcf90668b7a319538ba648de196b72d81a8a26aa1bcef7d45ba5ce4f393c6e8` and candidate `c918d6e76e702f86d66f17095f33f0aa00d912e8c7f4a469e9992dfbe90a03a0` run control/candidate/KV4/TurboQuant, then the reverse. Context sweeps are omitted in this short comparison.
3601
+
3602
+ The candidate composes ordinary continuation with shared cache layouts, fixes resumed cached-token accounting and the pending-token dtype, and materializes Gemma's model constants before compiler capture. Separate native/HTTP tests cover actual interruption and restoration; the timed requests complete normally. Decode and cold latency are means of arm medians; other columns are means of the two arms.
3603
+
3604
+ | Shared checkpoint configuration | Decode tok/s | Aggregate tok/s | Aggregate wall ms | Cached TTFT ms | Cold TTFT ms | Startup ms | Peak RSS MiB |
3605
+ |---|---:|---:|---:|---:|---:|---:|---:|
3606
+ | Control, bf16 KV | 59.186 | 168.196 | 3044.070 | 67.724 | 556.523 | 904.388 | 6751.820 |
3607
+ | Candidate, bf16 KV | 59.034 | 168.304 | 3042.116 | 67.836 | 558.943 | 908.403 | 6738.312 |
3608
+ | Candidate, affine KV4 | 58.286 | 164.636 | 3109.894 | 70.515 | 564.785 | 916.674 | 6768.227 |
3609
+ | Candidate, TurboQuant k8v3 | 57.197 | 165.002 | 3102.993 | 71.260 | 559.206 | 899.109 | 6744.930 |
3610
+
3611
+ At unchanged bf16 settings, decode changes −0.256%, aggregate throughput +0.064%, cached TTFT +0.166% and cold TTFT +0.435%. This is effectively flat performance. All source-comparison responses and usage records match. All four configurations repeat their own responses and usage exactly, all 120 requests succeed without phase failures, and every source hash remains fixed.
3612
+
3613
+ Compared with candidate bf16, KV4 changes decode −1.267% and aggregate throughput −2.179%; TurboQuant changes decode −3.112% and aggregate throughput −1.962%. KV4 changes ten response texts and TurboQuant nine, with unchanged usage records. These short-context settings do not improve speed or establish a memory advantage from peak RSS. They remain configuration tradeoffs rather than new defaults. Raw arms and derived response/timing comparisons: `reports/qwen38-closeout/composition-baseline/ordinary-continuation-final/`.