mlx-bun 0.4.0 → 0.5.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 (158) hide show
  1. package/README.md +57 -32
  2. package/docs/README.md +55 -42
  3. package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +3617 -0
  4. package/docs/archive/planning/release-notes-v0.5.0.md +37 -0
  5. package/docs/design/batching.md +220 -7
  6. package/docs/design/decode-speed-program.md +121 -66
  7. package/docs/design/generic-model-support.md +116 -0
  8. package/docs/design/kv-cache.md +380 -211
  9. package/docs/design/speculative-decoding.md +165 -26
  10. package/docs/design/turboquant.md +20 -7
  11. package/docs/design/unified-engine-frontier-plan.md +120 -13
  12. package/docs/planning/PRODUCT_ROADMAP.md +5 -6
  13. package/docs/planning/public-readiness-handoff.md +244 -0
  14. package/docs/planning/public-readiness.md +149 -0
  15. package/docs/reference/benchmarks.md +3463 -3489
  16. package/docs/reference/cli.md +62 -1
  17. package/docs/reference/distribution.md +29 -4
  18. package/docs/reference/environment.md +104 -8
  19. package/docs/reference/library-api.md +18 -4
  20. package/docs/reference/memory.md +1 -1
  21. package/docs/reference/models.md +17 -5
  22. package/docs/reference/server-api.md +181 -11
  23. package/docs/reference/server-config.md +232 -105
  24. package/package.json +2 -2
  25. package/src/audio/audiotoolbox.ts +112 -0
  26. package/src/audio/conformer.ts +8 -0
  27. package/src/audio/mic-capture.ts +98 -0
  28. package/src/audio/silero-vad.ts +379 -0
  29. package/src/audio/whisper-decode.ts +774 -0
  30. package/src/audio/whisper-fast.ts +732 -0
  31. package/src/audio/whisper-format.ts +73 -0
  32. package/src/audio/whisper-mel.ts +185 -0
  33. package/src/audio/whisper-timing.ts +274 -0
  34. package/src/audio/whisper-tokenizer.ts +239 -0
  35. package/src/audio/whisper-transcribe.ts +410 -0
  36. package/src/backends/mlx/autoregressive.ts +22 -1
  37. package/src/backends/mlx/batch-group.ts +111 -27
  38. package/src/backends/mlx/cache-layout.ts +3 -3
  39. package/src/backends/mlx/continuation-persistence.ts +5 -4
  40. package/src/backends/mlx/encoder-cache.ts +25 -0
  41. package/src/backends/mlx/fill-append.ts +21 -8
  42. package/src/backends/mlx/fill-group.ts +497 -0
  43. package/src/backends/mlx/gateway-binding.ts +56 -12
  44. package/src/backends/mlx/kv-maintenance.ts +30 -2
  45. package/src/backends/mlx/mixed-iteration.ts +62 -0
  46. package/src/backends/mlx/model-prompt.ts +46 -32
  47. package/src/backends/mlx/model-serving.ts +4 -3
  48. package/src/backends/mlx/paged-cache-codec.ts +27 -0
  49. package/src/backends/mlx/prefill-cohort.ts +15 -4
  50. package/src/backends/mlx/prefill-policy.ts +26 -0
  51. package/src/backends/mlx/prefill-rows.ts +57 -13
  52. package/src/backends/mlx/prompt-input.ts +29 -0
  53. package/src/backends/mlx/qwen-prompt-input.ts +40 -0
  54. package/src/backends/mlx/request-state-policy.ts +18 -5
  55. package/src/backends/mlx/rollback.ts +6 -3
  56. package/src/backends/mlx/serial-executor.ts +16 -7
  57. package/src/backends/mlx/speculative-group.ts +105 -26
  58. package/src/backends/mlx/speculative.ts +24 -7
  59. package/src/backends/mlx/target-layout-capability.ts +1 -1
  60. package/src/backends/mlx/transitioning-kv-rows.ts +8 -0
  61. package/src/cli.ts +322 -0
  62. package/src/contracts/execution.ts +10 -0
  63. package/src/contracts/object-cache.ts +8 -0
  64. package/src/contracts/pi-provider.ts +1 -1
  65. package/src/contracts/pi.ts +3 -1
  66. package/src/contracts/prefix-cache.ts +13 -3
  67. package/src/contracts/scheduling.ts +9 -0
  68. package/src/engine/execution-plan.ts +23 -12
  69. package/src/engine/execution-tasks.ts +44 -0
  70. package/src/engine/namespaced-cache.ts +13 -0
  71. package/src/engine/scheduler.ts +22 -2
  72. package/src/fill/fill-session.ts +14 -3
  73. package/src/generate.ts +28 -22
  74. package/src/grammar.ts +13 -0
  75. package/src/inference/prefill.ts +6 -0
  76. package/src/kv-scheme.ts +22 -0
  77. package/src/kv-store.ts +115 -79
  78. package/src/lab/README.md +5 -1
  79. package/src/lab/paged-kv/paged-attention.ts +117 -0
  80. package/src/lab/paged-kv/paged-kv-rows.ts +33 -5
  81. package/src/lab/paged-kv/paged-kv.ts +108 -42
  82. package/src/md-modules.d.ts +5 -0
  83. package/src/mlx/array.ts +37 -0
  84. package/src/mlx/ffi.ts +19 -0
  85. package/src/mlx/normalized-argmax.ts +116 -0
  86. package/src/mlx/ops.ts +97 -10
  87. package/src/model/batched-turboquant-kv.ts +6 -5
  88. package/src/model/delayed-quantized-kv.ts +3 -3
  89. package/src/model/delayed-rotating-quantized-kv.ts +1 -1
  90. package/src/model/delayed-turboquant-kv.ts +6 -4
  91. package/src/model/factory.ts +26 -0
  92. package/src/model/fingerprint.ts +12 -0
  93. package/src/model/full-prefill-row.ts +1 -1
  94. package/src/model/gemma4-base.ts +25 -6
  95. package/src/model/gemma4.ts +82 -2
  96. package/src/model/kv-attention-view.ts +4 -1
  97. package/src/model/profile.ts +29 -4
  98. package/src/model/quantized-append-attention.ts +31 -0
  99. package/src/model/qwen3-mrope.ts +7 -9
  100. package/src/model/qwen3_5.ts +99 -37
  101. package/src/model/support.ts +8 -0
  102. package/src/model/token-groups.ts +66 -0
  103. package/src/model/trellis-linear.ts +2 -2
  104. package/src/model/turboquant-codec.ts +6 -0
  105. package/src/model/whisper.ts +435 -0
  106. package/src/native/mic_capture.swift +92 -0
  107. package/src/native-pack.ts +6 -5
  108. package/src/pi-web.ts +9 -1
  109. package/src/prompt-cache.ts +265 -43
  110. package/src/runtime-config.ts +1 -5
  111. package/src/safetensors.ts +9 -2
  112. package/src/sampler.ts +5 -4
  113. package/src/serve/audio-routes.ts +323 -0
  114. package/src/serve/chat-request.ts +2 -0
  115. package/src/serve/chat-stage.ts +17 -12
  116. package/src/serve/completion-executor.ts +9 -1
  117. package/src/serve/discovery-routes.ts +17 -1
  118. package/src/serve/generated-token-history.ts +57 -0
  119. package/src/serve/generation-gateway.ts +52 -11
  120. package/src/serve/model-binding.ts +7 -1
  121. package/src/serve/preparation.ts +3 -3
  122. package/src/serve/prompt-response-trace.ts +14 -0
  123. package/src/serve/request-plan.ts +2 -0
  124. package/src/serve/request-prep.ts +38 -21
  125. package/src/serve/transcription-server.ts +64 -0
  126. package/src/serve/transcription-service.ts +502 -0
  127. package/src/server.ts +132 -164
  128. package/src/spec/assistant-rows.ts +1 -0
  129. package/src/spec/deepspec-rows.ts +1 -1
  130. package/src/spec/dflash-source.ts +1 -1
  131. package/src/spec/glm52-mtp-source.ts +1 -0
  132. package/src/spec/ngram-source.ts +27 -5
  133. package/src/spec/projected-draft-rows.ts +2 -2
  134. package/src/spec/qwen-mtp-rows.ts +11 -0
  135. package/src/spec/qwen-mtp-source.ts +3 -0
  136. package/src/spec/serve-loop.ts +5 -3
  137. package/src/spec/source.ts +14 -1
  138. package/src/spec/two-model-rows.ts +1 -0
  139. package/src/spec/two-model.ts +2 -2
  140. package/src/ssd-cache.ts +76 -17
  141. package/src/ssd-durability.ts +20 -22
  142. package/src/storage/host-buffer.ts +24 -0
  143. package/src/storage/kv-writer.ts +83 -0
  144. package/src/storage/kv-writer.worker.js +264 -0
  145. package/src/storage/retention-policy.ts +37 -0
  146. package/src/tiered-prompt-cache.ts +45 -0
  147. package/src/vision/embedder.ts +8 -0
  148. package/src/vision/prompt.ts +101 -65
  149. package/src/vision/qwen3vl-prompt.ts +101 -64
  150. package/src/vision/qwen3vl-tower.ts +11 -0
  151. package/src/vision/siglip.ts +8 -0
  152. package/src/web/app.html +12 -0
  153. package/src/web/app.js +160 -0
  154. package/src/web/src/chat.ts +4 -1
  155. package/src/web/src/composer.ts +3 -0
  156. package/src/web/src/voice.ts +141 -0
  157. package/src/web/sw.js +1 -1
  158. /package/docs/{planning → archive/planning}/release-notes-v0.4.0.md +0 -0
