Skip to main content

memra_engine/
pp.rs

1//! M2 pipeline-parallel N-stage runtime (generalizes the M1 2-stage seam).
2//!
3//! Door: `MEMRA_PP_STAGES=N` (default OFF — unset/0/1 = no behavior change anywhere).
4//! Stage map: N stages over the trunk layers with N-1 cuts. `MEMRA_PP_SPLITS=c1,..,cN-1`
5//! sets the cuts explicitly (strictly increasing, in (0, n_layers)); `MEMRA_PP_SPLIT=<i>`
6//! is the N=2 back-compat spelling; default = even split (cut s = s*n_layers/N).
7//! Placement: `MEMRA_PP_DEVICES=d0,..,dN-1` maps stage s to device ds (default: all on
8//! the primary engine's device).
9//!
10//! M1 history (increments 1-2, merged + hardened on the 8x box 2026-08-02): seam + gate
11//! single-device; then real transport — per-stage streams/events, device placement,
12//! peer-copy boundary (M0: cudaMemcpyPeerAsync beats NCCL 2.8x at PP activation sizes),
13//! per-context PDL module caches, default-mempool peer grants. All five r3 gates PASS
14//! bit-identical (receipts ~/receipts/m1-pp2/ on <bench-instance>).
15//!
16//! M2 increment 1 (this file): N-STAGE GENERALIZATION — `Pp2Rt` becomes `PpNRt`:
17//!   - `stages`: Vec of per-stage execution homes (device, context, stream, remote Engine);
18//!   - `boundaries`: N-1 boundary runtimes, each with TWO persistent double-buffered slots
19//!     (ev_tx/ev_rx per slot) and its own overlap step counter; transport is selected PER
20//!     BOUNDARY (dtod same-device / cudaMemcpyPeerAsync cross-device by default; opt-in
21//!     `MEMRA_PP_HOST_BOUNCE=1` uses pinned D2H + H2D instead);
22//!   - the default peer transport grants peer + default-mempool access between EVERY distinct
23//!     pair of devices in use. Host bounce skips serving-time grants; its boot diagnostics
24//!     transiently enable peer + pool access, then revoke the pool grants and disable peer access
25//!     before proceeding. Sharded weights plus stage-local auxiliary buffers ensure that no peer
26//!     read can bypass the bounced boundary.
27//!
28//! M2 increment 2 (weight sharding): the loader uploads each stage's layer range THROUGH
29//! that stage's engine (`layer_engine`), so weights land on the device that runs them —
30//! the bring-up peer-read placement dies. `output_norm` + lm head load through the LAST
31//! stage's engine; the embed table stays host-side with stage 0. Split-plane/f16 decode
32//! mirrors are built per layer through the owning stage's engine too (the rp4 mirrors ARE
33//! the decode weights on the q8 path — leaving them on dev0 would fake the kill).
34//! Rollback seam: `MEMRA_PP_SHARD=0` = M1 bring-up placement (all weights on primary,
35//! remote stages peer-read).
36//!
37//! M2 increment 3 (deferred readback — the pipelining seed): `PendingLogits` — the eager
38//! decode arm can END a step without the logits D2H (`decode_step_h_ppn_deferred`): the
39//! logits stay device-resident with a completion event; `wait()` drains them through a
40//! DEDICATED readback stream (waits the event, copies, syncs) so tokens t+1.. keep
41//! enqueuing on the stage streams while token t drains. Per-token math is fully
42//! event-ordered (same slots, same ev_tx/ev_rx chain) — scheduling changes, math does
43//! not; the pipelined replay arm of `ppn-gate` proves bit-identity per step.
44//!
45//! Ownership across a boundary (unchanged from M1):
46//!   - hidden state [n_embd] f32 is the ONLY tensor that crosses;
47//!   - KV/linear-attn cache entries are per-layer: stage s exclusively owns cache state
48//!     for its layer range (and, under MEMRA_PP_DEVICES, allocates it on its device);
49//!   - position/rope state is the scalar `cache.pos` snapshot taken once per step; every stage
50//!     uploads its own position buffer on its own stream (no cross-device position pointer);
51//!   - the embed table lives with stage 0, output_norm + lm head with the last stage.
52//!
53//! THE MULTI-STREAM LAW (why this is safe with cudarc event tracking disabled): all
54//! cross-stage bytes flow through the persistent boundary slots, ordered by ev_tx/ev_rx;
55//! per-stage scratch is allocated AND freed on that stage's stream (stream-ordered); the
56//! async mem pool runs with opportunistic reuse OFF + internal dependencies ON
57//! (memra-runtime), so a block freed on stream A and reused on stream B carries a
58//! driver-inserted dependency. Weights are load-time state no stage stream can precede,
59//! and the step's terminal logits readback (sync D2H, or PendingLogits' event-ordered
60//! readback stream) drains the last stage, whose TX-wait chain transitively drains all.
61//!
62//! Scope: plain eager decode only (generic arm N-stage; gemma4 arm 2-stage). NOT wired:
63//! batch/dc/graph/spec loops and the gemma4-E4B eager arm.
64//!
65//! CORRECTION (pp2-hardening 2026-08-06): this header used to add "(`warn_unwired_once`
66//! fires)" to that list, which was wrong. `warn_unwired_once` has exactly two call sites
67//! and BOTH are gemma4-specific (decode.rs, hybrid_forward.rs) — the batch/dc/graph/spec
68//! loops never warned. Worse, the batched loop did not merely run unsplit: it walked the
69//! whole trunk on the primary stream and, under a sharded cross-device placement,
70//! peer-read every remote stage's weights each step — 28x slower at B=1 with all three
71//! `decode-batch-gate` gates PASSING (peer reads are byte-exact, so only perf broke).
72//! `decode_step_batch` now FAILS CLOSED in that regime via `pp_sharded_cross_device()`
73//! (`MEMRA_PP_ALLOW_UNSPLIT_BATCH=1` = measurement override). "Unwired" for dc/graph/spec
74//! still means "runs unsplit, silently" — audit each before trusting it on a pair.
75
76use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
77use std::sync::{Arc, Mutex, OnceLock, Weak};
78
79use cudarc::driver::{CudaContext, CudaEvent, CudaSlice, CudaStream};
80
81use crate::Engine;
82
83/// Restores the caller's primary CUDA context on every return path, including panic unwind. The
84/// explicit `restore` call preserves the bind error for normal Result propagation; Drop is the
85/// final safety net when a scoped host worker or head-stage callback panics.
86pub(crate) struct PrimaryContextRestore<'a> {
87    engine: &'a Engine,
88    restored: bool,
89}
90
91impl<'a> PrimaryContextRestore<'a> {
92    pub(crate) fn new(engine: &'a Engine) -> Self {
93        Self {
94            engine,
95            restored: false,
96        }
97    }
98
99    pub(crate) fn restore(mut self) -> Result<(), Box<dyn std::error::Error>> {
100        let result = self.engine.ctx().bind_to_thread();
101        self.restored = result.is_ok();
102        result?;
103        Ok(())
104    }
105}
106
107impl Drop for PrimaryContextRestore<'_> {
108    fn drop(&mut self) {
109        if !self.restored {
110            let _ = self.engine.ctx().bind_to_thread();
111        }
112    }
113}
114
115/// Returns the stage fence iff the ppN door is open: `MEMRA_PP_STAGES=N` (N >= 2) with a
116/// valid cut list. The fence has N+1 entries: `[0, c1, .., cN-1, n_layers]`; stage s runs
117/// layers `[fence[s], fence[s+1])`. Reads the environment on every call (gates toggle the
118/// door in-process); the cost is a few getenv per decode step, eager-loop noise.
119pub fn pp_cuts(n_layers: usize) -> Option<Vec<usize>> {
120    let n_st: usize = match std::env::var("MEMRA_PP_STAGES") {
121        Ok(v) if v.is_empty() || v == "0" || v == "1" => return None,
122        Ok(v) => match v.parse::<usize>() {
123            Ok(n) => n,
124            Err(_) => {
125                warn_bad_once(&format!("MEMRA_PP_STAGES={v} unparseable; door stays OFF"));
126                return None;
127            }
128        },
129        Err(_) => return None,
130    };
131    if n_st < 2 || n_st > n_layers {
132        warn_bad_once(&format!(
133            "MEMRA_PP_STAGES={n_st} outside [2, n_layers={n_layers}]; door stays OFF"
134        ));
135        return None;
136    }
137    let mut fence = Vec::with_capacity(n_st + 1);
138    fence.push(0usize);
139    if let Ok(s) = std::env::var("MEMRA_PP_SPLITS") {
140        let parts: Result<Vec<usize>, _> =
141            s.split(',').map(|p| p.trim().parse::<usize>()).collect();
142        match parts {
143            Ok(cuts) if cuts.len() == n_st - 1 => fence.extend(cuts),
144            _ => {
145                warn_bad_once(&format!(
146                    "MEMRA_PP_SPLITS={s} invalid (want {} comma-separated cuts); door stays OFF",
147                    n_st - 1
148                ));
149                return None;
150            }
151        }
152    } else if let Ok(v) = std::env::var("MEMRA_PP_SPLIT") {
153        // N=2 back-compat spelling. With N>2 a single split is ambiguous — fail the door
154        // loudly rather than guess (a silent even-split would fake a gate config).
155        if n_st != 2 {
156            warn_bad_once(&format!(
157                "MEMRA_PP_SPLIT={v} set with MEMRA_PP_STAGES={n_st}; use MEMRA_PP_SPLITS \
158                 for N>2 — door stays OFF"
159            ));
160            return None;
161        }
162        match v.parse::<usize>() {
163            Ok(c) => fence.push(c),
164            Err(_) => {
165                warn_bad_once(&format!("MEMRA_PP_SPLIT={v} unparseable; door stays OFF"));
166                return None;
167            }
168        }
169    } else {
170        for s in 1..n_st {
171            fence.push(s * n_layers / n_st);
172        }
173    }
174    fence.push(n_layers);
175    for w in fence.windows(2) {
176        if w[0] >= w[1] {
177            warn_bad_once(&format!(
178                "pp stage fence {fence:?} not strictly increasing over [0, {n_layers}]; \
179                 door stays OFF"
180            ));
181            return None;
182        }
183    }
184    Some(fence)
185}
186
187/// N=2 back-compat view of the door (the gemma4 arm and `pp2-gate` are 2-stage): `Some(cut)`
188/// iff the door is open with EXACTLY two stages.
189pub fn pp2_split(n_layers: usize) -> Option<usize> {
190    pp_cuts(n_layers).filter(|f| f.len() == 3).map(|f| f[1])
191}
192
193/// The stage that owns layer `il` under `fence` (see `pp_cuts`).
194pub fn stage_of(fence: &[usize], il: usize) -> usize {
195    debug_assert!(fence.len() >= 2);
196    match fence[1..fence.len() - 1].binary_search(&il) {
197        // fence[1..][k] == il means il is the FIRST layer of stage k+1
198        Ok(k) => k + 1,
199        Err(k) => k,
200    }
201}
202
203/// MEMRA_PP_STREAMS=0: rollback to the increment-1 same-stream seam (boundary = two plain
204/// dtod copies on the ambient compute stream, no per-stage streams/events/devices).
205pub fn pp2_streams_off() -> bool {
206    matches!(std::env::var("MEMRA_PP_STREAMS").as_deref(), Ok("0"))
207}
208
209/// `MEMRA_PP_EXIT_PUBLISH` — the ppN EXIT-PUBLICATION guard (lane/glm5-accrace 2026-09-01).
210///
211/// **DEFAULT ON, and the default is the measurement, not a preference** (the new-flags law:
212/// ON/OFF by design, receipts attached, FLAGS.md row in the same commit). With per-stage
213/// streams on ONE device the hc ppN bodies published nothing to the caller except a
214/// last-stage drain, so a caller allocation could land under still-queued stage work: the
215/// prime over a fixed prompt returned three distinct logit fingerprints inside one process
216/// (32/110 non-canonical), and one glm5 spec round silently lost an acceptance. See
217/// [`PpNRt::publish_all_to`] for the anatomy and
218/// `research/glm53-flash-bringup-20260827/accrace-20260901/LANE.md` for the receipts.
219///
220/// `0` restores the pre-lane behaviour exactly — the ROLLBACK/CONTROL seam (flags doctrine:
221/// rollback seams are a legitimate flag class). It is a KNOWN-RACY arm: never a serving
222/// configuration, only an A/B control.
223///
224/// Read PER CALL rather than latched: the gate matrices drive both arms in one process.
225///
226/// POLARITY IS DELIBERATE, AND DO NOT COPY IT BLIND (review note, 2026-09-01): the test is
227/// "anything except exactly `0` is ON", so a typo'd rollback (`=false`, `=O`, `=00`) leaves the
228/// guard ON. That FAILS SAFE **here** — the ON arm is the correctness fix, the OFF arm is the
229/// known-racy control — and it is why this flag is written loosely on purpose rather than
230/// parsed strictly. The polarity is only safe because of which arm is dangerous. A default-ON
231/// flag whose `0` disables something HAZARDOUS needs the mirror shape (`Ok("1")`-style strict
232/// opt-in, or a parse that refuses an unrecognized value), because there the same typo would
233/// silently keep the hazard armed. Pick the polarity from which side fails safe, never by
234/// copying this line.
235pub fn pp_exit_publish() -> bool {
236    !matches!(std::env::var("MEMRA_PP_EXIT_PUBLISH").as_deref(), Ok("0"))
237}
238
239/// True iff the ppN door would put TWO OR MORE stage streams on ONE device (devices
240/// unset = all stages on the primary; or an explicit placement with a repeated device).
241/// The deferred-readback (pipelined) arm is REFUSED in this regime: the 2026-08-02 x20
242/// soak record — singledev pipelined 13/20 PASS default, 7 failures each diverging at a
243/// different step (timing-race signature); MEMRA_PDL=0 went 20/20 on one soak but a
244/// second same-config soak on the auto-gated build failed 2/20 (n2) and battery-4 failed
245/// n4 — so PDL narrows the window without closing it, and the true root cause (same
246/// Engine kernels concurrent on two streams of one device) is NOT fixed by any flag yet.
247/// Cross-device pipelined (one stage stream per device) is 23/23 clean post-fix. Refuse
248/// loudly rather than return silently-wrong logits. Env-only read (callable pre-runtime).
249///
250/// ONE MECHANISM OF THAT OPEN ROOT CAUSE IS NOW NAMED AND CLOSED (lane/glm5-accrace
251/// 2026-09-01), stated narrowly because it was measured on the SERIAL arm, not this
252/// refused pipelined one: a ppN body that returned to its caller published only the
253/// producing last stage, so a caller allocation could land under work still queued on a
254/// caller-CO-RESIDENT stage stream. That is exactly a "same Engine, two streams, one
255/// device" corruption, and it is the reason this predicate's regime is the dangerous one —
256/// on a DISTINCT-device placement only the head stage shares the caller's context, and a
257/// body's terminal drain already covers it. See [`PpNRt::publish_all_to`] and
258/// [`pp_exit_publish`]. Whether the pipelined arm's remaining flake is the same mechanism
259/// is UNMEASURED; this refusal stands.
260pub fn pp_multi_stream_same_device() -> bool {
261    let stages_open = std::env::var("MEMRA_PP_STAGES")
262        .map(|v| v.parse::<usize>().map(|n| n >= 2).unwrap_or(false))
263        .unwrap_or(false);
264    let devices = std::env::var("MEMRA_PP_DEVICES")
265        .ok()
266        .filter(|v| !v.is_empty());
267    if (!stages_open && devices.is_none()) || pp2_streams_off() {
268        return false;
269    }
270    match devices {
271        None => true, // door open, no placement: every stage stream lands on the primary
272        Some(s) => pp_devices_repeat(&s),
273    }
274}
275
276fn pp_devices_repeat(raw: &str) -> bool {
277    let Ok(mut devices) = raw
278        .split(',')
279        .map(|part| part.trim().parse::<usize>())
280        .collect::<Result<Vec<_>, _>>()
281    else {
282        // Runtime construction will return the precise parse error. Treat malformed input as
283        // unsafe here so a second environment interpretation can never admit a wavefront.
284        return true;
285    };
286    let count = devices.len();
287    devices.sort_unstable();
288    devices.dedup();
289    devices.len() < count
290}
291
292/// True iff the ppN door is open AND the placement spans 2+ DISTINCT devices AND the
293/// per-stage sharded loader is on — i.e. some layers' weights live on a device other than
294/// the primary. Any path that walks the WHOLE trunk on one stream in this regime reads
295/// those weights over PCIe every step. Env-only read (callable pre-runtime).
296///
297/// Measured cost of doing that (pp2-hardening 2026-08-06, 2x RTX PRO 6000, PCIe Gen5 x16
298/// P2P, decode-batch-bench q9, N=5 interleaved, `research/pp2-hardening-20260806`):
299/// **B=1 7.4 vs 208.9 tok/s (28x), B=4 29.8 vs 491.3 (16.5x), B=8 47.4 vs 657.0 (13.9x)**.
300/// The same sweep with `MEMRA_PP_SHARD=0` (weights all home) returns 178.5/491.1/656.6 —
301/// identical to the single-device door-open arm — so the entire cliff is the peer read,
302/// not the door and not the placement plumbing. Exactness is NOT the issue: peer reads
303/// return identical bytes and every `decode-batch-gate` gate PASSED on this config, which
304/// is precisely why it needs a refusal rather than a gate.
305pub fn pp_sharded_cross_device() -> bool {
306    let stages_open = std::env::var("MEMRA_PP_STAGES")
307        .map(|v| v.parse::<usize>().map(|n| n >= 2).unwrap_or(false))
308        .unwrap_or(false);
309    // MEMRA_PP_STREAMS=0 (2026-08-06, pp2-batch): the same-stream rollback seam ALSO turns
310    // the sharded loader off — `layer_engine` returns the primary engine whenever
311    // `pp2_streams_off()`, and `new_cache` skips `Cache::new_ppn` on the same condition. So
312    // in that regime every weight and every cache is home on the primary and an unsplit walk
313    // peer-reads NOTHING. Without this term the guard refused that config too: a spurious
314    // refusal of a placement that is sound and full-speed. Found wiring the batched pp arm.
315    if !stages_open || pp_shard_off() || pp2_streams_off() {
316        return false;
317    }
318    match pp2_devices_env() {
319        None => false, // no placement: every stage is the primary device, nothing remote
320        Some(s) => {
321            let mut v: Vec<&str> = s.split(',').map(|p| p.trim()).collect();
322            v.sort_unstable();
323            v.dedup();
324            v.len() >= 2
325        }
326    }
327}
328
329/// The shared fail-closed guard for EVERY decode path that has no pp stage split.
330/// Returns `Err` iff `pp_sharded_cross_device()` — i.e. the caller would walk the whole
331/// trunk on one stream while some layers' weights live on another device, peer-reading
332/// them every step. `path` names the refusing function so the operator knows which loop
333/// they hit; `alt` names the working alternative for that loop.
334///
335/// One helper rather than four copies because the audit found FOUR paths with the same
336/// hole (`decode_step_batch`, `decode_step_dc`, the graph capture that wraps dc, and
337/// `decode_step_t*` verify), and a per-path copy is how one gets missed on the next
338/// addition. Override: `MEMRA_PP_ALLOW_UNSPLIT_BATCH=1` (one door for all of them —
339/// they are the same measurement question).
340pub fn refuse_unsplit_if_remote(path: &str, alt: &str) -> Result<(), Box<dyn std::error::Error>> {
341    if pp_host_bounce_active() {
342        return Err(format!(
343            "{path}: refused with MEMRA_PP_HOST_BOUNCE=1 on sharded cross-device PP — \
344             this unsplit path peer-reads remote weights, while host bounce covers only \
345             explicit stage-boundary transfers. Use {alt}; the \
346             MEMRA_PP_ALLOW_UNSPLIT_BATCH override is unavailable on a broken-peer host."
347        )
348        .into());
349    }
350    if pp_sharded_cross_device()
351        && std::env::var("MEMRA_PP_ALLOW_UNSPLIT_BATCH").as_deref() != Ok("1")
352    {
353        return Err(format!(
354            "{path}: refused with the ppN door open across 2+ devices — this path has no pp \
355             stage split, so it would walk ALL layers on one stream and peer-read every \
356             remote stage's weights each step (measured 28x slower at B=1, 13.9x at B=8 on \
357             a PRO 6000 pair over PCIe Gen5 x16 P2P; research/pp2-hardening-20260806). \
358             Exactness is unaffected — peer reads return identical bytes and the exactness \
359             gates PASS on this config — which is exactly why it must refuse instead of \
360             being caught by a gate. Fixes, in order: {alt}; or MEMRA_PP_SHARD=0 (all \
361             weights home on the primary — full speed, forfeits the capacity PP-2 exists \
362             for); or close the pp door. MEMRA_PP_ALLOW_UNSPLIT_BATCH=1 overrides for \
363             measurement."
364        )
365        .into());
366    }
367    Ok(())
368}
369
370/// MEMRA_BATCH_PP=0: rollback/A-B seam for the BATCHED stage split (pp2-batch 2026-08-06).
371/// Default ON — with the ppN door open the batched decode step takes its own stage split
372/// (`decode_step_batch_ppn`) exactly as the eager step does. Setting 0 sends the batched
373/// path back through the unsplit body, which under a sharded cross-device placement is
374/// then caught by `refuse_unsplit_if_remote` (the 28x peer-read regime) rather than run
375/// silently. Exists so the bit-identity gate can A/B split vs unsplit IN ONE PROCESS
376/// against the same loaded weights — read per step, never memoized, for that reason.
377pub fn batch_pp_on() -> bool {
378    std::env::var("MEMRA_BATCH_PP").as_deref() != Ok("0")
379}
380
381/// Largest PP wavefront admitted by the RTX PRO 6000 product shape. The underlying placement
382/// runtime remains N-stage, but the serving wave scheduler is deliberately bounded to the 2--4
383/// card surface that has a concrete qualification plan.
384pub const PP_WAVE_MAX_STAGES: usize = 4;
385
386/// Strict opt-in for the PP3/PP4 request wavefront. PP2 keeps its independently qualified
387/// `MEMRA_DUAL_PP` default; a new stage count never inherits that default without its own target
388/// receipts.
389pub fn pp_wave_on_value(value: Option<&str>) -> Result<bool, &'static str> {
390    match value {
391        None | Some("0") => Ok(false),
392        Some("1") => Ok(true),
393        Some(_) => Err("MEMRA_PP_WAVE must be 0 or 1"),
394    }
395}
396
397pub fn pp_wave_on() -> Result<bool, &'static str> {
398    match std::env::var_os("MEMRA_PP_WAVE") {
399        None => pp_wave_on_value(None),
400        Some(value) => value
401            .to_str()
402            .ok_or("MEMRA_PP_WAVE must be valid UTF-8 and exactly 0 or 1")
403            .and_then(|value| pp_wave_on_value(Some(value))),
404    }
405}
406
407/// Split one scheduler tick into at most one wave per stage. Earlier waves carry the remainder so
408/// priority order is preserved, every row appears exactly once, and the largest wave is
409/// `ceil(batch / min(batch, stages))`.
410pub fn pp_wave_ranges(batch: usize, stages: usize) -> Vec<(usize, usize)> {
411    if batch == 0 || stages == 0 {
412        return Vec::new();
413    }
414    let waves = batch.min(stages);
415    let base = batch / waves;
416    let extra = batch % waves;
417    let mut out = Vec::with_capacity(waves);
418    let mut start = 0usize;
419    for wave in 0..waves {
420        let len = base + usize::from(wave < extra);
421        out.push((start, start + len));
422        start += len;
423    }
424    debug_assert_eq!(start, batch);
425    out
426}
427
428/// Cells on one pipeline anti-diagonal, returned as `(wave, stage)`. Cells in a diagonal never
429/// share a wave (request/cache state) or a stage (Engine scratch/stream), so they may be driven by
430/// scoped host threads without reintroducing the shared-Engine race that quarantined the old
431/// deferred PP walker.
432pub fn pp_wave_diagonal(stages: usize, waves: usize, diagonal: usize) -> Vec<(usize, usize)> {
433    if stages == 0 || waves == 0 || diagonal >= stages + waves - 1 {
434        return Vec::new();
435    }
436    let first_stage = diagonal.saturating_sub(waves - 1);
437    let last_stage = diagonal.min(stages - 1);
438    (first_stage..=last_stage)
439        .map(|stage| (diagonal - stage, stage))
440        .collect()
441}
442
443/// Fail-closed topology gate for the unqualified PP3/PP4 wavefront. Native peer transport and one
444/// physical device per stage are required for the first implementation; host bounce and repeated
445/// devices retain the serial PP-N walker.
446pub fn pp_wave_eligibility(
447    stages: usize,
448    double_slot: bool,
449    host_bounce: bool,
450    repeated_device: bool,
451) -> Result<(), &'static str> {
452    if !(3..=PP_WAVE_MAX_STAGES).contains(&stages) {
453        return Err("PP wavefront requires 3 or 4 stages; PP2 is owned by MEMRA_DUAL_PP");
454    }
455    if !double_slot {
456        return Err("PP wavefront requires MEMRA_PP_OVERLAP=1 double-buffered boundaries");
457    }
458    if host_bounce {
459        return Err(
460            "PP wavefront is unqualified with MEMRA_PP_HOST_BOUNCE=1; use native peer transport",
461        );
462    }
463    if repeated_device {
464        return Err("PP wavefront requires one distinct CUDA device per stage");
465    }
466    Ok(())
467}
468
469/// The PP3/PP4 scheduler decomposes one serving batch into narrower stage waves. A preserved-BF16
470/// W4A16 artifact therefore needs the row-wise BF16 matvec program: the default f32-expanded
471/// cuBLAS path is batch-width dependent, and HY3 B=4/B=8 changed every logit row when wave cells
472/// narrowed to B=1/B=2. `MEMRA_BF16_MMV=1` keeps the same checkpoint BF16 values and runs one
473/// deterministic per-row reduction program at every width.
474pub const PP_WAVE_W4A16_BF16_REFUSAL: &str = "PP wavefront for a W4A16 artifact with preserved BF16 non-expert weights requires \
475     MEMRA_BF16_MMV=1; without the row-wise BF16 program, wave batch-width decomposition changes \
476     logits. Keep MEMRA_PP_WAVE=0 or enable and qualify MEMRA_BF16_MMV=1";
477
478pub fn pp_wave_numeric_eligibility(
479    weight_only_nvfp4: bool,
480    bf16_mmv: bool,
481) -> Result<(), &'static str> {
482    if weight_only_nvfp4 && !bf16_mmv {
483        return Err(PP_WAVE_W4A16_BF16_REFUSAL);
484    }
485    Ok(())
486}
487
488/// One routing predicate shared by decode and prime: requesting the wave door without the
489/// double-slot policy is the documented serial rollback, not a late per-request refusal.
490pub fn pp_wave_route_enabled(
491    requested: bool,
492    overlap: bool,
493    stages: usize,
494    work_items: usize,
495) -> bool {
496    requested && overlap && (3..=PP_WAVE_MAX_STAGES).contains(&stages) && work_items >= 2
497}
498
499static PP_WAVE_ACTIVE_CELLS: AtomicUsize = AtomicUsize::new(0);
500static PP_WAVE_OVERLAPS: AtomicUsize = AtomicUsize::new(0);
501static PP_WAVE_TICKS: AtomicUsize = AtomicUsize::new(0);
502static PP_WAVE_CELLS: AtomicUsize = AtomicUsize::new(0);
503
504pub(crate) struct PpWaveCellGuard;
505
506/// Mark one host-driven PP3/PP4 cell active. An overlap increment is proof that two distinct
507/// stage walkers were simultaneously inside their model range; enqueue order alone is not proof
508/// for MoE paths whose router readback synchronizes the host.
509pub(crate) fn enter_pp_wave_cell() -> PpWaveCellGuard {
510    let active = PP_WAVE_ACTIVE_CELLS.fetch_add(1, Ordering::AcqRel);
511    if active > 0 {
512        PP_WAVE_OVERLAPS.fetch_add(1, Ordering::Relaxed);
513    }
514    PP_WAVE_CELLS.fetch_add(1, Ordering::Relaxed);
515    PpWaveCellGuard
516}
517
518impl Drop for PpWaveCellGuard {
519    fn drop(&mut self) {
520        let active = PP_WAVE_ACTIVE_CELLS.fetch_sub(1, Ordering::AcqRel);
521        debug_assert!(active > 0, "PP wave active-cell counter underflow");
522    }
523}
524
525pub(crate) fn record_pp_wave_tick() {
526    PP_WAVE_TICKS.fetch_add(1, Ordering::Relaxed);
527}
528
529/// `(completed ticks, entered cells, observed concurrent-cell overlaps)`.
530pub fn pp_wave_snapshot() -> (usize, usize, usize) {
531    (
532        PP_WAVE_TICKS.load(Ordering::Relaxed),
533        PP_WAVE_CELLS.load(Ordering::Relaxed),
534        PP_WAVE_OVERLAPS.load(Ordering::Relaxed),
535    )
536}
537
538/// MEMRA_DUAL_PP three-state mode for the dual-active PP-2 batched decode path.
539/// Default ON (owner flip 2026-08-11) after the box1 PRO-pair re-gate: correctness
540/// bit-identity B=1..5, servestress no-thrash, 10-boot soak 929/929 golden matches with
541/// 0 slot collisions across 9123 pairs (research/dualpp2-20260811/RESULTS-regate.md), plus
542/// the dualpp1 c>=8 interleaved perf floor (+20.753% minimum,
543/// research/dualpp1-20260811/RESULTS.md).
544///
545/// The three states carry different failure semantics on purpose:
546/// - `Off` (`MEMRA_DUAL_PP=0`): the serial rollback seam. Overlap also follows OFF unless
547///   `MEMRA_PP_OVERLAP` is set explicitly, so one flag restores the exact pre-flip naked path.
548/// - `Forced` (`MEMRA_DUAL_PP=1`): the pre-flip explicit request. A placement that cannot
549///   run dual (single-slot boundary, host bounce, non-PP-2 fence) REFUSES with the binding
550///   quoted reason before any token or cache advance — the gate negative cells pin this.
551/// - `Auto` (unset): the flipped default. Dual runs where the re-gate validated it
552///   (PP-2 fence, double-slot, peer transport, B>=2) and silently degrades to the serial
553///   PP-N walker everywhere else — naked PP-3 serving and the MEMRA_PP_HOST_BOUNCE=1
554///   broken-peer escape hatch must keep decoding, not refuse.
555#[derive(Clone, Copy, PartialEq, Eq, Debug)]
556pub enum DualPpMode {
557    Off,
558    Forced,
559    Auto,
560}
561
562/// Pure resolution for MEMRA_DUAL_PP, split from the env read so the flip regression tests
563/// cannot race parallel test threads on process env.
564pub fn dual_pp_mode_resolve(v: Option<&str>) -> DualPpMode {
565    match v {
566        Some("0") => DualPpMode::Off,
567        Some("1") => DualPpMode::Forced,
568        _ => DualPpMode::Auto,
569    }
570}
571
572pub fn dual_pp_mode() -> DualPpMode {
573    dual_pp_mode_resolve(std::env::var("MEMRA_DUAL_PP").ok().as_deref())
574}
575
576/// True when the dual-active door is open (Forced or Auto). Read per step so the
577/// model-level gate can replay serial and waved arms against one loaded checkpoint.
578pub fn dual_pp_on() -> bool {
579    dual_pp_mode() != DualPpMode::Off
580}
581
582/// Engine-entry routing for the dual-active path, kept pure for the flip regression
583/// tests. `Forced` routes every B>=2 PP-2 call into `decode_step_batch_dual` even when
584/// the placement cannot run it, so the binding refusals stay reachable and loud.
585/// `Auto` routes only the exact re-gated regime and leaves everything else on the serial
586/// PP-N walker. `dual_pp_eligibility` remains behind this as defense in depth.
587pub fn dual_pp_route(
588    mode: DualPpMode,
589    batch: usize,
590    stages: usize,
591    double_slot: bool,
592    host_bounce: bool,
593) -> bool {
594    if batch < 2 {
595        return false;
596    }
597    match mode {
598        DualPpMode::Off => false,
599        DualPpMode::Forced => true,
600        DualPpMode::Auto => stages == 2 && double_slot && !host_bounce,
601    }
602}
603
604/// Binding-amendment refusal text. The negative gate quotes this exact line and requires the
605/// decode call to return before producing a token or advancing a cache.
606pub const DUAL_PP_SINGLE_SLOT_REFUSAL: &str = "decode_step_batch_dual: refused: PP boundary is single-slot; set MEMRA_PP_OVERLAP=1 so both alternating boundary slots are prepared before dual-active decode";
607pub const DUAL_PP_HOST_BOUNCE_REFUSAL: &str = "decode_step_batch_dual: refused: MEMRA_PP_HOST_BOUNCE=1 is unvalidated for dual-active decode; disable MEMRA_DUAL_PP or use peer transport";
608
609/// Pure schedule policy shared by the runtime and kernel-check manifest cells. A single row
610/// has no second wave and must stay on the serial PP-N walker.
611#[allow(clippy::manual_div_ceil)] // allow: explicit (n + k - 1) / k is the load-bearing sizing form, kept textually identical to the kernel-side math
612pub fn dual_pp_wave_mid(batch: usize) -> Option<usize> {
613    (batch >= 2).then_some((batch + 1) / 2)
614}
615
616/// Fail-closed eligibility check kept pure so the negative manifest cell cannot accidentally
617/// initialize CUDA state. Slot preparation itself remains `PpNRt::prepare_overlap_slots`.
618pub fn dual_pp_eligibility(
619    stages: usize,
620    double_slot: bool,
621    host_bounce: bool,
622) -> Result<(), &'static str> {
623    if stages != 2 {
624        return Err(
625            "decode_step_batch_dual: refused: dual-active decode requires exactly two PP stages",
626        );
627    }
628    if !double_slot {
629        return Err(DUAL_PP_SINGLE_SLOT_REFUSAL);
630    }
631    if host_bounce {
632        return Err(DUAL_PP_HOST_BOUNCE_REFUSAL);
633    }
634    Ok(())
635}
636
637/// Liveness is counted only while the two host-driven decode layer walkers are both active.
638/// Enqueue order is not proof for Step: its router readback synchronizes the issuing thread.
639static DUAL_PP_OVERLAPS: AtomicUsize = AtomicUsize::new(0);
640static DUAL_PP_ACTIVE_STAGES: AtomicUsize = AtomicUsize::new(0);
641static DUAL_PP_STAGE_NS: [AtomicU64; 4] = [
642    AtomicU64::new(0),
643    AtomicU64::new(0),
644    AtomicU64::new(0),
645    AtomicU64::new(0),
646];
647static DUAL_PP_STAGE_SAMPLES: [AtomicUsize; 4] = [
648    AtomicUsize::new(0),
649    AtomicUsize::new(0),
650    AtomicUsize::new(0),
651    AtomicUsize::new(0),
652];
653static DUAL_PP_TIMING_DROPPED: AtomicUsize = AtomicUsize::new(0);
654static DUAL_PP_SLOT_PAIRS: AtomicUsize = AtomicUsize::new(0);
655static DUAL_PP_SLOT_USES: [AtomicUsize; 2] = [AtomicUsize::new(0), AtomicUsize::new(0)];
656static DUAL_PP_SLOT_COLLISIONS: AtomicUsize = AtomicUsize::new(0);
657
658pub const DUAL_PP_STAGE_NAMES: [&str; 4] = [
659    "wave_a_stage0",
660    "wave_a_stage1",
661    "wave_b_stage0",
662    "wave_b_stage1",
663];
664
665pub fn dual_pp_overlaps() -> usize {
666    DUAL_PP_OVERLAPS.load(Ordering::Relaxed)
667}
668
669/// Record the two boundary slots selected for one dual-active wave pair. A same-slot pair is
670/// rejected by the caller before wave B can consume a residual; the collision counter makes that
671/// fail-closed path observable to the detached soak instead of relying only on log scanning.
672pub(crate) fn record_dual_pp_slot_pair(slot_a: usize, slot_b: usize) -> bool {
673    debug_assert!(slot_a < DUAL_PP_SLOT_USES.len());
674    debug_assert!(slot_b < DUAL_PP_SLOT_USES.len());
675    if slot_a == slot_b {
676        DUAL_PP_SLOT_COLLISIONS.fetch_add(1, Ordering::Relaxed);
677        return false;
678    }
679    DUAL_PP_SLOT_USES[slot_a].fetch_add(1, Ordering::Relaxed);
680    DUAL_PP_SLOT_USES[slot_b].fetch_add(1, Ordering::Relaxed);
681    DUAL_PP_SLOT_PAIRS.fetch_add(1, Ordering::Relaxed);
682    true
683}
684
685/// `(completed wave pairs, [slot 0 uses, slot 1 uses], rejected same-slot pairs)`.
686pub fn dual_pp_slot_snapshot() -> (usize, [usize; 2], usize) {
687    (
688        DUAL_PP_SLOT_PAIRS.load(Ordering::Relaxed),
689        std::array::from_fn(|i| DUAL_PP_SLOT_USES[i].load(Ordering::Relaxed)),
690        DUAL_PP_SLOT_COLLISIONS.load(Ordering::Relaxed),
691    )
692}
693
694/// CUDA-event timing is a diagnostic-only process door. The scored N=5 block runs without
695/// it; the companion box1 diagnostic process enables it and exports cumulative per-wave
696/// stage spans through `/metrics`.
697pub fn dual_pp_timing_on() -> bool {
698    static ON: OnceLock<bool> = OnceLock::new();
699    *ON.get_or_init(|| std::env::var("MEMRA_DUAL_PP_TIMING").as_deref() == Ok("1"))
700}
701
702pub(crate) fn record_dual_pp_stage_ms(stage: usize, ms: f32) {
703    assert!(
704        stage < DUAL_PP_STAGE_NS.len(),
705        "dual PP timing stage out of range"
706    );
707    let ns = (f64::from(ms) * 1_000_000.0).round() as u64;
708    DUAL_PP_STAGE_NS[stage].fetch_add(ns, Ordering::Relaxed);
709    DUAL_PP_STAGE_SAMPLES[stage].fetch_add(1, Ordering::Relaxed);
710}
711
712/// Timing is diagnostic only: a CUDA event that is not ready (or otherwise fails) must not
713/// change decode control flow. Count and warn once, then leave the scored-path result intact.
714pub(crate) fn record_dual_pp_timing_drop(context: &str, err: &dyn std::fmt::Display) {
715    let previous = DUAL_PP_TIMING_DROPPED.fetch_add(1, Ordering::Relaxed);
716    if previous == 0 {
717        eprintln!(
718            "[dual-pp] WARN: skipped diagnostic timing sample at {context}: {err}; decode continues"
719        );
720    }
721}
722
723pub(crate) fn record_dual_pp_stage_result<E: std::fmt::Display>(
724    stage: usize,
725    elapsed: Result<f32, E>,
726) {
727    match elapsed {
728        Ok(ms) => record_dual_pp_stage_ms(stage, ms),
729        Err(err) => record_dual_pp_timing_drop(DUAL_PP_STAGE_NAMES[stage], &err),
730    }
731}
732
733pub fn dual_pp_timing_dropped() -> usize {
734    DUAL_PP_TIMING_DROPPED.load(Ordering::Relaxed)
735}
736
737/// `(total_nanoseconds, samples)` for wave-A stage0/stage1 then wave-B stage0/stage1.
738pub fn dual_pp_timing_snapshot() -> ([u64; 4], [usize; 4]) {
739    (
740        std::array::from_fn(|i| DUAL_PP_STAGE_NS[i].load(Ordering::Relaxed)),
741        std::array::from_fn(|i| DUAL_PP_STAGE_SAMPLES[i].load(Ordering::Relaxed)),
742    )
743}
744
745pub(crate) struct DualPpStageGuard;
746
747pub(crate) fn enter_dual_pp_stage() -> DualPpStageGuard {
748    let active = DUAL_PP_ACTIVE_STAGES.fetch_add(1, Ordering::AcqRel);
749    if active > 0 {
750        DUAL_PP_OVERLAPS.fetch_add(1, Ordering::Relaxed);
751    }
752    DualPpStageGuard
753}
754
755impl Drop for DualPpStageGuard {
756    fn drop(&mut self) {
757        let active = DUAL_PP_ACTIVE_STAGES.fetch_sub(1, Ordering::AcqRel);
758        debug_assert!(active > 0, "dual PP active-stage counter underflow");
759    }
760}
761
762/// MEMRA_PRIME_PP=0: rollback/A-B seam for the PRIME (chunked prefill) stage split
763/// (lane/pp-leverb 2026-08-08). Default ON — with the ppN door open the chunked prime takes
764/// its own per-stage range walk exactly as the eager/batched/verify steps do. Setting 0 sends
765/// prime back through the unsplit whole-trunk walk. NOTE: unlike batch/dc/graph/spec, prime
766/// keeps NO `refuse_unsplit_if_remote` — its unsplit walk over a sharded placement is the
767/// measured 22% amortized peer-read tax (research/pp-prefill-20260807 anatomy: m=4096
768/// amortizes the weight reads), not the decode 28x cliff, and the unsplit walk IS the
769/// split-vs-unsplit gate's reference arm (`prime-split-gate`), so it must stay callable.
770/// Read per call, never memoized (the gate A/Bs both arms in one process).
771pub fn prime_pp_on() -> bool {
772    std::env::var("MEMRA_PRIME_PP").as_deref() != Ok("0")
773}
774
775/// MEMRA_PRIME_PIPE=0: rollback/A-B seam for the PP-2 PRIME CHUNK PIPELINE
776/// (lane/cx-pipeline-prime 2026-08-08). Default ON when the prime stage split is live;
777/// setting 0 keeps the serial per-chunk stage walk. Read per prime call so the exactness
778/// gate can replay both schedules against one loaded model.
779pub fn prime_pipe_on() -> bool {
780    std::env::var("MEMRA_PRIME_PIPE").as_deref() != Ok("0")
781}
782
783/// SPLIT-LIVENESS COUNTER for the prime stage split: bumped ONCE per prime chunk that
784/// actually executed the per-stage walk. The `prime-split-gate` requires this to ADVANCE
785/// during its split arm — bit-identity of two identical UNSPLIT walks is vacuous, so a gate
786/// that only compared bits would go green while the walker doesn't exist. With the counter,
787/// the gate is RED until the walker lands (the tickinv35 pattern: the gate exists and fails
788/// before the mechanism does). Relaxed ordering: single-threaded host issue, count-only.
789pub static PRIME_SPLIT_CHUNKS: AtomicUsize = AtomicUsize::new(0);
790
791/// Read the split-liveness counter (gate-side).
792pub fn prime_split_chunks() -> usize {
793    PRIME_SPLIT_CHUNKS.load(Ordering::Relaxed)
794}
795
796/// PIPELINE-LIVENESS COUNTER: bumped only when a second PP-2 prime stage enters its layer
797/// walker while the other stage's walker is still active. Step's per-layer router readback
798/// synchronizes the host, so enqueue order alone is not liveness: a single host thread can
799/// call stage 0(N+1) before the stage-1 epilogue and still serialize all trunk computation.
800pub static PRIME_PIPE_OVERLAPS: AtomicUsize = AtomicUsize::new(0);
801
802/// Read the prime-pipeline overlap counter (gate-side).
803pub fn prime_pipe_overlaps() -> usize {
804    PRIME_PIPE_OVERLAPS.load(Ordering::Relaxed)
805}
806
807static PRIME_PIPE_ACTIVE_STAGES: AtomicUsize = AtomicUsize::new(0);
808
809pub(crate) struct PrimePipeStageGuard;
810
811/// Mark one host-driven stage walker active. With PP-2, a transition 1 -> 2 proves the
812/// two device walkers overlap in wall time; exactly one transition is counted per pair.
813pub(crate) fn enter_prime_pipe_stage() -> PrimePipeStageGuard {
814    let active = PRIME_PIPE_ACTIVE_STAGES.fetch_add(1, Ordering::AcqRel);
815    if active > 0 {
816        PRIME_PIPE_OVERLAPS.fetch_add(1, Ordering::Relaxed);
817    }
818    PrimePipeStageGuard
819}
820
821impl Drop for PrimePipeStageGuard {
822    fn drop(&mut self) {
823        let active = PRIME_PIPE_ACTIVE_STAGES.fetch_sub(1, Ordering::AcqRel);
824        debug_assert!(active > 0, "prime pipeline active-stage counter underflow");
825    }
826}
827
828/// Step35 cross-request prime liveness counters (lane/cx-prime-batch, 2026-08-08).
829/// The exactness gate requires BOTH to advance: a successful step35 batch alone is not
830/// sufficient under PP-N if it walked the whole sharded trunk on one stream.
831pub static STEP35_PRIME_BATCHES: AtomicUsize = AtomicUsize::new(0);
832pub static STEP35_PRIME_BATCH_SPLITS: AtomicUsize = AtomicUsize::new(0);
833
834pub fn step35_prime_batches() -> usize {
835    STEP35_PRIME_BATCHES.load(Ordering::Relaxed)
836}
837
838pub fn step35_prime_batch_splits() -> usize {
839    STEP35_PRIME_BATCH_SPLITS.load(Ordering::Relaxed)
840}
841
842/// MEMRA_SPEC_PP=0: rollback/A-B seam for the SPEC VERIFY stage split (pp2-spec 2026-08-06).
843/// Default ON — with the ppN door open the verify forward (`decode_step_t_core_ppn`) takes its
844/// own stage split exactly as the eager and batched steps do. Setting 0 sends verify back through
845/// the unsplit trunk walk, which under a sharded cross-device placement is then caught by
846/// `refuse_unsplit_if_remote` (the 28x peer-read regime) rather than running silently. Exists so
847/// the bit-identity gate can A/B split vs unsplit IN ONE PROCESS against the same loaded weights
848/// — read per verify call, never memoized, for that reason.
849pub fn spec_pp_on() -> bool {
850    std::env::var("MEMRA_SPEC_PP").as_deref() != Ok("0")
851}
852
853/// MEMRA_PP_OVERLAP: alternate the double-buffered boundary slots per step (the
854/// pipelining seed). Scheduling structure only, never math. Read per step so gates can
855/// A/B in-process.
856///
857/// Unset follows the dual-PP mode (owner flip 2026-08-11): `Auto` resolves ON — the naked
858/// serve path is the box1 re-gate's dual arm (MEMRA_DUAL_PP=1 MEMRA_PP_OVERLAP=1,
859/// 929/929 golden, 0/9123 slot collisions). `Off` resolves OFF so MEMRA_DUAL_PP=0 alone
860/// restores the exact pre-flip serial naked path. `Forced` resolves OFF so the binding
861/// single-slot refusal of the explicit pre-flip request stays reachable — the
862/// decode-batch-gate negative cell pins and asserts precisely that combination.
863pub fn pp2_overlap() -> bool {
864    pp2_overlap_resolve(
865        std::env::var("MEMRA_PP_OVERLAP").ok().as_deref(),
866        dual_pp_mode(),
867    )
868}
869
870/// Pure resolution for MEMRA_PP_OVERLAP, split from the env read for the flip
871/// regression tests.
872pub fn pp2_overlap_resolve(v: Option<&str>, mode: DualPpMode) -> bool {
873    match v {
874        Some("1") => true,
875        Some(_) => false,
876        None => mode == DualPpMode::Auto,
877    }
878}
879
880/// Broken-peer escape hatch: stage-boundary activations travel through page-locked host
881/// memory instead of `cudaMemcpyPeerAsync`. Default OFF; captured when `PpNRt` is built.
882pub fn pp_host_bounce_on() -> bool {
883    matches!(std::env::var("MEMRA_PP_HOST_BOUNCE").as_deref(), Ok("1"))
884}
885
886/// True when host bounce is the live transport for a sharded cross-device placement.
887/// Callers use this to close paths that still peer-read non-boundary state.
888pub fn pp_host_bounce_active() -> bool {
889    (pp_host_bounce_on() || PEER_RUNTIME_HOST_BOUNCE.load(Ordering::Acquire))
890        && pp_sharded_cross_device()
891}
892
893/// M2 increment 2 rollback seam: MEMRA_PP_SHARD=0 = the M1 bring-up placement (all
894/// weights upload through the primary engine; remote stages peer-read). Default ON —
895/// under MEMRA_PP_DEVICES each stage's layer range uploads through its own engine.
896pub fn pp_shard_off() -> bool {
897    matches!(std::env::var("MEMRA_PP_SHARD").as_deref(), Ok("0"))
898}
899
900/// Raw `MEMRA_PP_DEVICES` (parsed/validated at PpNRt build — a bad string must fail the
901/// decode step loudly, never silently fall back to same-device and fake a gate PASS).
902fn pp2_devices_env() -> Option<String> {
903    std::env::var("MEMRA_PP_DEVICES")
904        .ok()
905        .filter(|v| !v.is_empty())
906}
907
908static WARNED_BAD: AtomicBool = AtomicBool::new(false);
909fn warn_bad_once(msg: &str) {
910    if !WARNED_BAD.swap(true, Ordering::Relaxed) {
911        eprintln!("[pp] {msg}");
912    }
913}
914
915static WARNED_UNWIRED: AtomicBool = AtomicBool::new(false);
916/// One-time notice when the door is set but the executing path has no pp arm
917/// (M2 wires the generic eager decode at any N and the gemma4 eager arm at N=2).
918pub fn warn_unwired_once(path: &str) {
919    let open = std::env::var("MEMRA_PP_STAGES")
920        .map(|v| !v.is_empty() && v != "0" && v != "1")
921        .unwrap_or(false);
922    if open && !WARNED_UNWIRED.swap(true, Ordering::Relaxed) {
923        eprintln!("[pp] MEMRA_PP_STAGES set but `{path}` has no pp arm at this N; running unsplit");
924    }
925}
926
927// ======================================================================================
928//  PpNRt: the M2 transport runtime (per-stage streams, per-boundary events + slots)
929// ======================================================================================
930
931/// One pipeline stage's execution home: device, context, launch stream, and (for a stage
932/// remote to the primary engine's device) a dedicated Engine in that device's primary
933/// context (CUmodules are per-context).
934pub struct StageRt {
935    pub dev: usize,
936    pub ctx: Arc<CudaContext>,
937    pub stream: Arc<CudaStream>,
938    pub blas: Arc<cudarc::cublaslt::CudaBlasLT>,
939    /// `Some` only when `dev` differs from the primary engine's device.
940    engine: Option<Engine>,
941}
942
943/// One boundary slot: a persistent RX-side buffer + its TX/RX completion events.
944/// PERSISTENT because the buffer is written by the TX stage's stream and read by the RX
945/// stage's: a per-step alloc/free would enqueue the free on ONE stream while the other
946/// might still be reading (the cross-stream free hazard) — a never-freed slot cannot race.
947struct BoundarySlot {
948    buf: Mutex<Option<CudaSlice<f32>>>,
949    /// Recorded on the TX stage's stream after the TX copy; RX waits on it. Created in
950    /// the TX stage's context (cuEventRecord requires event ctx == stream ctx).
951    ev_tx: CudaEvent,
952    /// Recorded on the RX stage's stream after the RX copy; the NEXT TX into this slot
953    /// waits on it (write-after-read guard). Created in the RX stage's context. Waiting
954    /// on a never-recorded event is a defined no-op, so step 0 needs no special case.
955    ev_rx: CudaEvent,
956}
957
958/// Boundary b sits between stage b (TX) and stage b+1 (RX). Two slots, alternating per
959/// step under MEMRA_PP_OVERLAP=1 (each boundary counts its own steps — a decode step
960/// crosses every boundary exactly once, so the counters stay in lockstep).
961struct BoundaryRt {
962    slots: [BoundarySlot; 2],
963    step: AtomicUsize,
964    /// true iff stage b and stage b+1 live on different devices (peer transport).
965    cross: bool,
966}
967
968#[derive(Clone, Copy, Debug, PartialEq, Eq)]
969enum BoundaryTransport {
970    Local,
971    Peer,
972    HostBounce,
973}
974
975#[derive(Clone, Copy)]
976struct BoundaryPath {
977    boundary: usize,
978    src_stage: usize,
979    dst_stage: usize,
980    transport: BoundaryTransport,
981}
982
983fn boundary_transport(cross: bool, host_bounce: bool) -> BoundaryTransport {
984    match (cross, host_bounce) {
985        (false, _) => BoundaryTransport::Local,
986        (true, false) => BoundaryTransport::Peer,
987        (true, true) => BoundaryTransport::HostBounce,
988    }
989}
990
991const PEER_PROBE_FIXED_BYTES: usize = 16 * 1024;
992const PEER_PROBE_TOKEN_WIDTHS: [usize; 4] = [1, 8, 16, crate::cache::PRIME_CHUNK_MAX_TOKENS];
993
994/// Native cross-device boundary copies between low-frequency runtime integrity probes.
995/// Fixed rather than operator-tunable: this is a safety gate, not a performance experiment.
996pub const PEER_RUNTIME_PROBE_INTERVAL_COPIES: u64 = 8 * 1024;
997/// One complete runtime width rotation. The maximum-chunk rung runs once per cycle.
998pub const PEER_RUNTIME_PROBE_CYCLE_COPIES: u64 =
999    PEER_RUNTIME_PROBE_INTERVAL_COPIES * PEER_PROBE_TOKEN_WIDTHS.len() as u64;
1000/// Consecutive runnable probe intervals that may be blocked by live speculative UVA state before
1001/// integrity coverage becomes explicitly degraded. Four intervals are one full width rotation.
1002pub const PEER_RUNTIME_PROBE_DEFERRAL_BOUND_INTERVALS: u64 = PEER_PROBE_TOKEN_WIDTHS.len() as u64;
1003/// Maximum measured owner-thread wall cost that may remain on an interactive scheduler boundary.
1004const PEER_RUNTIME_PROBE_BUDGET_NS: u64 = 5_000_000;
1005
1006pub const PEER_PROBE_REQUIRED_REFUSAL: &str = "PP bring-up refused: MEMRA_PEER_PROBE=0 cannot authorize native peer transport for a \
1007     sharded cross-device placement while MEMRA_PP_HOST_BOUNCE!=1; leave MEMRA_PEER_PROBE \
1008     enabled or set MEMRA_PP_HOST_BOUNCE=1";
1009
1010#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1011pub enum PeerProbeStartupPolicy {
1012    Allowed,
1013    BypassedWithHostBounce,
1014}
1015
1016/// Pure startup policy so unit tests and kernel-check pin the entire refusal matrix without
1017/// mutating process-global environment variables.
1018pub fn peer_probe_startup_policy(
1019    probe_on: bool,
1020    sharded_cross_device: bool,
1021    host_bounce: bool,
1022) -> Result<PeerProbeStartupPolicy, &'static str> {
1023    match (probe_on, sharded_cross_device, host_bounce) {
1024        (false, true, false) => Err(PEER_PROBE_REQUIRED_REFUSAL),
1025        (false, true, true) => Ok(PeerProbeStartupPolicy::BypassedWithHostBounce),
1026        _ => Ok(PeerProbeStartupPolicy::Allowed),
1027    }
1028}
1029
1030static PEER_PROBE_BYPASSED: AtomicU64 = AtomicU64::new(0);
1031static PEER_BOUNDARY_COPIES: AtomicU64 = AtomicU64::new(0);
1032static PEER_RUNTIME_PROBES: AtomicU64 = AtomicU64::new(0);
1033static PEER_RUNTIME_PROBE_FAILURES: AtomicU64 = AtomicU64::new(0);
1034static PEER_RUNTIME_PROBE_DEFERRED: AtomicU64 = AtomicU64::new(0);
1035static PEER_RUNTIME_PROBE_INTEGRITY_DEGRADED: AtomicBool = AtomicBool::new(false);
1036static PEER_RUNTIME_PROBE_FAILED: AtomicBool = AtomicBool::new(false);
1037static PEER_RUNTIME_HOST_BOUNCE: AtomicBool = AtomicBool::new(false);
1038static PEER_RUNTIME_NEXT_PROBE_COPY: [AtomicU64; PEER_PROBE_TOKEN_WIDTHS.len()] = [
1039    AtomicU64::new(PEER_RUNTIME_PROBE_INTERVAL_COPIES),
1040    AtomicU64::new(2 * PEER_RUNTIME_PROBE_INTERVAL_COPIES),
1041    AtomicU64::new(3 * PEER_RUNTIME_PROBE_INTERVAL_COPIES),
1042    AtomicU64::new(4 * PEER_RUNTIME_PROBE_INTERVAL_COPIES),
1043];
1044static PEER_RUNTIME_PROBE_MAX_COST_NS: [AtomicU64; PEER_PROBE_TOKEN_WIDTHS.len()] = [
1045    AtomicU64::new(0),
1046    AtomicU64::new(0),
1047    AtomicU64::new(0),
1048    AtomicU64::new(0),
1049];
1050
1051#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1052pub struct PeerProbeMetrics {
1053    pub bypassed: u64,
1054    pub boundary_copies: u64,
1055    pub runtime_probes: u64,
1056    pub runtime_failures: u64,
1057    pub deferred_total: u64,
1058    pub integrity_degraded: bool,
1059    pub degraded_to_host_bounce: bool,
1060}
1061
1062pub fn peer_probe_metrics() -> PeerProbeMetrics {
1063    PeerProbeMetrics {
1064        bypassed: PEER_PROBE_BYPASSED.load(Ordering::Relaxed),
1065        boundary_copies: PEER_BOUNDARY_COPIES.load(Ordering::Relaxed),
1066        runtime_probes: PEER_RUNTIME_PROBES.load(Ordering::Relaxed),
1067        runtime_failures: PEER_RUNTIME_PROBE_FAILURES.load(Ordering::Relaxed),
1068        deferred_total: PEER_RUNTIME_PROBE_DEFERRED.load(Ordering::Relaxed),
1069        integrity_degraded: PEER_RUNTIME_PROBE_INTEGRITY_DEGRADED.load(Ordering::Acquire),
1070        degraded_to_host_bounce: PEER_RUNTIME_HOST_BOUNCE.load(Ordering::Acquire),
1071    }
1072}
1073
1074#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1075pub enum RuntimePeerProbeStatus {
1076    NotRun,
1077    Deferred,
1078    Passed,
1079    DegradedToHostBounce,
1080}
1081
1082impl RuntimePeerProbeStatus {
1083    pub fn ran(self) -> bool {
1084        matches!(self, Self::Passed | Self::DegradedToHostBounce)
1085    }
1086}
1087
1088fn publish_runtime_peer_probe_deferral(
1089    deferred_total: &AtomicU64,
1090    integrity_degraded: &AtomicBool,
1091    intervals: u64,
1092    bound_reached: bool,
1093) {
1094    deferred_total.fetch_add(intervals, Ordering::Relaxed);
1095    if bound_reached {
1096        integrity_degraded.store(true, Ordering::Release);
1097    }
1098}
1099
1100/// Publish newly observed copy-count intervals where a runnable peer probe was blocked by live
1101/// speculative UVA state. The worker coalesces scheduler polls before calling this function.
1102pub fn record_runtime_peer_probe_deferral(intervals: u64, bound_reached: bool) {
1103    publish_runtime_peer_probe_deferral(
1104        &PEER_RUNTIME_PROBE_DEFERRED,
1105        &PEER_RUNTIME_PROBE_INTEGRITY_DEGRADED,
1106        intervals,
1107        bound_reached,
1108    );
1109}
1110
1111/// A completed native probe or validated transport failover restores an explicit integrity state.
1112pub fn clear_runtime_peer_probe_integrity_degraded() {
1113    PEER_RUNTIME_PROBE_INTEGRITY_DEGRADED.store(false, Ordering::Release);
1114}
1115
1116fn runtime_peer_probe_idle_only(width_index: usize, measured_cost_ns: u64) -> bool {
1117    width_index + 1 == PEER_PROBE_TOKEN_WIDTHS.len()
1118        || measured_cost_ns > PEER_RUNTIME_PROBE_BUDGET_NS
1119}
1120
1121/// Pick the oldest runnable per-width deadline. Idle-only overdue work is skipped rather than
1122/// blocking later cheap deadlines, so the small integrity ladder keeps its copy-count cadence.
1123fn runtime_peer_probe_candidate(
1124    copies: u64,
1125    next_probe_copy: [u64; PEER_PROBE_TOKEN_WIDTHS.len()],
1126    measured_cost_ns: [u64; PEER_PROBE_TOKEN_WIDTHS.len()],
1127    scheduler_idle: bool,
1128) -> Option<(usize, usize)> {
1129    let mut selected: Option<(usize, u64)> = None;
1130    for width_index in 0..PEER_PROBE_TOKEN_WIDTHS.len() {
1131        let due = next_probe_copy[width_index];
1132        if copies < due
1133            || (!scheduler_idle
1134                && runtime_peer_probe_idle_only(width_index, measured_cost_ns[width_index]))
1135        {
1136            continue;
1137        }
1138        if selected.is_none_or(|(_, selected_due)| due < selected_due) {
1139            selected = Some((width_index, due));
1140        }
1141    }
1142    selected.map(|(width_index, _)| (width_index, PEER_PROBE_TOKEN_WIDTHS[width_index]))
1143}
1144
1145/// Advance a late per-width deadline to the first future cycle. Missed idle opportunities
1146/// collapse into one probe instead of producing an owner-thread catch-up burst.
1147fn runtime_peer_probe_next_copy(due: u64, copies: u64) -> u64 {
1148    let cycles = copies.saturating_sub(due) / PEER_RUNTIME_PROBE_CYCLE_COPIES + 1;
1149    due.saturating_add(PEER_RUNTIME_PROBE_CYCLE_COPIES.saturating_mul(cycles))
1150}
1151
1152/// Fail closed before arming the fallback, then publish host bounce only after its staging check
1153/// succeeds. The two atomics are parameters so unit tests never mutate process-global state.
1154fn latch_runtime_host_bounce<E>(
1155    native_failed: &AtomicBool,
1156    degraded_to_host_bounce: &AtomicBool,
1157    arm_and_validate: impl FnOnce() -> Result<(), E>,
1158) -> Result<(), E> {
1159    native_failed.store(true, Ordering::Release);
1160    arm_and_validate()?;
1161    degraded_to_host_bounce.store(true, Ordering::Release);
1162    Ok(())
1163}
1164
1165fn peer_probe_on() -> bool {
1166    std::env::var("MEMRA_PEER_PROBE").as_deref() != Ok("0")
1167}
1168
1169#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1170enum PeerProbeDecision {
1171    Clean,
1172    ProceedWithHostBounce { mismatches: usize },
1173}
1174
1175fn peer_probe_mismatch_count(expected: &[u8], readback: &[u8]) -> usize {
1176    expected
1177        .iter()
1178        .zip(readback)
1179        .filter(|(a, b)| a != b)
1180        .count()
1181        + expected.len().abs_diff(readback.len())
1182}
1183
1184fn peer_probe_decision(
1185    expected: &[u8],
1186    readback: &[u8],
1187    host_bounce: bool,
1188) -> Result<PeerProbeDecision, String> {
1189    let mismatches = peer_probe_mismatch_count(expected, readback);
1190    if mismatches == 0 {
1191        Ok(PeerProbeDecision::Clean)
1192    } else if host_bounce {
1193        Ok(PeerProbeDecision::ProceedWithHostBounce { mismatches })
1194    } else {
1195        Err(format!("{mismatches} mismatched byte(s)"))
1196    }
1197}
1198
1199fn peer_probe_pattern(bytes: usize, boundary: usize, src_dev: usize, dst_dev: usize) -> Vec<u8> {
1200    let mut state = 0xD1B5_4A32_D192_ED03u64
1201        ^ (bytes as u64).rotate_left(7)
1202        ^ (boundary as u64).rotate_left(19)
1203        ^ (src_dev as u64).rotate_left(31)
1204        ^ (dst_dev as u64).rotate_left(43);
1205    (0..bytes)
1206        .map(|_| {
1207            state ^= state << 13;
1208            state ^= state >> 7;
1209            state ^= state << 17;
1210            state as u8
1211        })
1212        .collect()
1213}
1214
1215fn peer_probe_bytes_to_f32(bytes: &[u8]) -> Vec<f32> {
1216    assert_eq!(bytes.len() % std::mem::size_of::<f32>(), 0);
1217    bytes
1218        .chunks_exact(std::mem::size_of::<f32>())
1219        .map(|chunk| f32::from_bits(u32::from_ne_bytes(chunk.try_into().unwrap())))
1220        .collect()
1221}
1222
1223fn peer_probe_f32_to_bytes(values: &[f32]) -> Vec<u8> {
1224    values
1225        .iter()
1226        .flat_map(|value| value.to_bits().to_ne_bytes())
1227        .collect()
1228}
1229
1230/// A legacy `cuMemAlloc` buffer used only by the boot probe. Unlike memra's normal
1231/// stream-ordered allocations, it becomes peer-visible through `cuCtxEnablePeerAccess`
1232/// without requiring the default-pool grants that deliberately happen after the probe.
1233struct PeerProbeBuffer {
1234    ctx: Arc<CudaContext>,
1235    ptr: cudarc::driver::sys::CUdeviceptr,
1236}
1237
1238impl PeerProbeBuffer {
1239    fn new(ctx: &Arc<CudaContext>, bytes: usize) -> Result<Self, Box<dyn std::error::Error>> {
1240        ctx.bind_to_thread()?;
1241        let ptr = unsafe { cudarc::driver::result::malloc_sync(bytes)? };
1242        Ok(Self {
1243            ctx: ctx.clone(),
1244            ptr,
1245        })
1246    }
1247}
1248
1249impl Drop for PeerProbeBuffer {
1250    fn drop(&mut self) {
1251        if self.ctx.bind_to_thread().is_ok() {
1252            let _ = unsafe { cudarc::driver::result::free_sync(self.ptr) };
1253        }
1254    }
1255}
1256
1257fn peer_probe_copy(
1258    src: &StageRt,
1259    dst: &StageRt,
1260    expected: &[u8],
1261) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
1262    let bytes = expected.len();
1263    let src_buf = PeerProbeBuffer::new(&src.ctx, bytes)?;
1264    unsafe {
1265        cudarc::driver::result::memcpy_htod_sync(src_buf.ptr, expected)?;
1266    }
1267
1268    let dst_buf = PeerProbeBuffer::new(&dst.ctx, bytes)?;
1269    let poison: Vec<u8> = expected.iter().map(|b| !b).collect();
1270    unsafe {
1271        cudarc::driver::result::memcpy_htod_sync(dst_buf.ptr, &poison)?;
1272    }
1273
1274    src.ctx.bind_to_thread()?;
1275    unsafe {
1276        cudarc::driver::result::memcpy_peer_async(
1277            dst.ctx.cu_ctx(),
1278            dst_buf.ptr,
1279            src.ctx.cu_ctx(),
1280            src_buf.ptr,
1281            bytes,
1282            src.stream.cu_stream(),
1283        )?;
1284    }
1285
1286    // Publish the peer write to the receiving context exactly like the live BoundarySlot
1287    // transport does. A host-side synchronize of only the TX stream is not the production
1288    // cross-context visibility contract; the RX stream waits on a TX event before touching the
1289    // destination allocation. Keeping the integrity probe on that same ordering path avoids
1290    // diagnosing an intentionally unordered destination-context read as fabric corruption.
1291    let published = src.ctx.new_event(None)?;
1292    published.record(&src.stream)?;
1293
1294    dst.ctx.bind_to_thread()?;
1295    dst.stream.wait(&published)?;
1296    dst.stream.synchronize()?;
1297    let mut readback = vec![0u8; bytes];
1298    unsafe {
1299        cudarc::driver::result::memcpy_dtoh_sync(&mut readback, dst_buf.ptr)?;
1300    }
1301    Ok(readback)
1302}
1303
1304fn run_peer_probe_pass(
1305    stages: &[StageRt],
1306    peer_capable: &[(usize, usize)],
1307    host_bounce: bool,
1308    label: &str,
1309    bytes: usize,
1310) -> Result<(), Box<dyn std::error::Error>> {
1311    if bytes == 0 {
1312        return Err(format!("PP peer byte-integrity probe {label} size is zero").into());
1313    }
1314    let started = std::time::Instant::now();
1315    let mut copies = 0usize;
1316    let mut skipped = 0usize;
1317    let mut total_mismatches = 0usize;
1318
1319    for boundary in 0..stages.len() - 1 {
1320        if stages[boundary].dev == stages[boundary + 1].dev {
1321            continue;
1322        }
1323        for (src_idx, dst_idx) in [(boundary, boundary + 1), (boundary + 1, boundary)] {
1324            let src = &stages[src_idx];
1325            let dst = &stages[dst_idx];
1326            if !peer_capable.contains(&(src.dev, dst.dev)) {
1327                if host_bounce {
1328                    skipped += 1;
1329                    eprintln!(
1330                        "[pp] peer byte-integrity probe SKIP: boundary={boundary} \
1331                         dev{}->dev{} label={label} bytes={bytes} (peer capability unavailable; \
1332                         MEMRA_PP_HOST_BOUNCE=1 remains fail-safe)",
1333                        src.dev, dst.dev,
1334                    );
1335                    continue;
1336                }
1337                return Err(format!(
1338                    "PP peer byte-integrity probe cannot run boundary={boundary} \
1339                     dev{}->dev{}: peer access was not enabled",
1340                    src.dev, dst.dev,
1341                )
1342                .into());
1343            }
1344
1345            let expected = peer_probe_pattern(bytes, boundary, src.dev, dst.dev);
1346            let readback = match peer_probe_copy(src, dst, &expected) {
1347                Ok(readback) => readback,
1348                Err(err) if host_bounce => {
1349                    skipped += 1;
1350                    eprintln!(
1351                        "[pp] peer byte-integrity probe ERROR: boundary={boundary} \
1352                         dev{}->dev{} label={label} bytes={bytes}: {err}; \
1353                         MEMRA_PP_HOST_BOUNCE=1, proceeding on the host-staged path",
1354                        src.dev, dst.dev,
1355                    );
1356                    continue;
1357                }
1358                Err(err) => {
1359                    return Err(format!(
1360                        "PP peer byte-integrity probe FAILED: boundary={boundary} \
1361                         dev{}->dev{} label={label} bytes={bytes}: {err}; refusing native P2P \
1362                         (set MEMRA_PP_HOST_BOUNCE=1 to use the host-staged path; \
1363                         MEMRA_PEER_PROBE=0 cannot authorize sharded native peer transport)",
1364                        src.dev, dst.dev,
1365                    )
1366                    .into());
1367                }
1368            };
1369            copies += 1;
1370            match peer_probe_decision(&expected, &readback, host_bounce) {
1371                Ok(PeerProbeDecision::Clean) => {}
1372                Ok(PeerProbeDecision::ProceedWithHostBounce { mismatches }) => {
1373                    total_mismatches += mismatches;
1374                    eprintln!(
1375                        "[pp] peer byte-integrity probe CORRUPTION: boundary={boundary} \
1376                         dev{}->dev{} label={label} bytes={bytes} mismatches={mismatches}; \
1377                         MEMRA_PP_HOST_BOUNCE=1, proceeding on the host-staged path",
1378                        src.dev, dst.dev,
1379                    );
1380                }
1381                Err(mismatch) => {
1382                    return Err(format!(
1383                        "PP peer byte-integrity probe FAILED: boundary={boundary} \
1384                         dev{}->dev{} label={label} bytes={bytes}: {mismatch}; refusing native \
1385                         P2P (set MEMRA_PP_HOST_BOUNCE=1 to use the host-staged path; \
1386                         MEMRA_PEER_PROBE=0 cannot authorize sharded native peer transport)",
1387                        src.dev, dst.dev,
1388                    )
1389                    .into());
1390                }
1391            }
1392        }
1393    }
1394
1395    let status = if total_mismatches > 0 {
1396        "BOUNCE"
1397    } else if skipped > 0 && copies > 0 {
1398        "PARTIAL"
1399    } else if skipped > 0 {
1400        "SKIP"
1401    } else {
1402        "PASS"
1403    };
1404    eprintln!(
1405        "[pp] peer byte-integrity probe {}: label={label} bytes={bytes} copies={copies} \
1406         skipped={skipped} mismatches={total_mismatches} elapsed_ms={:.3}",
1407        status,
1408        started.elapsed().as_secs_f64() * 1e3,
1409    );
1410    Ok(())
1411}
1412
1413fn host_bounce_capacity(n_embd: usize) -> Result<(usize, usize), String> {
1414    if n_embd == 0 {
1415        return Err("MEMRA_PP_HOST_BOUNCE needs non-zero model n_embd".into());
1416    }
1417    let elems = n_embd
1418        .checked_mul(crate::cache::PRIME_CHUNK_MAX_TOKENS)
1419        .ok_or_else(|| format!("host-bounce element count overflows for n_embd={n_embd}"))?;
1420    let bytes = elems
1421        .checked_mul(std::mem::size_of::<f32>())
1422        .ok_or_else(|| format!("host-bounce byte count overflows for n_embd={n_embd}"))?;
1423    Ok((elems, bytes))
1424}
1425
1426fn boundary_slot_growth_elements(current: [usize; 2], required: usize) -> usize {
1427    current.into_iter().fold(0usize, |total, len| {
1428        total.saturating_add(required.saturating_sub(len))
1429    })
1430}
1431
1432/// One bidirectional-DMA staging allocation. `CU_MEMHOSTALLOC_PORTABLE` matters here: the
1433/// D2H producer and H2D consumer are in distinct CUDA primary contexts. Cacheable memory is
1434/// intentional (rather than cudarc's write-combined pinned slice) because this allocation is
1435/// the destination of D2H as well as the source of H2D.
1436struct PinnedHostBounce {
1437    ptr: *mut f32,
1438    len: usize,
1439}
1440
1441unsafe impl Send for PinnedHostBounce {}
1442unsafe impl Sync for PinnedHostBounce {}
1443
1444impl PinnedHostBounce {
1445    fn new(len: usize) -> Result<Self, Box<dyn std::error::Error>> {
1446        let bytes = len
1447            .checked_mul(std::mem::size_of::<f32>())
1448            .ok_or("host-bounce pinned allocation size overflow")?;
1449        let ptr = unsafe {
1450            cudarc::driver::result::malloc_host(
1451                bytes,
1452                cudarc::driver::sys::CU_MEMHOSTALLOC_PORTABLE,
1453            )?
1454        } as *mut f32;
1455        if ptr.is_null() {
1456            return Err("cuMemHostAlloc returned a null host-bounce pointer".into());
1457        }
1458        Ok(Self { ptr, len })
1459    }
1460
1461    fn prefix(&self, n: usize) -> &[f32] {
1462        assert!(
1463            n <= self.len,
1464            "host-bounce source {n} > capacity {}",
1465            self.len
1466        );
1467        unsafe { std::slice::from_raw_parts(self.ptr, n) }
1468    }
1469
1470    fn prefix_mut(&mut self, n: usize) -> &mut [f32] {
1471        assert!(
1472            n <= self.len,
1473            "host-bounce destination {n} > capacity {}",
1474            self.len
1475        );
1476        unsafe { std::slice::from_raw_parts_mut(self.ptr, n) }
1477    }
1478}
1479
1480impl Drop for PinnedHostBounce {
1481    fn drop(&mut self) {
1482        let _ = unsafe { cudarc::driver::result::free_host(self.ptr.cast()) };
1483    }
1484}
1485
1486struct HostBounceRt {
1487    n_embd: usize,
1488    capacity: usize,
1489    slots: Vec<Option<[Mutex<PinnedHostBounce>; 2]>>,
1490}
1491
1492impl HostBounceRt {
1493    fn new(n_embd: usize, boundaries: &[BoundaryRt]) -> Result<Self, Box<dyn std::error::Error>> {
1494        let (capacity, _) = host_bounce_capacity(n_embd)?;
1495        let mut slots = Vec::with_capacity(boundaries.len());
1496        for boundary in boundaries {
1497            slots.push(if boundary.cross {
1498                Some([
1499                    Mutex::new(PinnedHostBounce::new(capacity)?),
1500                    Mutex::new(PinnedHostBounce::new(capacity)?),
1501                ])
1502            } else {
1503                None
1504            });
1505        }
1506        Ok(Self {
1507            n_embd,
1508            capacity,
1509            slots,
1510        })
1511    }
1512
1513    fn slot(
1514        &self,
1515        boundary: usize,
1516        slot: usize,
1517    ) -> Result<&Mutex<PinnedHostBounce>, Box<dyn std::error::Error>> {
1518        self.slots
1519            .get(boundary)
1520            .and_then(Option::as_ref)
1521            .and_then(|slots| slots.get(slot))
1522            .ok_or_else(|| format!("host-bounce slot {boundary}:{slot} is not initialized").into())
1523    }
1524}
1525
1526pub struct PpNRt {
1527    stages: Vec<StageRt>,
1528    boundaries: Vec<BoundaryRt>,
1529    /// Whole-walk ownership for the shared boundary slot/event sequence. Boundary-local atomics
1530    /// choose alternating slots but cannot distinguish two interleaved callers; one generation
1531    /// lease therefore spans entry fencing through final publication/result collection.
1532    walk_active: Arc<AtomicU64>,
1533    walk_next: AtomicU64,
1534    /// A deferred decode window intentionally owns several in-flight logits tickets. The weak
1535    /// reference lets consecutive enqueue calls on the same CUDA-owner thread join that window;
1536    /// the active generation is released only after the final `PendingLogits` is drained/dropped.
1537    deferred_walk: Mutex<Weak<PpWalkState>>,
1538    /// true iff ANY boundary crosses devices.
1539    cross_any: bool,
1540    /// Startup selection captured at runtime construction. A runtime probe failure may promote
1541    /// the process-wide one-way host-bounce latch without mutating this value.
1542    host_bounce: bool,
1543    /// Boot-time peer validation is default-on; `MEMRA_PEER_PROBE=0` is diagnostics-only.
1544    peer_probe: bool,
1545    /// Directed device pairs for which `cuDeviceCanAccessPeer` succeeded.
1546    peer_capable: Vec<(usize, usize)>,
1547    /// Sticky one-time model-width probe result. The value is the one-row geometry byte count.
1548    peer_probe_geometry: OnceLock<Result<usize, String>>,
1549    /// Lazily allocated after the authoritative model width is known at cache creation.
1550    bounce: OnceLock<Result<HostBounceRt, String>>,
1551    /// Dedicated readback stream in the LAST stage's context (deferred logits D2H —
1552    /// waiting there instead of on the compute stream keeps later tokens enqueuable).
1553    readback: Arc<CudaStream>,
1554}
1555
1556#[derive(Debug)]
1557struct PpWalkState {
1558    active: Arc<AtomicU64>,
1559    generation: u64,
1560    runtime_id: usize,
1561    deferred_owner: Option<std::thread::ThreadId>,
1562}
1563
1564impl PpWalkState {
1565    fn is_active(&self) -> bool {
1566        self.active.load(Ordering::Acquire) == self.generation
1567    }
1568}
1569
1570impl Drop for PpWalkState {
1571    fn drop(&mut self) {
1572        let _ =
1573            self.active
1574                .compare_exchange(self.generation, 0, Ordering::AcqRel, Ordering::Acquire);
1575    }
1576}
1577
1578/// Opaque lifetime token for one complete PP boundary walk. Clones are allowed only through
1579/// the same-thread deferred enqueue window; the active generation clears when the final clone
1580/// is dropped.
1581#[derive(Debug)]
1582pub struct PpWalkLease {
1583    state: Arc<PpWalkState>,
1584}
1585
1586fn next_pp_walk_generation(next: &AtomicU64) -> u64 {
1587    loop {
1588        let generation = next.fetch_add(1, Ordering::Relaxed);
1589        if generation != 0 {
1590            return generation;
1591        }
1592    }
1593}
1594
1595fn acquire_pp_walk(
1596    active: &Arc<AtomicU64>,
1597    next: &AtomicU64,
1598    runtime_id: usize,
1599    deferred_owner: Option<std::thread::ThreadId>,
1600    path: &str,
1601) -> Result<PpWalkLease, String> {
1602    let generation = next_pp_walk_generation(next);
1603    active
1604        .compare_exchange(0, generation, Ordering::AcqRel, Ordering::Acquire)
1605        .map_err(|_| {
1606            format!(
1607                "{path}: refused concurrent PP walk; shared boundary slots already have an owner"
1608            )
1609        })?;
1610    Ok(PpWalkLease {
1611        state: Arc::new(PpWalkState {
1612            active: active.clone(),
1613            generation,
1614            runtime_id,
1615            deferred_owner,
1616        }),
1617    })
1618}
1619
1620fn lock_deferred_walk<'a>(
1621    deferred: &'a Mutex<Weak<PpWalkState>>,
1622    path: &str,
1623) -> Result<std::sync::MutexGuard<'a, Weak<PpWalkState>>, String> {
1624    deferred
1625        .lock()
1626        .map_err(|_| format!("{path}: deferred PP walk owner lock is poisoned"))
1627}
1628
1629fn validate_walk_state(state: &PpWalkState, runtime_id: usize, path: &str) -> Result<(), String> {
1630    if state.runtime_id != runtime_id {
1631        return Err(format!(
1632            "{path}: PP walk permit belongs to a different runtime"
1633        ));
1634    }
1635    if !state.is_active() {
1636        return Err(format!(
1637            "{path}: PP walk permit generation is no longer active"
1638        ));
1639    }
1640    Ok(())
1641}
1642
1643/// M1 name kept alive for external callers (`pp-transport-smoke`, receipts, docs).
1644pub type Pp2Rt = PpNRt;
1645
1646static RTN: OnceLock<Result<PpNRt, String>> = OnceLock::new();
1647
1648impl PpNRt {
1649    /// The process-wide transport runtime, built on first use against the primary engine.
1650    /// The stage count + device map freeze at first build (one config per process — gates
1651    /// run one placement per invocation). Build errors are sticky and loud.
1652    pub fn get(e: &Engine) -> Result<&'static PpNRt, Box<dyn std::error::Error>> {
1653        RTN.get_or_init(|| Self::build(e).map_err(|err| err.to_string()))
1654            .as_ref()
1655            .map_err(|s| -> Box<dyn std::error::Error> { s.clone().into() })
1656    }
1657
1658    fn build(e: &Engine) -> Result<PpNRt, Box<dyn std::error::Error>> {
1659        // Validate the experimental PP3/PP4 door at runtime construction so an invalid value is a
1660        // boot refusal, never a silently-disabled serving policy discovered on the first request.
1661        pp_wave_on().map_err(|reason| -> Box<dyn std::error::Error> { reason.into() })?;
1662        let primary_dev = e.ctx().ordinal();
1663        // Stage count: MEMRA_PP_DEVICES length wins when set (it IS the placement);
1664        // else MEMRA_PP_STAGES; else 2 (the M1 default — pp-transport-smoke runs doorless).
1665        let devices: Vec<usize> =
1666            match pp2_devices_env() {
1667                Some(s) => {
1668                    let parts: Result<Vec<usize>, _> =
1669                        s.split(',').map(|p| p.trim().parse::<usize>()).collect();
1670                    match parts {
1671                        Ok(v) if v.len() >= 2 => v,
1672                        _ => return Err(format!(
1673                            "MEMRA_PP_DEVICES={s} unparseable (want <d0>,..,<dN-1> e.g. 0,1,2,3)"
1674                        )
1675                        .into()),
1676                    }
1677                }
1678                None => {
1679                    let n_st = std::env::var("MEMRA_PP_STAGES")
1680                        .ok()
1681                        .and_then(|v| v.parse::<usize>().ok())
1682                        .filter(|&n| n >= 2)
1683                        .unwrap_or(2);
1684                    vec![primary_dev; n_st]
1685                }
1686            };
1687        if let Ok(v) = std::env::var("MEMRA_PP_STAGES")
1688            && let Ok(n) = v.parse::<usize>()
1689            && n >= 2
1690            && n != devices.len()
1691        {
1692            return Err(format!(
1693                "MEMRA_PP_DEVICES lists {} devices but MEMRA_PP_STAGES={n} — \
1694                         refusing an ambiguous placement",
1695                devices.len()
1696            )
1697            .into());
1698        }
1699        let n_st = devices.len();
1700        let cross_any = devices.iter().any(|&d| d != devices[0]);
1701        let host_bounce = pp_host_bounce_on();
1702        let peer_probe = peer_probe_on();
1703        let sharded_cross_device = cross_any && !pp_shard_off();
1704        if host_bounce && cross_any {
1705            if pp_shard_off() {
1706                return Err(
1707                    "MEMRA_PP_HOST_BOUNCE=1 refuses MEMRA_PP_SHARD=0: the boundary can bounce, \
1708                     but remote stages would still peer-read primary-device weights"
1709                        .into(),
1710                );
1711            }
1712            if devices.last().copied() != Some(primary_dev) {
1713                return Err(format!(
1714                    "MEMRA_PP_HOST_BOUNCE=1 requires the primary engine on the last/head stage \
1715                     (primary dev{primary_dev}, placement {devices:?}); otherwise returned \
1716                     logits/hidden state remain peer reads"
1717                )
1718                .into());
1719            }
1720        }
1721        let peer_probe_policy =
1722            peer_probe_startup_policy(peer_probe, sharded_cross_device, host_bounce)?;
1723        if peer_probe_policy == PeerProbeStartupPolicy::BypassedWithHostBounce {
1724            PEER_PROBE_BYPASSED.fetch_add(1, Ordering::Relaxed);
1725            eprintln!(
1726                "[pp] SECURITY RED: peer_probe_bypassed: MEMRA_PEER_PROBE=0 on a sharded \
1727                 cross-device placement; MEMRA_PP_HOST_BOUNCE=1 is the only enabled transport"
1728            );
1729        }
1730
1731        // Validate every placement ordinal in both transports. Native peer transport requires
1732        // access both ways. Host bounce remains usable without it, but records any capable pairs
1733        // so the byte probe can still diagnose a lying peer path before selecting the fallback.
1734        let mut used: Vec<usize> = devices.clone();
1735        used.push(primary_dev);
1736        used.sort_unstable();
1737        used.dedup();
1738        let mut peer_capable = Vec::new();
1739        if used.len() > 1 {
1740            let n = cudarc::driver::result::device::get_count()? as usize;
1741            for &d in &used {
1742                if d >= n {
1743                    return Err(format!(
1744                        "MEMRA_PP_DEVICES={devices:?} but only {n} CUDA device(s) present"
1745                    )
1746                    .into());
1747                }
1748            }
1749            if !host_bounce || peer_probe {
1750                for &a in &used {
1751                    for &b in &used {
1752                        if a == b {
1753                            continue;
1754                        }
1755                        let da = cudarc::driver::result::device::get(a as i32)?;
1756                        let db = cudarc::driver::result::device::get(b as i32)?;
1757                        let mut can: i32 = 0;
1758                        let capability = unsafe {
1759                            cudarc::driver::sys::cuDeviceCanAccessPeer(&mut can, da, db).result()
1760                        };
1761                        if let Err(err) = capability {
1762                            if host_bounce {
1763                                eprintln!(
1764                                    "[pp] peer byte-integrity probe capability query failed for \
1765                                     dev{a}->dev{b}: {err}; MEMRA_PP_HOST_BOUNCE=1 remains active"
1766                                );
1767                                continue;
1768                            }
1769                            return Err(err.into());
1770                        }
1771                        if can == 0 {
1772                            if !host_bounce {
1773                                return Err(format!(
1774                                    "device {a} cannot peer-access device {b} \
1775                                     (cuDeviceCanAccessPeer=0); ppN cross-device needs P2P — \
1776                                     refusing a silently-staged path"
1777                                )
1778                                .into());
1779                            }
1780                        } else {
1781                            peer_capable.push((a, b));
1782                        }
1783                    }
1784                }
1785            }
1786        }
1787
1788        // PER-STAGE ENGINE ISOLATION (2026-08-02 singledev pipelined find): Engine owns
1789        // lazily-grown SHARED scratch pools (fa_part_pool, fa_vf16_scratch, argmax
1790        // partials, ...) that are stable-pointer by design — safe on one stream, a data
1791        // race the moment two stage streams run concurrently through the SAME Engine
1792        // (deferred readback, >=2 tokens in flight: token t+1's stage-0 fa memsets the
1793        // partials while token t's stage-s fa still reads them — the nondeterministic
1794        // all-logits divergence; cross-device arms were immune because remote stages
1795        // already got their own Engine). Every stage s>0 gets its OWN Engine even on the
1796        // primary device: same CUcontext (primary retain), so the per-context CUmodule
1797        // cache makes it cheap; scratch pools are per-Engine, so stages never share.
1798        // Stage 0 keeps the primary engine (single-threaded host issue: the only
1799        // concurrent user of `e` during a pp walk is stage 0 itself).
1800        let mk_stage = |dev: usize, s: usize| -> Result<StageRt, Box<dyn std::error::Error>> {
1801            if dev == primary_dev && s == 0 {
1802                let ctx = e.ctx().clone();
1803                let stream = ctx.new_stream()?;
1804                let blas = Arc::new(cudarc::cublaslt::CudaBlasLT::new(stream.clone())?);
1805                Ok(StageRt {
1806                    dev,
1807                    ctx,
1808                    stream,
1809                    blas,
1810                    engine: None,
1811                })
1812            } else {
1813                let eng = Engine::new(dev)?;
1814                let ctx = eng.ctx().clone();
1815                let stream = ctx.new_stream()?;
1816                let blas = Arc::new(cudarc::cublaslt::CudaBlasLT::new(stream.clone())?);
1817                Ok(StageRt {
1818                    dev,
1819                    ctx,
1820                    stream,
1821                    blas,
1822                    engine: Some(eng),
1823                })
1824            }
1825        };
1826        let mut stages = Vec::with_capacity(n_st);
1827        for (s, &d) in devices.iter().enumerate() {
1828            stages.push(mk_stage(d, s)?);
1829        }
1830
1831        if cross_any
1832            && !peer_probe
1833            && peer_probe_policy != PeerProbeStartupPolicy::BypassedWithHostBounce
1834        {
1835            eprintln!(
1836                "[pp] WARNING: MEMRA_PEER_PROBE=0 skips the boot-time peer byte-integrity \
1837                 gate; diagnostics escape hatch active"
1838            );
1839        }
1840
1841        if used.len() > 1 {
1842            if !host_bounce {
1843                // A context per distinct device (first stage that lives there; the primary's
1844                // context for the primary device).
1845                let ctx_of = |d: usize| -> &Arc<CudaContext> {
1846                    if d == primary_dev {
1847                        e.ctx()
1848                    } else {
1849                        &stages.iter().find(|s| s.dev == d).unwrap().ctx
1850                    }
1851                };
1852                // Enable peer access BOTH ways for every distinct pair (idempotent;
1853                // ALREADY_ENABLED is success).
1854                for &a in &used {
1855                    for &b in &used {
1856                        if a == b {
1857                            continue;
1858                        }
1859                        ctx_of(a).bind_to_thread()?;
1860                        let rc = unsafe {
1861                            cudarc::driver::sys::cuCtxEnablePeerAccess(ctx_of(b).cu_ctx(), 0)
1862                        };
1863                        use cudarc::driver::sys::cudaError_enum as E;
1864                        if rc != E::CUDA_SUCCESS && rc != E::CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED
1865                        {
1866                            return Err(format!(
1867                                "cuCtxEnablePeerAccess(dev{a} -> dev{b}) failed: {rc:?}"
1868                            )
1869                            .into());
1870                        }
1871                    }
1872                }
1873                // The fixed-size byte gate runs immediately after peer enable and before pool
1874                // grants. Legacy allocations make it exercise the exact `cuMemcpyPeerAsync` API
1875                // without depending on the pool setup that follows.
1876                if peer_probe && cross_any {
1877                    let probe = run_peer_probe_pass(
1878                        &stages,
1879                        &peer_capable,
1880                        host_bounce,
1881                        "fixed-16KiB",
1882                        PEER_PROBE_FIXED_BYTES,
1883                    );
1884                    e.ctx().bind_to_thread()?;
1885                    probe?;
1886                }
1887                // MEM-POOL access grant (8x box 2026-08-02, M1 cross-device fix #2):
1888                // cuCtxEnablePeerAccess does NOT map STREAM-ORDERED POOL allocations, and every
1889                // engine buffer/weight goes through the device default pool (cuMemAllocAsync via
1890                // cudarc; memra-runtime configures that pool). A stage kernel dereferencing
1891                // another device's weights — or a boundary peer TX writing the RX slot — needs
1892                // cuMemPoolSetAccess on the OWNING device's default pool for the ACCESSING
1893                // device; without it the first remote dereference is CUDA_ERROR_ILLEGAL_ADDRESS
1894                // (reported at the next API call in the poisoned context). Grant all pairs.
1895                for &owner in &used {
1896                    for &accessor in &used {
1897                        if owner == accessor {
1898                            continue;
1899                        }
1900                        let dev = cudarc::driver::result::device::get(owner as i32)?;
1901                        let mut pool: cudarc::driver::sys::CUmemoryPool = std::ptr::null_mut();
1902                        unsafe {
1903                            cudarc::driver::sys::cuDeviceGetDefaultMemPool(&mut pool, dev)
1904                                .result()?;
1905                        }
1906                        let desc = cudarc::driver::sys::CUmemAccessDesc {
1907                        location: cudarc::driver::sys::CUmemLocation {
1908                            type_: cudarc::driver::sys::CUmemLocationType::CU_MEM_LOCATION_TYPE_DEVICE,
1909                            id: accessor as i32,
1910                        },
1911                        flags: cudarc::driver::sys::CUmemAccess_flags::CU_MEM_ACCESS_FLAGS_PROT_READWRITE,
1912                    };
1913                        let rc = unsafe { cudarc::driver::sys::cuMemPoolSetAccess(pool, &desc, 1) };
1914                        if rc != cudarc::driver::sys::cudaError_enum::CUDA_SUCCESS {
1915                            return Err(format!(
1916                            "cuMemPoolSetAccess(dev{owner} pool -> dev{accessor}) failed: {rc:?}"
1917                        )
1918                        .into());
1919                        }
1920                    }
1921                }
1922                // MEM-POOL access grant (8x box 2026-08-02, cross-device fix #2):
1923                // cuCtxEnablePeerAccess does NOT map STREAM-ORDERED POOL allocations, and every
1924                // engine buffer/weight goes through the device default pool (cuMemAllocAsync via
1925                // cudarc; memra-runtime configures that pool). A stage-1 kernel dereferencing
1926                // dev0 weights — or the stage-0 peer TX writing dev1's RX slot — needs
1927                // cuMemPoolSetAccess on the OWNING device's default pool for the ACCESSING
1928                // device; without it the first remote dereference is CUDA_ERROR_ILLEGAL_ADDRESS
1929                // (reported at the next API call in the poisoned context). Grant both ways.
1930                for (owner, accessor) in [
1931                    (stages[0].dev, stages[1].dev),
1932                    (stages[1].dev, stages[0].dev),
1933                ] {
1934                    let dev = cudarc::driver::result::device::get(owner as i32)?;
1935                    let mut pool: cudarc::driver::sys::CUmemoryPool = std::ptr::null_mut();
1936                    unsafe {
1937                        cudarc::driver::sys::cuDeviceGetDefaultMemPool(&mut pool, dev).result()?;
1938                    }
1939                    let desc = cudarc::driver::sys::CUmemAccessDesc {
1940                    location: cudarc::driver::sys::CUmemLocation {
1941                        type_: cudarc::driver::sys::CUmemLocationType::CU_MEM_LOCATION_TYPE_DEVICE,
1942                        id: accessor as i32,
1943                    },
1944                    flags: cudarc::driver::sys::CUmemAccess_flags::CU_MEM_ACCESS_FLAGS_PROT_READWRITE,
1945                };
1946                    let rc = unsafe { cudarc::driver::sys::cuMemPoolSetAccess(pool, &desc, 1) };
1947                    if rc != cudarc::driver::sys::cudaError_enum::CUDA_SUCCESS {
1948                        return Err(format!(
1949                            "cuMemPoolSetAccess(dev{owner} pool -> dev{accessor}) failed: {rc:?}"
1950                        )
1951                        .into());
1952                    }
1953                }
1954                // restore the primary context for the caller's subsequent work
1955                e.ctx().bind_to_thread()?;
1956                eprintln!(
1957                    "[pp] cross-device transport: {} (cudaMemcpyPeerAsync per cross boundary; \
1958                 peer + default-pool access granted all pairs over {used:?}; weight home: {})",
1959                    devices
1960                        .iter()
1961                        .enumerate()
1962                        .map(|(s, d)| format!("stage{s}=dev{d}"))
1963                        .collect::<Vec<_>>()
1964                        .join(" "),
1965                    if pp_shard_off() {
1966                        format!("dev{primary_dev} (MEMRA_PP_SHARD=0 bring-up placement)")
1967                    } else {
1968                        "per-stage (sharded loader)".to_string()
1969                    }
1970                );
1971            } else {
1972                e.ctx().bind_to_thread()?;
1973                eprintln!(
1974                    "[pp] cross-device transport: {} (HOST-STAGED pinned D2H -> H2D per cross \
1975                     boundary; MEMRA_PP_HOST_BOUNCE=1; peer-pool grants bypassed; \
1976                     diagnostic peer access is removed before host-staged serving; \
1977                     weight home: per-stage (sharded loader))",
1978                    devices
1979                        .iter()
1980                        .enumerate()
1981                        .map(|(s, d)| format!("stage{s}=dev{d}"))
1982                        .collect::<Vec<_>>()
1983                        .join(" "),
1984                );
1985            }
1986        }
1987
1988        let mk_slot =
1989            |tx: &StageRt, rx: &StageRt| -> Result<BoundarySlot, Box<dyn std::error::Error>> {
1990                Ok(BoundarySlot {
1991                    buf: Mutex::new(None),
1992                    ev_tx: tx.ctx.new_event(None)?,
1993                    ev_rx: rx.ctx.new_event(None)?,
1994                })
1995            };
1996        let mut boundaries = Vec::with_capacity(n_st - 1);
1997        for b in 0..n_st - 1 {
1998            let (tx, rx) = (&stages[b], &stages[b + 1]);
1999            boundaries.push(BoundaryRt {
2000                slots: [mk_slot(tx, rx)?, mk_slot(tx, rx)?],
2001                step: AtomicUsize::new(0),
2002                cross: tx.dev != rx.dev,
2003            });
2004        }
2005        let readback = stages[n_st - 1].ctx.new_stream()?;
2006        let rt = PpNRt {
2007            stages,
2008            boundaries,
2009            walk_active: Arc::new(AtomicU64::new(0)),
2010            walk_next: AtomicU64::new(1),
2011            deferred_walk: Mutex::new(Weak::new()),
2012            cross_any,
2013            host_bounce,
2014            peer_probe,
2015            peer_capable,
2016            peer_probe_geometry: OnceLock::new(),
2017            bounce: OnceLock::new(),
2018            readback,
2019        };
2020        if rt.peer_probe && rt.cross_any && rt.host_bounce {
2021            rt.run_host_bounce_legacy_probe(e)?;
2022        }
2023        Ok(rt)
2024    }
2025
2026    pub fn n_stages(&self) -> usize {
2027        self.stages.len()
2028    }
2029
2030    /// Acquire exclusive ownership of the PP boundary/event sequence for one complete model walk.
2031    /// Fail fast rather than blocking; merely running on the original thread is not authority.
2032    pub fn acquire_walk(
2033        &'static self,
2034        path: &str,
2035    ) -> Result<PpWalkLease, Box<dyn std::error::Error>> {
2036        let runtime_id = self as *const Self as usize;
2037        acquire_pp_walk(&self.walk_active, &self.walk_next, runtime_id, None, path)
2038            .map_err(|error| -> Box<dyn std::error::Error> { error.into() })
2039    }
2040
2041    /// Join the one intentional multi-enqueue deferred window. Only the thread that opened the
2042    /// window may add work; unrelated callers still fail fast while any pending result exists.
2043    pub(crate) fn acquire_deferred_walk(
2044        &'static self,
2045        path: &str,
2046    ) -> Result<PpWalkLease, Box<dyn std::error::Error>> {
2047        let runtime_id = self as *const Self as usize;
2048        let current_thread = std::thread::current().id();
2049        let mut weak = lock_deferred_walk(&self.deferred_walk, path)
2050            .map_err(|error| -> Box<dyn std::error::Error> { error.into() })?;
2051        if let Some(state) = weak.upgrade() {
2052            validate_walk_state(&state, runtime_id, path)
2053                .map_err(|error| -> Box<dyn std::error::Error> { error.into() })?;
2054            if state.deferred_owner.as_ref() != Some(&current_thread) {
2055                return Err(format!(
2056                    "{path}: refused cross-thread join of the active deferred PP window"
2057                )
2058                .into());
2059            }
2060            return Ok(PpWalkLease { state });
2061        }
2062        let lease = acquire_pp_walk(
2063            &self.walk_active,
2064            &self.walk_next,
2065            runtime_id,
2066            Some(current_thread),
2067            path,
2068        )
2069        .map_err(|error| -> Box<dyn std::error::Error> { error.into() })?;
2070        *weak = Arc::downgrade(&lease.state);
2071        Ok(lease)
2072    }
2073
2074    /// True iff any boundary crosses devices.
2075    pub fn cross_device(&self) -> bool {
2076        self.cross_any
2077    }
2078
2079    pub fn host_bounce_active(&self) -> bool {
2080        self.host_bounce || PEER_RUNTIME_HOST_BOUNCE.load(Ordering::Acquire)
2081    }
2082
2083    /// Actual stage placement frozen when this runtime was built. Environment strings may be
2084    /// mutated by in-process gates later and are not authoritative for scheduler safety.
2085    pub fn repeated_stage_device(&self) -> bool {
2086        let mut devices: Vec<_> = self.stages.iter().map(|stage| stage.dev).collect();
2087        devices.sort_unstable();
2088        devices.dedup();
2089        devices.len() != self.stages.len()
2090    }
2091
2092    fn context_for_dev<'a>(
2093        &'a self,
2094        e: &'a Engine,
2095        dev: usize,
2096    ) -> Result<&'a Arc<CudaContext>, Box<dyn std::error::Error>> {
2097        if dev == e.ctx().ordinal() {
2098            return Ok(e.ctx());
2099        }
2100        self.stages
2101            .iter()
2102            .find(|stage| stage.dev == dev)
2103            .map(|stage| &stage.ctx)
2104            .ok_or_else(|| format!("PP peer probe has no CUDA context for dev{dev}").into())
2105    }
2106
2107    fn enable_probe_peer_access(
2108        &self,
2109        e: &Engine,
2110        pairs: &[(usize, usize)],
2111    ) -> Result<Vec<(usize, usize)>, Box<dyn std::error::Error>> {
2112        let mut enabled = Vec::new();
2113        for &(src_dev, dst_dev) in pairs {
2114            let enable = (|| -> Result<(), Box<dyn std::error::Error>> {
2115                let src_ctx = self.context_for_dev(e, src_dev)?;
2116                let dst_ctx = self.context_for_dev(e, dst_dev)?;
2117                src_ctx.bind_to_thread()?;
2118                let rc = unsafe { cudarc::driver::sys::cuCtxEnablePeerAccess(dst_ctx.cu_ctx(), 0) };
2119                use cudarc::driver::sys::cudaError_enum as E;
2120                if rc == E::CUDA_SUCCESS || rc == E::CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED {
2121                    Ok(())
2122                } else {
2123                    Err(format!("{rc:?}").into())
2124                }
2125            })();
2126            if let Err(err) = enable {
2127                eprintln!(
2128                    "[pp] peer byte-integrity probe could not enable \
2129                     dev{src_dev}->dev{dst_dev}: {err}; MEMRA_PP_HOST_BOUNCE=1 remains active"
2130                );
2131            } else {
2132                enabled.push((src_dev, dst_dev));
2133            }
2134        }
2135        Ok(enabled)
2136    }
2137
2138    fn disable_probe_peer_access(
2139        &self,
2140        e: &Engine,
2141        pairs: &[(usize, usize)],
2142    ) -> Result<(), Box<dyn std::error::Error>> {
2143        let mut failures = Vec::new();
2144        for &(src_dev, dst_dev) in pairs {
2145            let disable = (|| -> Result<(), Box<dyn std::error::Error>> {
2146                let src_ctx = self.context_for_dev(e, src_dev)?;
2147                let dst_ctx = self.context_for_dev(e, dst_dev)?;
2148                src_ctx.bind_to_thread()?;
2149                let rc = unsafe { cudarc::driver::sys::cuCtxDisablePeerAccess(dst_ctx.cu_ctx()) };
2150                use cudarc::driver::sys::cudaError_enum as E;
2151                if rc == E::CUDA_SUCCESS || rc == E::CUDA_ERROR_PEER_ACCESS_NOT_ENABLED {
2152                    Ok(())
2153                } else {
2154                    Err(format!("{rc:?}").into())
2155                }
2156            })();
2157            if let Err(err) = disable {
2158                failures.push(format!("dev{src_dev}->dev{dst_dev}: {err}"));
2159            }
2160        }
2161        e.ctx().bind_to_thread()?;
2162        if failures.is_empty() {
2163            eprintln!(
2164                "[pp] peer byte-integrity probe teardown: disabled {} diagnostic pair(s); \
2165                 host-bounce serving has no probe-enabled peer access",
2166                pairs.len(),
2167            );
2168            Ok(())
2169        } else {
2170            Err(format!(
2171                "PP peer probe could not disable diagnostic peer access ({}); \
2172                 refusing host-bounce serving",
2173                failures.join(", "),
2174            )
2175            .into())
2176        }
2177    }
2178
2179    fn grant_probe_pool_access(
2180        &self,
2181        e: &Engine,
2182        pairs: &[(usize, usize)],
2183    ) -> Result<Vec<(usize, usize)>, Box<dyn std::error::Error>> {
2184        let mut granted = Vec::new();
2185        for &(src_dev, dst_dev) in pairs {
2186            let grant = (|| -> Result<(), Box<dyn std::error::Error>> {
2187                self.context_for_dev(e, dst_dev)?.bind_to_thread()?;
2188                let dev = cudarc::driver::result::device::get(dst_dev as i32)?;
2189                let mut pool: cudarc::driver::sys::CUmemoryPool = std::ptr::null_mut();
2190                unsafe {
2191                    cudarc::driver::sys::cuDeviceGetDefaultMemPool(&mut pool, dev).result()?;
2192                }
2193                let desc = cudarc::driver::sys::CUmemAccessDesc {
2194                    location: cudarc::driver::sys::CUmemLocation {
2195                        type_: cudarc::driver::sys::CUmemLocationType::CU_MEM_LOCATION_TYPE_DEVICE,
2196                        id: src_dev as i32,
2197                    },
2198                    flags:
2199                        cudarc::driver::sys::CUmemAccess_flags::CU_MEM_ACCESS_FLAGS_PROT_READWRITE,
2200                };
2201                let rc = unsafe { cudarc::driver::sys::cuMemPoolSetAccess(pool, &desc, 1) };
2202                if rc == cudarc::driver::sys::cudaError_enum::CUDA_SUCCESS {
2203                    Ok(())
2204                } else {
2205                    Err(format!("{rc:?}").into())
2206                }
2207            })();
2208            if let Err(err) = grant {
2209                eprintln!(
2210                    "[pp] production-slot probe could not grant dev{src_dev} access to \
2211                     dev{dst_dev}'s default pool: {err}; MEMRA_PP_HOST_BOUNCE=1 remains active"
2212                );
2213            } else {
2214                granted.push((src_dev, dst_dev));
2215            }
2216        }
2217        Ok(granted)
2218    }
2219
2220    fn revoke_probe_pool_access(
2221        &self,
2222        e: &Engine,
2223        pairs: &[(usize, usize)],
2224    ) -> Result<(), Box<dyn std::error::Error>> {
2225        let mut failures = Vec::new();
2226        for &(src_dev, dst_dev) in pairs {
2227            let revoke = (|| -> Result<(), Box<dyn std::error::Error>> {
2228                self.context_for_dev(e, dst_dev)?.bind_to_thread()?;
2229                let dev = cudarc::driver::result::device::get(dst_dev as i32)?;
2230                let mut pool: cudarc::driver::sys::CUmemoryPool = std::ptr::null_mut();
2231                unsafe {
2232                    cudarc::driver::sys::cuDeviceGetDefaultMemPool(&mut pool, dev).result()?;
2233                }
2234                let desc = cudarc::driver::sys::CUmemAccessDesc {
2235                    location: cudarc::driver::sys::CUmemLocation {
2236                        type_: cudarc::driver::sys::CUmemLocationType::CU_MEM_LOCATION_TYPE_DEVICE,
2237                        id: src_dev as i32,
2238                    },
2239                    flags: cudarc::driver::sys::CUmemAccess_flags::CU_MEM_ACCESS_FLAGS_PROT_NONE,
2240                };
2241                let rc = unsafe { cudarc::driver::sys::cuMemPoolSetAccess(pool, &desc, 1) };
2242                if rc == cudarc::driver::sys::cudaError_enum::CUDA_SUCCESS {
2243                    Ok(())
2244                } else {
2245                    Err(format!("{rc:?}").into())
2246                }
2247            })();
2248            if let Err(err) = revoke {
2249                failures.push(format!("dev{src_dev}->dev{dst_dev}: {err}"));
2250            }
2251        }
2252        e.ctx().bind_to_thread()?;
2253        if failures.is_empty() {
2254            Ok(())
2255        } else {
2256            Err(format!(
2257                "PP peer probe could not revoke diagnostic pool access ({}); \
2258                 refusing host-bounce serving",
2259                failures.join(", "),
2260            )
2261            .into())
2262        }
2263    }
2264
2265    fn run_host_bounce_legacy_probe(&self, e: &Engine) -> Result<(), Box<dyn std::error::Error>> {
2266        let enabled = self.enable_probe_peer_access(e, &self.peer_capable)?;
2267        let probe = run_peer_probe_pass(
2268            &self.stages,
2269            &enabled,
2270            true,
2271            "fixed-16KiB-legacy-preflight",
2272            PEER_PROBE_FIXED_BYTES,
2273        );
2274        let disable = self.disable_probe_peer_access(e, &enabled);
2275        disable?;
2276        probe
2277    }
2278
2279    fn new_peer_probe_boundary(
2280        &self,
2281        src_stage: usize,
2282        dst_stage: usize,
2283    ) -> Result<BoundaryRt, Box<dyn std::error::Error>> {
2284        let tx = &self.stages[src_stage];
2285        let rx = &self.stages[dst_stage];
2286        let mk_slot = || -> Result<BoundarySlot, Box<dyn std::error::Error>> {
2287            Ok(BoundarySlot {
2288                buf: Mutex::new(None),
2289                ev_tx: tx.ctx.new_event(None)?,
2290                ev_rx: rx.ctx.new_event(None)?,
2291            })
2292        };
2293        Ok(BoundaryRt {
2294            slots: [mk_slot()?, mk_slot()?],
2295            step: AtomicUsize::new(0),
2296            cross: tx.dev != rx.dev,
2297        })
2298    }
2299
2300    fn production_probe_readback(
2301        &self,
2302        path: BoundaryPath,
2303        boundary: &BoundaryRt,
2304        expected: &[u8],
2305        n: usize,
2306        slot_idx: usize,
2307    ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
2308        debug_assert_eq!(expected.len(), n * std::mem::size_of::<f32>());
2309        let host = peer_probe_bytes_to_f32(expected);
2310        let poison_bytes: Vec<u8> = expected.iter().map(|byte| !byte).collect();
2311        let poison = peer_probe_bytes_to_f32(&poison_bytes);
2312        let src = &self.stages[path.src_stage];
2313        let dst = &self.stages[path.dst_stage];
2314
2315        // Pre-poison the exact stream-ordered BoundarySlot allocation so a missing or partial
2316        // peer write cannot accidentally agree where the deterministic source contains zeroes.
2317        dst.ctx.bind_to_thread()?;
2318        let poison_buf = dst.stream.clone_htod(&poison)?;
2319        dst.stream.synchronize()?;
2320        let replaced = boundary.slots[slot_idx]
2321            .buf
2322            .lock()
2323            .unwrap()
2324            .replace(poison_buf);
2325        drop(replaced);
2326        dst.stream.synchronize()?;
2327
2328        src.ctx.bind_to_thread()?;
2329        let x = src.stream.clone_htod(&host)?;
2330        self.tx_slot_path(path, boundary, &x, n, slot_idx)?;
2331
2332        dst.ctx.bind_to_thread()?;
2333        let work = self.rx_slot_path(path, boundary, slot_idx, n)?;
2334        let back = dst.stream.clone_dtoh(&work)?;
2335        dst.stream.synchronize()?;
2336        Ok(peer_probe_f32_to_bytes(&back))
2337    }
2338
2339    fn clear_peer_probe_boundary(
2340        &self,
2341        boundary: &BoundaryRt,
2342        src_stage: usize,
2343        dst_stage: usize,
2344    ) -> Result<(), Box<dyn std::error::Error>> {
2345        self.stages[dst_stage].ctx.bind_to_thread()?;
2346        for slot in &boundary.slots {
2347            let buffer = slot.buf.lock().unwrap().take();
2348            drop(buffer);
2349        }
2350        self.stages[src_stage].stream.synchronize()?;
2351        self.stages[dst_stage].stream.synchronize()?;
2352        Ok(())
2353    }
2354
2355    fn run_production_peer_probe_widths(
2356        &self,
2357        enabled_pairs: &[(usize, usize)],
2358        host_bounce: bool,
2359        n_embd: usize,
2360        widths: &[usize],
2361    ) -> Result<(), Box<dyn std::error::Error>> {
2362        let started = std::time::Instant::now();
2363        let mut copies = 0usize;
2364        let mut skipped = 0usize;
2365        let mut total_mismatches = 0usize;
2366        let mut largest_clean_payload = 0usize;
2367
2368        for boundary_idx in 0..self.stages.len() - 1 {
2369            if self.stages[boundary_idx].dev == self.stages[boundary_idx + 1].dev {
2370                continue;
2371            }
2372            for (src_stage, dst_stage) in [
2373                (boundary_idx, boundary_idx + 1),
2374                (boundary_idx + 1, boundary_idx),
2375            ] {
2376                let src_dev = self.stages[src_stage].dev;
2377                let dst_dev = self.stages[dst_stage].dev;
2378                if !enabled_pairs.contains(&(src_dev, dst_dev)) {
2379                    if host_bounce {
2380                        skipped += widths.len();
2381                        eprintln!(
2382                            "[pp] production-slot peer probe SKIP: boundary={boundary_idx} \
2383                             dev{src_dev}->dev{dst_dev} widths_tokens={:?} \
2384                             (peer or pool access unavailable; MEMRA_PP_HOST_BOUNCE=1 remains \
2385                             fail-safe)",
2386                            widths,
2387                        );
2388                        continue;
2389                    }
2390                    return Err(format!(
2391                        "PP production-slot peer probe cannot run boundary={boundary_idx} \
2392                         dev{src_dev}->dev{dst_dev}: peer/pool access is not enabled"
2393                    )
2394                    .into());
2395                }
2396
2397                let probe_boundary = self.new_peer_probe_boundary(src_stage, dst_stage)?;
2398                let path = BoundaryPath {
2399                    boundary: boundary_idx,
2400                    src_stage,
2401                    dst_stage,
2402                    transport: BoundaryTransport::Peer,
2403                };
2404                let mut direction_copies = 0usize;
2405                let mut direction_skipped = 0usize;
2406                let mut direction_mismatches = 0usize;
2407                let mut direction_largest_clean = 0usize;
2408                let mut failure = None;
2409
2410                for (width_idx, tokens) in widths.iter().copied().enumerate() {
2411                    let n = n_embd.checked_mul(tokens).ok_or_else(|| {
2412                        format!(
2413                            "PP production-slot probe element count overflows for \
2414                             n_embd={n_embd} tokens={tokens}"
2415                        )
2416                    })?;
2417                    let bytes = n.checked_mul(std::mem::size_of::<f32>()).ok_or_else(|| {
2418                        format!(
2419                            "PP production-slot probe byte count overflows for \
2420                             n_embd={n_embd} tokens={tokens}"
2421                        )
2422                    })?;
2423                    let expected = peer_probe_pattern(bytes, boundary_idx, src_dev, dst_dev);
2424                    let readback = match self.production_probe_readback(
2425                        path,
2426                        &probe_boundary,
2427                        &expected,
2428                        n,
2429                        width_idx % 2,
2430                    ) {
2431                        Ok(readback) => readback,
2432                        Err(err) if host_bounce => {
2433                            skipped += 1;
2434                            direction_skipped += 1;
2435                            eprintln!(
2436                                "[pp] production-slot peer probe ERROR: \
2437                                 boundary={boundary_idx} dev{src_dev}->dev{dst_dev} \
2438                                 tokens={tokens} bytes={bytes}: {err}; \
2439                                 MEMRA_PP_HOST_BOUNCE=1, proceeding on the host-staged path"
2440                            );
2441                            continue;
2442                        }
2443                        Err(err) => {
2444                            failure = Some(format!(
2445                                "PP production-slot peer probe FAILED: \
2446                                 boundary={boundary_idx} dev{src_dev}->dev{dst_dev} \
2447                                 tokens={tokens} bytes={bytes}: {err}; refusing native P2P \
2448                                 (set MEMRA_PP_HOST_BOUNCE=1 to use the host-staged path; \
2449                                 MEMRA_PEER_PROBE=0 cannot authorize sharded native peer \
2450                                 transport)"
2451                            ));
2452                            break;
2453                        }
2454                    };
2455                    copies += 1;
2456                    direction_copies += 1;
2457                    let mismatches = peer_probe_mismatch_count(&expected, &readback);
2458                    if mismatches == 0 {
2459                        largest_clean_payload = largest_clean_payload.max(bytes);
2460                        direction_largest_clean = direction_largest_clean.max(bytes);
2461                    } else if host_bounce {
2462                        total_mismatches += mismatches;
2463                        direction_mismatches += mismatches;
2464                        eprintln!(
2465                            "[pp] production-slot peer probe CORRUPTION: \
2466                             boundary={boundary_idx} dev{src_dev}->dev{dst_dev} tokens={tokens} \
2467                             bytes={bytes} mismatches={mismatches}; MEMRA_PP_HOST_BOUNCE=1, \
2468                             proceeding on the host-staged path"
2469                        );
2470                    } else {
2471                        failure = Some(format!(
2472                            "PP production-slot peer probe FAILED: boundary={boundary_idx} \
2473                             dev{src_dev}->dev{dst_dev} tokens={tokens} bytes={bytes}: \
2474                             {mismatches} mismatched byte(s); refusing native P2P \
2475                             (set MEMRA_PP_HOST_BOUNCE=1 to use the host-staged path; \
2476                             MEMRA_PEER_PROBE=0 cannot authorize sharded native peer transport)"
2477                        ));
2478                        break;
2479                    }
2480                }
2481
2482                self.clear_peer_probe_boundary(&probe_boundary, src_stage, dst_stage)?;
2483                if let Some(err) = failure {
2484                    return Err(err.into());
2485                }
2486                eprintln!(
2487                    "[pp] production-slot peer probe direction: boundary={boundary_idx} \
2488                     dev{src_dev}->dev{dst_dev} copies={direction_copies} \
2489                     skipped={direction_skipped} mismatches={direction_mismatches} \
2490                     largest_clean_payload_bytes={direction_largest_clean}"
2491                );
2492            }
2493        }
2494
2495        let status = if total_mismatches > 0 {
2496            "BOUNCE"
2497        } else if skipped > 0 && copies > 0 {
2498            "PARTIAL"
2499        } else if skipped > 0 {
2500            "SKIP"
2501        } else {
2502            "PASS"
2503        };
2504        eprintln!(
2505            "[pp] production-slot peer probe {status}: widths_tokens={:?} copies={copies} \
2506             skipped={skipped} mismatches={total_mismatches} \
2507             largest_clean_payload_bytes={largest_clean_payload} elapsed_ms={:.3}",
2508            widths,
2509            started.elapsed().as_secs_f64() * 1e3,
2510        );
2511        Ok(())
2512    }
2513
2514    fn run_production_peer_probe(
2515        &self,
2516        enabled_pairs: &[(usize, usize)],
2517        host_bounce: bool,
2518        n_embd: usize,
2519    ) -> Result<(), Box<dyn std::error::Error>> {
2520        self.run_production_peer_probe_widths(
2521            enabled_pairs,
2522            host_bounce,
2523            n_embd,
2524            &PEER_PROBE_TOKEN_WIDTHS,
2525        )
2526    }
2527
2528    fn run_host_bounce_production_probe(
2529        &self,
2530        e: &Engine,
2531        n_embd: usize,
2532    ) -> Result<(), Box<dyn std::error::Error>> {
2533        let enabled = self.enable_probe_peer_access(e, &self.peer_capable)?;
2534        let granted = self.grant_probe_pool_access(e, &enabled)?;
2535        let probe = self.run_production_peer_probe(&granted, true, n_embd);
2536        // Teardown always runs, but the probe verdict wins: a CORRUPTION verdict (probe is
2537        // Err) must never be masked by a teardown failure. `revoke?; disable?; probe`
2538        // short-circuited teardown errors BEFORE probe was inspected, discarding the byte-
2539        // integrity signal on any teardown hiccup (hermes 9d6ae8d3). Surface teardown errors
2540        // only when the probe itself succeeded.
2541        let revoke = self.revoke_probe_pool_access(e, &granted);
2542        let disable = self.disable_probe_peer_access(e, &enabled);
2543        probe?;
2544        revoke?;
2545        disable?;
2546        Ok(())
2547    }
2548
2549    fn init_peer_probe_geometry(
2550        &self,
2551        e: &Engine,
2552        n_embd: usize,
2553    ) -> Result<(), Box<dyn std::error::Error>> {
2554        if !self.peer_probe || !self.cross_any {
2555            return Ok(());
2556        }
2557        let bytes = n_embd
2558            .checked_mul(std::mem::size_of::<f32>())
2559            .ok_or_else(|| format!("PP boundary-slot byte count overflows for n_embd={n_embd}"))?;
2560        let result = self.peer_probe_geometry.get_or_init(|| {
2561            let probe = if self.host_bounce_active() {
2562                self.run_host_bounce_production_probe(e, n_embd)
2563            } else {
2564                self.run_production_peer_probe(&self.peer_capable, false, n_embd)
2565            };
2566            let restore = e.ctx().bind_to_thread();
2567            match (probe, restore) {
2568                (Ok(()), Ok(())) => Ok(bytes),
2569                (Err(err), _) => Err(err.to_string()),
2570                (_, Err(err)) => Err(err.to_string()),
2571            }
2572        });
2573        let probed = result
2574            .as_ref()
2575            .map_err(|err| -> Box<dyn std::error::Error> { err.clone().into() })?;
2576        if *probed != bytes {
2577            return Err(format!(
2578                "peer probe initialized for boundary-slot bytes={probed} but model requests \
2579                 bytes={bytes}; one PP runtime supports one model geometry per process"
2580            )
2581            .into());
2582        }
2583        Ok(())
2584    }
2585
2586    fn init_host_bounce_staging(
2587        &self,
2588        e: &Engine,
2589        n_embd: usize,
2590    ) -> Result<(), Box<dyn std::error::Error>> {
2591        if !self.cross_any {
2592            return Ok(());
2593        }
2594        e.ctx().bind_to_thread()?;
2595        let result = self.bounce.get_or_init(|| {
2596            HostBounceRt::new(n_embd, &self.boundaries)
2597                .inspect(|rt| {
2598                    let bytes = rt.capacity * std::mem::size_of::<f32>();
2599                    eprintln!(
2600                        "[pp] host-bounce staging ready: n_embd={n_embd} max_tokens={} \
2601                         slot_bytes={bytes} slots_per_cross_boundary=2",
2602                        crate::cache::PRIME_CHUNK_MAX_TOKENS,
2603                    );
2604                })
2605                .map_err(|err| err.to_string())
2606        });
2607        let bounce = result
2608            .as_ref()
2609            .map_err(|err| -> Box<dyn std::error::Error> { err.clone().into() })?;
2610        if bounce.n_embd != n_embd {
2611            return Err(format!(
2612                "host-bounce runtime initialized for n_embd={} but model requests n_embd={n_embd}; \
2613                 one PP runtime supports one model geometry per process",
2614                bounce.n_embd,
2615            )
2616            .into());
2617        }
2618        Ok(())
2619    }
2620
2621    /// Exercise the newly armed staging through the real D2H/event/H2D boundary path before the
2622    /// live transport latch can observe it. One row per cross boundary is enough to validate the
2623    /// pinned capacity, event ordering, contexts, and byte continuity without touching peer DMA.
2624    fn validate_host_bounce_staging(
2625        &self,
2626        e: &Engine,
2627        n_embd: usize,
2628    ) -> Result<(), Box<dyn std::error::Error>> {
2629        let bytes = n_embd
2630            .checked_mul(std::mem::size_of::<f32>())
2631            .ok_or_else(|| {
2632                format!("host-bounce validation byte count overflows for n_embd={n_embd}")
2633            })?;
2634        for boundary_idx in 0..self.stages.len() - 1 {
2635            if !self.boundaries[boundary_idx].cross {
2636                continue;
2637            }
2638            let src_stage = boundary_idx;
2639            let dst_stage = boundary_idx + 1;
2640            let probe_boundary = self.new_peer_probe_boundary(src_stage, dst_stage)?;
2641            let path = BoundaryPath {
2642                boundary: boundary_idx,
2643                src_stage,
2644                dst_stage,
2645                transport: BoundaryTransport::HostBounce,
2646            };
2647            let expected = peer_probe_pattern(
2648                bytes,
2649                boundary_idx,
2650                self.stages[src_stage].dev,
2651                self.stages[dst_stage].dev,
2652            );
2653            let readback =
2654                self.production_probe_readback(path, &probe_boundary, &expected, n_embd, 0);
2655            let clear = self.clear_peer_probe_boundary(&probe_boundary, src_stage, dst_stage);
2656            let readback = readback?;
2657            clear?;
2658            let mismatches = peer_probe_mismatch_count(&expected, &readback);
2659            if mismatches > 0 {
2660                return Err(format!(
2661                    "runtime host-bounce staging validation FAILED: boundary={boundary_idx} \
2662                     bytes={bytes} mismatches={mismatches}"
2663                )
2664                .into());
2665            }
2666        }
2667        e.ctx().bind_to_thread()?;
2668        eprintln!(
2669            "[pp] runtime host-bounce staging validation PASS: row_bytes={bytes} \
2670             cross_boundaries={}",
2671            self.boundaries
2672                .iter()
2673                .filter(|boundary| boundary.cross)
2674                .count(),
2675        );
2676        Ok(())
2677    }
2678
2679    fn arm_runtime_host_bounce(
2680        &self,
2681        e: &Engine,
2682        row_bytes: usize,
2683    ) -> Result<(), Box<dyn std::error::Error>> {
2684        if row_bytes == 0 || !row_bytes.is_multiple_of(std::mem::size_of::<f32>()) {
2685            return Err(format!(
2686                "runtime host-bounce cannot recover n_embd from row_bytes={row_bytes}"
2687            )
2688            .into());
2689        }
2690        let n_embd = row_bytes / std::mem::size_of::<f32>();
2691        self.init_host_bounce_staging(e, n_embd)?;
2692        self.validate_host_bounce_staging(e, n_embd)
2693    }
2694
2695    /// Finish boot-time transport setup from the authoritative model width. This runs the
2696    /// production `BoundarySlot` ladder at 1/8/16/`PRIME_CHUNK_MAX_TOKENS` `[n_embd] f32` rows
2697    /// once, then allocates host-bounce slots when selected. The loader calls it before uploading
2698    /// the first model weight; `new_cache` repeats the call as an idempotent guard before the first
2699    /// forward.
2700    pub fn init_boundary_transport(
2701        &self,
2702        e: &Engine,
2703        n_embd: usize,
2704    ) -> Result<(), Box<dyn std::error::Error>> {
2705        if PEER_RUNTIME_PROBE_FAILED.load(Ordering::Acquire)
2706            && !PEER_RUNTIME_HOST_BOUNCE.load(Ordering::Acquire)
2707        {
2708            return Err(
2709                "PP runtime peer byte-integrity probe previously failed; refusing native P2P \
2710                 reuse because runtime host-bounce staging could not be armed"
2711                    .into(),
2712            );
2713        }
2714        self.init_peer_probe_geometry(e, n_embd)?;
2715        if !self.host_bounce_active() || !self.cross_any {
2716            return Ok(());
2717        }
2718        self.init_host_bounce_staging(e, n_embd)
2719    }
2720
2721    /// Run one due peer re-probe at a scheduler boundary on the CUDA owner thread. Each width has
2722    /// an independent copy-count deadline: an idle-only rung can remain pending while later cheap
2723    /// rungs keep running. The probe synchronizes the stage streams it exercises; no background
2724    /// thread touches CUDA.
2725    fn service_runtime_peer_probe(
2726        &self,
2727        e: &Engine,
2728        scheduler_idle: bool,
2729        probe_allowed: bool,
2730    ) -> Result<RuntimePeerProbeStatus, Box<dyn std::error::Error>> {
2731        if !self.peer_probe || !self.cross_any || self.host_bounce_active() {
2732            return Ok(RuntimePeerProbeStatus::NotRun);
2733        }
2734        if PEER_RUNTIME_PROBE_FAILED.load(Ordering::Acquire) {
2735            return Err(
2736                "PP runtime peer byte-integrity probe previously failed; native P2P is latched off"
2737                    .into(),
2738            );
2739        }
2740        let row_bytes = match self.peer_probe_geometry.get() {
2741            Some(Ok(bytes)) => *bytes,
2742            _ => return Ok(RuntimePeerProbeStatus::NotRun),
2743        };
2744
2745        let copies = PEER_BOUNDARY_COPIES.load(Ordering::Relaxed);
2746        let (width_index, tokens) = loop {
2747            let next_probe_copy = std::array::from_fn(|width_index| {
2748                PEER_RUNTIME_NEXT_PROBE_COPY[width_index].load(Ordering::Relaxed)
2749            });
2750            let measured_cost_ns = std::array::from_fn(|width_index| {
2751                PEER_RUNTIME_PROBE_MAX_COST_NS[width_index].load(Ordering::Relaxed)
2752            });
2753            let Some(candidate) = runtime_peer_probe_candidate(
2754                copies,
2755                next_probe_copy,
2756                measured_cost_ns,
2757                scheduler_idle,
2758            ) else {
2759                return Ok(RuntimePeerProbeStatus::NotRun);
2760            };
2761            // A mismatch immediately revokes native peer access before validated host bounce is
2762            // published. Live speculative sessions still dereference token/position state through
2763            // UVA outside the bounced boundary, so the worker may defer a runnable cheap rung until
2764            // those sessions retire. Do not consume its deadline or completed-probe counter.
2765            if !probe_allowed {
2766                return Ok(RuntimePeerProbeStatus::Deferred);
2767            }
2768            let due = next_probe_copy[candidate.0];
2769            let next = runtime_peer_probe_next_copy(due, copies);
2770            if PEER_RUNTIME_NEXT_PROBE_COPY[candidate.0]
2771                .compare_exchange(due, next, Ordering::AcqRel, Ordering::Relaxed)
2772                .is_ok()
2773            {
2774                break candidate;
2775            }
2776        };
2777        let probe_index = PEER_RUNTIME_PROBES.fetch_add(1, Ordering::Relaxed);
2778        let probe_bytes = row_bytes.checked_mul(tokens);
2779        let started = std::time::Instant::now();
2780        let probe = match probe_bytes {
2781            Some(_) => self.run_production_peer_probe_widths(
2782                &self.peer_capable,
2783                false,
2784                row_bytes / std::mem::size_of::<f32>(),
2785                &[tokens],
2786            ),
2787            None => Err(format!(
2788                "PP runtime peer probe byte count overflows for row_bytes={row_bytes} \
2789                 tokens={tokens}"
2790            )
2791            .into()),
2792        };
2793        let restore = e.ctx().bind_to_thread();
2794        let elapsed_ns = started.elapsed().as_nanos().min(u64::MAX as u128) as u64;
2795        let previous_max =
2796            PEER_RUNTIME_PROBE_MAX_COST_NS[width_index].fetch_max(elapsed_ns, Ordering::Relaxed);
2797        let verdict = match (probe, restore) {
2798            (Ok(()), Ok(())) => Ok(()),
2799            (Err(err), _) => Err(err.to_string()),
2800            (_, Err(err)) => Err(err.to_string()),
2801        };
2802        if let Err(err) = verdict {
2803            PEER_RUNTIME_PROBE_FAILURES.fetch_add(1, Ordering::Relaxed);
2804            let arm = latch_runtime_host_bounce(
2805                &PEER_RUNTIME_PROBE_FAILED,
2806                &PEER_RUNTIME_HOST_BOUNCE,
2807                || {
2808                    self.arm_runtime_host_bounce(e, row_bytes)
2809                        .map_err(|arm_err| arm_err.to_string())
2810                },
2811            );
2812            if let Err(arm_err) = arm {
2813                let message = format!(
2814                    "PP runtime peer byte-integrity re-probe FAILED after \
2815                     boundary_copies={copies} rung={}/{} tokens={tokens}: {err}; native P2P is \
2816                     latched off and host-bounce staging could not be armed: {arm_err}",
2817                    width_index + 1,
2818                    PEER_PROBE_TOKEN_WIDTHS.len(),
2819                );
2820                eprintln!("[pp] SECURITY RED: {message}; worker must stop");
2821                return Err(message.into());
2822            }
2823            eprintln!(
2824                "[pp] SECURITY RED: PP runtime peer byte-integrity re-probe FAILED after \
2825                 boundary_copies={copies} rung={}/{} tokens={tokens}: {err}; native P2P is \
2826                 latched off and the live transport DEGRADED to validated host bounce for the \
2827                 remainder of this process",
2828                width_index + 1,
2829                PEER_PROBE_TOKEN_WIDTHS.len(),
2830            );
2831            return Ok(RuntimePeerProbeStatus::DegradedToHostBounce);
2832        }
2833        if width_index + 1 != PEER_PROBE_TOKEN_WIDTHS.len()
2834            && previous_max <= PEER_RUNTIME_PROBE_BUDGET_NS
2835            && elapsed_ns > PEER_RUNTIME_PROBE_BUDGET_NS
2836        {
2837            eprintln!(
2838                "[pp] runtime peer re-probe rung exceeded the {:.3}ms owner-thread budget: \
2839                 tokens={tokens} measured_ms={:.3}; future runs are idle-only",
2840                PEER_RUNTIME_PROBE_BUDGET_NS as f64 / 1e6,
2841                elapsed_ns as f64 / 1e6,
2842            );
2843        }
2844        eprintln!(
2845            "[pp] runtime peer byte-integrity re-probe PASS: \
2846             boundary_copies={copies} interval_copies={PEER_RUNTIME_PROBE_INTERVAL_COPIES} \
2847             rung={}/{} tokens={tokens} bytes={} probe_index={probe_index} elapsed_ms={:.3} \
2848             scheduler_idle={scheduler_idle}",
2849            width_index + 1,
2850            PEER_PROBE_TOKEN_WIDTHS.len(),
2851            probe_bytes.unwrap(),
2852            elapsed_ns as f64 / 1e6,
2853        );
2854        Ok(RuntimePeerProbeStatus::Passed)
2855    }
2856
2857    fn bounce_rt(&self) -> Result<&HostBounceRt, Box<dyn std::error::Error>> {
2858        self.bounce
2859            .get()
2860            .ok_or_else(|| -> Box<dyn std::error::Error> {
2861                "MEMRA_PP_HOST_BOUNCE=1 staging was not initialized from model geometry".into()
2862            })?
2863            .as_ref()
2864            .map_err(|err| -> Box<dyn std::error::Error> { err.clone().into() })
2865    }
2866
2867    /// The engine a stage's subgraph must run through: the primary engine when the stage
2868    /// lives on the primary device, else the stage's own (remote-context) engine.
2869    pub fn engine<'a>(&'a self, s: usize, primary: &'a Engine) -> &'a Engine {
2870        self.stages[s].engine.as_ref().unwrap_or(primary)
2871    }
2872
2873    /// Order `dst`'s OWN stream behind everything already enqueued on `src`'s OWN stream
2874    /// (memra#95).
2875    ///
2876    /// This is NOT [`Self::fence_stages_behind`] and the difference is the whole bug that
2877    /// named it. A stage owns TWO streams: `StageRt::stream`, which only carries work issued
2878    /// inside an [`Self::enter`] scope (the ambient override), and — for every stage `s > 0`,
2879    /// including stages on the PRIMARY device, per the per-stage Engine isolation above — the
2880    /// stage's own [`Engine`]'s stream, which is what `rt.engine(s, e)` launches on when the
2881    /// caller is NOT inside an enter scope. `fence_stages_behind` orders the first kind and
2882    /// says nothing about the second. Any body that hands a stage engine to a helper WITHOUT
2883    /// entering the stage (the glm5 spec round's whole draft phase does exactly that, through
2884    /// `glm5_head_engine`) needs this one instead.
2885    ///
2886    /// Same-Engine and same-stream calls are no-ops. Two Engines sharing a CUDA context (the
2887    /// deployed shape: the stage engines retain the same primary context) get an event record
2888    /// plus a stream wait, fully async. Genuinely different contexts (a stage on another
2889    /// device) fall back to draining `src` on the host, which is correct everywhere and costs
2890    /// one sync at session build, never per round.
2891    ///
2892    /// TWO DELIBERATE ASYMMETRIES, both of which a "tidy it up" edit would get wrong:
2893    ///
2894    /// * the SOURCE side reads `src.stream()`, the ambient-override-aware accessor, because
2895    ///   the work being ordered was issued through the same accessor and must be the same
2896    ///   stream even if a caller ever runs this inside a stage or `enter_main` scope. The
2897    ///   DESTINATION side reads `dst.gpu.main_stream()`, override-blind, because the reader
2898    ///   being ordered (the glm5 draft phase) provably never enters a scope, so its launches
2899    ///   go to that Engine's own stream and to nothing else.
2900    /// * the context test is VALUE equality, not `Arc::ptr_eq`. `CudaContext::new` allocates a
2901    ///   fresh `Arc` per call even though `primary_ctx::retain` hands back the same
2902    ///   `CUcontext`, so every stage Engine on the primary device has a distinct `Arc` for the
2903    ///   same context: `Arc::ptr_eq` would be false forever, the event path would be dead
2904    ///   code, and every restored session would pay a host sync on the TTFT path this feature
2905    ///   exists to protect (review round 2 on PR #100).
2906    ///
2907    /// Parked on `PpNRt` rather than made a free function so it sits beside
2908    /// `fence_stages_behind`: the pair is the documentation.
2909    pub fn order_engine_behind(
2910        src: &Engine,
2911        dst: &Engine,
2912    ) -> Result<(), Box<dyn std::error::Error>> {
2913        if std::ptr::eq(src, dst) {
2914            return Ok(());
2915        }
2916        let s = src.stream();
2917        let d = dst.gpu.main_stream();
2918        if Arc::ptr_eq(&s, d) {
2919            return Ok(());
2920        }
2921        if src.ctx() == dst.ctx() {
2922            let ev = s.context().new_event(None)?;
2923            ev.record(&s)?;
2924            d.wait(&ev)?;
2925        } else {
2926            s.synchronize()?;
2927        }
2928        Ok(())
2929    }
2930
2931    /// Bind this OS thread to stage `s`'s CUDA context before issuing work there.
2932    pub fn bind_stage(&self, s: usize) -> Result<(), Box<dyn std::error::Error>> {
2933        self.stages[s].ctx.bind_to_thread()?;
2934        Ok(())
2935    }
2936
2937    /// Enter stage `s`: until the guard drops, every engine op on this thread launches on
2938    /// the stage's stream (memra_runtime ambient-stream override).
2939    pub fn enter(&self, s: usize) -> memra_runtime::StreamOverride {
2940        memra_runtime::push_stream_override(
2941            self.stages[s].stream.clone(),
2942            self.stages[s].blas.clone(),
2943        )
2944    }
2945
2946    /// Allocate/grow BOTH slots for a boundary before pipelined issue starts. `tx()` can
2947    /// grow a slot lazily, but first-use ordering requires synchronizing the RX stream
2948    /// after that allocation. If slot 1 first grows after stage 1 of chunk N has already
2949    /// been queued, that sync drains chunk N and erases the only overlap in a two-chunk
2950    /// prime. Prewarming both slots pays the same one-time sync before either stage starts.
2951    pub fn prepare_overlap_slots(
2952        &self,
2953        b: usize,
2954        n: usize,
2955    ) -> Result<(), Box<dyn std::error::Error>> {
2956        let bd = &self.boundaries[b];
2957        let s_rx = &self.stages[b + 1].stream;
2958        let mut grew = false;
2959        for sl in &bd.slots {
2960            let mut guard = sl.buf.lock().unwrap();
2961            if guard.as_ref().map(|bf| bf.len() < n).unwrap_or(true) {
2962                *guard = Some(s_rx.alloc_zeros::<f32>(n)?);
2963                grew = true;
2964            }
2965        }
2966        if grew {
2967            s_rx.synchronize()?;
2968        }
2969        Ok(())
2970    }
2971
2972    /// Project only the additional device bytes needed to grow this process-global boundary to
2973    /// `n` elements per slot. Admission must not charge the full persistent high-water to every
2974    /// session after it already exists.
2975    pub fn boundary_slot_growth_bytes(
2976        &self,
2977        b: usize,
2978        n: usize,
2979    ) -> Result<usize, Box<dyn std::error::Error>> {
2980        let boundary = self
2981            .boundaries
2982            .get(b)
2983            .ok_or_else(|| format!("PP boundary {b} is outside the runtime"))?;
2984        let mut current = [0usize; 2];
2985        for (index, slot) in boundary.slots.iter().enumerate() {
2986            let guard = slot
2987                .buf
2988                .lock()
2989                .map_err(|_| format!("PP boundary {b} slot lock is poisoned"))?;
2990            current[index] = guard.as_ref().map_or(0, CudaSlice::len);
2991        }
2992        let elements = boundary_slot_growth_elements(current, n);
2993        Ok(elements.saturating_mul(std::mem::size_of::<f32>()))
2994    }
2995
2996    /// Boundary TX at boundary `b` (call within the stage-`b` scope; `x` = the
2997    /// materialized [n] residual): wait for the slot's previous RX (write-after-read
2998    /// guard), copy `x` into the slot's persistent buffer via the boundary's transport on
2999    /// stage-b's stream (the owning-stream/publication law), record ev_tx. Returns the
3000    /// slot index for the paired rx().
3001    ///
3002    /// `n` is the PAYLOAD ELEMENT COUNT, not a fixed model constant: the eager arm passes
3003    /// `n_embd` (one row), the batched arm passes `b_n * n_embd` (B stacked rows, the
3004    /// [B, n_embd] boundary). The slot buffer is GROW-ONLY and the transport moves exactly
3005    /// the first `n` elements — batched serving changes B every tick (chunk fill), and a
3006    /// realloc-on-every-size-change would host-sync the RX stream per width change (see the
3007    /// SLOT FIRST-USE ORDERING note below for why each allocation needs that sync). Growing
3008    /// to the high-water mark makes the syncs O(distinct widths) instead of O(width changes).
3009    pub fn tx(
3010        &self,
3011        b: usize,
3012        x: &CudaSlice<f32>,
3013        n: usize,
3014    ) -> Result<usize, Box<dyn std::error::Error>> {
3015        assert_eq!(x.len(), n, "pp tx: residual length mismatch");
3016        let bd = &self.boundaries[b];
3017        let slot_idx = if pp2_overlap() {
3018            bd.step.fetch_add(1, Ordering::Relaxed) % 2
3019        } else {
3020            0
3021        };
3022        self.tx_slot(b, x, n, slot_idx)
3023    }
3024
3025    /// Pipelined boundary TX: always alternate the shared double-buffer slots, independent
3026    /// of the decode-side `MEMRA_PP_OVERLAP` experiment flag. The boundary-local atomic
3027    /// keeps concurrent callers on one slot sequence rather than each restarting at A.
3028    pub fn tx_pipelined(
3029        &self,
3030        b: usize,
3031        x: &CudaSlice<f32>,
3032        n: usize,
3033    ) -> Result<usize, Box<dyn std::error::Error>> {
3034        assert_eq!(x.len(), n, "pp tx: residual length mismatch");
3035        let slot_idx = self.boundaries[b].step.fetch_add(1, Ordering::Relaxed) % 2;
3036        self.tx_slot(b, x, n, slot_idx)
3037    }
3038
3039    fn tx_slot(
3040        &self,
3041        b: usize,
3042        x: &CudaSlice<f32>,
3043        n: usize,
3044        slot_idx: usize,
3045    ) -> Result<usize, Box<dyn std::error::Error>> {
3046        let bd = &self.boundaries[b];
3047        let path = BoundaryPath {
3048            boundary: b,
3049            src_stage: b,
3050            dst_stage: b + 1,
3051            transport: boundary_transport(bd.cross, self.host_bounce_active()),
3052        };
3053        let copied_slot = self.tx_slot_path(path, bd, x, n, slot_idx)?;
3054        if path.transport == BoundaryTransport::Peer {
3055            PEER_BOUNDARY_COPIES.fetch_add(1, Ordering::Relaxed);
3056        }
3057        Ok(copied_slot)
3058    }
3059
3060    fn tx_slot_path(
3061        &self,
3062        path: BoundaryPath,
3063        bd: &BoundaryRt,
3064        x: &CudaSlice<f32>,
3065        n: usize,
3066        slot_idx: usize,
3067    ) -> Result<usize, Box<dyn std::error::Error>> {
3068        debug_assert!(slot_idx < 2);
3069        let sl = &bd.slots[slot_idx];
3070        let s_tx = &self.stages[path.src_stage].stream;
3071        s_tx.wait(&sl.ev_rx)?;
3072        let mut guard = sl.buf.lock().unwrap();
3073        if guard.as_ref().map(|bf| bf.len() < n).unwrap_or(true) {
3074            // allocated on the RX stage's stream: the buffer lives on the RX device.
3075            let s_rx = &self.stages[path.dst_stage].stream;
3076            *guard = Some(s_rx.alloc_zeros::<f32>(n)?);
3077            // SLOT FIRST-USE ORDERING (2026-08-02 pipelined-gate find): the lazy alloc's
3078            // pool-alloc + memset enqueue on the RX stream; the TX copy below issues on
3079            // the TX stream, and on a slot's FIRST use ev_rx has never been recorded —
3080            // nothing orders them. With >=2 tokens in flight the RX stream is still busy
3081            // with the previous token, the memset lands AFTER the TX copy, and the
3082            // boundary residual is zeroed (window=1 passed, window>=2 failed at the
3083            // slot-1 first-use step; -overlap arms passed because the synchronous serial
3084            // arm pre-warmed both slots). Host-sync the RX stream once per slot
3085            // allocation — at most 2*(N-1) one-time syncs per process, all during prime.
3086            s_rx.synchronize()?;
3087        }
3088        let buf = guard.as_mut().unwrap();
3089        match path.transport {
3090            BoundaryTransport::Local => s_tx.memcpy_dtod(x, buf)?,
3091            BoundaryTransport::HostBounce => {
3092                debug_assert_eq!(path.src_stage, path.boundary);
3093                debug_assert_eq!(path.dst_stage, path.boundary + 1);
3094                let bounce = self.bounce_rt()?;
3095                if n > bounce.capacity {
3096                    return Err(format!(
3097                        "pp host-bounce payload {n} exceeds geometry-sized capacity {} \
3098                         (n_embd={}, max prime tokens={})",
3099                        bounce.capacity,
3100                        bounce.n_embd,
3101                        crate::cache::PRIME_CHUNK_MAX_TOKENS,
3102                    )
3103                    .into());
3104                }
3105                let mut host = bounce.slot(path.boundary, slot_idx)?.lock().unwrap();
3106                // D2H is issued on the producing stage's stream. ev_tx below publishes the
3107                // completed host bytes to the receiving stream; the exact prefix avoids moving
3108                // a full 64 MiB slot for a one-row decode, and no peer pointer is formed here.
3109                s_tx.memcpy_dtoh(x, host.prefix_mut(n))?;
3110            }
3111            BoundaryTransport::Peer => {
3112                // cudaMemcpyPeerAsync (M0: 2.8x NCCL at PP activation sizes), issued on the
3113                // publishing TX stream with explicit src/dst contexts.
3114                use cudarc::driver::{DevicePtr, DevicePtrMut};
3115                let (sp, _g0) = x.device_ptr(s_tx);
3116                let (dp, _g1) = buf.device_ptr_mut(s_tx);
3117                self.stages[path.src_stage].ctx.bind_to_thread()?;
3118                unsafe {
3119                    cudarc::driver::result::memcpy_peer_async(
3120                        self.stages[path.dst_stage].ctx.cu_ctx(),
3121                        dp,
3122                        self.stages[path.src_stage].ctx.cu_ctx(),
3123                        sp,
3124                        n * std::mem::size_of::<f32>(),
3125                        s_tx.cu_stream(),
3126                    )?;
3127                }
3128            }
3129        }
3130        sl.ev_tx.record(s_tx)?;
3131        Ok(slot_idx)
3132    }
3133
3134    /// Boundary RX at boundary `b` (call within the stage-`b+1` scope): wait on the slot's
3135    /// ev_tx, copy the boundary buffer into a fresh working buffer (dtod on the RX stream —
3136    /// local on the RX device in both transports), record ev_rx. The returned buffer is
3137    /// RX-stage-owned: allocated, consumed, and eventually freed on that stage's stream.
3138    pub fn rx(
3139        &self,
3140        b: usize,
3141        slot_idx: usize,
3142        n: usize,
3143    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
3144        let bd = &self.boundaries[b];
3145        let path = BoundaryPath {
3146            boundary: b,
3147            src_stage: b,
3148            dst_stage: b + 1,
3149            transport: boundary_transport(bd.cross, self.host_bounce_active()),
3150        };
3151        self.rx_slot_path(path, bd, slot_idx, n)
3152    }
3153
3154    fn rx_slot_path(
3155        &self,
3156        path: BoundaryPath,
3157        bd: &BoundaryRt,
3158        slot_idx: usize,
3159        n: usize,
3160    ) -> Result<CudaSlice<f32>, Box<dyn std::error::Error>> {
3161        let sl = &bd.slots[slot_idx];
3162        let s_rx = &self.stages[path.dst_stage].stream;
3163        s_rx.wait(&sl.ev_tx)?;
3164        let mut guard = sl.buf.lock().unwrap();
3165        let buf = guard.as_mut().expect("pp rx before tx");
3166        assert!(
3167            buf.len() >= n,
3168            "pp rx: slot holds {} < requested {n}",
3169            buf.len()
3170        );
3171        if path.transport == BoundaryTransport::HostBounce {
3172            debug_assert_eq!(path.src_stage, path.boundary);
3173            debug_assert_eq!(path.dst_stage, path.boundary + 1);
3174            let bounce = self.bounce_rt()?;
3175            let host = bounce.slot(path.boundary, slot_idx)?.lock().unwrap();
3176            let mut dst = buf.slice_mut(0..n);
3177            // The destination stream already waits ev_tx, so this H2D cannot observe the
3178            // staging slot before the source stream's D2H completes.
3179            s_rx.memcpy_htod(host.prefix(n), &mut dst)?;
3180        }
3181        // uninit working buffer (fully overwritten by the copy), allocated explicitly on
3182        // the stage stream so rx() is correct even outside an enter() scope.
3183        let mut work = unsafe { s_rx.alloc::<f32>(n)? };
3184        // Slice the slot to the payload: the buffer is grow-only (see tx), so at a narrower
3185        // width it is LONGER than `work` and cudarc's memcpy_dtod (dst.len() >= src.len())
3186        // would assert. The paired tx wrote exactly these first n elements.
3187        s_rx.memcpy_dtod(&buf.slice(0..n), &mut work)?;
3188        sl.ev_rx.record(s_rx)?;
3189        Ok(work)
3190    }
3191
3192    /// PUBLISH a DEVICE-RESIDENT result off the last stage to the caller's stream
3193    /// (lane/pp2-spec 2026-08-06).
3194    ///
3195    /// Every ppN body before this one returned HOST values — `decode_step_h_ppn` and
3196    /// `decode_step_batch_ppn` both `dtoh` inside the last-stage scope, and a dtoh on the
3197    /// producing stream is self-ordering. The verify trunk is the FIRST ppN body whose
3198    /// contract is device-resident output (`decode_step_t_h_emb_dev` exists precisely so the
3199    /// accept walk argmaxes on-device instead of moving T x n_vocab f32 per round), and
3200    /// device slices carry no stream affinity: the caller resumes on the PRIMARY stream and
3201    /// dereferences buffers whose producing kernels are still queued on the last stage's
3202    /// stream. Nothing orders them.
3203    ///
3204    /// Why this only ever failed on ONE device: with stages on separate devices the caller's
3205    /// first touch is a cross-device copy that the driver orders against the source context,
3206    /// and the readback path syncs. Two streams on the SAME device genuinely overlap, so the
3207    /// primary stream reads a buffer whose matmul has not run — nondeterministic garbage
3208    /// (measured: NaN, 3155.677, and 2.87e-5 where the reference had -2.0048926), and it
3209    /// poisons the NEXT arm in the same process because the corrupted KV persists. This is
3210    /// the same class as the SLOT FIRST-USE ORDERING find above, one level up: there the
3211    /// unordered pair was alloc-memset vs TX copy, here it is stage-N compute vs the
3212    /// caller's consumer.
3213    ///
3214    /// Fix = the boundary law applied to the exit: record an event on the producing stage
3215    /// stream, make the caller's stream wait on it. Event-wait, not a device sync, so the
3216    /// stage streams keep running for the deferred-readback arm. Call INSIDE the last-stage
3217    /// scope, after the last enqueue, with the caller's (pre-`enter`) stream.
3218    pub fn publish_to(
3219        &self,
3220        s: usize,
3221        dst: &Arc<CudaStream>,
3222    ) -> Result<(), Box<dyn std::error::Error>> {
3223        let st = &self.stages[s];
3224        // Same stream (STREAMS=0 rollback, or a caller already on the stage stream): the
3225        // stream orders itself; recording+waiting would be a no-op with a stray event.
3226        if Arc::ptr_eq(&st.stream, dst) {
3227            return Ok(());
3228        }
3229        let ev = st.ctx.new_event(None)?;
3230        ev.record(&st.stream)?;
3231        dst.wait(&ev)?;
3232        Ok(())
3233    }
3234
3235    /// PUBLISH EVERY STAGE to the caller (lane/glm5-accrace 2026-09-01) — the exit half of
3236    /// the boundary law, applied to ALL stages instead of only the producing one.
3237    ///
3238    /// WHY `publish_to(last, …)` IS NOT ENOUGH. A ppN body's terminal drain (a `dtoh` in
3239    /// the last-stage scope, or `publish_to(n_st-1, …)`) orders the caller behind the last
3240    /// stage, and the TX-wait chain transitively covers every earlier stage's work UP TO
3241    /// its `ev_tx`. It does NOT cover what each earlier stage's stream still holds AFTER
3242    /// its tx: the stage-scope locals (`pos_d`, the embedded/expanded rows, the boundary
3243    /// residual, every per-layer transient, and a verify round's ckpt clones) are dropped
3244    /// with the stage override still active, so their `free_async` enqueues on the STAGE
3245    /// stream after `ev_tx`. The caller then resumes on its own stream and allocates —
3246    /// and, per the `fence_stages_behind` anatomy above, cudarc's drop carries no read
3247    /// guard, so the pool can hand the caller a block whose stage-stream lifetime has not
3248    /// retired and the caller's writes land under queued stage work.
3249    ///
3250    /// MEASURED (research/glm53-flash-bringup-20260827/accrace-20260901/): with per-stage
3251    /// streams on one device, the hc ppN PRIME over a fixed 24-token prompt returned THREE
3252    /// distinct logit fingerprints within a single process — the first prime always
3253    /// canonical, later ones drifting — while `MEMRA_PP_STREAMS=0` returned one
3254    /// fingerprint 11/11. Downstream, one glm5 spec round silently lost an acceptance
3255    /// (14/42 -> 13/42) and the e2e tape diverged.
3256    ///
3257    /// Event waits, never a device sync: the stage streams keep running. Call at a ppN
3258    /// body's EXIT with the pre-`enter` caller stream (a stage stream that IS the caller's
3259    /// stream is skipped by `publish_to`).
3260    ///
3261    /// `MEMRA_PP_EXIT_PUBLISH=0` is the ROLLBACK SEAM (see [`pp_exit_publish`]) and
3262    /// restores the pre-lane, racy program exactly — it exists so the fix can be A/B'd in
3263    /// ONE binary and so a future perf question has a control arm, not because the guard is
3264    /// optional.
3265    pub fn publish_all_to(&self, dst: &Arc<CudaStream>) -> Result<(), Box<dyn std::error::Error>> {
3266        if !pp_exit_publish() {
3267            return Ok(());
3268        }
3269        for s in 0..self.stages.len() {
3270            self.publish_to(s, dst)?;
3271        }
3272        Ok(())
3273    }
3274
3275    /// REVERSE PUBLICATION (#87 root cause, lane/pp2spec-crash 2026-08-07): order every
3276    /// STAGE stream behind the CALLER's stream — the mirror of `publish_to`.
3277    ///
3278    /// `publish_to` orders caller READS behind stage COMPUTE. Nothing ordered the other
3279    /// direction: buffers ALLOCATED on a stage stream (the verify's returned logits/hidden,
3280    /// the VerifyCkpt stashes) are CONSUMED by kernels the caller enqueues on the PRIMARY
3281    /// stream, and when they drop, cudarc enqueues `free_async` on the ALLOCATING (stage)
3282    /// stream. With event tracking elided (the decode-path default) the drop carries no
3283    /// read-guard, so the pool can hand the block to the NEXT stage-stream allocation and
3284    /// its writes overwrite memory the queued primary-stream consumer has not read yet.
3285    /// Measured (research/pp2spec-crash-20260807): the spec round-seed read 13/4096 NaN =
3286    /// the uninitialized-bits signature (P(NaN|random u32) ~ 1/256), clean by host re-read
3287    /// time — a read-before-write race, fatal via the argmax-sentinel -> embed_gather MMU
3288    /// fault, and gated on c>=2 because a backed-up primary stream widens the window.
3289    ///
3290    /// Fix law: before a ppN body enqueues NEW stage-stream work (allocations that may
3291    /// reuse freed blocks), every stage stream waits the caller's stream at its current
3292    /// point. All primary consumers of the previous round's stage-allocated buffers are
3293    /// enqueued by then (single host thread), so reuse-writes land strictly after them.
3294    /// Call at ppN-body ENTRY with the pre-`enter` caller stream. Door-shut configs never
3295    /// build a PpNRt, so single-card behavior is untouched.
3296    pub fn fence_stages_behind(
3297        &self,
3298        src: &Arc<CudaStream>,
3299    ) -> Result<(), Box<dyn std::error::Error>> {
3300        let ev = src.context().new_event(None)?;
3301        ev.record(src)?;
3302        for st in &self.stages {
3303            if Arc::ptr_eq(&st.stream, src) {
3304                continue;
3305            }
3306            st.stream.wait(&ev)?;
3307        }
3308        Ok(())
3309    }
3310
3311    /// Deferred readback: record a fresh completion event on the LAST stage's stream
3312    /// (call after the step's logits matmul has been enqueued there).
3313    pub fn record_done(&self) -> Result<CudaEvent, Box<dyn std::error::Error>> {
3314        let last = &self.stages[self.stages.len() - 1];
3315        let ev = last.ctx.new_event(None)?;
3316        ev.record(&last.stream)?;
3317        Ok(ev)
3318    }
3319
3320    /// The dedicated readback stream (last stage's context).
3321    pub fn readback_stream(&self) -> &Arc<CudaStream> {
3322        &self.readback
3323    }
3324}
3325
3326/// Service a due runtime peer probe without constructing a PP runtime on door-shut placements.
3327/// Must be called by the CUDA owner thread at a scheduling boundary.
3328pub fn service_runtime_peer_probe(
3329    e: &Engine,
3330    scheduler_idle: bool,
3331    probe_allowed: bool,
3332) -> Result<RuntimePeerProbeStatus, Box<dyn std::error::Error>> {
3333    let Some(rt) = RTN.get() else {
3334        return Ok(RuntimePeerProbeStatus::NotRun);
3335    };
3336    let rt = rt
3337        .as_ref()
3338        .map_err(|err| -> Box<dyn std::error::Error> { err.clone().into() })?;
3339    rt.service_runtime_peer_probe(e, scheduler_idle, probe_allowed)
3340}
3341
3342/// M2 increment 3: a step's logits, still device-resident on the LAST stage. `wait()`
3343/// orders the readback stream behind the step's completion event, copies, and syncs —
3344/// tokens enqueued after this step keep running on the stage streams while the caller
3345/// drains token t. Dropping without waiting is safe (buffers free stream-ordered).
3346pub struct PendingLogits {
3347    logits: CudaSlice<f32>,
3348    ev: CudaEvent,
3349    rb: Arc<CudaStream>,
3350    _walk: PpWalkLease,
3351}
3352
3353impl PendingLogits {
3354    pub(crate) fn new(
3355        logits: CudaSlice<f32>,
3356        ev: CudaEvent,
3357        rb: Arc<CudaStream>,
3358        walk: PpWalkLease,
3359    ) -> Self {
3360        PendingLogits {
3361            logits,
3362            ev,
3363            rb,
3364            _walk: walk,
3365        }
3366    }
3367
3368    /// Blocks until this step's logits are computed, returns them host-side. Only this
3369    /// step's work is waited on (event-ordered) — NOT later tokens already enqueued on
3370    /// the stage streams.
3371    pub fn wait(self) -> Result<Vec<f32>, Box<dyn std::error::Error>> {
3372        self.rb.wait(&self.ev)?;
3373        let host = self.rb.clone_dtoh(&self.logits)?;
3374        self.rb.synchronize()?;
3375        // logits drop AFTER the sync: the D2H has fully completed, so the stream-ordered
3376        // free on the compute stream cannot race the copy.
3377        Ok(host)
3378    }
3379}
3380
3381/// Bring up the PP transport while model geometry is known but before model weights upload.
3382/// Door-shut and placement-free loads remain untouched.
3383pub fn init_model_transport(
3384    e: &Engine,
3385    cfg: &memra_gguf::config::ModelConfig,
3386    n_trunk: usize,
3387) -> Result<(), Box<dyn std::error::Error>> {
3388    if pp2_streams_off() || pp2_devices_env().is_none() || pp_cuts(n_trunk).is_none() {
3389        return Ok(());
3390    }
3391    PpNRt::get(e)?.init_boundary_transport(e, cfg.n_embd as usize)
3392}
3393
3394/// Stage-owned cache allocation door: when the ppN door is open AND `MEMRA_PP_DEVICES`
3395/// is set (placement plumbing), each layer's cache is allocated by its OWNING stage's
3396/// engine — on one device this is byte-for-byte today's allocation (gated); cross-device
3397/// it puts each stage's KV on that stage's HBM. Door shut or devices unset: plain
3398/// `Cache::new` (zero behavior change). Trailing MTP/NextN layers (beyond the trunk)
3399/// map to the LAST stage.
3400pub fn new_cache(
3401    e: &Engine,
3402    cfg: &memra_gguf::config::ModelConfig,
3403    max_ctx: usize,
3404) -> Result<crate::cache::Cache, Box<dyn std::error::Error>> {
3405    new_cache_inner(e, cfg, None, max_ctx)
3406}
3407
3408pub fn new_cache_planned(
3409    e: &Engine,
3410    cfg: &memra_gguf::config::ModelConfig,
3411    plan: &memra_gguf::model_plan::ModelPlan,
3412    max_ctx: usize,
3413) -> Result<crate::cache::Cache, Box<dyn std::error::Error>> {
3414    new_cache_inner(e, cfg, Some(plan), max_ctx)
3415}
3416
3417fn new_cache_inner(
3418    e: &Engine,
3419    cfg: &memra_gguf::config::ModelConfig,
3420    plan: Option<&memra_gguf::model_plan::ModelPlan>,
3421    max_ctx: usize,
3422) -> Result<crate::cache::Cache, Box<dyn std::error::Error>> {
3423    let n_trunk = (cfg.n_layer - cfg.nextn_predict_layers) as usize;
3424    if let Some(fence) = pp_cuts(n_trunk) {
3425        if pp2_devices_env().is_some() && !pp2_streams_off() {
3426            let rt = PpNRt::get(e)?;
3427            rt.init_boundary_transport(e, cfg.n_embd as usize)?;
3428            let n_st = fence.len() - 1;
3429            assert_eq!(
3430                rt.n_stages(),
3431                n_st,
3432                "PpNRt stage count {} != fence stages {n_st}",
3433                rt.n_stages()
3434            );
3435            // #87 REVERSE PUBLICATION at ADMISSION (lane/pp2spec-crash): this is the one
3436            // stage-stream allocation site OUTSIDE the ppN step bodies — a NEW session's
3437            // KV alloc_zeros enqueue on the STAGE streams, and their pool blocks can be
3438            // reuse of buffers freed from ANOTHER session's in-flight verify whose
3439            // primary-stream reads are still queued (the c=2 residual: exactly one trap
3440            // per admission collision, round 0, after the step-body fences landed).
3441            // Order the stage streams behind the caller before the memsets can clobber.
3442            // Anatomy: `PpNRt::fence_stages_behind`.
3443            rt.fence_stages_behind(&e.stream())?;
3444            let devs: Vec<&dyn memra_kv::KvDev> = (0..n_st)
3445                .map(|s| rt.engine(s, e) as &dyn memra_kv::KvDev)
3446                .collect();
3447            let cache = match plan {
3448                Some(plan) => {
3449                    crate::cache::Cache::new_ppn_planned(&devs, &fence, cfg, plan, max_ctx)?
3450                }
3451                None => crate::cache::Cache::new_ppn(&devs, &fence, cfg, max_ctx)?,
3452            };
3453            sync_stages_after_load(e, n_trunk)?;
3454            return Ok(cache);
3455        }
3456        if !pp2_streams_off() {
3457            // CACHE BIRTH BARRIER (2026-08-02 pipelined-arm residual race): with the door
3458            // open but no device placement, Cache::new's alloc_zeros memsets enqueue on
3459            // the PRIMARY worker stream while the first KV appends / recurrent-state
3460            // reads run on the per-stage streams — no event orders them, and under
3461            // deferred readback the stage streams are hot immediately (a memset tail
3462            // can zero an already-appended KV row; intermittent, ~1-in-3 gate FAIL).
3463            // One context-sync per cache creation kills the class.
3464            let cache = match plan {
3465                Some(plan) => crate::cache::Cache::new_planned(e, cfg, plan, max_ctx)?,
3466                None => crate::cache::Cache::new(e, cfg, max_ctx)?,
3467            };
3468            sync_stages_after_load(e, n_trunk)?;
3469            return Ok(cache);
3470        }
3471    }
3472    match plan {
3473        Some(plan) => crate::cache::Cache::new_planned(e, cfg, plan, max_ctx),
3474        None => crate::cache::Cache::new(e, cfg, max_ctx),
3475    }
3476}
3477
3478/// M2 increment 2 LOAD BARRIER: weight uploads and decode-mirror builds enqueue on the
3479/// loading engines' WORKER streams; the first consumer launches on a DIFFERENT stream
3480/// with no load->decode event — the door-off reference walk on the primary worker
3481/// stream (sharded load: remote builds still in flight), or a fresh per-stage stream.
3482/// The 2026-08-02 gate finds (n2-dev01 step-0 168k-logit graze; split5 ref=0.0 head —
3483/// a half-built rp4 mirror — poisoning step-0 KV and every later step): one
3484/// context-wide synchronize per stage at load end kills the class. No-op when the door
3485/// is shut at load (single-stream load+decode is ordered by the stream itself).
3486pub fn sync_stages_after_load(
3487    e: &Engine,
3488    n_trunk: usize,
3489) -> Result<(), Box<dyn std::error::Error>> {
3490    if pp2_streams_off() || pp_cuts(n_trunk).is_none() {
3491        return Ok(());
3492    }
3493    let rt = PpNRt::get(e)?;
3494    for s in 0..rt.n_stages() {
3495        rt.stages[s].ctx.bind_to_thread()?;
3496        unsafe {
3497            cudarc::driver::sys::cuCtxSynchronize().result()?;
3498        }
3499    }
3500    e.ctx().bind_to_thread()?;
3501    unsafe {
3502        cudarc::driver::sys::cuCtxSynchronize().result()?;
3503    }
3504    Ok(())
3505}
3506
3507/// M2 increment 2 (weight sharding): the engine that should UPLOAD layer `il`'s weights
3508/// (and build its decode mirrors) — the owning stage's engine when the door is open with
3509/// device placement and sharding not rolled back; else the primary. `il >= n_trunk`
3510/// (MTP/NextN blocks) maps to the last stage. The head (output_norm + lm head) belongs
3511/// to the last trunk layer's stage — call with `il = n_trunk - 1`.
3512pub fn layer_engine(
3513    e: &Engine,
3514    n_trunk: usize,
3515    il: usize,
3516) -> Result<&Engine, Box<dyn std::error::Error>> {
3517    if pp_shard_off() || pp2_devices_env().is_none() || pp2_streams_off() {
3518        return Ok(e);
3519    }
3520    let Some(fence) = pp_cuts(n_trunk) else {
3521        return Ok(e);
3522    };
3523    let rt = PpNRt::get(e)?;
3524    let s = stage_of(&fence, il.min(n_trunk - 1));
3525    Ok(rt.engine(s, e))
3526}
3527
3528/// Why a checkpoint restore refused a layer's distributed (TP) KV mirror.
3529#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3530pub(crate) enum TpRestoreRefusal {
3531    /// Snapshot recorded a distributed length but the in-place target has no mirror to rewind.
3532    TargetAbsent,
3533    /// Grow path: the snapshot recorded a distributed length the parked source cannot supply.
3534    SourceAbsent,
3535    /// Grow path: the freshly allocated target already holds a mirror it should not have.
3536    GrowTargetNotFresh,
3537    /// The whole-token TP CUDA graph door is open. That graph is MODEL-level state which bakes
3538    /// the rank-cache pointers, so freeing a mirror under it strands the captured parent.
3539    TokenGraphDoorOpen,
3540}
3541
3542/// What a checkpoint restore must do with one layer's distributed (TP) KV mirror.
3543#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3544pub(crate) enum TpRestore {
3545    /// Neither side holds a mirror: nothing to do.
3546    Nothing,
3547    /// In-place rewind of the target's existing mirror to the recorded committed length.
3548    Rewind(usize),
3549    /// Grow path: build the target's mirror from the parked source's, truncated to `len`.
3550    Grow(usize),
3551    /// The snapshot PREDATES this layer's lazily-created mirror. Clear it: the mirror is derived
3552    /// state, and `ensure_step_tp_kv_cache` rebuilds it from the authoritative local plane on the
3553    /// next TP use, at whatever length that plane then holds.
3554    DropMirror,
3555    Refuse(TpRestoreRefusal),
3556}
3557
3558/// Resolve the distributed-KV arm of a checkpoint restore for ONE layer.
3559///
3560/// MECHANISM (lane/step37, 2026-08-28). `tp_kv[il]` is created LAZILY on a layer's first TP use
3561/// (`hybrid_forward.rs::ensure_step_tp_kv_cache`, reached only from the two TP DECODE paths and
3562/// the TP-PREFILL path). When rank-local TP prefill is not engaged, a cold prime never touches
3563/// it, so the session-affinity checkpoint captured mid-prime at the stable boundary records
3564/// `tp_kv_len[il] = None` for EVERY layer. The first decode step then materializes the mirror.
3565/// At reuse time the recorded `None` met a live `Some(..)` and the whole checkpoint was refused
3566/// at layer 0, so affinity reuse was 100% dead on step37 and every turn paid a full re-prime.
3567///
3568/// WHY DROPPING IS EXACT, NOT LENIENT. The mirror is not an independent plane: it is created by
3569/// hydrating from the local plane, and every TP decode gathers its rank shards back and appends
3570/// them into the local plane in the same step (`append_kv_quantized` into `local.k/v`, then
3571/// `local.len = base_len + 1`), which is why every TP entry point asserts
3572/// `distributed.committed_len() == local.len`. The local plane is therefore authoritative and
3573/// complete. Clearing the mirror reproduces the checkpoint-time state LITERALLY (the snapshot
3574/// says this layer had no mirror), and the rebuild reads the same bytes the checkpoint saw.
3575///
3576/// WHY THE `MEMRA_NO_LOCAL_SHADOW=1` DOOR DOES NOT BREAK THIS. That door skips the local-plane
3577/// gathers and appends in the eager v2 TP decode: lengths still advance, contents go STALE
3578/// (tp.rs::no_local_shadow_on). It is ON in the step37 serving env, so "the local plane is
3579/// authoritative" is NOT true of rows written by a TP decode under that door. The drop is
3580/// nonetheless safe, and self-guarding: `DropMirror` fires ONLY when the snapshot recorded NO
3581/// mirror for the layer, and a snapshot with no mirror is proof that no TP decode had yet run in
3582/// that cache's life (the mirror is created by the first TP use). Since the restore truncates the
3583/// local plane to exactly that snapshot length, every surviving row predates the first TP decode
3584/// and was therefore written by a PRIME, which always writes the local plane in full. The
3585/// rehydration cannot read a shadow-skipped row. Rows above the boundary are discarded and
3586/// re-primed by the suffix. The door also never rebases the local ring during decode (it does not
3587/// call `prepare_kv_append`), so the physical layout below the boundary is exactly as the prime
3588/// left it.
3589///
3590/// WHY NOT "MATERIALIZE BEFORE SNAPSHOT". The checkpoint is captured MID-PRIME. Nothing in the
3591/// non-TP-prefill prime path maintains a mirror, so a mirror created at capture time would be
3592/// stranded at the boundary length while the rest of the prime appends to the local plane only,
3593/// and the first decode would hard-error on `cache lengths diverged before decode`. Eager
3594/// materialization converts a re-prime into an outage.
3595///
3596/// Every genuinely inconsistent arm still refuses.
3597/// `source_has_tp`: `None` = in-place rewind; `Some(has_tp)` = restore into a freshly grown cache.
3598pub(crate) fn tp_restore_plan(
3599    snap_len: Option<usize>,
3600    source_has_tp: Option<bool>,
3601    target_has_tp: bool,
3602    token_graph_door: bool,
3603) -> TpRestore {
3604    match (source_has_tp, snap_len) {
3605        (None, Some(len)) => {
3606            if target_has_tp {
3607                TpRestore::Rewind(len)
3608            } else {
3609                TpRestore::Refuse(TpRestoreRefusal::TargetAbsent)
3610            }
3611        }
3612        (None, None) => {
3613            if !target_has_tp {
3614                TpRestore::Nothing
3615            } else if token_graph_door {
3616                TpRestore::Refuse(TpRestoreRefusal::TokenGraphDoorOpen)
3617            } else {
3618                TpRestore::DropMirror
3619            }
3620        }
3621        (Some(source_has_tp), Some(len)) => {
3622            if !source_has_tp {
3623                TpRestore::Refuse(TpRestoreRefusal::SourceAbsent)
3624            } else if target_has_tp {
3625                TpRestore::Refuse(TpRestoreRefusal::GrowTargetNotFresh)
3626            } else {
3627                TpRestore::Grow(len)
3628            }
3629        }
3630        (Some(_), None) => {
3631            if target_has_tp {
3632                // A freshly allocated cache must not already carry a mirror.
3633                TpRestore::Refuse(TpRestoreRefusal::GrowTargetNotFresh)
3634            } else {
3635                // The snapshot predates the source's mirror (or the source never had one). Leave
3636                // the grown target without one: the next TP use hydrates it from the local rows
3637                // this restore just copied in. Before the step37 fix a source that HELD a mirror
3638                // here was a hard refusal, which killed every grow-path affinity reuse too.
3639                TpRestore::Nothing
3640            }
3641        }
3642    }
3643}
3644
3645/// Restore a cache checkpoint through each layer's owning engine.
3646///
3647/// `source = None` is an in-place rewind: the target already owns the append-only KV bytes and
3648/// only its lengths plus recurrent state move back to the snapshot. `Some(source)` restores into
3649/// a freshly allocated larger cache: checkpoint-valid KV rows are copied from the parked cache,
3650/// rank-local TP sidecars are rebuilt through their model-owned runtimes, and recurrent state
3651/// always comes from the checkpoint's owned device copies.
3652///
3653/// This cannot use `Cache::rollback(e, ...)` under cross-device PP: a single primary engine is
3654/// not the owner of every stage's cache buffers. The rare rewind/grow boundary synchronizes open
3655/// PP contexts before publishing the restored cache to the next request.
3656pub fn restore_cache_checkpoint(
3657    e: &Engine,
3658    model: &crate::hybrid::HybridModel,
3659    source: Option<&crate::cache::Cache>,
3660    target: &mut crate::cache::Cache,
3661    snap: &crate::cache::CacheSnapshot,
3662) -> Result<(), Box<dyn std::error::Error>> {
3663    target.ensure_usable("restore_cache_checkpoint target")?;
3664    if let Some(source) = source {
3665        source.ensure_usable("restore_cache_checkpoint source")?;
3666    }
3667    let cfg = &model.cfg;
3668    let n = target.kv.len();
3669    if target.recur.len() != n
3670        || target.tp_kv.len() != n
3671        || snap.kv_len.len() != n
3672        || snap.tp_kv_len.len() != n
3673        || snap.conv.len() != n
3674        || snap.ssm.len() != n
3675        || source.is_some_and(|s| s.kv.len() != n || s.recur.len() != n || s.tp_kv.len() != n)
3676    {
3677        return Err("checkpoint cache layer-count mismatch".into());
3678    }
3679    if snap.pos > target.max_ctx {
3680        return Err(format!(
3681            "checkpoint pos {} exceeds target capacity {}",
3682            snap.pos, target.max_ctx,
3683        )
3684        .into());
3685    }
3686
3687    let n_trunk = (cfg.n_layer - cfg.nextn_predict_layers) as usize;
3688    // Read the door ONCE: the refusal it drives must be uniform across layers within a restore.
3689    let token_graph_door = crate::tp::step_tp_graph_enabled().unwrap_or(false);
3690    let mut dropped_mirrors = 0usize;
3691    for il in 0..n {
3692        let owner = layer_engine(e, n_trunk, il)?;
3693        let src_kv = source.map(|s| &s.kv[il]);
3694        match (src_kv, target.kv[il].as_mut(), snap.kv_len[il]) {
3695            (Some(Some(src)), Some(dst), Some(len)) => {
3696                if len > src.len || len > target.max_ctx {
3697                    return Err(format!(
3698                        "checkpoint layer {il} len {len} exceeds source {} or target {}",
3699                        src.len, target.max_ctx,
3700                    )
3701                    .into());
3702                }
3703                if src.kv_dim_k != dst.kv_dim_k
3704                    || src.kv_dim_v != dst.kv_dim_v
3705                    || src.k_tok_bytes != dst.k_tok_bytes
3706                    || src.v_tok_bytes != dst.v_tok_bytes
3707                {
3708                    return Err(format!("checkpoint KV layout mismatch at layer {il}").into());
3709                }
3710                match (&src.ring, dst.ring.as_ref()) {
3711                    (Some(sring), Some(dring)) => {
3712                        // SWA ring: `len` is ABSOLUTE and can exceed the physical row count once
3713                        // the ring has lapped (the 2026-08-29 warm-turn-at-40k panic: a flat
3714                        // `len`-row copy sliced past the window-sized buffer). Copy only the
3715                        // aligned live window and rebase the fresh target to its start — the
3716                        // same geometry `ResidentTpKvCache::prepare_grow` already uses.
3717                        if dring.base() != 0 {
3718                            return Err(format!(
3719                                "checkpoint SWA restore at layer {il} requires a fresh target \
3720                                 ring (base {}, expected 0)",
3721                                dring.base(),
3722                            )
3723                            .into());
3724                        }
3725                        let (new_base, phys) = sring.restore_plan(len).map_err(|e| {
3726                            format!("checkpoint SWA restore refused at layer {il}: {e}")
3727                        })?;
3728                        let rows = phys.len();
3729                        let kb = rows * src.k_tok_bytes;
3730                        let vb = rows * src.v_tok_bytes;
3731                        if kb > 0 {
3732                            owner.copy_u8_range_into(
3733                                &mut dst.k,
3734                                0,
3735                                &src.k,
3736                                phys.start * src.k_tok_bytes,
3737                                kb,
3738                            )?;
3739                        }
3740                        if vb > 0 {
3741                            owner.copy_u8_range_into(
3742                                &mut dst.v,
3743                                0,
3744                                &src.v,
3745                                phys.start * src.v_tok_bytes,
3746                                vb,
3747                            )?;
3748                        }
3749                        dst.ring
3750                            .as_mut()
3751                            .expect("ring presence checked above")
3752                            .apply_rebase(new_base);
3753                        if let Some(base_d) = dst.base_d.as_mut() {
3754                            owner.set_i32_one(base_d, new_base as i32)?;
3755                        }
3756                    }
3757                    (None, None) => {
3758                        let kb = len * src.k_tok_bytes;
3759                        let vb = len * src.v_tok_bytes;
3760                        if kb > 0 {
3761                            owner.copy_u8_into(&mut dst.k, 0, &src.k, kb)?;
3762                        }
3763                        if vb > 0 {
3764                            owner.copy_u8_into(&mut dst.v, 0, &src.v, vb)?;
3765                        }
3766                    }
3767                    _ => {
3768                        return Err(
3769                            format!("checkpoint ring/flat KV mismatch at layer {il}").into()
3770                        );
3771                    }
3772                }
3773                dst.len = len;
3774                owner.set_i32_one(&mut dst.len_d, len as i32)?;
3775            }
3776            (None, Some(dst), Some(len)) => {
3777                if len > dst.len || len > target.max_ctx {
3778                    return Err(format!(
3779                        "checkpoint layer {il} len {len} exceeds live {} or target {}",
3780                        dst.len, target.max_ctx,
3781                    )
3782                    .into());
3783                }
3784                if let Some(ring) = &dst.ring
3785                    && !ring.can_rewind_to(len)
3786                {
3787                    return Err(format!(
3788                        "checkpoint SWA rewind at layer {il} has been lapped \
3789                             (len {len}, ring base {}); full re-prime required",
3790                        ring.base(),
3791                    )
3792                    .into());
3793                }
3794                dst.len = len;
3795                owner.set_i32_one(&mut dst.len_d, len as i32)?;
3796            }
3797            (Some(None), None, None) | (None, None, None) => {}
3798            _ => return Err(format!("checkpoint KV kind mismatch at layer {il}").into()),
3799        }
3800
3801        match tp_restore_plan(
3802            snap.tp_kv_len[il],
3803            source.map(|s| s.tp_kv[il].is_some()),
3804            target.tp_kv[il].is_some(),
3805            token_graph_door,
3806        ) {
3807            TpRestore::Nothing => {}
3808            TpRestore::Rewind(len) => target.tp_kv[il]
3809                .as_mut()
3810                .expect("tp_restore_plan::Rewind implies a present target mirror")
3811                .rewind_to(len)?,
3812            TpRestore::Grow(len) => {
3813                let src = source
3814                    .and_then(|s| s.tp_kv[il].as_ref())
3815                    .expect("tp_restore_plan::Grow implies a present source mirror");
3816                let runtime = model.step_tp_runtime_for_layer(il).ok_or_else(|| {
3817                    format!("checkpoint TP KV layer {il} has no distributed runtime")
3818                })?;
3819                let grown = runtime.grow_tp_kv_cache(src, target.max_ctx, len)?;
3820                target.tp_kv[il] = Some(grown);
3821            }
3822            TpRestore::DropMirror => {
3823                // The snapshot predates this layer's lazily-created distributed mirror. Clear it
3824                // and let `ensure_step_tp_kv_cache` rebuild it from the authoritative local
3825                // plane on the next TP use. See `tp_restore_plan` for why this is exact.
3826                if target.tp_kv[il].take().is_some() {
3827                    dropped_mirrors += 1;
3828                }
3829            }
3830            TpRestore::Refuse(reason) => {
3831                return Err(format!(
3832                    "checkpoint TP KV restore refused at layer {il}: {} \
3833                     (snap.tp_kv_len={:?}, snap.kv_len={:?}, snap.pos={}, \
3834                     source_has_tp={:?}, target_has_tp={}, target_committed={})",
3835                    match reason {
3836                        TpRestoreRefusal::TargetAbsent =>
3837                            "the snapshot recorded a distributed length but the target holds no \
3838                             distributed cache to rewind",
3839                        TpRestoreRefusal::SourceAbsent =>
3840                            "the snapshot recorded a distributed length the parked source cannot \
3841                             supply",
3842                        TpRestoreRefusal::GrowTargetNotFresh =>
3843                            "the freshly allocated grow target already holds a distributed cache",
3844                        TpRestoreRefusal::TokenGraphDoorOpen =>
3845                            "MEMRA_STEP_TP_GRAPH is open, and its model-level whole-token graph \
3846                             bakes the rank-cache pointers, so the stale mirror cannot be freed",
3847                    },
3848                    snap.tp_kv_len[il],
3849                    snap.kv_len[il],
3850                    snap.pos,
3851                    source.map(|s| s.tp_kv[il].is_some()),
3852                    target.tp_kv[il].is_some(),
3853                    target.tp_kv[il]
3854                        .as_ref()
3855                        .map(|c| c.committed_len())
3856                        .unwrap_or(0),
3857                )
3858                .into());
3859            }
3860        }
3861
3862        match (target.recur[il].as_mut(), &snap.conv[il], &snap.ssm[il]) {
3863            (Some(dst), Some(conv), Some(ssm)) => {
3864                if conv.len() != dst.conv_state.len() || ssm.len() != dst.ssm_state.len() {
3865                    return Err(
3866                        format!("checkpoint recurrent layout mismatch at layer {il}").into(),
3867                    );
3868                }
3869                owner.copy_into(&mut dst.conv_state, 0, conv, conv.len())?;
3870                owner.copy_into(&mut dst.ssm_state, 0, ssm, ssm.len())?;
3871            }
3872            (None, None, None) => {}
3873            _ => {
3874                return Err(format!("checkpoint recurrent kind mismatch at layer {il}").into());
3875            }
3876        }
3877    }
3878    target.pos = snap.pos;
3879    if dropped_mirrors > 0 {
3880        // ENGAGEMENT RECEIPT. Before this fix the same condition returned "checkpoint TP KV kind
3881        // mismatch at layer 0" and the caller dropped the session for a full re-prime. This line
3882        // proves the restore took the rebuild path instead.
3883        eprintln!(
3884            "[pp] checkpoint restore: cleared {dropped_mirrors} stale distributed KV mirror(s) \
3885             at pos {} (snapshot predates lazy TP hydration); the next TP use rehydrates them \
3886             from the local plane",
3887            snap.pos,
3888        );
3889    }
3890
3891    // Open PP uses per-stage streams/contexts; publish every restored plane before the caller
3892    // starts the next prime. Door-shut single-stream restores remain naturally ordered.
3893    sync_stages_after_load(e, n_trunk)?;
3894    if source.is_some() {
3895        // A grown cache replaces and drops the source immediately after this returns. Bound the
3896        // D2D copies first so an async-pool free cannot recycle a source plane prematurely.
3897        e.stream().synchronize()?;
3898    }
3899    Ok(())
3900}
3901
3902#[cfg(test)]
3903mod host_bounce_tests {
3904    use super::{
3905        BoundaryTransport, DUAL_PP_HOST_BOUNCE_REFUSAL, DUAL_PP_SINGLE_SLOT_REFUSAL,
3906        PEER_PROBE_FIXED_BYTES, PEER_PROBE_REQUIRED_REFUSAL, PEER_PROBE_TOKEN_WIDTHS,
3907        PEER_RUNTIME_PROBE_BUDGET_NS, PEER_RUNTIME_PROBE_CYCLE_COPIES,
3908        PEER_RUNTIME_PROBE_DEFERRAL_BOUND_INTERVALS, PEER_RUNTIME_PROBE_INTERVAL_COPIES,
3909        PP_WAVE_MAX_STAGES, PeerProbeDecision, PeerProbeStartupPolicy, acquire_pp_walk,
3910        boundary_slot_growth_elements, boundary_transport, dual_pp_eligibility,
3911        dual_pp_timing_dropped, dual_pp_timing_snapshot, dual_pp_wave_mid, enter_pp_wave_cell,
3912        host_bounce_capacity, latch_runtime_host_bounce, peer_probe_bytes_to_f32,
3913        peer_probe_decision, peer_probe_f32_to_bytes, peer_probe_mismatch_count,
3914        peer_probe_pattern, peer_probe_startup_policy, pp_devices_repeat, pp_wave_diagonal,
3915        pp_wave_eligibility, pp_wave_numeric_eligibility, pp_wave_on_value, pp_wave_ranges,
3916        pp_wave_route_enabled, pp_wave_snapshot, publish_runtime_peer_probe_deferral,
3917        record_dual_pp_stage_result, record_pp_wave_tick, runtime_peer_probe_candidate,
3918        runtime_peer_probe_next_copy,
3919    };
3920
3921    // ---- lane/step37 session-affinity TP-mirror regression (2026-08-28) -------------------
3922    //
3923    // BEFORE this fix `restore_cache_checkpoint` refused with "checkpoint TP KV kind mismatch at
3924    // layer 0" whenever a checkpoint captured mid-prime (tp_kv not yet lazily created) met a
3925    // target whose first decode had since materialized the mirror. That is EVERY step37
3926    // session-affinity reuse, so reuse was 100% dead and every turn paid a full re-prime.
3927    // The `mismatch_*` cases below assert the new outcome; each of them was a hard refusal
3928    // before. The `refuses_*` cases pin the arms that must STILL fail closed.
3929
3930    use super::{TpRestore, TpRestoreRefusal, tp_restore_plan};
3931
3932    #[test]
3933    fn mismatch_snapshot_predating_lazy_tp_drops_the_mirror_instead_of_refusing() {
3934        // in-place rewind, snapshot has no distributed length, target materialized one.
3935        assert_eq!(
3936            tp_restore_plan(None, None, true, false),
3937            TpRestore::DropMirror
3938        );
3939    }
3940
3941    #[test]
3942    fn mismatch_on_the_grow_path_leaves_the_fresh_target_without_a_mirror() {
3943        // Grow path, snapshot predates the source's mirror, fresh target has none. Build none and
3944        // let the next TP use hydrate from the copied local rows. This arm REFUSED before the fix.
3945        assert_eq!(
3946            tp_restore_plan(None, Some(true), false, false),
3947            TpRestore::Nothing
3948        );
3949    }
3950
3951    #[test]
3952    fn drop_is_refused_while_the_token_graph_door_bakes_rank_pointers() {
3953        assert_eq!(
3954            tp_restore_plan(None, None, true, true),
3955            TpRestore::Refuse(TpRestoreRefusal::TokenGraphDoorOpen)
3956        );
3957    }
3958
3959    #[test]
3960    fn healthy_arms_are_untouched() {
3961        assert_eq!(
3962            tp_restore_plan(None, None, false, false),
3963            TpRestore::Nothing
3964        );
3965        assert_eq!(tp_restore_plan(None, None, false, true), TpRestore::Nothing);
3966        assert_eq!(
3967            tp_restore_plan(Some(15222), None, true, false),
3968            TpRestore::Rewind(15222)
3969        );
3970        assert_eq!(
3971            tp_restore_plan(Some(15222), Some(true), false, false),
3972            TpRestore::Grow(15222)
3973        );
3974        assert_eq!(
3975            tp_restore_plan(None, Some(false), false, false),
3976            TpRestore::Nothing
3977        );
3978    }
3979
3980    #[test]
3981    fn refuses_a_recorded_distributed_length_with_no_target_mirror() {
3982        assert_eq!(
3983            tp_restore_plan(Some(15222), None, false, false),
3984            TpRestore::Refuse(TpRestoreRefusal::TargetAbsent)
3985        );
3986    }
3987
3988    #[test]
3989    fn refuses_a_recorded_distributed_length_the_source_cannot_supply() {
3990        assert_eq!(
3991            tp_restore_plan(Some(15222), Some(false), false, false),
3992            TpRestore::Refuse(TpRestoreRefusal::SourceAbsent)
3993        );
3994    }
3995
3996    #[test]
3997    fn refuses_a_grow_target_that_is_not_fresh() {
3998        assert_eq!(
3999            tp_restore_plan(Some(15222), Some(true), true, false),
4000            TpRestore::Refuse(TpRestoreRefusal::GrowTargetNotFresh)
4001        );
4002        assert_eq!(
4003            tp_restore_plan(None, Some(true), true, false),
4004            TpRestore::Refuse(TpRestoreRefusal::GrowTargetNotFresh)
4005        );
4006    }
4007
4008    // ---- 2026-08-11 default-flip safety regression (owner-ordered) ----------------------
4009    // All pure-resolution tests: no env mutation (parallel test threads share process env).
4010
4011    #[test]
4012    fn flip_default_is_dual_auto_with_explicit_off_and_forced_seams() {
4013        use super::{DualPpMode, dual_pp_mode_resolve};
4014        assert_eq!(dual_pp_mode_resolve(None), DualPpMode::Auto);
4015        assert_eq!(dual_pp_mode_resolve(Some("0")), DualPpMode::Off);
4016        assert_eq!(dual_pp_mode_resolve(Some("1")), DualPpMode::Forced);
4017        // Any other value is not a silent third state: treat as the default.
4018        assert_eq!(dual_pp_mode_resolve(Some("2")), DualPpMode::Auto);
4019        assert_eq!(dual_pp_mode_resolve(Some("")), DualPpMode::Auto);
4020    }
4021
4022    #[test]
4023    fn flip_overlap_follows_mode_and_one_flag_restores_preflip_serial() {
4024        use super::{DualPpMode, pp2_overlap_resolve};
4025        // Naked default = the re-gated dual arm: overlap ON.
4026        assert!(pp2_overlap_resolve(None, DualPpMode::Auto));
4027        // MEMRA_DUAL_PP=0 ALONE restores the exact pre-flip naked path (single-slot serial).
4028        assert!(!pp2_overlap_resolve(None, DualPpMode::Off));
4029        // The explicit pre-flip request keeps its binding single-slot refusal reachable.
4030        assert!(!pp2_overlap_resolve(None, DualPpMode::Forced));
4031        // Explicit values always win over the mode.
4032        for mode in [DualPpMode::Off, DualPpMode::Forced, DualPpMode::Auto] {
4033            assert!(pp2_overlap_resolve(Some("1"), mode));
4034            assert!(!pp2_overlap_resolve(Some("0"), mode));
4035        }
4036    }
4037
4038    #[test]
4039    fn flip_auto_routes_only_the_regated_regime_and_degrades_serially_elsewhere() {
4040        use super::{DualPpMode, dual_pp_route};
4041        // The exact box1 re-gate regime: PP-2, double-slot, peer transport, B>=2.
4042        assert!(dual_pp_route(DualPpMode::Auto, 2, 2, true, false));
4043        assert!(dual_pp_route(DualPpMode::Auto, 17, 2, true, false));
4044        // Outside it, Auto must DEGRADE (serial PP-N walker), never refuse:
4045        assert!(!dual_pp_route(DualPpMode::Auto, 1, 2, true, false)); // no second wave
4046        assert!(!dual_pp_route(DualPpMode::Auto, 2, 3, true, false)); // naked PP-3 keeps serving
4047        assert!(!dual_pp_route(DualPpMode::Auto, 2, 2, false, false)); // single-slot boundary
4048        assert!(!dual_pp_route(DualPpMode::Auto, 2, 2, true, true)); // host-bounce escape hatch
4049        // Forced routes every B>=2 call into the dual body so the binding refusals fire loud.
4050        assert!(dual_pp_route(DualPpMode::Forced, 2, 3, false, true));
4051        assert!(!dual_pp_route(DualPpMode::Forced, 1, 2, true, false));
4052        // Off is the rollback seam: never dual.
4053        assert!(!dual_pp_route(DualPpMode::Off, 8, 2, true, false));
4054    }
4055
4056    #[test]
4057    fn pp_wave_flag_is_strict_and_does_not_inherit_the_pp2_default() {
4058        assert_eq!(pp_wave_on_value(None), Ok(false));
4059        assert!(pp_wave_on_value(Some("")).is_err());
4060        assert_eq!(pp_wave_on_value(Some("0")), Ok(false));
4061        assert_eq!(pp_wave_on_value(Some("1")), Ok(true));
4062        assert!(pp_wave_on_value(Some("auto")).is_err());
4063        assert!(pp_wave_on_value(Some("2")).is_err());
4064    }
4065
4066    #[test]
4067    fn pp_wave_route_treats_overlap_off_and_single_work_item_as_serial_rollback() {
4068        assert!(pp_wave_route_enabled(true, true, 3, 2));
4069        assert!(pp_wave_route_enabled(true, true, 4, 8));
4070        assert!(!pp_wave_route_enabled(true, false, 3, 8));
4071        assert!(!pp_wave_route_enabled(false, true, 3, 8));
4072        assert!(!pp_wave_route_enabled(true, true, 2, 8));
4073        assert!(!pp_wave_route_enabled(true, true, 4, 1));
4074    }
4075
4076    #[test]
4077    fn pp_wave_ranges_are_balanced_contiguous_and_priority_preserving() {
4078        assert!(pp_wave_ranges(0, 4).is_empty());
4079        assert!(pp_wave_ranges(8, 0).is_empty());
4080        assert_eq!(pp_wave_ranges(1, 4), vec![(0, 1)]);
4081        assert_eq!(pp_wave_ranges(2, 4), vec![(0, 1), (1, 2)]);
4082        assert_eq!(pp_wave_ranges(8, 4), vec![(0, 2), (2, 4), (4, 6), (6, 8)]);
4083        assert_eq!(
4084            pp_wave_ranges(17, 4),
4085            vec![(0, 5), (5, 9), (9, 13), (13, 17)]
4086        );
4087        for batch in 1..=64 {
4088            for stages in 2..=PP_WAVE_MAX_STAGES {
4089                let ranges = pp_wave_ranges(batch, stages);
4090                assert_eq!(ranges.len(), batch.min(stages));
4091                assert_eq!(ranges.first().copied().unwrap().0, 0);
4092                assert_eq!(ranges.last().copied().unwrap().1, batch);
4093                assert!(ranges.iter().all(|(lo, hi)| lo < hi));
4094                assert!(ranges.windows(2).all(|pair| pair[0].1 == pair[1].0));
4095                let widths: Vec<_> = ranges.iter().map(|(lo, hi)| hi - lo).collect();
4096                assert!(widths.windows(2).all(|pair| pair[0] >= pair[1]));
4097                assert!(widths.first().unwrap() - widths.last().unwrap() <= 1);
4098            }
4099        }
4100    }
4101
4102    #[test]
4103    fn pp_wave_diagonals_cover_the_grid_without_stage_or_wave_aliasing() {
4104        for stages in 3..=PP_WAVE_MAX_STAGES {
4105            for waves in 1..=stages {
4106                let mut seen = vec![vec![false; stages]; waves];
4107                for diagonal in 0..stages + waves - 1 {
4108                    let cells = pp_wave_diagonal(stages, waves, diagonal);
4109                    let mut stage_seen = vec![false; stages];
4110                    let mut wave_seen = vec![false; waves];
4111                    for (wave, stage) in cells {
4112                        assert_eq!(wave + stage, diagonal);
4113                        assert!(!stage_seen[stage]);
4114                        assert!(!wave_seen[wave]);
4115                        assert!(!seen[wave][stage]);
4116                        stage_seen[stage] = true;
4117                        wave_seen[wave] = true;
4118                        seen[wave][stage] = true;
4119                    }
4120                }
4121                assert!(seen.into_iter().flatten().all(|cell| cell));
4122            }
4123        }
4124        assert!(pp_wave_diagonal(4, 4, 7).is_empty());
4125    }
4126
4127    #[test]
4128    fn pp_wavefront_refuses_every_unqualified_transport_shape() {
4129        assert!(pp_wave_eligibility(3, true, false, false).is_ok());
4130        assert!(pp_wave_eligibility(4, true, false, false).is_ok());
4131        assert!(pp_wave_eligibility(2, true, false, false).is_err());
4132        assert!(pp_wave_eligibility(5, true, false, false).is_err());
4133        assert!(pp_wave_eligibility(3, false, false, false).is_err());
4134        assert!(pp_wave_eligibility(3, true, true, false).is_err());
4135        assert!(pp_wave_eligibility(3, true, false, true).is_err());
4136    }
4137
4138    #[test]
4139    fn pp_wavefront_requires_width_invariant_bf16_for_w4a16() {
4140        assert!(pp_wave_numeric_eligibility(false, false).is_ok());
4141        assert!(pp_wave_numeric_eligibility(false, true).is_ok());
4142        assert!(pp_wave_numeric_eligibility(true, true).is_ok());
4143        assert!(pp_wave_numeric_eligibility(true, false).is_err());
4144    }
4145
4146    #[test]
4147    fn pp_device_aliases_cannot_bypass_the_distinct_stage_gate() {
4148        assert!(!pp_devices_repeat("0,1,2,3"));
4149        assert!(pp_devices_repeat("0,00,1"));
4150        assert!(pp_devices_repeat("2,1,2"));
4151        assert!(pp_devices_repeat("0,nope,1"));
4152    }
4153
4154    #[test]
4155    fn pp_walk_owner_refuses_reentry_and_releases_at_scope_end() {
4156        let active = std::sync::Arc::new(std::sync::atomic::AtomicU64::new(0));
4157        let next = std::sync::atomic::AtomicU64::new(1);
4158        let first = acquire_pp_walk(&active, &next, 7, None, "first").unwrap();
4159        let held_clone = super::PpWalkLease {
4160            state: first.state.clone(),
4161        };
4162        let error = acquire_pp_walk(&active, &next, 7, None, "second").unwrap_err();
4163        assert!(error.contains("refused concurrent PP walk"));
4164        drop(first);
4165        assert!(acquire_pp_walk(&active, &next, 7, None, "third").is_err());
4166        drop(held_clone);
4167        assert!(acquire_pp_walk(&active, &next, 7, None, "fourth").is_ok());
4168    }
4169
4170    #[test]
4171    fn boundary_growth_charges_first_allocation_and_only_missing_high_water_afterward() {
4172        assert_eq!(boundary_slot_growth_elements([0, 0], 4096), 8192);
4173        assert_eq!(boundary_slot_growth_elements([4096, 4096], 4096), 0);
4174        assert_eq!(boundary_slot_growth_elements([4096, 2048], 4096), 2048);
4175        assert_eq!(boundary_slot_growth_elements([8192, 8192], 4096), 0);
4176    }
4177
4178    #[test]
4179    fn pp_wave_liveness_snapshot_counts_ticks_cells_and_real_overlap() {
4180        let before = pp_wave_snapshot();
4181        let first = enter_pp_wave_cell();
4182        let second = enter_pp_wave_cell();
4183        drop(second);
4184        drop(first);
4185        record_pp_wave_tick();
4186        let after = pp_wave_snapshot();
4187        assert!(after.0 > before.0);
4188        assert!(after.1 >= before.1 + 2);
4189        assert!(after.2 > before.2);
4190    }
4191
4192    #[test]
4193    fn dual_pp_split_is_honest_at_one_and_ceil_first_afterward() {
4194        assert_eq!(dual_pp_wave_mid(1), None);
4195        assert_eq!(dual_pp_wave_mid(2), Some(1));
4196        assert_eq!(dual_pp_wave_mid(3), Some(2));
4197        assert_eq!(dual_pp_wave_mid(8), Some(4));
4198        assert_eq!(dual_pp_wave_mid(16), Some(8));
4199        assert_eq!(dual_pp_wave_mid(31), Some(16));
4200        assert_eq!(dual_pp_wave_mid(32), Some(16));
4201    }
4202
4203    #[test]
4204    fn dual_pp_refuses_single_slot_and_non_pp2_shapes() {
4205        assert_eq!(
4206            dual_pp_eligibility(2, false, false),
4207            Err(DUAL_PP_SINGLE_SLOT_REFUSAL)
4208        );
4209        assert!(dual_pp_eligibility(2, true, false).is_ok());
4210        assert!(dual_pp_eligibility(3, true, false).is_err());
4211    }
4212
4213    #[test]
4214    fn dual_pp_refuses_unvalidated_host_bounce_transport() {
4215        assert_eq!(
4216            dual_pp_eligibility(2, true, true),
4217            Err(DUAL_PP_HOST_BOUNCE_REFUSAL),
4218        );
4219    }
4220
4221    #[test]
4222    #[allow(clippy::int_plus_one)] // allow: the +1 form states the at-least-one-more-drop bound
4223    fn dual_pp_timing_error_is_counted_without_recording_a_sample() {
4224        let dropped_before = dual_pp_timing_dropped();
4225        let (_, samples_before) = dual_pp_timing_snapshot();
4226        record_dual_pp_stage_result(0, Err::<f32, _>("CUDA_ERROR_NOT_READY"));
4227        let (_, samples_after) = dual_pp_timing_snapshot();
4228        assert_eq!(samples_after[0], samples_before[0]);
4229        assert!(dual_pp_timing_dropped() >= dropped_before + 1);
4230    }
4231
4232    #[test]
4233    fn corrupted_peer_readback_fails_closed_unless_host_bounce_is_selected() {
4234        assert_eq!(
4235            PEER_PROBE_TOKEN_WIDTHS,
4236            [1, 8, 16, crate::cache::PRIME_CHUNK_MAX_TOKENS],
4237        );
4238        let largest_payload_bytes = PEER_PROBE_TOKEN_WIDTHS[3] * 4096 * std::mem::size_of::<f32>();
4239        assert_eq!(largest_payload_bytes, 64 * 1024 * 1024);
4240        assert!(largest_payload_bytes >= 1024 * 1024);
4241        let expected = peer_probe_pattern(PEER_PROBE_FIXED_BYTES, 2, 0, 1);
4242        assert_eq!(
4243            peer_probe_f32_to_bytes(&peer_probe_bytes_to_f32(&expected)),
4244            expected,
4245        );
4246        let mut corrupted = expected.clone();
4247        for offset in [0, 8_191, PEER_PROBE_FIXED_BYTES - 1] {
4248            corrupted[offset] ^= 0x5a;
4249        }
4250
4251        assert_eq!(peer_probe_mismatch_count(&expected, &corrupted), 3);
4252        assert_eq!(
4253            peer_probe_decision(&expected, &corrupted, false),
4254            Err("3 mismatched byte(s)".to_string()),
4255        );
4256        assert_eq!(
4257            peer_probe_decision(&expected, &corrupted, true),
4258            Ok(PeerProbeDecision::ProceedWithHostBounce { mismatches: 3 }),
4259        );
4260    }
4261
4262    #[test]
4263    fn probe_off_refusal_matrix_is_fail_closed_only_for_sharded_native_peer() {
4264        for probe_on in [false, true] {
4265            for sharded in [false, true] {
4266                for host_bounce in [false, true] {
4267                    let got = peer_probe_startup_policy(probe_on, sharded, host_bounce);
4268                    let expected = match (probe_on, sharded, host_bounce) {
4269                        (false, true, false) => Err(PEER_PROBE_REQUIRED_REFUSAL),
4270                        (false, true, true) => Ok(PeerProbeStartupPolicy::BypassedWithHostBounce),
4271                        _ => Ok(PeerProbeStartupPolicy::Allowed),
4272                    };
4273                    assert_eq!(
4274                        got, expected,
4275                        "probe_on={probe_on} sharded={sharded} host_bounce={host_bounce}",
4276                    );
4277                }
4278            }
4279        }
4280        assert!(PEER_PROBE_REQUIRED_REFUSAL.contains("MEMRA_PEER_PROBE=0"));
4281        assert!(PEER_PROBE_REQUIRED_REFUSAL.contains("MEMRA_PP_HOST_BOUNCE!=1"));
4282    }
4283
4284    #[test]
4285    fn runtime_reprobe_keeps_cheap_deadlines_live_while_expensive_work_waits_for_idle() {
4286        let every = PEER_RUNTIME_PROBE_INTERVAL_COPIES;
4287        assert_eq!(PEER_RUNTIME_PROBE_CYCLE_COPIES, 4 * every);
4288        let mut next = [every, 2 * every, 3 * every, 4 * every];
4289        let measured_ns = [1_000_000, 2_000_000, 3_000_000, 0];
4290
4291        assert_eq!(
4292            runtime_peer_probe_candidate(every - 1, next, measured_ns, false),
4293            None,
4294        );
4295        assert_eq!(
4296            runtime_peer_probe_candidate(every, next, measured_ns, false),
4297            Some((0, 1)),
4298        );
4299
4300        // Pretend the three cheap deadlines completed. The maximum rung is due but must not run
4301        // on the interactive boundary.
4302        next[..3].copy_from_slice(&[5 * every, 6 * every, 7 * every]);
4303        assert_eq!(
4304            runtime_peer_probe_candidate(4 * every, next, measured_ns, false),
4305            None,
4306        );
4307        // Once the next cheap deadline arrives, it remains runnable even though the older max
4308        // deadline is still pending.
4309        assert_eq!(
4310            runtime_peer_probe_candidate(5 * every, next, measured_ns, false),
4311            Some((0, 1)),
4312        );
4313        // An idle boundary drains the oldest pending rung first.
4314        assert_eq!(
4315            runtime_peer_probe_candidate(5 * every, next, measured_ns, true),
4316            Some((3, crate::cache::PRIME_CHUNK_MAX_TOKENS)),
4317        );
4318    }
4319
4320    #[test]
4321    fn runtime_reprobe_moves_any_measured_over_budget_rung_to_idle_only() {
4322        let every = PEER_RUNTIME_PROBE_INTERVAL_COPIES;
4323        let next = [u64::MAX, every, u64::MAX, u64::MAX];
4324        let mut measured_ns = [0; PEER_PROBE_TOKEN_WIDTHS.len()];
4325        measured_ns[1] = PEER_RUNTIME_PROBE_BUDGET_NS + 1;
4326        assert_eq!(
4327            runtime_peer_probe_candidate(every, next, measured_ns, false),
4328            None
4329        );
4330        assert_eq!(
4331            runtime_peer_probe_candidate(every, next, measured_ns, true),
4332            Some((1, 8)),
4333        );
4334    }
4335
4336    #[test]
4337    fn late_runtime_reprobe_advances_once_instead_of_bursting_catchup() {
4338        let every = PEER_RUNTIME_PROBE_INTERVAL_COPIES;
4339        let due = every;
4340        assert_eq!(runtime_peer_probe_next_copy(due, due), due + 4 * every);
4341        assert_eq!(runtime_peer_probe_next_copy(due, 20 * every), 21 * every);
4342    }
4343
4344    #[test]
4345    fn runtime_reprobe_deferral_metric_counts_intervals_and_publishes_bound_state() {
4346        use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
4347
4348        assert_eq!(
4349            PEER_RUNTIME_PROBE_DEFERRAL_BOUND_INTERVALS * PEER_RUNTIME_PROBE_INTERVAL_COPIES,
4350            PEER_RUNTIME_PROBE_CYCLE_COPIES,
4351        );
4352        let deferred = AtomicU64::new(0);
4353        let degraded = AtomicBool::new(false);
4354        publish_runtime_peer_probe_deferral(&deferred, &degraded, 1, false);
4355        assert_eq!(deferred.load(Ordering::Relaxed), 1);
4356        assert!(!degraded.load(Ordering::Acquire));
4357
4358        publish_runtime_peer_probe_deferral(
4359            &deferred,
4360            &degraded,
4361            PEER_RUNTIME_PROBE_DEFERRAL_BOUND_INTERVALS - 1,
4362            true,
4363        );
4364        assert_eq!(
4365            deferred.load(Ordering::Relaxed),
4366            PEER_RUNTIME_PROBE_DEFERRAL_BOUND_INTERVALS,
4367        );
4368        assert!(degraded.load(Ordering::Acquire));
4369    }
4370
4371    #[test]
4372    fn runtime_probe_failure_latches_native_before_publishing_validated_bounce() {
4373        use std::sync::atomic::{AtomicBool, Ordering};
4374
4375        let failed = AtomicBool::new(false);
4376        let degraded = AtomicBool::new(false);
4377        let armed = latch_runtime_host_bounce(&failed, &degraded, || Ok::<_, String>(()));
4378        assert!(armed.is_ok());
4379        assert!(failed.load(Ordering::Acquire));
4380        assert!(degraded.load(Ordering::Acquire));
4381
4382        let failed = AtomicBool::new(false);
4383        let degraded = AtomicBool::new(false);
4384        let refused = latch_runtime_host_bounce(&failed, &degraded, || {
4385            Err::<(), _>("injected staging mismatch".to_string())
4386        });
4387        assert_eq!(refused, Err("injected staging mismatch".to_string()));
4388        assert!(failed.load(Ordering::Acquire));
4389        assert!(!degraded.load(Ordering::Acquire));
4390    }
4391
4392    #[test]
4393    fn transport_selection_keeps_peer_default_and_bounces_only_cross_device() {
4394        assert_eq!(boundary_transport(false, false), BoundaryTransport::Local);
4395        assert_eq!(boundary_transport(false, true), BoundaryTransport::Local);
4396        assert_eq!(boundary_transport(true, false), BoundaryTransport::Peer);
4397        assert_eq!(
4398            boundary_transport(true, true),
4399            BoundaryTransport::HostBounce
4400        );
4401    }
4402
4403    #[test]
4404    fn step37_geometry_sizes_each_slot_from_the_prime_cap() {
4405        let (elems, bytes) = host_bounce_capacity(4096).expect("valid Step-3.7 geometry");
4406        assert_eq!(elems, 4096 * crate::cache::PRIME_CHUNK_MAX_TOKENS);
4407        assert_eq!(bytes, 64 * 1024 * 1024);
4408    }
4409
4410    #[test]
4411    fn host_bounce_capacity_rejects_invalid_or_overflowing_geometry() {
4412        assert!(host_bounce_capacity(0).is_err());
4413        assert!(host_bounce_capacity(usize::MAX).is_err());
4414    }
4415}