Skip to main content

memra_engine/
dflash.rs

1//! DFlash block-diffusion drafter (DFLASH-BRINGUP-PLAN.md, 2026-07-13).
2//!
3//! 5-layer qwen3-class mini-transformer that drafts a 16-token block in ONE non-causal
4//! forward, conditioned on the TARGET's hidden states at 6 tapped layers (concatenated
5//! through `fc` + `hidden_norm`). No embed / lm_head of its own — the round reuses the
6//! target's. Reference: z-lab/dflash `dflash/model.py` (semantics frozen in the plan doc);
7//! oracle: tools/dflash_oracle.py -> /data/cache/dflash-oracle.npz.
8//!
9//! FIRST LIGHT = f32-resident weights + fresh full-context forward (no draft KV cache) —
10//! correctness vs the oracle, then the cache/quant/window arms land measurement-gated.
11
12use crate::Engine;
13use crate::model::GpuTensor;
14use cudarc::driver::CudaSlice;
15
16pub struct DflashCfg {
17    pub hidden: usize,                // 5376
18    pub n_head: usize,                // 64
19    pub n_kv: usize,                  // 8
20    pub head_dim: usize,              // 128
21    pub n_ff: usize,                  // 10752
22    pub n_layer: usize,               // 5
23    pub eps: f32,                     // 1e-6
24    pub rope_theta: f32,              // 1e6
25    pub block_size: usize,            // 16
26    pub mask_token_id: u32,           // 4
27    pub target_layer_ids: Vec<usize>, // [1,12,23,35,46,57]
28    pub sliding_window: usize,        // 2048
29    /// true = sliding_attention for that layer (4x true + 1x false on the 31B draft).
30    pub layer_sliding: Vec<bool>,
31    /// Checkpoint training-strategy census (`dspark_strategy_census` over the raw
32    /// config.json): true = a SpecForge DSPARK-strategy export (shifted labels, ALL rows
33    /// supervised — the q38 arm-a family). Keys the HARVEST DEFAULT strategy-keyed,
34    /// never env-keyed (owner-ratified 2026-08-20 after B1 confirmed H1 ×5;
35    /// DSPARK-POSTMORTEM-20260820.md B0 default-flip plan).
36    pub strategy_dspark: bool,
37    /// Explicit top-level `is_causal` from config.json (z-lab reference: an explicit
38    /// value OVERRIDES the per-layer-type default). The DFlash2 q38 checkpoint carries
39    /// `"is_causal": false` — every sliding layer is NON-causal with a symmetric
40    /// +/-2048 window (model.py `_attention_mask`). None = key absent (historical
41    /// exports; the windowless-assert arm keeps handling those byte-identically).
42    pub is_causal: Option<bool>,
43}
44
45pub struct DflashLayer {
46    pub wq: GpuTensor,           // [nh*hd, hidden] row-major (out_f rows)
47    pub wk: GpuTensor,           // [nkv*hd, hidden]
48    pub wv: GpuTensor,           // [nkv*hd, hidden]
49    pub wo: GpuTensor,           // [hidden, nh*hd]
50    pub w_gate: GpuTensor,       // [n_ff, hidden]
51    pub w_up: GpuTensor,         // [n_ff, hidden]
52    pub w_down: GpuTensor,       // [hidden, n_ff]
53    pub ln_in: CudaSlice<f32>,   // [hidden]
54    pub ln_post: CudaSlice<f32>, // [hidden]
55    pub q_norm: CudaSlice<f32>,  // [hd]
56    pub k_norm: CudaSlice<f32>,  // [hd]
57}
58
59pub struct DflashDraft {
60    pub cfg: DflashCfg,
61    pub layers: Vec<DflashLayer>,
62    pub fc: GpuTensor,               // [hidden, n_taps*hidden]
63    pub hidden_norm: CudaSlice<f32>, // [hidden]
64    pub norm: CudaSlice<f32>,        // [hidden]
65    /// DSpark semi-AR markov head (present in the repo-root checkpoint variant):
66    /// draft logits at position k get + W2(W1[prev_realized_token]) — left-to-right
67    /// within the block (the patch's _markov_semiar_sample_block semantics, greedy).
68    /// w1 = raw bf16 [V, rank] (row-gathered by device token id); w2 = q8_0 [rank->V].
69    pub markov: Option<MarkovHead>,
70    /// DSpark accept-rate head (trained with confidence loss). sglang's DSPARK planner
71    /// consumes it to SIZE VERIFY WINDOWS (cumprod survival — v0.5.16 headline; the
72    /// earlier "reference serving loop never consumes it" note matched SpecForge's
73    /// legacy spec_generate only). memra schedules with it under
74    /// `MEMRA_DSPARK_VT=confidence` (the H4 fix, DSPARK-POSTMORTEM-20260820.md:
75    /// per-round verify window from cumprod survival, `dspark_confidence_vt`) and
76    /// keeps it census+parity-only under the default ladder. Host-resident (5k floats).
77    pub confidence: Option<ConfidenceHead>,
78    /// YaRN rope (q38 arm-a inherits the target's rope_parameters: rope_type yarn,
79    /// factor 32, original 8192, beta 32/1). ff = per-dim divisors for rope_neox_ff
80    /// (effective inv_freq_j = base^(-2j/d)/ff[j] = the HF-yarn remapped frequency,
81    /// verified vs Qwen3RotaryEmbedding to 1.6e-7), mscale = attention_scaling
82    /// (0.1*ln(factor)+1) applied to q/k post-rope — cos/sin scaling distributes onto
83    /// the rotated vector exactly. None = plain rope (gemma/z-lab drafters).
84    pub rope_yarn: Option<(CudaSlice<f32>, f32)>,
85    /// DFlash2 head (z-lab `DFlash2DraftModel`, DFLASH2-EVAL-20260820.md): grouped
86    /// dynamic causal convs around EVERY sublayer + the candidate path selector that
87    /// replaces the markov chain. A DISTINCT semantic program from the DSpark head
88    /// (no-generic-support law): present iff config `architectures` names
89    /// `DFlash2DraftModel`, and then ALL 23 family tensors are REQUIRED — loading the
90    /// 58 backbone tensors alone computes an untrained model (the census trap).
91    pub dflash2: Option<Dflash2Head>,
92}
93
94/// One `GroupedDynamicCausalConv` module (reference model.py): a causal 2-tap
95/// depthwise conv over the BLOCK rows (block-local — row 0 zero-pads its missing
96/// predecessor; stateless across rounds), with per-position dynamic per-group
97/// coefficients projected from the module INPUT. `prepare` convolves the sublayer
98/// input with base_kernel[0] + dyn half 0; `finish` convolves the sublayer OUTPUT
99/// with base_kernel[1] + dyn half 1 (both dyn halves come from the SAME projection
100/// of the pre-conv input).
101pub struct Dflash2Conv {
102    /// base_kernel [2, k, hidden] flattened f32 (half-major: prepare then finish).
103    pub base: CudaSlice<f32>,
104    /// kernel_projection.weight [2*k*groups, hidden] (row layout = view(2, k, groups)).
105    pub proj: GpuTensor,
106}
107
108pub struct Dflash2Head {
109    pub attn_conv: Vec<Dflash2Conv>, // per layer
110    pub mlp_conv: Vec<Dflash2Conv>,  // per layer
111    /// candidate_selector.hidden_projection.weight [rank, hidden].
112    pub hidden_proj: GpuTensor,
113    /// Codebooks [V, rank] raw bf16, HOST-resident: the walk gathers ~1+16 rows per
114    /// draft slot (~70KB/round) — host math beside the round's existing chain dtoh,
115    /// no device residency for 2x127MB tables. Checkpoint quirk: stored WITHOUT the
116    /// `.weight` suffix (reference from_pretrained installs a key_mapping).
117    pub pred_codebook: Vec<u8>,
118    pub succ_codebook: Vec<u8>,
119    pub rank: usize,       // selector_rank 256
120    pub top_k: usize,      // selector_top_k 16
121    pub conv_k: usize,     // conv_kernel_size 2
122    pub group_size: usize, // conv_group_size 16
123    pub vocab: usize,      // codebook rows (248320)
124}
125
126/// Resolve the named DFlash weight program. Keep this separate from loading so a typo cannot
127/// silently select q8 and invalidate a performance/default receipt.
128fn dflash_precision(raw: Option<&str>) -> Result<&str, String> {
129    let prec = raw.unwrap_or("q4");
130    match prec {
131        "q4" | "q8" | "mixed" | "bf16" | "fc" => Ok(prec),
132        other => Err(format!(
133            "MEMRA_DFLASH_PREC={other:?}: want q4, q8, mixed, bf16, or fc \
134             (q5 was measured defective and is not a serving mode)"
135        )),
136    }
137}
138
139/// One bf16 codebook row -> f32 (exact widening).
140fn cb_row(cb: &[u8], tok: usize, rank: usize) -> Vec<f32> {
141    bf16_to_f32(&cb[tok * rank * 2..(tok + 1) * rank * 2])
142}
143
144/// The per-row top-k selector's EXHAUSTED-SLOT sentinel. `topk_rows_f32` and its sharded twin
145/// (`cu/kernels.cu`) fill a slot they could not fill with `0xffffffff`: a row with fewer than
146/// `k` FINITE values — in practice an all-NaN logits row, since every comparison against NaN
147/// is false and a NaN therefore never enters a candidate list.
148pub const TOPK_EMPTY_SLOT: u32 = u32::MAX;
149
150/// Refuse a candidate buffer the selector could not fill (memra#95).
151///
152/// A sentinel row reaching the walk means the DRAFT LOGITS were not a number, which is a
153/// broken invariant upstream (memra#95: a restored full-cover glm5 session read its drafter
154/// ctx KV on a pp stage stream before the caller's import had landed). Two reasons this is a
155/// guard at the proposal seam and not a clamp:
156///
157/// * clamping would silently draft a wrong token, and the drafts feed the verify batch — a
158///   worse outcome than any failure, per the exactness law;
159/// * the walk's own `assert!(c < vocab)` is the last line of defence inside a PURE function,
160///   and it kills the GPU WORKER THREAD, which is fleet-fatal (one respawn, then
161///   the process exits and every in-flight session on the box dies). Returning `Err` here
162///   fails ONE request instead, the same trade `crate::spec::guard_vocab_token` makes for the
163///   native-MTP chain's sentinel (memra#87). The assert stays where it is.
164///
165/// `bound` is the selector's own column space: the `n_vocab` the caller handed `topk_rows`,
166/// which on a trimmed FR-Spec head is the trim's rank count and on a full head is the target
167/// vocabulary. Checked BEFORE any d2t remap, because remapping a sentinel would index the map
168/// out of bounds and panic before the walk is ever reached; the map is pre-checked to cover
169/// `n_vocab`, so passing this bound also proves the remap safe.
170///
171/// ASSUMES UNMASKED DRAFT LOGITS, which is what both proposal seams feed it today: `dl` is a
172/// raw `matmul` output and constrained requests never take the spec route, so a row cannot
173/// legitimately hold fewer than `top_k` finite values. A future masked-draft-logits arm would
174/// have to revisit this, and would want a shorter round rather than a refusal.
175///
176/// NOTE THE SCOPE: both proposal seams are shared with the LIVE dspark/q38 serve arm, not
177/// only the flagged glm5 restore. This changes that route's failure mode too, from a
178/// fleet-fatal worker panic to one refused request. That is the intended direction, and it
179/// is the only behaviour change outside the default-OFF flag.
180pub fn dflash2_guard_candidates(cand: &[u32], bound: usize, ctx: &str) -> Result<(), String> {
181    for (i, &c) in cand.iter().enumerate() {
182        if c as usize >= bound {
183            let why = if c == TOPK_EMPTY_SLOT {
184                " (the top-k selector's exhausted-slot sentinel: the draft logits row carried \
185                   fewer than top_k finite values, i.e. it was NaN)"
186            } else {
187                ""
188            };
189            return Err(format!(
190                "{ctx}: DFlash2 candidate slot {i} is {c}, outside the selector's {bound} \
191                 columns{why}"
192            ));
193        }
194    }
195    Ok(())
196}
197
198/// Greedy selector walk (reference `CandidateSelector.select` at T=0): per draft
199/// slot p, score(k) = unary[p,k] + <pred_codebook[prev] .* hidden_proj_row[p],
200/// succ_codebook[cand[p,k]]>, argmax over the top-k candidate set; the CHOSEN
201/// candidate seeds the next slot (sequential — the chain is the semantics, not an
202/// optimization). Host math (~nd*k*rank fused ops per round) over host-resident bf16
203/// codebooks; ties break to the LOWEST k (torch argmax convention). Pure so the
204/// selector semantics are CPU-gateable.
205///
206/// `unary`/`cand`: [nd, top_k] row-major; `hproj`: [nd, rank] row-major.
207#[allow(clippy::too_many_arguments)]
208pub fn dflash2_walk_greedy(
209    pred_codebook: &[u8],
210    succ_codebook: &[u8],
211    vocab: usize,
212    rank: usize,
213    top_k: usize,
214    unary: &[f32],
215    cand: &[u32],
216    hproj: &[f32],
217    anchor: u32,
218    nd: usize,
219) -> Vec<u32> {
220    dflash2_walk_greedy_q(
221        pred_codebook,
222        succ_codebook,
223        vocab,
224        rank,
225        top_k,
226        unary,
227        cand,
228        hproj,
229        anchor,
230        nd,
231    )
232    .0
233}
234
235/// [`dflash2_walk_greedy`] with the per-slot CONFIDENCE recorded (lane/glm5-loop-port,
236/// 2026-08-30): q[p] = softmax over the slot's candidate-set scores at T=1, of the chosen
237/// candidate — the greedy twin of `dflash2_walk_sampled`'s recorded `q_chosen` (same
238/// statistic family the owner's "take only high confidence offers" tau gate thresholds on
239/// the dspark route). The argmax selection is UNCHANGED (q is bookkeeping over the same
240/// scores, ~top_k exps per slot on host), so every existing greedy caller is byte-identical
241/// through the delegating wrapper. Pure, CPU-gateable like its siblings.
242#[allow(clippy::too_many_arguments)]
243pub fn dflash2_walk_greedy_q(
244    pred_codebook: &[u8],
245    succ_codebook: &[u8],
246    vocab: usize,
247    rank: usize,
248    top_k: usize,
249    unary: &[f32],
250    cand: &[u32],
251    hproj: &[f32],
252    anchor: u32,
253    nd: usize,
254) -> (Vec<u32>, Vec<f32>) {
255    let (kk, r) = (top_k, rank);
256    assert_eq!(unary.len(), nd * kk, "walk: unary shape");
257    assert_eq!(cand.len(), nd * kk, "walk: candidate shape");
258    assert_eq!(hproj.len(), nd * r, "walk: hidden-projection shape");
259    let mut path = Vec::with_capacity(nd);
260    let mut q_chosen = Vec::with_capacity(nd);
261    let mut prev = anchor;
262    for p in 0..nd {
263        assert!(
264            (prev as usize) < vocab,
265            "walk: predecessor token {prev} outside codebook vocab {vocab}"
266        );
267        let pr = cb_row(pred_codebook, prev as usize, r);
268        let hp = &hproj[p * r..(p + 1) * r];
269        // gate = pred_row .* hidden_proj (shared across the candidate set)
270        let gate: Vec<f32> = pr.iter().zip(hp).map(|(a, b)| a * b).collect();
271        let mut scores = vec![0f32; kk];
272        let (mut best, mut bi) = (f32::NEG_INFINITY, 0usize);
273        for (k, s) in scores.iter_mut().enumerate() {
274            let c = cand[p * kk + k] as usize;
275            assert!(c < vocab, "walk: candidate {c} outside codebook vocab");
276            let sr = cb_row(succ_codebook, c, r);
277            let mut acc = unary[p * kk + k];
278            for j in 0..r {
279                acc += gate[j] * sr[j];
280            }
281            *s = acc;
282            if acc > best {
283                best = acc;
284                bi = k;
285            }
286        }
287        // Recorded confidence: softmax at T=1 over the candidate set (f64 accumulation,
288        // the sampled walk's numeric discipline), of the argmaxed candidate.
289        let mut z = 0f64;
290        for &s in &scores {
291            z += ((s - best) as f64).exp();
292        }
293        q_chosen.push(if z > 0.0 { (1.0 / z) as f32 } else { 1.0 });
294        prev = cand[p * kk + bi];
295        path.push(prev);
296    }
297    (path, q_chosen)
298}
299
300impl Dflash2Head {
301    /// Greedy selector walk over this head's codebooks — see `dflash2_walk_greedy`.
302    pub fn walk_greedy(
303        &self,
304        unary: &[f32],
305        cand: &[u32],
306        hproj: &[f32],
307        anchor: u32,
308        nd: usize,
309    ) -> Vec<u32> {
310        dflash2_walk_greedy(
311            &self.pred_codebook,
312            &self.succ_codebook,
313            self.vocab,
314            self.rank,
315            self.top_k,
316            unary,
317            cand,
318            hproj,
319            anchor,
320            nd,
321        )
322    }
323
324    /// Greedy walk with the per-slot confidence recorded — see `dflash2_walk_greedy_q`.
325    pub fn walk_greedy_q(
326        &self,
327        unary: &[f32],
328        cand: &[u32],
329        hproj: &[f32],
330        anchor: u32,
331        nd: usize,
332    ) -> (Vec<u32>, Vec<f32>) {
333        dflash2_walk_greedy_q(
334            &self.pred_codebook,
335            &self.succ_codebook,
336            self.vocab,
337            self.rank,
338            self.top_k,
339            unary,
340            cand,
341            hproj,
342            anchor,
343            nd,
344        )
345    }
346
347    /// Sampled (T>0) selector walk — see `dflash2_walk_sampled`.
348    #[allow(clippy::too_many_arguments)]
349    pub fn walk_sampled(
350        &self,
351        unary: &[f32],
352        cand: &[u32],
353        hproj: &[f32],
354        anchor: u32,
355        nd: usize,
356        temp: f32,
357        uniforms: &mut dyn FnMut() -> f32,
358    ) -> (Vec<u32>, Vec<f32>, Vec<f32>) {
359        dflash2_walk_sampled(
360            &self.pred_codebook,
361            &self.succ_codebook,
362            self.vocab,
363            self.rank,
364            self.top_k,
365            unary,
366            cand,
367            hproj,
368            anchor,
369            nd,
370            temp,
371            uniforms,
372        )
373    }
374}
375
376/// AcceptRatePredictor: raw linear proj over [hidden ; markov_prev_embedding(rank)]
377/// (with_markov=true on the q38 arm-a export) — output is the PRE-sigmoid scalar.
378pub struct ConfidenceHead {
379    pub w: Vec<f32>, // [in_dim]
380    pub b: f32,
381    pub in_dim: usize,
382    pub with_markov: bool,
383}
384
385impl ConfidenceHead {
386    /// Host dot: the PRE-sigmoid accept score for one draft slot. `hidden` = the
387    /// drafter output row the slot is harvested from (the same row its logits use);
388    /// `emb` = the markov `w1` row of the slot's PREVIOUS chain token (required iff
389    /// `with_markov`) — the exact input contract the parity gate pins (prev ids =
390    /// `[anchor, chain[..nd-1]]`, dspark_q38_parity.rs stage 5).
391    pub fn raw_score(&self, hidden: &[f32], emb: Option<&[f32]>) -> f32 {
392        let mut acc = self.b;
393        for (w, x) in self.w.iter().zip(hidden) {
394            acc += w * x;
395        }
396        if self.with_markov {
397            let emb = emb.expect("with_markov confidence head scored without the markov embedding");
398            debug_assert_eq!(hidden.len() + emb.len(), self.in_dim);
399            for (w, x) in self.w[hidden.len()..].iter().zip(emb) {
400                acc += w * x;
401            }
402        } else {
403            debug_assert_eq!(hidden.len(), self.in_dim);
404        }
405        acc
406    }
407}
408
409pub struct MarkovHead {
410    pub w1_bf16: CudaSlice<u8>, // [V, rank] bf16 raw
411    pub w2: GpuTensor,          // [rank -> V] q8_0
412    pub rank: usize,
413    pub vocab: usize,
414}
415
416/// Draft-row harvest convention for DFlash-family block drafters
417/// (darklanes research/deepseek-flash-20260818/DSPARK-POSTMORTEM-20260820.md).
418///
419/// The DFlash and DSpark SpecForge training strategies supervise DIFFERENT rows of the
420/// same `[anchor, MASK x b-1]` block, so the row -> trunk-position mapping is a property
421/// of the CHECKPOINT's training strategy, not of the loader:
422///
423/// - **Dflash** (mask-fill; z-lab dflash / SpecForge `OnlineDFlashModel`): row k is
424///   trained to predict the token AT position anchor+k — "Labels: same-position
425///   prediction", `weight_mask *= (pos_in_block > 0)` excludes the anchor row
426///   (SpecForge `specforge/algorithms/common/dflash_family_model.py:453-472`).
427///   Drafts = rows 1..b-1; the anchor row's output is untrained.
428/// - **Dspark** (shifted; SpecForge `OnlineDSparkModel`, `training.strategy: dspark` —
429///   the q38 arm-a export): row k is trained to predict the token at anchor+k+1, ALL
430///   rows supervised INCLUDING the anchor row (`label_offsets = arange(1,
431///   block_size+1)`, `dflash_family_model.py:816`). sglang's DSPARK worker — the stack
432///   every arm-a bank number was measured on — harvests gamma = block_size drafts with
433///   the anchor row's output as draft 1 (verified on the v0.5.17 eval-pin tag:
434///   `dspark_components/dspark_draft.py:248,260,318`; `dspark_config.py:269`).
435///
436/// Mismatching the convention verifies every slot against a position the row was never
437/// trained for — the q38 accept collapse (2.9 -> 1.43) in the postmortem.
438#[derive(Clone, Copy, PartialEq, Eq, Debug)]
439pub enum DsparkHarvest {
440    /// mask-fill: drafts = rows 1..b-1, row k fills position anchor+k.
441    Dflash,
442    /// shifted: drafts = rows 0..b-1, row k predicts position anchor+k+1.
443    Dspark,
444}
445
446impl DsparkHarvest {
447    /// The served resolution: explicit `MEMRA_DSPARK_HARVEST={dflash|dspark}` wins
448    /// (unknown values REFUSE loudly — a typo silently reverting the convention would
449    /// re-open the postmortem's misalignment); UNSET defers to the CHECKPOINT's own
450    /// training-strategy census — the owner-ratified default flip (2026-08-20, after
451    /// B1 confirmed H1 interleaved ×5 on serving-class hardware: accept 1.38→2.41
452    /// agentic / 1.53→3.66 math, E2E ALL EXACT both arms). Strategy-keyed, not
453    /// env-keyed, per the B0 plan: a DSPARK-strategy export harvests shifted
454    /// (all-rows), a mask-fill export keeps the historical dflash arm byte-identical.
455    pub fn resolve(cfg: &DflashCfg) -> Self {
456        Self::resolve_value(
457            std::env::var("MEMRA_DSPARK_HARVEST").ok().as_deref(),
458            cfg.strategy_dspark,
459        )
460    }
461
462    pub fn resolve_value(v: Option<&str>, strategy_dspark: bool) -> Self {
463        match v {
464            None | Some("") => {
465                if strategy_dspark {
466                    DsparkHarvest::Dspark
467                } else {
468                    DsparkHarvest::Dflash
469                }
470            }
471            set => Self::from_env_value(set),
472        }
473    }
474
475    /// ENV-ONLY parser (no checkpoint census): unset = `Dflash`, the historical arm.
476    /// Kept for the explicit-value path of [`Self::resolve_value`] and the seam tests;
477    /// round arms resolve through [`Self::resolve`] so the default stays strategy-keyed.
478    pub fn from_env_value(v: Option<&str>) -> Self {
479        match v {
480            None | Some("") | Some("dflash") => DsparkHarvest::Dflash,
481            Some("dspark") => DsparkHarvest::Dspark,
482            Some(other) => panic!(
483                "MEMRA_DSPARK_HARVEST={other}: unknown harvest convention (dflash|dspark); \
484                 refusing — a wrong convention verifies every draft slot against a position \
485                 the drafter row was not trained for (DSPARK-POSTMORTEM-20260820.md)"
486            ),
487        }
488    }
489
490    /// Resolve the harvest convention for a LOADED drafter — FAMILY-keyed first, then
491    /// STRATEGY-keyed (v0.100 train merge of the two ratified keyings):
492    /// - DFlash2 is a mask-fill-family drafter by construction (reference
493    ///   `dflash_generate` harvests rows `1-verify_size:`; the card says "block size 8
494    ///   (7 draft tokens per verification step)" — DFLASH2-EVAL-20260820.md §3). An env
495    ///   value that CONTRADICTS the census REFUSES rather than silently re-keying the
496    ///   round.
497    /// - Every other checkpoint rides [`Self::resolve_value`]: explicit env wins (typos
498    ///   refuse loudly), unset defers to the checkpoint's own training-strategy census
499    ///   (the owner-ratified 2026-08-20 default flip).
500    pub fn for_draft(draft: &DflashDraft) -> Self {
501        Self::for_family_value(
502            draft.dflash2.is_some(),
503            std::env::var("MEMRA_DSPARK_HARVEST").ok().as_deref(),
504            draft.cfg.strategy_dspark,
505        )
506    }
507
508    pub fn for_family_value(is_dflash2: bool, env: Option<&str>, strategy_dspark: bool) -> Self {
509        if is_dflash2 {
510            if env == Some("dspark") {
511                panic!(
512                    "MEMRA_DSPARK_HARVEST=dspark with a DFlash2 checkpoint: DFlash2 \
513                     is mask-fill (b-1 drafts, anchor row is not a draft — reference \
514                     dflash_generate rows 1-verify_size:); the shifted harvest would \
515                     verify every slot one position early. Refusing (census-keyed, \
516                     not env-keyed)."
517                );
518            }
519            return DsparkHarvest::Dflash;
520        }
521        Self::resolve_value(env, strategy_dspark)
522    }
523
524    /// Manifest/serialized name (the oracle geometry manifest's `harvest` field).
525    pub fn name(self) -> &'static str {
526        match self {
527            DsparkHarvest::Dflash => "dflash",
528            DsparkHarvest::Dspark => "dspark",
529        }
530    }
531
532    pub fn from_name(v: &str) -> Option<Self> {
533        match v {
534            "dflash" => Some(DsparkHarvest::Dflash),
535            "dspark" => Some(DsparkHarvest::Dspark),
536            _ => None,
537        }
538    }
539
540    /// First drafter OUTPUT row consumed as a draft candidate.
541    pub fn first_row(self) -> usize {
542        match self {
543            DsparkHarvest::Dflash => 1,
544            DsparkHarvest::Dspark => 0,
545        }
546    }
547
548    /// Drafted tokens harvested per round from a `b`-row block.
549    pub fn n_drafts(self, b: usize) -> usize {
550        match self {
551            DsparkHarvest::Dflash => b - 1,
552            DsparkHarvest::Dspark => b,
553        }
554    }
555
556    /// The position offset (relative to the round anchor at the block's row 0) that
557    /// drafter output row `row` is TRAINED to predict under this convention.
558    pub fn trained_offset_of_row(self, row: usize) -> usize {
559        match self {
560            DsparkHarvest::Dflash => row,
561            DsparkHarvest::Dspark => row + 1,
562        }
563    }
564}
565
566/// Checkpoint training-strategy census over the raw config.json text (the loader's
567/// minimal-extractor idiom — no json dep in-tree). TRUE iff the export declares the
568/// DSPARK strategy: `architectures` naming a DSpark model class (`Qwen3DSparkModel`,
569/// the SpecForge OnlineDSparkModel export form) or `dflash_config.projector_type ==
570/// "dspark"`. z-lab / OnlineDFlashModel mask-fill exports carry neither signal. Pure,
571/// so the census is testable against config fragments without files.
572pub fn dspark_strategy_census(txt: &str) -> bool {
573    let arch = txt
574        .find("\"architectures\"")
575        .and_then(|i| {
576            let rest = &txt[i..];
577            let a = rest.find('[')?;
578            let b = rest.find(']')?;
579            Some(rest[a..b].contains("DSpark"))
580        })
581        .unwrap_or(false);
582    let proj = txt
583        .find("\"projector_type\"")
584        .map(|i| {
585            let rest = &txt[i..];
586            let after = rest.find(':').map(|c| &rest[c + 1..]).unwrap_or("");
587            after.trim_start().starts_with("\"dspark\"")
588        })
589        .unwrap_or(false);
590    arch || proj
591}
592
593/// Accepted-prefix length of a round's candidates against the trunk's verify argmaxes:
594/// `cand[0]` = the round anchor (already decided), `cand[1..]` = the drafts;
595/// `vam[j]` = the trunk's argmax prediction for position anchor+j+1. Returns m =
596/// number of accepted drafts (`cand[1..=m]` committed, `vam[m]` becomes the next
597/// anchor). Pure so the harvest-alignment fixture can exercise it CPU-side.
598pub fn dspark_accept_prefix(cand: &[u32], vam: &[u32], vt: usize) -> usize {
599    let mut m = 0usize;
600    while m < vt - 1 && cand[m + 1] == vam[m] {
601        m += 1;
602    }
603    m
604}
605
606/// Verify-window policy for the dspark round (H4, DSPARK-POSTMORTEM-20260820.md §3).
607///
608/// B2 measured the structural fork: the fixed full-block window (vt=8) buys 95–100%
609/// of the sglang accept bank but LOSES wall speed to the reactive ladder everywhere
610/// except math — at 0.2–0.5 slot rates, full-block verify pays 5–6 empty rows per
611/// round. The confidence policy is the mechanism both leading engines schedule with
612/// (sglang v0.5.16 `dspark_planner.py` cumprod survival; vLLM #47808): size EACH
613/// round's window from the drafter's own trained accept-rate head, so windows open
614/// on confident streaks (math/code) and shrink on bursty text without a 4-round
615/// ladder climb.
616#[derive(Clone, Copy, PartialEq, Debug)]
617pub enum DsparkVtPolicy {
618    /// The shipped reactive ladder: `vt = (m+2).clamp(3, vt_cap)` per round
619    /// (`MEMRA_DFLASH_ADAPT=0` pins vt at `vt_cap` = the fixed-window arm).
620    Ladder,
621    /// `MEMRA_DSPARK_VT=confidence`: per-round window from cumprod survival of the
622    /// confidence head's sigmoid scores, thresholded at `tau`
623    /// (`MEMRA_DSPARK_VT_TAU`, default 0.5). Raw sigmoid — no STS sidecar
624    /// calibration exists for this export; the postmortem names this the starting
625    /// policy.
626    Confidence { tau: f32 },
627    /// `MEMRA_DSPARK_VT=confidence-slot` (owner directive, 2026-08-20: "take only
628    /// high confidence offers"): submit only the longest draft PREFIX whose every
629    /// slot clears `tau` on its own sigmoid — the low-confidence tail never enters
630    /// verify. Same tau env. vs `Confidence`: if the head's per-row score is the
631    /// MARGINAL accept probability (it already sinks with depth), cumprod survival
632    /// double-counts the decay and over-truncates; if it is the CONDITIONAL,
633    /// per-slot under-truncates. Which statistic the q38 head emits is empirical —
634    /// both arms ride the A/B.
635    ConfidenceSlot { tau: f32 },
636}
637
638impl DsparkVtPolicy {
639    /// The served resolution: explicit `MEMRA_DSPARK_VT={ladder|confidence|
640    /// confidence-slot}` wins (unknown values REFUSE loudly — a typo silently
641    /// reverting the window policy would invalidate an A/B without a trace); UNSET
642    /// defaults to **`confidence-slot` at τ = `MEMRA_DSPARK_VT_TAU` (default 0.5)** —
643    /// the owner-ratified H4 flip (2026-08-20; cell 2's 4-arm A/B ×5 + cell 3's tau
644    /// ladder put the knee at τ=.5 for the slot arm: 94–98% of the fixed-8 accept bank
645    /// at wall ≥ the reactive ladder, exactness 11/11 ALL EXACT). Census-keyed per the
646    /// capacity-keyed-defaults law: a checkpoint WITHOUT an accept-rate head has no
647    /// signal to schedule with, so unset-env resolves to the ladder there (loudly, at
648    /// load) instead of panicking on a default; `MEMRA_DFLASH_ADAPT=0` (an explicit
649    /// fixed-window request) also keeps the ladder-family arm.
650    pub fn resolve(has_confidence_head: bool) -> Self {
651        Self::resolve_value(
652            std::env::var("MEMRA_DSPARK_VT").ok().as_deref(),
653            std::env::var("MEMRA_DSPARK_VT_TAU").ok().as_deref(),
654            std::env::var("MEMRA_DFLASH_ADAPT").ok().as_deref(),
655            has_confidence_head,
656        )
657    }
658
659    pub fn resolve_value(
660        vt: Option<&str>,
661        tau: Option<&str>,
662        adapt: Option<&str>,
663        has_confidence_head: bool,
664    ) -> Self {
665        match vt {
666            None | Some("") => {
667                if adapt == Some("0") || !has_confidence_head {
668                    DsparkVtPolicy::Ladder
669                } else {
670                    // The ratified default rides the SAME tau parse as the explicit
671                    // arm (a bad MEMRA_DSPARK_VT_TAU refuses, never silently ignored).
672                    Self::from_env_value(Some("confidence-slot"), tau, adapt)
673                }
674            }
675            set => Self::from_env_value(set, tau, adapt),
676        }
677    }
678
679    /// ENV-ONLY parser (no head census): unset = `Ladder`. Kept for the explicit-value
680    /// path of [`Self::resolve_value`] and the policy-gate tests; round arms resolve
681    /// through [`Self::resolve`] so the default stays head-census-keyed.
682    pub fn from_env_value(vt: Option<&str>, tau: Option<&str>, adapt: Option<&str>) -> Self {
683        match vt {
684            None | Some("") | Some("ladder") => DsparkVtPolicy::Ladder,
685            Some(mode @ ("confidence" | "confidence-slot")) => {
686                if adapt == Some("0") {
687                    panic!(
688                        "MEMRA_DSPARK_VT={mode} together with MEMRA_DFLASH_ADAPT=0 is \
689                         contradictory (a pinned fixed window vs a per-round confidence \
690                         window); unset one — refuse-on-ambiguity"
691                    );
692                }
693                let tau = tau
694                    .map(|t| {
695                        t.parse::<f32>()
696                            .unwrap_or_else(|_| panic!("MEMRA_DSPARK_VT_TAU={t}: not a float"))
697                    })
698                    .unwrap_or(0.5);
699                assert!(
700                    tau > 0.0 && tau < 1.0,
701                    "MEMRA_DSPARK_VT_TAU={tau}: confidence threshold must be in (0,1)"
702                );
703                if mode == "confidence" {
704                    DsparkVtPolicy::Confidence { tau }
705                } else {
706                    DsparkVtPolicy::ConfidenceSlot { tau }
707                }
708            }
709            Some(other) => panic!(
710                "MEMRA_DSPARK_VT={other}: unknown verify-window policy \
711                 (ladder|confidence|confidence-slot); refusing — a wrong policy \
712                 silently reverts the H4 arm (DSPARK-POSTMORTEM-20260820.md)"
713            ),
714        }
715    }
716
717    /// True for every head-scheduled arm (the loops gate the head requirement and
718    /// the embedding stash on this).
719    pub fn is_confidence(&self) -> bool {
720        !matches!(self, DsparkVtPolicy::Ladder)
721    }
722
723    /// Size this round's verify window from the head's pre-sigmoid slot scores.
724    /// `None` under the ladder (the caller keeps its carried vt).
725    pub fn size_window(&self, raws: &[f32], vt_cap: usize) -> Option<usize> {
726        match *self {
727            DsparkVtPolicy::Ladder => None,
728            DsparkVtPolicy::Confidence { tau } => Some(dspark_confidence_vt(raws, tau, vt_cap)),
729            DsparkVtPolicy::ConfidenceSlot { tau } => {
730                Some(dspark_slot_confidence_vt(raws, tau, vt_cap))
731            }
732        }
733    }
734}
735
736/// H4 window sizing (the sglang-planner/vLLM-#47808 mechanism, thresholded): `raws[k]`
737/// = the accept-rate head's PRE-sigmoid score for draft slot k+1; survival
738/// `S_k = prod_{j<=k} sigmoid(raws[j])`; the window keeps leading slots while
739/// `S_k >= tau`. Returns `vt` = 1 (anchor) + kept drafts, clamped to `[2, vt_cap]`:
740/// the draft forward is already paid, so at least one draft rides every verify — one
741/// extra verify row costs less than a guaranteed empty round. Pure, so the policy's
742/// knee is testable CPU-side like `dspark_accept_prefix`.
743pub fn dspark_confidence_vt(raws: &[f32], tau: f32, vt_cap: usize) -> usize {
744    let mut surv = 1.0f32;
745    let mut kept = 0usize;
746    for &r in raws {
747        surv *= 1.0 / (1.0 + (-r).exp());
748        if surv < tau {
749            break;
750        }
751        kept += 1;
752    }
753    (1 + kept).clamp(2, vt_cap.max(2))
754}
755
756/// Owner-directive arm (2026-08-20, "take only high confidence offers"): keep the
757/// longest draft PREFIX whose EVERY slot clears `tau` on its own sigmoid — truncate
758/// at the first sub-threshold slot, so the low-confidence tail (B2 measured 0.2–0.5
759/// slot rates at depth) never enters verify. Prefix truncation is forced by the
760/// accept rule anyway (`dspark_accept_prefix` stops at the first miss — a kept slot
761/// after a dropped one could never commit); the policy fork vs `dspark_confidence_vt`
762/// is only the stopping statistic (per-slot marginal vs cumulative survival). Same
763/// floor/cap contract.
764pub fn dspark_slot_confidence_vt(raws: &[f32], tau: f32, vt_cap: usize) -> usize {
765    let mut kept = 0usize;
766    for &r in raws {
767        let p = 1.0 / (1.0 + (-r).exp());
768        if p < tau {
769            break;
770        }
771        kept += 1;
772    }
773    (1 + kept).clamp(2, vt_cap.max(2))
774}
775
776// ================= SAMPLED ADMISSION (T>0) — lane/dspark-sampled-admission-20260820 =====
777// True rejection sampling for the dspark route (mystery A of DSPARK-POSTMORTEM-20260820):
778// draft slot j is DRAWN from a recorded proposal distribution q_j, the trunk's verify column
779// arbitrates with the Leviathan/Chen rule (accept x_j while u_j*q_j(x_j) < p_j(x_j); on
780// reject resample from norm(max(0, p-q)); on full accept the bonus ~ p at the last column),
781// so the committed stream's distribution equals trunk-only sampling from the FILTERED target
782// p — the same contract the frspec/MTP route ships (spec.rs sampled accept walk; kernels
783// oracled by sample_check). T==0/None keeps every greedy path byte-identical (the exactness
784// instrument and the kill-switch are the same code).
785//
786// Two proposal families, each recording the TRUE distribution its drafts were drawn from:
787// - Rows (dspark/dflash strategy checkpoints): per-slot FILTERED softmax of the draft-logits
788//   row — markov-corrected in place when the head is present (the sglang DSPARK worker's
789//   "chain rejection sampling over markov-corrected draft probs"), plain rows otherwise
790//   (the z-lab reference's independent-row T>0 arm).
791// - Selector (DFlash2): the candidate-path selector's per-slot softmax over its top-k
792//   candidate set at temperature ONLY — the reference applies no top-k/top-p to selector
793//   scores (z-lab model.py `CandidateSelector.select`: `_sampling_probs(scores, temperature)`
794//   with default filters) — with the candidate-set residual (`scatter_add_` of -q, clamped).
795
796/// Rejection-sampling prefix walk: accept draft j while `u_j * q_j < p_j` (strict, f64 —
797/// byte-identical to the frspec accept test). `p`/`q` are the FILTERED target/proposal
798/// probabilities of the drafted tokens; `u` the per-slot uniforms. Pure so the composition
799/// gate can pin the rule on CPU.
800pub fn rejection_accept_len(p: &[f32], q: &[f32], u: &[f32]) -> usize {
801    assert!(
802        q.len() >= p.len() && u.len() >= p.len(),
803        "accept walk shape"
804    );
805    let mut m = 0usize;
806    while m < p.len() && (u[m] as f64) * (q[m] as f64) < p[m] as f64 {
807        m += 1;
808    }
809    m
810}
811
812/// Sampled selector walk (reference `CandidateSelector.select`, temperature>0 arm): per
813/// draft slot the pair scores over the top-k candidate set become a softmax at `temp`
814/// (temperature ONLY — the reference passes no top-k/top-p here), one uniform draws the
815/// candidate (fixed-order CDF walk), and the CHOSEN candidate seeds the next slot exactly
816/// like the greedy chain. Returns (path, q_chosen[nd], q_rows[nd*top_k]) — q_rows are the
817/// recorded per-slot candidate probabilities (the residual's `scatter_add_` input), and
818/// q_chosen[j] == q_rows[j*top_k + chosen_j] is the accept-test q. Pure (uniforms injected)
819/// so the T->0 limit, the chain conditioning, and the recorded-q contract are CPU-gateable.
820#[allow(clippy::too_many_arguments)]
821pub fn dflash2_walk_sampled(
822    pred_codebook: &[u8],
823    succ_codebook: &[u8],
824    vocab: usize,
825    rank: usize,
826    top_k: usize,
827    unary: &[f32],
828    cand: &[u32],
829    hproj: &[f32],
830    anchor: u32,
831    nd: usize,
832    temp: f32,
833    uniforms: &mut dyn FnMut() -> f32,
834) -> (Vec<u32>, Vec<f32>, Vec<f32>) {
835    assert!(
836        temp > 0.0,
837        "sampled walk is the T>0 arm; T=0 is walk_greedy"
838    );
839    let (kk, r) = (top_k, rank);
840    assert_eq!(unary.len(), nd * kk, "walk: unary shape");
841    assert_eq!(cand.len(), nd * kk, "walk: candidate shape");
842    assert_eq!(hproj.len(), nd * r, "walk: hidden-projection shape");
843    let mut path = Vec::with_capacity(nd);
844    let mut q_chosen = Vec::with_capacity(nd);
845    let mut q_rows = Vec::with_capacity(nd * kk);
846    let mut prev = anchor;
847    for p in 0..nd {
848        assert!(
849            (prev as usize) < vocab,
850            "walk: predecessor token {prev} outside codebook vocab {vocab}"
851        );
852        let pr = cb_row(pred_codebook, prev as usize, r);
853        let hp = &hproj[p * r..(p + 1) * r];
854        let gate: Vec<f32> = pr.iter().zip(hp).map(|(a, b)| a * b).collect();
855        let mut scores = vec![0f32; kk];
856        for (k, s) in scores.iter_mut().enumerate() {
857            let c = cand[p * kk + k] as usize;
858            assert!(c < vocab, "walk: candidate {c} outside codebook vocab");
859            let sr = cb_row(succ_codebook, c, r);
860            let mut acc = unary[p * kk + k];
861            for j in 0..r {
862                acc += gate[j] * sr[j];
863            }
864            *s = acc;
865        }
866        // softmax over the candidate set at temp (f64 internals; recorded probs are the
867        // f32 values the CDF walk actually samples from — recorded q IS the proposal).
868        let mx = scores.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
869        let mut z = 0f64;
870        let ex: Vec<f64> = scores
871            .iter()
872            .map(|&s| {
873                let e0 = (((s - mx) / temp) as f64).exp();
874                z += e0;
875                e0
876            })
877            .collect();
878        let probs: Vec<f32> = ex.iter().map(|&e0| (e0 / z) as f32).collect();
879        let u = uniforms() as f64;
880        let mut acc = 0f64;
881        // fp-residue fallback (u >= f32-accumulated mass, ~2^-24 events): the max-prob
882        // candidate — never a zero-prob one (host_u01's range includes 1.0 exactly).
883        let mut bi = probs
884            .iter()
885            .enumerate()
886            .max_by(|a, b| a.1.total_cmp(b.1))
887            .map(|(k, _)| k)
888            .unwrap_or(0);
889        for (k, &pk) in probs.iter().enumerate() {
890            acc += pk as f64;
891            if u < acc {
892                bi = k;
893                break;
894            }
895        }
896        prev = cand[p * kk + bi];
897        path.push(prev);
898        q_chosen.push(probs[bi]);
899        q_rows.extend_from_slice(&probs);
900    }
901    (path, q_chosen, q_rows)
902}
903
904/// `dflash2_propose_sampled`'s wire: (path, q_chosen, candidate ids, q_rows).
905pub(crate) type Dflash2SampledProposal = (Vec<u32>, Vec<f32>, Vec<u32>, Vec<f32>);
906
907/// Per-round proposal record for the sampled dspark round — everything the rejection
908/// walk needs to evaluate the TRUE per-slot proposal distribution q.
909pub(crate) enum DsparkDraftSample {
910    /// q lives in the round's draft-logits buffer `dl` (markov-biased in place when the
911    /// head is armed); per-slot FILTERED stats retained device-contiguous for the accept
912    /// gather + host-mirrored for the reject-slot residual.
913    Rows {
914        th: CudaSlice<f32>,          // [nd] filter thresholds (e-units), slot-indexed
915        z: CudaSlice<f32>,           // [nd] renorm masses
916        stats: Vec<(f32, f32, f32)>, // host (mx, th, z) per slot
917    },
918    /// DFlash2 candidate-path selector: q is the recorded candidate-set distribution.
919    Selector {
920        cand: Vec<u32>,     // [nd*top_k] candidate ids
921        q_rows: Vec<f32>,   // [nd*top_k] per-slot candidate probs
922        q_chosen: Vec<f32>, // [nd] prob of the drawn candidate (accept-test q)
923        top_k: usize,
924    },
925}
926
927/// The sampled round's verify+accept: filtered p gathered from the trunk's verify logits
928/// (row j arbitrates draft `cand[j+1]` — the position mapping the greedy prefix walk uses),
929/// the rejection walk over host uniforms, then `next` = bonus (full accept: filtered-Gumbel
930/// from the LAST verify row with its OWN fresh stats — the sampfix-20260805 law: that row is
931/// one past the gathered set) or the residual sample at the reject slot (family-keyed q:
932/// full-row logits for Rows, sparse candidate-set probs for Selector). Returns (m, next) —
933/// the exact (accepted-drafts, next-anchor) contract of the greedy `dspark_accept_prefix` +
934/// `vam[m]` pair, so both round bodies commit identically downstream.
935///
936/// PENALIZED SAMPLED (lane/dspark-penalized-sampled-20260821): when the request carries
937/// non-identity penalties, the vt verify columns are materialized ONCE into a penalized
938/// copy where row j's Keskar pass runs over `pen_win ++ cand[1..=j]` (window-capped) —
939/// the tokens committed before position j ON EVERY PATH WHERE ROW j IS CONSULTED,
940/// same-round accepts included (row j is only read when drafts 1..j were all accepted,
941/// i.e. exactly when `cand[1..=j]` is the committed prefix; the bonus row vt-1 is only
942/// read on full accept, when all nq drafts are committed). Every p read — the batched
943/// stats+gather, the bonus draw, the reject-slot residual column — points at that buffer,
944/// so p is the true penalized per-state target and the committed stream equals plain
945/// penalized sampling (the composition gate's penalty fixtures, self-hit included).
946/// q stays the RECORDED proposal the drafts were actually drawn from (unpenalized):
947/// rejection sampling is unbiased for ANY proposal with `u·q(x) < p(x)` + residual
948/// `norm(max(0, p−q))`; penalizing q would only buy acceptance overlap and would cost an
949/// evolving-history pass inside the sync-free device chain. `pen_win` is the caller's
950/// session window ALREADY trimmed to `min(penalty_last_n, PEN_WINDOW_MAX)` (empty when
951/// penalties are off — the unpenalized path is byte-untouched).
952#[allow(clippy::too_many_arguments)]
953pub(crate) fn dspark_accept_sampled(
954    e: &Engine,
955    tlogits: &CudaSlice<f32>,
956    cand: &[u32],
957    vt: usize,
958    n_vocab: usize,
959    dl: &CudaSlice<f32>,
960    prop: &DsparkDraftSample,
961    sp: &crate::spec::SpecSampling,
962    pen_win: &[u32],
963    sctr: &mut u32,
964    uctr: &mut u32,
965) -> Result<(usize, u32), Box<dyn std::error::Error>> {
966    let nq = vt - 1; // drafts under this round's verify window
967    debug_assert!(nq >= 1 && cand.len() > nq, "sampled accept shape");
968    // --- penalized verify columns (identity penalties: no copy, no launch, raw tlogits) ---
969    let pen_on = sp.pen_on();
970    let ptl: Option<CudaSlice<f32>> = if pen_on {
971        let win = sp.penalty_last_n.min(crate::spec::PEN_WINDOW_MAX);
972        debug_assert!(pen_win.len() <= win, "pen_win must arrive pre-trimmed");
973        let mut hist: Vec<u32> = Vec::with_capacity(pen_win.len() + nq);
974        hist.extend_from_slice(pen_win);
975        hist.extend_from_slice(&cand[1..=nq]); // drafted tokens: row j reads the first j
976        let hd = e.htod_u32_v(&hist)?;
977        let mut buf = e.clone_dtod(tlogits)?;
978        e.penalize_logits_rows_inc(
979            &mut buf,
980            &hd,
981            pen_win.len(),
982            sp.penalty_repeat,
983            sp.penalty_freq,
984            sp.penalty_present,
985            n_vocab,
986            vt,
987            win,
988        )?;
989        Some(buf)
990    } else {
991        None
992    };
993    let p_src: &CudaSlice<f32> = ptl.as_ref().unwrap_or(tlogits);
994    // --- filtered p at the drafted tokens (one batched stats + gather over rows 0..nq-1) ---
995    let rows: Vec<i32> = (0..nq as i32).collect();
996    let ids: Vec<u32> = cand[1..=nq].to_vec();
997    let rowsd = e.htod_i32(&rows)?;
998    let idsd = e.htod_u32_v(&ids)?;
999    let (mut pth, mut pz, mut pmx) = (e.zeros(nq)?, e.zeros(nq)?, e.zeros(nq)?);
1000    e.filter_stats(
1001        p_src, n_vocab, &rowsd, &mut pth, &mut pz, &mut pmx, n_vocab, nq, sp.temp, sp.top_k,
1002        sp.top_p, sp.min_p,
1003    )?;
1004    let mut pj_d = e.zeros(nq)?;
1005    e.softmax_gather_filtered(
1006        p_src, n_vocab, &idsd, &rowsd, &pth, &pz, &mut pj_d, n_vocab, nq, sp.temp,
1007    )?;
1008    let pj = e.dtoh(&pj_d)?;
1009    let (pthv, pzv, pmxv) = (e.dtoh(&pth)?, e.dtoh(&pz)?, e.dtoh(&pmx)?);
1010    // --- q at the drafted tokens (the recorded proposal distribution) ---
1011    let qj: Vec<f32> = match prop {
1012        DsparkDraftSample::Rows { th, z, .. } => {
1013            // dl row j is draft j's (bias-corrected) logits row; th/z are slot-indexed, and
1014            // rows 0..nq-1 index both the buffer rows and the stat pairs.
1015            let mut qd = e.zeros(nq)?;
1016            e.softmax_gather_filtered(
1017                dl, n_vocab, &idsd, &rowsd, th, z, &mut qd, n_vocab, nq, sp.temp,
1018            )?;
1019            e.dtoh(&qd)?
1020        }
1021        DsparkDraftSample::Selector { q_chosen, .. } => q_chosen[..nq].to_vec(),
1022    };
1023    // --- the rejection walk ---
1024    let mut us = Vec::with_capacity(nq);
1025    for _ in 0..nq {
1026        us.push(crate::spec::host_u01(sp.seed, *uctr));
1027        *uctr = uctr.wrapping_add(1);
1028    }
1029    let m = rejection_accept_len(&pj[..nq], &qj[..nq], &us);
1030    // --- next anchor: bonus or residual ---
1031    let next = if m == nq {
1032        // FULL ACCEPT: bonus ~ filtered p at verify row vt-1 — fresh stats for THIS row.
1033        // Under penalties p_src row vt-1 carries the FULL drafted block in its window
1034        // (all nq drafts are committed on this path — the "drafted token penalizes its
1035        // own successor" case the composition gate's self-hit fixture pins).
1036        let rows_l = e.htod_i32(&[(vt - 1) as i32])?;
1037        let (mut th1, mut z1, mut mx1) = (e.zeros(1)?, e.zeros(1)?, e.zeros(1)?);
1038        e.filter_stats(
1039            p_src, n_vocab, &rows_l, &mut th1, &mut z1, &mut mx1, n_vocab, 1, sp.temp, sp.top_k,
1040            sp.top_p, sp.min_p,
1041        )?;
1042        let mut pb = e.zeros(n_vocab)?;
1043        e.gumbel_perturb_filtered_col(
1044            p_src,
1045            vt - 1,
1046            &mut pb,
1047            n_vocab,
1048            sp.seed,
1049            *sctr,
1050            sp.temp,
1051            &mx1,
1052            &th1,
1053            0,
1054        )?;
1055        *sctr = sctr.wrapping_add(1);
1056        let td = e.argmax_token_device(&pb, n_vocab)?;
1057        e.dtoh_u32_one(&td)?
1058    } else {
1059        // REJECT at slot m: token ~ norm(max(0, p_m - q_m)); p row m's stats come from the
1060        // gathered set (rows 0..nq-1 cover every reject slot). Under penalties the column
1061        // copy MUST come from p_src (the penalized buffer) — a raw-tlogits residual is the
1062        // composition gate's "residual reads unpenalized p" tooth.
1063        let mut col = e.zeros(n_vocab)?;
1064        e.copy_view_into(
1065            &mut col,
1066            0,
1067            &p_src.slice(m * n_vocab..(m + 1) * n_vocab),
1068            n_vocab,
1069        )?;
1070        let p_stats = (pmxv[m], pthv[m], pzv[m]);
1071        let mut tok_d = e.alloc_u32_zeroed(1)?;
1072        let sc = *sctr;
1073        *sctr = sctr.wrapping_add(1);
1074        match prop {
1075            DsparkDraftSample::Rows { stats, .. } => {
1076                let mut qbuf = e.zeros(n_vocab)?;
1077                e.copy_view_into(
1078                    &mut qbuf,
1079                    0,
1080                    &dl.slice(m * n_vocab..(m + 1) * n_vocab),
1081                    n_vocab,
1082                )?;
1083                e.residual_sample_filtered(
1084                    &col,
1085                    Some(&qbuf),
1086                    n_vocab,
1087                    sp.temp,
1088                    sp.seed,
1089                    sc,
1090                    p_stats,
1091                    stats[m],
1092                    &mut tok_d,
1093                )?;
1094            }
1095            DsparkDraftSample::Selector {
1096                cand: cids,
1097                q_rows,
1098                top_k,
1099                ..
1100            } => {
1101                let k = *top_k;
1102                let ids_m = e.htod_u32_v(&cids[m * k..(m + 1) * k])?;
1103                let qs_m = e.htod(&q_rows[m * k..(m + 1) * k])?;
1104                e.residual_sample_sparse_q(
1105                    &col, &ids_m, &qs_m, k, n_vocab, sp.temp, sp.seed, sc, p_stats, &mut tok_d,
1106                )?;
1107            }
1108        }
1109        e.dtoh_u32(&tok_d)?[0]
1110    };
1111    Ok((m, next))
1112}
1113
1114/// Clip door for the DFlash2 windowed round attention (lane/dflash2-longctx, §10.6(c)).
1115/// Default ON: the lo-clipped kernel — byte-identical output (kernel_check
1116/// `sdpa_naive_w_lo`), O(window) key scan, and no T_kv*4-byte shared-mem launch bound, so
1117/// the route survives past ~12k ctx (GATES-SMOKE-20260821 B2: DriverError(
1118/// CUDA_ERROR_INVALID_VALUE) at ctx 16,571/30,157, last success 9,510).
1119/// MEMRA_DFLASH2_SDPA_CLIP=0 = the legacy full-scan kernel byte-for-byte — the rollback
1120/// seam and the long-ctx gate's crash-reproduction arm.
1121fn dflash2_sdpa_clip_on() -> bool {
1122    std::env::var("MEMRA_DFLASH2_SDPA_CLIP")
1123        .map(|v| v != "0")
1124        .unwrap_or(true)
1125}
1126
1127/// The DFlash2 round attention over the non-causal symmetric window: one seam for both the
1128/// first-light (`forward_block`) and cached (`forward_round`) arms, dispatching the clipped
1129/// kernel unless the rollback door is thrown.
1130///
1131/// `floor` (lane/spec-exclusions-20260902): the KV's first EXISTING ctx row
1132/// (`DflashKv::floor`, 0 on every cold-primed or full-tail KV). A COLD-DRAFTER session
1133/// (`DflashKv::new_cold_at`) or a short-tail import owns rows only from `floor` up; the
1134/// clipped kernel raises its window floor to it and the drafter attends a shorter context,
1135/// exactly the program a shorter prompt runs. The legacy full-scan kernel has no floor arm
1136/// (it would score the zero rows below the floor at e^0 each and dilute the real context),
1137/// so a binding floor under `MEMRA_DFLASH2_SDPA_CLIP=0` refuses by name instead of drafting
1138/// silently worse — the cold-drafter constructors refuse the same combination up front.
1139#[allow(clippy::too_many_arguments)]
1140fn d2_windowed_attn(
1141    e: &Engine,
1142    q: &CudaSlice<f32>,
1143    k: &CudaSlice<f32>,
1144    v: &CudaSlice<f32>,
1145    attn: &mut CudaSlice<f32>,
1146    hd: usize,
1147    nh: usize,
1148    nkv: usize,
1149    t: usize,
1150    t_kv: usize,
1151    scale: f32,
1152    c: &DflashCfg,
1153    floor: usize,
1154) -> Result<(), Box<dyn std::error::Error>> {
1155    if dflash2_sdpa_clip_on() {
1156        e.sdpa_naive_w_lo(
1157            q,
1158            k,
1159            v,
1160            attn,
1161            hd,
1162            nh,
1163            nkv,
1164            t,
1165            t_kv,
1166            scale,
1167            false,
1168            c.sliding_window,
1169            floor,
1170        )
1171    } else {
1172        if floor > 0 {
1173            return Err(
1174                "DFlash2 round attention: the drafter KV carries a context floor (cold-drafter \
1175                 or short-tail import) and MEMRA_DFLASH2_SDPA_CLIP=0 selects the full-scan \
1176                 kernel, which has no floor arm; unset the clip rollback or serve plain"
1177                    .into(),
1178            );
1179        }
1180        e.sdpa_naive_w(
1181            q,
1182            k,
1183            v,
1184            attn,
1185            hd,
1186            nh,
1187            nkv,
1188            t,
1189            t_kv,
1190            scale,
1191            false,
1192            c.sliding_window,
1193        )
1194    }
1195}
1196
1197fn bf16_to_f32(bytes: &[u8]) -> Vec<f32> {
1198    bytes
1199        .chunks_exact(2)
1200        .map(|c| f32::from_bits((u16::from_le_bytes([c[0], c[1]]) as u32) << 16))
1201        .collect()
1202}
1203
1204fn validate_dflash_tensor(
1205    name: &str,
1206    info: &memra_gguf::safetensors::StInfo,
1207    expected: &[u64],
1208) -> Result<(), String> {
1209    if info.dtype != "BF16" {
1210        return Err(format!(
1211            "DFlash tensor {name} has dtype {}, expected BF16",
1212            info.dtype
1213        ));
1214    }
1215    let found = info.ne();
1216    if found != expected {
1217        return Err(format!(
1218            "DFlash tensor {name} has shape {found:?}, expected {expected:?}"
1219        ));
1220    }
1221    Ok(())
1222}
1223
1224fn validate_dflash_attention_geometry(
1225    n_head: usize,
1226    n_kv: usize,
1227    head_dim: usize,
1228) -> Result<(), String> {
1229    if n_head == 0 || n_kv == 0 || head_dim == 0 || !n_head.is_multiple_of(n_kv) {
1230        return Err(format!(
1231            "DFlash attention geometry requires nonzero n_head divisible by n_kv; got n_head={n_head}, n_kv={n_kv}, head_dim={head_dim}"
1232        ));
1233    }
1234    n_head
1235        .checked_mul(head_dim)
1236        .ok_or("DFlash query-head geometry overflow")?;
1237    n_kv.checked_mul(head_dim)
1238        .ok_or("DFlash key/value-head geometry overflow")?;
1239    Ok(())
1240}
1241
1242fn validate_selector_top_k(top_k: usize, vocab: usize) -> Result<(), String> {
1243    if top_k == 0 || top_k > vocab {
1244        return Err(format!(
1245            "DFlash2 selector_top_k {top_k} is outside codebook vocabulary 1..={vocab}"
1246        ));
1247    }
1248    Ok(())
1249}
1250
1251fn validate_layer_layout(layer_sliding: &[bool], n_layer: usize) -> Result<(), String> {
1252    if layer_sliding.len() != n_layer {
1253        return Err(format!(
1254            "DFlash layer_types has {} entries, expected num_hidden_layers {n_layer}",
1255            layer_sliding.len()
1256        ));
1257    }
1258    Ok(())
1259}
1260
1261/// Host q8_0 encode (ggml block layout: [d f16][32 x i8] = 34B/32 vals). The drafter's
1262/// weights ride the dp4a fast path at 1.6GB resident (bf16 3.1GB + the 31B trunk OOM'd
1263/// 24GB; f32 6.2GB worse). Drafter quantization moves ACCEPTANCE only — verify exactness
1264/// is structural.
1265fn encode_q8_0(vals: &[f32]) -> Vec<u8> {
1266    let mut out = Vec::with_capacity(vals.len() / 32 * 34);
1267    for blk in vals.chunks_exact(32) {
1268        let amax = blk.iter().fold(0f32, |a, v| a.max(v.abs()));
1269        let d = amax / 127.0;
1270        let id = if d > 0.0 { 1.0 / d } else { 0.0 };
1271        let dh = half_from_f32(d);
1272        out.extend_from_slice(&dh.to_le_bytes());
1273        for &v in blk {
1274            out.push(((v * id).round().clamp(-127.0, 127.0)) as i8 as u8);
1275        }
1276    }
1277    out
1278}
1279
1280/// Host q4_0 encode (ggml: [d f16][16B packed nibbles] = 18B/32 vals; q = round(v/d)+8,
1281/// d = amax/-7 sign trick NOT used — plain amax/7? ggml uses d = max/-8 .. follow ggml:
1282/// d = amax / -8 when the max is negative-dominant; reference quantize_row_q4_0: d =
1283/// max(|v|)/-8 signed-max form). Implemented to match ggml quantize_row_q4_0_ref.
1284fn encode_q4_0(vals: &[f32]) -> Vec<u8> {
1285    let mut out = Vec::with_capacity(vals.len() / 32 * 18);
1286    for blk in vals.chunks_exact(32) {
1287        // ggml ref: pick the value with the LARGEST |v| (keeping sign), d = that / -8
1288        let mut amax = 0f32;
1289        let mut mx = 0f32;
1290        for &v in blk {
1291            if v.abs() > amax {
1292                amax = v.abs();
1293                mx = v;
1294            }
1295        }
1296        let d = mx / -8.0;
1297        let id = if d != 0.0 { 1.0 / d } else { 0.0 };
1298        out.extend_from_slice(&half_from_f32(d).to_le_bytes());
1299        for j in 0..16 {
1300            let x0 = (blk[j] * id + 8.5).clamp(0.0, 15.0) as u8;
1301            let x1 = (blk[j + 16] * id + 8.5).clamp(0.0, 15.0) as u8;
1302            out.push(x0 | (x1 << 4));
1303        }
1304    }
1305    out
1306}
1307
1308fn half_from_f32(v: f32) -> u16 {
1309    // f32 -> IEEE f16 (round-to-nearest-even; range of q8_0 d values is tame)
1310    let b = v.to_bits();
1311    let sign = ((b >> 16) & 0x8000) as u16;
1312    let exp = ((b >> 23) & 0xff) as i32 - 127 + 15;
1313    let man = b & 0x7fffff;
1314    if exp <= 0 {
1315        return sign;
1316    } // flush tiny d to zero
1317    if exp >= 31 {
1318        return sign | 0x7c00;
1319    } // inf (unreachable for sane d)
1320    let mut h = sign | ((exp as u16) << 10) | ((man >> 13) as u16);
1321    // round to nearest even on the truncated 13 bits
1322    let rem = man & 0x1fff;
1323    if rem > 0x1000 || (rem == 0x1000 && (h & 1) == 1) {
1324        h += 1;
1325    }
1326    h
1327}
1328
1329impl DflashDraft {
1330    /// Load the backbone-only checkpoint dir (config.json + model.safetensors, bf16).
1331    /// Config scalars ride a minimal extractor (no json dep in-tree — HfConfig precedent).
1332    pub fn load(e: &Engine, dir: &std::path::Path) -> Result<Self, Box<dyn std::error::Error>> {
1333        let txt = std::fs::read_to_string(dir.join("config.json"))?;
1334        fn num(txt: &str, key: &str) -> Option<f64> {
1335            let i = txt.find(&format!("\"{key}\""))?;
1336            let rest = &txt[i..];
1337            let colon = rest.find(':')?;
1338            let val: String = rest[colon + 1..]
1339                .trim_start()
1340                .chars()
1341                .take_while(|c| {
1342                    c.is_ascii_digit()
1343                        || *c == '.'
1344                        || *c == '-'
1345                        || *c == 'e'
1346                        || *c == 'E'
1347                        || *c == '+'
1348                })
1349                .collect();
1350            val.parse().ok()
1351        }
1352        fn num_list(txt: &str, key: &str) -> Vec<usize> {
1353            let Some(i) = txt.find(&format!("\"{key}\"")) else {
1354                return Vec::new();
1355            };
1356            let rest = &txt[i..];
1357            let (Some(a), Some(b)) = (rest.find('['), rest.find(']')) else {
1358                return Vec::new();
1359            };
1360            rest[a + 1..b]
1361                .split(',')
1362                .filter_map(|s| s.trim().parse().ok())
1363                .collect()
1364        }
1365        /// Substring of the JSON OBJECT value of a top-level key (brace-balanced) —
1366        /// the explicit scoped parse the DFlash2 census demands: `dflash_config` and
1367        /// `rope_parameters` are nested objects, and finding their keys by global
1368        /// `txt.find` is luck, not a contract (DFLASH2-EVAL-20260820.md §5.1).
1369        fn scope<'a>(txt: &'a str, key: &str) -> Option<&'a str> {
1370            let i = txt.find(&format!("\"{key}\""))?;
1371            let rest = &txt[i..];
1372            let open = rest.find('{')?;
1373            let mut depth = 0usize;
1374            for (j, ch) in rest[open..].char_indices() {
1375                match ch {
1376                    '{' => depth += 1,
1377                    '}' => {
1378                        depth -= 1;
1379                        if depth == 0 {
1380                            return Some(&rest[open..open + j + 1]);
1381                        }
1382                    }
1383                    _ => {}
1384                }
1385            }
1386            None
1387        }
1388        // Family detection is the ARCHITECTURES string, not tensor presence: a DFlash2
1389        // checkpoint whose new tensors were stripped must REFUSE, not degrade into the
1390        // 58-tensor untrained program (DFLASH2-EVAL-20260820.md §3).
1391        let is_dflash2 = {
1392            let arch = scope_list(&txt, "architectures");
1393            arch.contains("DFlash2DraftModel")
1394        };
1395        fn scope_list(txt: &str, key: &str) -> String {
1396            let Some(i) = txt.find(&format!("\"{key}\"")) else {
1397                return String::new();
1398            };
1399            let rest = &txt[i..];
1400            match (rest.find('['), rest.find(']')) {
1401                (Some(a), Some(b)) if a < b => rest[a + 1..b].to_string(),
1402                _ => String::new(),
1403            }
1404        }
1405        // DFlash2 scalars parse from their OWN scopes; other families keep the
1406        // historical global-find behavior byte-identically.
1407        let d2_cfg_txt: Option<&str> = if is_dflash2 {
1408            Some(
1409                scope(&txt, "dflash_config")
1410                    .ok_or("DFlash2DraftModel config.json has no dflash_config object")?,
1411            )
1412        } else {
1413            None
1414        };
1415        let required_usize =
1416            |scope: &str, k: &str, label: &str| -> Result<usize, Box<dyn std::error::Error>> {
1417                let value = num(scope, k).ok_or_else(|| format!("{label} missing {k}"))?;
1418                if !value.is_finite()
1419                    || value < 0.0
1420                    || value.fract() != 0.0
1421                    || value > usize::MAX as f64
1422                {
1423                    return Err(format!("{label} {k}={value} is not a non-negative usize").into());
1424                }
1425                Ok(value as usize)
1426            };
1427        let g = |k: &str| required_usize(&txt, k, "config");
1428        let g2 = |k: &str| {
1429            required_usize(
1430                d2_cfg_txt.ok_or("DFlash2 config scope is unavailable")?,
1431                k,
1432                "dflash_config",
1433            )
1434        };
1435        // layer_types order: count entries, mark sliding ones
1436        let layer_sliding: Vec<bool> = {
1437            let i = txt
1438                .find("\"layer_types\"")
1439                .ok_or("config missing layer_types")?;
1440            let rest = &txt[i..];
1441            let a = rest.find('[').ok_or("layer_types is not an array")?;
1442            let b = rest.find(']').ok_or("layer_types array is unterminated")?;
1443            rest[a + 1..b]
1444                .split(',')
1445                .map(|s| s.contains("sliding_attention"))
1446                .collect()
1447        };
1448        // sliding_window is null on all-full-attention exports (q38 arm-a); the window
1449        // only constrains rounds when a sliding layer exists (reference: resolve_dflash_
1450        // attention_layout returns None when no layer slides).
1451        let sliding_window = if layer_sliding.iter().any(|&s| s) {
1452            g("sliding_window")?
1453        } else {
1454            num(&txt, "sliding_window")
1455                .map(|v| v as usize)
1456                .unwrap_or(usize::MAX)
1457        };
1458        // Explicit top-level is_causal (z-lab reference: overrides the layer-type
1459        // default). Parsed as a bare bool; absent = None (historical arms unchanged).
1460        let is_causal = txt
1461            .find("\"is_causal\"")
1462            .and_then(|i| txt[i..].find(':').map(|c| i + c + 1))
1463            .map(|v| txt[v..].trim_start().starts_with("true"));
1464        let cfg = DflashCfg {
1465            hidden: g("hidden_size")?,
1466            n_head: g("num_attention_heads")?,
1467            n_kv: g("num_key_value_heads")?,
1468            head_dim: g("head_dim")?,
1469            n_ff: g("intermediate_size")?,
1470            n_layer: g("num_hidden_layers")?,
1471            eps: num(&txt, "rms_norm_eps").ok_or("config missing rms_norm_eps")? as f32,
1472            // DFlash2 (transformers-5 style): rope_theta lives in the nested
1473            // rope_parameters object — parse it from its scope, not by global find.
1474            rope_theta: if is_dflash2 {
1475                let rp = scope(&txt, "rope_parameters")
1476                    .ok_or("DFlash2 config has no rope_parameters")?;
1477                if !rp.contains("\"default\"") {
1478                    return Err(format!(
1479                        "DFlash2 rope_parameters rope_type is not default; refusing {rp}"
1480                    )
1481                    .into());
1482                }
1483                num(rp, "rope_theta").ok_or("rope_parameters missing rope_theta")? as f32
1484            } else {
1485                num(&txt, "rope_theta").ok_or("config missing rope_theta")? as f32
1486            },
1487            block_size: if is_dflash2 {
1488                g2("block_size")?
1489            } else {
1490                g("block_size")?
1491            },
1492            mask_token_id: u32::try_from(if is_dflash2 {
1493                g2("mask_token_id")?
1494            } else {
1495                g("mask_token_id")?
1496            })
1497            .map_err(|_| "DFlash mask_token_id does not fit u32")?,
1498            target_layer_ids: if is_dflash2 {
1499                num_list(
1500                    d2_cfg_txt.ok_or("DFlash2 config scope is unavailable")?,
1501                    "target_layer_ids",
1502                )
1503            } else {
1504                num_list(&txt, "target_layer_ids")
1505            },
1506            sliding_window,
1507            layer_sliding,
1508            strategy_dspark: dspark_strategy_census(&txt),
1509            is_causal,
1510        };
1511        if cfg.n_layer == 0 || cfg.n_layer > 1_024 {
1512            return Err(format!(
1513                "DFlash num_hidden_layers {} is outside 1..=1024",
1514                cfg.n_layer
1515            )
1516            .into());
1517        }
1518        if cfg.hidden == 0
1519            || cfg.n_head == 0
1520            || cfg.n_kv == 0
1521            || cfg.head_dim == 0
1522            || cfg.n_ff == 0
1523            || !cfg.eps.is_finite()
1524            || cfg.eps <= 0.0
1525            || !cfg.rope_theta.is_finite()
1526            || cfg.rope_theta <= 0.0
1527        {
1528            return Err("DFlash config carries zero or non-finite model geometry".into());
1529        }
1530        validate_dflash_attention_geometry(cfg.n_head, cfg.n_kv, cfg.head_dim)?;
1531        validate_layer_layout(&cfg.layer_sliding, cfg.n_layer)?;
1532        if is_dflash2 {
1533            // The windowed round arm implements the reference's NON-causal symmetric
1534            // window only (config `is_causal: false` on the q38 DFlash2 export). A
1535            // causal DFlash2 variant is a different mask program — refuse it rather
1536            // than run the wrong one fluently.
1537            if cfg.is_causal != Some(false) {
1538                return Err(format!(
1539                    "DFlash2 requires explicit is_causal=false; got {:?}",
1540                    cfg.is_causal
1541                )
1542                .into());
1543            }
1544            if !cfg.layer_sliding.iter().all(|&sliding| sliding) {
1545                return Err(format!(
1546                    "DFlash2 expects all layers sliding_attention; got {:?}",
1547                    cfg.layer_sliding
1548                )
1549                .into());
1550            }
1551            if cfg.block_size > cfg.sliding_window {
1552                return Err(format!(
1553                    "DFlash2 block {} exceeds sliding window {}",
1554                    cfg.block_size, cfg.sliding_window
1555                )
1556                .into());
1557            }
1558        }
1559        let st = memra_gguf::safetensors::StModel::open(&dir.join("model.safetensors"))?;
1560        let validate = |name: &str,
1561                        info: &memra_gguf::safetensors::StInfo,
1562                        expected: &[u64]|
1563         -> Result<(), Box<dyn std::error::Error>> {
1564            validate_dflash_tensor(name, info, expected).map_err(Into::into)
1565        };
1566        // 1D norm weights ride raw slices; 2D matmul weights ride GpuTensor::Float
1567        // (cuBLASLt f32 arm — the Stage-A numeric class, right for oracle parity).
1568        let up =
1569            |name: &str, expected: &[u64]| -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
1570                let (info, bytes) = st
1571                    .raw(name)
1572                    .ok_or_else(|| format!("missing tensor {name}"))?;
1573                validate(name, info, expected)?;
1574                e.htod(&bf16_to_f32(bytes))
1575            };
1576        // Precision policy (MEMRA_DFLASH_PREC seam): "q4" = all q4_0 (DEFAULT since
1577        // lane/dflash2-head-trim 2026-08-25, owner-ratified): measured on BOTH engaging
1578        // card classes at unchanged acceptance — RTX PRO 6000 dspark_q38_gate x3
1579        // interleaved 157.9 vs q8 152.4 spec tok/s (accept 0.662 vs 0.656, ALL EXACT;
1580        // darklanes research/dflash2-pro6000-20260824/prec-ladder + trim cells) and the
1581        // 5090 rig cell that shipped the arm (PR #41). "q8" = all q8_0 (1.6GB, the
1582        // pre-flip default = the rollback seam); "mixed" = bf16 attn+fc (the
1583        // ctx-conditioning path) + q8_0 ffn (~2.2GB — fits the ~2.8GB headroom beside
1584        // the 31B trunk); "bf16" = all bf16 (parity runs, no target). The asymmetric
1585        // "q5" arm was measured DEFECTIVE (acceptance 0.656 -> 0.424) and never landed.
1586        let prec_env = std::env::var("MEMRA_DFLASH_PREC").ok();
1587        let prec = dflash_precision(prec_env.as_deref())?;
1588        let upw = |name: &str, expected: &[u64]| -> Result<GpuTensor, Box<dyn std::error::Error>> {
1589            let (info, bytes) = st
1590                .raw(name)
1591                .ok_or_else(|| format!("missing tensor {name}"))?;
1592            validate(name, info, expected)?;
1593            let shape = info.ne(); // ggml order: ne[0]=in_f, ne[1]=out_f
1594            let in_f = shape[0] as usize;
1595            let is_ffn = name.contains(".mlp.");
1596            let bf16 = prec == "bf16"
1597                || (prec == "mixed" && !is_ffn)
1598                || (prec == "fc" && name == "fc.weight");
1599            if bf16 {
1600                return Ok(GpuTensor::FloatBf16 {
1601                    data: e.upload_u8(bytes)?,
1602                    ne: shape.to_vec(),
1603                });
1604            }
1605            let f32s = bf16_to_f32(bytes);
1606            if prec == "q4" {
1607                let q = encode_q4_0(&f32s);
1608                return Ok(GpuTensor::Quant {
1609                    bytes: e.upload_u8(&q)?,
1610                    qtype: crate::QT_Q4_0,
1611                    row_bytes: in_f / 32 * 18,
1612                    ne: shape.to_vec(),
1613                    scale: 1.0,
1614                    rp: false,
1615                    #[cfg(memra_cutlass)]
1616                    cutlass: None,
1617                    fp8: None,
1618                    blk: None,
1619                    rp4: None,
1620                    f16: None,
1621                });
1622            }
1623            let q = encode_q8_0(&f32s);
1624            Ok(GpuTensor::Quant {
1625                bytes: e.upload_u8(&q)?,
1626                qtype: crate::QT_Q8_0,
1627                row_bytes: in_f / 32 * 34,
1628                ne: shape.to_vec(),
1629                scale: 1.0,
1630                rp: false,
1631                #[cfg(memra_cutlass)]
1632                cutlass: None,
1633                fp8: None,
1634                blk: None,
1635                rp4: None,
1636                f16: None,
1637            })
1638        };
1639        let hidden = cfg.hidden as u64;
1640        let q_width = cfg
1641            .n_head
1642            .checked_mul(cfg.head_dim)
1643            .ok_or("DFlash q geometry overflow")? as u64;
1644        let kv_width = cfg
1645            .n_kv
1646            .checked_mul(cfg.head_dim)
1647            .ok_or("DFlash kv geometry overflow")? as u64;
1648        let ff = cfg.n_ff as u64;
1649        let head_dim = cfg.head_dim as u64;
1650        let mut layers = Vec::with_capacity(cfg.n_layer);
1651        for i in 0..cfg.n_layer {
1652            let p = |s: &str| format!("layers.{i}.{s}");
1653            layers.push(DflashLayer {
1654                wq: upw(&p("self_attn.q_proj.weight"), &[hidden, q_width])?,
1655                wk: upw(&p("self_attn.k_proj.weight"), &[hidden, kv_width])?,
1656                wv: upw(&p("self_attn.v_proj.weight"), &[hidden, kv_width])?,
1657                wo: upw(&p("self_attn.o_proj.weight"), &[q_width, hidden])?,
1658                w_gate: upw(&p("mlp.gate_proj.weight"), &[hidden, ff])?,
1659                w_up: upw(&p("mlp.up_proj.weight"), &[hidden, ff])?,
1660                w_down: upw(&p("mlp.down_proj.weight"), &[ff, hidden])?,
1661                ln_in: up(&p("input_layernorm.weight"), &[hidden])?,
1662                ln_post: up(&p("post_attention_layernorm.weight"), &[hidden])?,
1663                q_norm: up(&p("self_attn.q_norm.weight"), &[head_dim])?,
1664                k_norm: up(&p("self_attn.k_norm.weight"), &[head_dim])?,
1665            });
1666        }
1667        let markov = if let Some((info, bytes)) = st.raw("markov_head.markov_w1.weight") {
1668            let sh = info.ne(); // [rank, vocab] in ggml order (safetensors [V, rank] reversed)
1669            if info.dtype != "BF16" || sh.len() != 2 {
1670                return Err("markov_head.markov_w1.weight must be rank-2 BF16".into());
1671            }
1672            let (rank, vocab) = (sh[0] as usize, sh[1] as usize);
1673            let (i2, b2) = st
1674                .raw("markov_head.markov_w2.weight")
1675                .ok_or("markov_w2 missing beside markov_w1")?;
1676            validate("markov_head.markov_w2.weight", i2, &sh)?;
1677            // w2 follows the precision seam: bf16 for parity runs (the q8_0 encode is a
1678            // serving-size choice and would put quant error inside the markov-logits gate),
1679            // q8_0 otherwise (acceptance-only impact, like the trunk weights).
1680            let w2 = if prec == "bf16" {
1681                GpuTensor::FloatBf16 {
1682                    data: e.upload_u8(b2)?,
1683                    ne: i2.ne().to_vec(),
1684                }
1685            } else {
1686                let w2f = bf16_to_f32(b2);
1687                let w2q = encode_q8_0(&w2f);
1688                GpuTensor::Quant {
1689                    bytes: e.upload_u8(&w2q)?,
1690                    qtype: crate::QT_Q8_0,
1691                    row_bytes: rank / 32 * 34,
1692                    ne: vec![rank as u64, vocab as u64],
1693                    scale: 1.0,
1694                    rp: false,
1695                    #[cfg(memra_cutlass)]
1696                    cutlass: None,
1697                    fp8: None,
1698                    blk: None,
1699                    rp4: None,
1700                    f16: None,
1701                }
1702            };
1703            Some(MarkovHead {
1704                w1_bf16: e.upload_u8(bytes)?,
1705                w2,
1706                rank,
1707                vocab,
1708            })
1709        } else {
1710            None
1711        };
1712        let confidence = if let Some((info, bytes)) = st.raw("confidence_head.proj.weight") {
1713            let sh = info.ne(); // ggml order: ne[0]=in_dim, ne[1]=1
1714            if info.dtype != "BF16" || sh.len() != 2 || sh[1] != 1 {
1715                return Err("confidence_head.proj.weight must be BF16 [in_dim, 1]".into());
1716            }
1717            let in_dim = sh[0] as usize;
1718            let (bi, bb) = st
1719                .raw("confidence_head.proj.bias")
1720                .ok_or("confidence bias missing beside weight")?;
1721            validate("confidence_head.proj.bias", bi, &[1])?;
1722            let with_markov = markov
1723                .as_ref()
1724                .map(|m| in_dim == cfg.hidden + m.rank)
1725                .unwrap_or(false);
1726            if !with_markov && in_dim != cfg.hidden {
1727                return Err(format!(
1728                    "confidence_head in_dim {in_dim} matches neither hidden {} nor hidden+rank",
1729                    cfg.hidden
1730                )
1731                .into());
1732            }
1733            Some(ConfidenceHead {
1734                w: bf16_to_f32(bytes),
1735                b: bf16_to_f32(bb)[0],
1736                in_dim,
1737                with_markov,
1738            })
1739        } else {
1740            None
1741        };
1742        // ---- DFlash2 family tensors (DFLASH2-EVAL-20260820.md §2): 10 conv modules
1743        // (base_kernel + kernel_projection around attention AND mlp in EVERY layer) +
1744        // the candidate path selector (hidden_projection + two codebooks). REQUIRED
1745        // when the arch says DFlash2DraftModel: a missing tensor is a refusal (`?`),
1746        // never a degraded program.
1747        let dflash2 = if is_dflash2 {
1748            if markov.is_some() || confidence.is_some() {
1749                return Err(
1750                    "DFlash2 checkpoint carries unsupported markov/confidence tensors".into(),
1751                );
1752            }
1753            let rank = g2("selector_rank")?;
1754            let top_k = g2("selector_top_k")?;
1755            let conv_k = g2("conv_kernel_size")?;
1756            let group_size = g2("conv_group_size")?;
1757            if rank == 0
1758                || top_k == 0
1759                || conv_k == 0
1760                || group_size == 0
1761                || !cfg.hidden.is_multiple_of(group_size)
1762            {
1763                return Err(
1764                    "DFlash2 selector/convolution geometry is zero or not divisible".into(),
1765                );
1766            }
1767            let groups = cfg.hidden / group_size;
1768            let load_conv = |name: &str| -> Result<Dflash2Conv, Box<dyn std::error::Error>> {
1769                let (bi, bb) = st
1770                    .raw(&format!("{name}.base_kernel"))
1771                    .ok_or_else(|| format!("DFlash2 census: missing {name}.base_kernel"))?;
1772                // safetensors [2, k, hidden] -> ggml ne reversed [hidden, k, 2]
1773                validate(
1774                    &format!("{name}.base_kernel"),
1775                    bi,
1776                    &[cfg.hidden as u64, conv_k as u64, 2],
1777                )?;
1778                let pname = format!("{name}.kernel_projection.weight");
1779                let (pi, _pb) = st
1780                    .raw(&pname)
1781                    .ok_or_else(|| format!("DFlash2 census: missing {pname}"))?;
1782                let projected = 2usize
1783                    .checked_mul(conv_k)
1784                    .and_then(|value| value.checked_mul(groups))
1785                    .ok_or("DFlash2 convolution projection geometry overflow")?;
1786                let expected = [cfg.hidden as u64, projected as u64];
1787                validate(&pname, pi, &expected)?;
1788                Ok(Dflash2Conv {
1789                    base: e.htod(&bf16_to_f32(bb))?,
1790                    proj: upw(&pname, &expected)?,
1791                })
1792            };
1793            let mut attn_conv = Vec::with_capacity(cfg.n_layer);
1794            let mut mlp_conv = Vec::with_capacity(cfg.n_layer);
1795            for i in 0..cfg.n_layer {
1796                attn_conv.push(load_conv(&format!("layers.{i}.attention_conv"))?);
1797                mlp_conv.push(load_conv(&format!("layers.{i}.mlp_conv"))?);
1798            }
1799            // Codebooks: stored WITHOUT `.weight` (checkpoint quirk; reference
1800            // from_pretrained maps the keys). Host-resident raw bf16.
1801            let cb = |name: &str| -> Result<(Vec<u8>, usize), Box<dyn std::error::Error>> {
1802                let (ci, cbytes) = st
1803                    .raw(&format!("candidate_selector.{name}"))
1804                    .ok_or_else(|| format!("DFlash2 census: missing candidate_selector.{name}"))?;
1805                let ne = ci.ne(); // ggml: [rank, V]
1806                if ci.dtype != "BF16" || ne.len() != 2 || ne[0] as usize != rank {
1807                    return Err(format!(
1808                        "candidate_selector.{name} must be rank-2 BF16 with inner rank {rank}; found {:?} {}",
1809                        ne, ci.dtype
1810                    )
1811                    .into());
1812                }
1813                Ok((cbytes.to_vec(), ne[1] as usize))
1814            };
1815            let (pred_codebook, v1) = cb("predecessor_codebook")?;
1816            let (succ_codebook, v2) = cb("successor_codebook")?;
1817            if v1 != v2 {
1818                return Err(format!("DFlash2 codebook vocab mismatch: {v1} != {v2}").into());
1819            }
1820            validate_selector_top_k(top_k, v1)?;
1821            let hp_name = "candidate_selector.hidden_projection.weight";
1822            let (hi, _hb) = st
1823                .raw(hp_name)
1824                .ok_or_else(|| format!("DFlash2 census: missing {hp_name}"))?;
1825            let hp_expected = [cfg.hidden as u64, rank as u64];
1826            validate(hp_name, hi, &hp_expected)?;
1827            Some(Dflash2Head {
1828                attn_conv,
1829                mlp_conv,
1830                hidden_proj: upw(hp_name, &hp_expected)?,
1831                pred_codebook,
1832                succ_codebook,
1833                rank,
1834                top_k,
1835                conv_k,
1836                group_size,
1837                vocab: v1,
1838            })
1839        } else {
1840            None
1841        };
1842        // CENSUS GATE: every tensor in the export must be consumed by the map above.
1843        // DSpark-class checkpoints (markov head present) and DFlash2 checkpoints
1844        // REFUSE on unrecognized names — an unmapped tensor is a semantic program we
1845        // would silently drop (house law). Plain dflash checkpoints keep the
1846        // historical warn-only behavior.
1847        {
1848            let mut consumed: std::collections::HashSet<String> = std::collections::HashSet::new();
1849            for i in 0..cfg.n_layer {
1850                for s in [
1851                    "self_attn.q_proj.weight",
1852                    "self_attn.k_proj.weight",
1853                    "self_attn.v_proj.weight",
1854                    "self_attn.o_proj.weight",
1855                    "self_attn.q_norm.weight",
1856                    "self_attn.k_norm.weight",
1857                    "input_layernorm.weight",
1858                    "post_attention_layernorm.weight",
1859                    "mlp.gate_proj.weight",
1860                    "mlp.up_proj.weight",
1861                    "mlp.down_proj.weight",
1862                ] {
1863                    consumed.insert(format!("layers.{i}.{s}"));
1864                }
1865                if dflash2.is_some() {
1866                    for s in [
1867                        "attention_conv.base_kernel",
1868                        "attention_conv.kernel_projection.weight",
1869                        "mlp_conv.base_kernel",
1870                        "mlp_conv.kernel_projection.weight",
1871                    ] {
1872                        consumed.insert(format!("layers.{i}.{s}"));
1873                    }
1874                }
1875            }
1876            for s in [
1877                "fc.weight",
1878                "hidden_norm.weight",
1879                "norm.weight",
1880                "markov_head.markov_w1.weight",
1881                "markov_head.markov_w2.weight",
1882                "confidence_head.proj.weight",
1883                "confidence_head.proj.bias",
1884            ] {
1885                consumed.insert(s.into());
1886            }
1887            if dflash2.is_some() {
1888                for s in [
1889                    "candidate_selector.hidden_projection.weight",
1890                    "candidate_selector.predecessor_codebook",
1891                    "candidate_selector.successor_codebook",
1892                ] {
1893                    consumed.insert(s.into());
1894                }
1895            }
1896            let leftovers: Vec<&String> = st.names().filter(|n| !consumed.contains(*n)).collect();
1897            if !leftovers.is_empty() {
1898                if markov.is_some() || dflash2.is_some() {
1899                    return Err(format!(
1900                        "dspark/dflash2 census: unrecognized tensors {leftovers:?}"
1901                    )
1902                    .into());
1903                }
1904                eprintln!("[dflash census] unmapped tensors (ignored): {leftovers:?}");
1905            }
1906        }
1907        // YaRN rope from config rope_parameters (HF _compute_yarn_parameters, verified
1908        // numerically vs Qwen3RotaryEmbedding on the arm-a export).
1909        let rope_yarn =
1910            if txt.contains("\"rope_type\": \"yarn\"") || txt.contains("\"rope_type\":\"yarn\"") {
1911                let factor = num(&txt, "factor").ok_or("yarn missing factor")?;
1912                let orig = num(&txt, "original_max_position_embeddings")
1913                    .ok_or("yarn missing original_max_position_embeddings")?;
1914                let beta_fast = num(&txt, "beta_fast").ok_or("yarn missing beta_fast")?;
1915                let beta_slow = num(&txt, "beta_slow").ok_or("yarn missing beta_slow")?;
1916                if !factor.is_finite()
1917                    || factor <= 0.0
1918                    || !orig.is_finite()
1919                    || orig <= 0.0
1920                    || !beta_fast.is_finite()
1921                    || !beta_slow.is_finite()
1922                {
1923                    return Err("yarn parameters must be finite and positive".into());
1924                }
1925                let base = cfg.rope_theta as f64;
1926                let d = cfg.head_dim as f64;
1927                let corr =
1928                    |r: f64| d * (orig / (r * 2.0 * std::f64::consts::PI)).ln() / (2.0 * base.ln());
1929                let low = corr(beta_fast).floor().max(0.0);
1930                let high = corr(beta_slow).ceil().min(d - 1.0);
1931                let half = cfg.head_dim / 2;
1932                let mut ff = Vec::with_capacity(half);
1933                for j in 0..half {
1934                    let base_inv = base.powf(-2.0 * j as f64 / d);
1935                    let ramp = (((j as f64) - low) / (high - low)).clamp(0.0, 1.0);
1936                    let ex = 1.0 - ramp; // extrapolation share
1937                    let yarn_inv = (base_inv / factor) * (1.0 - ex) + base_inv * ex;
1938                    ff.push((base_inv / yarn_inv) as f32);
1939                }
1940                let mscale = (0.1 * factor.ln() + 1.0) as f32;
1941                Some((e.htod(&ff)?, mscale))
1942            } else {
1943                None
1944            };
1945        let fc_in = cfg
1946            .target_layer_ids
1947            .len()
1948            .checked_mul(cfg.hidden)
1949            .ok_or("DFlash fc geometry overflow")? as u64;
1950        let fc = upw("fc.weight", &[fc_in, hidden])?;
1951        // Ratified-default receipts (capacity-keyed-defaults law: the active program is
1952        // NAMED at load, never inferred from silence). The boot output-sample gate greps
1953        // these lines; a run whose log lacks them did not load this code.
1954        eprintln!(
1955            "[dspark] precision={prec} (MEMRA_DFLASH_PREC {})",
1956            if prec_env.is_some() { "set" } else { "unset" },
1957        );
1958        eprintln!(
1959            "[dspark] harvest={} (checkpoint census dflash2={} strategy_dspark={}, \
1960             MEMRA_DSPARK_HARVEST {})",
1961            DsparkHarvest::for_family_value(
1962                dflash2.is_some(),
1963                std::env::var("MEMRA_DSPARK_HARVEST").ok().as_deref(),
1964                cfg.strategy_dspark,
1965            )
1966            .name(),
1967            dflash2.is_some(),
1968            cfg.strategy_dspark,
1969            match std::env::var("MEMRA_DSPARK_HARVEST") {
1970                Ok(v) if !v.is_empty() => "set",
1971                _ => "unset",
1972            },
1973        );
1974        eprintln!(
1975            "[dspark] verify-window={:?} (accept-rate head {}, MEMRA_DSPARK_VT {})",
1976            DsparkVtPolicy::resolve(confidence.is_some()),
1977            if confidence.is_some() {
1978                "present"
1979            } else {
1980                "ABSENT -> ladder"
1981            },
1982            match std::env::var("MEMRA_DSPARK_VT") {
1983                Ok(v) if !v.is_empty() => "set",
1984                _ => "unset",
1985            },
1986        );
1987        Ok(Self {
1988            fc,
1989            hidden_norm: up("hidden_norm.weight", &[hidden])?,
1990            norm: up("norm.weight", &[hidden])?,
1991            cfg,
1992            layers,
1993            markov,
1994            confidence,
1995            rope_yarn,
1996            dflash2,
1997        })
1998    }
1999
2000    /// Rope q or k rows in place: yarn (ff divisors + post-rope mscale) when the config
2001    /// carries it, plain neox otherwise. One primitive for all five drafter rope sites.
2002    fn rope_rows(
2003        &self,
2004        e: &Engine,
2005        x: &mut CudaSlice<f32>,
2006        pos_d: &CudaSlice<i32>,
2007        n_heads: usize,
2008        n_tokens: usize,
2009    ) -> Result<(), Box<dyn std::error::Error>> {
2010        let c = &self.cfg;
2011        match &self.rope_yarn {
2012            Some((ff, mscale)) => {
2013                e.rope_neox_ff(
2014                    x,
2015                    pos_d,
2016                    c.head_dim,
2017                    c.head_dim,
2018                    n_heads,
2019                    n_tokens,
2020                    c.rope_theta,
2021                    1.0,
2022                    ff,
2023                )?;
2024                e.scale_inplace(x, *mscale, n_tokens * n_heads * c.head_dim)?;
2025            }
2026            None => {
2027                e.rope_neox(
2028                    x,
2029                    pos_d,
2030                    c.head_dim,
2031                    c.head_dim,
2032                    n_heads,
2033                    n_tokens,
2034                    c.rope_theta,
2035                    1.0,
2036                )?;
2037            }
2038        }
2039        Ok(())
2040    }
2041
2042    /// f32 GEMM helper via the engine Float arm (cuBLASLt): y[t, out_f].
2043    fn mm(
2044        &self,
2045        e: &Engine,
2046        w: &GpuTensor,
2047        x: &CudaSlice<f32>,
2048        t: usize,
2049        _in_f: usize,
2050        _out_f: usize,
2051    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
2052        e.matmul(w, x, t)
2053    }
2054
2055    /// DFlash2 conv `prepare` (reference GroupedDynamicCausalConv.prepare): projects
2056    /// the pre-conv rows to BOTH dynamic kernels, convolves the rows with base half 0
2057    /// + dyn half 0, and returns (convolved rows, the dyn projection) — `finish`
2058    ///   reuses the SAME projection's half 1. Block-local causal shift (row 0 zero-pads).
2059    pub fn d2_conv_prepare(
2060        &self,
2061        e: &Engine,
2062        conv: &Dflash2Conv,
2063        xn: &CudaSlice<f32>,
2064        rows: usize,
2065    ) -> Result<(CudaSlice<f32>, CudaSlice<f32>), Box<dyn std::error::Error>> {
2066        let d2 = self
2067            .dflash2
2068            .as_ref()
2069            .expect("d2_conv on a non-dflash2 draft");
2070        let h = self.cfg.hidden;
2071        let groups = h / d2.group_size;
2072        let dyn_ = self.mm(e, &conv.proj, xn, rows, h, 2 * d2.conv_k * groups)?;
2073        let mut out = e.uninit(rows * h)?;
2074        e.dflash2_dynconv(
2075            xn,
2076            &dyn_,
2077            &conv.base,
2078            &mut out,
2079            rows,
2080            h,
2081            d2.group_size,
2082            d2.conv_k,
2083            0,
2084        )?;
2085        Ok((out, dyn_))
2086    }
2087
2088    /// DFlash2 conv `finish`: convolves the sublayer OUTPUT rows with base half 1 +
2089    /// dyn half 1 (dyn from the matching `prepare`).
2090    pub fn d2_conv_finish(
2091        &self,
2092        e: &Engine,
2093        conv: &Dflash2Conv,
2094        y: &CudaSlice<f32>,
2095        dyn_: &CudaSlice<f32>,
2096        rows: usize,
2097    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
2098        let d2 = self
2099            .dflash2
2100            .as_ref()
2101            .expect("d2_conv on a non-dflash2 draft");
2102        let h = self.cfg.hidden;
2103        let mut out = e.uninit(rows * h)?;
2104        e.dflash2_dynconv(
2105            y,
2106            dyn_,
2107            &conv.base,
2108            &mut out,
2109            rows,
2110            h,
2111            d2.group_size,
2112            d2.conv_k,
2113            1,
2114        )?;
2115        Ok(out)
2116    }
2117
2118    /// DFlash2 proposal (reference `DFlash2DraftModel.propose`, greedy arm): device
2119    /// top-k over the draft logits + the rank-`r` hidden projection, ONE small dtoh
2120    /// (~nd*(2k+rank) floats — the same per-round sync slot the markov chain's token
2121    /// readback occupies), then the host codebook walk. Returns the nd drafted tokens
2122    /// (mask-fill rows 1..b-1; the anchor row is not a draft).
2123    #[allow(clippy::too_many_arguments)] // allow: the parameter list mirrors the kernel/FFI/call contract; bundling into a struct is a refactor, not a lint fix
2124    pub fn dflash2_propose_greedy(
2125        &self,
2126        e: &Engine,
2127        dl: &CudaSlice<f32>,
2128        rows: &CudaSlice<f32>,
2129        nd: usize,
2130        n_vocab: usize,
2131        anchor: u32,
2132        d2t: Option<&[u32]>,
2133    ) -> Result<Vec<u32>, Box<dyn std::error::Error>> {
2134        Ok(self
2135            .dflash2_propose_greedy_q(e, dl, rows, nd, n_vocab, anchor, d2t)?
2136            .0)
2137    }
2138
2139    /// [`Self::dflash2_propose_greedy`] with the walk's per-slot confidence returned
2140    /// (lane/glm5-loop-port, 2026-08-30): q[p] = the chosen candidate's softmax mass over
2141    /// its slot's candidate set at T=1 — the statistic the glm5 loop's MEMRA_SPEC_PMIN
2142    /// tau-slot truncation thresholds on. Same walk, same path, same one-DtoH sync slot.
2143    #[allow(clippy::too_many_arguments)]
2144    // allow: mirrors the greedy propose contract it wraps
2145    pub fn dflash2_propose_greedy_q(
2146        &self,
2147        e: &Engine,
2148        dl: &CudaSlice<f32>,
2149        rows: &CudaSlice<f32>,
2150        nd: usize,
2151        n_vocab: usize,
2152        anchor: u32,
2153        d2t: Option<&[u32]>,
2154    ) -> Result<(Vec<u32>, Vec<f32>), Box<dyn std::error::Error>> {
2155        let d2 = self
2156            .dflash2
2157            .as_ref()
2158            .expect("dflash2_propose on a non-dflash2 draft");
2159        if n_vocab > d2.vocab || d2.top_k > n_vocab {
2160            return Err(format!(
2161                "DFlash2 proposal geometry invalid: target vocab {n_vocab}, selector vocab {}, top_k {}",
2162                d2.vocab, d2.top_k
2163            )
2164            .into());
2165        }
2166        if let Some(map) = d2t
2167            && map.len() < n_vocab
2168        {
2169            return Err(format!(
2170                "DFlash2 d2t has {} entries, fewer than proposal vocab {n_vocab}",
2171                map.len()
2172            )
2173            .into());
2174        }
2175        let (vals_d, idx_d) = e.topk_rows(dl, nd, n_vocab, d2.top_k)?;
2176        let hproj_d = e.matmul(&d2.hidden_proj, rows, nd)?;
2177        let unary = e.dtoh(&vals_d)?;
2178        let mut cand = e.dtoh_u32(&idx_d)?;
2179        // memra#95: refuse a selector row the top-k could not fill, BEFORE the d2t remap.
2180        dflash2_guard_candidates(&cand, n_vocab, "dflash2 greedy proposal")?;
2181        // TRIMMED draft head (lane/dflash2-head-trim, 2026-08-25): `dl` was scored over the
2182        // FR-Spec-gathered rows, so candidate index i names trimmed row i — remap to the true
2183        // token id BEFORE the selector walk (the codebooks and the verify block index the full
2184        // vocabulary). Same permute-the-proposal law as the MTP arm's spec.rs d2t map; verify
2185        // stays full-vocab, so the trim moves acceptance only, never output.
2186        if let Some(map) = d2t {
2187            for c in cand.iter_mut() {
2188                *c = map[*c as usize];
2189            }
2190        }
2191        let hproj = e.dtoh(&hproj_d)?;
2192        Ok(d2.walk_greedy_q(&unary, &cand, &hproj, anchor, nd))
2193    }
2194
2195    /// DFlash2 proposal, SAMPLED arm (reference `DFlash2DraftModel.propose` at T>0): same
2196    /// device top-k + hidden projection + one dtoh as the greedy arm, then the host
2197    /// candidate-set softmax walk (`dflash2_walk_sampled`) drawing one host-Philox uniform
2198    /// per slot from the session's `uctr` stream. Returns (path, q_chosen, cand, q_rows).
2199    #[allow(clippy::too_many_arguments)]
2200    pub(crate) fn dflash2_propose_sampled(
2201        &self,
2202        e: &Engine,
2203        dl: &CudaSlice<f32>,
2204        rows: &CudaSlice<f32>,
2205        nd: usize,
2206        n_vocab: usize,
2207        anchor: u32,
2208        temp: f32,
2209        seed: u64,
2210        uctr: &mut u32,
2211        d2t: Option<&[u32]>,
2212    ) -> Result<Dflash2SampledProposal, Box<dyn std::error::Error>> {
2213        let d2 = self
2214            .dflash2
2215            .as_ref()
2216            .expect("dflash2_propose on a non-dflash2 draft");
2217        if n_vocab > d2.vocab || d2.top_k > n_vocab {
2218            return Err(format!(
2219                "DFlash2 proposal geometry invalid: target vocab {n_vocab}, selector vocab {}, top_k {}",
2220                d2.vocab, d2.top_k
2221            )
2222            .into());
2223        }
2224        if let Some(map) = d2t
2225            && map.len() < n_vocab
2226        {
2227            return Err(format!(
2228                "DFlash2 d2t has {} entries, fewer than proposal vocab {n_vocab}",
2229                map.len()
2230            )
2231            .into());
2232        }
2233        let (vals_d, idx_d) = e.topk_rows(dl, nd, n_vocab, d2.top_k)?;
2234        let hproj_d = e.matmul(&d2.hidden_proj, rows, nd)?;
2235        let unary = e.dtoh(&vals_d)?;
2236        let mut cand = e.dtoh_u32(&idx_d)?;
2237        // memra#95: refuse a selector row the top-k could not fill, BEFORE the d2t remap.
2238        dflash2_guard_candidates(&cand, n_vocab, "dflash2 sampled proposal")?;
2239        // Trimmed-head remap — see the greedy arm. The q the walk reports is the softmax
2240        // over the candidate SET it actually proposed (ids are labels, not indices into a
2241        // distribution), so the rejection-verify contract is unchanged by the remap.
2242        if let Some(map) = d2t {
2243            for c in cand.iter_mut() {
2244                *c = map[*c as usize];
2245            }
2246        }
2247        let hproj = e.dtoh(&hproj_d)?;
2248        let mut draw = || {
2249            let u = crate::spec::host_u01(seed, *uctr);
2250            *uctr = uctr.wrapping_add(1);
2251            u
2252        };
2253        let (path, q_chosen, q_rows) =
2254            d2.walk_sampled(&unary, &cand, &hproj, anchor, nd, temp, &mut draw);
2255        Ok((path, q_chosen, cand, q_rows))
2256    }
2257
2258    /// Sampled draft chain for the Rows families (T>0 twin of the greedy markov chain):
2259    /// slot k gets the markov bias of the PREVIOUS chain token added in place (when the
2260    /// head is armed — the sglang DSPARK worker's markov-corrected draft probs), then ONE
2261    /// draw from the row's FILTERED softmax (filter_stats -> device-stat gumbel perturb ->
2262    /// argmax into the chain buffer — the frspec eager-chain composition, stats kept on
2263    /// device so the chain stays sync-free like the greedy arm). Without a markov head the
2264    /// rows sample independently (the z-lab reference's T>0 arm for plain DFlash). `dl` is
2265    /// biased IN PLACE and retained by the caller: it is the accept walk's q source.
2266    #[allow(clippy::too_many_arguments)]
2267    pub(crate) fn dspark_chain_sampled(
2268        &self,
2269        e: &Engine,
2270        dl: &mut CudaSlice<f32>,
2271        nd: usize,
2272        n_vocab: usize,
2273        anchor: u32,
2274        sp: &crate::spec::SpecSampling,
2275        sctr: &mut u32,
2276        // H4 confidence-policy stash (v0.100 train merge): Some = copy each slot's
2277        // markov prev-token embedding (the exact `w1` row the chain gathers) into a
2278        // [nd, rank] buffer — the same d2d stash the greedy chain carries, so the
2279        // confidence window sizes identically at T>0.
2280        mut conf_emb: Option<&mut CudaSlice<f32>>,
2281    ) -> Result<(Vec<u32>, DsparkDraftSample), Box<dyn std::error::Error>> {
2282        let markov_on = std::env::var("MEMRA_DFLASH_MARKOV").as_deref() != Ok("0");
2283        let mut chain_d = e.stream().alloc_zeros::<u32>(nd + 1)?;
2284        e.set_u32_one(&mut chain_d, anchor)?;
2285        let mut th_all = e.zeros(nd)?;
2286        let mut z_all = e.zeros(nd)?;
2287        let mut mx_all = e.zeros(nd)?;
2288        let mut pb = e.zeros(n_vocab)?;
2289        for k in 0..nd {
2290            if let (Some(mk), true) = (&self.markov, markov_on) {
2291                let mut f = e.uninit(mk.rank)?;
2292                e.gather_row_bf16(&mk.w1_bf16, &chain_d, k, &mut f, mk.rank)?;
2293                if let Some(ce) = conf_emb.as_deref_mut() {
2294                    let fv = e.view(&f, mk.rank);
2295                    e.copy_view_into(ce, k * mk.rank, &fv, mk.rank)?;
2296                }
2297                let bias = e.matmul(&mk.w2, &f, 1)?;
2298                e.add_row_inplace(dl, &bias, n_vocab, k * n_vocab)?;
2299            } else if let (Some(ce), Some(mk)) = (conf_emb.as_deref_mut(), &self.markov) {
2300                // MARKOV=0 arm still stashes the embedding for the confidence head —
2301                // the greedy chain's exact behavior.
2302                let mut f = e.uninit(mk.rank)?;
2303                e.gather_row_bf16(&mk.w1_bf16, &chain_d, k, &mut f, mk.rank)?;
2304                let fv = e.view(&f, mk.rank);
2305                e.copy_view_into(ce, k * mk.rank, &fv, mk.rank)?;
2306            }
2307            let rows_k = e.htod_i32(&[k as i32])?;
2308            let (mut th1, mut z1, mut mx1) = (e.zeros(1)?, e.zeros(1)?, e.zeros(1)?);
2309            e.filter_stats(
2310                dl, n_vocab, &rows_k, &mut th1, &mut z1, &mut mx1, n_vocab, 1, sp.temp, sp.top_k,
2311                sp.top_p, sp.min_p,
2312            )?;
2313            e.gumbel_perturb_filtered_col(
2314                dl, k, &mut pb, n_vocab, sp.seed, *sctr, sp.temp, &mx1, &th1, 0,
2315            )?;
2316            *sctr = sctr.wrapping_add(1);
2317            e.argmax_token_device_col(&pb, 0, n_vocab, &mut chain_d, k + 1)?;
2318            e.copy_into(&mut th_all, k, &th1, 1)?;
2319            e.copy_into(&mut z_all, k, &z1, 1)?;
2320            e.copy_into(&mut mx_all, k, &mx1, 1)?;
2321        }
2322        let chain = e.dtoh_u32(&chain_d)?;
2323        let (thv, zv, mxv) = (e.dtoh(&th_all)?, e.dtoh(&z_all)?, e.dtoh(&mx_all)?);
2324        let stats = (0..nd).map(|i| (mxv[i], thv[i], zv[i])).collect();
2325        Ok((
2326            chain[1..].to_vec(),
2327            DsparkDraftSample::Rows {
2328                th: th_all,
2329                z: z_all,
2330                stats,
2331            },
2332        ))
2333    }
2334
2335    /// Family dispatch for the sampled proposal: Selector for DFlash2, Rows otherwise.
2336    /// Returns the drafted tokens (the round's `cand` tail) + the proposal record.
2337    #[allow(clippy::too_many_arguments)]
2338    pub(crate) fn dspark_propose_sampled(
2339        &self,
2340        e: &Engine,
2341        dl: &mut CudaSlice<f32>,
2342        rows: &CudaSlice<f32>,
2343        nd: usize,
2344        n_vocab: usize,
2345        anchor: u32,
2346        sp: &crate::spec::SpecSampling,
2347        sctr: &mut u32,
2348        uctr: &mut u32,
2349        conf_emb: Option<&mut CudaSlice<f32>>,
2350        d2t: Option<&[u32]>,
2351    ) -> Result<(Vec<u32>, DsparkDraftSample), Box<dyn std::error::Error>> {
2352        if let Some(d2) = self.dflash2.as_ref() {
2353            // The confidence stash is a markov-family program; DFlash2 has no
2354            // accept-rate head (the policy resolver never arms it for this family).
2355            debug_assert!(
2356                conf_emb.is_none(),
2357                "conf_emb stash requested on a DFlash2 selector proposal"
2358            );
2359            let (path, q_chosen, cand, q_rows) = self.dflash2_propose_sampled(
2360                e, dl, rows, nd, n_vocab, anchor, sp.temp, sp.seed, uctr, d2t,
2361            )?;
2362            Ok((
2363                path,
2364                DsparkDraftSample::Selector {
2365                    cand,
2366                    q_rows,
2367                    q_chosen,
2368                    top_k: d2.top_k,
2369                },
2370            ))
2371        } else {
2372            self.dspark_chain_sampled(e, dl, nd, n_vocab, anchor, sp, sctr, conf_emb)
2373        }
2374    }
2375
2376    /// FIRST-LIGHT forward (oracle contract): full non-causal attention over
2377    /// [ctx_features ; block], NO draft KV cache, NO sliding window (the oracle bypasses
2378    /// the reference mask machinery the same way — window/caching land in the round arm).
2379    ///
2380    /// `target_hidden`: [ctx, n_taps*hidden] (f32, device)  — raw tapped states.
2381    /// `noise_emb`:     [block, hidden] — target embed rows for [accepted, MASK x b-1].
2382    /// `pos`:           absolute positions for ctx rows THEN block rows (ctx+block i32).
2383    /// Returns final normed hidden [block, hidden] (feed target lm_head for draft logits).
2384    /// ctx features for `t` tapped rows: hidden_norm(fc(taps)) — the drafter's context
2385    /// representation, cacheable across rounds (append-only in committed-token order).
2386    pub fn ctx_features(
2387        &self,
2388        e: &Engine,
2389        taps: &CudaSlice<f32>,
2390        t: usize,
2391    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
2392        let c = &self.cfg;
2393        let n_taps = c.target_layer_ids.len();
2394        let fc_out = self.mm(e, &self.fc, taps, t, n_taps * c.hidden, c.hidden)?;
2395        let mut out = e.uninit(t * c.hidden)?;
2396        e.rms_norm(&fc_out, &self.hidden_norm, &mut out, c.hidden, t, c.eps)?;
2397        Ok(out)
2398    }
2399
2400    pub fn forward(
2401        &self,
2402        e: &Engine,
2403        target_hidden: &CudaSlice<f32>,
2404        noise_emb: &CudaSlice<f32>,
2405        pos: &[i32],
2406        ctx: usize,
2407    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
2408        let ctx_f = self.ctx_features(e, target_hidden, ctx)?;
2409        if let Ok(dir) = std::env::var("MEMRA_DFLASH_DUMP") {
2410            let v = e.dtoh(&ctx_f)?;
2411            let bytes: Vec<u8> = v.iter().flat_map(|f| f.to_le_bytes()).collect();
2412            std::fs::write(format!("{dir}/memra-ctx_features.f32"), bytes)?;
2413        }
2414        self.forward_block(e, &ctx_f, noise_emb, pos, ctx)
2415    }
2416
2417    /// Block forward over PRECOMPUTED ctx features (the round arm's entry: features are
2418    /// cached across rounds; only the block work repeats).
2419    pub fn forward_block(
2420        &self,
2421        e: &Engine,
2422        ctx_f: &CudaSlice<f32>,
2423        noise_emb: &CudaSlice<f32>,
2424        pos: &[i32],
2425        ctx: usize,
2426    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
2427        let c = &self.cfg;
2428        let (h, nh, nkv, hd) = (c.hidden, c.n_head, c.n_kv, c.head_dim);
2429        let b = c.block_size;
2430        assert_eq!(pos.len(), ctx + b, "pos covers ctx rows then block rows");
2431
2432        let pos_blk = e.htod_i32(&pos[ctx..])?;
2433
2434        let mut x = e.clone_dtod(noise_emb)?; // [b, hidden] residual stream
2435        for (li, l) in self.layers.iter().enumerate() {
2436            // input_layernorm on the block rows only (ctx features are norm-free per ref:
2437            // k/v project the SAME ctx_f every layer, un-layernormed).
2438            let mut xn = e.uninit(b * h)?;
2439            e.rms_norm(&x, &l.ln_in, &mut xn, h, b, c.eps)?;
2440            // DFlash2: dynamic conv WRAPS attention — q/k_noise/v_noise all project the
2441            // CONVOLVED block rows (reference decoder layer: prepare -> self_attn ->
2442            // finish, all inside the residual branch). ctx_f is never convolved.
2443            let mut attn_dyn: Option<CudaSlice<f32>> = None;
2444            if let Some(d2) = &self.dflash2 {
2445                let (xc, dyn_) = self.d2_conv_prepare(e, &d2.attn_conv[li], &xn, b)?;
2446                xn = xc;
2447                attn_dyn = Some(dyn_);
2448            }
2449
2450            // q from block; k/v from [ctx_f ; block-normed]
2451            let q0 = self.mm(e, &l.wq, &xn, b, h, nh * hd)?;
2452            let k0c = self.mm(e, &l.wk, ctx_f, ctx, h, nkv * hd)?;
2453            let v0c = self.mm(e, &l.wv, ctx_f, ctx, h, nkv * hd)?;
2454            let k0b = self.mm(e, &l.wk, &xn, b, h, nkv * hd)?;
2455            let v0b = self.mm(e, &l.wv, &xn, b, h, nkv * hd)?;
2456
2457            // per-head q/k rms norm (v passes through: ones weight trick not needed — the
2458            // qkv kernel norms rq+rk rows; concatenate k first).
2459            let mut k0 = e.uninit((ctx + b) * nkv * hd)?;
2460            e.copy_into(&mut k0, 0, &k0c, ctx * nkv * hd)?;
2461            e.copy_into(&mut k0, ctx * nkv * hd, &k0b, b * nkv * hd)?;
2462            let mut v = e.uninit((ctx + b) * nkv * hd)?;
2463            e.copy_into(&mut v, 0, &v0c, ctx * nkv * hd)?;
2464            e.copy_into(&mut v, ctx * nkv * hd, &v0b, b * nkv * hd)?;
2465
2466            if li == 0
2467                && let Ok(dir) = std::env::var("MEMRA_DFLASH_DUMP")
2468            {
2469                let v = e.dtoh(&q0)?;
2470                let bytes: Vec<u8> = v.iter().flat_map(|f| f.to_le_bytes()).collect();
2471                std::fs::write(format!("{dir}/memra-l0_q0.f32"), bytes)?;
2472            }
2473            let mut q = e.uninit(b * nh * hd)?;
2474            let mut k = e.uninit((ctx + b) * nkv * hd)?;
2475            // rms over head_dim rows: q has b*nh rows, k has (ctx+b)*nkv rows.
2476            e.rms_norm(&q0, &l.q_norm, &mut q, hd, b * nh, c.eps)?;
2477            if li == 0
2478                && let Ok(dir) = std::env::var("MEMRA_DFLASH_DUMP")
2479            {
2480                let v = e.dtoh(&q)?;
2481                let bytes: Vec<u8> = v.iter().flat_map(|f| f.to_le_bytes()).collect();
2482                std::fs::write(format!("{dir}/memra-l0_qn.f32"), bytes)?;
2483            }
2484            e.rms_norm(&k0, &l.k_norm, &mut k, hd, (ctx + b) * nkv, c.eps)?;
2485
2486            // rope: q at block positions, k at ctx-then-block positions (absolute).
2487            let norope = std::env::var("MEMRA_DFLASH_NOROPE").is_ok();
2488            if !norope {
2489                self.rope_rows(e, &mut q, &pos_blk, nh, b)?;
2490            }
2491            if li == 0
2492                && let Ok(dir) = std::env::var("MEMRA_DFLASH_DUMP")
2493            {
2494                let dump = |name: &str,
2495                            t: &cudarc::driver::CudaSlice<f32>|
2496                 -> Result<(), Box<dyn std::error::Error>> {
2497                    let v = e.dtoh(t)?;
2498                    let bytes: Vec<u8> = v.iter().flat_map(|f| f.to_le_bytes()).collect();
2499                    std::fs::write(format!("{dir}/memra-l0_{name}.f32"), bytes)?;
2500                    Ok(())
2501                };
2502                dump("xn", &xn)?;
2503                dump("q_prerope", &q)?;
2504            }
2505            // k rows are laid out [row, nkv, hd] with row-major tokens — rope_neox expects
2506            // (n_heads, n_tokens); ctx and block ropes run as one call over ctx+b tokens.
2507            let pos_all = e.htod_i32(pos)?;
2508            if !norope {
2509                self.rope_rows(e, &mut k, &pos_all, nkv, ctx + b)?;
2510            }
2511
2512            // full non-causal attention: every block query sees all ctx+b keys.
2513            let mut attn = e.uninit(b * nh * hd)?;
2514            let scale = 1.0f32 / (hd as f32).sqrt();
2515            // NAIVE SDPA for first light: fa_prefill's NON-CAUSAL arm with T != T_kv is
2516            // BROKEN (attn maxdiff 0.34 vs the torch oracle; q/k inputs bit-close — no
2517            // existing caller exercises that shape class, jsonl 2026-07-13). The 16 x
2518            // (ctx+16) block attention is tiny; the fa arm returns behind this seam once
2519            // its kernel is fixed + parity-gated.
2520            if self.dflash2.is_some() && c.layer_sliding[li] {
2521                // DFlash2 non-causal symmetric window (config is_causal=false, all
2522                // layers sliding). The kernel masks only keys OLDER than
2523                // q_pos-(window-1); the future side (k - q < window) never binds
2524                // because keys reach at most q_pos + block <= q_pos + window
2525                // (asserted at load). Positions must be contiguous — q_pos is derived
2526                // in-kernel as (T_kv - T) + qt.
2527                debug_assert!(pos.windows(2).all(|w| w[1] == w[0] + 1));
2528                d2_windowed_attn(
2529                    e,
2530                    &q,
2531                    &k,
2532                    &v,
2533                    &mut attn,
2534                    hd,
2535                    nh,
2536                    nkv,
2537                    b,
2538                    ctx + b,
2539                    scale,
2540                    c,
2541                    0,
2542                )?;
2543            } else if std::env::var("MEMRA_DFLASH_FA").is_ok() {
2544                e.fa_prefill(&q, &k, &v, &mut attn, hd, nh, nkv, b, ctx + b, scale, false)?;
2545            } else {
2546                e.sdpa_naive(&q, &k, &v, &mut attn, hd, nh, nkv, b, ctx + b, scale, false)?;
2547            }
2548
2549            let mut o = self.mm(e, &l.wo, &attn, b, nh * hd, h)?;
2550            if let (Some(d2), Some(dyn_)) = (&self.dflash2, &attn_dyn) {
2551                o = self.d2_conv_finish(e, &d2.attn_conv[li], &o, dyn_, b)?;
2552            }
2553            let mut x1 = e.uninit(b * h)?;
2554            e.add(&o, &x, &mut x1, b * h)?;
2555            if li == 0
2556                && let Ok(dir) = std::env::var("MEMRA_DFLASH_DUMP")
2557            {
2558                let dump = |name: &str,
2559                            t: &cudarc::driver::CudaSlice<f32>|
2560                 -> Result<(), Box<dyn std::error::Error>> {
2561                    let v = e.dtoh(t)?;
2562                    let bytes: Vec<u8> = v.iter().flat_map(|f| f.to_le_bytes()).collect();
2563                    std::fs::write(format!("{dir}/memra-l0_{name}.f32"), bytes)?;
2564                    Ok(())
2565                };
2566                dump("q", &q)?;
2567                dump("k", &k)?;
2568                dump("attn", &attn)?;
2569                dump("x1", &x1)?;
2570            }
2571
2572            // mlp (DFlash2: the same conv wrap — prepare on the post-ln rows, mlp on
2573            // the convolved rows, finish on the mlp output, then the residual add)
2574            let mut x1n = e.uninit(b * h)?;
2575            e.rms_norm(&x1, &l.ln_post, &mut x1n, h, b, c.eps)?;
2576            let mut mlp_dyn: Option<CudaSlice<f32>> = None;
2577            if let Some(d2) = &self.dflash2 {
2578                let (xc, dyn_) = self.d2_conv_prepare(e, &d2.mlp_conv[li], &x1n, b)?;
2579                x1n = xc;
2580                mlp_dyn = Some(dyn_);
2581            }
2582            let gate = self.mm(e, &l.w_gate, &x1n, b, h, c.n_ff)?;
2583            let up_ = self.mm(e, &l.w_up, &x1n, b, h, c.n_ff)?;
2584            let mut act = e.uninit(b * c.n_ff)?;
2585            e.silu_mul(&gate, &up_, &mut act, b * c.n_ff)?;
2586            let mut down = self.mm(e, &l.w_down, &act, b, c.n_ff, h)?;
2587            if let (Some(d2), Some(dyn_)) = (&self.dflash2, &mlp_dyn) {
2588                down = self.d2_conv_finish(e, &d2.mlp_conv[li], &down, dyn_, b)?;
2589            }
2590            let mut x2 = e.uninit(b * h)?;
2591            e.add(&down, &x1, &mut x2, b * h)?;
2592            x = x2;
2593            if let Ok(dir) = std::env::var("MEMRA_DFLASH_DUMP") {
2594                let v = e.dtoh(&x)?;
2595                let bytes: Vec<u8> = v.iter().flat_map(|f| f.to_le_bytes()).collect();
2596                std::fs::write(format!("{dir}/memra-layer{li}_out.f32"), bytes)?;
2597            }
2598        }
2599        let mut out = e.uninit(b * h)?;
2600        e.rms_norm(&x, &self.norm, &mut out, h, b, c.eps)?;
2601        Ok(out)
2602    }
2603}
2604
2605/// Draft KV cache (round-cost fix, 2026-07-13): per-layer normed+roped ctx K and raw ctx V,
2606/// append-only in committed order. Block K/V land TRANSIENTLY at [len..len+b] each round
2607/// (never committed — the reference crops them identically). Kills the per-round full-ctx
2608/// projection recompute (first light was O(ctx)/round -> 7 tok/s).
2609pub struct DflashKv {
2610    pub k: Vec<CudaSlice<f32>>, // per layer [cap + block, nkv*hd]
2611    pub v: Vec<CudaSlice<f32>>,
2612    pub len: usize,
2613    pub cap: usize,
2614    /// Trailing rows the drafter can still observe: `sliding_window + block_size`. Carried on
2615    /// the KV (not recomputed at call sites) so an export and an import cannot disagree about
2616    /// the geometry — see `DsparkSpecSession::draft_tail_rows`.
2617    window_rows: usize,
2618    /// `n_kv * head_dim * size_of::<f32>()` — the row unit for tail copies.
2619    row_bytes: usize,
2620    /// CONTEXT FLOOR (lane/spec-exclusions-20260902): the first ctx row that EXISTS. `0` on
2621    /// every cold-primed KV and every full-tail import (the pre-lane shape). A COLD-DRAFTER
2622    /// KV (`new_cold_at`) or a short-tail import (`from_tail` of a tail whose exporter had
2623    /// a floor) owns rows only from here up; the round attention's window floor is raised
2624    /// to it (`d2_windowed_attn`), so the rows below are never read, and an export never
2625    /// publishes them (`export_tail` starts at the floor). The drafter then simply sees a
2626    /// shorter context, which can move ACCEPTANCE, never output — verify arbitrates.
2627    floor: usize,
2628}
2629
2630impl DflashKv {
2631    pub fn new(
2632        e: &Engine,
2633        cfg: &DflashCfg,
2634        cap: usize,
2635    ) -> Result<Self, Box<dyn std::error::Error>> {
2636        let rowsz = cfg.n_kv * cfg.head_dim;
2637        let mut k = Vec::with_capacity(cfg.n_layer);
2638        let mut v = Vec::with_capacity(cfg.n_layer);
2639        for _ in 0..cfg.n_layer {
2640            k.push(e.uninit((cap + cfg.block_size) * rowsz)?);
2641            v.push(e.uninit((cap + cfg.block_size) * rowsz)?);
2642        }
2643        Ok(Self {
2644            k,
2645            v,
2646            len: 0,
2647            cap,
2648            window_rows: cfg.sliding_window.saturating_add(cfg.block_size),
2649            row_bytes: rowsz * std::mem::size_of::<f32>(),
2650            floor: 0,
2651        })
2652    }
2653
2654    /// A COLD DRAFTER at a restored trunk boundary (lane/spec-exclusions-20260902, the
2655    /// `MEMRA_SPEC_WARM=1` arm): a fresh KV whose logical length is already `pos` (the
2656    /// restored prefix the trunk cache holds) but which owns NO ctx rows below it —
2657    /// `floor == len == pos`. The restored prefix's tap features do not exist (the trunk
2658    /// planes hold K/V latents, not the tapped residual rows), and re-running the trunk to
2659    /// recover them is the prime the restore exists to skip; so instead the drafter starts
2660    /// with an empty context at the right absolute position and fills it from the suffix
2661    /// prime's taps and every committed round from there, exactly as a cold session over a
2662    /// shorter prompt would. Row addressing (rope positions, `kv.len == cache.pos` at every
2663    /// round boundary) is identical to a tail import; only the attention floor differs.
2664    ///
2665    /// The `window_rows` below the floor are zero-filled so a later `export_tail` (which
2666    /// starts at the floor anyway) can never publish uninitialised bytes even under a
2667    /// future geometry mistake — finite zeros are the same belt `from_tail` wears.
2668    ///
2669    /// REFUSES under `MEMRA_DFLASH2_SDPA_CLIP=0`: the legacy full-scan kernel has no floor
2670    /// arm (`d2_windowed_attn`), and a cold drafter that scored 2048 zero rows at e^0 each
2671    /// would draft silently worse; the caller serves the plain hit by name instead.
2672    pub fn new_cold_at(
2673        e: &Engine,
2674        cfg: &DflashCfg,
2675        cap: usize,
2676        pos: usize,
2677    ) -> Result<Self, Box<dyn std::error::Error>> {
2678        if !dflash2_sdpa_clip_on() {
2679            return Err(
2680                "cold drafter needs the clipped round attention (MEMRA_DFLASH2_SDPA_CLIP=0 \
2681                        selects the full-scan kernel, which has no context-floor arm)"
2682                    .into(),
2683            );
2684        }
2685        if pos > cap {
2686            return Err(
2687                format!("cold drafter position {pos} exceeds the session cap {cap}").into(),
2688            );
2689        }
2690        let mut kv = Self::new(e, cfg, cap)?;
2691        let rowsz = kv.row_bytes / std::mem::size_of::<f32>();
2692        let zero_from = pos.saturating_sub(kv.window_rows);
2693        if zero_from < pos {
2694            for li in 0..kv.k.len() {
2695                e.memset_zeros_view(&mut kv.k[li].slice_mut(zero_from * rowsz..pos * rowsz))?;
2696                e.memset_zeros_view(&mut kv.v[li].slice_mut(zero_from * rowsz..pos * rowsz))?;
2697            }
2698        }
2699        kv.len = pos;
2700        kv.floor = pos;
2701        Ok(kv)
2702    }
2703
2704    /// The first ctx row this KV owns (doc on the field): `0` unless the KV was born as a
2705    /// cold drafter or imported from a short (floor-bearing) tail.
2706    pub fn floor(&self) -> usize {
2707        self.floor
2708    }
2709}
2710
2711impl DflashDraft {
2712    /// Ingest `t` NEW ctx-feature rows (committed order, absolute positions `pos_new`) into
2713    /// the draft KV: per layer k/v projections + k head-norm + rope, appended at kv.len.
2714    pub fn ingest_ctx(
2715        &self,
2716        e: &Engine,
2717        kv: &mut DflashKv,
2718        feats: &CudaSlice<f32>,
2719        pos_new: &[i32],
2720        t: usize,
2721    ) -> Result<(), Box<dyn std::error::Error>> {
2722        let c = &self.cfg;
2723        let (h, nkv, hd) = (c.hidden, c.n_kv, c.head_dim);
2724        assert!(kv.len + t <= kv.cap, "draft kv overflow");
2725        let pos_d = e.htod_i32(pos_new)?;
2726        for (li, l) in self.layers.iter().enumerate() {
2727            let k0 = self.mm(e, &l.wk, feats, t, h, nkv * hd)?;
2728            let v0 = self.mm(e, &l.wv, feats, t, h, nkv * hd)?;
2729            let mut kn = e.uninit(t * nkv * hd)?;
2730            e.rms_norm(&k0, &l.k_norm, &mut kn, hd, t * nkv, c.eps)?;
2731            self.rope_rows(e, &mut kn, &pos_d, nkv, t)?;
2732            e.copy_into(&mut kv.k[li], kv.len * nkv * hd, &kn, t * nkv * hd)?;
2733            e.copy_into(&mut kv.v[li], kv.len * nkv * hd, &v0, t * nkv * hd)?;
2734        }
2735        kv.len += t;
2736        Ok(())
2737    }
2738
2739    /// Block forward over the CACHED ctx KV: only the 16 block rows are projected per layer;
2740    /// block K/V land transiently at kv[len..len+b]. Bit-class-identical to forward_block
2741    /// (same kernels, same per-row programs; ONLY the ctx K/V recompute is cached).
2742    pub fn forward_round(
2743        &self,
2744        e: &Engine,
2745        kv: &mut DflashKv,
2746        noise_emb: &CudaSlice<f32>,
2747        pos_block: &[i32],
2748    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
2749        let c = &self.cfg;
2750        let (h, nh, nkv, hd) = (c.hidden, c.n_head, c.n_kv, c.head_dim);
2751        let b = c.block_size;
2752        assert_eq!(pos_block.len(), b);
2753        let ctx = kv.len;
2754        let pos_blk = e.htod_i32(pos_block)?;
2755        let mut x = e.clone_dtod(noise_emb)?;
2756        for (li, l) in self.layers.iter().enumerate() {
2757            let mut xn = e.uninit(b * h)?;
2758            e.rms_norm(&x, &l.ln_in, &mut xn, h, b, c.eps)?;
2759            // DFlash2: dynamic conv wraps attention (see forward_block).
2760            let mut attn_dyn: Option<CudaSlice<f32>> = None;
2761            if let Some(d2) = &self.dflash2 {
2762                let (xc, dyn_) = self.d2_conv_prepare(e, &d2.attn_conv[li], &xn, b)?;
2763                xn = xc;
2764                attn_dyn = Some(dyn_);
2765            }
2766            let q0 = self.mm(e, &l.wq, &xn, b, h, nh * hd)?;
2767            let k0b = self.mm(e, &l.wk, &xn, b, h, nkv * hd)?;
2768            let v0b = self.mm(e, &l.wv, &xn, b, h, nkv * hd)?;
2769            let mut q = e.uninit(b * nh * hd)?;
2770            let mut kb = e.uninit(b * nkv * hd)?;
2771            e.rms_norm(&q0, &l.q_norm, &mut q, hd, b * nh, c.eps)?;
2772            e.rms_norm(&k0b, &l.k_norm, &mut kb, hd, b * nkv, c.eps)?;
2773            self.rope_rows(e, &mut q, &pos_blk, nh, b)?;
2774            self.rope_rows(e, &mut kb, &pos_blk, nkv, b)?;
2775            e.copy_into(&mut kv.k[li], ctx * nkv * hd, &kb, b * nkv * hd)?;
2776            e.copy_into(&mut kv.v[li], ctx * nkv * hd, &v0b, b * nkv * hd)?;
2777            let mut attn = e.uninit(b * nh * hd)?;
2778            let scale = 1.0f32 / (hd as f32).sqrt();
2779            if self.dflash2.is_some() && c.layer_sliding[li] {
2780                // Non-causal symmetric window (config is_causal=false): kv row index
2781                // == absolute position for BOTH ctx rows (committed order) and the
2782                // transient block rows, so the kernel's q_pos = (T_kv - T) + qt is the
2783                // absolute position and the old-side mask is exact. The future side
2784                // never binds (block <= window, asserted at load).
2785                d2_windowed_attn(
2786                    e,
2787                    &q,
2788                    &kv.k[li],
2789                    &kv.v[li],
2790                    &mut attn,
2791                    hd,
2792                    nh,
2793                    nkv,
2794                    b,
2795                    ctx + b,
2796                    scale,
2797                    c,
2798                    kv.floor,
2799                )?;
2800            } else if std::env::var("MEMRA_DFLASH_FA").is_ok() {
2801                e.fa_prefill(
2802                    &q,
2803                    &kv.k[li],
2804                    &kv.v[li],
2805                    &mut attn,
2806                    hd,
2807                    nh,
2808                    nkv,
2809                    b,
2810                    ctx + b,
2811                    scale,
2812                    false,
2813                )?;
2814            } else {
2815                e.sdpa_naive(
2816                    &q,
2817                    &kv.k[li],
2818                    &kv.v[li],
2819                    &mut attn,
2820                    hd,
2821                    nh,
2822                    nkv,
2823                    b,
2824                    ctx + b,
2825                    scale,
2826                    false,
2827                )?;
2828            }
2829            let mut o = self.mm(e, &l.wo, &attn, b, nh * hd, h)?;
2830            if let (Some(d2), Some(dyn_)) = (&self.dflash2, &attn_dyn) {
2831                o = self.d2_conv_finish(e, &d2.attn_conv[li], &o, dyn_, b)?;
2832            }
2833            let mut x1 = e.uninit(b * h)?;
2834            e.add(&o, &x, &mut x1, b * h)?;
2835            let mut x1n = e.uninit(b * h)?;
2836            e.rms_norm(&x1, &l.ln_post, &mut x1n, h, b, c.eps)?;
2837            let mut mlp_dyn: Option<CudaSlice<f32>> = None;
2838            if let Some(d2) = &self.dflash2 {
2839                let (xc, dyn_) = self.d2_conv_prepare(e, &d2.mlp_conv[li], &x1n, b)?;
2840                x1n = xc;
2841                mlp_dyn = Some(dyn_);
2842            }
2843            let gate = self.mm(e, &l.w_gate, &x1n, b, h, c.n_ff)?;
2844            let up_ = self.mm(e, &l.w_up, &x1n, b, h, c.n_ff)?;
2845            let mut act = e.uninit(b * c.n_ff)?;
2846            e.silu_mul(&gate, &up_, &mut act, b * c.n_ff)?;
2847            let mut down = self.mm(e, &l.w_down, &act, b, c.n_ff, h)?;
2848            if let (Some(d2), Some(dyn_)) = (&self.dflash2, &mlp_dyn) {
2849                down = self.d2_conv_finish(e, &d2.mlp_conv[li], &down, dyn_, b)?;
2850            }
2851            let mut x2 = e.uninit(b * h)?;
2852            e.add(&down, &x1, &mut x2, b * h)?;
2853            x = x2;
2854        }
2855        let mut out = e.uninit(b * h)?;
2856        e.rms_norm(&x, &self.norm, &mut out, h, b, c.eps)?;
2857        Ok(out)
2858    }
2859}
2860
2861/// Emit an accepted draft run under the `max_new` budget: check BEFORE each push — at
2862/// real acceptance the final round often accepts a draft at the boundary, and
2863/// push-then-check emitted max_new+1 tokens (plain emits exactly max_new; the E2E gate
2864/// read it as a length divergence at index max_new with the shared prefix
2865/// byte-identical). f8300340cd fixed generate_spec_dspark this way; generate_spec_dflash
2866/// kept the buggy shape until the hermes sweep (fixed 2026-08-23) — both now share this
2867/// one helper. Returns true when the caller must break (budget reached or EOS emitted).
2868fn emit_accepted_run(out: &mut Vec<u32>, accepted: &[u32], eos: &[u32], max_new: usize) -> bool {
2869    for &dt in accepted {
2870        if out.len() >= max_new {
2871            return true;
2872        }
2873        out.push(dt);
2874        if eos.contains(&dt) {
2875            return true;
2876        }
2877    }
2878    false
2879}
2880
2881// ===== THE DRAFT-SOURCE SEAM (lane/glm5-extract2, phase 2 of the extraction program) ======
2882//
2883// `DraftSourcePlan` (memra-gguf `model_plan.rs`) has always been general: it is the PLAN's
2884// statement of where a family's drafts come from. What was glm5-named was everything on the
2885// ENGINE side of it — the loaded-drafter holder, the flag-to-drafter load contract, and the
2886// tap-layer resolution. All three are family-agnostic by content, so they live here, in the
2887// general DFlash module, and glm5 is a CONSUMER.
2888//
2889// WHAT IS DELIBERATELY *NOT* HERE, and why (phase-1 discipline, restated):
2890// the PER-SESSION draft state (`glm_spec::Glm5DraftState`) and the source-keyed round /
2891// maintenance walks. Those are not family-agnostic today: each arm reaches into the family's
2892// own cache planes (glm5's MLA latent plane, `HcTapSink` hc-contract taps, the KDA rollback
2893// stash) and the retained-q type carries the family's rank space. A trait over them would have
2894// exactly ONE implementor whose associated types are all glm5 types — a decorative trait cut
2895// blind, on the hottest file in the lane program. The trigger for that cut is the SECOND
2896// hybrid spec family's session state, which is what tells us which half of the state is
2897// shared. The trait sketch is banked in the lane doc so the second consumer starts from it,
2898// not from scratch.
2899
2900/// A loaded alternate draft source: the drafter weights plus the byte identity they were
2901/// pinned by. Model-level (loaded ONCE per model, on the head engine where the trunk lm_head
2902/// it projects through lives — the MTP-head placement law); per-session state is the family's.
2903///
2904/// Generalized from `glm_spec::Glm5DflashDrafter`, which stays re-exported under its old name
2905/// for the glm5 call sites and gates.
2906pub struct DflashDrafter {
2907    pub draft: DflashDraft,
2908    /// First 8 hex of sha256(model.safetensors) — the boot-receipt identity pin
2909    /// (`b33c0347` for the probe-pinned incoai/GLM-5.3-Flash-DFlash2 @ dc77ff1c bytes).
2910    pub sha8: String,
2911}
2912
2913/// Resolve a drafter's tap layers against the trunk it will read features from.
2914///
2915/// PURE (no env, no engine): the drafter's own `target_layer_ids`, plus a caller-supplied
2916/// `shift` and the trunk bound. `shift` exists because the tap-shift RED ARM is a GATE
2917/// INSTRUMENT owned by the family that runs the gate (`MEMRA_GLM5_*_GATE_RED` is classified
2918/// as an instrument, never a serving flag, and never generalized) — the family reads its own
2919/// red-arm env, prints its own tag, and passes the shift in here.
2920pub fn resolve_tap_layers(
2921    target_layer_ids: &[usize],
2922    n_trunk: usize,
2923    shift: usize,
2924    what: &str,
2925) -> Result<Vec<usize>, String> {
2926    if target_layer_ids.is_empty() {
2927        return Err(format!("{what} drafter config carries no target_layer_ids"));
2928    }
2929    let taps: Vec<usize> = target_layer_ids.iter().map(|t| t + shift).collect();
2930    if let Some(&bad) = taps.iter().find(|&&t| t >= n_trunk) {
2931        return Err(format!(
2932            "{what} tap layer {bad} is outside the {n_trunk}-layer trunk"
2933        ));
2934    }
2935    Ok(taps)
2936}
2937
2938/// Load a DFlash2 drafter named by `flag` from `dir`, validating every contract that binds a
2939/// drafter to a TARGET — family-agnostic, because each one is a property of the pair, not of
2940/// the family:
2941///
2942/// * the checkpoint is a `DFlash2DraftModel` (the selector family is the only draft source
2943///   this seam serves);
2944/// * `cfg.hidden == n_embd` (the drafter consumes the target's features and projects through
2945///   the target's embed/lm_head);
2946/// * `cfg.target_layer_ids` name valid trunk layers;
2947/// * `cfg.mask_token_id` is inside the target vocab.
2948///
2949/// A set flag that cannot load is a LOUD failure, never a silent plain fallback. Every error
2950/// is prefixed `{flag}={dir}` so the operator sees the flag they typed; the glm5 call site's
2951/// message bytes are unchanged by construction.
2952pub fn load_drafter(
2953    e: &Engine,
2954    dir: &std::path::Path,
2955    flag: &str,
2956    n_trunk: usize,
2957    n_embd: usize,
2958    n_vocab: usize,
2959) -> Result<DflashDrafter, String> {
2960    let dpath = dir.display();
2961    let draft = DflashDraft::load(e, dir)
2962        .map_err(|err| format!("{flag}={dpath}: drafter load failed: {err}"))?;
2963    if draft.dflash2.is_none() {
2964        return Err(format!(
2965            "{flag}={dpath}: checkpoint is not a DFlash2DraftModel \
2966             (the glm5 draft source is the selector family only)"
2967        ));
2968    }
2969    if draft.cfg.hidden != n_embd {
2970        return Err(format!(
2971            "{flag}={dpath}: drafter hidden {} != target n_embd {n_embd} \
2972             (the drafter consumes target features and the target's embed/lm_head)",
2973            draft.cfg.hidden
2974        ));
2975    }
2976    if draft.cfg.target_layer_ids.is_empty()
2977        || draft.cfg.target_layer_ids.iter().any(|&t| t >= n_trunk)
2978    {
2979        return Err(format!(
2980            "{flag}={dpath}: target_layer_ids {:?} do not name valid \
2981             trunk layers (n_trunk {n_trunk})",
2982            draft.cfg.target_layer_ids
2983        ));
2984    }
2985    if draft.cfg.mask_token_id as usize >= n_vocab {
2986        return Err(format!(
2987            "{flag}={dpath}: mask token {} outside the target vocab {n_vocab}",
2988            draft.cfg.mask_token_id
2989        ));
2990    }
2991    let sha8 = crate::hybrid::sha256_file_hex8(&dir.join("model.safetensors"))
2992        .map_err(|err| format!("{flag}={dpath}: sha256 pin: {err}"))?;
2993    Ok(DflashDrafter { draft, sha8 })
2994}
2995
2996#[cfg(test)]
2997mod draft_source_seam_tests {
2998    use super::resolve_tap_layers;
2999
3000    #[test]
3001    fn taps_resolve_and_the_shift_is_the_callers() {
3002        assert_eq!(
3003            resolve_tap_layers(&[1, 12, 23], 46, 0, "glm5 DFlash2").unwrap(),
3004            vec![1, 12, 23]
3005        );
3006        // the red arm's +1 rides in as a parameter, not as an env read in here
3007        assert_eq!(
3008            resolve_tap_layers(&[1, 12, 23], 46, 1, "glm5 DFlash2").unwrap(),
3009            vec![2, 13, 24]
3010        );
3011    }
3012
3013    #[test]
3014    fn empty_and_out_of_trunk_taps_refuse_by_name() {
3015        let err = resolve_tap_layers(&[], 46, 0, "glm5 DFlash2").unwrap_err();
3016        assert!(err.contains("no target_layer_ids"), "{err}");
3017        let err = resolve_tap_layers(&[1, 46], 46, 0, "glm5 DFlash2").unwrap_err();
3018        assert!(
3019            err.contains("tap layer 46 is outside the 46-layer trunk"),
3020            "{err}"
3021        );
3022        // the SHIFTED tap is what gets bounds-checked — the red arm must not be able to
3023        // walk off the trunk silently
3024        let err = resolve_tap_layers(&[45], 46, 1, "glm5 DFlash2").unwrap_err();
3025        assert!(err.contains("tap layer 46 is outside"), "{err}");
3026    }
3027}
3028
3029#[cfg(test)]
3030mod emit_budget_tests {
3031    use super::emit_accepted_run;
3032
3033    #[test]
3034    fn accepted_run_never_exceeds_max_new() {
3035        // TOOTH (hermes finding, fixed 2026-08-23): the dflash accept loop pushed THEN
3036        // checked, emitting max_new+1 whenever the final round accepted at the boundary.
3037        let mut out = vec![1, 2, 3]; // 3 committed, budget 4: exactly ONE slot left
3038        let stop = emit_accepted_run(&mut out, &[10, 11, 12], &[], 4);
3039        assert!(stop, "hitting the budget must break the round loop");
3040        assert_eq!(
3041            out,
3042            vec![1, 2, 3, 10],
3043            "exactly max_new tokens, never max_new+1"
3044        );
3045        // EOS inside the run stops after emitting it (unchanged semantics).
3046        let mut out = vec![1];
3047        let stop = emit_accepted_run(&mut out, &[10, 99, 12], &[99], 8);
3048        assert!(stop);
3049        assert_eq!(out, vec![1, 10, 99]);
3050        // A run fitting the budget with no EOS lets the round continue.
3051        let mut out = vec![1];
3052        assert!(!emit_accepted_run(&mut out, &[10, 11], &[], 8));
3053        assert_eq!(out, vec![1, 10, 11]);
3054    }
3055}
3056
3057// ================= DFlash spec round (greedy, first light) =================
3058// Exact contract: identical output stream to plain greedy decode BY CONSTRUCTION — the
3059// target's batched verify argmax decides every committed token; the drafter only proposes.
3060// (Same verify+rewind pattern as generate_spec_gemma's eager round; t=16 verify rides the
3061// straddle-split-safe fa_decode_rows.)
3062impl crate::hybrid::HybridModel {
3063    pub fn generate_spec_dflash(
3064        &self,
3065        e: &Engine,
3066        draft: &DflashDraft,
3067        prompt: &[u32],
3068        max_new: usize,
3069        eos: &[u32],
3070    ) -> Result<Vec<u32>, Box<dyn std::error::Error>> {
3071        self.refuse_hyper("generate_spec_dflash")?;
3072        use crate::cache::{Cache, DflashTapSink};
3073        let n_embd = self.cfg.n_embd as usize;
3074        let c = &draft.cfg;
3075        assert!(
3076            draft.dflash2.is_none(),
3077            "DFlash2 drafters ride the qwen-hybrid dspark round (selector + windowed \
3078             attention); the gemma arm has no consumer for the family's ops"
3079        );
3080        assert_eq!(n_embd, c.hidden, "draft hidden must match target n_embd");
3081        let b = c.block_size;
3082        let n_taps = c.target_layer_ids.len();
3083        let max_ctx = prompt.len() + max_new + b + 8;
3084        // First light holds ctx <= sliding_window: the draft was trained with 4 sliding
3085        // layers (window 2048) and the first-light attention is windowless full — inside
3086        // the window the two are identical. The depth cell (1736 + 128) fits.
3087        assert!(
3088            max_ctx <= c.sliding_window,
3089            "first-light dflash round is windowless — ctx cap {} exceeds the draft window {}",
3090            max_ctx,
3091            c.sliding_window
3092        );
3093        let mut cache = Cache::new(e, &self.cfg, max_ctx)?;
3094
3095        // ---- prime with taps armed ----
3096        let tp = prompt.len();
3097        cache.dflash_taps = Some(DflashTapSink {
3098            layer_ids: c.target_layer_ids.clone(),
3099            buf: e.uninit(tp * n_taps * n_embd)?,
3100            hidden: n_embd,
3101            t: tp,
3102            base: 0,
3103        });
3104        let t_prime = std::time::Instant::now();
3105        let (logits, _h_seed, _hiddens) = self.prime_cache(e, prompt, &mut cache, 0)?;
3106        let mut last = crate::forward::argmax(&logits) as u32;
3107        // draft KV cache: ingest the prompt's ctx features once; per round only the kept
3108        // rows ingest + the block projects (round cost O(block), not O(ctx)).
3109        let mut dkv = DflashKv::new(e, &draft.cfg, max_ctx)?;
3110        {
3111            // CHUNKED ingest (depth OOM fix): the 1736-row prompt tap buffer is ~224MB f32;
3112            // running fc + 5-layer k/v projection over it in one shot stacks another
3113            // ~300MB of transients on the ~21.3GB trunk peak. 256-row windows bound the
3114            // transient set; identical values (row-independent ops).
3115            let taps = cache.dflash_taps.take().unwrap();
3116            let n_taps_h = n_taps * n_embd;
3117            let mut r0 = 0usize;
3118            while r0 < tp {
3119                let t_c = (tp - r0).min(256);
3120                let tv = e.view(&taps.buf, tp * n_taps_h);
3121                let win = tv.slice(r0 * n_taps_h..(r0 + t_c) * n_taps_h);
3122                let mut chunk = e.uninit(t_c * n_taps_h)?;
3123                e.copy_view_into(&mut chunk, 0, &win, t_c * n_taps_h)?;
3124                let f = draft.ctx_features(e, &chunk, t_c)?;
3125                let pos_c: Vec<i32> = ((r0 as i32)..(r0 + t_c) as i32).collect();
3126                draft.ingest_ctx(e, &mut dkv, &f, &pos_c, t_c)?;
3127                r0 += t_c;
3128            }
3129        }
3130        let mut ctx_len = tp;
3131        e.stream().synchronize()?;
3132        // published prime wall (the run-spec/gemma-gate timing contract subtracts it)
3133        crate::PRIME_NANOS.store(
3134            t_prime.elapsed().as_nanos() as u64,
3135            std::sync::atomic::Ordering::Relaxed,
3136        );
3137
3138        // embed-scale seam (MEMRA_DFLASH_EMB_SCALE): gemma trunks scale embeddings by
3139        // sqrt(n_embd) INSIDE the forward; whether the z-lab gemma4 training fed the
3140        // drafter scaled or raw embed rows is not visible from the reference (qwen path
3141        // uses raw embed_tokens). Acceptance arbitrates; default raw.
3142        let emb_scale = if std::env::var("MEMRA_DFLASH_EMB_SCALE").as_deref() == Ok("1") {
3143            (n_embd as f32).sqrt()
3144        } else {
3145            1.0
3146        };
3147
3148        let mut out = Vec::with_capacity(max_new);
3149        let n_vocab = self.output.out_features();
3150        // VERIFY WIDTH (MEMRA_DFLASH_VERIFY_T, default 8): the drafter always drafts a full
3151        // block (its trained mask pattern) but only the first vt rows go through the target
3152        // verify — the t=16 verify rides the untuned b16 tier at ~32% of the byte wall
3153        // (65ms/verify) while b8 rides the tuned r2 tier; with ~2.7 committed/round the
3154        // deep block positions almost never survive anyway. Exactness unaffected (verify
3155        // still decides every committed token).
3156        let vt_cap: usize = std::env::var("MEMRA_DFLASH_VERIFY_T")
3157            .ok()
3158            .and_then(|v| v.parse().ok())
3159            .unwrap_or(8)
3160            .clamp(2, b);
3161        // adaptive verify width (MEMRA_DFLASH_ADAPT!=0, MTP accepted+1 recipe): next round
3162        // verifies one past this round's accepted run, clamped [3, cap].
3163        let adapt = std::env::var("MEMRA_DFLASH_ADAPT").as_deref() != Ok("0");
3164        let mut vt = vt_cap;
3165        let mut attempted = 0usize;
3166        let mut accepted = 0usize;
3167        // The whole round runs in the decode-exact matmul scope: the m=16 draft mms were
3168        // otherwise falling into the prefill-GEMM class (770us/matmul, 17% of the depth
3169        // round). Prime (before this loop) keeps the prefill GEMM path. RAII: a `?` exit
3170        // anywhere in the loop restores the pre-scope value instead of latching exact ON
3171        // engine-wide (hermes finding, fixed 2026-08-23).
3172        let exact_scope = e.exact_scope(true);
3173        'outer: while out.len() < max_new {
3174            let start = cache.pos; // committed length
3175            // ---- draft: block = [last, MASK x b-1] ----
3176            let mut block: Vec<u32> = vec![c.mask_token_id; b];
3177            block[0] = last;
3178            let mut noise = e.htod(&self.embd.try_gather(n_embd, &block)?)?;
3179            if emb_scale != 1.0 {
3180                e.scale_inplace(&mut noise, emb_scale, b * n_embd)?;
3181            }
3182            if std::env::var("MEMRA_DFLASH_DEBUG").as_deref() == Ok("1") && start == cache.pos {
3183                let nv = e.dtoh(&noise)?;
3184                let r0: f32 = nv[..n_embd].iter().map(|x| x * x).sum::<f32>().sqrt();
3185                let r1: f32 = nv[n_embd..2 * n_embd]
3186                    .iter()
3187                    .map(|x| x * x)
3188                    .sum::<f32>()
3189                    .sqrt();
3190                eprintln!(
3191                    "[dflash noise] |row0(last)|={r0:.3} |row1(MASK id {})|={r1:.3}",
3192                    c.mask_token_id
3193                );
3194            }
3195            let pos_block: Vec<i32> = ((start as i32)..(start + b) as i32).collect();
3196            let dh = draft.forward_round(e, &mut dkv, &noise, &pos_block)?;
3197            // draft tokens = argmax(lm_head(h rows 1..b))
3198            let mut rows = e.uninit((b - 1) * n_embd)?;
3199            {
3200                let dv = e.view(&dh, b * n_embd);
3201                let tail = dv.slice(n_embd..b * n_embd);
3202                e.copy_view_into(&mut rows, 0, &tail, (b - 1) * n_embd)?;
3203            }
3204            let mut dl = e.matmul(&self.output, &rows, b - 1)?;
3205            // SEMI-AR MARKOV CHAIN (DSpark head, when present + MEMRA_DFLASH_MARKOV!=0):
3206            // left-to-right, logits_k += W2(W1[prev realized token]) — the whole chain
3207            // stays on-device (chain_d[0] = the pending token; argmax k writes
3208            // chain_d[k+1], the k+1 bias gathers from it). Greedy mirror of the patch's
3209            // _markov_semiar_sample_block.
3210            let markov_on = std::env::var("MEMRA_DFLASH_MARKOV").as_deref() != Ok("0");
3211            let mut chain_d = e.stream().alloc_zeros::<u32>(b)?;
3212            if let (Some(mk), true) = (&draft.markov, markov_on) {
3213                e.set_u32_one(&mut chain_d, last)?;
3214                for k in 0..(b - 1) {
3215                    let mut f = e.uninit(mk.rank)?;
3216                    e.gather_row_bf16(&mk.w1_bf16, &chain_d, k, &mut f, mk.rank)?;
3217                    let bias = e.matmul(&mk.w2, &f, 1)?;
3218                    e.add_row_inplace(&mut dl, &bias, n_vocab, k * n_vocab)?;
3219                    e.argmax_token_device_col(&dl, k, n_vocab, &mut chain_d, k + 1)?;
3220                }
3221            } else {
3222                for i in 0..(b - 1) {
3223                    e.argmax_token_device_col(&dl, i, n_vocab, &mut chain_d, i + 1)?;
3224                }
3225            }
3226            let chain = e.dtoh_u32(&chain_d)?;
3227            let dtoks = &chain[1..];
3228            for (i, &dt) in dtoks.iter().enumerate() {
3229                block[i + 1] = dt;
3230            }
3231            let dbg = std::env::var("MEMRA_DFLASH_DEBUG").as_deref() == Ok("1");
3232
3233            // ---- verify: one t=vt target forward with taps armed ----
3234            let vblock = &block[..vt];
3235            cache.dflash_taps = Some(DflashTapSink {
3236                layer_ids: c.target_layer_ids.clone(),
3237                buf: e.uninit(vt * n_taps * n_embd)?,
3238                hidden: n_embd,
3239                t: vt,
3240                base: 0,
3241            });
3242            let (vam, _vh) = self.gemma4_decode_step_t_am(e, vblock, start, &mut cache)?;
3243            let taps = cache.dflash_taps.take().unwrap();
3244            if dbg {
3245                eprintln!(
3246                    "[dflash r] start={start} last={last}\n  draft={:?}\n  vam  ={:?}",
3247                    &block[1..],
3248                    vam
3249                );
3250            }
3251
3252            // ---- accept ----
3253            let mut m = 0usize;
3254            while m < vt - 1 && block[m + 1] as usize == vam[m] as usize {
3255                m += 1;
3256            }
3257            attempted += vt - 1;
3258            accepted += m;
3259            out.push(last);
3260            if eos.contains(&last) {
3261                break 'outer;
3262            }
3263            if emit_accepted_run(&mut out, &block[1..=m], eos, max_new) {
3264                break 'outer;
3265            }
3266            let next = vam[m];
3267
3268            // ---- commit/rollback: keep m+1 of the b appended rows ----
3269            let keep = m + 1;
3270            for kvl in cache.kv.iter_mut().flatten() {
3271                kvl.len -= vt - keep;
3272                e.set_i32_one(&mut kvl.len_d, kvl.len as i32)?;
3273            }
3274            cache.pos -= vt - keep;
3275
3276            // ---- ingest the kept rows' ctx features into the draft KV ----
3277            {
3278                let tv = e.view(&taps.buf, vt * n_taps * n_embd);
3279                let keep_view = tv.slice(0..keep * n_taps * n_embd);
3280                let mut kept = e.uninit(keep * n_taps * n_embd)?;
3281                e.copy_view_into(&mut kept, 0, &keep_view, keep * n_taps * n_embd)?;
3282                let f = draft.ctx_features(e, &kept, keep)?;
3283                let pos_k: Vec<i32> = ((ctx_len as i32)..(ctx_len + keep) as i32).collect();
3284                draft.ingest_ctx(e, &mut dkv, &f, &pos_k, keep)?;
3285                ctx_len += keep;
3286            }
3287            last = next;
3288            if adapt {
3289                vt = (m + 2).clamp(3, vt_cap);
3290            }
3291        }
3292        drop(exact_scope);
3293        if std::env::var("MEMRA_SPEC_STATS").as_deref() == Ok("1") {
3294            eprintln!(
3295                "[dflash] acceptance {accepted}/{attempted} = {:.3}",
3296                accepted as f64 / attempted.max(1) as f64
3297            );
3298        }
3299        Ok(out)
3300    }
3301}
3302
3303// ================= Engine-bundle slice 1: batched GDN state snapshot ====================
3304// DSF-ROUNDCOST-20260820 §1.1 measured the dspark round's `cache.snapshot(e)` at 0.67 ms
3305// native wall — 48 linear layers x {conv, ssm} x (alloc_zeros + memcpy_dtod) of pure
3306// dispatch serialization, zero kernels. This batcher holds ONE persistent CacheSnapshot
3307// (buffers allocated on round 1, reused every round — kills the per-round alloc/memset
3308// churn) plus device pointer tables, so a round's snap is one small H2D table refresh
3309// (the ssm handles ping-pong per verify row, so live pointers are re-read each round;
3310// conv handles are rolled in place and never move) + TWO `copy_batch_uniform_f32`
3311// launches. Bytes, buffers and stream order are identical to `Cache::snapshot`; only the
3312// dispatch count changes, so acceptance and streams stay bit-identical (E2E-gated).
3313// `MEMRA_STATE_COPY_BATCH=0` reverts to the legacy per-layer snapshot.
3314
3315pub(crate) struct DsparkSnapBatch {
3316    pub(crate) snap: crate::cache::CacheSnapshot,
3317    /// Linear-attention layer indices, in `conv_table`/`ssm_table` order.
3318    lin: Vec<usize>,
3319    /// [src_0..src_{n-1}, dst_0..dst_{n-1}] — live conv states -> snapshot conv buffers.
3320    conv_table: CudaSlice<u64>,
3321    ssm_table: CudaSlice<u64>,
3322    host_ssm: Vec<u64>,
3323    conv_words: usize,
3324    ssm_words: usize,
3325}
3326
3327impl DsparkSnapBatch {
3328    /// Build from a fresh full snapshot (this IS round 1's snap — the caller uses
3329    /// `self.snap` directly after `new`). Returns None when the cache has no linear
3330    /// layers or their state sizes are non-uniform (a future hybrid shape) — the caller
3331    /// then stays on the legacy per-layer snapshot rather than copying wrong byte counts.
3332    pub(crate) fn new(
3333        e: &Engine,
3334        cache: &crate::cache::Cache,
3335    ) -> Result<Option<Self>, Box<dyn std::error::Error>> {
3336        use cudarc::driver::DevicePtr;
3337        let snap = cache.snapshot(e)?;
3338        let lin: Vec<usize> = (0..cache.recur.len())
3339            .filter(|&il| cache.recur[il].is_some())
3340            .collect();
3341        if lin.is_empty() {
3342            return Ok(None);
3343        }
3344        let first = cache.recur[lin[0]].as_ref().unwrap();
3345        let (conv_words, ssm_words) = (first.conv_state.len(), first.ssm_state.len());
3346        for &il in &lin {
3347            let rl = cache.recur[il].as_ref().unwrap();
3348            if rl.conv_state.len() != conv_words || rl.ssm_state.len() != ssm_words {
3349                return Ok(None);
3350            }
3351        }
3352        let n = lin.len();
3353        let mut host_conv = vec![0u64; 2 * n];
3354        let mut host_ssm = vec![0u64; 2 * n];
3355        {
3356            let s = &e.gpu.stream();
3357            for (k, &il) in lin.iter().enumerate() {
3358                let rl = cache.recur[il].as_ref().unwrap();
3359                let (pc, _g0) = rl.conv_state.device_ptr(s);
3360                let (ps, _g1) = rl.ssm_state.device_ptr(s);
3361                let (dc, _g2) = snap.conv[il].as_ref().unwrap().device_ptr(s);
3362                let (ds, _g3) = snap.ssm[il].as_ref().unwrap().device_ptr(s);
3363                host_conv[k] = pc;
3364                host_conv[n + k] = dc;
3365                host_ssm[k] = ps;
3366                host_ssm[n + k] = ds;
3367            }
3368        }
3369        let conv_table = e.htod_u64(&host_conv)?;
3370        let ssm_table = e.htod_u64(&host_ssm)?;
3371        Ok(Some(Self {
3372            snap,
3373            lin,
3374            conv_table,
3375            ssm_table,
3376            host_ssm,
3377            conv_words,
3378            ssm_words,
3379        }))
3380    }
3381
3382    /// The per-round snap: refresh kv lens/pos host-side (as `snapshot_into` does),
3383    /// re-read the live ssm handles into the table (gdn ping-pong moves them; the conv
3384    /// handles and every snapshot dst are stable), then two batched-copy launches.
3385    pub(crate) fn refresh(
3386        &mut self,
3387        e: &Engine,
3388        cache: &crate::cache::Cache,
3389    ) -> Result<(), Box<dyn std::error::Error>> {
3390        use cudarc::driver::DevicePtr;
3391        for il in 0..cache.kv.len() {
3392            self.snap.kv_len[il] = cache.kv[il].as_ref().map(|kvl| kvl.len);
3393        }
3394        self.snap.pos = cache.pos;
3395        let n = self.lin.len();
3396        {
3397            let s = &e.gpu.stream();
3398            for (k, &il) in self.lin.iter().enumerate() {
3399                let rl = cache.recur[il].as_ref().unwrap();
3400                let (ps, _g) = rl.ssm_state.device_ptr(s);
3401                self.host_ssm[k] = ps;
3402            }
3403        }
3404        e.htod_u64_into(&self.host_ssm, &mut self.ssm_table)?;
3405        e.copy_batch_uniform_f32(&self.conv_table, n, self.conv_words)?;
3406        e.copy_batch_uniform_f32(&self.ssm_table, n, self.ssm_words)?;
3407        Ok(())
3408    }
3409}
3410
3411// ================= DSpark spec round, QWEN-HYBRID target (lane/dspark-q38-recover) =====
3412// The q38 twin of generate_spec_dflash. Same drafter machinery (rounds, markov chain,
3413// draft KV, adaptive verify width); the TARGET side swaps gemma4's dense verify for the
3414// qwen serving-class verify funnel (dspark_verify_t_am) + snapshot/rollback, because the
3415// hybrid GDN conv/ssm state mutates in place — dense KV truncation cannot roll it back.
3416// Exactness contract unchanged: identical stream to plain greedy BY CONSTRUCTION (the
3417// target's verify argmax decides every committed token).
3418impl crate::hybrid::HybridModel {
3419    #[allow(clippy::type_complexity)] // allow: one-shot composite type; naming it would hide the shape that matters at the call site
3420    pub fn generate_spec_dspark(
3421        &self,
3422        e: &Engine,
3423        draft: &DflashDraft,
3424        prompt: &[u32],
3425        max_new: usize,
3426        eos: &[u32],
3427        sampling: Option<&crate::spec::SpecSampling>,
3428    ) -> Result<Vec<u32>, Box<dyn std::error::Error>> {
3429        self.refuse_hyper("generate_spec_dspark")?;
3430        use crate::cache::{Cache, DflashTapSink};
3431        assert!(
3432            !self.uses_gemma_program(),
3433            "gemma4 targets use generate_spec_dflash; this is the qwen-hybrid arm"
3434        );
3435        // SAMPLED ADMISSION (T>0, lane/dspark-sampled-admission-20260820): Some+temp>0
3436        // routes the round's proposal/accept through the rejection-sampling arms; None or
3437        // temp==0 keeps every greedy path byte-identical (the exactness instrument).
3438        let sp_on: Option<&crate::spec::SpecSampling> = sampling.filter(|s| s.temp > 0.0);
3439        // PENALTIES AT T==0 ARE A LOUD REFUSAL (lane/dspark-penalized-sampled-20260821):
3440        // the greedy walk argmaxes RAW verify columns, so a temp==0 config carrying
3441        // non-identity penalties would silently serve the UNPENALIZED greedy stream —
3442        // exactly the H-class silent-program-switch this route refuses everywhere else.
3443        // Penalized greedy stays on the plain path (worker admission owns the exclusion).
3444        if let Some(s) = sampling
3445            && s.temp <= 0.0
3446            && s.pen_on()
3447        {
3448            return Err(
3449                "dspark spec at temp==0 is the greedy route and would silently drop \
3450                     the request's penalties; penalized greedy is served on the plain path"
3451                    .into(),
3452            );
3453        }
3454        // Penalized-sampled state: the session window (pen_window_seed — one definition
3455        // across both spec routes), extended with every committed token; each round's
3456        // accept receives the trimmed tail (min(penalty_last_n, PEN_WINDOW_MAX)).
3457        let pen_on = sp_on.is_some_and(|s| s.pen_on());
3458        let mut pen_hist: Vec<u32> = if pen_on {
3459            crate::spec::pen_window_seed(&[], prompt, sp_on.unwrap().penalty_last_n)
3460        } else {
3461            Vec::new()
3462        };
3463        let (mut sctr, mut uctr) = (0u32, 0u32);
3464        let n_embd = self.cfg.n_embd as usize;
3465        let c = &draft.cfg;
3466        assert_eq!(n_embd, c.hidden, "draft hidden must match target n_embd");
3467        let b = c.block_size;
3468        let n_taps = c.target_layer_ids.len();
3469        let max_ctx = prompt.len() + max_new + b + 8;
3470        // DFlash2 implements the reference's non-causal symmetric sliding window in
3471        // the round attention (sdpa_naive_w), so depth past the window is admitted;
3472        // other families keep the historical windowless contract.
3473        assert!(
3474            draft.dflash2.is_some() || max_ctx <= c.sliding_window,
3475            "dspark round is windowless — ctx cap {} exceeds the draft window {}",
3476            max_ctx,
3477            c.sliding_window
3478        );
3479        let mut cache = Cache::new(e, &self.cfg, max_ctx)?;
3480
3481        // ---- prime with taps armed (chunked prime writes at chunk offsets via sink.base) ----
3482        let tp = prompt.len();
3483        cache.dflash_taps = Some(DflashTapSink {
3484            layer_ids: c.target_layer_ids.clone(),
3485            buf: e.uninit(tp * n_taps * n_embd)?,
3486            hidden: n_embd,
3487            t: tp,
3488            base: 0,
3489        });
3490        let t_prime = std::time::Instant::now();
3491        let (logits, _h_seed, _hiddens) = self.prime_cache(e, prompt, &mut cache, 0)?;
3492        // Boundary token: greedy takes the argmax (byte contract); sampled draws it from
3493        // the request's own filtered target through the session Philox stream — the same
3494        // shipped composition the frspec route uses (sample_check arm 9 oracles it).
3495        let mut last = match sp_on {
3496            Some(sp) => crate::spec::sample_boundary_token(
3497                e,
3498                &logits,
3499                sp,
3500                &pen_hist,
3501                &mut sctr,
3502                "dspark-prime",
3503            )?,
3504            None => crate::forward::argmax(&logits) as u32,
3505        };
3506        let mut dkv = DflashKv::new(e, &draft.cfg, max_ctx)?;
3507        {
3508            let taps = cache.dflash_taps.take().unwrap();
3509            let n_taps_h = n_taps * n_embd;
3510            let mut r0 = 0usize;
3511            while r0 < tp {
3512                let t_c = (tp - r0).min(256);
3513                let tv = e.view(&taps.buf, tp * n_taps_h);
3514                let win = tv.slice(r0 * n_taps_h..(r0 + t_c) * n_taps_h);
3515                let mut chunk = e.uninit(t_c * n_taps_h)?;
3516                e.copy_view_into(&mut chunk, 0, &win, t_c * n_taps_h)?;
3517                let f = draft.ctx_features(e, &chunk, t_c)?;
3518                let pos_c: Vec<i32> = ((r0 as i32)..(r0 + t_c) as i32).collect();
3519                draft.ingest_ctx(e, &mut dkv, &f, &pos_c, t_c)?;
3520                r0 += t_c;
3521            }
3522        }
3523        let mut ctx_len = tp;
3524        e.stream().synchronize()?;
3525        crate::PRIME_NANOS.store(
3526            t_prime.elapsed().as_nanos() as u64,
3527            std::sync::atomic::Ordering::Relaxed,
3528        );
3529
3530        let mut out = Vec::with_capacity(max_new);
3531        let n_vocab = self.output.out_features();
3532        // Harvest convention (DSPARK-POSTMORTEM-20260820.md): which drafter output rows
3533        // become draft candidates. nd = drafts/round; verify carries [anchor, drafts]
3534        // = up to nd+1 rows. FAMILY-keyed for DFlash2 (mask-fill by construction),
3535        // else default = the CHECKPOINT's own strategy census (owner-ratified flip,
3536        // 2026-08-20); explicit env still wins (contradiction refuses).
3537        let harvest = DsparkHarvest::for_draft(draft);
3538        let nd = harvest.n_drafts(b);
3539        let r0 = harvest.first_row();
3540        let vt_cap: usize = std::env::var("MEMRA_DFLASH_VERIFY_T")
3541            .ok()
3542            .and_then(|v| v.parse().ok())
3543            .unwrap_or(nd + 1)
3544            .clamp(2, nd + 1);
3545        let adapt = std::env::var("MEMRA_DFLASH_ADAPT").as_deref() != Ok("0");
3546        // Verify-window policy (H4, DSPARK-POSTMORTEM-20260820.md): default =
3547        // confidence-slot tau=.5 when the checkpoint carries an accept-rate head
3548        // (owner-ratified flip 2026-08-20; cell-3 tau ladder knee) — each round's
3549        // window is sized from the head's own slot scores, post-draft pre-verify.
3550        // Head-less checkpoints and MEMRA_DFLASH_ADAPT=0 keep the reactive ladder.
3551        let vt_policy = DsparkVtPolicy::resolve(draft.confidence.is_some());
3552        if vt_policy.is_confidence() {
3553            assert!(
3554                draft.confidence.is_some(),
3555                "MEMRA_DSPARK_VT={vt_policy:?} needs a checkpoint with an accept-rate \
3556                 head (confidence_head.* absent in this export)"
3557            );
3558        }
3559        let mut vt = vt_cap;
3560        let mut attempted = 0usize;
3561        let mut accepted = 0usize;
3562        // Engine-bundle slice 1: persistent batched snapshot (None until round 1; stays
3563        // None — legacy per-layer snapshot — under MEMRA_STATE_COPY_BATCH=0 or when the
3564        // batcher declines the cache shape).
3565        let mut snapb: Option<DsparkSnapBatch> = None;
3566        let mut snapb_off = !crate::spec::state_copy_batch_on();
3567        // Engine-bundle slice 2: deferred chain readback needs the resident embed table
3568        // (verify then embeds chain_d directly). Ladder/stash arms only — the confidence
3569        // policies size vt from a pre-verify head readback and keep the legacy order.
3570        let defer_rb = crate::spec::dspark_defer_readback_on() && !vt_policy.is_confidence();
3571        let (embd_qt, embd_rb) = self.embd.qt_and_row_bytes(n_embd);
3572        let embd_gpu = if !defer_rb || crate::spec::spec_host_embd() {
3573            None
3574        } else {
3575            Some(
3576                self.embd_gpu
3577                    .get_or_init(|| e.upload_u8(&self.embd.raw).expect("embed table upload")),
3578            )
3579        };
3580        // Engine-bundle slice 3: per-(segment, vt) verify graphs for the linear-layer runs
3581        // (rides the slice-2 deferred path only — device tokens keep the whole verify off
3582        // the host). PERSISTENT across generations on the model (rebuilding per call
3583        // re-captured ~80 graphs per prompt — measured 97.8 -> 79.1 tok/s e2e); the
3584        // captured bodies are cache-independent: all state reads go through per-round
3585        // refreshed pointer tables and ctx-owned slabs. None = eager walk, byte-identical.
3586        let mut vg_guard = self.dspark_vgraphs.lock().unwrap();
3587        if vg_guard.is_none() && embd_gpu.is_some() && crate::spec::dspark_verify_graph_on() {
3588            *vg_guard = crate::spec::DsparkVerifyGraphs::new(e, &cache, vt_cap, n_embd)?;
3589        }
3590        let vgraphs: &mut Option<crate::spec::DsparkVerifyGraphs> = &mut vg_guard;
3591        // per-phase economics counters (ns) — the verify-toll dataset
3592        let (mut ns_draft, mut ns_snap, mut ns_verify, mut ns_roll, mut ns_ingest) =
3593            (0u64, 0u64, 0u64, 0u64, 0u64);
3594        let mut rounds = 0usize;
3595        let stats = std::env::var("MEMRA_SPEC_STATS").as_deref() == Ok("1");
3596        let clock = |on: bool, e: &Engine| -> std::time::Instant {
3597            if on {
3598                let _ = e.stream().synchronize();
3599            }
3600            std::time::Instant::now()
3601        };
3602        'outer: while out.len() < max_new {
3603            rounds += 1;
3604            let start = cache.pos; // committed length
3605            // ---- draft: block = [last, MASK x b-1] (decode-exact class for the m=b mms) ----
3606            let t0 = clock(stats, e);
3607            // RAII: a `?` exit restores the pre-scope value instead of latching exact
3608            // ON engine-wide (hermes finding, fixed 2026-08-23).
3609            let exact_scope = e.exact_scope(true);
3610            let mut block: Vec<u32> = vec![c.mask_token_id; b];
3611            block[0] = last;
3612            let noise = e.htod(&self.embd.try_gather(n_embd, &block)?)?;
3613            let pos_block: Vec<i32> = ((start as i32)..(start + b) as i32).collect();
3614            let dh = draft.forward_round(e, &mut dkv, &noise, &pos_block)?;
3615            // Harvest: logits over rows r0..r0+nd (Dflash: mask rows 1..b-1, fill
3616            // semantics; Dspark: ALL b rows, shifted semantics — row k predicts
3617            // anchor+k+1, so col k of `dl` is the draft for position start+k+1).
3618            let mut rows = e.uninit(nd * n_embd)?;
3619            {
3620                let dv = e.view(&dh, b * n_embd);
3621                let src = dv.slice(r0 * n_embd..(r0 + nd) * n_embd);
3622                e.copy_view_into(&mut rows, 0, &src, nd * n_embd)?;
3623            }
3624            // TRIMMED DRAFT HEAD (lane/dflash2-head-trim, 2026-08-25): DFlash2 family
3625            // only — the selector consumes (value, candidate-id) pairs, so a d2t remap
3626            // after top-k restores true ids; the markov/chain arms argmax dl columns
3627            // into token ids DIRECTLY and must keep the full head. Reuses the FR-Spec
3628            // self-trim the load path builds on the MTP struct (MEMRA_FRSPEC_TRIM):
3629            // gathered rows of the target's own head, zero requant. Verify stays
3630            // full-vocab, so the trim moves draft acceptance only, never output.
3631            let trim = if draft.dflash2.is_some() {
3632                self.mtp
3633                    .as_ref()
3634                    .filter(|m| m.d2t_from_target_head)
3635                    .and_then(|m| m.shared_head_head.as_ref().zip(m.d2t.as_ref()))
3636                    // MEMRA_MTP_SKIP stub: the same target-head trimmed rows, parked in
3637                    // `dflash_trim` because the embedded MTP block was skipped (hybrid.rs;
3638                    // rows are target-head by construction; the loader refuses otherwise).
3639                    .or_else(|| self.dflash_trim.as_ref().map(|t| (&t.head, &t.d2t)))
3640                    .filter(|(_, d2t)| !d2t.is_empty())
3641            } else {
3642                None
3643            };
3644            let (dl_head, dl_vocab) = match trim {
3645                Some((head, d2t)) => (head, d2t.len()),
3646                None => (&self.output, n_vocab),
3647            };
3648            let trim_d2t = trim.map(|(_, d2t)| d2t.as_slice());
3649            let mut dl = e.matmul(dl_head, &rows, nd)?;
3650            // Family/sampling-keyed proposal (v0.100 train merge of the port and H4/
3651            // engine-bundle stacks — BOTH programs preserved):
3652            //  - SAMPLED (sp_on): rejection-sampling proposal, records the true per-slot
3653            //    q (family-keyed inside: selector for DFlash2, markov-corrected rows
3654            //    otherwise). Host CDF/readback syncs inside — slice-2 deferral N/A.
3655            //  - DFlash2 greedy: the candidate path selector REPLACES the markov chain
3656            //    (reference DFlash2DraftModel.propose — greedy arm).
3657            //  - markov/plain greedy chain: the engine-bundle arm; slice-2 readback
3658            //    deferral decided below (needs the ckpt arm reads).
3659            // Confidence policy: stash each slot's markov prev-token embedding (the
3660            // exact `w1` row the chain gathers) into a [nd, rank] buffer — d2d async,
3661            // read back beside `rows` in one host sync after the chain.
3662            let want_conf_emb = vt_policy.is_confidence()
3663                && draft.confidence.as_ref().is_some_and(|ch| ch.with_markov);
3664            let mut conf_emb: Option<CudaSlice<f32>> = match (&draft.markov, want_conf_emb) {
3665                (Some(mk), true) => Some(e.uninit(nd * mk.rank)?),
3666                (None, true) => unreachable!(
3667                    "with_markov confidence head without a markov table — the loader forbids it"
3668                ),
3669                _ => None,
3670            };
3671            let mut cand: Vec<u32> = Vec::with_capacity(nd + 1);
3672            let mut prop: Option<DsparkDraftSample> = None;
3673            let mut chain_dev: Option<CudaSlice<u32>> = None;
3674            if let Some(sp) = sp_on {
3675                let (tail, ds) = draft.dspark_propose_sampled(
3676                    e,
3677                    &mut dl,
3678                    &rows,
3679                    nd,
3680                    dl_vocab,
3681                    last,
3682                    sp,
3683                    &mut sctr,
3684                    &mut uctr,
3685                    conf_emb.as_mut(),
3686                    trim_d2t,
3687                )?;
3688                drop(exact_scope);
3689                cand.push(last);
3690                cand.extend_from_slice(&tail);
3691                prop = Some(ds);
3692            } else if draft.dflash2.is_some() {
3693                let path =
3694                    draft.dflash2_propose_greedy(e, &dl, &rows, nd, dl_vocab, last, trim_d2t)?;
3695                drop(exact_scope);
3696                cand.push(last);
3697                cand.extend_from_slice(&path);
3698            } else {
3699                let markov_on = std::env::var("MEMRA_DFLASH_MARKOV").as_deref() != Ok("0");
3700                let mut chain_d = e.stream().alloc_zeros::<u32>(nd + 1)?;
3701                if let (Some(mk), true) = (&draft.markov, markov_on) {
3702                    e.set_u32_one(&mut chain_d, last)?;
3703                    for k in 0..nd {
3704                        let mut f = e.uninit(mk.rank)?;
3705                        e.gather_row_bf16(&mk.w1_bf16, &chain_d, k, &mut f, mk.rank)?;
3706                        if let Some(ce) = conf_emb.as_mut() {
3707                            let fv = e.view(&f, mk.rank);
3708                            e.copy_view_into(ce, k * mk.rank, &fv, mk.rank)?;
3709                        }
3710                        let bias = e.matmul(&mk.w2, &f, 1)?;
3711                        e.add_row_inplace(&mut dl, &bias, n_vocab, k * n_vocab)?;
3712                        e.argmax_token_device_col(&dl, k, n_vocab, &mut chain_d, k + 1)?;
3713                    }
3714                } else {
3715                    if want_conf_emb {
3716                        // chain_d[0] must carry the anchor — slot 0's prev token.
3717                        e.set_u32_one(&mut chain_d, last)?;
3718                    }
3719                    for i in 0..nd {
3720                        if let (Some(ce), Some(mk)) = (conf_emb.as_mut(), &draft.markov) {
3721                            let mut f = e.uninit(mk.rank)?;
3722                            e.gather_row_bf16(&mk.w1_bf16, &chain_d, i, &mut f, mk.rank)?;
3723                            let fv = e.view(&f, mk.rank);
3724                            e.copy_view_into(ce, i * mk.rank, &fv, mk.rank)?;
3725                        }
3726                        e.argmax_token_device_col(&dl, i, n_vocab, &mut chain_d, i + 1)?;
3727                    }
3728                }
3729                drop(exact_scope);
3730                chain_dev = Some(chain_d);
3731            }
3732            // MEMRA_DSPARK_CKPT (default 1): verify with the MTP column-stash armed so a
3733            // partial accept restores state directly. =0 keeps the snapshot+replay arm
3734            // (the oracle the stash arm is gated against — MEMRA_DSPARK_CKPT_GATE=1 runs
3735            // BOTH per partial round and byte-compares the resulting cache state).
3736            // Read here (was at the verify site) — slice 2's deferral needs the arm
3737            // choice before deciding whether the chain readback can move past verify.
3738            let ckpt_on = std::env::var("MEMRA_DSPARK_CKPT").as_deref() != Ok("0");
3739            let ckpt_gate = std::env::var("MEMRA_DSPARK_CKPT_GATE").as_deref() == Ok("1");
3740            // SAMPLED x ckpt-gate refusal: the gate compares verify argmaxes across a
3741            // replay — a greedy-exactness instrument (port lane). Refuse loudly.
3742            if sp_on.is_some() && ckpt_gate {
3743                return Err(
3744                    "MEMRA_DSPARK_CKPT_GATE compares verify argmaxes across a replay \
3745                            — a greedy-exactness instrument; unset it for T>0 dspark rounds"
3746                        .into(),
3747                );
3748            }
3749            // Slice 2: under the stash/gate arms with a resident embed table, the GREEDY
3750            // chain readback is DEFERRED past verify dispatch and merged with the argmax
3751            // readback into one sync. The replay arm (CKPT=0) verifies host tokens and
3752            // keeps the legacy order; the sampled and DFlash2 proposals already synced
3753            // at the walk (chain_dev is None there).
3754            let deferred = chain_dev.is_some() && embd_gpu.is_some() && (ckpt_on || ckpt_gate);
3755            // ---- H4 confidence window: size THIS round's verify from the head ----
3756            if vt_policy.is_confidence() {
3757                let ch = draft.confidence.as_ref().expect("asserted at loop entry");
3758                let (rows_h, emb_h) = match conf_emb.as_ref() {
3759                    Some(ce) => {
3760                        let (a, b2) = e.dtoh_pair(&rows, ce)?;
3761                        (a, Some(b2))
3762                    }
3763                    None => (e.dtoh(&rows)?, None),
3764                };
3765                let rank = draft.markov.as_ref().map(|m| m.rank).unwrap_or(0);
3766                let mut raws = Vec::with_capacity(nd);
3767                for k in 0..nd {
3768                    let hrow = &rows_h[k * n_embd..(k + 1) * n_embd];
3769                    let emb = emb_h.as_ref().map(|eh| &eh[k * rank..(k + 1) * rank]);
3770                    raws.push(ch.raw_score(hrow, emb));
3771                }
3772                vt = vt_policy
3773                    .size_window(&raws, vt_cap)
3774                    .expect("confidence policies always size the window");
3775            }
3776            // Verify candidates: [anchor, draft 1..nd]. Under Dflash this is the
3777            // historical `block` content; under Dspark it is one longer than the
3778            // drafter's input block (nd = b drafts + the anchor). The sampled/DFlash2
3779            // proposals built `cand` at the walk; deferred greedy rounds build it after
3780            // the merged readback — the bytes are identical (chain_d is written before
3781            // either sync).
3782            if let Some(chain_d) = chain_dev.as_ref()
3783                && !deferred
3784            {
3785                let chain = e.dtoh_u32(chain_d)?;
3786                cand.push(last);
3787                cand.extend_from_slice(&chain[1..]);
3788            }
3789            ns_draft += clock(stats, e).duration_since(t0).as_nanos() as u64;
3790
3791            // ---- snapshot (GDN conv/ssm state + KV lens), then verify t=vt ----
3792            let t1 = std::time::Instant::now();
3793            // Slice 1: batched snap (one table refresh + two copy launches) with the
3794            // legacy per-layer snapshot as the kill-switch / non-uniform fallback.
3795            let mut snap_legacy: Option<crate::cache::CacheSnapshot> = None;
3796            if !snapb_off && snapb.is_none() {
3797                snapb = DsparkSnapBatch::new(e, &cache)?;
3798                snapb_off = snapb.is_none();
3799            } else if let Some(sb) = snapb.as_mut() {
3800                sb.refresh(e, &cache)?;
3801            }
3802            let snap: &crate::cache::CacheSnapshot = match snapb.as_ref() {
3803                Some(sb) => &sb.snap,
3804                None => {
3805                    snap_legacy = Some(cache.snapshot(e)?);
3806                    snap_legacy.as_ref().unwrap()
3807                }
3808            };
3809            let _ = &snap_legacy;
3810            ns_snap += clock(stats, e).duration_since(t1).as_nanos() as u64;
3811            let t2 = std::time::Instant::now();
3812            // Slice 3: the tap-sink buffer is persistent per vt in the graphs ctx
3813            // (captured segments bake its address); fully rewritten by every verify.
3814            let tap_buf = match vgraphs.as_mut().and_then(|g| g.tap_bufs.remove(&vt)) {
3815                Some(buf) => buf,
3816                None => e.uninit(vt * n_taps * n_embd)?,
3817            };
3818            cache.dflash_taps = Some(DflashTapSink {
3819                layer_ids: c.target_layer_ids.clone(),
3820                buf: tap_buf,
3821                hidden: n_embd,
3822                t: vt,
3823                base: 0,
3824            });
3825            // The whole fallible verify window runs inside a closure so the Err path can
3826            // return the sink buffer to the ctx pool before propagating (v0.98 review
3827            // carry-over): five `?`s span the window, and an early return would drop
3828            // `cache.dflash_taps` — freeing the buffer whose ADDRESS the model-persistent
3829            // captured graphs bake, so the next generation's replayed tap copies would
3830            // write freed memory. The never-orphan invariant below now holds on EVERY
3831            // exit, not just the EOS/budget break.
3832            let verify_res = (|cache: &mut crate::cache::Cache,
3833                               cand: &mut Vec<u32>,
3834                               vgraphs: &mut Option<crate::spec::DsparkVerifyGraphs>|
3835             -> Result<
3836                (
3837                    Vec<u32>,
3838                    Option<CudaSlice<f32>>,
3839                    Option<crate::spec::DsparkVerifyCkpt>,
3840                ),
3841                Box<dyn std::error::Error>,
3842            > {
3843                if sp_on.is_some() {
3844                    // SAMPLED: keep the raw verify logits — the accept walk gathers
3845                    // filtered p from them (argmaxes are the greedy arm's instrument,
3846                    // not this one's).
3847                    if ckpt_on {
3848                        let (tl, vck) =
3849                            self.dspark_verify_t_logits_ckpt(e, &cand[..vt], start, cache)?;
3850                        Ok((Vec::new(), Some(tl), Some(vck)))
3851                    } else {
3852                        Ok((
3853                            Vec::new(),
3854                            Some(self.dspark_verify_t_logits(e, &cand[..vt], start, cache)?),
3855                            None,
3856                        ))
3857                    }
3858                } else if deferred {
3859                    // Slice 2: verify embeds the DEVICE chain (cand layout by construction:
3860                    // chain_d[0] = anchor, chain_d[1..] = drafts), then ONE host sync reads
3861                    // chain + verify argmaxes together — the host dispatched snap + all of
3862                    // verify while the draft was still executing.
3863                    let chain_d = chain_dev.as_ref().expect("deferred implies greedy chain");
3864                    let g = embd_gpu.expect("deferred implies resident embed");
3865                    let (am_d, vck) = self.dspark_verify_t_am_ckpt_dev(
3866                        e,
3867                        chain_d,
3868                        vt,
3869                        start,
3870                        cache,
3871                        (g, embd_qt, embd_rb),
3872                        vgraphs.as_mut(),
3873                    )?;
3874                    let ch = e.stream().clone_dtoh(chain_d)?;
3875                    let am = e.stream().clone_dtoh(&am_d)?;
3876                    e.stream().synchronize()?;
3877                    cand.push(last);
3878                    cand.extend_from_slice(&ch[1..]);
3879                    Ok((am, None, Some(vck)))
3880                } else if ckpt_on || ckpt_gate {
3881                    let (vam, vck) = self.dspark_verify_t_am_ckpt(e, &cand[..vt], start, cache)?;
3882                    Ok((vam, None, Some(vck)))
3883                } else {
3884                    Ok((
3885                        self.dspark_verify_t_am(e, &cand[..vt], start, cache)?,
3886                        None,
3887                        None,
3888                    ))
3889                }
3890            })(&mut cache, &mut cand, vgraphs);
3891            let (vam, tl, vck) = match verify_res {
3892                Ok(v) => v,
3893                Err(err) => {
3894                    if let (Some(g), Some(taps)) = (vgraphs.as_mut(), cache.dflash_taps.take()) {
3895                        g.tap_bufs.insert(vt, taps.buf);
3896                    }
3897                    return Err(err);
3898                }
3899            };
3900            let taps = cache.dflash_taps.take().unwrap();
3901            // Return the tap buffer to the ctx pool IMMEDIATELY — an EOS/budget break
3902            // between accept and ingest must never orphan an address the captured
3903            // graphs bake (the next generation would alloc a fresh buffer and the
3904            // replayed tap copies would write freed memory). Ingest reads it borrowed.
3905            let tap_local: Option<CudaSlice<f32>> = match vgraphs.as_mut() {
3906                Some(g) => {
3907                    g.tap_bufs.insert(vt, taps.buf);
3908                    None
3909                }
3910                None => Some(taps.buf),
3911            };
3912            let tap_ref: &CudaSlice<f32> = match &tap_local {
3913                Some(b) => b,
3914                None => &vgraphs.as_ref().expect("ctx present above").tap_bufs[&vt],
3915            };
3916            ns_verify += clock(stats, e).duration_since(t2).as_nanos() as u64;
3917
3918            // ---- accept ----
3919            // Penalized-sampled: the anchor `last` is committed THIS round unconditionally
3920            // (the out.push below), so it joins the window before the accept walk — verify
3921            // row 0's state includes it. Accepted drafts extend the window after the walk;
3922            // `next` joins as the anchor of ITS round.
3923            if pen_on {
3924                pen_hist.push(last);
3925            }
3926            let (m, next) = match (sp_on, tl.as_ref()) {
3927                (Some(sp), Some(tl)) => {
3928                    let w0 = pen_hist
3929                        .len()
3930                        .saturating_sub(sp.penalty_last_n.min(crate::spec::PEN_WINDOW_MAX));
3931                    dspark_accept_sampled(
3932                        e,
3933                        tl,
3934                        &cand,
3935                        vt,
3936                        n_vocab,
3937                        &dl,
3938                        prop.as_ref()
3939                            .expect("sampled round without a proposal record"),
3940                        sp,
3941                        &pen_hist[w0..],
3942                        &mut sctr,
3943                        &mut uctr,
3944                    )?
3945                }
3946                _ => {
3947                    let m = dspark_accept_prefix(&cand, &vam, vt);
3948                    (m, vam[m])
3949                }
3950            };
3951            if pen_on {
3952                pen_hist.extend_from_slice(&cand[1..=m]);
3953            }
3954            attempted += vt - 1;
3955            accepted += m;
3956            out.push(last);
3957            if eos.contains(&last) {
3958                break 'outer;
3959            }
3960            if emit_accepted_run(&mut out, &cand[1..=m], eos, max_new) {
3961                break 'outer;
3962            }
3963
3964            // ---- commit/rollback: hybrid state cannot truncate — restore + replay kept ----
3965            let keep = m + 1;
3966            let t3 = std::time::Instant::now();
3967            // Slice 3: rounds whose linear column stash lives in the graphs ctx's slabs
3968            // commit through the slab twin (same semantics, slab-addressed sources).
3969            let slab_commit = vgraphs.as_ref().map(|g| g.round_slab).unwrap_or(false);
3970            if keep < vt {
3971                if ckpt_gate {
3972                    // GATE ARM: stash-restore, snapshot S1; then the replay oracle, snapshot
3973                    // S2; the two cache states must match BIT-FOR-BIT (kv lens, pos, every
3974                    // conv/ssm buffer). Continue from the replay state (proven identical).
3975                    if slab_commit {
3976                        self.dspark_commit_prefix_slab(
3977                            e,
3978                            &mut cache,
3979                            snap,
3980                            vgraphs.as_ref().expect("slab_commit implies ctx"),
3981                            keep,
3982                        )?;
3983                    } else {
3984                        let vck = vck.as_ref().expect("gate arm always fills the ckpt");
3985                        self.dspark_commit_prefix(e, &mut cache, snap, vck, keep)?;
3986                    }
3987                    // host-side state capture (NO device snapshot copies — two extra
3988                    // device snapshots per round OOM'd beside the 15GB trunk)
3989                    #[allow(clippy::type_complexity)]
3990                    // allow: one-shot composite type; naming it would hide the shape that matters at the call site
3991                    let capture = |cache: &Cache| -> Result<
3992                        (usize, Vec<Option<usize>>, Vec<(Vec<f32>, Vec<f32>)>),
3993                        Box<dyn std::error::Error>,
3994                    > {
3995                        let mut lens = Vec::new();
3996                        let mut states = Vec::new();
3997                        for il in 0..cache.kv.len() {
3998                            lens.push(cache.kv[il].as_ref().map(|k| k.len));
3999                            if let Some(rl) = &cache.recur[il] {
4000                                states.push((e.dtoh(&rl.conv_state)?, e.dtoh(&rl.ssm_state)?));
4001                            }
4002                        }
4003                        Ok((cache.pos, lens, states))
4004                    };
4005                    let (p1, l1, st1) = capture(&cache)?;
4006                    crate::pp::restore_cache_checkpoint(e, self, None, &mut cache, snap)?;
4007                    let ram = self.dspark_verify_t_am(e, &cand[..keep], start, &mut cache)?;
4008                    assert_eq!(
4009                        &ram[..],
4010                        &vam[..keep],
4011                        "prefix replay must reproduce the verify argmaxes"
4012                    );
4013                    let (p2, l2, st2) = capture(&cache)?;
4014                    assert_eq!(p1, p2, "ckpt-gate: pos mismatch");
4015                    assert_eq!(l1, l2, "ckpt-gate: kv_len mismatch");
4016                    for (il, ((c1, s1v), (c2, s2v))) in st1.iter().zip(&st2).enumerate() {
4017                        let bits = |a: &[f32], b: &[f32]| {
4018                            a.iter().zip(b).all(|(x, y)| x.to_bits() == y.to_bits())
4019                        };
4020                        assert!(
4021                            bits(c1, c2),
4022                            "ckpt-gate: linear layer {il} conv state differs"
4023                        );
4024                        assert!(
4025                            bits(s1v, s2v),
4026                            "ckpt-gate: linear layer {il} ssm state differs"
4027                        );
4028                    }
4029                } else if slab_commit {
4030                    // STASH ARM, slab twin (slice 3): same restore, slab-addressed.
4031                    self.dspark_commit_prefix_slab(
4032                        e,
4033                        &mut cache,
4034                        snap,
4035                        vgraphs.as_ref().expect("slab_commit implies ctx"),
4036                        keep,
4037                    )?;
4038                } else if let Some(vck) = vck.as_ref() {
4039                    // STASH ARM (default): column-state restore, no replay forward.
4040                    self.dspark_commit_prefix(e, &mut cache, snap, vck, keep)?;
4041                } else {
4042                    // REPLAY ARM (MEMRA_DSPARK_CKPT=0): the original snapshot+replay oracle.
4043                    crate::pp::restore_cache_checkpoint(e, self, None, &mut cache, snap)?;
4044                    debug_assert_eq!(cache.pos, start, "rollback landed off the round start");
4045                    let ram = self.dspark_verify_t_am(e, &cand[..keep], start, &mut cache)?;
4046                    if sp_on.is_none() {
4047                        // the argmax-reproduction oracle is greedy-only; the sampled arm
4048                        // replays purely to rebuild the cache state.
4049                        debug_assert_eq!(
4050                            &ram[..],
4051                            &vam[..keep],
4052                            "prefix replay must reproduce the verify argmaxes"
4053                        );
4054                    }
4055                }
4056            }
4057            ns_roll += clock(stats, e).duration_since(t3).as_nanos() as u64;
4058
4059            // ---- ingest the kept rows' ctx features into the draft KV ----
4060            let t4 = std::time::Instant::now();
4061            {
4062                let tv = e.view(tap_ref, vt * n_taps * n_embd);
4063                let keep_view = tv.slice(0..keep * n_taps * n_embd);
4064                let mut kept = e.uninit(keep * n_taps * n_embd)?;
4065                e.copy_view_into(&mut kept, 0, &keep_view, keep * n_taps * n_embd)?;
4066                let f = draft.ctx_features(e, &kept, keep)?;
4067                let pos_k: Vec<i32> = ((ctx_len as i32)..(ctx_len + keep) as i32).collect();
4068                draft.ingest_ctx(e, &mut dkv, &f, &pos_k, keep)?;
4069                ctx_len += keep;
4070            }
4071            ns_ingest += clock(stats, e).duration_since(t4).as_nanos() as u64;
4072            last = next;
4073            // Ladder update only — under the confidence policies vt is recomputed
4074            // from the head every round, post-draft pre-verify.
4075            if !vt_policy.is_confidence() && adapt {
4076                vt = (m + 2).clamp(3, vt_cap);
4077            }
4078        }
4079        if stats {
4080            let ms = |n: u64| n as f64 / 1e6;
4081            eprintln!(
4082                "[dspark-q38] acceptance {accepted}/{attempted} = {:.3} rounds={rounds} \
4083                 draft={:.1}ms snap={:.1}ms verify={:.1}ms rollback+replay={:.1}ms ingest={:.1}ms",
4084                accepted as f64 / attempted.max(1) as f64,
4085                ms(ns_draft),
4086                ms(ns_snap),
4087                ms(ns_verify),
4088                ms(ns_roll),
4089                ms(ns_ingest)
4090            );
4091        }
4092        Ok(out)
4093    }
4094}
4095
4096// ================= DSpark SERVING session (lane/dspark-q38-recover serve route) =========
4097// Burst-scoped state for the worker's dspark spec arm — the qwen-hybrid twin of
4098// GemmaSpecSession. Holds the trunk cache + draft KV + the round loop's carry state
4099// (`last`, ctx_len, adaptive vt) so the scheduler round-robins other sessions between
4100// bursts. The round body is generate_spec_dspark's loop, hoisted; that bin arm stays the
4101// banked oracle (E2E gate), and the serve-route smoke gates this twin byte-identical to
4102// a spec-off boot over the real HTTP surface. Exactness contract unchanged: the target's
4103// verify argmax decides every committed token, so the stream equals plain greedy BY
4104// CONSTRUCTION on every accept path (ckpt stash, gate, replay).
4105fn take_dspark_prefix_capture(
4106    slot: &mut Option<crate::spec::SpecBoundaryCapture>,
4107) -> Option<crate::spec::SpecBoundaryCapture> {
4108    slot.take()
4109}
4110
4111/// Deterministic preflight for the serving session's prompt-headroom requirement. Kept pure so
4112/// the worker can make the same decision before choosing whether to consume a prefix entry.
4113pub fn dspark_spec_prompt_fits(
4114    prompt_len: usize,
4115    ctx_cap: usize,
4116    block_size: usize,
4117    sliding_window: usize,
4118    is_dflash2: bool,
4119) -> bool {
4120    // PRIME FLOOR (incident 2026-08-25, second hit — the one that actually took prod down
4121    // twice). This predicate is the ONE admission gate the worker consumes for the dspark
4122    // route, and it only ever checked the ctx CEILING. A prompt shorter than
4123    // `PRIME_MIN_T` was therefore admitted and then panicked inside the cold prime, because
4124    // `prime_cache`'s batched arm asserts `T >= PRIME_MIN_T` and has no tokenwise twin that
4125    // fills the DFlash tap sink. A panic there is not a failed request: the GPU worker
4126    // exits 70 (poisoned-context contract) and every live session on the box dies, then the
4127    // guard relaunches into the same prompt — 20 panics and ~5 min of edge 502s on box10,
4128    // and a second loop on BOTH boxes when the route was redeployed. The trigger is
4129    // ordinary traffic: "Say OK." is 5 tokens, and our own watchdog sends that class.
4130    // Below the floor the route simply declines and the request serves on the plain path.
4131    if prompt_len < crate::hybrid_forward::PRIME_MIN_T {
4132        return false;
4133    }
4134    let max_ctx = if is_dflash2 {
4135        ctx_cap
4136    } else {
4137        ctx_cap.min(sliding_window)
4138    };
4139    prompt_len
4140        .checked_add(block_size)
4141        .and_then(|n| n.checked_add(8))
4142        .is_some_and(|need| need <= max_ctx)
4143}
4144
4145pub struct DsparkSpecSession {
4146    pub cache: crate::cache::Cache,
4147    /// One-shot prompt-end state for the worker's cross-request prefix cache. DFlash has no
4148    /// restorable draft plane, so this capture deliberately carries trunk snapshot + logits
4149    /// only; low-load DFlash requests ignore the resulting trunk-only entry while a later
4150    /// shed-to-plain request can consume it.
4151    prefix_capture: Option<crate::spec::SpecBoundaryCapture>,
4152    dkv: DflashKv,
4153    last: u32,
4154    ctx_len: usize,
4155    vt: usize,
4156    pub rounds: usize,
4157    max_ctx: usize,
4158    done: bool,
4159    /// Engine-bundle slice 1: persistent batched snapshot (buffers + pointer tables live
4160    /// with the session so bursts reuse them). None until the first round; stays None —
4161    /// legacy per-layer snapshot — when `snapb_off`.
4162    snapb: Option<DsparkSnapBatch>,
4163    snapb_off: bool,
4164    /// SAMPLED ADMISSION (T>0, lane/dspark-sampled-admission-20260820): the request's
4165    /// sampling config (None/temp==0 = the greedy route, byte-identical). Fixed for the
4166    /// session — the worker's admission owns the sampler identity.
4167    sampling: Option<crate::spec::SpecSampling>,
4168    /// Philox event counters, session-owned so randomness never repeats across bursts
4169    /// (the frspec session-continuity law): `sctr` = device sampling events (boundary,
4170    /// draft chain, bonus, residual), `uctr` = host uniforms (selector walk, accept tests).
4171    sctr: u32,
4172    uctr: u32,
4173    /// Penalized-sampled window (lane/dspark-penalized-sampled-20260821): seeded from
4174    /// the prompt tail (`pen_window_seed`), extended with every committed token, carried
4175    /// across bursts so a burst boundary never resets the stream the client asked us to
4176    /// penalize. Empty (and never touched) when the request carries no penalties.
4177    pen_hist: Vec<u32>,
4178}
4179
4180fn dspark_commit_limit(
4181    accepted_keep: usize,
4182    burst_out_len: usize,
4183    request_room: usize,
4184) -> (usize, bool) {
4185    let public_room = request_room.saturating_sub(burst_out_len);
4186    debug_assert!(public_room > 0);
4187    let keep = accepted_keep.min(public_room);
4188    (keep, keep < accepted_keep)
4189}
4190
4191impl DsparkSpecSession {
4192    /// How many trailing draft-KV rows a restore must carry for the drafter to be
4193    /// indistinguishable from one that cold-primed: the sliding window plus one block.
4194    ///
4195    /// WHY A TAIL IS SUFFICIENT, and why this is a fact about THIS export rather than a hope:
4196    /// every DFlash2 draft layer is `sliding_attention` (the port asserts
4197    /// `cfg.layer_sliding.iter().all(|&s| s)` at load and refuses otherwise), so the windowed
4198    /// SDPA never reads a key below the current block's window floor
4199    /// (`sdpa_naive_w_lo`, whose bit-identity at Tkv 4104 and legacy launch failure are both
4200    /// pinned by kernel_check). A round at context `pos` therefore reads rows
4201    /// `[pos - window + 1, pos + block)` and nothing older. Storing that tail is storing
4202    /// everything the drafter can observe.
4203    ///
4204    /// SIZE, the reason this is affordable at all: 5 layers x (2048 + 16) rows x 8 kv x 128
4205    /// dim x 4 B x 2 (k+v) is ~85 MB, against ~1,057 MB for the trunk planes of a
4206    /// 30k-token entry. Storing the FULL draft history instead would be ~1,229 MB — more than
4207    /// the trunk entry itself — which is what makes the tail the only viable form.
4208    pub fn draft_tail_rows(&self) -> usize {
4209        self.dkv.cfg_window_rows()
4210    }
4211
4212    /// The drafter's KV, for a worker publishing the tail into its cross-request prefix cache.
4213    pub fn draft_kv(&self) -> &DflashKv {
4214        &self.dkv
4215    }
4216}
4217
4218/// The tail-import refusal arms, PURE so they are testable without CUDA. These are the fence
4219/// in front of the deliberate uninitialised-rows-below-`base` design: rows the import does not
4220/// copy are unreadable ONLY if the tail actually covers the drafter's window ending exactly at
4221/// the logical length — every arm here is what makes that "only if" hold. A refusal that
4222/// silently stopped firing would let a session attend garbage without crashing, which is the
4223/// silent-quality-loss class, so each arm names itself.
4224///
4225/// `tail_floor` (lane/spec-exclusions-20260902): the EXPORTER's context floor, `0` for
4226/// every tail a cold-primed drafter publishes (the pre-lane rule verbatim). A floor-bearing
4227/// exporter (`DflashKv::new_cold_at`, or itself a short-tail import) never owned rows below
4228/// it, so its tail legitimately covers only `[floor, len)`; the coverage rule then asks for
4229/// everything readable ABOVE the floor. A short tail whose exporter had NO floor is still the
4230/// refusal it always was.
4231#[allow(clippy::too_many_arguments)]
4232pub fn tail_geometry_ok(
4233    tail_layers: usize,
4234    tail_row_bytes: usize,
4235    tail_base: usize,
4236    tail_rows: usize,
4237    tail_len: usize,
4238    tail_floor: usize,
4239    kv_layers: usize,
4240    kv_row_bytes: usize,
4241    kv_window_rows: usize,
4242    cap: usize,
4243) -> Result<(), &'static str> {
4244    if tail_layers != kv_layers {
4245        return Err("layer count differs from the live drafter");
4246    }
4247    if tail_row_bytes != kv_row_bytes {
4248        return Err("row geometry differs from the live drafter");
4249    }
4250    if tail_len > cap {
4251        return Err("logical length exceeds the session cap");
4252    }
4253    if tail_base + tail_rows != tail_len {
4254        return Err("tail does not end at its own logical length");
4255    }
4256    if tail_floor > tail_base {
4257        return Err("tail starts below its exporter's context floor");
4258    }
4259    // The whole point of the tail: it must cover everything a round can read. A shorter
4260    // tail than the window is only acceptable when the tail IS the entire history above the
4261    // exporter's floor (floor 0: the entire history).
4262    if tail_rows < kv_window_rows.min(tail_len - tail_floor) {
4263        return Err("tail shorter than the drafter's readable window");
4264    }
4265    Ok(())
4266}
4267
4268/// A DFlash draft-KV tail, per drafter layer, ready to ride a cross-request prefix-cache
4269/// entry: `(k, v)` f32 rows covering absolute positions `[base, base + rows)`.
4270///
4271/// Only the tail travels, and that is a fact about this export rather than an optimisation:
4272/// every DFlash2 draft layer is `sliding_attention` (the port asserts it at load), so a round
4273/// at context `pos` reads rows `[pos - window + 1, pos + block)` and nothing older. Storing
4274/// the whole history for a 30k-token prompt would be ~1,229 MB — MORE than the ~1,057 MB of
4275/// trunk planes it would ride with; the tail is ~85 MB.
4276pub struct DflashKvTail {
4277    pub layers: Vec<(CudaSlice<f32>, CudaSlice<f32>)>,
4278    /// Absolute position of the first stored row.
4279    pub base: usize,
4280    /// Rows stored per layer.
4281    pub rows: usize,
4282    /// Logical length the KV had when exported (`= pos`), so an import can restore the same
4283    /// absolute row addressing the rope positions were baked against.
4284    pub len: usize,
4285    /// Bytes per row per layer, carried so an import cannot disagree about the geometry.
4286    pub row_bytes: usize,
4287    /// The exporter's context floor (`DflashKv::floor`): `0` for every tail a cold-primed
4288    /// drafter publishes; the first row the exporter ever owned otherwise. Travels with the
4289    /// tail so `tail_geometry_ok` can tell a legitimately short tail (nothing below the
4290    /// floor ever existed) from a truncated one, and so the import inherits the floor.
4291    pub floor: usize,
4292}
4293
4294impl DflashKvTail {
4295    pub fn bytes(&self) -> usize {
4296        self.layers.len() * self.rows * self.row_bytes * 2
4297    }
4298}
4299
4300impl DflashKv {
4301    /// Copy out the readable tail ending at `upto` (see `DflashKvTail`). `None` when there is
4302    /// nothing to publish or an allocation fails — publication is always optional.
4303    ///
4304    /// `upto` IS NOT `self.len`, and conflating them was the bug the first exactness-gate run
4305    /// caught: publication happens at the scheduler's drain sweep, by which time the session
4306    /// has committed generated rows, so `len` had run 35 rows past the capture boundary and
4307    /// every restore was refused with `draft KV len 30364 != prompt 30329`. The trunk planes
4308    /// are copied at the capture `pos` for the same reason; the tail must agree with them.
4309    pub fn export_tail(&self, e: &Engine, upto: usize) -> Option<DflashKvTail> {
4310        if upto == 0 || upto > self.len {
4311            return None;
4312        }
4313        let rowsz = self.row_bytes / std::mem::size_of::<f32>();
4314        // Never below the floor: a floor-bearing KV owns no rows there (doc on `floor`), and
4315        // a tail with nothing above the floor has nothing to publish.
4316        let floor = self.floor.min(upto);
4317        let rows = self.window_rows.min(upto - floor);
4318        if rows == 0 {
4319            return None;
4320        }
4321        let base = upto - rows;
4322        let mut layers = Vec::with_capacity(self.k.len());
4323        for li in 0..self.k.len() {
4324            let (Ok(mut k), Ok(mut v)) = (e.uninit(rows * rowsz), e.uninit(rows * rowsz)) else {
4325                return None;
4326            };
4327            if e.copy_range_into(&mut k, 0, &self.k[li], base * rowsz, rows * rowsz)
4328                .is_err()
4329                || e.copy_range_into(&mut v, 0, &self.v[li], base * rowsz, rows * rowsz)
4330                    .is_err()
4331            {
4332                return None;
4333            }
4334            layers.push((k, v));
4335        }
4336        Some(DflashKvTail {
4337            layers,
4338            base,
4339            rows,
4340            len: upto,
4341            row_bytes: self.row_bytes,
4342            floor,
4343        })
4344    }
4345
4346    /// Rebuild a draft KV from a published tail: a fresh allocation at `cap`, the tail copied
4347    /// back to the SAME absolute rows it came from, and `len` restored so the next round
4348    /// addresses positions exactly as a cold-primed session would.
4349    ///
4350    /// Rows below `tail.base` are ZEROED, not left uninitialised. The clipped SDPA never reads
4351    /// below the block's window floor, but the legacy full-scan kernel
4352    /// (`MEMRA_DFLASH2_SDPA_CLIP=0`, the rollback seam) scans EVERY row into the score and the
4353    /// output, relying on masked rows contributing exactly zero — an identity that holds only
4354    /// for finite data (`0.0 * NaN = NaN`, and an uninit K row can produce a NaN score that
4355    /// poisons the softmax sum). Zeros keep that identity on both kernel arms, so a clip
4356    /// rollback on a restore-armed box stays byte-exact instead of decoding silent garbage
4357    /// (review round 3). Rows above `tail.len` stay uninit — equally unwritten and unread in
4358    /// the cold path, so restored matches cold there.
4359    ///
4360    /// This function still REFUSES rather than trusts the window math — if the tail does not
4361    /// cover the window, the caller gets `None` and must cold-prime.
4362    ///
4363    /// FLOOR-BEARING TAILS (lane/spec-exclusions-20260902): a tail whose exporter had a
4364    /// context floor covers only `[floor, len)` and the import inherits `floor = tail.base`
4365    /// (the first row it actually owns), so the round attention never reads the zero rows
4366    /// below it. That needs the clipped kernel (`d2_windowed_attn`), so a floor-bearing tail
4367    /// under `MEMRA_DFLASH2_SDPA_CLIP=0` refuses here by name. Full tails keep `floor = 0`
4368    /// and the pre-lane program exactly.
4369    pub fn from_tail(e: &Engine, cfg: &DflashCfg, cap: usize, tail: &DflashKvTail) -> Option<Self> {
4370        let mut kv = Self::new(e, cfg, cap).ok()?;
4371        if let Err(why) = tail_geometry_ok(
4372            tail.layers.len(),
4373            tail.row_bytes,
4374            tail.base,
4375            tail.rows,
4376            tail.len,
4377            tail.floor,
4378            kv.k.len(),
4379            kv.row_bytes,
4380            kv.window_rows,
4381            cap,
4382        ) {
4383            eprintln!("[dspark] tail import refused: {why}");
4384            return None;
4385        }
4386        // A short tail (rows below the window because the exporter never owned them) makes
4387        // this KV floor-bearing; a full tail from a floored exporter does not need the floor
4388        // (every readable row is present) and keeps the pre-lane program.
4389        let short = tail.rows < kv.window_rows.min(tail.len);
4390        if short && !dflash2_sdpa_clip_on() {
4391            eprintln!(
4392                "[dspark] tail import refused: floor-bearing tail needs the clipped round \
4393                 attention (MEMRA_DFLASH2_SDPA_CLIP=0 has no context-floor arm)"
4394            );
4395            return None;
4396        }
4397        let rowsz = kv.row_bytes / std::mem::size_of::<f32>();
4398        for li in 0..kv.k.len() {
4399            let (src_k, src_v) = &tail.layers[li];
4400            if tail.base > 0 {
4401                // Finite zeros below the tail: the legacy full-scan kernel reads these rows
4402                // (see the doc above); NaN in either K or V poisons the row's contribution.
4403                e.memset_zeros_view(&mut kv.k[li].slice_mut(0..tail.base * rowsz))
4404                    .ok()?;
4405                e.memset_zeros_view(&mut kv.v[li].slice_mut(0..tail.base * rowsz))
4406                    .ok()?;
4407            }
4408            e.copy_range_into(
4409                &mut kv.k[li],
4410                tail.base * rowsz,
4411                src_k,
4412                0,
4413                tail.rows * rowsz,
4414            )
4415            .ok()?;
4416            e.copy_range_into(
4417                &mut kv.v[li],
4418                tail.base * rowsz,
4419                src_v,
4420                0,
4421                tail.rows * rowsz,
4422            )
4423            .ok()?;
4424        }
4425        kv.len = tail.len;
4426        if short {
4427            kv.floor = tail.base;
4428        }
4429        Some(kv)
4430    }
4431
4432    /// Rows a restore must carry (see `DsparkSpecSession::draft_tail_rows`). Stored here
4433    /// because `DflashKv` owns the row geometry; the value comes from the drafter cfg.
4434    pub fn cfg_window_rows(&self) -> usize {
4435        self.window_rows
4436    }
4437
4438    /// Bytes per row per layer (`n_kv * head_dim * 4`), the unit both the export and the
4439    /// import address rows in.
4440    pub fn row_bytes(&self) -> usize {
4441        self.row_bytes
4442    }
4443
4444    /// Number of draft layers, i.e. how many per-layer planes an export produces.
4445    pub fn n_layer(&self) -> usize {
4446        self.k.len()
4447    }
4448}
4449
4450impl DsparkSpecSession {
4451    pub fn cache_max_ctx(&self) -> usize {
4452        self.max_ctx
4453    }
4454    pub fn finished(&self) -> bool {
4455        self.done
4456    }
4457    pub fn pos(&self) -> usize {
4458        self.cache.pos
4459    }
4460    /// Drain the prompt-end prefix capture exactly once. Publication is worker-owned so it can
4461    /// apply namespace isolation, dedupe and the shared byte budget at the scheduler boundary.
4462    pub fn take_prefix_capture(&mut self) -> Option<crate::spec::SpecBoundaryCapture> {
4463        take_dspark_prefix_capture(&mut self.prefix_capture)
4464    }
4465    /// DEMOTION HANDOFF (lane/dspark-spec-gate-demote, 2026-08-24): consume this session and
4466    /// hand its trunk cache + next-token prediction to the plain batched-decode path — the
4467    /// dspark twin of [`crate::spec::SpecSession::into_demoted`].
4468    ///
4469    /// WHY THIS IS EXACT (greedy). The burst-boundary invariant is `cache.pos == prompt rows
4470    /// + emitted tokens`: each round commits exactly `m+1` trunk rows (anchor + accepted
4471    /// drafts) and emits exactly those `m+1` tokens, so every emitted token has its KV row
4472    /// and nothing else does. `last` is the verify argmax at the LAST committed row — and
4473    /// verify-column argmax equality with plain decode is the very property the dspark E2E
4474    /// byte-identity gate pins (`dspark_q38_gate`: ALL EXACT). Handing (cache, last) to the
4475    ///   batched path therefore continues the stream from a state indistinguishable from one
4476    ///   the batched path produced itself.
4477    ///
4478    /// Unlike the MTP twin there is no carried-pending shape: the round commits its bonus
4479    /// inside the burst, so a session at a burst boundary is ALWAYS in handoff shape. The
4480    /// caller still cross-checks `pos()` against its fed-token count (a budget-clamped
4481    /// overshoot leaves cache rows past the public stream — those sessions finish, never
4482    /// demote). The draft KV, snapshot buffers and philox counters are DROPPED here
4483    /// (freeing their VRAM): the batched path never drafts, and the handoff is one-way.
4484    ///
4485    /// Sampled sessions must not be demoted (the caller excludes them, mirroring the MTP
4486    /// gate): their committed stream depends on the session-owned philox counters, and the
4487    /// plain batched sampler is a different random program mid-request.
4488    pub fn into_demoted(self) -> (crate::cache::Cache, u32) {
4489        (self.cache, self.last)
4490    }
4491}
4492
4493impl crate::hybrid::HybridModel {
4494    /// Turn-1 prime: trunk prefill with taps armed + chunked ctx ingest into the draft KV.
4495    /// Mirrors generate_spec_dspark's prime block exactly (chunk offsets via sink.base are
4496    /// handled inside prime_cache's tick loop; the 256-row ingest chunks match the bin arm).
4497    pub fn dspark_spec_session_new(
4498        &self,
4499        e: &Engine,
4500        draft: &DflashDraft,
4501        prompt: &[u32],
4502        ctx_cap: usize,
4503        sampling: Option<crate::spec::SpecSampling>,
4504        capture_prefix: bool,
4505    ) -> Result<DsparkSpecSession, Box<dyn std::error::Error>> {
4506        use crate::cache::{Cache, DflashTapSink};
4507        assert!(
4508            !self.uses_gemma_program(),
4509            "gemma4 targets use the assistant-drafter route; dspark is the qwen-hybrid arm"
4510        );
4511        // Penalized SAMPLED requests are IN scope (lane/dspark-penalized-sampled-20260821:
4512        // p-side penalties over the true per-state window, q the recorded proposal — the
4513        // accept walk's penalty arm). Penalties at temp==0 stay a LOUD refusal: the greedy
4514        // walk argmaxes RAW columns and would silently drop them — penalized greedy is
4515        // served exactly on the plain path (worker admission owns that exclusion).
4516        if let Some(sp) = sampling.as_ref()
4517            && sp.temp <= 0.0
4518            && sp.pen_on()
4519        {
4520            return Err(
4521                "dspark spec at temp==0 is the greedy route and would silently drop \
4522                     the request's penalties; penalized greedy is served on the plain path"
4523                    .into(),
4524            );
4525        }
4526        let n_embd = self.cfg.n_embd as usize;
4527        let c = &draft.cfg;
4528        assert_eq!(n_embd, c.hidden, "draft hidden must match target n_embd");
4529        let b = c.block_size;
4530        let n_taps = c.target_layer_ids.len();
4531        // The dspark round is windowless: every position the session will ever hold must
4532        // fit the draft window. Clamp the session ctx to it and refuse prompts that
4533        // cannot take even one round — admission falls back to the plain path.
4534        // DFlash2 rounds implement the reference's symmetric sliding window
4535        // (sdpa_naive_w), so its sessions take the full ctx cap.
4536        let is_dflash2 = draft.dflash2.is_some();
4537        let max_ctx = if is_dflash2 {
4538            ctx_cap
4539        } else {
4540            ctx_cap.min(c.sliding_window)
4541        };
4542        if !dspark_spec_prompt_fits(prompt.len(), ctx_cap, b, c.sliding_window, is_dflash2) {
4543            let need = prompt.len().saturating_add(b).saturating_add(8);
4544            return Err(format!(
4545                "dspark session needs {need} ctx (prompt {} + block {b} + 8), cap {max_ctx}",
4546                prompt.len()
4547            )
4548            .into());
4549        }
4550        let mut cache = Cache::new(e, &self.cfg, max_ctx)?;
4551        let tp = prompt.len();
4552        cache.dflash_taps = Some(DflashTapSink {
4553            layer_ids: c.target_layer_ids.clone(),
4554            buf: e.uninit(tp * n_taps * n_embd)?,
4555            hidden: n_embd,
4556            t: tp,
4557            base: 0,
4558        });
4559        let (logits, _h_seed, _hiddens) = self.prime_cache(e, prompt, &mut cache, 0)?;
4560        // Boundary token: greedy argmax (byte contract) or the request's own filtered
4561        // draw through the session Philox stream (the frspec boundary composition) —
4562        // penalized over the prompt window when the request carries penalties.
4563        let mut sctr0 = 0u32;
4564        let pen_hist: Vec<u32> = match sampling.as_ref().filter(|s| s.temp > 0.0 && s.pen_on()) {
4565            Some(sp) => crate::spec::pen_window_seed(&[], prompt, sp.penalty_last_n),
4566            None => Vec::new(),
4567        };
4568        let last = match sampling.as_ref().filter(|s| s.temp > 0.0) {
4569            Some(sp) => crate::spec::sample_boundary_token(
4570                e,
4571                &logits,
4572                sp,
4573                &pen_hist,
4574                &mut sctr0,
4575                "dspark-prime",
4576            )?,
4577            None => crate::forward::argmax(&logits) as u32,
4578        };
4579        let mut dkv = DflashKv::new(e, &draft.cfg, max_ctx)?;
4580        {
4581            let taps = cache.dflash_taps.take().unwrap();
4582            let n_taps_h = n_taps * n_embd;
4583            let mut r0 = 0usize;
4584            while r0 < tp {
4585                let t_c = (tp - r0).min(256);
4586                let tv = e.view(&taps.buf, tp * n_taps_h);
4587                let win = tv.slice(r0 * n_taps_h..(r0 + t_c) * n_taps_h);
4588                let mut chunk = e.uninit(t_c * n_taps_h)?;
4589                e.copy_view_into(&mut chunk, 0, &win, t_c * n_taps_h)?;
4590                let f = draft.ctx_features(e, &chunk, t_c)?;
4591                let pos_c: Vec<i32> = ((r0 as i32)..(r0 + t_c) as i32).collect();
4592                draft.ingest_ctx(e, &mut dkv, &f, &pos_c, t_c)?;
4593                r0 += t_c;
4594            }
4595        }
4596        e.stream().synchronize()?;
4597        // FULL-PROMPT ONLY. Unlike MTP, DFlash cannot restore its draft plane from a trunk
4598        // prefix, so there is no LCP/message-boundary split arm here. Mandatory draft-KV
4599        // allocation + ingest has already succeeded; the optional snapshot can no longer turn
4600        // a session that would have fit into a draft-allocation failure. Capture remains before
4601        // any speculative burst mutates the recurrent state.
4602        let prefix_capture = if capture_prefix {
4603            cache
4604                .snapshot(e)
4605                .ok()
4606                .map(|snap| crate::spec::SpecBoundaryCapture {
4607                    snap,
4608                    pos: tp,
4609                    logits: logits.clone(),
4610                    last_h: Vec::new(),
4611                    latent_tails: Vec::new(),
4612                })
4613        } else {
4614            None
4615        };
4616        // Verify carries [anchor, drafts] = up to n_drafts+1 rows (harvest-dependent;
4617        // DSPARK-POSTMORTEM-20260820.md; family-keyed for DFlash2, else checkpoint
4618        // strategy census).
4619        let nd = DsparkHarvest::for_draft(draft).n_drafts(b);
4620        let vt_cap: usize = std::env::var("MEMRA_DFLASH_VERIFY_T")
4621            .ok()
4622            .and_then(|v| v.parse().ok())
4623            .unwrap_or(nd + 1)
4624            .clamp(2, nd + 1);
4625        Ok(DsparkSpecSession {
4626            cache,
4627            prefix_capture,
4628            dkv,
4629            last,
4630            ctx_len: tp,
4631            vt: vt_cap,
4632            rounds: 0,
4633            max_ctx,
4634            done: false,
4635            snapb: None,
4636            snapb_off: !crate::spec::state_copy_batch_on(),
4637            sampling,
4638            sctr: sctr0,
4639            uctr: 0,
4640            pen_hist,
4641        })
4642    }
4643
4644    /// One scheduler burst: dspark rounds until >= `burst_target` tokens are committed,
4645    /// EOS lands, or the ctx cap is reached. `request_room` is the request's remaining
4646    /// public budget, which may be larger than the per-tick scheduler quantum. Returns
4647    /// (tokens, drafted, accepted) for this burst — mid-request quantum overshoot stays
4648    /// public, while only the true request boundary clamps the committed cache prefix.
4649    /// ADMISSION DEBT of this model's verify-graph pool, in bytes (lane/
4650    /// hermes-perf-fixes, 2026-08-23): the projected remaining growth the serve admission
4651    /// gate must reserve so sessions admitted while the pool is cold do not overcommit VRAM
4652    /// the pool will hold (it grows monotonically with no eviction by design — the pool's
4653    /// high-water is per-export and unknown until observed on the serving box; the 1.5 GiB
4654    /// SPEC_SHRINK_RESERVE never covered it). Projection contract and the self-measuring
4655    /// arithmetic live on [`crate::spec::dspark_vg_debt_projection`]; the observed bytes
4656    /// come from the device graph mem pool (`Engine::device_graph_mem_reserved`).
4657    ///
4658    /// CHARGED BY STRUCT, not by which route filled it (lane/graph-launch-guard-sweep-
4659    /// 20260831, fleet-peer refuted-read fix): the MTP spec route's verify-graph door
4660    /// (`MEMRA_SPEC_VERIFY_GRAPH`, family default for GDN+MoE) fills the SAME
4661    /// `dspark_vgraphs` pool with the same monotonic growth, and used to escape charging
4662    /// because the door check named only the dspark flags. 0 when EVERY door is closed
4663    /// (`MEMRA_DSPARK_VERIFY_GRAPH=0` and the MTP door off), frozen
4664    /// (`MEMRA_DSPARK_VG_MAX=0`), or the pool has not captured yet.
4665    pub fn dspark_vg_admission_debt(&self, e: &Engine) -> usize {
4666        let dspark_door =
4667            crate::spec::dspark_verify_graph_serve_on() || crate::spec::dspark_verify_graph_on();
4668        let mtp_door =
4669            crate::spec::spec_verify_graph_env().unwrap_or_else(|| self.vgraph_family_default());
4670        if !dspark_door && !mtp_door {
4671            return 0;
4672        }
4673        let reserved = e.device_graph_mem_reserved();
4674        self.dspark_vgraphs
4675            .lock()
4676            .unwrap()
4677            .as_mut()
4678            .map(|g| g.admission_debt(reserved))
4679            .unwrap_or(0)
4680    }
4681
4682    /// MULTI-TURN RESUME (lane/dflash2-session-reuse, 2026-08-25): continue a parked
4683    /// dspark session with the next turn's suffix — the dspark twin of the MTP pool
4684    /// resume. Trunk rows for the committed stream are already resident in `cache` and
4685    /// their ctx features in `dkv`, so turn N+1 primes ONLY its delta instead of
4686    /// re-priming the whole conversation (the route previously served every turn cold —
4687    /// a full-prompt prime whose cost grows with the conversation).
4688    ///
4689    /// EXACTNESS. The suffix prime is the same session-continuation `prime_cache` the
4690    /// serve path uses for split prompts and LCP restores (chunk N+1 attends chunk N's
4691    /// resident KV); the tap sink collects the suffix rows prompt-relative and the dkv
4692    /// ingest lands them at their absolute positions, exactly as the burst's per-round
4693    /// keep-ingest does. The boundary token re-derives as the cold prime does: greedy
4694    /// argmax of the suffix's last row, or the request's filtered draw through the
4695    /// SESSION's own Philox stream (`sctr` continues — the frspec session-continuity
4696    /// law), penalized over the session+suffix window. A resumed stream is therefore
4697    /// byte-identical to the stream a cold prime of the full concatenation produces —
4698    /// the verify arbitrates every committed token either way.
4699    ///
4700    /// EOS in the committed history is fine (a finished turn parks with EOS committed;
4701    /// the new user turn continues past it) — `done` resets here. Callers must pass a
4702    /// NON-EMPTY suffix for a `done` session (an empty-suffix continuation of a finished
4703    /// stream would re-emit from a terminal state); the worker's probe enforces it.
4704    /// Re-arm a dspark session from a RESTORED trunk cache plus a published draft tail —
4705    /// the long-answer half of lane/dspark-draft-plane-20260827.
4706    ///
4707    /// WHY THIS EXISTS. `dspark_spec_session_new` must prime the full prompt, because the draft
4708    /// KV derives from trunk hidden FEATURES the prime produces as a side effect. A cache hit
4709    /// returns trunk K/V, not features, so before this a speculating request had to discard even
4710    /// a full-prompt hit and re-prefill (~10 s at 30k tokens). With the drafter's readable tail
4711    /// travelling on the entry, both halves are restorable and the discard is unnecessary.
4712    ///
4713    /// WHY IT IS EQUIVALENT TO A COLD PRIME, field by field:
4714    /// * `cache` — the caller's restored trunk cache, already at `prompt.len()` with recurrent
4715    ///   state, which is why only WHOLE-ENTRY hits are eligible (a GDN trunk cannot rebuild
4716    ///   recurrent state mid-sequence, so there is no LCP arm here — same restriction as the
4717    ///   cold path's full-prompt-only rule).
4718    /// * `dkv` — byte-copied from the tail into the SAME absolute rows, so rope positions and
4719    ///   every row the windowed SDPA can read are identical to what the prime produced.
4720    /// * `last` — drawn from the entry's boundary logits with the request's own sampler, the
4721    ///   same composition the cold path applies to its prime logits.
4722    /// * `pen_hist` / `sctr` / `uctr` — seeded exactly as a cold session's are: the penalty
4723    ///   window from this prompt, the Philox counters fresh, because randomness is
4724    ///   session-owned by the frspec continuity law and a restore is a NEW session.
4725    /// * `prefix_capture` — `None`: the entry this restored FROM already exists, so
4726    ///   republishing the same key would be dropped by the worker's dedupe anyway.
4727    ///
4728    /// Refuses (rather than asserting) whenever the rebuilt draft KV and the cache disagree, so
4729    /// a caller that gets `Err` simply cold-primes.
4730    #[allow(clippy::too_many_arguments)]
4731    pub fn dspark_spec_session_from_restored(
4732        &self,
4733        e: &Engine,
4734        draft: &DflashDraft,
4735        cache: crate::cache::Cache,
4736        prompt: &[u32],
4737        // Draft KV ALREADY rebuilt from the entry's tail by the caller (`DflashKv::from_tail`)
4738        // while the prefix cache was borrowable. Taking the built KV rather than the tail is
4739        // what keeps the ~85 MB tail in the entry for other requests — `from_tail` copies OUT
4740        // of it, so no clone of the tail is ever needed.
4741        dkv: DflashKv,
4742        boundary_logits: &[f32],
4743        sampling: Option<crate::spec::SpecSampling>,
4744        ctx_cap: usize,
4745    ) -> Result<DsparkSpecSession, Box<dyn std::error::Error>> {
4746        assert!(
4747            !self.uses_gemma_program(),
4748            "gemma4 targets use the assistant-drafter route; dspark is the qwen-hybrid arm"
4749        );
4750        if let Some(sp) = sampling.as_ref()
4751            && sp.temp <= 0.0
4752            && sp.pen_on()
4753        {
4754            return Err("penalized greedy is served on the plain path".into());
4755        }
4756        let c = &draft.cfg;
4757        let b = c.block_size;
4758        let is_dflash2 = draft.dflash2.is_some();
4759        let max_ctx = if is_dflash2 {
4760            ctx_cap
4761        } else {
4762            ctx_cap.min(c.sliding_window)
4763        };
4764        let tp = prompt.len();
4765        if !dspark_spec_prompt_fits(tp, ctx_cap, b, c.sliding_window, is_dflash2) {
4766            return Err(format!("restored dspark session does not fit ctx {max_ctx}").into());
4767        }
4768        if cache.pos != tp {
4769            return Err(format!(
4770                "restored dspark session needs a whole-entry trunk cache: cache.pos {} !=                  prompt {tp}",
4771                cache.pos
4772            )
4773            .into());
4774        }
4775        if dkv.len != tp {
4776            return Err(format!("restored draft KV len {} != prompt {tp}", dkv.len).into());
4777        }
4778        if dkv.cap != max_ctx {
4779            return Err(
4780                format!("restored draft KV cap {} != session ctx {max_ctx}", dkv.cap).into(),
4781            );
4782        }
4783        if boundary_logits.is_empty() {
4784            return Err("restored dspark session needs the entry's boundary logits".into());
4785        }
4786        let mut sctr0 = 0u32;
4787        let pen_hist: Vec<u32> = match sampling.as_ref().filter(|s| s.temp > 0.0 && s.pen_on()) {
4788            Some(sp) => crate::spec::pen_window_seed(&[], prompt, sp.penalty_last_n),
4789            None => Vec::new(),
4790        };
4791        let last = match sampling.as_ref().filter(|s| s.temp > 0.0) {
4792            Some(sp) => crate::spec::sample_boundary_token(
4793                e,
4794                boundary_logits,
4795                sp,
4796                &pen_hist,
4797                &mut sctr0,
4798                "dspark-restore",
4799            )?,
4800            None => crate::forward::argmax(boundary_logits) as u32,
4801        };
4802        let nd = DsparkHarvest::for_draft(draft).n_drafts(b);
4803        let vt_cap: usize = std::env::var("MEMRA_DFLASH_VERIFY_T")
4804            .ok()
4805            .and_then(|v| v.parse().ok())
4806            .unwrap_or(nd + 1)
4807            .clamp(2, nd + 1);
4808        Ok(DsparkSpecSession {
4809            cache,
4810            prefix_capture: None,
4811            dkv,
4812            last,
4813            ctx_len: tp,
4814            vt: vt_cap,
4815            rounds: 0,
4816            max_ctx,
4817            done: false,
4818            snapb: None,
4819            snapb_off: !crate::spec::state_copy_batch_on(),
4820            sampling,
4821            sctr: sctr0,
4822            uctr: 0,
4823            pen_hist,
4824        })
4825    }
4826
4827    pub fn dspark_spec_session_resume(
4828        &self,
4829        e: &Engine,
4830        draft: &DflashDraft,
4831        sess: &mut DsparkSpecSession,
4832        suffix: &[u32],
4833    ) -> Result<(), Box<dyn std::error::Error>> {
4834        use crate::cache::DflashTapSink;
4835        let n_embd = self.cfg.n_embd as usize;
4836        let c = &draft.cfg;
4837        let b = c.block_size;
4838        let n_taps = c.target_layer_ids.len();
4839        let pos0 = sess.cache.pos;
4840        debug_assert_eq!(
4841            sess.ctx_len, pos0,
4842            "dspark resume: draft KV rows != trunk cache rows"
4843        );
4844        if suffix.is_empty() {
4845            return Err(
4846                "dspark resume needs a non-empty suffix (worker probe owns the \
4847                        empty-suffix exact-continuation case)"
4848                    .into(),
4849            );
4850        }
4851        // SHORT-SUFFIX FLOOR (incident 2026-08-25, box10 crash loop). The suffix prime goes
4852        // through `prime_cache`, which asserts `T >= PRIME_MIN_T` — the batched prefill arm
4853        // has no tokenwise twin that also fills the DFlash tap sink. A resumed turn shorter
4854        // than that floor (the watchdog's "Say OK." class, and any brief agent follow-up)
4855        // therefore PANICKED the GPU worker, which exits 70 and takes every session on the
4856        // box with it: 20 panics and ~5 minutes of 502s on box10 before MEMRA_REUSE_POOL=0
4857        // stopped it. The worker probe declines these before it ever gets here (its own
4858        // guard is the one that keeps the request on the cold path, which is exactly the
4859        // pre-lane behavior); this is the engine-side backstop so no future caller can
4860        // reintroduce the panic, and it is a refusal rather than an assert because a
4861        // too-short turn is ordinary traffic, not a bug.
4862        if suffix.len() < crate::hybrid_forward::PRIME_MIN_T {
4863            return Err(format!(
4864                "dspark resume suffix {} < PRIME_MIN_T {} (prime_cache has no tokenwise \
4865                 tap-filling twin); serve this turn cold",
4866                suffix.len(),
4867                crate::hybrid_forward::PRIME_MIN_T
4868            )
4869            .into());
4870        }
4871        let need = pos0
4872            .saturating_add(suffix.len())
4873            .saturating_add(b)
4874            .saturating_add(8);
4875        if need > sess.max_ctx {
4876            return Err(format!(
4877                "dspark resume needs {need} ctx (resident {pos0} + suffix {} + block {b} + 8), \
4878                 cap {}",
4879                suffix.len(),
4880                sess.max_ctx
4881            )
4882            .into());
4883        }
4884        let tp = suffix.len();
4885        sess.cache.dflash_taps = Some(DflashTapSink {
4886            layer_ids: c.target_layer_ids.clone(),
4887            buf: e.uninit(tp * n_taps * n_embd)?,
4888            hidden: n_embd,
4889            t: tp,
4890            base: 0,
4891        });
4892        let (logits, _h_seed, _hiddens) = self.prime_cache(e, suffix, &mut sess.cache, 0)?;
4893        let sp_pen = sess.sampling.filter(|s| s.temp > 0.0 && s.pen_on());
4894        if let Some(sp) = sp_pen.as_ref() {
4895            sess.pen_hist = crate::spec::pen_window_seed(&sess.pen_hist, suffix, sp.penalty_last_n);
4896        }
4897        let last = match sess.sampling.filter(|s| s.temp > 0.0) {
4898            Some(sp) => crate::spec::sample_boundary_token(
4899                e,
4900                &logits,
4901                &sp,
4902                &sess.pen_hist,
4903                &mut sess.sctr,
4904                "dspark-resume",
4905            )?,
4906            None => crate::forward::argmax(&logits) as u32,
4907        };
4908        {
4909            let taps = sess.cache.dflash_taps.take().unwrap();
4910            let n_taps_h = n_taps * n_embd;
4911            let mut r0 = 0usize;
4912            while r0 < tp {
4913                let t_c = (tp - r0).min(256);
4914                let tv = e.view(&taps.buf, tp * n_taps_h);
4915                let win = tv.slice(r0 * n_taps_h..(r0 + t_c) * n_taps_h);
4916                let mut chunk = e.uninit(t_c * n_taps_h)?;
4917                e.copy_view_into(&mut chunk, 0, &win, t_c * n_taps_h)?;
4918                let f = draft.ctx_features(e, &chunk, t_c)?;
4919                let pos_c: Vec<i32> = (((pos0 + r0) as i32)..((pos0 + r0 + t_c) as i32)).collect();
4920                draft.ingest_ctx(e, &mut sess.dkv, &f, &pos_c, t_c)?;
4921                r0 += t_c;
4922            }
4923        }
4924        e.stream().synchronize()?;
4925        sess.ctx_len += tp;
4926        sess.last = last;
4927        sess.done = false;
4928        Ok(())
4929    }
4930
4931    pub fn dspark_spec_session_burst(
4932        &self,
4933        e: &Engine,
4934        draft: &DflashDraft,
4935        sess: &mut DsparkSpecSession,
4936        burst_target: usize,
4937        request_room: usize,
4938        eos: &[u32],
4939    ) -> Result<(Vec<u32>, usize, usize), Box<dyn std::error::Error>> {
4940        use crate::cache::DflashTapSink;
4941        let n_embd = self.cfg.n_embd as usize;
4942        let c = &draft.cfg;
4943        let b = c.block_size;
4944        let n_taps = c.target_layer_ids.len();
4945        let n_vocab = self.output.out_features();
4946        // Harvest convention (DSPARK-POSTMORTEM-20260820.md) — identical to the bin arm
4947        // (family-keyed for DFlash2, else checkpoint strategy census; owner-ratified
4948        // flip 2026-08-20).
4949        let harvest = DsparkHarvest::for_draft(draft);
4950        let nd = harvest.n_drafts(b);
4951        let r0 = harvest.first_row();
4952        let vt_cap: usize = std::env::var("MEMRA_DFLASH_VERIFY_T")
4953            .ok()
4954            .and_then(|v| v.parse().ok())
4955            .unwrap_or(nd + 1)
4956            .clamp(2, nd + 1);
4957        let adapt = std::env::var("MEMRA_DFLASH_ADAPT").as_deref() != Ok("0");
4958        // Verify-window policy (H4, DSPARK-POSTMORTEM-20260820.md) — identical to the
4959        // bin arm: default = confidence-slot tau=.5 on a head-carrying checkpoint
4960        // (owner-ratified flip 2026-08-20); head-less (incl. the DFlash2 family) and
4961        // ADAPT=0 keep the ladder.
4962        let vt_policy = DsparkVtPolicy::resolve(draft.confidence.is_some());
4963        if vt_policy.is_confidence() {
4964            assert!(
4965                draft.confidence.is_some(),
4966                "MEMRA_DSPARK_VT={vt_policy:?} needs a checkpoint with an accept-rate \
4967                 head (confidence_head.* absent in this export)"
4968            );
4969        }
4970        // SAMPLED ADMISSION (T>0): session-fixed config; counters live on the session so
4971        // randomness never repeats across bursts. None/temp==0 = the greedy route.
4972        let sp_on: Option<crate::spec::SpecSampling> = sess.sampling.filter(|s| s.temp > 0.0);
4973        let pen_on = sp_on.as_ref().is_some_and(|s| s.pen_on());
4974        let mut out: Vec<u32> = Vec::with_capacity(burst_target + b);
4975        let mut drafted = 0usize;
4976        let mut accepted_n = 0usize;
4977        // Engine-bundle slice 2 — identical to the bin arm: deferred chain readback under
4978        // the stash arm with a resident embed table (ladder policy only).
4979        let defer_rb = crate::spec::dspark_defer_readback_on() && !vt_policy.is_confidence();
4980        let (embd_qt, embd_rb) = self.embd.qt_and_row_bytes(n_embd);
4981        let embd_gpu = if !defer_rb || crate::spec::spec_host_embd() {
4982            None
4983        } else {
4984            Some(
4985                self.embd_gpu
4986                    .get_or_init(|| e.upload_u8(&self.embd.raw).expect("embed table upload")),
4987            )
4988        };
4989        // Slice 3/4c SERVE ENGAGEMENT (graphs-serve lane; DSF-ROUNDCOST §9.3 -> §10): the
4990        // verify-graph pool lives on the MODEL (`dspark_vgraphs`, one per process) and its
4991        // keys — (segment, vt) and (vt, rung, hi) — carry NOTHING session-scoped, so ANY
4992        // session whose round matches a key replays the same capture (this is the
4993        // cache-reuse-pool the old bin-arm-only note asked for). Sharing is sound because
4994        // every per-session-varying address the captured bodies touch is indirect:
4995        // conv/ssm state and the ckpt stash resolve through the per-verify refreshed
4996        // pointer table (refresh_tables + copy_indirect_src_f32 — the slice-3
4997        // parity/lifetime law; a baked address is the known 12/12-divergence class), kv
4998        // bases through fa_table, residual/pos/tap through ctx-owned staging rewritten
4999        // every round; per-row t_kv derives in-kernel from pos_seq, and the per-round
5000        // host bookkeeping (parity swap, len bump) runs on THIS session's cache. The
5001        // guard spans the burst: the slab stash is live verify -> commit inside each
5002        // round, and the worker drives bursts from one scheduler thread
5003        // (step_dspark_spec), so sessions interleave at burst boundaries only.
5004        // DEFAULT ON on the serve route since the v0.103 train (owner-ratified
5005        // 2026-08-22, §10 re-gate at flip): MEMRA_DSPARK_VERIFY_GRAPH=0 is the
5006        // kill-switch that keeps this None — the eager walk, byte-identical (the
5007        // kill-switch arm of the serve battery). The bin arm keeps its own opt-in.
5008        let mut vg_guard = self.dspark_vgraphs.lock().unwrap();
5009        if vg_guard.is_none() && embd_gpu.is_some() && crate::spec::dspark_verify_graph_serve_on() {
5010            *vg_guard = crate::spec::DsparkVerifyGraphs::new(e, &sess.cache, vt_cap, n_embd)?;
5011            if vg_guard.is_some() {
5012                // Engagement receipt (the §8 dead-arm lesson): prove the door is LIVE on
5013                // the serve surface — S6b banked the tip server carrying zero door strings.
5014                eprintln!("[dspark-vg] serve pool ENGAGED (vt_cap={vt_cap})");
5015            }
5016        }
5017        let vgraphs: &mut Option<crate::spec::DsparkVerifyGraphs> = &mut vg_guard;
5018        'outer: while out.len() < burst_target && !sess.done {
5019            let start = sess.cache.pos;
5020            if start + nd + 1 > sess.max_ctx {
5021                sess.done = true;
5022                break;
5023            }
5024            sess.rounds += 1;
5025            let mut vt = sess.vt;
5026            // ---- draft: block = [last, MASK x b-1] (identical to the bin arm) ----
5027            // RAII: a `?` exit restores the pre-scope value instead of latching exact
5028            // ON engine-wide across every later request (hermes finding, fixed
5029            // 2026-08-23 — this burst had several `?`s between the manual true/false).
5030            let exact_scope = e.exact_scope(true);
5031            let mut block: Vec<u32> = vec![c.mask_token_id; b];
5032            block[0] = sess.last;
5033            let noise = e.htod(&self.embd.try_gather(n_embd, &block)?)?;
5034            let pos_block: Vec<i32> = ((start as i32)..(start + b) as i32).collect();
5035            let dh = draft.forward_round(e, &mut sess.dkv, &noise, &pos_block)?;
5036            // Harvest: logits over rows r0..r0+nd (see the bin arm / the postmortem).
5037            let mut rows = e.uninit(nd * n_embd)?;
5038            {
5039                let dv = e.view(&dh, b * n_embd);
5040                let src = dv.slice(r0 * n_embd..(r0 + nd) * n_embd);
5041                e.copy_view_into(&mut rows, 0, &src, nd * n_embd)?;
5042            }
5043            // TRIMMED DRAFT HEAD (lane/dflash2-head-trim, 2026-08-25): DFlash2 family
5044            // only — the selector consumes (value, candidate-id) pairs, so a d2t remap
5045            // after top-k restores true ids; the markov/chain arms argmax dl columns
5046            // into token ids DIRECTLY and must keep the full head. Reuses the FR-Spec
5047            // self-trim the load path builds on the MTP struct (MEMRA_FRSPEC_TRIM):
5048            // gathered rows of the target's own head, zero requant. Verify stays
5049            // full-vocab, so the trim moves draft acceptance only, never output.
5050            let trim = if draft.dflash2.is_some() {
5051                self.mtp
5052                    .as_ref()
5053                    .filter(|m| m.d2t_from_target_head)
5054                    .and_then(|m| m.shared_head_head.as_ref().zip(m.d2t.as_ref()))
5055                    // MEMRA_MTP_SKIP stub: the same target-head trimmed rows, parked in
5056                    // `dflash_trim` because the embedded MTP block was skipped (hybrid.rs;
5057                    // rows are target-head by construction; the loader refuses otherwise).
5058                    .or_else(|| self.dflash_trim.as_ref().map(|t| (&t.head, &t.d2t)))
5059                    .filter(|(_, d2t)| !d2t.is_empty())
5060            } else {
5061                None
5062            };
5063            let (dl_head, dl_vocab) = match trim {
5064                Some((head, d2t)) => (head, d2t.len()),
5065                None => (&self.output, n_vocab),
5066            };
5067            let trim_d2t = trim.map(|(_, d2t)| d2t.as_slice());
5068            let mut dl = e.matmul(dl_head, &rows, nd)?;
5069            // Family/sampling-keyed proposal — identical to the bin arm (see there for
5070            // the program law: sampled records the true q, DFlash2 rides the selector,
5071            // the markov/plain greedy chain keeps the slice-2 deferral). Confidence
5072            // policy: stash markov prev-token embeddings d2d during the chain, one host
5073            // readback after — identical to the bin arm.
5074            let want_conf_emb = vt_policy.is_confidence()
5075                && draft.confidence.as_ref().is_some_and(|ch| ch.with_markov);
5076            let mut conf_emb: Option<CudaSlice<f32>> = match (&draft.markov, want_conf_emb) {
5077                (Some(mk), true) => Some(e.uninit(nd * mk.rank)?),
5078                (None, true) => unreachable!(
5079                    "with_markov confidence head without a markov table — the loader forbids it"
5080                ),
5081                _ => None,
5082            };
5083            let mut cand: Vec<u32> = Vec::with_capacity(nd + 1);
5084            let mut prop: Option<DsparkDraftSample> = None;
5085            let mut chain_dev: Option<CudaSlice<u32>> = None;
5086            // Slice 2: arm choice read before the chain readback (see the bin arm; the
5087            // serve arm has no CKPT_GATE oracle — the bin arm carries it).
5088            let ckpt_on = std::env::var("MEMRA_DSPARK_CKPT").as_deref() != Ok("0");
5089            let mut deferred = false;
5090            if let Some(sp) = sp_on.as_ref() {
5091                // SAMPLED proposal (family-keyed; identical to the bin arm).
5092                let (tail, ds) = draft.dspark_propose_sampled(
5093                    e,
5094                    &mut dl,
5095                    &rows,
5096                    nd,
5097                    dl_vocab,
5098                    sess.last,
5099                    sp,
5100                    &mut sess.sctr,
5101                    &mut sess.uctr,
5102                    conf_emb.as_mut(),
5103                    trim_d2t,
5104                )?;
5105                drop(exact_scope);
5106                cand.push(sess.last);
5107                cand.extend_from_slice(&tail);
5108                prop = Some(ds);
5109            } else if draft.dflash2.is_some() {
5110                // DFlash2: candidate path selector replaces the markov chain
5111                // (identical to the bin arm).
5112                let path = draft
5113                    .dflash2_propose_greedy(e, &dl, &rows, nd, dl_vocab, sess.last, trim_d2t)?;
5114                drop(exact_scope);
5115                cand.push(sess.last);
5116                cand.extend_from_slice(&path);
5117            } else {
5118                let markov_on = std::env::var("MEMRA_DFLASH_MARKOV").as_deref() != Ok("0");
5119                let mut chain_d = e.stream().alloc_zeros::<u32>(nd + 1)?;
5120                if let (Some(mk), true) = (&draft.markov, markov_on) {
5121                    e.set_u32_one(&mut chain_d, sess.last)?;
5122                    for k in 0..nd {
5123                        let mut f = e.uninit(mk.rank)?;
5124                        e.gather_row_bf16(&mk.w1_bf16, &chain_d, k, &mut f, mk.rank)?;
5125                        if let Some(ce) = conf_emb.as_mut() {
5126                            let fv = e.view(&f, mk.rank);
5127                            e.copy_view_into(ce, k * mk.rank, &fv, mk.rank)?;
5128                        }
5129                        let bias = e.matmul(&mk.w2, &f, 1)?;
5130                        e.add_row_inplace(&mut dl, &bias, n_vocab, k * n_vocab)?;
5131                        e.argmax_token_device_col(&dl, k, n_vocab, &mut chain_d, k + 1)?;
5132                    }
5133                } else {
5134                    if want_conf_emb {
5135                        // chain_d[0] must carry the anchor — slot 0's prev token.
5136                        e.set_u32_one(&mut chain_d, sess.last)?;
5137                    }
5138                    for i in 0..nd {
5139                        if let (Some(ce), Some(mk)) = (conf_emb.as_mut(), &draft.markov) {
5140                            let mut f = e.uninit(mk.rank)?;
5141                            e.gather_row_bf16(&mk.w1_bf16, &chain_d, i, &mut f, mk.rank)?;
5142                            let fv = e.view(&f, mk.rank);
5143                            e.copy_view_into(ce, i * mk.rank, &fv, mk.rank)?;
5144                        }
5145                        e.argmax_token_device_col(&dl, i, n_vocab, &mut chain_d, i + 1)?;
5146                    }
5147                }
5148                drop(exact_scope);
5149                deferred = embd_gpu.is_some() && ckpt_on;
5150                chain_dev = Some(chain_d);
5151            }
5152            // ---- H4 confidence window: size THIS round's verify from the head ----
5153            if vt_policy.is_confidence() {
5154                let ch = draft.confidence.as_ref().expect("asserted at burst entry");
5155                let (rows_h, emb_h) = match conf_emb.as_ref() {
5156                    Some(ce) => {
5157                        let (a, b2) = e.dtoh_pair(&rows, ce)?;
5158                        (a, Some(b2))
5159                    }
5160                    None => (e.dtoh(&rows)?, None),
5161                };
5162                let rank = draft.markov.as_ref().map(|m| m.rank).unwrap_or(0);
5163                let mut raws = Vec::with_capacity(nd);
5164                for k in 0..nd {
5165                    let hrow = &rows_h[k * n_embd..(k + 1) * n_embd];
5166                    let emb = emb_h.as_ref().map(|eh| &eh[k * rank..(k + 1) * rank]);
5167                    raws.push(ch.raw_score(hrow, emb));
5168                }
5169                vt = vt_policy
5170                    .size_window(&raws, vt_cap)
5171                    .expect("confidence policies always size the window");
5172            }
5173            // Non-deferred greedy chain readback (the sampled and DFlash2 proposals
5174            // built `cand` at the walk; deferred rounds build it after the merged
5175            // readback — bytes identical, chain_d written before either sync).
5176            if let Some(chain_d) = chain_dev.as_ref()
5177                && !deferred
5178            {
5179                let chain = e.dtoh_u32(chain_d)?;
5180                cand.push(sess.last);
5181                cand.extend_from_slice(&chain[1..]);
5182            }
5183
5184            // ---- snapshot, then verify t=vt (ckpt stash default; oracle arms kept) ----
5185            // Slice 1: batched snap (see DsparkSnapBatch) with the legacy per-layer
5186            // snapshot as the kill-switch / non-uniform fallback.
5187            let mut snap_legacy: Option<crate::cache::CacheSnapshot> = None;
5188            if !sess.snapb_off && sess.snapb.is_none() {
5189                sess.snapb = DsparkSnapBatch::new(e, &sess.cache)?;
5190                sess.snapb_off = sess.snapb.is_none();
5191            } else if let Some(sb) = sess.snapb.as_mut() {
5192                sb.refresh(e, &sess.cache)?;
5193            }
5194            let snap: &crate::cache::CacheSnapshot = match sess.snapb.as_ref() {
5195                Some(sb) => &sb.snap,
5196                None => {
5197                    snap_legacy = Some(sess.cache.snapshot(e)?);
5198                    snap_legacy.as_ref().unwrap()
5199                }
5200            };
5201            let _ = &snap_legacy;
5202            // Slice 3: the tap-sink buffer is persistent per vt in the graphs ctx
5203            // (captured segments bake its address — a per-round alloc here would make
5204            // every session's replayed tap copies write freed memory); fully rewritten
5205            // by every verify, so pool ownership changes no bytes.
5206            let tap_buf = match vgraphs.as_mut().and_then(|g| g.tap_bufs.remove(&vt)) {
5207                Some(buf) => buf,
5208                None => e.uninit(vt * n_taps * n_embd)?,
5209            };
5210            sess.cache.dflash_taps = Some(DflashTapSink {
5211                layer_ids: c.target_layer_ids.clone(),
5212                buf: tap_buf,
5213                hidden: n_embd,
5214                t: vt,
5215                base: 0,
5216            });
5217            // Composition guard (sampled admission × model-owned pool, this train's
5218            // cross-product): the slab flag is a per-round statement, but only the
5219            // graphs-aware verify (`_am_ckpt_dev`) clears it. Serve sessions MIX arms
5220            // within one process-lifetime pool — a SAMPLED round rides the raw-logits
5221            // twins (no graphs param) and must not inherit `round_slab=true` from a
5222            // previous greedy session's captured round, or its commit is steered at
5223            // slabs the round never wrote. Clear at the round boundary; the deferred
5224            // arm re-derives it inside the verify. (The bin arm has the same shape but
5225            // fixes its sampling mode per process, so no mixed rounds exist there.)
5226            if let Some(g) = vgraphs.as_mut() {
5227                g.round_slab = false;
5228            }
5229            // The whole fallible verify window runs inside a closure so the Err path
5230            // can return the sink buffer to the ctx pool before propagating — the
5231            // serve-surface twin of the EOS-orphan lesson: a mid-verify error
5232            // propagates OUT of the burst, the request dies, the session's cache is
5233            // dropped — but the PROCESS (and the pool, with the tap-buffer address
5234            // baked into its captures) lives on. Recover the ctx-owned buffer before
5235            // the error escapes, or the next session's replayed tap copies write
5236            // freed memory. The bin arm has no such path (a gate-binary error ends
5237            // the process).
5238            #[allow(clippy::type_complexity)] // allow: one-shot composite type; naming it would hide the shape that matters at the call site
5239            let verify_out = (|| -> Result<
5240                (
5241                    Vec<u32>,
5242                    Option<CudaSlice<f32>>,
5243                    Option<crate::spec::DsparkVerifyCkpt>,
5244                ),
5245                Box<dyn std::error::Error>,
5246            > {
5247                if sp_on.is_some() {
5248                    // SAMPLED: raw verify logits for the rejection walk (bin-arm twin).
5249                    if ckpt_on {
5250                        let (tl, vck) = self.dspark_verify_t_logits_ckpt(
5251                            e,
5252                            &cand[..vt],
5253                            start,
5254                            &mut sess.cache,
5255                        )?;
5256                        Ok((Vec::new(), Some(tl), Some(vck)))
5257                    } else {
5258                        Ok((
5259                            Vec::new(),
5260                            Some(self.dspark_verify_t_logits(
5261                                e,
5262                                &cand[..vt],
5263                                start,
5264                                &mut sess.cache,
5265                            )?),
5266                            None,
5267                        ))
5268                    }
5269                } else if deferred {
5270                    // Slice 2: device-token verify + ONE merged readback (see the bin arm).
5271                    let chain_d = chain_dev.as_ref().expect("deferred implies greedy chain");
5272                    let g = embd_gpu.expect("deferred implies resident embed");
5273                    let (am_d, vck) = self.dspark_verify_t_am_ckpt_dev(
5274                        e,
5275                        chain_d,
5276                        vt,
5277                        start,
5278                        &mut sess.cache,
5279                        (g, embd_qt, embd_rb),
5280                        vgraphs.as_mut(),
5281                    )?;
5282                    let ch = e.stream().clone_dtoh(chain_d)?;
5283                    let am = e.stream().clone_dtoh(&am_d)?;
5284                    e.stream().synchronize()?;
5285                    cand.push(sess.last);
5286                    cand.extend_from_slice(&ch[1..]);
5287                    Ok((am, None, Some(vck)))
5288                } else if ckpt_on {
5289                    let (vam, vck) =
5290                        self.dspark_verify_t_am_ckpt(e, &cand[..vt], start, &mut sess.cache)?;
5291                    Ok((vam, None, Some(vck)))
5292                } else {
5293                    Ok((
5294                        self.dspark_verify_t_am(e, &cand[..vt], start, &mut sess.cache)?,
5295                        None,
5296                        None,
5297                    ))
5298                }
5299            })();
5300            let (vam, tl, vck) = match verify_out {
5301                Ok(v) => v,
5302                Err(err) => {
5303                    if let Some(taps) = sess.cache.dflash_taps.take()
5304                        && let Some(g) = vgraphs.as_mut()
5305                    {
5306                        g.tap_bufs.insert(vt, taps.buf);
5307                    }
5308                    return Err(err);
5309                }
5310            };
5311            let taps = sess.cache.dflash_taps.take().unwrap();
5312            // Return the tap buffer to the ctx pool IMMEDIATELY — an EOS/budget break
5313            // between accept and ingest must never orphan an address the captured graphs
5314            // bake (the bin arm's lesson, and it holds doubly here: the pool outlives
5315            // the SESSION, not just the round). Ingest reads it borrowed.
5316            let tap_local: Option<CudaSlice<f32>> = match vgraphs.as_mut() {
5317                Some(g) => {
5318                    g.tap_bufs.insert(vt, taps.buf);
5319                    None
5320                }
5321                None => Some(taps.buf),
5322            };
5323            let tap_ref: &CudaSlice<f32> = match &tap_local {
5324                Some(b) => b,
5325                None => &vgraphs.as_ref().expect("ctx present above").tap_bufs[&vt],
5326            };
5327
5328            // ---- accept ----
5329            // Penalized-sampled: anchor joins the window before the walk (committed this
5330            // round via the out.push below); accepted drafts extend it after — identical
5331            // to the bin arm.
5332            if pen_on {
5333                sess.pen_hist.push(sess.last);
5334            }
5335            let (m, next) = match (sp_on.as_ref(), tl.as_ref()) {
5336                (Some(sp), Some(tl)) => {
5337                    let w0 = sess
5338                        .pen_hist
5339                        .len()
5340                        .saturating_sub(sp.penalty_last_n.min(crate::spec::PEN_WINDOW_MAX));
5341                    dspark_accept_sampled(
5342                        e,
5343                        tl,
5344                        &cand,
5345                        vt,
5346                        n_vocab,
5347                        &dl,
5348                        prop.as_ref()
5349                            .expect("sampled round without a proposal record"),
5350                        sp,
5351                        &sess.pen_hist[w0..],
5352                        &mut sess.sctr,
5353                        &mut sess.uctr,
5354                    )?
5355                }
5356                _ => {
5357                    let m = dspark_accept_prefix(&cand, &vam, vt);
5358                    (m, vam[m])
5359                }
5360            };
5361            drafted += vt - 1;
5362            accepted_n += m;
5363            // keep = the rows this round adds to the PUBLIC stream. Without eos that is
5364            // the anchor + all accepted drafts (m+1). With eos it is the anchor + drafts
5365            // UP TO AND INCLUDING eos: the walk may accept real tokens past eos (they are
5366            // the model's own continuation), but emission stops at eos, and a parked
5367            // session whose cache holds rows past the public stream can never resume —
5368            // the park gate `pos() == fed` would refuse every eos-terminated stream
5369            // (measured: 7/8 turns on the mtreuse gate, overshoot 1-6 rows). Truncating
5370            // the commit at eos uses the SAME prefix-commit machinery as a mid-round
5371            // rejection, so the hybrid (GDN) state is exact by the same argument.
5372            // Emitted bytes are untouched — this only changes post-eos cache state.
5373            let mut keep = m + 1;
5374            let mut terminal = false;
5375            if eos.contains(&sess.last) {
5376                terminal = true;
5377                keep = 1;
5378            } else {
5379                for (j, &dt) in cand[1..=m].iter().enumerate() {
5380                    if eos.contains(&dt) {
5381                        terminal = true;
5382                        keep = j + 2; // anchor + drafts through eos
5383                        break;
5384                    }
5385                }
5386            }
5387            // The request's max_tokens boundary is also a commit boundary, not merely an
5388            // output slice. It is NOT the scheduler's smaller per-tick burst quantum: accepted
5389            // surplus crossing that quantum stays public and the session remains live. Only at
5390            // the true request boundary do we keep the publishable prefix so cache.pos == fed at
5391            // retire and mark the session terminal until a non-empty next-turn suffix resumes
5392            // it. This uses the same prefix-commit machinery as EOS/rejection and makes
5393            // max-token sessions safe to park instead of permanently cold (Hermes
5394            // `f22a180d1638b95a`).
5395            let (bounded_keep, budget_terminal) =
5396                dspark_commit_limit(keep, out.len(), request_room);
5397            keep = bounded_keep;
5398            terminal |= budget_terminal;
5399            out.push(sess.last);
5400            out.extend_from_slice(&cand[1..keep]);
5401            sess.done = terminal;
5402            if pen_on {
5403                // Only the PUBLIC drafts feed the penalty window — tokens accepted past
5404                // eos never reach the stream, and a resumed session must not penalize
5405                // ghosts (the parked pen_hist seeds the resume's window).
5406                sess.pen_hist.extend_from_slice(&cand[1..keep]);
5407            }
5408
5409            // ---- commit/rollback (stash arm default; replay oracle kept) ----
5410            // Slice 3: rounds whose linear column stash lives in the graphs ctx's slabs
5411            // commit through the slab twin (same semantics, slab-addressed sources) —
5412            // identical to the bin arm's dispatch.
5413            let slab_commit = vgraphs.as_ref().map(|g| g.round_slab).unwrap_or(false);
5414            if keep < vt {
5415                if slab_commit {
5416                    self.dspark_commit_prefix_slab(
5417                        e,
5418                        &mut sess.cache,
5419                        snap,
5420                        vgraphs.as_ref().expect("slab_commit implies ctx"),
5421                        keep,
5422                    )?;
5423                } else if let Some(vck) = vck.as_ref() {
5424                    self.dspark_commit_prefix(e, &mut sess.cache, snap, vck, keep)?;
5425                } else {
5426                    crate::pp::restore_cache_checkpoint(e, self, None, &mut sess.cache, snap)?;
5427                    debug_assert_eq!(sess.cache.pos, start, "rollback landed off the round start");
5428                    let ram = self.dspark_verify_t_am(e, &cand[..keep], start, &mut sess.cache)?;
5429                    if sp_on.is_none() {
5430                        // greedy-only oracle; the sampled arm replays to rebuild state.
5431                        debug_assert_eq!(
5432                            &ram[..],
5433                            &vam[..keep],
5434                            "prefix replay must reproduce the verify argmaxes"
5435                        );
5436                    }
5437                }
5438            }
5439
5440            // ---- ingest the kept rows' ctx features into the draft KV ----
5441            {
5442                let tv = e.view(tap_ref, vt * n_taps * n_embd);
5443                let keep_view = tv.slice(0..keep * n_taps * n_embd);
5444                let mut kept = e.uninit(keep * n_taps * n_embd)?;
5445                e.copy_view_into(&mut kept, 0, &keep_view, keep * n_taps * n_embd)?;
5446                let f = draft.ctx_features(e, &kept, keep)?;
5447                let pos_k: Vec<i32> =
5448                    ((sess.ctx_len as i32)..(sess.ctx_len + keep) as i32).collect();
5449                draft.ingest_ctx(e, &mut sess.dkv, &f, &pos_k, keep)?;
5450                sess.ctx_len += keep;
5451            }
5452            if sess.done {
5453                // EOS or the public budget landed this round: cache, draft KV and ctx_len are
5454                // all clamped to the public stream (park shape); `next` is beyond the terminal
5455                // boundary and must not become the anchor of a resumed session.
5456                break 'outer;
5457            }
5458            sess.last = next;
5459            // Ladder update only — the confidence policies recompute vt from the
5460            // head every round, post-draft pre-verify; their carry just keeps
5461            // observability (sess.vt = the last confidence-sized window).
5462            if vt_policy.is_confidence() {
5463                sess.vt = vt;
5464            } else if adapt {
5465                sess.vt = (m + 2).clamp(3, vt_cap);
5466            }
5467        }
5468        Ok((out, drafted, accepted_n))
5469    }
5470}
5471
5472// ================= Harvest-convention gate (CPU; DSPARK-POSTMORTEM-20260820.md) =========
5473// The parity oracle is row-count-agnostic (it reproduces the markov MODULE on whatever
5474// rows it is fed) and the E2E gate is harvest-independent (verify-side truth), so
5475// NEITHER can catch a wrong row->position mapping — that blindness is how the q38
5476// misalignment shipped. These tests pin the convention itself as logic the round
5477// consumes, so a mutation back to the mask-fill harvest under the Dspark variant fails
5478// HERE, naming the convention.
5479#[cfg(test)]
5480mod dflash2_tests {
5481
5482    /// The tail-import refusal arms (lane/dspark-draft-plane-20260827 review finding: these
5483    /// were claimed tested and were not). Pure, so they run everywhere; the geometry mirrors
5484    /// the served DFlash2 drafter (5 layers, 8 kv x 128 dim f32 rows, window 2048 + block 8).
5485    #[test]
5486    fn tail_import_refuses_every_geometry_disagreement_and_accepts_the_exported_shape() {
5487        let rb = 8 * 128 * 4; // n_kv * head_dim * f32
5488        let win = 2048 + 8; // window_rows = sliding_window + block
5489        // THE EXPORTED SHAPE: window_rows ending exactly at len, same geometry — accepted.
5490        assert!(
5491            super::tail_geometry_ok(5, rb, 30_329 - win, win, 30_329, 0, 5, rb, win, 34_433)
5492                .is_ok()
5493        );
5494        // A short history where the tail IS the whole history — accepted.
5495        assert!(super::tail_geometry_ok(5, rb, 0, 100, 100, 0, 5, rb, win, 34_433).is_ok());
5496        // FLOOR-BEARING (lane/spec-exclusions-20260902): a cold-drafter exporter at floor
5497        // 30_000 owns rows [30_000, 30_329) only, so its 329-row tail is everything readable
5498        // above the floor — accepted; the same 329 rows from a floor-0 exporter are the
5499        // truncation the pre-lane rule refuses, verbatim; a tail claiming rows BELOW its
5500        // exporter's floor is a geometry lie and refuses by name.
5501        assert!(
5502            super::tail_geometry_ok(5, rb, 30_000, 329, 30_329, 30_000, 5, rb, win, 34_433).is_ok()
5503        );
5504        assert_eq!(
5505            super::tail_geometry_ok(5, rb, 30_000, 329, 30_329, 0, 5, rb, win, 34_433).unwrap_err(),
5506            "tail shorter than the drafter's readable window"
5507        );
5508        assert_eq!(
5509            super::tail_geometry_ok(5, rb, 29_990, 339, 30_329, 30_000, 5, rb, win, 34_433)
5510                .unwrap_err(),
5511            "tail starts below its exporter's context floor"
5512        );
5513        // Every refusal arm, each by name:
5514        let arm = |l, r, b, rows, len, cap| {
5515            super::tail_geometry_ok(l, r, b, rows, len, 0, 5, rb, win, cap)
5516        };
5517        assert_eq!(
5518            arm(4, rb, 30_329 - win, win, 30_329, 34_433).unwrap_err(),
5519            "layer count differs from the live drafter"
5520        );
5521        assert_eq!(
5522            arm(5, rb - 4, 30_329 - win, win, 30_329, 34_433).unwrap_err(),
5523            "row geometry differs from the live drafter"
5524        );
5525        assert_eq!(
5526            arm(5, rb, 30_329 - win, win, 30_329, 30_000).unwrap_err(),
5527            "logical length exceeds the session cap"
5528        );
5529        // THE RUN-2 BUG, pinned: a tail whose base+rows lands past its own logical length —
5530        // the export-at-current-length defect the gate caught on the box.
5531        assert_eq!(
5532            arm(5, rb, 30_364 - win, win, 30_329, 34_433).unwrap_err(),
5533            "tail does not end at its own logical length"
5534        );
5535        assert_eq!(
5536            arm(5, rb, 30_329 - (win - 100), win - 100, 30_329, 34_433).unwrap_err(),
5537            "tail shorter than the drafter's readable window"
5538        );
5539    }
5540
5541    use super::{
5542        DsparkHarvest, dflash2_walk_greedy, dflash2_walk_sampled, dspark_commit_limit,
5543        rejection_accept_len,
5544    };
5545
5546    // ================= memra#95: the full-cover restore panic =================
5547    //
5548    // `walk: candidate 4294967295 outside codebook vocab` (the greedy and sampled walk
5549    // asserts) on the FIRST round of a `MEMRA_GLM5_SPEC_FULLCOVER=1` restored session,
5550    // fleet-fatal. `4294967295` is the top-k selector's exhausted-slot sentinel, so the
5551    // draft logits row was NaN. The row was NaN because the drafter ctx KV is imported on
5552    // the CALLER's stream at admission (`DflashKv::from_tail`) while round 1 reads it
5553    // through `glm5_head_engine`, which under a live ppN split is the last stage's OWN
5554    // Engine used OUTSIDE any `rt.enter` scope, i.e. that Engine's own stream. Nothing
5555    // ordered the two.
5556    //
5557    // THE RETRACTED THEORY, kept because it is what made a wrong fix look right (review
5558    // round 1 on PR #100): "the full-cover arm never calls `prime_cache` and therefore
5559    // never inherits `prime_cache_hyper_ppn`'s `fence_stages_behind`". That fence has the
5560    // SAME blind spot — it orders `StageRt::stream`, the enter-scope stream, not a stage
5561    // ENGINE's own stream — so inheriting it would have fixed nothing. What actually shields
5562    // the suffix arm is that `prime_cache` returns its logits through `Engine::dtoh`, which
5563    // is `stream().synchronize()` on the caller. The full-cover arm has no prime and no
5564    // device readback at all between the import and the round (its anchor comes from the
5565    // entry's host-side boundary logits), which is why it is the only exposed path, and why
5566    // only round 1 dies: from round 2 on, `dflash2_propose_*`'s own `dtoh_u32` drains the
5567    // head engine.
5568    //
5569    // Two gates below: the ordering seam (asserted on the ENGINE-ordering helper, so it
5570    // rejects the `fence_stages_behind` shape too), and the blast radius.
5571
5572    /// The sentinel a top-k row that could not be filled carries into the walk.
5573    #[test]
5574    fn an_unfilled_selector_slot_is_refused_by_name_not_clamped() {
5575        // top_k = 4, one draft slot; the selector filled two slots and gave up, which is what
5576        // `topk_rows_f32` writes for a partially finite row.
5577        let cand = [7u32, 11, super::TOPK_EMPTY_SLOT, super::TOPK_EMPTY_SLOT];
5578        let why = super::dflash2_guard_candidates(&cand, 1000, "gate")
5579            .expect_err("an exhausted slot must be refused");
5580        assert!(why.contains("slot 2"), "{why}");
5581        assert!(why.contains("4294967295"), "{why}");
5582        assert!(
5583            why.contains("exhausted-slot sentinel") && why.contains("NaN"),
5584            "the refusal must name the mechanism, not just the number: {why}"
5585        );
5586        // THE OBSERVED SHAPE (memra#95): a fully NaN row fills EVERY slot with the sentinel,
5587        // so the refusal has to bite at slot 0, before the walk's `prev` chain even starts.
5588        let all_nan = [super::TOPK_EMPTY_SLOT; 4];
5589        let why0 = super::dflash2_guard_candidates(&all_nan, 1000, "gate")
5590            .expect_err("an all-sentinel row must be refused");
5591        assert!(why0.contains("slot 0"), "{why0}");
5592        // An ordinary out-of-range id is refused too (the trimmed head's rank space is
5593        // narrower than the vocab, and a remap of a bad rank would panic in the map).
5594        assert!(super::dflash2_guard_candidates(&[7, 1000], 1000, "gate").is_err());
5595        // A well-formed row passes, and the bound is exclusive.
5596        super::dflash2_guard_candidates(&[0, 999, 500, 1], 1000, "gate").expect("clean row");
5597    }
5598
5599    /// The walk's own assert is the LAST line of defence and stays exactly where it is:
5600    /// the guard above refuses one request, this refuses the round.
5601    #[test]
5602    #[should_panic(expected = "walk: candidate")]
5603    fn the_walk_assert_survives_the_guard() {
5604        const VOCAB: usize = 8;
5605        const RANK: usize = 2;
5606        const TOPK: usize = 2;
5607        let pred = vec![0u8; VOCAB * RANK * 2];
5608        let succ = vec![0u8; VOCAB * RANK * 2];
5609        let cand = [1u32, super::TOPK_EMPTY_SLOT];
5610        let _ = dflash2_walk_greedy(
5611            &pred,
5612            &succ,
5613            VOCAB,
5614            RANK,
5615            TOPK,
5616            &[0.0; TOPK],
5617            &cand,
5618            &[0.0; RANK],
5619            0,
5620            1,
5621        );
5622    }
5623
5624    /// WIRING GATE (invocations in comment-stripped source, never prose, the
5625    /// wiring-assertions-match-prose law). Both halves of the memra#95 fix are LIVE code.
5626    ///
5627    /// The ordering half is asserted on the ENGINE-ordering seam, not on
5628    /// `fence_stages_behind`: that distinction IS the defect (a stage's enter-scope stream is
5629    /// not the stage Engine's own stream, and the draft phase runs on the latter), so a gate
5630    /// that accepted either would accept the broken shape.
5631    #[test]
5632    fn the_fullcover_restore_ordering_seam_is_live_in_comment_stripped_source() {
5633        let strip = |src: &str| -> String {
5634            src.lines()
5635                .map(|l| l.split("//").next().unwrap_or(""))
5636                .collect::<Vec<_>>()
5637                .join("\n")
5638        };
5639
5640        // 1. THE CAUSE. `glm5_spec_session_from_restored` orders the head/drafter engine
5641        //    behind the caller BEFORE the suffix branch, so it covers the full-cover arm
5642        //    (which has no prime, and therefore no incidental host sync, to hide behind).
5643        let glm5 = strip(include_str!("glm_spec.rs"));
5644        let body = glm5
5645            .find("pub fn glm5_spec_session_from_restored(")
5646            .expect("the restored-session builder exists");
5647        let end = glm5[body..]
5648            .find("fn glm5_d2t(")
5649            .expect("the builder's end anchor exists")
5650            + body;
5651        let scope = &glm5[body..end];
5652        let eh = scope
5653            .find("let eh = self.glm5_head_engine(e)?;")
5654            .expect("the builder resolves the head engine");
5655        let order = scope
5656            .find("crate::pp::PpNRt::order_engine_behind(e, eh)?;")
5657            .expect(
5658                "the restored-session builder must order the head engine's own stream behind \
5659                 the caller (fence_stages_behind is the WRONG seam: it orders enter-scope \
5660                 stage streams, and the draft phase never enters a stage)",
5661            );
5662        let branch = scope
5663            .find("let (logits_s, tap_rows, prefix_capture) = if suffix.is_empty()")
5664            .expect("the full-cover branch exists");
5665        assert!(
5666            eh < order && order < branch,
5667            "the ordering must sit between the head-engine binding and the full-cover/suffix \
5668             branch: after it so it names the right engine, before it so the prime-free arm \
5669             is covered"
5670        );
5671
5672        // 1b. The helper it calls really orders the ENGINE streams, not the stage streams.
5673        let pp = strip(include_str!("pp.rs"));
5674        let helper = pp
5675            .find("pub fn order_engine_behind(")
5676            .expect("the engine-ordering helper exists");
5677        let rest = &pp[helper..];
5678        let hbody = &rest[..rest.find("\n    pub fn ").unwrap_or(rest.len().min(2000))];
5679        assert!(
5680            hbody.contains("let s = src.stream();") && hbody.contains("dst.gpu.main_stream()"),
5681            "the helper must order the two ENGINES' own streams, source side through the \
5682             ambient-aware accessor and destination side through the override-blind one"
5683        );
5684        assert!(
5685            hbody.contains("if src.ctx() == dst.ctx() {"),
5686            "the context test must be VALUE equality: CudaContext::new allocates a fresh Arc \
5687             per call for the same primary context, so Arc::ptr_eq would make the async event \
5688             path dead code and every restored session would pay a host sync"
5689        );
5690
5691        // 2. THE BLAST RADIUS. Both proposal seams guard the candidate buffer BEFORE the
5692        //    d2t remap (a sentinel would index the map out of bounds) and before the walk.
5693        let d2 = strip(include_str!("dflash.rs"));
5694        // Cut at the FIRST test module so no assertion can be satisfied by this test's own
5695        // string literals (the self-match trap the wiring-assertions law names). Note this
5696        // leaves only the pre-test part of the file live: a seam added AFTER the first
5697        // `#[cfg(test)]` would be invisible here and would need its own anchor.
5698        let live = &d2[..d2.find("#[cfg(test)]").expect("this file has test modules")];
5699        for (seam, arm) in [
5700            ("pub fn dflash2_propose_greedy_q(", "greedy"),
5701            ("pub(crate) fn dflash2_propose_sampled(", "sampled"),
5702        ] {
5703            let at = live
5704                .find(seam)
5705                .unwrap_or_else(|| panic!("{arm} proposal seam exists"));
5706            let window = live.get(at..at + 4000).unwrap_or(&live[at..]);
5707            let guard = window
5708                .find("dflash2_guard_candidates(&cand, n_vocab,")
5709                .unwrap_or_else(|| panic!("the {arm} proposal must guard its candidates"));
5710            let remap = window
5711                .find("*c = map[*c as usize];")
5712                .unwrap_or_else(|| panic!("the {arm} proposal still remaps through d2t"));
5713            assert!(
5714                guard < remap,
5715                "the {arm} guard must run before the d2t remap"
5716            );
5717        }
5718    }
5719
5720    #[test]
5721    fn max_tokens_caps_the_committed_prefix_not_only_the_visible_slice() {
5722        // A round crossing the scheduler's 32-token quantum is not terminal when the
5723        // request still has room. The whole accepted prefix stays public and committed.
5724        assert_eq!(dspark_commit_limit(5, 30, 100), (5, false));
5725        // The same round at the true request boundary is clamped and terminal so the
5726        // parked cache cannot contain rows the worker did not publish.
5727        assert_eq!(dspark_commit_limit(5, 30, 33), (3, true));
5728        assert_eq!(dspark_commit_limit(2, 3, 10), (2, false));
5729        assert_eq!(dspark_commit_limit(1, 0, 1), (1, false));
5730    }
5731
5732    /// f32 -> bf16 bytes (truncation; test values are bf16-exact small integers).
5733    fn bf16(vals: &[f32]) -> Vec<u8> {
5734        vals.iter()
5735            .flat_map(|v| ((v.to_bits() >> 16) as u16).to_le_bytes())
5736            .collect()
5737    }
5738
5739    const V: usize = 8; // test vocab
5740    const R: usize = 2; // selector rank
5741    const K: usize = 2; // top_k
5742
5743    /// Codebooks for the chain tests: pred rows are one-hot-ish, succ rows chosen so
5744    /// the slot-1 winner FLIPS with the slot-0 choice.
5745    #[allow(clippy::identity_op)] // allow: the explicit +0/*1/>>0 terms document the lane/byte symmetry of the reference layout
5746    fn books() -> (Vec<u8>, Vec<u8>) {
5747        let mut pred = vec![0f32; V * R];
5748        pred[0] = 1.0; // tok 0: [1, 0]  (the anchor)
5749        pred[1 * R + 1] = 1.0; // tok 1: [0, 1]
5750        pred[2 * R] = 1.0; // tok 2: [1, 0]
5751        let mut succ = vec![0f32; V * R];
5752        succ[1 * R] = 2.0; // tok 1: [2, 0]
5753        succ[2 * R + 1] = 5.0; // tok 2: [0, 5]
5754        succ[3 * R + 1] = 3.0; // tok 3: [0, 3]
5755        succ[4 * R] = 10.0; // tok 4: [10, 0]
5756        (bf16(&pred), bf16(&succ))
5757    }
5758
5759    #[test]
5760    fn selector_walk_is_a_chain_not_per_slot_argmax() {
5761        let (pred, succ) = books();
5762        // slot 0 candidates {1, 2}, slot 1 candidates {3, 4}; hproj all-ones.
5763        let cand: Vec<u32> = vec![1, 2, 3, 4];
5764        let hproj = vec![1.0f32; 2 * R];
5765        // Anchor 0 (pred [1,0]): slot 0 scores = <[1,0],succ> -> tok1: 2, tok2: 0
5766        // -> picks 1. Slot 1 must then walk from pred[1]=[0,1]: tok3 scores 3,
5767        // tok4 scores 0 -> picks 3. A mutation that seeds every slot from the ANCHOR
5768        // (pred[0]=[1,0]) scores tok3: 0 / tok4: 10 and picks 4 instead — the chain
5769        // IS the semantics (reference CandidateSelector.select: `predecessor` is the
5770        // previously CHOSEN candidate, seeded by anchor_ids).
5771        let path = dflash2_walk_greedy(&pred, &succ, V, R, K, &[0.0; 4], &cand, &hproj, 0, 2);
5772        assert_eq!(
5773            path,
5774            vec![1, 3],
5775            "walk must seed slot p from slot p-1's CHOSEN candidate \
5776             (z-lab model.py CandidateSelector.select)"
5777        );
5778    }
5779
5780    #[test]
5781    fn selector_walk_unary_term_participates() {
5782        let (pred, succ) = books();
5783        let cand: Vec<u32> = vec![1, 2, 3, 4];
5784        let hproj = vec![1.0f32; 2 * R];
5785        // unary +10 on slot-0 candidate 2 overrides the bilinear 2-vs-0 margin;
5786        // the chain then walks from pred[2]=[1,0] and slot 1 flips to tok 4.
5787        let path = dflash2_walk_greedy(
5788            &pred,
5789            &succ,
5790            V,
5791            R,
5792            K,
5793            &[0.0, 10.0, 0.0, 0.0],
5794            &cand,
5795            &hproj,
5796            0,
5797            2,
5798        );
5799        assert_eq!(
5800            path,
5801            vec![2, 4],
5802            "score = unary + bilinear (reference: `unary[:, position] + einsum(...)`); \
5803             dropping the unary term picks tok 1 here"
5804        );
5805    }
5806
5807    #[test]
5808    fn selector_walk_hidden_gate_participates() {
5809        let (pred, succ) = books();
5810        let cand: Vec<u32> = vec![1, 2, 3, 4];
5811        // hproj [0, .] zeroes the pred[0]=[1,0] gate for slot 0: tok1's bilinear 2
5812        // vanishes, and the unary tiebreak (+1 on tok2) decides. The chain from tok2
5813        // (pred [1,0]) with slot-1 hproj [1,1] then picks tok4 (10 vs 0).
5814        let hproj = vec![0.0f32, 1.0, 1.0, 1.0];
5815        let path = dflash2_walk_greedy(
5816            &pred,
5817            &succ,
5818            V,
5819            R,
5820            K,
5821            &[0.0, 1.0, 0.0, 0.0],
5822            &cand,
5823            &hproj,
5824            0,
5825            2,
5826        );
5827        assert_eq!(
5828            path,
5829            vec![2, 4],
5830            "the bilinear gate is pred_row .* HIDDEN_PROJECTION (reference: \
5831             `predecessor_codebook(predecessor) * hidden[:, position]`); ignoring \
5832             hproj leaves tok1's margin standing"
5833        );
5834    }
5835
5836    #[test]
5837    fn dflash2_harvest_is_census_keyed() {
5838        // DFlash2 is mask-fill BY CONSTRUCTION (reference dflash_generate harvests
5839        // rows 1-verify_size:; card: "7 draft tokens per verification step").
5840        assert_eq!(
5841            DsparkHarvest::for_family_value(true, None, false),
5842            DsparkHarvest::Dflash
5843        );
5844        assert_eq!(
5845            DsparkHarvest::for_family_value(true, Some("dflash"), false),
5846            DsparkHarvest::Dflash
5847        );
5848        // The family key BEATS the strategy census: a (hypothetical) DFlash2 export
5849        // whose config also strategy-censuses dspark still harvests mask-fill.
5850        assert_eq!(
5851            DsparkHarvest::for_family_value(true, None, true),
5852            DsparkHarvest::Dflash
5853        );
5854        // An env override to the SHIFTED harvest contradicts the census — REFUSE,
5855        // never re-key (the postmortem's misalignment class in reverse).
5856        assert!(
5857            std::panic::catch_unwind(|| DsparkHarvest::for_family_value(
5858                true,
5859                Some("dspark"),
5860                false
5861            ))
5862            .is_err(),
5863            "MEMRA_DSPARK_HARVEST=dspark on a DFlash2 checkpoint must refuse"
5864        );
5865        // Non-DFlash2 checkpoints ride the strategy-keyed resolution (env wins).
5866        assert_eq!(
5867            DsparkHarvest::for_family_value(false, Some("dspark"), false),
5868            DsparkHarvest::Dspark
5869        );
5870        assert_eq!(
5871            DsparkHarvest::for_family_value(false, None, false),
5872            DsparkHarvest::Dflash
5873        );
5874        assert_eq!(
5875            DsparkHarvest::for_family_value(false, None, true),
5876            DsparkHarvest::Dspark,
5877            "unset env on a DSPARK-strategy export must keep the ratified census flip"
5878        );
5879    }
5880
5881    // ============ SAMPLED ADMISSION (T>0) gates — lane/dspark-sampled-admission-20260820 =
5882    // The device kernels are oracled by sample_check (filter_stats/gumbel/residual arms);
5883    // these pin the HOST math the route ships — the selector's sampled walk, the accept
5884    // rule, and the round COMPOSITION (accept + residual + bonus must reproduce the target
5885    // distribution p exactly; a mis-composition leaves every kernel individually correct,
5886    // which is why the composition arm exists — sample_check arm 6's lesson).
5887
5888    #[test]
5889    fn sampled_walk_tiny_temp_matches_greedy() {
5890        // T->0 continuity: at tiny temperature the candidate softmax concentrates on the
5891        // argmax and the sampled walk must reproduce the greedy chain token-for-token
5892        // (the frspec gate-(1) shape). Same fixture as the chain test.
5893        let (pred, succ) = books();
5894        let cand: Vec<u32> = vec![1, 2, 3, 4];
5895        let hproj = vec![1.0f32; 2 * R];
5896        let greedy = dflash2_walk_greedy(&pred, &succ, V, R, K, &[0.0; 4], &cand, &hproj, 0, 2);
5897        let mut u = || 0.5f32;
5898        let (path, q_chosen, q_rows) = dflash2_walk_sampled(
5899            &pred, &succ, V, R, K, &[0.0; 4], &cand, &hproj, 0, 2, 1e-6, &mut u,
5900        );
5901        assert_eq!(
5902            path, greedy,
5903            "tiny-T sampled walk must equal the greedy chain"
5904        );
5905        assert_eq!(q_rows.len(), 2 * K);
5906        for (p, &q) in path.iter().zip(&q_chosen) {
5907            let _ = p;
5908            assert!(
5909                q > 0.999,
5910                "tiny-T chosen-candidate prob must be ~1, got {q}"
5911            );
5912        }
5913    }
5914
5915    #[test]
5916    fn sampled_walk_records_the_distribution_it_samples() {
5917        // The recorded q IS the proposal: per slot the q_rows sum to ~1, q_chosen is the
5918        // row value at the drawn candidate, and the CDF walk picks the candidate whose
5919        // cumulative bracket contains the uniform.
5920        let (pred, succ) = books();
5921        let cand: Vec<u32> = vec![1, 2, 3, 4];
5922        let hproj = vec![1.0f32; 2 * R];
5923        // slot-0 scores at anchor 0: tok1 = 2.0, tok2 = 0.0; at T=2.0 the softmax is
5924        // e^1/(e^1+e^0) ~= 0.731 for tok1.
5925        let q1 = (1f64.exp() / (1f64.exp() + 1.0)) as f32;
5926        for (u0, want0) in [(q1 - 0.01, 1u32), (q1 + 0.01, 2u32)] {
5927            let mut seq = vec![u0, 0.0f32].into_iter();
5928            let mut u = move || seq.next().unwrap();
5929            let (path, q_chosen, q_rows) = dflash2_walk_sampled(
5930                &pred, &succ, V, R, K, &[0.0; 4], &cand, &hproj, 0, 2, 2.0, &mut u,
5931            );
5932            assert_eq!(
5933                path[0], want0,
5934                "CDF walk must place u={u0} in the right candidate bracket"
5935            );
5936            let row0: f32 = q_rows[..K].iter().sum();
5937            assert!(
5938                (row0 - 1.0).abs() < 1e-5,
5939                "slot-0 q must sum to 1, got {row0}"
5940            );
5941            let ci = cand[..K].iter().position(|&c| c == path[0]).unwrap();
5942            assert_eq!(
5943                q_chosen[0], q_rows[ci],
5944                "q_chosen must be the recorded row prob of the drawn candidate"
5945            );
5946            assert!(
5947                (q_rows[0] - q1).abs() < 1e-4,
5948                "slot-0 tok1 prob must be softmax(scores/T), got {} want {q1}",
5949                q_rows[0]
5950            );
5951        }
5952    }
5953
5954    #[test]
5955    fn sampled_walk_chains_the_drawn_candidate() {
5956        // The chain conditions on the DRAWN candidate, not the argmax: forcing the
5957        // low-prob slot-0 candidate (tok 2) flips slot 1's winner (tok 4 over tok 3),
5958        // exactly like the greedy chain test — a walk that seeds every slot from the
5959        // anchor (or the argmax) fails here.
5960        let (pred, succ) = books();
5961        let cand: Vec<u32> = vec![1, 2, 3, 4];
5962        let hproj = vec![1.0f32; 2 * R];
5963        let mut seq = vec![0.99f32, 0.01].into_iter();
5964        let mut u = move || seq.next().unwrap();
5965        let (path, _, _) = dflash2_walk_sampled(
5966            &pred, &succ, V, R, K, &[0.0; 4], &cand, &hproj, 0, 2, 2.0, &mut u,
5967        );
5968        assert_eq!(path[0], 2, "u=0.99 must draw the low-prob candidate");
5969        assert_eq!(
5970            path[1], 4,
5971            "slot 1 must walk from pred[2] (the DRAWN token), which scores tok4 at 10 \
5972             — chaining from the anchor or the argmax picks tok3"
5973        );
5974    }
5975
5976    #[test]
5977    fn rejection_accept_walk_is_the_leviathan_rule() {
5978        // accept while u*q < p, strict, prefix-stop at the first reject.
5979        assert_eq!(
5980            rejection_accept_len(&[0.5, 0.5], &[0.5, 0.5], &[0.9, 0.9]),
5981            2
5982        );
5983        assert_eq!(
5984            rejection_accept_len(&[0.5, 0.5], &[0.5, 0.5], &[1.0, 0.0]),
5985            0
5986        );
5987        // u*q == p is a REJECT (strict <) — the frspec test byte-for-byte.
5988        assert_eq!(rejection_accept_len(&[0.25], &[0.5], &[0.5]), 0);
5989        // q == 0 with p > 0 accepts unconditionally (the skey exactness signature).
5990        assert_eq!(rejection_accept_len(&[1e-6], &[0.0], &[0.999]), 1);
5991        // prefix stop: slot 1 rejects, slot 2 never tested.
5992        assert_eq!(
5993            rejection_accept_len(&[0.9, 0.0, 0.9], &[0.1, 0.9, 0.1], &[0.5, 0.5, 0.5]),
5994            1
5995        );
5996    }
5997
5998    // ---- round composition: the committed-token distribution must equal the target p ----
5999    // CPU mirror of the shipped rule for the FIRST post-anchor slot: draft x ~ q, accept
6000    // iff u*q(x) < p(x) (rejection_accept_len — the shipped fn), else commit a residual
6001    // sample ~ norm(max(0, p - q)). The marginal of the committed token is exactly p —
6002    // for ANY q — which is the whole correctness claim of the route's sampled admission.
6003
6004    fn tv(a: &[f64], b: &[f64]) -> f64 {
6005        a.iter().zip(b).map(|(x, y)| (x - y).abs()).sum::<f64>() / 2.0
6006    }
6007
6008    /// One composed trial with an injectable accept rule; returns the committed token.
6009    #[allow(clippy::neg_cmp_op_on_partial_ord)] // allow: NaN must take this branch; !(a > b) is not a <= b under IEEE comparisons
6010    fn compose_once(
6011        p: &[f32],
6012        q: &[f32],
6013        u_draw: f32,
6014        u_accept: f32,
6015        u_resid: f32,
6016        invert_accept: bool,
6017        skip_q_in_residual: bool,
6018    ) -> usize {
6019        let n = p.len();
6020        // draft ~ q (CDF walk, the walk_sampled convention)
6021        let mut acc = 0f64;
6022        let mut x = n - 1;
6023        for (i, &qi) in q.iter().enumerate() {
6024            acc += qi as f64;
6025            if (u_draw as f64) < acc {
6026                x = i;
6027                break;
6028            }
6029        }
6030        let accepted = if invert_accept {
6031            !((u_accept as f64) * (q[x] as f64) < p[x] as f64)
6032        } else {
6033            rejection_accept_len(&p[x..=x], &q[x..=x], &[u_accept]) == 1
6034        };
6035        if accepted {
6036            return x;
6037        }
6038        // residual ~ norm(max(0, p - q)) (the device kernel's fixed-order CDF walk)
6039        let r: Vec<f64> = p
6040            .iter()
6041            .zip(q)
6042            .map(|(&pi, &qi)| {
6043                let qq = if skip_q_in_residual { 0.0 } else { qi as f64 };
6044                (pi as f64 - qq).max(0.0)
6045            })
6046            .collect();
6047        let total: f64 = r.iter().sum();
6048        let mut acc = 0f64;
6049        let target = u_resid as f64 * total;
6050        for (i, &ri) in r.iter().enumerate() {
6051            acc += ri;
6052            if acc >= target && ri > 0.0 {
6053                return i;
6054            }
6055        }
6056        n - 1
6057    }
6058
6059    fn compose_tv(q: &[f32], invert_accept: bool, skip_q_in_residual: bool) -> f64 {
6060        // target p: a spread-out 8-token distribution
6061        let p: Vec<f32> = vec![0.30, 0.22, 0.15, 0.12, 0.09, 0.06, 0.04, 0.02];
6062        let trials = 200_000usize;
6063        let mut counts = [0f64; V];
6064        for t in 0..trials {
6065            // three independent uniforms per trial off the host Philox stream
6066            let u_draw = crate::spec::host_u01(7, (t * 3) as u32);
6067            let u_accept = crate::spec::host_u01(7, (t * 3 + 1) as u32);
6068            let u_resid = crate::spec::host_u01(7, (t * 3 + 2) as u32);
6069            counts[compose_once(
6070                &p,
6071                q,
6072                u_draw,
6073                u_accept,
6074                u_resid,
6075                invert_accept,
6076                skip_q_in_residual,
6077            )] += 1.0;
6078        }
6079        let emp: Vec<f64> = counts.iter().map(|c| c / trials as f64).collect();
6080        let pf: Vec<f64> = p.iter().map(|&v| v as f64).collect();
6081        tv(&emp, &pf)
6082    }
6083
6084    #[test]
6085    fn sampled_round_composition_matches_the_target() {
6086        // Monte-Carlo floor at 200k draws over 8 tokens ~ 0.004 TV; bound 0.01.
6087        // (a) full-vocab q (the Rows families' shape), far from p;
6088        let q_rows: Vec<f32> = vec![0.02, 0.04, 0.06, 0.09, 0.12, 0.15, 0.22, 0.30];
6089        // (b) SPARSE candidate-set q (the DFlash2 selector shape: support on 2 of 8).
6090        let q_sparse: Vec<f32> = vec![0.0, 0.7, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0];
6091        for (name, q) in [("rows", &q_rows), ("sparse", &q_sparse)] {
6092            let d = compose_tv(q, false, false);
6093            assert!(
6094                d < 0.01,
6095                "composition[{name}]: committed-token distribution must equal p \
6096                 (TV {d:.4} >= 0.01)"
6097            );
6098        }
6099    }
6100
6101    #[test]
6102    fn composition_teeth_inverted_accept_fails() {
6103        // DECISIVE teeth: the same harness with the accept inequality inverted must
6104        // MISS the target — otherwise the composition gate is vacuous.
6105        let q: Vec<f32> = vec![0.02, 0.04, 0.06, 0.09, 0.12, 0.15, 0.22, 0.30];
6106        let d = compose_tv(&q, true, false);
6107        assert!(
6108            d > 0.05,
6109            "inverted accept rule must fail the composition bound (TV {d:.4})"
6110        );
6111    }
6112
6113    #[test]
6114    fn composition_teeth_residual_without_q_fails() {
6115        // Sampling the reject slot from p instead of norm(max(0, p-q)) double-counts
6116        // the overlap mass min(p,q) — the committed distribution leaves p.
6117        let q: Vec<f32> = vec![0.0, 0.7, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0];
6118        let d = compose_tv(&q, false, true);
6119        assert!(
6120            d > 0.05,
6121            "residual that skips the q subtraction must fail the bound (TV {d:.4})"
6122        );
6123    }
6124
6125    // ---- PENALIZED round composition (lane/dspark-penalized-sampled-20260821) ----
6126    // Multi-slot rounds where the penalty state EVOLVES within the round. The base trunk
6127    // logits are state-independent, so ALL context dependence flows through penalties —
6128    // the sharpest fixture for "verify row j's target is penalized by the tokens accepted
6129    // before j in the same round", and the proposal concentrates on ONE token, so the
6130    // dominant drafted block is a self-hit (a drafted token penalizing its own successor
6131    // — the within-round case a frozen round-start window cannot see). The reference is
6132    // EXACT (analytic chain p1(a)·p2(b|a), the plain sampler's semantics); the spec arm
6133    // is the shipped round rule — chain draw from q, `rejection_accept_len`, residual
6134    // norm(max(0, p−q)) at the reject slot, bonus from the one-past row on full accept —
6135    // with per-slot penalized p (mirroring penalize_logits_rows_inc_f32's window rule).
6136
6137    const PV: usize = 6;
6138    const PEN_REP: f32 = 1.6;
6139    const PEN_FREQ: f32 = 0.8;
6140    const PEN_PRESENT: f32 = 1.2;
6141
6142    fn pen_base() -> Vec<f32> {
6143        vec![1.5, 0.8, 0.3, -0.2, -0.7, -1.2]
6144    }
6145
6146    /// The proposal: heavy on token 0 so drafted blocks repeat it (the self-hit case).
6147    fn pen_q() -> Vec<f32> {
6148        vec![0.85, 0.06, 0.04, 0.03, 0.01, 0.01]
6149    }
6150
6151    /// CPU mirror of penalize_logits_f32 / the plain sampler's apply_penalties: first
6152    /// occurrence does the whole adjustment, cnt = occurrences in the window, rep
6153    /// divides positive logits and multiplies negative ones.
6154    fn pen_apply(logits: &mut [f32], window: &[u32]) {
6155        let mut seen: Vec<u32> = Vec::new();
6156        for &id in window {
6157            if seen.contains(&id) {
6158                continue;
6159            }
6160            seen.push(id);
6161            let cnt = window.iter().filter(|&&h| h == id).count() as f32;
6162            let v = &mut logits[id as usize];
6163            if *v > 0.0 {
6164                *v /= PEN_REP;
6165            } else {
6166                *v *= PEN_REP;
6167            }
6168            *v -= PEN_FREQ * cnt + PEN_PRESENT;
6169        }
6170    }
6171
6172    /// Penalized target at history `window` (temp 1.0, no truncation filters — those are
6173    /// orthogonal and covered by the unpenalized composition tests + kernel oracles).
6174    fn pen_target(window: &[u32]) -> Vec<f64> {
6175        let mut l = pen_base();
6176        pen_apply(&mut l, window);
6177        let mx = l.iter().cloned().fold(f32::NEG_INFINITY, f32::max) as f64;
6178        let ex: Vec<f64> = l.iter().map(|&v| ((v as f64) - mx).exp()).collect();
6179        let z: f64 = ex.iter().sum();
6180        ex.iter().map(|v| v / z).collect()
6181    }
6182
6183    /// Which penalty-arm mutation the harness runs — `None` is the shipped rule.
6184    #[derive(Clone, Copy, PartialEq)]
6185    enum PenMutation {
6186        None,
6187        /// All rows (walk + bonus) penalized with the ROUND-START window only — the
6188        /// within-round update dropped (the frspec per-round posture; what a flat
6189        /// `penalize_logits_rows` launch would ship).
6190        FrozenWindow,
6191        /// Reject-slot residual computed from the UNPENALIZED p (a raw-tlogits column
6192        /// copy instead of the penalized buffer).
6193        UnpenalizedResidual,
6194        /// Full-accept bonus drawn from the UNPENALIZED one-past row.
6195        UnpenalizedBonus,
6196    }
6197
6198    /// Emit `want` committed tokens through spec rounds of `k` drafts (the shipped round
6199    /// rule, penalty-aware) and return them. `hist0` = the pre-stream window (the prompt
6200    /// seed); uniforms come off the injected stream.
6201    fn pen_round_stream(
6202        hist0: &[u32],
6203        k: usize,
6204        want: usize,
6205        mutation: PenMutation,
6206        next_u: &mut dyn FnMut() -> f32,
6207    ) -> Vec<u32> {
6208        let q = pen_q();
6209        let mut hist: Vec<u32> = hist0.to_vec();
6210        let mut committed: Vec<u32> = Vec::new();
6211        while committed.len() < want {
6212            // draft k tokens ~ q (fixed-order CDF walk, the walk_sampled convention)
6213            let drafted: Vec<u32> = (0..k)
6214                .map(|_| {
6215                    let u = next_u() as f64;
6216                    let mut acc = 0f64;
6217                    let mut bi = 0usize;
6218                    for (i, &qi) in q.iter().enumerate() {
6219                        acc += qi as f64;
6220                        if u < acc {
6221                            bi = i;
6222                            break;
6223                        }
6224                    }
6225                    bi as u32
6226                })
6227                .collect();
6228            // per-slot penalized p at the drafted ids (row j's window = hist ++ drafted[..j])
6229            let pj: Vec<f32> = (0..k)
6230                .map(|j| {
6231                    let win: Vec<u32> = if mutation == PenMutation::FrozenWindow {
6232                        hist.clone()
6233                    } else {
6234                        hist.iter()
6235                            .copied()
6236                            .chain(drafted[..j].iter().copied())
6237                            .collect()
6238                    };
6239                    pen_target(&win)[drafted[j] as usize] as f32
6240                })
6241                .collect();
6242            let qj: Vec<f32> = drafted.iter().map(|&d| q[d as usize]).collect();
6243            let us: Vec<f32> = (0..k).map(|_| next_u()).collect();
6244            let m = rejection_accept_len(&pj, &qj, &us);
6245            committed.extend_from_slice(&drafted[..m]);
6246            hist.extend_from_slice(&drafted[..m]);
6247            let next: u32 = if m == k {
6248                // bonus ~ p at the one-past row (window carries the WHOLE drafted block)
6249                let win: Vec<u32> = if matches!(
6250                    mutation,
6251                    PenMutation::FrozenWindow | PenMutation::UnpenalizedBonus
6252                ) {
6253                    if mutation == PenMutation::UnpenalizedBonus {
6254                        Vec::new() // raw row: no penalties at all
6255                    } else {
6256                        hist[..hist.len() - m].to_vec() // round-start window
6257                    }
6258                } else {
6259                    hist.clone()
6260                };
6261                let p = pen_target(&win);
6262                let u = next_u() as f64;
6263                let mut acc = 0f64;
6264                let mut bi = PV - 1;
6265                for (i, &pi) in p.iter().enumerate() {
6266                    acc += pi;
6267                    if u < acc {
6268                        bi = i;
6269                        break;
6270                    }
6271                }
6272                bi as u32
6273            } else {
6274                // residual ~ norm(max(0, p_m − q)) at the reject slot's state
6275                let win: Vec<u32> = match mutation {
6276                    PenMutation::UnpenalizedResidual => Vec::new(),
6277                    PenMutation::FrozenWindow => hist[..hist.len() - m].to_vec(),
6278                    _ => hist.clone(),
6279                };
6280                let p = pen_target(&win);
6281                let r: Vec<f64> = p
6282                    .iter()
6283                    .zip(&q)
6284                    .map(|(&pi, &qi)| (pi - qi as f64).max(0.0))
6285                    .collect();
6286                let total: f64 = r.iter().sum();
6287                let target = next_u() as f64 * total;
6288                let mut acc = 0f64;
6289                let mut bi = PV - 1;
6290                for (i, &ri) in r.iter().enumerate() {
6291                    acc += ri;
6292                    if acc >= target && ri > 0.0 {
6293                        bi = i;
6294                        break;
6295                    }
6296                }
6297                bi as u32
6298            };
6299            committed.push(next);
6300            hist.push(next);
6301        }
6302        committed.truncate(want);
6303        committed
6304    }
6305
6306    /// Joint TV of the spec arm's first two committed tokens vs the EXACT penalized
6307    /// chain p1(a)·p2(b|a) — the plain sampler's distribution over the same two steps.
6308    fn pen_compose_tv(hist0: &[u32], k: usize, mutation: PenMutation) -> f64 {
6309        let trials = 300_000usize;
6310        let mut counts = vec![0f64; PV * PV];
6311        for t in 0..trials {
6312            // stride 64: a k<=2 round consumes <=2k+1 uniforms, <=2 rounds per trial
6313            let mut ctr = (t as u32) * 64;
6314            let mut next_u = move || {
6315                let u = crate::spec::host_u01(11, ctr);
6316                ctr = ctr.wrapping_add(1);
6317                u
6318            };
6319            let s = pen_round_stream(hist0, k, 2, mutation, &mut next_u);
6320            counts[s[0] as usize * PV + s[1] as usize] += 1.0;
6321        }
6322        let p1 = pen_target(hist0);
6323        let mut tv = 0f64;
6324        for a in 0..PV {
6325            let mut w: Vec<u32> = hist0.to_vec();
6326            w.push(a as u32);
6327            let p2 = pen_target(&w);
6328            for b in 0..PV {
6329                let refp = p1[a] * p2[b];
6330                tv += (counts[a * PV + b] / trials as f64 - refp).abs();
6331            }
6332        }
6333        tv / 2.0
6334    }
6335
6336    #[test]
6337    fn penalized_round_composition_matches_the_penalized_chain() {
6338        // MC floor at 300k trials over 36 cells ~ 0.004 TV; bound 0.01. Fixture (a):
6339        // k=2, empty prompt window — the drafted pair (0,0) dominates, so slot 2's
6340        // accept is the SELF-HIT case (its own predecessor was drafted this round).
6341        // Fixture (b): k=1, prompt window [1,1] — the bonus is the successor of a
6342        // same-round accepted draft, and cnt>1 exercises the freq×count path.
6343        for (name, hist0, k) in [
6344            ("k2-selfhit", vec![], 2usize),
6345            ("k1-bonus-successor", vec![1u32, 1u32], 1usize),
6346        ] {
6347            let d = pen_compose_tv(&hist0, k, PenMutation::None);
6348            eprintln!("penalized composition[{name}]: TV {d:.4} (bound 0.01)");
6349            assert!(
6350                d < 0.01,
6351                "penalized composition[{name}]: committed-token distribution must equal \
6352                 the penalized chain (TV {d:.4} >= 0.01)"
6353            );
6354        }
6355    }
6356
6357    #[test]
6358    fn penalized_composition_teeth_frozen_window_fails() {
6359        // DECISIVE teeth: penalizing every verify row with the ROUND-START window —
6360        // dropping the within-round penalty update, i.e. a flat penalize_logits_rows
6361        // launch where the route ships penalize_logits_rows_inc — must MISS the
6362        // penalized chain, or the composition gate cannot see the one thing this lane
6363        // adds over the frozen-window prior art.
6364        let d = pen_compose_tv(&[], 2, PenMutation::FrozenWindow);
6365        eprintln!("penalized teeth[frozen-window]: TV {d:.4} (must exceed 0.05)");
6366        assert!(
6367            d > 0.05,
6368            "within-round penalty update dropped (frozen round-start window) must FAIL \
6369             the composition bound (TV {d:.4})"
6370        );
6371    }
6372
6373    #[test]
6374    fn penalized_composition_teeth_unpenalized_residual_fails() {
6375        // The reject-slot residual must read the PENALIZED column: a raw-tlogits column
6376        // copy (p_raw − q) commits from the wrong measure. Non-empty prompt window so
6377        // even round-start reject slots hit the mutation (an empty-window fixture only
6378        // sees it on within-round rejects and the margin thins to ~0.055).
6379        let d = pen_compose_tv(&[1, 1], 2, PenMutation::UnpenalizedResidual);
6380        eprintln!("penalized teeth[unpenalized-residual]: TV {d:.4} (must exceed 0.05)");
6381        assert!(
6382            d > 0.05,
6383            "residual computed from the unpenalized p must FAIL the composition bound \
6384             (TV {d:.4})"
6385        );
6386    }
6387
6388    #[test]
6389    fn penalized_composition_teeth_unpenalized_bonus_fails() {
6390        // The full-accept bonus row must carry the whole drafted block in its window:
6391        // a raw one-past row draw commits the unpenalized measure right after a
6392        // same-round accept.
6393        let d = pen_compose_tv(&[1, 1], 1, PenMutation::UnpenalizedBonus);
6394        eprintln!("penalized teeth[unpenalized-bonus]: TV {d:.4} (must exceed 0.05)");
6395        assert!(
6396            d > 0.05,
6397            "bonus drawn from the unpenalized one-past row must FAIL the composition \
6398             bound (TV {d:.4})"
6399        );
6400    }
6401}
6402
6403#[cfg(test)]
6404mod dspark_harvest_tests {
6405    use super::{DsparkHarvest, DsparkVtPolicy, dspark_accept_prefix, dspark_strategy_census};
6406
6407    const B: usize = 7; // q38 arm-a block_size
6408
6409    #[test]
6410    fn dspark_strategy_requires_shifted_harvest() {
6411        let h = DsparkHarvest::Dspark;
6412        assert_eq!(
6413            h.first_row(),
6414            0,
6415            "DSPARK-strategy checkpoints (SpecForge OnlineDSparkModel, \
6416             training.strategy=dspark — the q38 arm-a export) supervise ALL rows with \
6417             SHIFTED labels: label_offsets = arange(1, block_size+1), i.e. the ANCHOR \
6418             row's output is draft 1 (specforge/algorithms/common/\
6419             dflash_family_model.py:816; sglang v0.5.17 dspark_draft.py:248,260). \
6420             Harvesting from row 1 re-opens the DSPARK-POSTMORTEM-20260820 slot \
6421             misalignment (accept 2.9 -> 1.43)."
6422        );
6423        assert_eq!(
6424            h.n_drafts(B),
6425            B,
6426            "DSpark harvests gamma = block_size drafts per round (sglang \
6427             dspark_config.py:269, verify_num_draft_tokens = gamma+1); b-1 is the \
6428             DFlash mask-fill count and drops the best-trained slot \
6429             (DSPARK-POSTMORTEM-20260820.md §3-H1)."
6430        );
6431        for row in 0..B {
6432            assert_eq!(
6433                h.trained_offset_of_row(row),
6434                row + 1,
6435                "OnlineDSparkModel trains row k to predict anchor+k+1 \
6436                 (dflash_family_model.py:816); a same-position (mask-fill) mapping \
6437                 here verifies every slot one position early — the postmortem's \
6438                 collapse."
6439            );
6440        }
6441    }
6442
6443    #[test]
6444    fn dflash_strategy_keeps_mask_fill_harvest() {
6445        // Guards the reverse mutation: z-lab dflash checkpoints (the gemma arm) are
6446        // mask-fill — row k FILLS anchor+k, the anchor row is loss-excluded
6447        // (dflash_family_model.py:453-472). Shifting THEM would break the gemma arm.
6448        let h = DsparkHarvest::Dflash;
6449        assert_eq!(h.first_row(), 1, "DFlash drafts start at mask row 1");
6450        assert_eq!(h.n_drafts(B), B - 1, "DFlash harvests block_size-1 drafts");
6451        for row in 1..B {
6452            assert_eq!(h.trained_offset_of_row(row), row);
6453        }
6454    }
6455
6456    #[test]
6457    fn every_candidate_verifies_the_position_its_row_was_trained_for() {
6458        // The round's invariant: draft candidate i (1-based; verified against the
6459        // trunk's prediction for anchor+i) is filled from drafter output row
6460        // first_row + i - 1. Alignment == that row was TRAINED for offset i.
6461        for h in [DsparkHarvest::Dflash, DsparkHarvest::Dspark] {
6462            for i in 1..=h.n_drafts(B) {
6463                let row = h.first_row() + i - 1;
6464                assert_eq!(
6465                    h.trained_offset_of_row(row),
6466                    i,
6467                    "{h:?}: candidate {i} rides row {row}, which is trained for \
6468                     offset {} — harvest misaligned",
6469                    h.trained_offset_of_row(row)
6470                );
6471            }
6472        }
6473    }
6474
6475    #[test]
6476    fn env_seam_parses_and_refuses() {
6477        assert_eq!(
6478            DsparkHarvest::from_env_value(None),
6479            DsparkHarvest::Dflash,
6480            "the ENV-ONLY parser keeps the historical arm; the ratified strategy-keyed \
6481             default lives in resolve_value (checkpoint census), not here"
6482        );
6483        assert_eq!(
6484            DsparkHarvest::from_env_value(Some("dspark")),
6485            DsparkHarvest::Dspark
6486        );
6487        assert_eq!(
6488            DsparkHarvest::from_env_value(Some("dflash")),
6489            DsparkHarvest::Dflash
6490        );
6491        assert!(
6492            std::panic::catch_unwind(|| DsparkHarvest::from_env_value(Some("shifted"))).is_err(),
6493            "unknown harvest values must REFUSE, not default"
6494        );
6495        assert_eq!(
6496            DsparkHarvest::from_name("dspark"),
6497            Some(DsparkHarvest::Dspark)
6498        );
6499        assert_eq!(
6500            DsparkHarvest::from_name("dflash"),
6501            Some(DsparkHarvest::Dflash)
6502        );
6503        assert_eq!(DsparkHarvest::from_name("mask-fill"), None);
6504    }
6505
6506    /// The owner-ratified default flips (2026-08-20). Each assertion names its
6507    /// evidence; mutating either resolve back to the old default fails these.
6508    #[test]
6509    fn ratified_default_harvest_is_strategy_keyed() {
6510        // DSPARK-strategy checkpoint + unset env = the shifted harvest (B1: accept
6511        // 1.38->2.41 agentic / 1.53->3.66 math, E2E ALL EXACT x5, interleaved x5).
6512        assert_eq!(
6513            DsparkHarvest::resolve_value(None, true),
6514            DsparkHarvest::Dspark,
6515            "owner-ratified 2026-08-20: unset env defaults a DSPARK-strategy \
6516             checkpoint to the shifted harvest (DSPARK-POSTMORTEM-20260820.md B1)"
6517        );
6518        // mask-fill checkpoint + unset env = the historical arm, byte-identical.
6519        assert_eq!(
6520            DsparkHarvest::resolve_value(None, false),
6521            DsparkHarvest::Dflash
6522        );
6523        assert_eq!(
6524            DsparkHarvest::resolve_value(Some(""), false),
6525            DsparkHarvest::Dflash
6526        );
6527        // Explicit env overrides the census in BOTH directions (the A/B seam).
6528        assert_eq!(
6529            DsparkHarvest::resolve_value(Some("dflash"), true),
6530            DsparkHarvest::Dflash
6531        );
6532        assert_eq!(
6533            DsparkHarvest::resolve_value(Some("dspark"), false),
6534            DsparkHarvest::Dspark
6535        );
6536        // Unknown values still REFUSE through the resolve path.
6537        assert!(
6538            std::panic::catch_unwind(|| DsparkHarvest::resolve_value(Some("shifted"), true))
6539                .is_err()
6540        );
6541    }
6542
6543    #[test]
6544    fn strategy_census_reads_the_checkpoint_not_the_env() {
6545        // The q38 arm-a export shape: both signals present.
6546        let q38 = r#"{"architectures": ["Qwen3DSparkModel"], "block_size": 7,
6547            "dflash_config": {"projector_type": "dspark", "markov_rank": 256}}"#;
6548        assert!(dspark_strategy_census(q38));
6549        // Either signal alone suffices.
6550        assert!(dspark_strategy_census(
6551            r#"{"architectures": ["Qwen3DSparkModel"]}"#
6552        ));
6553        assert!(dspark_strategy_census(
6554            r#"{"dflash_config": {"projector_type": "dspark"}}"#
6555        ));
6556        // A mask-fill DFlash export carries neither -> historical default.
6557        let dflash = r#"{"architectures": ["Qwen3DFlashModel"],
6558            "dflash_config": {"attention_mode": "gqa"}}"#;
6559        assert!(!dspark_strategy_census(dflash));
6560        assert!(!dspark_strategy_census("{}"));
6561    }
6562
6563    #[test]
6564    fn ratified_default_vt_is_confidence_slot_tau_half() {
6565        // Head-carrying checkpoint + unset env = confidence-slot tau=.5 (H4 cell 3:
6566        // the tau ladder's knee; cell 2: 93.9%/97.7% of fixed-8 accept at wall >=
6567        // the reactive ladder, exactness 11/11 ALL EXACT).
6568        assert_eq!(
6569            DsparkVtPolicy::resolve_value(None, None, None, true),
6570            DsparkVtPolicy::ConfidenceSlot { tau: 0.5 },
6571            "owner-ratified 2026-08-20: unset MEMRA_DSPARK_VT defaults to \
6572             confidence-slot tau=.5 on a head-carrying checkpoint (H4 cells 2-3)"
6573        );
6574        // tau env still steers the default arm (and a bad tau still refuses).
6575        assert_eq!(
6576            DsparkVtPolicy::resolve_value(None, Some("0.35"), None, true),
6577            DsparkVtPolicy::ConfidenceSlot { tau: 0.35 }
6578        );
6579        assert!(
6580            std::panic::catch_unwind(|| DsparkVtPolicy::resolve_value(
6581                None,
6582                Some("nan-ish"),
6583                None,
6584                true
6585            ))
6586            .is_err()
6587        );
6588        // Census: no accept-rate head -> nothing to schedule with -> ladder.
6589        assert_eq!(
6590            DsparkVtPolicy::resolve_value(None, None, None, false),
6591            DsparkVtPolicy::Ladder
6592        );
6593        // MEMRA_DFLASH_ADAPT=0 is an explicit fixed-window request: honored.
6594        assert_eq!(
6595            DsparkVtPolicy::resolve_value(None, None, Some("0"), true),
6596            DsparkVtPolicy::Ladder
6597        );
6598        // Explicit values keep their exact prior semantics through resolve.
6599        assert_eq!(
6600            DsparkVtPolicy::resolve_value(Some("ladder"), None, None, true),
6601            DsparkVtPolicy::Ladder
6602        );
6603        assert_eq!(
6604            DsparkVtPolicy::resolve_value(Some("confidence"), Some("0.35"), None, true),
6605            DsparkVtPolicy::Confidence { tau: 0.35 }
6606        );
6607        // Explicit confidence mode with ADAPT=0 stays a refusal.
6608        assert!(
6609            std::panic::catch_unwind(|| DsparkVtPolicy::resolve_value(
6610                Some("confidence-slot"),
6611                None,
6612                Some("0"),
6613                true
6614            ))
6615            .is_err()
6616        );
6617    }
6618
6619    /// End-to-end alignment fixture in miniature: a mock drafter whose row r argmaxes
6620    /// to token BASE + (its trained offset under the DSPARK strategy), and a mock trunk
6621    /// whose prediction for anchor+j is BASE + j. The DSpark harvest accepts the whole
6622    /// block; feeding the same drafter through the mask-fill harvest accepts ZERO —
6623    /// the postmortem's collapse reproduced as pure logic.
6624    #[test]
6625    fn dspark_trained_rows_through_mask_fill_harvest_accept_nothing() {
6626        const BASE: u32 = 1000;
6627        let anchor: u32 = BASE; // token at the round anchor position (offset 0)
6628        // trunk verify argmaxes: vam[j] = prediction for anchor offset j+1
6629        let vam: Vec<u32> = (1..=B as u32 + 1).map(|j| BASE + j).collect();
6630        // drafter rows trained under the DSPARK strategy: row r predicts offset r+1
6631        let dspark_trained_row_argmax =
6632            |r: usize| BASE + DsparkHarvest::Dspark.trained_offset_of_row(r) as u32;
6633
6634        // Correct (shifted) harvest: candidate i <- row i-1.
6635        let h = DsparkHarvest::Dspark;
6636        let mut cand = vec![anchor];
6637        for i in 1..=h.n_drafts(B) {
6638            cand.push(dspark_trained_row_argmax(h.first_row() + i - 1));
6639        }
6640        let vt = h.n_drafts(B) + 1;
6641        assert_eq!(
6642            dspark_accept_prefix(&cand, &vam, vt),
6643            vt - 1,
6644            "aligned harvest must accept the full block"
6645        );
6646
6647        // Mask-fill harvest of the SAME dspark-trained drafter: candidate i <- row i,
6648        // which was trained for offset i+1 — every slot one position late.
6649        let wrong = DsparkHarvest::Dflash;
6650        let mut cand_wrong = vec![anchor];
6651        for i in 1..=wrong.n_drafts(B) {
6652            cand_wrong.push(dspark_trained_row_argmax(wrong.first_row() + i - 1));
6653        }
6654        let vt_wrong = wrong.n_drafts(B) + 1;
6655        assert_eq!(
6656            dspark_accept_prefix(&cand_wrong, &vam, vt_wrong),
6657            0,
6658            "mask-fill harvest of a dspark-trained drafter verifies every slot against \
6659             a position the row was not trained for (DSPARK-POSTMORTEM-20260820.md)"
6660        );
6661    }
6662}
6663
6664// ================= Verify-window policy gate (CPU; H4, DSPARK-POSTMORTEM-20260820.md) ===
6665// Pins the confidence-vt semantics as logic the round consumes: cumprod survival over
6666// sigmoid scores, thresholded, anchor + kept drafts, floor 2 / cap vt_cap — and the env
6667// seam's refuse-on-ambiguity. Mutating the policy (per-slot threshold instead of
6668// survival, off-by-one on the anchor, silent unknown-value fallback) fails HERE.
6669#[cfg(test)]
6670mod dspark_vt_tests {
6671    use super::{ConfidenceHead, DsparkVtPolicy, dspark_confidence_vt, dspark_slot_confidence_vt};
6672
6673    /// Pre-sigmoid logit for a target probability: sigmoid(logit(p)) == p.
6674    fn logit(p: f32) -> f32 {
6675        (p / (1.0 - p)).ln()
6676    }
6677
6678    #[test]
6679    fn confidence_vt_is_cumprod_survival_not_per_slot_threshold() {
6680        // sigmoids = [0.9, 0.8, 0.9, ...]: every PER-SLOT score clears tau=0.5, but
6681        // cumulative survival sinks below it at slot 6 (0.9, 0.72, 0.648, 0.583,
6682        // 0.525, then 0.472 < 0.5) — the window must stop where the EXPECTED
6683        // accepted-prefix stops paying, not where a slot looks locally fine.
6684        let raws: Vec<f32> = [0.9, 0.8, 0.9, 0.9, 0.9, 0.9, 0.9]
6685            .iter()
6686            .map(|&p| logit(p))
6687            .collect();
6688        assert_eq!(
6689            dspark_confidence_vt(&raws, 0.5, 8),
6690            6,
6691            "keeps 5 drafts + anchor"
6692        );
6693        // Tighter threshold closes the window sooner; looser opens it to the cap.
6694        assert_eq!(
6695            dspark_confidence_vt(&raws, 0.7, 8),
6696            3,
6697            "tau=0.7 keeps 2 drafts"
6698        );
6699        assert_eq!(
6700            dspark_confidence_vt(&raws, 0.05, 8),
6701            8,
6702            "tau→0 = full block"
6703        );
6704    }
6705
6706    #[test]
6707    fn slot_arm_truncates_at_first_low_confidence_slot() {
6708        // Owner directive (2026-08-20): submit only the longest prefix whose EVERY
6709        // slot clears tau on its own sigmoid. On the survival test's raws
6710        // ([0.9, 0.8, 0.9 x5], tau=0.5) every slot clears per-slot, so the slot arm
6711        // opens the full block where survival stopped at 6 — the two stopping
6712        // statistics must stay distinct arms.
6713        let raws: Vec<f32> = [0.9, 0.8, 0.9, 0.9, 0.9, 0.9, 0.9]
6714            .iter()
6715            .map(|&p| logit(p))
6716            .collect();
6717        assert_eq!(dspark_slot_confidence_vt(&raws, 0.5, 8), 8);
6718        assert_eq!(dspark_confidence_vt(&raws, 0.5, 8), 6);
6719        // A low-confidence tail never enters verify: [0.9, 0.9, 0.3, 0.9, ...]
6720        // truncates at slot 3 REGARDLESS of the confident slots behind it — a kept
6721        // slot after a dropped one could never commit (prefix accept rule).
6722        let tail: Vec<f32> = [0.9, 0.9, 0.3, 0.9, 0.9, 0.9, 0.9]
6723            .iter()
6724            .map(|&p| logit(p))
6725            .collect();
6726        assert_eq!(
6727            dspark_slot_confidence_vt(&tail, 0.5, 8),
6728            3,
6729            "2 drafts + anchor"
6730        );
6731        // Tighter tau keeps less.
6732        assert_eq!(
6733            dspark_slot_confidence_vt(&tail, 0.95, 8),
6734            2,
6735            "floor at tau=0.95"
6736        );
6737    }
6738
6739    #[test]
6740    fn confidence_vt_floor_and_cap() {
6741        // A hopeless round still verifies ONE draft (the draft forward is paid;
6742        // vt=1 would guarantee an empty round at the same cost class).
6743        let cold: Vec<f32> = [0.1f32, 0.1, 0.1].iter().map(|&p| logit(p)).collect();
6744        assert_eq!(
6745            dspark_confidence_vt(&cold, 0.5, 8),
6746            2,
6747            "floor = anchor + 1 draft"
6748        );
6749        assert_eq!(
6750            dspark_slot_confidence_vt(&cold, 0.5, 8),
6751            2,
6752            "slot arm same floor"
6753        );
6754        // The MEMRA_DFLASH_VERIFY_T cap still binds a confident round.
6755        let hot: Vec<f32> = vec![logit(0.99); 7];
6756        assert_eq!(dspark_confidence_vt(&hot, 0.5, 5), 5, "vt_cap binds");
6757        assert_eq!(
6758            dspark_confidence_vt(&hot, 0.5, 8),
6759            8,
6760            "full block when confident"
6761        );
6762        assert_eq!(
6763            dspark_slot_confidence_vt(&hot, 0.5, 5),
6764            5,
6765            "slot arm same cap"
6766        );
6767        // No scores (defensive): floor.
6768        assert_eq!(dspark_confidence_vt(&[], 0.5, 8), 2);
6769        assert_eq!(dspark_slot_confidence_vt(&[], 0.5, 8), 2);
6770    }
6771
6772    #[test]
6773    fn vt_policy_env_seam_parses_and_refuses() {
6774        assert_eq!(
6775            DsparkVtPolicy::from_env_value(None, None, None),
6776            DsparkVtPolicy::Ladder,
6777            "default stays the shipped ladder — the H4 arm is opt-in"
6778        );
6779        assert_eq!(
6780            DsparkVtPolicy::from_env_value(Some(""), None, None),
6781            DsparkVtPolicy::Ladder
6782        );
6783        assert_eq!(
6784            DsparkVtPolicy::from_env_value(Some("ladder"), None, Some("0")),
6785            DsparkVtPolicy::Ladder,
6786            "ladder + ADAPT=0 = the fixed-window arm, untouched"
6787        );
6788        assert_eq!(
6789            DsparkVtPolicy::from_env_value(Some("confidence"), None, None),
6790            DsparkVtPolicy::Confidence { tau: 0.5 },
6791            "tau defaults to 0.5 (raw sigmoid, no STS sidecar — postmortem §3-H4)"
6792        );
6793        assert_eq!(
6794            DsparkVtPolicy::from_env_value(Some("confidence"), Some("0.35"), Some("1")),
6795            DsparkVtPolicy::Confidence { tau: 0.35 }
6796        );
6797        assert_eq!(
6798            DsparkVtPolicy::from_env_value(Some("confidence-slot"), Some("0.6"), None),
6799            DsparkVtPolicy::ConfidenceSlot { tau: 0.6 },
6800            "the owner-directive per-slot arm parses with the same tau env"
6801        );
6802        assert!(
6803            std::panic::catch_unwind(|| DsparkVtPolicy::from_env_value(
6804                Some("confidence-slot"),
6805                None,
6806                Some("0")
6807            ))
6808            .is_err(),
6809            "confidence-slot + MEMRA_DFLASH_ADAPT=0 must REFUSE like confidence"
6810        );
6811        assert!(
6812            std::panic::catch_unwind(|| DsparkVtPolicy::from_env_value(Some("static"), None, None))
6813                .is_err(),
6814            "unknown policy values must REFUSE, not default — a typo silently \
6815             reverting the window policy invalidates an A/B"
6816        );
6817        assert!(
6818            std::panic::catch_unwind(|| DsparkVtPolicy::from_env_value(
6819                Some("confidence"),
6820                None,
6821                Some("0")
6822            ))
6823            .is_err(),
6824            "confidence + MEMRA_DFLASH_ADAPT=0 is contradictory and must REFUSE"
6825        );
6826        for bad in ["0", "1", "1.5", "-0.1", "nan"] {
6827            assert!(
6828                std::panic::catch_unwind(|| DsparkVtPolicy::from_env_value(
6829                    Some("confidence"),
6830                    Some(bad),
6831                    None
6832                ))
6833                .is_err(),
6834                "tau={bad} must REFUSE (survival threshold lives in (0,1))"
6835            );
6836        }
6837    }
6838
6839    #[test]
6840    fn raw_score_matches_the_parity_gate_dot() {
6841        // The head is a raw linear proj over [hidden ; markov_prev_embedding] + b —
6842        // the exact stage-5 contract in dspark_q38_parity.rs.
6843        let ch = ConfidenceHead {
6844            w: vec![0.5, -1.0, 2.0, 0.25, -0.5],
6845            b: 0.125,
6846            in_dim: 5,
6847            with_markov: true,
6848        };
6849        let hidden = [1.0f32, 2.0, 3.0];
6850        let emb = [4.0f32, 8.0];
6851        let want = 0.125 + 0.5 * 1.0 - 1.0 * 2.0 + 2.0 * 3.0 + 0.25 * 4.0 - 0.5 * 8.0;
6852        assert_eq!(ch.raw_score(&hidden, Some(&emb)), want);
6853        let ch_plain = ConfidenceHead {
6854            w: vec![0.5, -1.0, 2.0],
6855            b: -0.25,
6856            in_dim: 3,
6857            with_markov: false,
6858        };
6859        let want_plain = -0.25 + 0.5 * 1.0 - 1.0 * 2.0 + 2.0 * 3.0;
6860        assert_eq!(ch_plain.raw_score(&hidden, None), want_plain);
6861    }
6862}
6863
6864#[cfg(test)]
6865mod dspark_prefix_capture_tests {
6866    use super::{dspark_spec_prompt_fits, take_dspark_prefix_capture};
6867
6868    /// INCIDENT REGRESSION (2026-08-25). This gate is the only admission check the dspark
6869    /// route has, and it checked the ctx ceiling ONLY — so a short prompt was admitted and
6870    /// then panicked in the cold prime (`prime_cache needs T >= 16`), inside the GPU worker
6871    /// thread, which exits 70 and kills every live session on the box. Two crash loops and
6872    /// ~5 minutes of customer 502s came from a 5-token "Say OK." — the class our own
6873    /// watchdog sends. The floor belongs HERE, in the gate, not in each caller.
6874    #[test]
6875    fn a_prompt_below_the_prime_floor_never_enters_the_dspark_route() {
6876        let floor = crate::hybrid_forward::PRIME_MIN_T;
6877        for short in [1usize, 5, floor - 1] {
6878            assert!(
6879                !dspark_spec_prompt_fits(short, 262_144, 8, 2_048, true),
6880                "a {short}-token prompt must decline to the plain path, not prime"
6881            );
6882        }
6883        // At and above the floor the route admits exactly as before (ceiling still applies).
6884        assert!(dspark_spec_prompt_fits(floor, 262_144, 8, 2_048, true));
6885        assert!(dspark_spec_prompt_fits(512, 262_144, 8, 2_048, true));
6886        assert!(!dspark_spec_prompt_fits(512, 300, 8, 2_048, true));
6887    }
6888
6889    #[test]
6890    fn session_prompt_preflight_matches_dflash2_and_windowed_caps() {
6891        // DFlash2 uses the request ctx cap: prompt + block + 8 fits exactly, one row less does not.
6892        assert!(dspark_spec_prompt_fits(96, 111, 7, 2_048, true));
6893        assert!(!dspark_spec_prompt_fits(96, 110, 7, 2_048, true));
6894
6895        // Legacy/windowed drafts are additionally bounded by their own sliding window.
6896        assert!(dspark_spec_prompt_fits(113, 8_192, 7, 128, false));
6897        assert!(!dspark_spec_prompt_fits(114, 8_192, 7, 128, false));
6898        assert!(!dspark_spec_prompt_fits(
6899            usize::MAX,
6900            usize::MAX,
6901            7,
6902            usize::MAX,
6903            true,
6904        ));
6905    }
6906
6907    #[test]
6908    fn prompt_end_capture_is_full_prompt_and_one_shot() {
6909        let prompt_len = 96;
6910        let mut slot = Some(crate::spec::SpecBoundaryCapture {
6911            snap: crate::cache::CacheSnapshot {
6912                kv_len: Vec::new(),
6913                tp_kv_len: Vec::new(),
6914                conv: Vec::new(),
6915                ssm: Vec::new(),
6916                pos: prompt_len,
6917            },
6918            pos: prompt_len,
6919            logits: vec![1.0, 2.0],
6920            last_h: Vec::new(),
6921            latent_tails: Vec::new(),
6922        });
6923
6924        let capture = take_dspark_prefix_capture(&mut slot).expect("first drain gets capture");
6925        assert_eq!(capture.pos, prompt_len, "capture is at full prompt end");
6926        assert_eq!(capture.snap.pos, prompt_len);
6927        assert!(
6928            capture.last_h.is_empty(),
6929            "DFlash publishes no hidden anchor"
6930        );
6931        assert!(
6932            take_dspark_prefix_capture(&mut slot).is_none(),
6933            "capture drains exactly once",
6934        );
6935    }
6936}
6937
6938#[cfg(test)]
6939mod dflash_precision_tests {
6940    use super::dflash_precision;
6941
6942    #[test]
6943    fn default_and_supported_precision_programs_are_explicit() {
6944        assert_eq!(dflash_precision(None), Ok("q4"));
6945        for prec in ["q4", "q8", "mixed", "bf16", "fc"] {
6946            assert_eq!(dflash_precision(Some(prec)), Ok(prec));
6947        }
6948    }
6949
6950    #[test]
6951    fn q5_and_typos_refuse_instead_of_silently_selecting_q8() {
6952        for prec in ["q5", "Q4", "", "typo"] {
6953            let err = dflash_precision(Some(prec)).unwrap_err();
6954            assert!(err.contains("want q4, q8, mixed, bf16, or fc"));
6955        }
6956    }
6957}
6958
6959#[cfg(test)]
6960mod dflash_tensor_contract_tests {
6961    use super::{
6962        validate_dflash_attention_geometry, validate_dflash_tensor, validate_layer_layout,
6963        validate_selector_top_k,
6964    };
6965    use memra_gguf::safetensors::StInfo;
6966
6967    #[test]
6968    fn named_tensor_contract_refuses_wrong_dtype_rank_and_shape_before_cuda() {
6969        let valid = StInfo {
6970            dtype: "BF16".into(),
6971            shape: vec![8, 4],
6972            data_offsets: [0, 64],
6973        };
6974        assert!(validate_dflash_tensor("w", &valid, &[4, 8]).is_ok());
6975
6976        let mut bad = valid.clone();
6977        bad.dtype = "F32".into();
6978        assert!(
6979            validate_dflash_tensor("w", &bad, &[4, 8])
6980                .unwrap_err()
6981                .contains("dtype")
6982        );
6983        bad = valid.clone();
6984        bad.shape = vec![32];
6985        assert!(
6986            validate_dflash_tensor("w", &bad, &[4, 8])
6987                .unwrap_err()
6988                .contains("shape")
6989        );
6990        assert!(
6991            validate_dflash_tensor("w", &valid, &[8, 4])
6992                .unwrap_err()
6993                .contains("expected")
6994        );
6995    }
6996
6997    #[test]
6998    fn attention_and_selector_geometry_refuse_before_cuda() {
6999        assert!(validate_dflash_attention_geometry(64, 8, 128).is_ok());
7000        assert!(validate_dflash_attention_geometry(63, 8, 128).is_err());
7001        assert!(validate_dflash_attention_geometry(64, 0, 128).is_err());
7002        assert!(validate_dflash_attention_geometry(usize::MAX, 1, 2).is_err());
7003        assert!(validate_selector_top_k(16, 128).is_ok());
7004        assert!(validate_selector_top_k(0, 128).is_err());
7005        assert!(validate_selector_top_k(129, 128).is_err());
7006        assert!(validate_layer_layout(&[true, true], 2).is_ok());
7007        assert!(validate_layer_layout(&[true], 2).is_err());
7008    }
7009}