@@ -1108,16 +1108,13 @@ The bar for this tier is NOT token identity (sampling never guaranteed that):
1108
1108
  it is a paired A/B on task success and wall clock over mocked-replay agent
1109
1109
  sessions. Default off until that lands.
1110
1110
 
1111
- **Composition.** Serial lane only, and it never FORCES a request serial — a
1112
- batch-placed request simply does not fill, because `generate()` is the only
1113
- site that reads `options.fill`. Refused for: a compiled grammar (forced tokens
1114
- are its job), `logprobs`/`top_logprobs` (injected tokens have no distribution
1115
- row — the same rule as `shouldUseGrammarJump`), a user-fixed `seed`
1116
- (reproducibility: the step index would skip injected positions), media
1117
- prompts, a mounted draft model, quantized/TurboQuant KV (post-conversion
1118
- multi-token append is L-generic but unvalidated), and sliding-window models
1119
- (RotatingKVCache multi-token append is O(window) via `#updateConcat` — one
1120
- warning, then no fill).
1111
+ **Composition.** Strict fill has serial and shared methods. Shared fill keeps
1112
+ request-local sampler history and absolute seeded positions while using the
1113
+ same preparation and encoded-row interfaces as other methods. Echo verification
1114
+ remains an explicit serial operation. Grammar, probability metadata, media,
1115
+ mounted drafting, paging and interrupted-generation checkpoints remain separate
1116
+ compositions. Quantized committed append is supported by the qualified model
1117
+ bindings described below; quantized echo verification remains inactive.
1121
1118
 
