mlx-bun 0.3.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 (150) hide show
  1. package/docs/README.md +4 -1
  2. package/docs/archive/investigations/openjarvis-fit.md +198 -0
  3. package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
  4. package/docs/design/batching.md +1321 -49
  5. package/docs/design/decode-speed-program.md +331 -1163
  6. package/docs/design/generic-model-support.md +79 -3
  7. package/docs/design/kv-cache.md +198 -54
  8. package/docs/design/speculative-decoding.md +387 -24
  9. package/docs/design/turboquant.md +123 -13
  10. package/docs/design/unified-engine-frontier-plan.md +144 -142
  11. package/docs/planning/PRODUCT_ROADMAP.md +16 -0
  12. package/docs/planning/release-notes-v0.4.0.md +45 -0
  13. package/docs/reference/benchmarks.md +2457 -6
  14. package/docs/reference/cli.md +41 -2
  15. package/docs/reference/distribution.md +16 -9
  16. package/docs/reference/environment.md +55 -5
  17. package/docs/reference/models.md +13 -4
  18. package/docs/reference/server-api.md +79 -25
  19. package/docs/reference/server-config.md +178 -84
  20. package/docs/reference/troubleshooting.md +13 -21
  21. package/package.json +1 -1
  22. package/src/backends/mlx/assistant-target.ts +46 -0
  23. package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
  24. package/src/backends/mlx/batch-group.ts +368 -224
  25. package/src/backends/mlx/cache-attachment.ts +67 -0
  26. package/src/backends/mlx/cache-layout.ts +31 -0
  27. package/src/backends/mlx/checkpoint-state.ts +53 -0
  28. package/src/backends/mlx/continuation-persistence.ts +106 -0
  29. package/src/backends/mlx/continuation-request.ts +43 -0
  30. package/src/backends/mlx/continuation.ts +77 -0
  31. package/src/backends/mlx/draft-target.ts +7 -22
  32. package/src/backends/mlx/full-kv-row-append.ts +32 -0
  33. package/src/backends/mlx/full-kv-row-donor.ts +54 -0
  34. package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
  35. package/src/backends/mlx/gateway-binding.ts +77 -18
  36. package/src/backends/mlx/kv-codec.ts +9 -0
  37. package/src/backends/mlx/kv-maintenance.ts +133 -0
  38. package/src/backends/mlx/kv-tensor-rows.ts +212 -0
  39. package/src/backends/mlx/model-serving.ts +1 -1
  40. package/src/backends/mlx/prefill-cohort.ts +89 -0
  41. package/src/backends/mlx/prefill-rows.ts +200 -0
  42. package/src/backends/mlx/prefill.ts +1 -1
  43. package/src/backends/mlx/projected-context-rows.ts +72 -0
  44. package/src/backends/mlx/request-state-policy.ts +41 -0
  45. package/src/backends/mlx/rollback.ts +41 -3
  46. package/src/backends/mlx/row-sampling.ts +49 -0
  47. package/src/backends/mlx/serial-executor.ts +35 -66
  48. package/src/backends/mlx/speculative-group.ts +359 -0
  49. package/src/backends/mlx/speculative-round.ts +161 -0
  50. package/src/backends/mlx/state-rows.ts +104 -0
  51. package/src/backends/mlx/state-views.ts +21 -1
  52. package/src/backends/mlx/target-layout-capability.ts +35 -0
  53. package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
  54. package/src/cli.ts +11 -36
  55. package/src/contracts/execution.ts +11 -0
  56. package/src/contracts/prefix-cache.ts +23 -0
  57. package/src/contracts/resources.ts +7 -0
  58. package/src/contracts/sampling.ts +23 -0
  59. package/src/contracts/scheduling.ts +18 -0
  60. package/src/engine/execution-plan.ts +18 -16
  61. package/src/engine/resources.ts +12 -1
  62. package/src/engine/scheduler.ts +10 -5
  63. package/src/fit.ts +29 -15
  64. package/src/generate.ts +77 -173
  65. package/src/inference/draft-acceptance.ts +41 -0
  66. package/src/inference/draft-output.ts +49 -0
  67. package/src/inference/rollback.ts +2 -2
  68. package/src/kv-scheme.ts +70 -12
  69. package/src/kv-store.ts +70 -16
  70. package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
  71. package/src/lab/paged-kv/paged-kv.ts +25 -11
  72. package/src/mlx/array.ts +2 -1
  73. package/src/model/artifact-identity.ts +73 -0
  74. package/src/model/batched-kv.ts +235 -0
  75. package/src/model/batched-mask.ts +12 -4
  76. package/src/model/batched-quant.ts +8 -2
  77. package/src/model/batched-quantized-kv.ts +144 -0
  78. package/src/model/batched-rotating-quant.ts +76 -15
  79. package/src/model/batched-rotating-state.ts +76 -0
  80. package/src/model/batched-rotating.ts +64 -22
  81. package/src/model/batched-row-storage.ts +52 -0
  82. package/src/model/batched-ssm.ts +52 -0
  83. package/src/model/batched-turboquant-kv.ts +93 -0
  84. package/src/model/compiled-decode.ts +7 -1
  85. package/src/model/decoded-kv-donor.ts +12 -0
  86. package/src/model/delayed-quantized-kv.ts +72 -0
  87. package/src/model/delayed-rotating-quantized-kv.ts +93 -0
  88. package/src/model/delayed-turboquant-kv.ts +55 -0
  89. package/src/model/full-prefill-padding.ts +56 -0
  90. package/src/model/full-prefill-row.ts +105 -0
  91. package/src/model/gemma4-base.ts +162 -80
  92. package/src/model/gemma4.ts +34 -26
  93. package/src/model/generated/gemma4-12b.ts +4 -1
  94. package/src/model/generated/gemma4-26b.ts +4 -1
  95. package/src/model/generated/gemma4-e4b.ts +4 -1
  96. package/src/model/glm52-cache.ts +80 -4
  97. package/src/model/glm52-mla.ts +12 -6
  98. package/src/model/glm52.ts +19 -40
  99. package/src/model/kv-attention-view.ts +67 -0
  100. package/src/model/minicpm5.ts +11 -7
  101. package/src/model/qwen3-delta-state.ts +74 -0
  102. package/src/model/qwen3-delta.ts +59 -36
  103. package/src/model/qwen3_5.ts +82 -42
  104. package/src/model/rotating-kv-donor.ts +35 -0
  105. package/src/model/rotating-kv-layout.ts +262 -0
  106. package/src/model/rotating-row-transaction.ts +35 -0
  107. package/src/model/speculative-rotating-kv.ts +101 -0
  108. package/src/model/ssm-prefill-padding.ts +39 -0
  109. package/src/model/trellis-linear.ts +2 -2
  110. package/src/model/turboquant-codec.ts +83 -0
  111. package/src/model/universal/dense.ts +14 -13
  112. package/src/preflight.ts +31 -15
  113. package/src/prompt-cache.ts +42 -44
  114. package/src/sampler.ts +36 -25
  115. package/src/serve/chat-stage.ts +2 -2
  116. package/src/serve/generation-gateway.ts +39 -30
  117. package/src/serve/model-host.ts +3 -4
  118. package/src/serve/request-plan.ts +4 -3
  119. package/src/serve/request-prep.ts +2 -4
  120. package/src/serve/text-completion-stage.ts +2 -2
  121. package/src/server.ts +64 -108
  122. package/src/spec/assistant-rows.ts +92 -0
  123. package/src/spec/assistant-source.ts +28 -18
  124. package/src/spec/cache-identity.ts +22 -0
  125. package/src/spec/deepspec-rows.ts +29 -0
  126. package/src/spec/deepspec-source.ts +12 -10
  127. package/src/spec/dflash-source.ts +28 -4
  128. package/src/spec/drafter.ts +153 -142
  129. package/src/spec/dspark/deepspec-module.ts +95 -120
  130. package/src/spec/dspark/module-dflash.ts +126 -170
  131. package/src/spec/glm52-mtp-graph.ts +29 -0
  132. package/src/spec/glm52-mtp-rows.ts +132 -0
  133. package/src/spec/glm52-mtp-source.ts +53 -136
  134. package/src/spec/glm52-mtp-state.ts +33 -0
  135. package/src/spec/ngram-source.ts +92 -20
  136. package/src/spec/projected-draft-rows.ts +73 -0
  137. package/src/spec/qwen-mtp-module.ts +171 -0
  138. package/src/spec/qwen-mtp-rows.ts +219 -0
  139. package/src/spec/qwen-mtp-source.ts +81 -226
  140. package/src/spec/qwen-mtp-state.ts +30 -0
  141. package/src/spec/serve-loop.ts +70 -68
  142. package/src/spec/source.ts +80 -15
  143. package/src/spec/two-model-rows.ts +61 -0
  144. package/src/spec/two-model.ts +43 -101
  145. package/src/ssd-cache.ts +33 -21
  146. package/src/ssd-durability.ts +11 -7
  147. package/src/web/app.js +57 -57
  148. package/src/backends/mlx/memory-guard.ts +0 -40
  149. package/src/spec/prefix-state.ts +0 -45
  150. /package/docs/{planning → archive/planning}/release-notes-v0.3.0.md +0 -0
@@ -3,7 +3,7 @@ status: active
3
3
  axis: ON
4
4
  canonical-for: batching
5
5
  plan-anchor: "Phase 18 — Concurrent / batched serving (slots) + parallel load benchmark `[~]` (2026-06-13)"
6
- last-verified: 2026-08-23
6
+ last-verified: 2026-09-10
7
7
  ---
8
8
 
9
9
  # Batching — continuous scheduling for `--batch N`
@@ -19,6 +19,14 @@ docs/design/kv-cache.md. Status and dated progress live in PLAN.md (see the
19
19
  plan anchor above); this file describes the mechanism as it exists and
20
20
  what is still open.
21
21
 