1122
1119
  **Mismatch policy.** If `parseGeneratedToolCalls` rejects the emitted markup
1123
1120
  on a request whose rows fired, `usage.fill.parseFallback` increments and
@@ -1415,22 +1412,30 @@ decode. The machine still fails the quiet preflight, so these are diagnostic
1415
1412
  results. Both external-drive failures remain recorded separately. Evidence:
1416
1413
  `fill-append-http-internal-repeat.json` and `fill-append-http-internal-review.json`.
1417
1414
 
1418
- Quantized-KV composition remains disabled. A direct R6 append screen with
1419
- TurboQuant k8v3 preserves hidden rows, logits, live cache state and four
1420
- continuations at prefixes 128 and 1021, but exposes retained temporary state
1421
- views between chunks. `appendFillHidden` now uses the existing
1422
- `leaseCacheStates` ownership interface, as prefill does. Explicit release
1423
- removes the extra 21,528,576 and 131,153,920 active bytes in those two checks;
1424
- both ordinary and fused TurboQuant decoding then have identical post-arm
1425
- allocation and numerical results. This fixes the research composition's
1426
- view lifetime; the ordinary served path already excludes this combination.
1427
- Seven targeted ownership tests and all three typechecks pass. The affine
1428
- KV4 comparison fails both contexts, first changing recurrent state at layer
1429
- 4 after the first attention layer. Keep its failure and the composition
1430
- guard. Other quant/cache modes, longer contexts and actual serving
1431
- performance remain unqualified. Evidence:
1432
- `fill-append-quant-cache-review.json` and
1433
- `fill-append-state-ownership-native-test.log`.
1415
+ The original quantized-KV append screen passed TurboQuant K8V3 after fixing
1416
+ retained temporary state views through `leaseCacheStates`, but affine KV4
1417
+ changed recurrent state after the first full-attention layer. That failure
1418
+ is now resolved: multi-token affine attention selected different arithmetic
1419
+ from one-token decode, both in tiled and ordinary unfused forms. The model's
1420
+ committed-append path now computes each query against its own causal KV
1421
+ prefix using the one-token attention operation, while retaining shared
1422
+ projection work. No sampled decode or ordinary prefill arithmetic changes.
1423
+
1424
+ On M4 Pro, packed and RTN4 Qwen27B both preserve complete hidden/logit/cache
1425
+ bytes and four subsequent continuations for KV4/KV8 at prefixes 128 and
1426
+ 1021, including the attention boundary. The real KV4 generation loop also
1427
+ preserves emitted IDs, final state, subsequent logits and active allocation,
1428
+ with nonzero fill and zero verification. The append binding declares affine
1429
+ format support; HTTP preparation and placement leave that decision to the
1430
+ method. K8V3 TurboQuant now uses the same declaration and delayed-conversion
1431
+ boundary interface. Both Qwen artifacts pass real-generation state/continuation
1432
+ and six-pair HTTP comparisons; quantized echo verification remains separate.
1433
+ Full numerical and HTTP measurements live in benchmarks.md. Tests:
1434
+ `tests/unit/quantized-append-attention.test.ts`,
1435
+ `tests/parity/qwen-affine-append.test.ts`, and
1436
+ `MLX_BUN_TEST_FILL_KV_BITS=4` with the existing strict-fill parity test.
1437
+ Earlier failure/lease evidence remains `fill-append-quant-cache-review.json`
1438
+ and `fill-append-state-ownership-native-test.log`.
1434
1439
 
1435
1440
  The literal/reasoning checks deliberately decline ambiguous text, including some
1436
1441
  otherwise valid prose with unmatched quote characters. This is bounded
@@ -1600,6 +1605,140 @@ grammar/KV/batch/logprobs/seed exclusions individually after their own gates.
1600
1605
  The full experimental matrix and completion rule are in
1601
1606
  [decode-speed-program.md](decode-speed-program.md#7-qwen38-27b-research-program).
1602
1607
 
1608
+ #### Shared strict-fill method
1609
+
1610
+ `backends/mlx/fill-group.ts` composes `MlxPrefillCohort`, `MlxStateRows`, the
1611
+ model graph, the sampler and the common prompt-cache interface. The scheduler
1612
+ continues to select work through `MlxGroupedMethod`. It does not compile tool
1613
+ schemas or choose filled tokens. A request owns its `FillSession`, partial
1614
+ proposal and sampler history.
1615
+
1616
+ Ordinary samples retain build-next-before-read overlap. The method commits a
1617
+ token to sampler history only when that token becomes model input. An in-flight
1618
+ sample replaced by a strict continuation never enters history. Known positions
1619
+ skip sampling; if every next position is known, the method also omits the
1620
+ vocabulary projection. The model binding supplies the maximum committed chunk
1621
+ size for the current row geometry. When every row has a known continuation and
1622
+ the model permits wider chunks, the method uses the same append operation as
1623
+ explicit serial execution. Qualified Qwen B1 uses its specialized multi-position
1624
+ operation; wider rows retain one-position arithmetic and pipeline overlap.
1625
+ Performance parity remains a measured acceptance gate.
1626
+
1627
+ Before a row joins, the method flushes pending outputs. Retirement and
1628
+ cancellation settle exactly the emitted prefix of a proposal once. Cache
1629
+ publication uses the tokens actually consumed by the model, which can lead
1630
+ visible output by one pipelined position or the remaining committed span.
1631
+ The cache owns RAM retention and
1632
+ queued SSD persistence. No storage work is awaited by the method.
1633
+
1634
+ The row-aware `appendHiddenRows` interface separately accepts borrowed `[B,L]`
1635
+ inputs and asks the model for its maximum chunk length at the actual B. The
1636
+ qualified Qwen binding retains its specialized B1 append and declares one
1637
+ position for wider rows. Full hidden outputs, live cache bytes and subsequent
1638
+ logits match ordinary same-B forwards after retirement on M1 MiniCPM/Qwen0.8B
1639
+ and M4 packed Qwen27B with bf16, KV4 and k8v3.
1640
+
1641
+ `tests/unit/fill-group.test.ts` exercises actual shared execution, including
1642
+ mixed sampled/filled rows, head omission, stream stops, length limits,
1643
+ consumer failures, cancellation and late joins. `tests/parity/shared-fill.test.ts`
1644
+ compares ordinary, empty-fill and saved-continuation arms at matched B1/B2/B4
1645
+ with seeded sampling, presence/repetition penalties and bf16/KV4/k8v3. All
1646
+ nine cases pass on M1 MiniCPM, Qwen0.8B and Gemma4-e4b and M4 packed Qwen27B.
1647
+ Gemma's sliding layers remain bf16 in the TurboQuant arm.
1648
+
1649
+ The M4 delayed-conversion gate caught two composition defects. Shared row
1650
+ layouts did not expose their pending precision boundary to committed append;
1651
+ the affine attention view also bypassed the model's single-position reduction
1652
+ policy. The cache now publishes `maxAppendTokens()` from logical row offsets,
1653
+ including padding and retirement, and the attention view carries the qualified
1654
+ committed-position policy to its codec. Both delayed KV4 and k8v3 seeded cases
1655
+ pass after splitting the five-token span into two and three positions at the
1656
+ boundary. Separate B1 full-hidden/cache-byte/continuation comparisons pass for
1657
+ bf16, KV4, k8v3 and both delayed formats. Earlier failed logs are retained.
1658
+
1659
+ The first unequal-prompt comparison did not fix the admission geometry and
1660
+ produced different later tokens; preserve it as an unmatched experiment.
1661
+ A later fixture reused a short suffix which recurred during stochastic
1662
+ sampling and wrongly supplied the same continuation twice. The numerical
1663
+ gate now supplies a saved span at one exact position. Parser/source validity
1664
+ has its own tests; numerical replay does not prove arbitrary suffix asserts.
1665
+ The failed logs and corrected runs remain in `reports/prefill-observation/`.
1666
+ Serving binding tests also cover seeded placement and `usage.fill` propagation.
1667
+ The six-arm M4 HTTP comparison preserves all 108 responses and all paired token/cache counts, with six durable SSD restarts. Sequential shared strict-fill performance matches serial within 0.13%; the fill-off comparison and concurrent latency tradeoffs are recorded in benchmarks.md. Model-declared codec eligibility is resolved once at binding: unsupported multi-position formats still use shared one-position fill. A separate k4v3 seeded gate proves that execution with no specialized append.
1668
+
1669
+ #### Shared echo verification
1670
+
1671
+ The fill method accepts both asserted and verified proposals. A pending
1672
+ sample checks the first echo token without replacing the sampler's choice.
1673
+ When a live row has a verified echo continuation, the method supplies
1674
+ its proposal to `advanceSpeculativeOutputs`, the same grouped target
1675
+ verification and output-aligned rollback operation used by speculative
1676
+ providers. Ordinary rows join with empty proposals and retain only their
1677
+ consumed inputs. Asserted spans keep their append policy. Proposals discovered
1678
+ while publishing pending output stay within the scheduler's declared token
1679
+ work; any remainder belongs to the request's next iteration.
1680
+ No scheduler or storage branch chooses echo tokens.
1681
+
1682
+ Each request retains its own seed and processor history. The sampler adapter
1683
+ commits a token when it becomes model input; rejected proposals never enter
1684
+ that history. Eligible plain-greedy rows use the sampler's existing independent
1685
+ verification kernel. Output delivery determines how much state survives a consumer
1686
+ stop, then the common cache receives the corresponding tokens and row state.
1687
+ The cache retains RAM donors and owns SSD persistence. Checkpoint telemetry
1688
+ includes the shared cohort's begin and resolve time for each participating
1689
+ request. Fill remains opt-in. Shared paged execution is unsupported. Qwen MTP can
1690
+ consume verified echo continuations through the provider operation below.
1691
+
1692
+ `shared-echo.test.ts` audits the real sampler against an independent sampler
1693
+ on the exact same score tensor and selected-token history, across B1/B2/B4,
1694
+ bf16, KV4, k8v3 and delayed quantization. It covers accepted, first-rejected,
1695
+ partially rejected, mixed and staggered proposals plus a consumer stopping inside
1696
+ the span. Published cache keys must match emitted history and every layer offset.
1697
+ B2 retained state also survives SSD store/reopen with identical state and two
1698
+ subsequent logit vectors against its RAM clone. These checks pass on M1
1699
+ Qwen0.8B/Gemma-e4b and M4 packed Qwen27B. HTTP tests cover actual copied tool arguments,
1700
+ seeded concurrent requests, follow-up reuse and durable SSD restart.
1701
+
1702
+ An early experiment compared multi-position verification against one-position
1703
+ ordinary decoding and found changed sampled tokens. That comparison changes
1704
+ numerical geometry and is preserved as an unmatched experiment, not an exact
1705
+ oracle. The original strict-fill exact replay gate remains unchanged. Echo
1706
+ acceptance preserves the sampler's decision for the verified logits; it does
1707
+ not promise identical text to a different forward shape. Request timing and
1708
+ paired-response results are recorded in benchmarks.md.
1709
+
1710
+ #### Echo with a mounted MTP provider
1711
+
1712
+ `DraftRowGroup.consume` consumes externally verified target tokens and hidden
1713
+ context, retaining the specified prefix length for each row. Provider
1714
+ capabilities advertise this operation before execution. The Qwen MTP provider
1715
+ uses its existing true-hidden prefill graph and per-row rollback; it neither
1716
+ samples draft tokens nor projects its vocabulary during this operation.
1717
+
1718
+ The speculative method first compares ordinary MTP output with a pending copy
1719
+ proposal. A first-token mismatch uses no additional target forward. Once output
1720
+ establishes a matching prefix, the method verifies the remaining copied span.
1721
+ Other rows supply empty proposals. The existing verifier and
1722
+ sampler select output, then output delivery determines how many inputs survive.
1723
+ The provider consumes that same prefix before ordinary MTP resumes. Target and
1724
+ companion state are published together through the unchanged cache interface.
1725
+ No scheduling or storage implementation selects between echo and MTP.
1726
+
1727
+ `FillSession.observe` records sampled output independently of proposal timing.
1728
+ The method asks for verified proposals at committed output boundaries. Under
1729
+ MTP, asserted template spans remain ordinary sampled output; this combination
1730
+ adds echo without changing the strict append algorithm. Grammar, probability
1731
+ metadata, media, paging and providers without external-token consumption remain
1732
+ outside this combination's serving coverage.
1733
+
1734
+ `usage.fill` counts verified echo proposals. Learned-provider drafted/accepted
1735
+ counts, rounds and acceptance histograms exclude echo. Target calls and tokens
1736
+ per forward cover both kinds of round. A request can legitimately use no
1737
+ learned drafts if echo supplies every continuation. Both-machine companion
1738
+ oracle checks cover external prefixes and subsequent full decoder output;
1739
+ shared tests cover sampling, mixed rows, rejection, stop and paired SSD state.
1740
+
1741
+
1603
1742
  ### 7.5 Logical jump-ahead prefill
1604
1743
 
1605
1744
  Proposal by Josh Rossi, recorded 2026-09-08. Research proposal, not an
@@ -357,7 +357,7 @@ Gemma-4-e4b's D512 deferred consumer also passes: 20 forward/state cases, four
357
357
  generations and 1,220 matching cache reads, one specialization and 1,057,864
358
358
  final active bytes per arm. Evidence: tq-kv-gemma-e4b-full{,-review}.json.
359
359
 
360
- The joint decoder is now integrated as an experimental opt-in. The environment
360
+ The joint decoder was initially integrated as an experimental opt-in. The environment
361
361
  setting and supported inputs are documented in server-config.md. A shared
362
362
  `src/mlx/turboquant-kv-decode.ts` owns only the packed Metal operation; the existing
363
363
  codec owns inverse rotation and the cache captures operation selection once.
@@ -517,8 +517,8 @@ longer prompt. Sampled RSS establishes no reduction. The server-exit observer
517
517
  still sees resident model arrays, so its active capacity is not a disposal-to-
518
518
  zero test. Native operation and full-model ownership gates remain separate.
519
519
  These are M4 Pro 24 GB diagnostics with k8v3, greedy seed 42 and 128 generated
520
- tokens. TurboQuant KV requires serial placement in the existing execution
521
- planner. Evidence: mlx-upgrade-0.32.2/deferred-kv-http{,-review}.json. This closes
520
+ tokens. Those measurements used serial placement; shared integration is covered below.
521
+ Evidence: mlx-upgrade-0.32.2/deferred-kv-http{,-review}.json. This closes
522
522
  the deferred-model serving comparison; broader pressure and quiet gates remain.
523
523
 
524
524
  Direct packed-key attention is closed as an additional speed candidate. A
@@ -612,9 +612,9 @@ snapshots with no missing, pending, dropped or failed writes. The constrained
612
612
  arms cause six eviction spills; the async observer confirms 3,264 submissions.
613
613
  These sequential shared-server pressure checks cause substantial swapping;
614
614
  B4 correctness is a separate native gate, and no speed or memory-reduction
615
- claim follows. M4 pressure and strict paired performance acceptance remain open.
616
- The shared integration is now adopted in the unreleased working tree; the
617
- released v0.3.0 binary retains its earlier placement limits.
615
+ claim follows. The subsequent M4 combined pressure gate also passes with both asynchronous and blocking submissions exercised; full usage, responses and final persistence match. Current measurements and provenance live in benchmarks.md. This closes the named pressure gate; performance and default selection remain separate.
616
+ Shared TurboQuant integration ships in v0.4.0; v0.3.0 retained the earlier
617
+ placement limits.
618
618
  Evidence: `reports/qwen38-closeout/composition-baseline/turboquant-composition-manifest.json`.
619
619
  Integration evidence: `reports/qwen38-closeout/composition-baseline/turboquant-serving/`.
620
620
  Broader family checks pass MiniCPM seeded/logprob serving but reproduce a
@@ -626,6 +626,19 @@ Gemma seeded sampling, affine KV4 controls and Qwen MTP3 B4 serving.
626
626
  MiniCPM prefix checks allow the existing policy to supersede trimmable donors
627
627
  while proving byte identity and continuation through retirement.
628
628
 
629
+ ### Fused codec default selection
630
+
631
+ The unreleased decoder selects packed K/V fusion by default when a caller
632
+ chooses TurboQuant. `turboQuantFusedDecode` resolves the runtime policy once;
633
+ ordinary storage, shared rows and delayed conversion capture the same value.
634
+ Copies and restored rows retain the codec selection through their existing
635
+ interfaces. `MLX_BUN_TURBOQUANT_FUSED_DECODE=0` selects the original operations.
636
+ The numerical kernels and eligibility rules are unchanged from the accepted
637
+ opt-in. TurboQuant quantization itself remains an explicit cache-format choice.
638
+ The current shared-serving comparison and combined pressure measurements are
639
+ recorded in benchmarks.md; the earlier six-pair timing and native/state gates
640
+ above remain the evidence for the fused implementation.
641
+
629
642
  ## KV-leg limits and non-goals (recorded so they don't creep)
630
643
 
631
644
  - Full-attention layers only; rotating/sliding-window layers stay bf16 (warn
@@ -950,7 +963,7 @@ since e·Hinv[k,k] = w−q) and `err[..., k:k+1]` indexes a group-local buffer
950
963
  with the GLOBAL k (mlx out-of-range slice assignment silently no-ops →
951
964
  cross-group propagation lost after block 0). Fixing only err
952
965
  DOUBLE-compensates [j, k+j) and REGRESSES below RTN (measured: 7.22/7.50);
953
- fixing both = paper GPTQ. Worth an upstream report. Fork:
966
+ fixing both = paper GPTQ. [mlx-lm #1878](https://github.com/ml-explore/mlx-lm/issues/1878) contains the CPU-only reproduction, observed results against mlx-lm 0.31.3 and upstream `e5962529`, and proposed two-line correction; [mlx-lm PR #1880](https://github.com/ml-explore/mlx-lm/pull/1880) carries the fix plus `tests/test_gptq.py` (column-by-column reference, four groups fail on `main`, single-group control passes on both). Fork:
954
967
  `scripts/turboquant/tq-gptq.py` (also restricts GPTQ+fallback to language
955
968
  modules — vision H is a zero scalar and stays bf16).
956
969
 
@@ -215,6 +215,17 @@ fusedSdpaRuntimeOk(q, mask)` in `src/model/generated/gemma4-*.ts`) that are
215
215
  per-generation-decidable and should be hoisted out of the token path; compiled
216
216
  decode already achieves the debranched line dynamically (trace once, replay).
217
217
 
218
+ The shared greedy operation uses native logsumexp followed by tiled normalized
219
+ score/index reductions in `src/mlx/normalized-argmax.ts`. It preserves rounding
220
+ and lowest-ID ties without materializing the normalized vocabulary array.
221
+ The step sampler applies processors and grammar first, and selects this operation
222
+ only for built-in greedy requests that do not require metadata. Independent
223
+ verification calls the same operation. Fixed-shape compilation caches each
224
+ geometry; enclosing shapeless graphs retain native operations. No scheduler,
225
+ model-family branch or separate sampling setting selects this optimization.
226
+ Actual-model and operation comparisons, plus both-machine serving measurements,
227
+ are recorded in benchmarks.md under fused normalized greedy selection.
228
+
218
229
  ### Layer 0 — the SSD spill substrate
219
230
 
220
231
  It is almost always faster to cache to SSD and mmap it back than to
@@ -648,14 +659,12 @@ implementations throughout migration. New numerical work has separate paired
648
659
  validation, so structural changes cannot conceal a quality or performance
649
660
  tradeoff. §12.11 defines the shared frontier scorecard.
650
661
 
651
- Future design question (2026-09-05): consider a monorepo with the inference
652
- engine kept together as one package, and application modules such as memory
653
- and the web UI in separate packages. CLI/TUI and training boundaries can be
654
- considered in that discussion. This is an unplanned idea, not part of the
655
- current optimization campaign. Before choosing boundaries, map dependencies,
656
- native assets, builds, tests, and releases; preserve in-process execution and
657
- the single-binary distribution. Package boundaries should follow demonstrated
658
- ownership and dependency needs without adding abstractions to the decode path.
662
+ Package organization is now a planned decision in the
663
+ [public-readiness program](../../PLAN.md#public-readiness), separate from
664
+ the optimization campaign. §12.15 records the initial boundary audit and
665
+ remaining evidence needed before choosing a workspace layout. Preserve
666
+ in-process execution and the single-binary distribution; package boundaries
667
+ must follow ownership and dependency needs without adding decode overhead.
659
668
 
660
669
  ### 12.2 Dependency structure
661
670
 
@@ -1826,7 +1835,7 @@ flowchart TB
1826
1835
  output -->|response events| server
1827
1836
  method <-->|borrow, update, snapshot, rollback| state
1828
1837
  session <-->|restore / publish prefill checkpoint| cache
1829
- method -.->|publish generated checkpoint: still open| cache
1838
+ method -->|publish generated checkpoint| cache
1830
1839
  cache <-->|fast reuse| ram
1831
1840
  ram <-->|spill and restore when needed| persistence
1832
1841
  ```
@@ -1856,12 +1865,12 @@ SSD spill; an explicit durability flush can wait for persistence.
1856
1865
  | Chat template | `ChatTemplate.render` | Expose the renderer as its own narrow port instead of requiring a concrete serving context. Record rendered-stable boundaries for generated checkpoint alignment. |
1857
1866
  | Tokenizer | `LoadedTokenizer` | Reuse the same encode/decode contract across preparation, caching and output. Keep incremental encoding inside this component. |
1858
1867
  | Session / scheduling | `InferenceEngine`, `GenerationSession`, `ExecutionGroup`, `SchedulingClock` | Close all feature and performance gaps before deleting the remaining serial executor. |
1859
- | Inference method | `InferenceMethod`; shared MTP method in the isolated candidate | Complete every shared-method composition and acceptance gate. Draft depth belongs here, independently of queue policy. |
1868
+ | Inference method | `InferenceMethod`; shared ordinary and speculative methods | Complete every shared-method composition and acceptance gate. Draft depth belongs here, independently of queue policy. |
1860
1869
  | Numerical graph / kernels | `AutoregressiveGraph`, `GraphFactory`, backend bindings | Continue hardware-specific fusion and kernel optimization behind these contracts. |
1861
1870
  | Sampler | `SamplingSession` | Retain one set of sampling/history/logprob semantics for ordinary and speculative execution. |
1862
- | Active state / codec | `Cache`, `KvAttentionState` / `KvAttentionView`, row layouts, `SpeculativeTransaction`, checkpoint attachments | Appending and attending are separate operations. One captured view can serve multiple model layers while retaining pre-write positions and tensor ownership. Delayed rotating affine and broader model/layout composition remain open. |
1863
- | Reusable cache | `PrefixCache.take/put`, shared `PromptCache` | Generated-output checkpoints and next-request token alignment remain open. Prefill reuse is already implemented. |
1864
- | Persistence | `ColdTier`, `SpillSink`, `SsdCacheStore`, `SsdDurabilityCoordinator` | Complete combined M4 pressure/restart acceptance. RAM and SSD remain interchangeable retention tiers behind cache operations. |
1871
+ | Active state / codec | `Cache`, `KvAttentionState` / `KvAttentionView`, row layouts, `SpeculativeTransaction`, checkpoint attachments | Appending and attending are separate operations. One captured view can serve multiple model layers while retaining pre-write positions and tensor ownership. Delayed affine/TurboQuant and rotating layouts are integrated; qualify additional model/layout combinations separately. |
1872
+ | Reusable cache | `PrefixCache.take/put`, shared `PromptCache` | Prefill and processed generated output populate the same immutable RAM/SSD cache. Session lookup and rendered-token alignment are integrated. |
1873
+ | Persistence | `ColdTier`, `SpillSink`, `SsdCacheStore`, `SsdDurabilityCoordinator` | Queued persistence, native/restart checks and full Kanban durability acceptance are complete. RAM/SSD retention remains behind cache operations. |
1865
1874
 
1866
1875
  An interface boundary does not require copying tensors, downloading logits,
1867
1876
  or adding an RPC or synchronization per token. Device handles can stay lazy;
@@ -1878,3 +1887,101 @@ Contract sources: [generation](../../src/contracts/generation.ts),
1878
1887
  [cache tiers](../../src/prompt-cache.ts).
1879
1888
  Performance evidence and default selection live in
1880
1889
  [benchmarks.md](../reference/benchmarks.md); open acceptance remains in Phase 6/18.
1890
+
1891
+ #### Kernel configuration ownership
1892
+
1893
+ Shared and serial bindings execute within one immutable `RuntimeConfig`.
1894
+ Numerical helpers read that scope; they do not read process environment in
1895
+ forward loops. The serial speculative trace switch is captured once per run.
1896
+ Trellis mode resolves through the same configuration port at weight creation.
1897
+
1898
+ TurboQuant caches capture their codec's fused-decode choice at construction.
1899
+ RAM clones, full-prefill row restoration, batch layout factories, extraction
1900
+ and delayed conversion preserve that choice. KV maintenance binds its runtime
1901
+ before conversion, including conversion performed after a host setting changes.
1902
+ SSD formats contain numerical state, not a frozen process configuration; their
1903
+ receiving cache factory selects the destination binding's policy.
1904
+
1905
+ The configuration tests change host settings around scoped construction,
1906
+ copy/extraction and delayed conversion. Existing codec/donor tests now select
1907
+ both fused settings through `configureRuntime`, so they exercise the same
1908
+ configuration contract as serving. Paged request policies also bind the numerical
1909
+ namespace and construction policy before deferred lookup or allocation, including
1910
+ when a gateway outlives later host configuration changes. The serving reference
1911
+ maps flags to their owning interfaces and records supported combinations. The
1912
+ legacy internal `flagOn` wrapper is removed; CLI controls remain compatible.
1913
+ The new paged-policy tests first reproduce both deferred-setting failures, then
1914
+ pass with the captured policy. Paged operation/layout checks pass on both Macs;
1915
+ the full local model-free suite and all typechecks pass.
1916
+
1917
+ ### 12.15 Package boundaries before community outreach
1918
+
1919
+ Initial audit, 2026-09-11. The public-readiness program owns the packaging
1920
+ work; the existing interface and optimization milestones retain their scope.
1921
+ The three published entry points need different treatment:
1922
+
1923
+ | Entry or layer | Verified dependency boundary | Packaging consequence |
1924
+ |---|---|---|
1925
+ | `mlx-bun/client`, `src/client.ts` | Imports only completion/host contracts; uses standard Request, Response, fetch and cancellation APIs | A candidate for independent client installation. The current npm package still has Darwin/arm64 metadata and application dependencies; a portable source file alone does not change that install contract. |
1926
+ | `src/contracts/`, `src/engine/`, `src/inference/` | Separate TypeScript project excludes Bun and DOM types; the AST boundary test limits imports by layer | Keep these interfaces and policies together inside the engine. They do not each need a published package. |
1927
+ | `mlx-bun/engine`, `src/library.ts` | CPU-safe entry exports engine/client APIs, but `initializeMlx()` dynamically imports the broad root API; `openIsolatedHost()` imports serving isolation and locates the CLI | Preserve this compatibility entry. Separate native engine initialization from application/worker assembly before treating it as a standalone engine package. |
1928
+ | `mlx-bun`, `src/index.ts` | Re-exports concrete models, generation, downloads, registry, fit and server construction | Already a published compatibility API. A workspace move needs forwarding exports, not a silent reduction of available functionality. |
1929
+ | Browser application | Own TypeScript project; boundary test allows web code and contracts | A candidate private application workspace. Its assets still participate in the CLI/native bundle. |
1930
+ | Website | Already has its own package manifest and build; generates reference pages from canonical docs | Keep one source for reference facts. A root workspace declaration alone would not improve this ownership. |
1931
+
1932
+ The source audit followed static imports, re-exports, type imports and literal
1933
+ `import()`/`require()` references using TypeScript module resolution. The
1934
+ client closure contained four source files and no external module imports.
1935
+ The high-level engine entry reached the broad root API, including Pi and web
1936
+ assets. This is a dependency inventory, not a claim that importing the
1937
+ CPU-safe entry eagerly loads those modules. Non-code assets and executable
1938
+ paths also need a packaging check; import analysis cannot establish that they
1939
+ ship correctly.
1940
+
1941
+ Recommended direction for the remaining audit: one engine package containing
1942
+ models, native bindings, cache codecs, inference methods and their interfaces;
1943
+ application assembly outside it; a small client package if independent
1944
+ installation is useful. Keep specialized kernels and tensor ownership within
1945
+ that engine. Memory, Pi and training require their own dependency and asset
1946
+ review before deciding whether they become private workspaces. A general MLX
1947
+ array binding is a separate API commitment and is not implied by this split.
1948
+
1949
+ Before choosing and implementing the layout, map the engine-to-application
1950
+ edges through server construction, native bootstrap, worker commands and
1951
+ bundled assets. Verify the package tarball and a consumer installed outside
1952
+ the repository. Public import compatibility and the single-binary release are
1953
+ acceptance requirements. The initial audit does not yet close the package
1954
+ organization milestone.
1955
+
1956
+ The initial `bun pm pack --dry-run --ignore-scripts` also confirms that the
1957
+ package includes the whole `docs/` tree, including archived investigations
1958
+ and active plans. Review that allowlist during packaging work; these are not
1959
+ runtime dependencies. This dry run inventories the candidate but does not
1960
+ replace installation and asset checks against an actual tarball.
1961
+
1962
+
1963
+ ### 12.15 Prefill workspace policy
1964
+
1965
+ `PrefillPolicy` selects a request's chunk size independently of scheduling,
1966
+ cache placement and sampling. The MLX backend captures model geometry and
1967
+ explicit configuration when it binds the policy. Ordinary generation,
1968
+ shared rows and speculative preparation consume the selected size through
1969
+ their existing prefill interfaces. A caller's explicit request value wins.
1970
+ The automatic recurrent-attention policy bounds the temporary materialized
1971
+ SDPA score workspace; it does not inspect live free memory or refuse work.
1972
+ Default values and precedence live in [server configuration](../reference/server-config.md).
1973
+
1974
+ ### 12.16 Committed append cache formats
1975
+
1976
+ `MlxTokenAppend` declares supported affine precisions and TurboQuant K/V
1977
+ formats. Qualified Qwen27B bindings expose KV4/KV8 and K8V3.
1978
+ Request preparation supplies template-derived candidates; placement selects
1979
+ an eligible method without inspecting numerical cache formats. The ordinary
1980
+ method consumes the binding's declaration once and uses its committed-append
1981
+ operation. Qwen shares projection work over known tokens while retaining each
1982
+ query's one-token affine attention calculation and causal KV extent.
1983
+ `KvMaintenance.maxAppendTokens` bounds a committed chunk at a pending
1984
+ precision transition; the method runs maintenance before continuing.
1985
+ Verification remains a separate method capability: enabling committed
1986
+ quantized appends does not enable quantized echo verification. No default fill setting or
1987
+ shared-group support is inferred from that declaration.
@@ -65,12 +65,11 @@ disclosure: appliance defaults at the front, sharp instruments underneath.
65
65
 
66
66
  ## The three modes (the organizing design law)
67
67
 
68
- mlx-bun has not published anything: the entire CLI, command, and flag
69
- surface is still ours to invent, and we are not married to any flag
70
- name. Where a de-facto standard name exists (mlx-lm's), we adopt it
71
- rather than reinvent. The surface is designed once, to serve three
72
- audiences at three depths — progressive disclosure over ONE set of
73
- verbs and one flag vocabulary, not three separate CLIs:
68
+ mlx-bun is published. Existing commands, flags, and package exports are
69
+ compatibility commitments; changes need documented migration behavior.
70
+ Where an mlx-lm flag has matching semantics, prefer its established name.
71
+ The CLI serves three audiences through one set of verbs, with more explicit
72
+ configuration available as users need it:
74
73
 
75
74
  1. **Automatic mode** — first-time local-AI users. `mlx-bun` (and bare
76
75
  verbs) with zero flags. Smart, sane defaults from the device-profile