22
+ Phase 6 now requires shared method/session execution at B=1 and B>1, full
23
+ batch feature parity, and configuration organized by owning interface. The
24
+ boundaries are defined in [engine architecture §12.5–12.7](unified-engine-frontier-plan.md#125-capability-negotiation-and-planning).
25
+ The separate serial mechanism described below is the current implementation;
26
+ retiring its duplicate lifecycle is open work. Backend specializations may
27
+ remain when they improve measured performance. R17 owns output checkpoint
28
+ publication to the shared RAM/SSD cache.
29
+
22
30
  User-facing mirror: docs/reference/server-config.md ("Execution modes",
23
31
  compatibility matrix, known limitations) and docs/reference/cli.md.
24
32
 
@@ -84,7 +92,9 @@ and the engine runs its B=1 fast path (§4.4).
84
92
  - **Never downgrade a composition to make it batchable.** Placement is a
85
93
  support check only: it does not strip MTP/drafting, KV schemes,
86
94
  TurboQuant, grammar, adapters, or sampling. A composition the scheduler
87
- does not implement runs unchanged on the serial mechanism.
95
+ does not implement runs unchanged on the serial mechanism today. That
96
+ fallback preserves behavior during migration; it does not meet the new
97
+ batch feature-parity requirement.
88
98
  - **Drain, never starve.** A serial-lane waiter pauses admission; running
89
99
  rows finish; the lock hands over FIFO; admission resumes (mlx-lm
90
100
  `drain_batch`). One `AsyncMutex` is the single exclusion domain for
@@ -108,10 +118,11 @@ and the engine runs its B=1 fast path (§4.4).
108
118
  `setImmediate` hop costs microseconds; there is nothing to dodge.
109
119
  Reverted; the per-yield step is the measured optimum. Don't re-add
110
120
  without new evidence.
111
- - **Spec decode and batching are different mechanisms.** A mounted
112
- `--draft-model` routes every request serial (upstream
113
- `is_batchable = draft is None`); per-row speculation inside the batch
114
- is a research question, not a feature gap.
121
+ - **Spec decode and scheduling are separate concerns.** A mounted
122
+ `--draft-model` selects speculation only for compatible requests. Ordinary
123
+ fallback requests can batch when their actual features permit it. Concurrent
124
+ speculation is an explicit feature gap in the shared-execution program;
125
+ accepted lengths and target/draft state belong to the decode method.
115
126
 
116
127
  ## 3. Scheduling seam — `GenerationGateway`
117
128
 
@@ -126,12 +137,9 @@ continuous iff
126
137
  AND batch > 1
127
138
  AND #modelCachesBatchable() (cache-capability gate, below)
128
139
  AND !hasVision (offset-0 prefill + bidirectional mask)
129
- AND !hasAdapters (loraState is one global field)
130
- AND !wantsLogprobs (batch sampler does not capture logprob arrays)
131
- AND !userSeed (reproducibility ⇒ solo, matches mlx-lm)
132
- AND !(kvQuant AND !#kvBatchable()) (scheme must be a batchable per-layer config)
133
- AND !turboQuant (solo-only v1; belt on top of the capability braces)
134
- AND !hasDraft (spec is a B=1 mode)
140
+ AND adapter state supports compatible groups (when adapters are selected)
141
+ AND KV scheme supports the loaded cache layouts
142
+ AND selected method has a grouped implementation
135
143
  AND !(hasGrammar AND MLX_BUN_GRAMMAR_BATCH=0)
136
144
  ```
137
145
 
@@ -154,17 +162,17 @@ server.py's all-caches-have-`merge` check), memoized from a fresh
154
162
  merge/extract/filter and byte projection), or `SSMCache` (Qwen3.5's
155
163
  gated-DeltaNet state; `MLX_BUN_BATCH_SSM=0` removes it → serial).
156
164
 
157
- **KV-scheme gate** (`#kvBatchable`): the server's resolved `KvScheme`
158
- batches iff `kind === "affine-config"` and `scheme.batchable()` holds
159
- with every configured layer a plain `KVCache` or plain `RotatingKVCache`.
160
- Uniform `--kv-quant 4|8` (quantizedKvStart threshold semantics) and
161
- `turbo` route serial with a startup warning. The scheme is threaded to
162
- the scheduler only when this passes; the scheduler re-checks at
163
- construction and throws on an unsupported scheme (never bf16 service
164
- with quantized accounting).
165
-
166
- Startup refusals (server.ts): `--paged-kv` with `--batch N>1` throws
167
- (paged caches can't merge); GLM `--mtp on` (its default) mounts the MTP
165
+ **KV-scheme capability:** the resolved `KvScheme` qualifies per-layer affine,
166
+ start-zero uniform affine, and ordinary TurboQuant with immediate or delayed
167
+ conversion through actual cache and layout support. The MLX layout binding
168
+ creates encoded rows; scheduling does not encode or decode KV. Qualified methods
169
+ share delayed affine/TurboQuant conversion and per-layer affine policies through
170
+ these row interfaces; TurboQuant sliding layers remain bf16.
171
+ Unsupported compositions retain the existing serial route until their shared implementation and acceptance are complete.
172
+
173
+ Paged Gemma4 bf16 requests compose through `PagedKvRows`; the request state
174
+ policy supplies block storage and prompt-cache bypass without changing scheduling.
175
+ GLM `--mtp on` (its default) mounts the MTP
168
176
  drafter and therefore routes serial+spec — `--mtp off` exposes ordinary
169
177
  GLM batching.
170
178
 
@@ -308,13 +316,30 @@ dense model, the scheduler replays the serial engine's compiled step
308
316
  transactional: the scheduler permanently falls back to the graph path.
309
317
 
310
318
  **Vectorized homogeneous sampling.** When every live row is plain greedy
311
- (`plainGreedy` from the gateway: temperature 0, no processors, no
319
+ (`plainGreedy` from the gateway: temperature 0, no logprob capture, no processors, no
312
320
  grammar), one `toLogprobs` + `argmaxAxis` over `[B,V]` replaces B
313
321
  slice/sample/concat graphs — per-row identical math, tie behavior
314
322
  included. `MLX_BUN_BATCH_VEC_SAMPLE=0` forces the per-row closure path.
315
323
  Length-doomed rows get a placeholder slot (never emitted; one KV write
316
324
  on their own about-to-evict row).
317
325
 
326
+ **Sampling boundary.** `contracts/sampling.ts` defines `SamplingSession`:
327
+ borrow model logits, apply request-owned processing/selection, return the
328
+ chosen token and optional probability tensors. Device and host-token MLX
329
+ samplers implement the same generic contract. `createRowSampling` accepts a
330
+ sampler through that interface and binds its captures to output delivery.
331
+ The scheduler receives token tensors and a callback, with no probability
332
+ retention policy. Captures are evaluated with their token and retained by
333
+ request-local step until emission; cancellation and unconsumed lookahead
334
+ release them. Token-only requests retain the existing vectorized shortcut.
335
+ Explicit seeds no longer determine scheduler placement. The seed and local
336
+ sample index select the random key, independently of sibling requests.
337
+ Reproducibility is conditional on the same numerical execution composition,
338
+ not a promise of equal logits across different batch shapes. The preserved
339
+ `--batch 1` control supplies the earlier fixed-shape behavior.
340
+ Vectorized logprob capture and the broader sampling-kernel interface remain
341
+ optimization work; this change establishes no performance dominance.
342
+
318
343
  **Grammar rows** (`#stepGrammar`): read the previous register *before*
319
344
  building the graph (the matcher's `accept` needs JS numbers), `accept()`
320
345
  per live grammar row (fires async bitmask fills that overlap the graph
@@ -348,8 +373,12 @@ dropped (`dropOnly`, never put). A prefill error rejects only the joiner.
348
373
  **Eviction** (`#applyFilter(keep)`): `filterRows` on batched/owned
349
374
  caches; `filterKVRows` / `filterQuantRows` (B-axis `takeAxis`) on full
350
375
  layers; the pending register and `#pendingReal` flags are filtered in
351
- lockstep. Full-layer filter keeps stale left padding (no `min_left_pad`
352
- shift-left) — width waste, not correctness (open, §8).
376
+ lockstep. Full layers also remove the minimum left padding shared by all
377
+ survivors, matching `mlx-lm BatchKVCache.filter`. Buffer width and per-row
378
+ padding shrink together, preserving absolute RoPE positions. Quantized full
379
+ layers slice the token axis of packed/scales/biases together; rotating layers
380
+ retain their separate layout. Keeping those unused columns can change logits
381
+ through a different attention reduction shape.
353
382
 
354
383
  **Finish-time prompt-cache put.** A lone never-merged row hands its
355
384
  adopted serial-class caches back zero-copy, keyed by `promptIds + fed`
@@ -444,7 +473,7 @@ consistency check only, never the gate.
444
473
  | rotating merge/decode/mask/filter incl. ring wrap vs mlx-lm; generic row-storage state | `tests/batched-rotating.test.ts`, `batched-rotating-state.test.ts` | fast, oracle |
445
474
  | static B=2 + dynamic join/leave + extend-join vs mlx-lm (CPM, Gemma 12B/e4b/26B, Llama 3B Tier-0) | `tests/batched-decode-parity.test.ts` (`MLX_BUN_TEST_BATCH_DECODE=1`) | gated, oracle |
446
475
  | Qwen3.5 SSM batched vs mlx-lm B=2 | `tests/qwen35-batched-parity.test.ts` | gated, oracle |
447
- | scheduler orchestration (admit/step/evict/join) | `tests/batch-scheduler.test.ts` | gated (teacher-forced KL + 12B golden) |
476
+ | scheduler orchestration (admit/step/evict/join) | `tests/batch-scheduler.test.ts` | gated, exact live same-B protocol oracle (CPM and Gemma 12B) |
448
477
  | per-row containment, drain, full-attention join routing | `tests/batch-containment.test.ts` | gated |
449
478
  | rotating-layer join mid-decode (2026-08-22 regression) | `tests/batch-rotating-join.test.ts` | gated |
450
479
  | KV-budget queueing + projection math | `tests/batch-kv-budget.test.ts`, `kv-budget-projection.test.ts` | gated / fast |
@@ -454,6 +483,28 @@ consistency check only, never the gate.
454
483
  | per-row extract == solo bytes | `tests/batched-extract.test.ts` | fast |
455
484
  | live server: engage, `/stats`, SSE fan-out, serial coexistence | `tests/batch-serving.test.ts` | gated smoke |
456
485
 
486
+ Closeout recheck (2026-09-08, Apple M1 Max 32 GB, Bun 1.4.0,
487
+ MLX 0.32.2): the old Gemma solo-KL bound failed even though all 24 captured
488
+ simultaneous-admission vectors matched the same-B oracle exactly. Replaying
489
+ the mid-stream join exposed a separate mismatch in two later vectors: the
490
+ native full cache retained padding that `BatchKVCache.filter` removes.
491
+ The scheduler now performs that removal. The live protocol gate passes all
492
+ 48 full-vector hashes on each of MiniCPM5 and Gemma 12B, including row
493
+ retirement and a join triggered after two emitted tokens. The oracle receives
494
+ inputs and row/step identities, never the native expected hashes. It uses
495
+ mlx-lm merge/extend/filter operations and ordinary full-attention KV caches
496
+ when the reference state has no padding, matching serving's scalar-position
497
+ policy. No tolerance was increased and no golden was regenerated.
498
+
499
+ Production oracle: `scripts/oracle/batch-scheduler-reference.py`. Initial
500
+ capture and comparison: `reports/qwen38-closeout/gemma-protocol/`.
501
+ Before/after gates: `gemma-protocol-gate.log`,
502
+ `gemma-protocol-filter-trim-gate.log`, `batch-protocol-final-gate.log`.
503
+ The original unchanged-HEAD failure remains in
504
+ `memory-baseline-batch-scheduler.log`. Quantized slice and broader serving
505
+ checks accompany the filter change; M4 campaign acceptance remains separate.
506
+
507
+
457
508
  Benchmark harness: `scripts/bench-matrix.ts features` (six-cell
458
509
  composition matrix over live SSE: TTFT p50/p95 at the first SSE token,
459
510
  wall-clock aggregate tok/s, schema conformance as a hard gate);
@@ -463,37 +514,278 @@ naive tok/s — use wall-clock.
463
514
 
464
515
  ## 8. Open items
465
516
 
517
+ ### Consolidation matrix
518
+
519
+ This is the implementation gap inventory, not a claim that all combinations
520
+ have passed acceptance. Phase 6 coordinates the work; Phase 18 tracks its
521
+ batch cells. Current placement rules are in `src/engine/execution-plan.ts`.
522
+
523
+ The window-crossing scheduler gate in `tests/parity/batch-scheduler.test.ts`
524
+ now passes on Gemma 12B and e4b on both development machines. Two rows cross
525
+ the sliding window during decode; a third begins beyond it and joins late.
526
+ The pinned oracle replays the same admissions, merges and retirements and
527
+ compares every sampled full float32 logit vector. Run with
528
+ `MLX_BUN_TEST_BATCH_RING_WRAP=1`; `MLX_BUN_TEST_BATCH_RING_MODEL` selects the
529
+ existing artifact. Evidence is recorded in benchmarks.md.
530
+
531
+ Josh revised the immediate objective to shared batching by default with
532
+ effectively equal measured single-request performance. Serving already defaults
533
+ to a concurrency cap of eight, with B1 execution for a lone eligible request.
534
+ Explicit `--batch 1` and compatibility routing retain serial. Removing that
535
+ executor is deferred; complete feature parity is follow-up work, not a blocker
536
+ for the current default. Supported ordinary requests use the shared method.
537
+ Compare single-request B=1 latency, cold/cached
538
+ prefill and sustained decode as well as concurrent throughput. Record memory,
539
+ cache reuse and actual admitted rows. Keep kernel settings fixed for the
540
+ refactor comparison; measure new kernel optimizations in separate experiments.
541
+ Keep measured single-request regressions and unsupported features explicit.
542
+ They do not require repeating completed checks or withholding the current default.
543
+
544
+ | Concern | Current implementation | Required completion |
545
+ |---|---|---|
546
+ | Scheduling and ordinary decode | Default cap eight uses shared execution at B1/B>1; explicit `--batch 1` retains serial | Keep the batched default using existing measurements; address specific regressions separately. Serial removal is deferred |
547
+ | Speculative decode | Qwen MTP, prompt lookup, standalone, assistant, DeepSpec and seeded DSpark/DFlash providers are integrated through shared B1/B>1 interfaces, with the native/HTTP/cache checks recorded below | Finish specific unsupported combinations and measured regressions; GLM artifact testing is deferred and no trained DSpark/DFlash checkpoint exists |
548
+ | Sampling and logprobs | Shared sampler contract; ordinary groups capture logprobs and accept explicit seeds | Extend same-B oracle/feature compositions and matched performance; preserve per-request RNG/history |
549
+ | Grammar and fill | Grammar batches where enabled; grammar jump and fill remain serial-only | Shared constraint/proposal contracts and qualified batch compositions |
550
+ | Adapters and media | Compatible adapter groups use shared execution; media remains serial | Adapter performance and broader compositions; media preparation and compatible state through shared execution |
551
+ | KV layout | Full and rotating affine/TurboQuant layouts, delayed/per-layer transitions, speculative donors and ordinary paged storage are integrated and tested below | Direct paged-attention kernel, block sharing and quantized/speculative paging remain separate extensions; do not repeat the completed row-layout gates |
552
+ | Prefix and output reuse | Ordinary execution and Qwen MTP prefill/completed decode use the shared RAM/SSD cache | Finish composed native, long Kanban and pressure/timing acceptance; identical retention semantics at B=1 and B>1 |
553
+ | Generation resume | Shared ordinary resume is integrated after both-machine native/HTTP compiled, quantized/delayed and mixed-grammar checks, combined suites and eight M4 timing arms. The packed-model fixture now owns fresh weights per server | Adapter resume is integrated through the same policy; native/HTTP composition checks accompany it. Reuse the completed ordinary resume evidence |
554
+ | Usage and cleanup | The gateway forwards timing/rates; the missing first-token timestamp in ordinary batch admission is now fixed | Consistent events/accounting, row cancellation, failure cleanup and persistence on shutdown |
555
+ | Configuration | Placement still chooses path-specific implementations | One resolved configuration per concern; no setting silently disappears when B changes |
556
+
557
+ Tests must exercise actual B>1 work, not requests routed back to serial.
558
+ Completed checks remain evidence for their recorded source and settings. A new
559
+ run needs a named changed behavior, uncovered case or reproduced failure;
560
+ an open umbrella row is not a reason to repeat all its passing checks.
561
+ The working tree now has a shared transaction lifecycle for request-owned
562
+ acceptance counts. Recurrent state and attention KV implement the same round
563
+ operations. Attention rollback changes logical coverage without moving KV;
564
+ subsequent appends overwrite rejected tips. Positions, masks, extraction,
565
+ empty draft prefixes, late joins and retirement belong to that storage layout.
566
+ A singleton preserves allocated prefill capacity and uses the existing scalar
567
+ RoPE and causal-mask operations. Removing the longest recurrent row now updates
568
+ the group's maximum coverage to its survivors.
569
+
570
+ `MlxStateRows` applies admission, filtering and extraction through layer-owned
571
+ row layouts. Attention KV and `BatchedSSMCache` implement the same port; the
572
+ collection contains no model-family branches or persistence policy. Admission
573
+ borrows prepared state and builds all layer replacements before releasing the
574
+ active collection. Unit checks cover reorder, extraction, removal of every row,
575
+ reuse, donor ownership and failed admission. Full-target MTP controls preserve
576
+ all retained state at B=1/2/4 on both Macs through this collection.
577
+
578
+ The affine row layout composes those same position/retention
579
+ operations for affine KV's packed values, scales and biases. It adds no
580
+ dequantization to joins, rollback or extraction. Qwen attention consumes a
581
+ quantized numerical port rather than selecting the concrete cache class.
582
+ Focused KV4/KV8 storage checks pass, including unequal acceptance, overwritten
583
+ rejected tips, joins, growth, removal and compact extraction. Full-target MTP
584
+ bf16/KV4/KV8 round checks pass on both Macs, including output-aligned stopping
585
+ and survivor continuation at smaller B. Both complete model-free suites and
586
+ typechecks pass. `BatchedQuantizedKVCache` and the numerical attention port are
587
+ adopted in the working tree. The tested source matches the adopted source;
588
+ native logs and the `batched-quantized-state-manifest.json` live in the
589
+ composition-baseline reports. Same-B external quantized-oracle coverage and
590
+ actual speculative serving acceptance remain open.
591
+
592
+ The row method also handles a zero-proposal round through the
593
+ same graph/commit interfaces. It processes the pending companion KV row without
594
+ sampling a draft or projecting draft logits, then retains the target hidden
595
+ row needed for later speculation. The old request producer skips this update;
596
+ the native control instead discards a depth-one proposal to obtain the same
597
+ processed state. The change is adopted after full-round bf16/KV4/KV8 checks at B=1/2/4 on
598
+ both Macs, companion checks that forbid draft sampling/head projection in the
599
+ zero round, both complete model-free suites and typechecks. The source manifest
600
+ and native logs live in the composition-baseline reports. This does not adopt
601
+ the separately measured request-producer replacement or B=1 hidden slice.
602
+
603
+ The provider exposes grouped companion state through the existing
604
+ checkpoint representation. `PreparedStateChange` lets target and draft owners
605
+ stage a join independently; `applyStateChanges` publishes both only after all
606
+ preparation succeeds, then releases their old state. A failed preparation
607
+ leaves active membership intact. Publication performs no graph construction or
608
+ validation, and adds no operation to the decode round. Focused checks cover
609
+ failed joins, cleanup errors and released allocations. Full bf16/KV4/KV8
610
+ rounds through coordinated admission and both complete suites pass on both
611
+ Macs. This interface is adopted; serving must now use it before exposing a new
612
+ request to scheduling. Source identity and checks live in the
613
+ composition-baseline `mtp-admission-manifest.json`. Companion ownership
614
+ details live in speculative-decoding §4.8.
615
+
616
+ The MTP numerical graph is separate from request lifecycle and sampling. It
617
+ uses the cache's positions for both singleton and batched forwards. Native
618
+ checks on both Macs preserve full-target state and subsequent output at B=2,
619
+ plus the companion graph's output and KV after unequal prefix retention.
620
+ Uniform acceptance uses the existing recurrent kernel; unequal acceptance uses
621
+ the row-length-aware state-only kernel. The separate uniform state-only replay
622
+ experiment did not establish a serving win, so it is not promoted.
623
+
624
+ The exact-token acceptance walk is now a portable request state machine.
625
+ It tracks accepted drafts, correction/bonus tokens, EOS, token budgets and
626
+ grammar termination. Sampling still owns score processing and request history.
627
+ A group can stop sampling a finished walk while advancing the others.
628
+
629
+ The MTP row method keeps draft-token arrays on device between steps and reads
630
+ one complete proposal block. Its sampler is injected; committed state can be
631
+ extracted, filtered and joined between rounds. Greedy and seeded sampling pass
632
+ at depths 1/2/4 on both Macs, including retirement, reorder, rejoin and reuse
633
+ after removing every row. B=1 preserves the existing producer's proposals and
634
+ state. At B=2, per-step host-read and device-chain controls match at the same B.
635
+ The M4's B=2 KV differs from independent B=1 controls; cross-B byte equality is
636
+ not claimed, and the initial result remains in the raw logs.
637
+
638
+ `advanceSpeculativeRows` composes injected drafting, target verification,
639
+ request samplers and state transactions into one committed round. It has no
640
+ admission, output delivery or persistence policy. Each sampler walks only its
641
+ accepted prefix, recording logprobs and respecting EOS, grammar and remaining
642
+ token budget. The existing request adapter and grouped method now use the same
643
+ `sampleSpeculativeRows` operation. Failure tests cover disposal of verification
644
+ tensors when sampling or target/draft retention fails; the caller discards the
645
+ failed method state.
646
+
647
+ Native complete-round tests pass on both Macs at B=1/2/4 and depths 1/2/4,
648
+ with seeded depth-two coverage. They compare proposals, target samples,
649
+ logprobs, every retained target layer and draft KV/hidden state across three
650
+ rounds. B=1 uses the prior request producer and manual accept loop as control;
651
+ B=2/4 use a manual same-B loop with host reads between draft steps. These are
652
+ internal refactor controls, not a replacement for the external numerical oracle.
653
+ The row method is adopted in the working tree but not yet selected by serving;
654
+ matched complete-request performance remains an acceptance gate.
655
+
656
+ The next isolated candidate replaces the request producer's draft/commit loop
657
+ with the shared row method at B=1. The frozen `mtp-shared-draft-reference`
658
+ checkout retains the previous producer for native continuation and paired
659
+ serving comparisons. A zero-proposal round must retain its pending companion
660
+ KV row before resuming speculation; the old producer skipped that state update.
661
+ Native continuation checks pass on both Macs. Both serving orders preserve
662
+ responses but do not establish equal-or-better performance; the candidate is
663
+ not adopted. Numbers and frozen source identities live in benchmarks.md.
664
+ The subsequent isolated change replaces the B=1 hidden gather with a slice of
665
+ the same verification context, retaining the shared method. Its first serving
666
+ block is essentially flat in decode, but the reverse-order block regresses;
667
+ neither the source replacement nor the slice specialization is adopted.
668
+
669
+ The isolated round interface also separates verification/sampling from state
670
+ commit. `advanceSpeculativeOutputs` composes that round with the portable
671
+ `deliverDraftOutputs` operation. Each consumer receives verified tokens through
672
+ `GenerationOutput`; its stop, failure or cancellation affects its own request.
673
+ Both target and draft state then retain the same published, processed prefix,
674
+ excluding unpublished EOS and unprocessed correction/bonus tokens. Failed or
675
+ cancelled state must be discarded. Continuing requests keep their complete
676
+ accepted prefix. Verification context is an opaque disposable resource,
677
+ allowing graph-specific hidden taps without putting model details into
678
+ scheduling. The output method is adopted in the working tree; it is not wired
679
+ to serving. Focused tests and the complete isolated model-free suite pass.
680
+ Final-source native controls pass on both Macs, including removal of stopped
681
+ requests and continued generation at B=4→2 and B=2→1. They retain the old
682
+ request producer as the independent B=1 control. Same-B survivor comparisons
683
+ check tokens, logprobs and every retained target/companion state. Logs and the
684
+ source manifest live in the composition-baseline reports.
685
+
686
+ These are method/state dependencies, not served batched MTP acceptance. Grouped
687
+ draft generation, verification and sampling still need to be integrated into
688
+ the shared executor, with actual concurrent serving, cancellation, persistence,
689
+ quantized-layout composition and matched performance checks.
690
+ Parallel tool execution in Pi only exercises inference batching if model
691
+ requests overlap; record admitted rows and arrival schedules in the evidence.
692
+ Josh's September 8 M1 Max and M4 Pro suites are the ordinary-execution
693
+ baseline, recorded in [benchmarks.md](../reference/benchmarks.md#direct-scheduler-b1-versus-serial--both-machines-2026-09-08).
694
+ Retain those results and target new measurements at changed implementations
695
+ and newly supported features. They justify consolidation, but do not prove
696
+ the missing feature combinations or removal of host overhead.
697
+
698
+ ### Remaining mechanisms
699
+
466
700
  - **`--prompt-concurrency`**: not accepted by the CLI (mlx-lm's cap on
467
701
  joiners per iteration; the drop-in alias slot). Today at most one
468
702
  joiner prefills at a time.
469
703
  - **Rotating-layer `extend`**: Gemma joins extend their full layers but
470
704
  re-merge their sliding layers (`BatchedRotatingCache.merge` only).
471
- - **Full-layer filter `min_left_pad` shift** after eviction (mlx-lm
472
- cache.py does it); width waste only.
473
- - **Logprobs on the batch lane**: `wantsLogprobs` routes serial; the
474
- per-row sampler already computes `toLogprobs` — extend `RowSampler` to
475
- return extras and pass them through `onToken`.
476
- - **Batched timing stats**: the gateway returns `prefillMs/decodeMs/
477
- *Tps = 0` for continuous rows; `usage` timing is missing there.
478
- `maxTokens ?? 512` fallback in the gateway differs from the server
479
- default (dead in practice, a trap for library callers).
480
- - **LoRA-group batching**: adapter requests route serial. Design
481
- decided (adapter-set as the batch compatibility key; join if equal,
482
- drain if not; `loraState.active` set once per epoch); end state is
483
- per-slot adapter state in the batched step (vLLM/Punica is the oracle).
705
+ - **Logprobs acceptance**: ordinary batch capture is implemented through
706
+ the sampler interface. Unit coverage checks interleaved pipelines,
707
+ processor-adjusted probabilities, top-only capture and abandoned outputs;
708
+ `tests/parity/batch-logprobs.test.ts` exercises real B=1/B=2 and retirement.
709
+ On M4 Pro, the packed Qwen campaign artifact passes native and HTTP
710
+ serial/B=1 identity, actual B=2 capture on/off token identity, row retirement,
711
+ selected/top-only wire shapes and SSE omission. This is an internal
712
+ composition check, not a same-B external oracle or performance comparison.
713
+ Explicit-seed gateway tests also reproduce serial/B=1 outputs and repeat
714
+ fixed B=2 and controlled B=3 joins on M1 Gemma e4b and M4 packed Qwen.
715
+ These keep the numerical composition fixed; they do not assert
716
+ arrival-independent output across different batch shapes.
717
+ Broader compositions and matched performance remain open.
718
+ Cached-request diagnostics found synchronous recurrent-boundary persistence
719
+ inside a RAM hit and a serial request-time durability flush. Both are
720
+ removed: the shared cache lends immutable state views, and SSD writes run
721
+ independently of requests, acquiring idle ownership without draining active
722
+ batches. Explicit flush and shutdown remain durability
723
+ boundaries. Native repeated-prefix and SSD-restart continuation checks pass
724
+ on M1 and M4, including the saved long-prefix size on M4. A stalled-write
725
+ regression verifies RAM reuse and snapshot lifetime through donor eviction.
726
+ Balanced Bun 1.4.2 serving preserves outputs and near-equal decode time,
727
+ but a small cached first-output gap remains. First admission now seeds the existing device-token register to overlap its readback
728
+ with the following forward. Same-B MiniCPM/Gemma oracle vectors, compiled
729
+ B=1, grammar, first-token stop/EOS/length, callback containment, seeded
730
+ sampling and native/HTTP logprobs pass. Both serving arm orders preserve
731
+ outputs and close most of the remaining gap; the change is adopted in the
732
+ working tree. Actual method selection now precedes scheduling: configuring
733
+ a draft does not force ordinary logprob or supported affine-KV fallbacks
734
+ onto the serial executor. Native B=2 fallback outputs match ordinary B=2
735
+ on M1 and M4; HTTP tests with a configured draft also reach B=2 without
736
+ opening the producer. HTTP correctness tests align request arrivals at the gateway
737
+ to require concurrent work; serving benchmarks retain natural arrivals.
738
+ Broader pressure acceptance remains open.
739
+ Measurements live in benchmarks.md.
740
+ The gateway forwards timing/rates, but native regression coverage found that
741
+ ordinary admission never set the first-token timestamp. That caused zero decode
742
+ time even for multi-token responses. The timestamp is now recorded at first-token
743
+ emission; repeated shared-prefix B=2 tests check positive decode time and rate.
744
+ Both execution lanes already use the same omitted-library-cap fallback. Broader
745
+ usage and stopping compositions remain in the matrix.
746
+ - **LoRA-group batching**: ordered adapter sets now select compatible groups
747
+ through a backend-owned execution context. The scheduling driver sees only
748
+ readiness. Context changes and prefix identity bind under the execution
749
+ lease; adapter replacement while queued cannot reuse stale KV. Gemma e4b
750
+ native B=1/B=2, mixed queues, callback failure, separate prefix reuse and
751
+ queued replacement pass on M1/M4. Both machines match the pinned same-B
752
+ oracle through retirement and late joins; KV4/logprobs composition also passes.
753
+ Both M4 serving arm orders preserve single-request output. A small cached
754
+ first-output gap keeps strict performance dominance open;
755
+ simultaneous different adapters within a single forward remain future work.
756
+ Shared adapter speculation is qualified by the grouped provider's
757
+ `supportsTargetAdapters` capability. Prompt lookup declares it because its
758
+ draft state contains token history, with no separate learned graph to adapt.
759
+ Target prefill and verification retain the existing group adapter context;
760
+ adapter revision namespaces protect both target and lookup checkpoints.
761
+ Unqualified combinations retain ordinary execution. Learned providers do not
762
+ declare this capability. The native `adapter-lookup.test.ts` gate covers
763
+ compatible rows, seeded logprobs, failure cleanup and adapter prefix isolation;
764
+ both-machine bf16/KV4/TurboQuant checks pass, including existing ordinary-adapter
765
+ regressions. HTTP tests verify actual generated token alignment, exact seeded
766
+ RAM/SSD restart choices and speculation metadata, adapter namespace isolation
767
+ and concurrent requests. Concatenating a second newline can change the rendered
768
+ token boundary; the negative tokenization control preserves that distinction.
769
+ Full suites/typechecks pass; eight M4 comparisons are complete. Ordinary source cost is
770
+ effectively flat. Enabled lookup has low draft acceptance and loses concurrent
771
+ throughput on this workload; stricter matching is under separate measurement.
772
+ The feature remains opt-in and does not qualify a new default.
773
+ Evidence: `reports/qwen38-closeout/composition-baseline/adapter-lookup/`.
484
774
  - **Prompt-cache byte interplay**: mirror mlx-lm's
485
775
  `trim_to(total − activeBatchBytes)` so the LRU and the live batch
486
776
  share one ceiling. Derived default for `--kv-budget` (usable − weights
487
777
  − prompt-cache cap − headroom) instead of unlimited-when-unset.
488
- - **Long-context batched golden**: bf16 batched decode past the sliding
489
- window is oracle-gated model-free (`batched-rotating`), not yet as an
490
- end-to-end forward golden on a real Gemma.
778
+ - **Long-context batched golden is complete** for the recorded Gemma 12B/e4b
779
+ same-B window-crossing, retirement and late-join cases on both machines.
780
+ See the ring-wrap gate above; it is not outstanding implementation work.
491
781
  - **Unvalidated model cells** stay serial by the capability gate:
492
782
  gemma2-family (`maskArray`) and sliding-window universal archs.
493
- - **Paged KV batched integration** (§6 rung 3): block allocation in the
494
- scheduler, block-count admission, block CoW, fused paged kernel.
495
- - **GLM per-row MTP**: `--mtp on` routes serial+spec; batched MTP is
496
- post-release.
783
+ - **Paged KV**: ordinary shared storage is integrated and measured. Direct
784
+ paged attention, block sharing and quantized/speculative paging remain;
785
+ the state/cache interfaces own storage, independently of scheduling.
786
+ - **GLM MTP with concurrent requests**: the isolated shared provider passes
787
+ tiny-model and same-B Python state checks. Josh deferred final real-artifact
788
+ testing; see the GLM section below.
497
789
  - **Grammar jump-forward** (`MLX_BUN_GRAMMAR_JUMP`) is serial-only;
498
790
  `#stepGrammar` does not jump. Native XGrammar-2 via TVM-FFI has a
499
791
  B≫8 trigger.
@@ -502,8 +794,10 @@ naive tok/s — use wall-clock.
502
794
  its headroom.
503
795
  - **Batch-invariant kernels** (identical numerics regardless of B): Lab
504
796
  research item; would restore determinism under load for free.
505
- - **Per-row speculation inside the batch**: non-goal (variable accept
506
- lengths break uniform B); research question, not scheduled.
797
+ - **Qwen MTP with concurrent requests is integrated**: variable accepted
798
+ lengths, method-owned state alignment, shared sampling and generated RAM/SSD
799
+ reuse have passed the controls recorded below. Further work must identify a
800
+ specific unsupported composition or regression.
507
801
  - **Stale source comments**: `batch-scheduler.ts` header still says
508
802
  joins re-merge (extend landed 2026-07-04); `generation-gateway.ts`
509
803
  header and server-config.md say merged rows are never re-put
@@ -567,3 +861,981 @@ naive tok/s — use wall-clock.
567
861
  `BatchableCache`.
568
862
  - 2026-08-22 — rotating-join regression from 443f333 fixed (capability-only
569
863
  merge routing); `tests/batch-rotating-join.test.ts`.
864
+
865
+ ### Shared KV maintenance
866
+
867
+ `createKvMaintenance` resolves the KV policy once when composing an execution
868
+ session. The ordinary generator, speculative prefill and the MLX execution group call
869
+ this same backend operation at their populated-cache boundaries. Per-layer lookup
870
+ is no longer rebuilt on every serial decode step. Streaming conversion still
871
+ materializes and releases each layer before converting the next. The existing
872
+ single-call `maybeQuantizeKv` export remains a compatibility entry point.
873
+ Server uniform KV4/KV8 now uses the same operation and existing quantized
874
+ batch layouts. Capability discovery probes actual cache-owning layers, including
875
+ Gemma's shorter donor prefix; it does not infer a separate scheduler from the
876
+ quantization label. M1 Gemma e4b and M4 packed Qwen native tests cover seeded
877
+ sampling with logprobs, exact serial/B=1 output, and repeatable controlled
878
+ B=2/B=3 joins. Matched serving performance and same-B external oracle coverage
879
+ remain open. Start-zero TurboQuant now has encoded row-layout support for
880
+ ordinary and Qwen MTP methods. Positive ordinary TurboQuant thresholds now
881
+ have merged-row transitions; Qwen delayed affine conversion is also adopted.
882
+
883
+ Prefill policy is now shared too. The execution group captures its chunk
884
+ default once; ordinary and speculative preparation use it, and both honor a
885
+ library request override. The gateway forwards that override instead of
886
+ silently using the group default for ordinary requests. The scheduler does
887
+ not choose a numerical prefill chunk. M1 native seeded-sampling and MTP
888
+ RAM/SSD checks pass on both Macs. The first matched M4 short control preserves
889
+ all measured outputs with effectively unchanged timing; long-context checks
890
+ and balanced acceptance remain open.
891
+
892
+ Delayed ordinary TurboQuant conversion is now adopted after the mixed-phase,
893
+ prefix-reuse, fused/unfused and composed MTP/generated-output checks pass on
894
+ M4 as well as the original M1 family gates. The cache publishes its actual
895
+ irreversible conversion boundary through clone, extraction, RAM lookup and
896
+ SSD metadata; earlier plain donors remain usable. The first M4 hygiene run
897
+ found only a stale generated docs map. After regeneration, full hygiene passes
898
+ on both machines without changing tested code. The main full suite and typecheck
899
+ pass for ordinary conversion. Delayed shared MTP is also adopted after native
900
+ state/continuation, seeded B1/B3/late-admission, SSD and complete-suite gates on
901
+ both machines. Conversion follows retained state after rollback and preserves
902
+ physical row positions; the codec and kernels are unchanged. The main full suite, typecheck and hygiene pass. Qwen delayed affine is also adopted; these correctness gates establish
903
+ no new TQ default or performance gain.
904
+
905
+ ### Variable proposal lengths
906
+
907
+ The shared method accepts 0..depth proposals independently per
908
+ request. It sizes the rectangular target graph from the longest returned
909
+ proposal, right-pads shorter rows, and samples only through each row's own
910
+ bonus position. State commit retains the pending token and accepted inputs;
911
+ no padding enters a reusable checkpoint. If every proposal is empty, the
912
+ method runs one target step even when the configured draft depth is positive.
913
+ Scheduling does not choose proposal lengths or manage their acceptance.
914
+
915
+ The M1 Qwen control covers four rows with 0/1/2/3 proposals, greedy and seeded
916
+ sampling, independent retirement and re-admission. Both bf16 and KV4 preserve
917
+ tokens, logprobs, target state and companion state against explicit same-B
918
+ controls that use a different right-padding token. These are internal
919
+ composition checks, not an external oracle or a performance claim. Unit tests
920
+ also prove that padding consumes no sampler steps and terminal consumers
921
+ retain only delivered inputs. The complete candidate suite and typecheck pass.
922
+ M4 uniform/variable native controls and the complete suite also pass. The
923
+ first fixed-settings serving comparison was slower despite identical outputs
924
+ and speculation statistics. Alternating frozen-source controls do not reproduce
925
+ that slowdown and retain identical work. The three-file verifier patch is now
926
+ adopted; the main complete suite and typecheck pass. Provider migrations must retain their own
927
+ prefill/checkpoint conventions; this verifier alone does not change eligibility.
928
+ Evidence: `reports/qwen38-closeout/composition-baseline/variable-proposals/`.
929
+
930
+ ### Prompt lookup through the shared method
931
+
932
+ The shared executor now implements prompt lookup as a provider-owned draft
933
+ row group. Each row holds committed token history, proposes repeated spans,
934
+ and appends only inputs retained by verification. It uses the same variable
935
+ proposal verifier, sampler, target state, membership transactions and cache
936
+ publication as MTP. Scheduling has no prompt-lookup branch.
937
+
938
+ Preparation explicitly supplies processed-token coverage to the provider.
939
+ For tail-split lookup, the last prompt token becomes the first pending input;
940
+ completed-output keys include it exactly once. Integer history tensors use the
941
+ existing companion-checkpoint format and byte accounting. The generic tensor
942
+ reader now supports int32 for streamed SSD persistence; no separate prompt
943
+ lookup writer or storage queue is introduced.
944
+
945
+ M1 Qwen bf16/KV4/KV8/fused-TQ serving checks pass B1 controls, real B4 verification, independent
946
+ consumer stops/failures, cancellation, late joins, seeded logprobs and grammar.
947
+ All four schemes pass tool turns with thinking off/on, generated-prefix RAM reuse and fresh-PID
948
+ SSD restoration with identical responses, logprobs and acceptance. The initial
949
+ SSD flush failure exposed the missing int32 raw-byte reader; its regression
950
+ now passes. MTP3 serving regressions also pass in bf16/KV4/TQ after the shared
951
+ preparation changes. Unsplit-prefill serving and the complete model-free/SSD
952
+ suite and typecheck also pass. The same planned native/HTTP scheme matrix,
953
+ MTP regressions, unsplit-prefill and complete suite now pass on M4. An initial
954
+ M4 wrapper failure supplied CLI quantization value `0` instead of `off`; it
955
+ failed before inference, was retained, and the corrected wrapper resumed
956
+ without source changes. Fixed-MTP timing is effectively unchanged. Both lookup arm orders preserve
957
+ single-request outputs with small decode improvements and new cached-prefix
958
+ reuse. Concurrent outputs differ and observed shared throughput is lower, so
959
+ strict dominance is unproven. Default depth-10 KV4 serving checks now pass on
960
+ both Macs and exercise all ten proposal positions. Serving eligibility is
961
+ currently Qwen only. The seven-file patch is adopted; its concurrent
962
+ performance gap remains open, and serial deletion is not qualified.
963
+ Evidence: `reports/qwen38-closeout/composition-baseline/ngram-group/`.
964
+
965
+ A separate composed checkout combines the adopted variable verifier and ordinary
966
+ TQ cache with prompt lookup and delayed speculative TQ. The only production
967
+ hunk shared by the two candidate patches is the generic cache preparation hook
968
+ before state admission; the merged source is verified against both deltas.
969
+ M1 fused/unfused target/MTP and prompt-lookup native checks, threshold-crossing
970
+ SSD restart, full suite and typecheck pass. The lookup extension exercises the
971
+ same delayed-cache serving test by substituting its draft provider, including
972
+ mixed phases, seeded metadata, retirement and late joins. M4 composition now passes the same native/SSD gates, full suite, typecheck
973
+ and hygiene. Both production patches are now adopted in main, with exact
974
+ file identity against the tested composed source. Fixed-MTP composition
975
+ timing is effectively unchanged. Main full-suite, typecheck and hygiene checks pass.
976
+ Evidence: `reports/qwen38-closeout/composition-baseline/method-composed/`.
977
+
978
+ ### One-token prefill allocator maintenance candidate
979
+
980
+ A native first-output diagnostic found milliseconds of allocator cleanup after
981
+ a cached one-token target forward. A separate candidate retains allocator
982
+ buffers for single-token prefill work and still clears after larger chunks.
983
+ This is method-owned maintenance; the scheduler, sampler and cache-persistence
984
+ policy are unchanged. KV4 and delayed-TQ one-token suffix SSD continuations,
985
+ complete suites and typechecks pass on M1/M4. Alternating M4 fixed-MTP timing
986
+ preserves every request/output/usage record and consistently reduces cached
987
+ first-output latency. The first control has slower cold/decode timings, so
988
+ a broad throughput gain is not established. The 8k M1 allocation comparison
989
+ retains identical output/acceptance, nearly equal peak live allocation and a
990
+ larger final allocator pool. Matched serial/shared timing still shows a cached-latency regression; the
991
+ candidate remains isolated and long-context/SSD pressure remains open.
992
+ Evidence: `reports/qwen38-closeout/composition-baseline/single-token-maintenance/`.
993
+
994
+ ### Delayed affine conversion
995
+
996
+ The adopted delayed-affine implementation extracts `TransitioningKvRows` from the
997
+ existing TurboQuant adapter. It owns committed positions, conversion, physical
998
+ padding, merge/extract and speculative rollback. Codec-specific adapters retain
999
+ their attention arithmetic. The affine adapter uses the storage-owned
1000
+ `KvAttentionState` port for mixed-precision rows and the existing packed batch
1001
+ attention once every row converts. Model binding declares support once and
1002
+ passes that capability to request planning and executor construction.
1003
+
1004
+ Both Macs pass KV4/KV8 target rollback and continuation, ordinary serial/B1
1005
+ seeded token/logprob equality, MTP B1/B3 retirement and late admission, plus SSD
1006
+ restoration with conversion in prefill or decode. Fused/unfused TQ native and
1007
+ serving regressions pass. Final full suites and typechecks pass on both Macs.
1008
+ Positive affine thresholds and non-default group sizes have distinct cache
1009
+ identities; captured conversion floors survive extraction and SSD restoration.
1010
+ The original constructor-capability failure is retained in the raw evidence.
1011
+
1012
+ Alternating M4 fixed-settings comparisons preserve every request output, usage
1013
+ and finish reason with effectively unchanged timing. The reviewed implementation
1014
+ is adopted in the unreleased working tree. Eligibility currently covers Qwen;
1015
+ other model attention ports remain open. Main full-suite/typecheck/hygiene checks pass. Prompt lookup also passes KV4/KV8
1016
+ B1/B3 seeded continuation, actual proposals, retirement and late admission on
1017
+ both Macs without scheduler or sampler changes.
1018
+ No serial deletion or performance gain is established by these checks. Evidence is under
1019
+ `reports/qwen38-closeout/composition-baseline/delayed-affine/`.
1020
+
1021
+ The adopted attention port preserves Gemma's donor/shared-layer contract: a donor
1022
+ calls `Cache.attentionState.appendAndFetch` once, then every sharing layer calls
1023
+ `KvAttentionView.attend` on the same captured state. The view owns tensor handles
1024
+ and captured row alignment independently of later cache mutation or disposal.
1025
+ The model retains pre-write RoPE positions through all consumers and releases
1026
+ the view once at the end of the pass. Qwen and MiniCPM use one consumer per
1027
+ append. Existing training attention paths remain separate from these inference
1028
+ cache views. Scheduling and sampling do not manage attention-view lifetimes.
1029
+
1030
+
1031
+ The captured-view implementation exposes `appendAndFetch` and a
1032
+ reusable `KvAttentionView.attend`. Qwen consumes one view per append; Gemma can
1033
+ retain it for sharing layers. KV4/KV8 unit checks preserve two distinct queries
1034
+ after further appends, conversion, row reordering and disposal of the original
1035
+ cache. Full-model Gemma 12B logits and active cache state match the existing
1036
+ consumer path. The initial state test compared unused allocator capacity;
1037
+ the corrected check compares every processed value, and keeps the failed raw
1038
+ comparison. Gemma 12B/e4b and MiniCPM KV4/KV8 pass on both machines. The e4b checks
1039
+ exercise multiple reads per append. The M4 full suite passes. The initial M1
1040
+ suite used a fallback DeltaNet fixture because this worktree lacked the
1041
+ already-qualified machine golden; copying that unchanged fixture makes the
1042
+ focused test pass. Qwen KV4/KV8 rollback, MTP and prompt lookup regressions plus the corrected
1043
+ M1 suite pass. Both-machine typechecks and KV4/KV8 SSD continuations pass.
1044
+ Alternating M4 decode/cached/throughput timing is effectively unchanged. The
1045
+ final control end check flags a small CPU daemon; the raw result is retained
1046
+ and assessed under the campaign background-CPU policy. Startup remains less
1047
+ stable and is not qualified by this screen. The reviewed change is adopted;
1048
+ main integration suite, typecheck and hygiene pass.
1049
+ Gateway eligibility is unchanged until the broader storage combinations pass.
1050
+ Candidate evidence: `reports/qwen38-closeout/composition-baseline/kv-attention-view/`.
1051
+
1052
+
1053
+ Delayed rotating affine storage remains a separate missing composition. Its
1054
+ logical row positions and physical ring columns are different state: conversion
1055
+ or packing must preserve the mask/column relationship. Existing
1056
+ `BatchedRotatingQuantCache` has encoded row merging; the shared
1057
+ `BatchedRotatingState` owns ring positions. Reuse those interfaces rather than
1058
+ introducing a scheduler quantization branch. Qualify unequal offsets, conversion
1059
+ before/after wrap, retirement, late admission, shared Gemma consumers and
1060
+ persisted conversion floors before widening the gateway capability.
1061
+
1062
+ The first M4 benchmark wrapper stopped before inference because its parent
1063
+ shell inherited an older oracle path. The Qwen correctness child had already
1064
+ passed with the explicit pinned environment. Only the unstarted benchmark was
1065
+ resumed, with that same explicit environment; the completed four-arm comparison
1066
+ and failed launch log are retained.
1067
+
1068
+
1069
+ ### Multi-token rotating storage
1070
+
1071
+ The adopted rotating-block implementation removes the one-token-only restriction
1072
+ from both bf16 and affine batched rings. `RowStorage` supplies encoded tensor
1073
+ operations; `appendRotatingStorage` retains chronological history without
1074
+ unpacking affine tensors; `BatchedRotatingState.commitConcat` owns padding,
1075
+ logical positions and the physical write head. One-token updates retain their
1076
+ existing in-place implementation. The port follows the pinned mlx-lm
1077
+ `BatchRotatingKVCache._update_concat` for left-padded inputs.
1078
+
1079
+ A block temporarily holds up to window + block length - 1 columns so every
1080
+ query retains its full context. Extraction preserves that active block, while
1081
+ merge views select the newest window. Dropping the temporary suffix during
1082
+ extraction would corrupt subsequent continuation. No scheduler or sampler
1083
+ changes are needed for these storage operations.
1084
+
1085
+ The same-B live oracle gate covers B=1/2/3, unequal left padding, mixed
1086
+ one-token and block writes, repeated wrap, overshoot, row reordering,
1087
+ retirement, late admission and extracted state. bf16 values and masks match
1088
+ mlx-lm exactly on both Macs. KV4/KV8 share its geometry and preserve every
1089
+ extracted affine component against the native quantizer. Existing Gemma 12B
1090
+ ring-wrap serving still matches 48 full logit vectors per machine. Both-machine model-free/SSD suites and typechecks pass. The reviewed six-file
1091
+ change is adopted; main typecheck/hygiene pass. No performance or full
1092
+ batched-prefill claim is made.
1093
+ Right-padded prefill finalization and speculative rollback of overwritten
1094
+ ring entries remain part of the shared-execution work. Delayed rotating
1095
+ precision conversion is implemented below.
1096
+ Evidence: `reports/qwen38-closeout/composition-baseline/rotating-block/`.
1097
+
1098
+
1099
+ ### Delayed rotating affine conversion
1100
+
1101
+ The adopted implementation uses `TransitioningKvRows` for ordinary membership,
1102
+ retirement, checkpoints and precision changes. `SpeculativeTransitioningKvRows`
1103
+ adds rollback for layouts that implement it; ordinary rotating storage does not
1104
+ advertise speculative rollback. `TransitioningKvPositions` supplies geometry
1105
+ without a codec. Full-attention positions retain the existing `KvTensorRows`
1106
+ operations, and rotating positions use `BatchedRotatingState`.
1107
+
1108
+ An aligned row keeps the group's physical ring columns while exposing its own
1109
+ logical position to the shared affine-maintenance policy. Conversion quantizes
1110
+ the existing buffers without changing their physical layout, write head or
1111
+ padding. Once every row is converted, the encoded planes concatenate
1112
+ without reordering columns. `captureKvAttention` provides the same owned read
1113
+ view for either representation; Gemma's donor and sharing layers can keep
1114
+ reading it after the cache advances. No scheduling or sampling branch is added.
1115
+
1116
+ Membership changes normalize borrowed solo rows through owned clones. Empty
1117
+ plain and affine cache clones now remain valid empty caches, enabling a group
1118
+ to be assembled before its first input. Extraction preserves each row's
1119
+ conversion floor in the existing persistence schema. The implementation enables
1120
+ positive affine thresholds for ordinary Gemma execution; other speculative
1121
+ providers, rotating rollback and true batched-prefill scheduling remain open.
1122
+
1123
+ Gemma 12B and e4b KV4/KV8 pass exact hidden/logit and active-state checks before
1124
+ and after the real sliding window on both Macs. Serialized output snapshots
1125
+ preserve token IDs, state and conversion floors; restored snapshots continue
1126
+ identically to RAM snapshots in the same process. These are not fresh-process
1127
+ or long Kanban acceptance. Seeded gateway checks match serial at B1 and repeat
1128
+ B2/B3 admission schedules exactly on both machines. The model-free checks cover
1129
+ mixed precision, empty rows, conversion before/after wrap, block updates,
1130
+ retirement, late joins and attention reads after owner disposal. Final complete suites and typechecks pass on both Macs, as do Qwen affine
1131
+ MTP/lookup and fused/unfused TurboQuant regressions. Artifact-defined per-layer
1132
+ Gemma compression also passes both-machine hidden/logit/state and persistence
1133
+ checks. Four alternating M4 default Qwen benchmark arms preserve all responses
1134
+ and show effectively flat decode, cached latency and concurrent throughput;
1135
+ startup equivalence remains open. The reviewed fifteen-file implementation is
1136
+ adopted in the unreleased working tree. Main integration suite, typecheck and hygiene pass.
1137
+ Measurements and source identities live in benchmarks.md.
1138
+ Evidence: `reports/qwen38-closeout/composition-baseline/delayed-rotating/`.
1139
+
1140
+
1141
+ ### Singleton admission copy candidate
1142
+
1143
+ An isolated candidate replaces singleton `copyOf` calls with `contiguous` in
1144
+ attention and recurrent admission. The proposed GPU-copy saving is not
1145
+ supported: the M4 MLX 0.32.2 probe shows both operations share existing storage.
1146
+ This agrees with the existing explanation in `mlx/materialize.ts`; a method
1147
+ name is not evidence of a physical copy. The evaluated synthetic Qwen-shaped
1148
+ probe shows no additional GPU allocation for either version. Also, shared MTP
1149
+ publishes its first token before the singleton group merge, so that merge is
1150
+ not on its first-output critical path.
1151
+
1152
+ Both-machine ownership tests cover independent updates, donor immutability,
1153
+ self-merge, spare capacity and source/group disposal. Typechecks pass. The M4
1154
+ bf16/KV4/KV8 round matrix, fused/unfused TQ, delayed affine/TQ serving and full
1155
+ suite pass. M1 native/serving and the complete suite also pass. The alternating
1156
+ M4 HTTP comparison preserves all responses and records lower cached latency
1157
+ in both candidate arms. The physical-copy explanation is disproven, so further
1158
+ attribution/repetition remains before adoption. Startup equivalence and direct
1159
+ serial dominance are still unproven. Extraction and larger group concatenation
1160
+ are unchanged. Timing belongs in benchmarks.md.
1161
+ Evidence: `reports/qwen38-closeout/composition-baseline/singleton-state/`.
1162
+
1163
+
1164
+ ### Recurrent output-row retention
1165
+
1166
+ `SSMCache.extractRow` used `copyOf` with a comment promising compact storage.
1167
+ The current MLX implementation aliases that storage: after releasing a B>1
1168
+ source group, one retained row still owns the entire group's backing buffers.
1169
+ The M1 allocation probe reproduces this for B=2/4/8. This is separate from
1170
+ singleton admission, where sharing a complete allocation is appropriate.
1171
+
1172
+ The adopted extraction fix uses the existing `materializeCopy` port for
1173
+ a proper subset of a batch and retains a separate array handle for B1. Row
1174
+ values and logical offsets do not change. The allocation regression fails on
1175
+ the unchanged control and passes on the candidate, including exact values and
1176
+ disposal on both Macs. Both-machine KV4 MTP round matrices, bf16/KV4/TQ generated
1177
+ RAM/SSD continuations, complete suites and typechecks pass. Four alternating
1178
+ M4 HTTP arms preserve all responses and support integration without a broad
1179
+ speed claim. The source and regression test are adopted; main integration
1180
+ suite and typecheck pass. Long-context pressure acceptance remains open.
1181
+ No scheduler, sampler, persistence queue or quantization policy changes.
1182
+ Evidence: `reports/qwen38-closeout/composition-baseline/ssm-extraction/`.
1183
+
1184
+
1185
+ ### Padded prefill cache interfaces
1186
+
1187
+ The adopted cache-interface portion adds `PaddedPrefillCache`. Its frozen
1188
+ validation checkout is `padded-prefill-validation`.
1189
+ Preparation receives each prompt's lengths and left/right padding. Finalization
1190
+ removes trailing padding from logical coverage and aligns retained state before
1191
+ decode or checkpoint publication. The cache owns these operations; neither the
1192
+ scheduler nor a quantization codec chooses token positions.
1193
+
1194
+ `FullPrefillPadding` applies one row-roll index to arbitrary full-cache tensor
1195
+ planes. Plain KV, affine KV4/KV8 and TurboQuant reuse it without dequantizing or
1196
+ requantizing the stored values. Rotating storage instead moves completed rows'
1197
+ padding ahead of valid history before each block trims its window. Both plain
1198
+ and affine rings share that position logic and preserve physical alignment.
1199
+
1200
+ One-token padded chunks use the existing rotating concat operation and block
1201
+ mask. MLX-LM's public dispatch rejects this case before finalization. The gate
1202
+ therefore invokes its existing `_update_concat` and takes the first query from
1203
+ its two-token block mask for this extension. Ordinary decode retains the ring
1204
+ write. This is an extension checked against oracle operations, not a claim that
1205
+ the upstream public dispatcher supports the same call.
1206
+
1207
+ The live geometry gate checks B1/B2/B3, left/right padding, an existing prefix,
1208
+ window overflow, zero-length prefixes, one-token chunks, finalization, extraction
1209
+ and continuation.
1210
+ Plain tensors, masks and positions match the reference. Affine and TurboQuant
1211
+ retained bytes match their existing codecs applied to oracle-retained rows.
1212
+ MiniCPM5 and Gemma 12B/e4b also match full same-B logit vectors after padded
1213
+ prefill and three continuations with whole-prompt, 5/5/1 and singleton chunks
1214
+ on both Macs. Complete suites and typechecks pass on both machines. Qwen KV4
1215
+ MTP rounds, both TurboQuant decode settings and generated-prefix bf16/KV4/TQ
1216
+ RAM/SSD continuations also pass on both Macs. These regression runs use ordinary
1217
+ unpadded preparation; they do not qualify Qwen padded prefill.
1218
+
1219
+ The cache-interface changes are adopted; main integration suite and typecheck pass.
1220
+ Qwen recurrent-state masking, delayed rotating transitions and ordinary
1221
+ preparation cohorts are adopted below, including cancellation/checkpoints.
1222
+ MTP preparation and full-cache delayed padding still keep S1a open.
1223
+ No serving performance result or default change is claimed for this candidate.
1224
+ Evidence: `reports/qwen38-closeout/composition-baseline/padded-prefill/`.
1225
+
1226
+ Full-cache finalization now retains absolute valid ends, as rotating storage
1227
+ already does. It removes only padding actually processed. This lets a cohort
1228
+ finish early after a longer request leaves, or finalize a partial prefix before
1229
+ the original planned width. Ending before any right padding leaves tensors and
1230
+ positions untouched. Filtering and reordering requests also filters those ends.
1231
+ The unchanged control subtracts unprocessed padding and produces negative
1232
+ coverage in the shortened-cohort regression; its failure log is retained.
1233
+
1234
+ Both-machine geometry checks cover completed and shortened B1/B2/B3 prefills,
1235
+ cached prefixes, leading padding, request retirement/reordering before
1236
+ finalization, extraction and three subsequent decode steps. The reference full
1237
+ cache receives the effective padding of the processed prefix; Bun receives the
1238
+ original plan. Survivor checks select the corresponding oracle rows without
1239
+ changing their physical columns. Plain state/masks match exactly; affine and
1240
+ TurboQuant retained bytes match encoding those oracle rows. Host lifecycle
1241
+ tests also cover finalization before any work and preparation after a partial
1242
+ checkpoint. Model-free suites, SSD tests and typechecks pass on both Macs.
1243
+ This fixes cache preparation semantics; serving cohorts and their cancellation
1244
+ handling are still unwired. No speed or default change is claimed.
1245
+ Evidence: `reports/qwen38-closeout/composition-baseline/padded-partial/`.
1246
+
1247
+
1248
+ ### Recurrent-state padding
1249
+
1250
+ The adopted recurrent-padding change extends the same prefill port to
1251
+ Qwen's recurrent cache. `SsmPrefillPadding` tracks remaining real-token lengths
1252
+ and leading padding. Each cache advances coverage by real tokens only and
1253
+ filters that metadata with its rows. Finalization clears preparation state.
1254
+ Uniform prompts keep the unmasked kernel and ordinary convolution tail.
1255
+
1256
+ The model constructs one mask for all recurrent layers. DeltaNet zeroes padded
1257
+ QKV inputs before convolution, selects each row's convolution tail by its
1258
+ remaining length, and uses the pinned oracle's masked recurrence. Masked steps
1259
+ leave recurrent state unchanged. The existing kernel body is shared between
1260
+ masked and unmasked specializations; scheduling does not choose or manipulate
1261
+ these state operations. The convolution-tail selection already used by
1262
+ variable speculative rollback is reused here.
1263
+
1264
+ The primitive gate compares full output and state hashes with the pinned GPU
1265
+ oracle at the 27B head geometry. It includes B1/B3, fully masked rows, singleton
1266
+ steps and an unmasked continuation. The unchanged control fails this gate.
1267
+ The small Qwen model passes padded full-model checks on M1. Both Macs pass
1268
+ same-B 27B full-logit and convolution/recurrent-state checks for unequal prompts,
1269
+ batch-of-one and uniform B3, with whole-prompt, singleton-tail and all-singleton
1270
+ chunks. The machines use their locally installed affine 27B artifacts; these
1271
+ are per-machine oracle comparisons, not an engine or artifact speed comparison.
1272
+
1273
+ The isolated checkout initially retained three obsolete HEAD files and lacked
1274
+ its machine-specific golden blobs. Those setup problems were corrected against
1275
+ the validated base; no golden was regenerated. Initial scalar creation also
1276
+ needed the existing typed-array constructor. Failure logs remain with the
1277
+ candidate evidence. Both-machine MTP/TQ/generated RAM/SSD regressions, full
1278
+ suites and typechecks pass. Four alternating M4 HTTP arms preserve all responses
1279
+ with roughly flat decode/cached/throughput timing. Startup equivalence remains
1280
+ open. The change is adopted; main integration suite and typecheck pass.
1281
+ Delayed-codec preparation and actual serving cohorts remain open.
1282
+ Evidence: `reports/qwen38-closeout/composition-baseline/padded-ssm/`.
1283
+
1284
+ ### Delayed rotating compression during padded prefill
1285
+
1286
+ Delayed rotating KV4/KV8 now implements the same preparation/finalization port.
1287
+ Each physical row receives its own token lengths and the common batch layout.
1288
+ All rows use the padded block operation when any sibling has right padding,
1289
+ including a singleton chunk in a row without padding. An initial implementation
1290
+ lost alignment by letting that row switch to a ring write while its sibling
1291
+ continued block writes. The retained failing regression exposed incorrect cache
1292
+ bytes when those rows later packed together.
1293
+
1294
+ The shared position snapshot now combines every row's pending valid end when
1295
+ format conversion packs a group. Maintenance uses valid token counts, so a
1296
+ padded suffix cannot cross a precision threshold or inflate the earliest
1297
+ reusable prefix. Physical write positions remain separate. Retirement and
1298
+ reordering preserve pending preparation state before and after packing.
1299
+
1300
+ Both-machine geometry gates include B1/B2/B3/B4/B8, KV4/KV8, multiple transition
1301
+ thresholds, cached history, ring overflow, singleton chunks, early finalization
1302
+ and survivor continuation. Cache geometry comes from the pinned MLX-LM oracle.
1303
+ Encoded bytes match the existing codec applied to oracle-retained rows; exact
1304
+ attention checks use those oracle tensors and masks with the native operation
1305
+ at the same B as each mixed or packed representation. Gemma 12B/e4b also pass
1306
+ same-B padded model logits through the delayed layout before conversion.
1307
+ The latter is plain-KV model coverage, not a quantized padded full-model oracle.
1308
+ Ordinary Gemma conversion and RAM/SSD continuations, complete model-free suites
1309
+ and typechecks pass on both Macs.
1310
+
1311
+ The change is adopted in the unreleased working tree. Four alternating Gemma
1312
+ M4 benchmark arms preserve all responses; the small timing differences are
1313
+ recorded in benchmarks.md and establish no speed win or serial dominance.
1314
+ Full-attention delayed affine/TurboQuant padding remains open. Ordinary serving
1315
+ now uses the real-token cohort described below.
1316
+
1317
+ Ordinary serving uses a method-owned cohort of equal-length
1318
+ chunks of real tokens. It admits later arrivals between forwards. Each request
1319
+ retains its planned maintenance, checkpoint and tail boundaries when a peer
1320
+ causes an earlier split. Scheduling chooses membership; the preparation method
1321
+ runs shared forwards; cache layouts merge positions and retain precision policy.
1322
+ The same target driver now serves MTP and prompt lookup; their providers own
1323
+ companion prefill state through the separate method interface.
1324
+
1325
+ The first lifecycle runs exposed an empty-state native evaluation and missing
1326
+ initialization when a cold recurrent row joins populated state. Empty caches
1327
+ submit no evaluation. The recurrent layout initializes the new row's state
1328
+ with zeros, matching the pinned reference's ArraysCache.merge behavior.
1329
+ Qwen 27B on the M4 then exposed a logit mismatch immediately after retirement.
1330
+ Full-attention storage now removes padding shared by all survivors, matching
1331
+ BatchKVCache.filter. Affine planes inherit that operation; TurboQuant's tensor
1332
+ storage applies it too. These are cache membership operations, independent of
1333
+ scheduler, sampler and inference method.
1334
+
1335
+ Focused tests cover staggered B1→B2→B3 joins, real-token identity, native retained
1336
+ bytes with immediate/delayed affine and TurboQuant conversion, checkpoint
1337
+ boundaries, cancellation and completion callback failure. A scheduler-level test
1338
+ submits a request during the first forward and observes it in the next chunk.
1339
+ The model gate compares every full logit vector to the pinned same-B reference
1340
+ through joins and retirement, then compares each extracted row's continuation.
1341
+ It passes Qwen 27B and Gemma 12B on both Macs; the M1 also passes Qwen 0.8B.
1342
+ Padded cache geometry/encoded-state/attention checks pass on both machines.
1343
+ The padded oracle now performs retirement itself; stock filter omits pending
1344
+ prefill metadata, so the fixture selects its right-padding/length metadata with
1345
+ the same row indices before calling the existing finalize operation.
1346
+
1347
+ MTP delayed affine/TurboQuant regressions pass on both Macs. Four-arm M4
1348
+ timing and response differences are recorded in benchmarks.md.
1349
+ An added token-zero check then found that the M4 Qwen 27B sampler receives
1350
+ different logits when each completed row projects its hidden state separately.
1351
+ The shared forward's full vectors still match; the M=1 projection changes its
1352
+ arithmetic. A follow-up candidate projects the batch before selecting logits
1353
+ for each sampler. Its focused lifecycle checks and the M4 Qwen 27B/Gemma 12B full-vector,
1354
+ sampler-logit and continuation checks pass on both Macs. Full model-free suites
1355
+ and typechecks pass on both; all 829 nonignored source/test files match across
1356
+ the isolated copies. Fresh four-arm M4 timing is effectively flat. The corrected
1357
+ cohort is adopted in the unreleased working tree; main integration suite, typecheck and hygiene pass. Seeded delayed-TQ/affine serving and logprob/wire checks also pass on
1358
+ M1. Unsplit-prefill seeded serving passes M1 Qwen 0.8B and M4 Gemma 12B.
1359
+ Validated source: `/Users/joshrossi/.cache/mlx-bun/prefill-cohort-logits-validation`.
1360
+ A separate admission-control benchmark retains the measured code but disables
1361
+ additional cohort admission. That control restores every baseline response,
1362
+ attributing the changed concurrent text to shared prefill.
1363
+ Full delayed affine/TurboQuant padded preparation and MTP prefill cohorts remain
1364
+ open. The production HTTP benchmark now measures long aggregate prompts and
1365
+ staggered arrivals. Its four-arm M4 comparison exposes a first-output latency
1366
+ regression and no throughput win at the current chunk size. M1 traces show
1367
+ internal token zero ready before a long B3 preparation chunk delays the first
1368
+ response write. A matching smaller-chunk M4 screen still loses latency and
1369
+ throughput. Prefill work-unit sizing and admission policy need tuning through
1370
+ the shared scheduler/preparation interfaces. This is a scheduling decision
1371
+ within the shared executor; it must not introduce another serial method.
1372
+ See benchmarks.md for numbers and limits.
1373
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/`.
1374
+
1375
+ An isolated follow-up exposes preparation work through the scheduling contract.
1376
+ The preparation owner reports each admitted request's initial uncached token
1377
+ count; the queue adapter reports the next prompt length as an upper bound before
1378
+ cache restoration. The scheduler extends a cohort only while the combined
1379
+ weight fits its internal preparation budget, currently 2,048 tokens. The first
1380
+ request always enters and can exceed that budget alone. No request is rejected
1381
+ or sent to another executor. Short late arrivals still join ongoing preparation.
1382
+ An earlier version reduced the weight as prefill progressed. That allowed a
1383
+ nearly completed request to attract another long request into its tail; the
1384
+ first M4 screen restored early latency but still lost total request time. The
1385
+ current candidate retains admission weight until the request leaves preparation.
1386
+ This policy changes grouping, not per-request chunk or precision boundaries.
1387
+ Cache lookup/restoration remains in preparation, not scheduling. The conservative
1388
+ queued estimate can postpone a cached long request until current preparation
1389
+ ends. A native Qwen/TurboQuant check with a long RAM prefix passes repeat output,
1390
+ retirement, immutable cache bytes and actual B2 decode on M1. The original late
1391
+ prefill join remains covered, alongside a group test that holds a nearly finished
1392
+ row's weight and then advances its queued sibling through the same executor.
1393
+ The seven-file fixed-weight policy is adopted in the unreleased working tree.
1394
+ Both complete suites/types and long-prefix ownership checks pass. The M4
1395
+ comparison restores the large first-output loss and all response identity,
1396
+ while small unfavorable timing differences remain in benchmarks.md. Main
1397
+ integration suite/typecheck pass; strict performance dominance remains open.
1398
+ Candidate: `/Users/joshrossi/.cache/mlx-bun/prefill-budget-validation`.
1399
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/budget*`.
1400
+
1401
+ A separate two-file lifetime candidate releases input IDs after the forward and
1402
+ releases unused hidden output before cache evaluation/maintenance, matching the
1403
+ existing shared prefill primitive. The cohort previously retained those handles
1404
+ until the end of the work unit. Finished rows still retain hidden output through
1405
+ batched projection and sampling. Focused ownership checks pass on M1, and the Qwen 27B
1406
+ same-B model/sampler/continuation gates pass on both Macs. The M1 full suite and
1407
+ typecheck pass. The four-arm M4 comparison preserves all responses but shows no
1408
+ throughput or material measured-memory benefit. This candidate is not adopted;
1409
+ its M4 full suite/typecheck was not run. Timing and limits are in benchmarks.md.
1410
+ Candidate: `/Users/joshrossi/.cache/mlx-bun/prefill-drain-validation`.
1411
+
1412
+ The next isolated candidate exposes `DraftPrefillGroup` from the draft provider.
1413
+ It borrows each batch of new target tokens and context, and owns companion KV,
1414
+ the pending true hidden row, cold/restored membership and checkpoint capture.
1415
+ `QwenMtpRows` supplies preparation and draft/commit state at B1 and B>1;
1416
+ its preparation port requires no sampler. A restored request bridges its next
1417
+ token to the saved preceding hidden; cold members discard that bridge. The
1418
+ remaining chunk pairs each shifted token with its preceding target hidden.
1419
+ Preparation evaluates KV and the retained final hidden, leaving unused decoder
1420
+ outputs outside the evaluated graph. Membership and state extraction reuse the
1421
+ existing cache storage and checkpoint format. The scheduler is unchanged.
1422
+
1423
+ Pinned same-B checks pass companion KV and full decoder continuation through
1424
+ B1/B2/B3/B4, cold joins, restored prefixes, retirement and a long chunk boundary
1425
+ on both Macs. Those checks exposed a pre-existing unfused activation in the MTP
1426
+ MLP. Reusing the target's compiled SwiGLU matches the reference vectors. Existing
1427
+ MTP draft/commit checks and both complete suites/typechecks pass. Initial suite
1428
+ failures came from omitted benchmark fixtures and an old M1 DeltaNet golden in
1429
+ the isolated checkouts; restoring each machine's existing inputs fixes them
1430
+ without changing the implementation or regenerating goldens.
1431
+
1432
+ The seven-file provider port and numerical correction are adopted in the
1433
+ unreleased working tree. The M4 HTTP comparison preserves response text and
1434
+ prompt/output counts with effectively flat timing, while draft acceptance
1435
+ traces change. That comparison did not exercise batched MTP prefill because
1436
+ shared target preparation was not yet connected to the new port. Numbers and limits are in
1437
+ benchmarks.md. Main integration suite/typecheck pass.
1438
+
1439
+ The isolated `MlxPrefillRows` driver now owns target membership and chunk
1440
+ progression for ordinary, Qwen MTP and prompt-lookup preparation. Each method
1441
+ supplies initialization, chunk planning, checkpoint capture and completion.
1442
+ The draft provider owns companion prefill state and materializes restored
1443
+ companion copies before target membership releases an SSD backing lease.
1444
+ Final-step maintenance is explicit in the chunk plan. A fully restored
1445
+ pending-token prefix completes without a zero-length model forward.
1446
+ Prepared rows return to scheduling before joining active decode, preserving
1447
+ the first-output publication boundary.
1448
+
1449
+ The connected implementation passes full suites and typechecks on both Macs,
1450
+ and the target's same-B oracle checks through staggered prefill and continuation.
1451
+ The companion and Gemma 12B target oracles also pass on M1. Expanded native MTP serving checks on both
1452
+ Macs prove that a request submitted during the first target chunk joins the
1453
+ next chunk before any output. M4 passes this check with prompt lookup and
1454
+ TurboQuant as well. These checks also cover B1 producer parity, B4 execution,
1455
+ retirement, cache reuse and HTTP grammar/logprobs. Generated target/draft
1456
+ checkpoints preserve RAM/SSD continuation after restart on both Macs with TQ.
1457
+ An added M1 probe confirms four rows actually share prefill in that cache test,
1458
+ before the first output.
1459
+
1460
+ Added method lifecycle checks verify exact target/history coverage, zero-work
1461
+ restored prefixes and cancellation before and after preparation completes.
1462
+ The latter exposed a failure that rejected siblings before active admission.
1463
+ The method now rejects and releases only the cancelled ready row. A first-token
1464
+ consumer failure also leaves an unfinished sibling running. M1 delayed affine
1465
+ MTP/lookup and delayed TurboQuant MTP checks preserve seeded continuation,
1466
+ metadata and speculation through mixed precision, retirement and late joins.
1467
+ The common driver also passes M1 ordinary TQ ownership checks with a 4096-token
1468
+ RAM prefix through concurrent use, retirement and supersession.
1469
+ The balanced M4 comparison is complete. Shared MTP prefill reduces concurrent
1470
+ throughput. Two attribution runs retain the same shared engine but prepare
1471
+ requests individually; both reproduce control responses and restore throughput.
1472
+ This isolates the regression to enabling shared preparation, without requiring
1473
+ a separate serial executor. A narrower policy that finishes a resumed final
1474
+ prefill step before admitting new rows does not recover throughput and produces
1475
+ the same responses and speculation counters as the shared-prefill candidate.
1476
+ Neither scheduling variant is adopted. The common driver is adopted with the
1477
+ cache ownership fix described below.
1478
+ Phase/layer probes narrow the sustained gap to MLP evaluation despite identical
1479
+ Trellis routes, shapes, dtypes and call counts. Settling target state and clearing
1480
+ the temporary pool after preparation does not restore throughput and is not
1481
+ adopted. The snapshot-lifetime investigation below recovers this loss. Numbers
1482
+ and conditions are in benchmarks.md. Broader composed oracle/cache coverage and
1483
+ other draft providers remain open.
1484
+ Candidate: `/Users/joshrossi/.cache/mlx-bun/mtp-prefill-validation`.
1485
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/mtp-prefill*`.
1486
+
1487
+ Common-driver candidate: `/Users/joshrossi/.cache/mlx-bun/mtp-cohort-validation`.
1488
+ Evidence: `reports/qwen38-closeout/composition-baseline/prefill-cohort/mtp-cohort*`.
1489
+ The integration patch and source hashes are recorded in
1490
+ `mtp-cohort-integration.patch` and `mtp-cohort-integration-manifest.json`
1491
+ under that evidence directory. Native logs identify which test expansion
1492
+ ran; earlier serving checks did not include arrival during target prefill.
1493
+
1494
+
1495
+ A deferred compact row snapshot retained its full parent batch until evaluated.
1496
+ Resolving target snapshots before RAM retention recovers the concurrent loss
1497
+ in two M4 runs while preserving every shared-prefill response and full usage
1498
+ record. Failed tile-size, input-evaluation and residency experiments are closed.
1499
+
1500
+ The adopted implementation moves snapshot materialization into the
1501
+ RAM prefix-cache implementation. A backend operation resolves target state and
1502
+ opaque companion tensors before storage accepts ownership. It performs no
1503
+ serialization or disk I/O; eventual SSD persistence keeps its existing queue.
1504
+ Ordinary decode, MTP and lookup publish through the same interface and need no
1505
+ method-local evaluation rule. Evaluation failure leaves ownership with the
1506
+ publisher. The regression test measures retained allocation before any cache
1507
+ read and covers both target and companion rows. Both-machine suites/typechecks, composed native checks and the matched M4
1508
+ comparison pass. Main integration suite, typechecks and hygiene pass. Strict B1/long-prefill
1509
+ acceptance and remaining feature combinations are still open. Numbers belong in
1510
+ benchmarks.md; source and validation records are in
1511
+ `mtp-cohort-cache-boundary-manifest.json` under the cohort evidence directory.
1512
+
1513
+
1514
+ ### Full-attention delayed compression during padded prefill
1515
+
1516
+ The integrated full-attention implementation provides the existing padded-prefill
1517
+ port for delayed affine and TurboQuant rows. Each row keeps physical write
1518
+ positions, valid token coverage and pending finalization separately. Conversion
1519
+ uses valid coverage; codec tensors retain their physical alignment. When all
1520
+ rows share an encoding, the packed layout inherits pending valid ends. Finalizing
1521
+ and retiring rows move encoded planes without re-encoding live values. The same
1522
+ row wrapper and transition lifecycle serve affine and TurboQuant; model methods
1523
+ and scheduling are unchanged.
1524
+
1525
+ The extended pinned cache oracle passes on both Macs with KV4/KV8 and TQ K8/V3
1526
+ and K4/V4, multiple conversion thresholds, cached history, shortened prefill,
1527
+ retirement/reorder, continuation, and leading padding across multiple chunks.
1528
+ It checks masks, positions, retained encoded bytes and same-B attention. Invalid
1529
+ padding bytes are not state: moving encoded zero padding can preserve a different
1530
+ signed zero than encoding it again, while retained values and attention remain
1531
+ exact. Existing unpadded row/cohort regressions pass on M1. The Gemma model gate
1532
+ exposes a before-conversion mismatch when affine attention runs uniform BF16
1533
+ rows separately. The candidate now assembles those tensors through the same
1534
+ helper as TurboQuant and runs attention at the model's B. The cache oracle
1535
+ passes after that change, as does the Gemma affine full-model gate. Both
1536
+ regression suites and typechecks pass. Affine MTP/lookup and delayed affine/TQ
1537
+ seeded serving pass on M1; TQ MTP serving passes on M4. Generated MTP3/B4
1538
+ RAM/SSD continuations pass on both Macs. All four matched M4 arms preserve responses and usage. The measured small
1539
+ throughput decrease is recorded in benchmarks.md; strict B1/long-prefill
1540
+ acceptance remains open. Main integration suite/typechecks pass. Candidate:
1541
+ `/Users/joshrossi/.cache/mlx-bun/full-delayed-prefill-validation`; evidence:
1542
+ `reports/qwen38-closeout/composition-baseline/full-delayed-prefill/`.
1543
+
1544
+
1545
+ ### Standalone autoregressive draft graph integration
1546
+
1547
+ The integrated implementation runs a standalone draft graph at the group's B and
1548
+ hands its log-probabilities to the existing row sampler. Immutable batch
1549
+ snapshots retain accepted recurrent/attention boundaries without changing
1550
+ scheduler policy. Full acceptance retains the last draft token as companion
1551
+ state and re-feeds it with the next target token in one forward, preserving
1552
+ the reference's two-token shape. Mixed one-/two-token feeds use the existing
1553
+ padding interface. Zero-proposal rounds preserve processed-token coverage.
1554
+
1555
+ The lifecycle test covers mixed acceptance, removal/reordering, zero proposals
1556
+ and mixed re-feed lengths. A native Qwen 0.8B gate on M1 checks exact B1
1557
+ attention/recurrent state and continuation at depths 0, 1, 3 and 4. The provider is integrated; its old single-request source now
1558
+ adapts the same draft engine at B1. The small Qwen target/drafter passes B1/B4
1559
+ serving, late joins, consumer failures, seeded sampling/logprobs and HTTP
1560
+ coverage. Companion state reuses backend cache codecs; asynchronous prefill
1561
+ completion now preserves target-context ownership. The 27B target with the 0.8B
1562
+ standalone drafter passes B1/B4 serving on both Macs (228 assertions each),
1563
+ and depth-three TurboQuant generation restores through RAM and cold SSD
1564
+ (33 assertions each). The M4 pinned Python oracle passes the Llama 3B/1B
1565
+ pair, including four templated cases at draft depths two and three, grammar
1566
+ and stopping. Full suites pass on M1/M4 (2,153/2,157 tests), as do all
1567
+ typechecks and the existing MTP/lookup native regressions. The first matched M4 comparison improves B1 decode and cache reuse but
1568
+ hits a GPU allocation failure in the four-request phase, including the
1569
+ benchmark’s retry. The allocation trace explains why short correctness
1570
+ coverage did not expose this workload failure. Replaying
1571
+ all prior requests reproduces the failure with 4,005 MiB of accounted RAM
1572
+ cache entries and a 17,987 MiB observed allocation peak. A fresh aggregate
1573
+ passes. The retained entries consume the remaining working-set headroom;
1574
+ the repeated comparison holds both arms at 2 GiB RAM plus SSD and completes
1575
+ all four arms. Decode/cached/aggregate gains and cold/startup costs are
1576
+ recorded in benchmarks.md. Main integration suite, typechecks and hygiene pass. The retained 4 GiB failure remains part of cache-settings acceptance.
1577
+ Validation source:
1578
+ `/Users/joshrossi/.cache/mlx-bun/two-model-batch-validation`; source hashes and
1579
+ checks: `reports/qwen38-closeout/composition-baseline/two-model-batch/`.
1580
+
1581
+ ### Full-attention target capability binding
1582
+
1583
+ The integrated implementation moves the shared target-layout factory behind
1584
+ one storage capability binding. Grouped speculation then depends on the
1585
+ model graph's batch support and the storage transaction factory, replacing
1586
+ the Qwen-only target selection. Scheduler and draft-provider policy are
1587
+ unchanged; quantized speculation retains its existing qualification while
1588
+ plain full-attention targets are tested. On M1, Llama 3B with the same model
1589
+ as drafter passes shared B1/B4 serving, late joins, retirement, seeded
1590
+ sampling/logprobs and grammar (224 assertions). Prompt lookup passes the
1591
+ same serving harness; generated RAM/SSD continuation passes at depth three.
1592
+ The pinned Llama model oracle is exact at B1/2/3/4/8 across padding, chunks
1593
+ and continuation (541 assertions), and mixed-prefix target rollback passes
1594
+ 1,352 state/continuation assertions. The complete M1 suite and typechecks pass.
1595
+ Both-machine Llama and MiniCPM serving/lookup/cache checks pass, as do the
1596
+ wide same-B oracle, Qwen MTP/TQ regressions, full suites and typechecks.
1597
+ The M4 shared B1 path also passes the pinned templated speculation oracle.
1598
+ Four matched M4 arms complete; gains, cold-prefill cost and the changed
1599
+ concurrent response are recorded in benchmarks.md. Main integration suite, all typechecks and full hygiene pass. Rotating target transactions remain the next storage gap.
1600
+ Validation source:
1601
+ `/Users/joshrossi/.cache/mlx-bun/full-kv-speculation-validation`;
1602
+ evidence: `reports/qwen38-closeout/composition-baseline/full-kv-speculation/`.
1603
+
1604
+
1605
+ ### Rotating target transactions
1606
+
1607
+ The rotating-storage adapter now exposes independent speculative acceptance
1608
+ through the existing target transaction interface. It reuses the existing
1609
+ ring kernels and keeps the verification rectangle: rejected suffixes move
1610
+ into masked left padding. Contracting the rectangle preserved KV columns
1611
+ but failed Gemma continuation equality; that candidate was replaced.
1612
+ Published rows contain the newest accepted window; ordinary ring extraction
1613
+ retains its pinned-oracle oversized-block behavior. No scheduler change.
1614
+
1615
+ Tagged storage windows, cloning, retirement and subsequent writes pass.
1616
+ Both-machine Gemma 12B lookup serving passes at B1/B4, including late joins,
1617
+ consumer failures, grammar, seeded sampling/logprobs and HTTP coverage.
1618
+ Both-machine Gemma target transactions pass 3,080 assertions across prompts
1619
+ straddling the actual 1,024-token window, unequal acceptance and continuation.
1620
+ Both-machine pinned padded-model oracle passes at B1/2/3/4/8, and
1621
+ standalone draft generation restores through RAM/cold SSD. The default
1622
+ lookup depth of ten exposed a singleton geometry difference; an unwrapped
1623
+ single row now retains its scalar prefix geometry without adding padding.
1624
+ The depth-ten serving gates now pass for Gemma 12B and e4b on both Macs.
1625
+ Both final suites/typechecks pass, alongside the Qwen MTP/TurboQuant regression.
1626
+ The final-source matched M4 comparison completes: concurrent throughput and
1627
+ cache reuse improve, while B1 decode is effectively equal. Startup variation
1628
+ and different concurrent trajectories are recorded in benchmarks.md.
1629
+ The adapter is integrated; main integration suite, all typechecks and full hygiene pass. Quantized rotating
1630
+ speculation and the remaining providers are still open.
1631
+ Validation source: `/Users/joshrossi/.cache/mlx-bun/rotating-speculation-validation`.
1632
+ Evidence: `reports/qwen38-closeout/composition-baseline/rotating-speculation/`.
1633
+
1634
+
1635
+ ### Assistant draft rows
1636
+
1637
+ The assistant provider now supplies the same prefill and decode row interfaces
1638
+ as standalone drafting. It retains only the last true target hidden and its
1639
+ processed-token count. The target layout supplies captured donor attention;
1640
+ full and rotating layouts own valid intervals and masks. The draft graph does
1641
+ not know the scheduler or cache geometry. Matching layers and draft steps reuse
1642
+ the same donor mask. All proposals remain on device until the chain completes.
1643
+ Generated checkpoints store the hidden companion alongside existing target KV,
1644
+ using the same RAM ownership and queued SSD persistence.
1645
+
1646
+ Both e4b centroid and 12B tied heads use one graph at B1/B2/B4. The pinned
1647
+ optiq loader assumes centroid presence from config; the 12B numerical test binds
1648
+ its actual tied embedding head by tensor presence while retaining upstream
1649
+ layers. The e4b end-to-end test uses unmodified optiq `spec_generate`. Both
1650
+ machines pass these checks, serving/retirement/late joins, grammar/logprobs and
1651
+ generated RAM/SSD continuations. Tagged donor columns independently verify
1652
+ padding, rejected suffixes, wrap and row removal. The old contiguous transposed
1653
+ weights caused a hidden-state mismatch on M4 even before this refactor. Keeping
1654
+ upstream's strided weight views restores exactness and avoids duplicate weights.
1655
+
1656
+ The candidate is integrated after both regression suites/types and the four-arm
1657
+ M4 comparison. Main integration suite, all typechecks and full hygiene pass. Throughput and cached
1658
+ latency improve; readiness and concurrent-trajectory differences remain recorded
1659
+ in benchmarks.md. DeepSpec follows through projected context rows.
1660
+ Evidence: `reports/qwen38-closeout/composition-baseline/assistant-batch/`.
1661
+
1662
+
1663
+ ### Shared DeepSpec context rows
1664
+
1665
+ DeepSpec's context projections and block graph now accept the active row count.
1666
+ The MLX projected-context owner reuses full-attention row storage, cache codecs
1667
+ and coordinated membership. Its attention port hides context geometry and
1668
+ validity from the block graph. The provider declares its target taps and stores
1669
+ projected context as the ordinary method companion in RAM and queued SSD.
1670
+ Accepted lengths advance each row independently; rejected context never survives
1671
+ in a published checkpoint. The sequential proposal head stays on device through
1672
+ the block, and serving skips unconsumed confidence values when truncation is off.
1673
+
1674
+ Synthetic tests cover bf16/quantized projections, confidence truncation through
1675
+ zero proposals, differing commit lengths, restoration and retirement. Real Gemma
1676
+ 12B serving/generated RAM/SSD checks pass with both DeepSpec bf16 and its affine
1677
+ 4-bit sibling on both Macs, including the trained seven-token block. Native B1
1678
+ full logits and confidence match the frozen implementation; B2/B4 repeat exactly
1679
+ with independent positions. These comparisons are regression controls, not a new
1680
+ external DeepSpec oracle: the existing Torch oracle requires a separate reference
1681
+ environment and bf16 target that are not currently installed on either laptop.
1682
+ Real-window checks confirm that shared speculation remains active across wrap
1683
+ while the previous serial path stops drafting there. Both-machine regression
1684
+ suites and all typechecks pass. Four matched M4 arms improve aggregate throughput
1685
+ and cached latency; startup cost and one changed concurrent response remain
1686
+ recorded in benchmarks.md. The candidate is integrated; the main regression
1687
+ suite, all typechecks and full hygiene pass. DSpark/DFlash is next and shares the projected-context lifecycle.
1688
+ Evidence: `reports/qwen38-closeout/composition-baseline/deepspec-batch/`.
1689
+
1690
+
1691
+ ### Shared DSpark/DFlash provider
1692
+
1693
+ The draft graph accepts B1 and B>1 through one backbone and sequential proposal
1694
+ head. Markov and RNN heads retain their existing numerical behavior. Confidence
1695
+ can retire proposals independently for each row, and sampled proposal streams
1696
+ remain independent. Serving avoids confidence and float-logit outputs it does
1697
+ not consume. Scheduling does not select a draft implementation.
1698
+
1699
+ DSpark and DeepSpec use the same projected-context lifecycle. The provider binds
1700
+ projection and proposal operations; the shared owner handles prefill, accepted
1701
+ lengths, row membership, capture and restoration. The MLX context store applies
1702
+ padding and attention validity. Generated context enters the existing RAM cache
1703
+ and queued SSD persistence as a method companion.
1704
+
1705
+ Pinned graph outputs and both-machine Markov/RNN real-Gemma serving/generated
1706
+ RAM/SSD tests pass. Those tests use seeded draft weights, so they establish
1707
+ execution and state contracts, not trained acceptance or quality. Josh confirms
1708
+ that no DSpark/DFlash checkpoint has been trained yet. DeepSpec's real trained provider passes again
1709
+ after the extraction. Full suites and all typechecks pass on both Macs. Four M4
1710
+ arms measure the extraction using the same trained DeepSpec checkpoint and
1711
+ preserve all responses and usage. The measured throughput cost is recorded in
1712
+ benchmarks.md. The provider is integrated; the main suite, all typechecks
1713
+ and full hygiene pass. Trained DSpark performance qualification remains open. Evidence:
1714
+ `reports/qwen38-closeout/composition-baseline/dflash-batch/`.
1715
+
1716
+
1717
+ ### Affine rotating speculation and encoded assistant donors
1718
+
1719
+ Uniform start-zero KV4/KV8 target layouts now compose with grouped draft
1720
+ providers on full-attention and rotating targets. Acceptance bookkeeping is
1721
+ shared by plain and encoded rings. Packed values, scales and biases use the
1722
+ same row operations; rollback, retirement and snapshots never dequantize.
1723
+ Ordinary rotating extraction retains the oracle's oversized-block geometry;
1724
+ committed speculative snapshots retain only the newest valid window.
1725
+ Unpadded verification keeps the existing fused attention mask dispatch.
1726
+ Standard universal attention and MiniCPM now consume encoded cache ports
1727
+ instead of assuming plain arrays or a concrete affine cache class. The
1728
+ universal softcap branch retains its existing plain-only qualification.
1729
+
1730
+ Assistant drafting consumes an opaque donor-attention interface. Storage owns
1731
+ the encoded planes and validity ranges; the assistant only supplies queries.
1732
+ Its compatibility source now adapts the same row graph at B1. The redundant
1733
+ plain-only AssistantTarget interface is removed. Additive donor masks follow
1734
+ the pinned affine attention operation, independently of boolean cache masks.
1735
+
1736
+ Native continuation controls must hold both batch size and physical attention
1737
+ width fixed. The pinned Python oracle reproduces the captured different-width
1738
+ full-attention results byte for byte: one bf16 output differs despite identical
1739
+ queries and valid KV. The transaction test pads only the reference's fetched
1740
+ views to the compared width, retaining exact state and hidden checks.
1741
+ The old executor disables speculation near the rotating boundary, so its KV4
1742
+ text can differ from active shared speculation. Live-window tests record that
1743
+ comparison and check repeated active execution; they do not relabel ordinary
1744
+ fallback as an exact speculative oracle.
1745
+
1746
+ Both-machine KV4/KV8 serving and generated RAM/SSD checks pass for DeepSpec,
1747
+ assistant, standalone and lookup providers; seeded DSpark heads pass the same
1748
+ state contracts. Real-window transactions, same-width target controls, pinned
1749
+ regressions, full suites and all typechecks pass. Six M4 benchmark arms preserve
1750
+ bf16 responses and usage with effectively unchanged throughput. KV4 improves
1751
+ aggregate throughput on this workload, with different generated text and more
1752
+ prefill time; the comparison is recorded in benchmarks.md. The change is
1753
+ integrated; the main suite, all typechecks and full hygiene pass.
1754
+ Evidence: reports/qwen38-closeout/composition-baseline/rotating-spec-quant/.
1755
+ Strict performance dominance and removal of the serial control remain open.
1756
+
1757
+
1758
+ ### TurboQuant donor attention and grouped draft composition
1759
+
1760
+ Solo, packed and delayed TurboQuant storage expose the same owned donor-attention
1761
+ interface as plain and affine caches. Captures preserve physical columns, row
1762
+ validity and right-prefill padding without appending tokens, converting precision
1763
+ or advancing membership. Assistant attention consumes eagerly decoded values,
1764
+ preserving its existing operation order. MiniCPM retains its explicit deferred
1765
+ value rotation. Storage chooses the existing codec and fused decode kernels;
1766
+ scheduling does not identify the encoding or draft provider.
1767
+
1768
+ The gateway advertises grouped TurboQuant from the bound target and provider
1769
+ capabilities. Positive conversion thresholds use the existing row-local
1770
+ transition lifecycle; sliding layers remain bf16. Per-layer affine speculative
1771
+ configuration composes through the same bound row capabilities. Group binding now snapshots per-layer and
1772
+ TQ options so caller mutation cannot change a live graph or its persisted
1773
+ identity. Explicit per-layer schemes get distinct group/cache keys, with
1774
+ canonical layer ordering; absent/empty schemes preserve existing keys exactly.
1775
+
1776
+ The isolated candidate passes independent K8/V3 donor codec plus pinned assistant
1777
+ graph controls at B1/B2/B4 with fused decoding on/off for both Gemma assistant
1778
+ artifacts on the M4, alongside the unchanged bf16 oracle. M1 assistant and
1779
+ MiniCPM lookup pass start-zero serving/generated RAM/SSD and delayed conversion,
1780
+ retirement and late admission. Both-machine assistant, DeepSpec, standalone and lookup serving/generated
1781
+ RAM/SSD, delayed conversion and late admission pass, along with seeded DSpark
1782
+ heads, Qwen regressions, final suites and typechecks. Twelve M4 timing arms
1783
+ record both source-only costs and TQ configuration tradeoffs in benchmarks.md.
1784
+ The source is integrated; main suite, all typechecks and full hygiene pass.
1785
+ Evidence: `reports/qwen38-closeout/composition-baseline/turboquant-donor/`.
1786
+
1787
+ The independent assistant control also exposed an existing centroid-head
1788
+ numerical shortcut on M1: matrix multiplication did not preserve the oracle's
1789
+ bf16 multiplication followed by reduction. On identical B2 hidden state, Python
1790
+ reproduced the old candidate token with matmul and the oracle token with explicit
1791
+ multiply/sum. The shared head now preserves that operation order at every B and
1792
+ selects the lowest vocabulary ID among tied candidate scores, matching sparse
1793
+ vocabulary argmax without materializing a full-vocabulary logits buffer. The
1794
+ independent codec, hidden-state and token assertions remain exact. The M1 e4b
1795
+ control and unmodified end-to-end optiq generation pass after the correction;
1796
+ final both-machine regressions pass. The source-only and TQ timing comparisons
1797
+ are recorded in benchmarks.md. Attribution repeats recover the prior decode rate on the unchanged candidate, so they do not establish a code regression. Captured diagnostics live
1798
+ with the composition evidence.
1799
+
1800
+
1801
+ ### Delayed and per-layer affine rotating speculation
1802
+
1803
+ Rotating storage owns an accepted-column transaction shared by plain and affine rings. The generic transition interface invokes that transaction while rows have different precisions; after conversion it packs them into the existing affine layout. Conversion sees only committed tokens. Scheduling and draft providers do not inspect the quantization scheme.
1804
+
1805
+ Full and rotating caches expose owned donor-attention views. Mixed rows retain their physical columns, valid offsets and padding; assistants submit queries and masks without materializing a common decoded cache. Pending right-prefill padding is excluded before finalization, including when a physical block exceeds the sliding window. Captures survive cache conversion, row reordering and disposal.
1806
+
1807
+ The gateway now advertises supported affine configurations from the target/provider binding, including model-defined per-layer schemes and positive library thresholds. The served CLI schemes retain start zero. Independent attention fixtures cover padding and ownership; exact target hidden/logit controls cross the real sliding boundary at verification widths one and eight. Native checks cover continuation, precision transitions, unequal retirement, late admission, grammar/logprobs and generated RAM/SSD companions. Legacy serving rejects some of these combinations; repeated shared execution is not relabeled as a legacy speculative oracle.
1808
+
1809
+ Both-machine provider/native/suite/typechecks and six matched M4 benchmark arms are complete. Bf16 responses and usage remain exact; model-defined per-layer KV trades higher single-request decode for lower aggregate throughput on the measured workload. The change is integrated; main suite, types and full hygiene pass. Evidence: `reports/qwen38-closeout/composition-baseline/delayed-rotating-spec/`. Defaults and the serial retirement criterion remain unchanged.
1810
+
1811
+
1812
+ ### GLM compressed target and native MTP rows
1813
+
1814
+ The integrated implementation adds independent accepted-column transactions and cold-row membership to compressed MLA/DSA storage, without reconstructing full K/V. Native MTP exposes a shared numerical graph and a grouped provider. Its prompt prefill retains the target anchor while leaving MTP cache empty; committed accepted positions are rebuilt from true target hidden states. Target token coverage and the shorter draft-cache offset remain separate checkpoint metadata. The existing attachment interface persists both through the generic RAM/SSD cache.
1815
+
1816
+ Both-machine tiny-model controls cover exact B1 proposals/absorption, zero-proposal rounds, streamed expert calls, B4 membership with DSA enabled, late admission, retirement, generated-prefix identity and identical RAM/SSD next drafts. DSA verification retains every request row and shares each logical query selection across FULL/SHARED layers. Compressed multi-token attention now masks physical left padding, including native MTP absorption. Empty DSA rows survive filtering and resumed writes. Six two-layer dense/sparse boundary cases per machine match independent pinned Python/MLX hidden and every cache plane byte-for-byte. Python uses the uncompiled sigmoid/multiply activation that this model graph calls. Different-B controls retain greedy IDs but can differ in small f32 values because physical widths select absorbed/reconstructed attention and different matrix kernels; they are not the exact numerical oracle. Both full model-free suites, the SSD suite and all typechecks pass. The tested implementation is integrated in the PR. Josh has deferred final GLM-5.2 Colibri artifact testing. This does not establish real-artifact numerical or performance acceptance. Evidence: `reports/qwen38-closeout/composition-baseline/mla-transaction/`.
1817
+
1818
+
1819
+ ### Paged storage through shared row and request-state interfaces
1820
+
1821
+ `PagedKvRows` owns per-request block pools, immutable snapshots, gathering, masks, offsets and row membership. The existing executor binds it through the cache-layout interface. `MlxRequestStatePolicy` supplies compatible state construction and a prompt-cache port; paging selects no prefix store. Switching back to ordinary requests restores their cache port. The same paging constructor serves the compatibility entry point and shared prefill. B1 keeps the existing paged numerical graph; B>1 gathers padded attention inputs while retaining separate persistent pools. Gemma12 full sampled logits and HTTP choices match the ordinary same-B controls, including seeded sampling, logprobs and grammar. Both-machine model-free, SSD and typechecks pass. The native storage comparison fixes cohort membership and snapshot boundaries on both sides, covering small blocks and the default block boundary; otherwise cache publication changes the numerical prefill graph. The matched M4 source comparison is effectively flat, and shared paging improves concurrent throughput versus serial while retaining effectively equal B1 decode. Concurrent text can differ across batch geometries; the exact storage oracle compares the same geometry. Timing and limitations live in benchmarks.md; evidence is `reports/qwen38-closeout/composition-baseline/paged-rows/`. Paged attention kernels, block-level prefix sharing, quantized paging and speculative paging remain separate work.
1822
+
1823
+ The sampler now exposes an optional stateless operation for compatible independent score rows. Ordinary decode and speculative verification share normalized-score argmax. Verification can sample a rectangle in one device operation and readback; acceptance still consumes only each request's valid positions. Grammar, processors, stochastic sampling, logprob capture and custom sampler functions retain their request-local operation. Same-shape numerical tests include rounding-created ties and large vocabularies; both-machine native/generated RAM/SSD and suites pass. Twelve matched M4 arms preserve ordinary throughput and improve lookup aggregate throughput; startup and trajectory limits are recorded in benchmarks.md. Lookup defaults remain unchanged. Evidence: `reports/qwen38-closeout/composition-baseline/independent-sampling/`.
1824
+
1825
+
1826
+ ### Campaign checkout consolidation
1827
+
1828
+ The PR incorporates the accepted implementations from the M1 and M4 campaign
1829
+ checkouts, including ordinary resume, adapter-aware resume and GLM shared MTP
1830
+ state. Older TQ, provider, cache and prefill candidates are superseded by the
1831
+ integrated compositions above. Benchmark baselines and rejected wider-Trellis,
1832
+ option-capture, state-only replay and cohort scheduling variants remain
1833
+ experiment records; copying them over the selected implementation would undo
1834
+ later work. The singleton `copyOf` to `contiguous` candidate remains unpromoted
1835
+ because its attribution and startup result are unresolved.
1836
+
1837
+ The 80 secondary Git worktrees and 99 campaign source copies were removed
1838
+ after their source files and reports were verified in a content-addressed local archive under
1839
+ `reports/pr-closeout/checkout-archive/`, with per-checkout manifests, SHA-256
1840
+ objects and the recorded base commit. The PR retains the implementation and
1841
+ findings; bulky raw experiment data stays local under the repository policy.