From af8fe57d1c15082e030a04d2eb95cc585cdae283 Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Fri, 1 May 2026 19:50:49 +0200 Subject: [PATCH] =?UTF-8?q?docs(sp5):=20apply=20critical=20review=20fixes?= =?UTF-8?q?=20=E2=80=94=20Layer=20D,=20Kelly=20carve-out,=20Pearl=204=20mi?= =?UTF-8?q?tigations,=20acceptance=20loosened?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical self-review surfaced 15 issues; user directed fixes: - "a no cpu path": KEEP host-EMA close-out (rule compliance) — but split into separate Layer D atomic commit (was mis-scoped as Layer A) - Pearl 4 kept: 3 concrete risks documented (constant-β proof break, β2 memory reset destabilization, ε numerical envelope), structural envelope bounds added, ALPHA_META halved, ε-only fall-back path defined - Pearl 6 Kelly cross-fold persistence carve-out: separate slot range 280..286, NOT in SP4 fold-reset registry, Invariant 1 architectural exception - Commit ordering Pearls 1 → 3 → 2 → 4 → 5 → 6 → 8 → 1-ext (resolves Pearl 2 circular dependency on 1+3) - Acceptance criteria: correctness gates (must pass) + performance gates (loosened to "not catastrophically negative", within 2σ of pre-SP5) - Pearl 7 timing: explicitly Layer C step 4, post-Layer-B + 3-seed validation - Pearl 8 enumeration: 4 slots (TRAIL_DIST_PER_DIR per direction) - Pearl 9 collapsed: 0 slots (Thompson achieved via Pearl 1's atom adaptation) - Total slot count corrected: 110 (was 120-128 inconsistent) Layer structure: A (additive, 8 commits) → B (atomic, 11 consumers) → C (validation + Pearl 7 investigation) → D (host-EMA close-out, separate atomic commit). Layer D split off from A's "close-out" because PnL aggregation pipeline migration is its own architectural concern. User final review pending before invoking writing-plans skill. --- ...ifferentiation-and-eval-collapse-design.md | 161 +++++++++++++----- 1 file changed, 114 insertions(+), 47 deletions(-) diff --git a/docs/superpowers/specs/2026-05-01-sp5-magnitude-differentiation-and-eval-collapse-design.md b/docs/superpowers/specs/2026-05-01-sp5-magnitude-differentiation-and-eval-collapse-design.md index dd2b2e40a..f287ccd1d 100644 --- a/docs/superpowers/specs/2026-05-01-sp5-magnitude-differentiation-and-eval-collapse-design.md +++ b/docs/superpowers/specs/2026-05-01-sp5-magnitude-differentiation-and-eval-collapse-design.md @@ -32,15 +32,15 @@ Plus all SP4 close-out and sweep deferrals (see [Scope](#scope) below). | 1-3 | Per-branch atom span / loss budget / NoisyNet σ | core SP5 | 52 | | 4 | Per-param-group Adam β1/β2/ε ISV-driven | from SP4 close-out memory | 24 (3 × 8 param groups) | | 5 | Per-branch IQN τ schedule | from SP5 out-of-scope | 20 (5 × 4 branches) | -| 6 | Kelly cap signal-driven floors | from project_magnitude_eval_collapse_kelly_capped.md | 6 | -| 7 | `dist_q/h/f Bin(2,0.5)` root-cause + action_select fix | new investigation | 0-8 | -| 8 | Trail stop signal-driven thresholds | new (Kelly-adjacent) | 6-8 | -| 9 | Thompson direction-branch temperature ISV-driven | from SP5 out-of-scope | 4 | +| 6 | Kelly cap signal-driven floors (cross-fold persistent — see [Pearl 6](#pearl-6-pearl_kelly_cap_signal_driven_floors)) | from project_magnitude_eval_collapse_kelly_capped.md | 6 | +| 7 | `dist_q/h/f Bin(2,0.5)` investigation only — fix in follow-up if needed | per Q2=a | **0** | +| 8 | Trail stop `base_trail_distance` signal-driven (per-direction) | new (Kelly-adjacent) | 4 | +| 9 | Thompson direction-branch temperature — **achieved via Pearl 1** (no separate slots) | per code audit | 0 | | 1-ext | Per-branch C51 num_atoms | extension of Pearl 1 | 4 | -| Layer A close-out | 5 host-EMA host→GPU migrations | from sweep audit | 5 sites (no slots) | +| Layer D close-out | 5 host-EMA host→GPU migrations (PnL aggregation pipeline → GPU) | from sweep audit, separate Layer | 5 sites | | Validation | 3-seed × 50-epoch harness as exit gate | from SP5 out-of-scope | (no code) | -**Total: 120-128 new ISV slots, ~5000-7500 LOC, 11-13 producer kernels, ~12 consumer migrations.** +**Total: 110 new ISV slots** (52 + 24 + 20 + 6 + 0 + 4 + 0 + 4 = 110). LOC ~5500-7500 across Layers A+B+D. 9-11 producer kernels. 11 consumer migrations. After SP5: zero deferrals on hardcoded multipliers in DQN training loop. Every adaptive value ISV-driven. @@ -75,9 +75,22 @@ Per-branch NoisyNet σ scales to per-branch Q-magnitude so noise/signal ratio st **Per Q3=a (include as designed, accept theoretical risk):** per-param-group Adam β1, β2, ε ISV-driven (8 SP4 param groups: DqnTrunk/Value/Branches/Iqn/IqlHigh/IqlLow/Attn/Curiosity). Each group's Adam dynamics adapt to per-group gradient signal-to-noise. -**Theoretical caveat:** Adam's original paper assumes constant β1/β2 across training. Per-group adaptive β1/β2 breaks this constant-β convergence guarantee. Mitigation: Pearls A+D smoothing prevents abrupt β-changes (Wiener α adapts gradually); EPS_CLAMP_FLOOR ensures β stays in [0.5, 0.999] structural envelope. Practical consequences monitored via Layer C smoke. If destabilization observed, fall back to Pearl 4 variant adapting ε only (β1, β2 stay constant). +**Theoretical caveat (3 concrete risks):** -**Producer signal:** per-group gradient direction-stability EMA (cosine similarity of consecutive gradients). High stability → β2 closer to 0.999 (long memory); low stability → β2 closer to 0.9 (short memory). β1 derived analogously from per-group gradient-magnitude variance. +1. **Adam's convergence proof requires constant β1, β2 across training.** Per-group adaptive β breaks this guarantee. Combined with Pearl 2 (per-branch loss budget), Adam's update direction becomes a moving target — could oscillate or saturate. No theoretical guarantee that the system converges. + +2. **β2 = 0.999 means ~1000-step memory of squared gradients.** Reducing β2 mid-training discards that memory; the variance estimate effectively resets, which can spike `m̂/√v̂` to large values and destabilize. Pearls A+D smoothing limits the rate of change but doesn't eliminate the discontinuity. + +3. **Per-group ε pushed too small (e.g. 1e-12) → numerical instability** (division-by-near-zero). Pushed too large (e.g. 1e-3) → loss of precision on small gradients. Auto-adapting could push outside the safe range. + +**Mitigations:** +- Pearls A+D Wiener α adapts gradually — no abrupt β changes step-to-step +- Structural β envelopes: β1 ∈ [0.85, 0.95], β2 ∈ [0.99, 0.9995], ε ∈ [1e-10, 1e-6] (Invariant 1 carve-outs) +- ALPHA_META in Pearls A+D set to **5e-4** (half the SP4 default 1e-3) to limit Pearl 4's β change rate +- Layer C smoke MUST monitor for destabilization (Q-explosion kill-criterion + per-group Adam-state checks) +- Fall-back: if destabilization observed in Layer C, revert Pearl 4 commit, replace with **ε-only adaptive** variant (β1=0.9, β2=0.999 stay Invariant 1 anchors; only ε adapts per-group). 8 slots instead of 24. + +**Producer signal:** per-group gradient direction-stability EMA (cosine similarity of consecutive gradients). High stability → β2 closer to 0.999 (long memory); low stability → β2 closer to 0.99 (short memory, narrower envelope). β1 derived analogously from per-group gradient-magnitude variance. ε derived from per-group gradient L2 norm scale. **Slots (24):** ADAM_BETA1[8], ADAM_BETA2[8], ADAM_EPS[8] @@ -93,11 +106,15 @@ Per-branch IQN τ quantiles `{τ_05, τ_25, τ_50, τ_75, τ_95}` adapt to per-b Kelly cap removes hardcoded `0.5` warmup_floor and `0.5 + 0.5 × h` health_safety formula. Replaces with Pearls A+D smoothed kelly_f + conviction + trade-variance signals. Sentinel bootstrap handles cold-start naturally. -**Slots (6):** KELLY_F_SMOOTH, CONVICTION_SMOOTH, TRADE_VAR_SMOOTH, KELLY_SAMPLE_COUNT, WIN_RATE_SMOOTH, LOSS_RATE_SMOOTH +**Cross-fold persistence carve-out:** Kelly cap's signals serve a cross-fold steady-state baseline purpose (see [`grad_norm_slow_ema_pinned` precedent in fold_warmup_factor_kernel docstring](../../crates/ml/src/trainers/dqn/state_reset_registry.rs)). The 6 Pearl 6 slots are **explicitly NOT in SP4's per-fold-reset registry** — they persist trade-history across fold boundaries by design. Documented as Invariant 1 architectural carve-out: cross-fold-persistent signals are exempt from sentinel-contract reset because their semantic purpose IS cross-fold continuity. + +Mechanism: Pearl 6 slots are allocated in a separate cross-fold-persistent ISV slot range (slots 280..286, NOT 174..226). State-reset registry has no entries for these slots; they retain values across fold boundaries throughout training. Pearls A+D bootstrap on first observation (training step 0); subsequent folds resume from prior state. + +**Slots (6, cross-fold persistent):** KELLY_F_SMOOTH, CONVICTION_SMOOTH, TRADE_VAR_SMOOTH, KELLY_SAMPLE_COUNT, WIN_RATE_SMOOTH, LOSS_RATE_SMOOTH ### Pearl 7: `pearl_action_select_decomposition_audit` (investigation-only in SP5) -**Per Q2=a (investigate-first):** Pearl 7 is dispatched as an INVESTIGATION TASK after Pearls 1-3 land in Layer A and Layer B's first smoke run. Hypothesis: `intent_dist` freezing at exact `Bin(2, 0.5)` ratio (0.25/0.50/0.25) may be incidentally resolved once Pearls 1-3 fix Q-flatness + per-branch σ. If resolved, Pearl 7 closes with no code changes. +**Per Q2=a (investigate-first):** Pearl 7 is dispatched as an INVESTIGATION TASK at Layer C step 4 — AFTER the full atomic Layer B commit lands AND the 3-seed × 50-epoch L40S validation completes. Hypothesis: `intent_dist` freezing at exact `Bin(2, 0.5)` ratio (0.25/0.50/0.25) may be incidentally resolved once Pearls 1-3 fix Q-flatness + per-branch σ. If resolved, Pearl 7 closes with no code changes. **If pattern persists post-Layer-B smoke:** root-cause `action_select_kernel` for hidden binary decomposition (e.g., 2 independent {0,1} bits sampled then summed for magnitude). Fix logic in a SEPARATE follow-up commit/spec — NOT bundled into SP5 atomic Layer B. @@ -105,15 +122,21 @@ Kelly cap removes hardcoded `0.5` warmup_floor and `0.5 + 0.5 × h` health_safet ### Pearl 8: `pearl_trail_stop_signal_driven` -Replace hardcoded `0.005f` ATR multiplier and other tuning constants in `check_trailing_stop` with per-trade signal-driven thresholds. ATR EMA, drawdown EMA, holding-time EMA all ISV-driven. Trail stop level adapts to per-trade volatility regime. +`check_trailing_stop` (`trade_physics.cuh:486`) takes `base_trail_distance` as kernel arg, currently hardcoded `0.005` (0.5%) at call site. `vol_scale` (CUSUM-based) and `trend_scale` (ADX-based) are already feature-driven adaptive multipliers. Floor constants (`hold_time<1.0f`, `peak_equity<1.0f`) are Invariant 1 carve-outs. -**Slots (6-8):** ATR_EMA, DRAWDOWN_EMA, HOLD_TIME_EMA, plus per-direction adaptive trail multipliers. +Pearl 8 migrates the `base_trail_distance` from hardcoded constant to per-direction ISV-driven signal. Producer signal: per-trade ATR EMA (volatility regime). Consumer: `check_trailing_stop` reads `ISV[TRAIL_DIST_PER_DIR + dir]` per call. -### Pearl 9: `pearl_thompson_temperature_signal_driven` +**Slots (4):** TRAIL_DIST_PER_DIR[4 directions: Short, Hold, Long, Flat] -Direction-branch Thompson sampling currently uses fixed temperature in `experience_action_select`. Make per-branch temperature ISV-driven from per-branch Q-distribution sharpness. Confident distributions → low temperature → near-argmax. Uncertain → high temperature → exploration. +(Hold/Flat directions read floor from EPS_CLAMP_FLOOR — they don't actually trigger trail stop but slot symmetry simplifies kernel signature.) -**Slots (4):** THOMPSON_TEMP[4 branches] +### Pearl 9 — REMOVED (achieved via Pearl 1) + +Code audit of `experience_action_select`'s Thompson direction-branch sampling: uses `sample_C51_inverse_cdf(probs_d, atoms_d, u)` where `atoms_d` IS the per-branch atom support. There is no explicit "temperature" parameter — the spread of the C51 distribution implicitly sets the exploration scale. + +**Therefore Pearl 9 collapses to zero scope.** Once Pearl 1 makes atom positions per-branch adaptive (per Pearl 1's `ATOM_V_CENTER` + `ATOM_V_HALF` + `ATOM_HEADROOM` slots), the Thompson distribution is automatically per-branch adaptive. No additional Pearl 9 slots needed. + +Documented here for completeness; the SP5 brainstorm flagged this as a question. Code inspection resolved it. ### Layer A close-out: host-EMA → GPU sweep migration @@ -130,42 +153,66 @@ Substantial: requires per-step trade-PnL aggregation kernel + multi-step composi ### Layer A — additive infrastructure -**Commit granularity: 1 commit per pearl** (decision Q1=c). ~9 commits in Layer A — Pearls 1-3 separately (3 commits), Pearl 4, Pearl 5, Pearl 6, Pearl 8, Pearl 9, Pearl 1-ext, plus the host-EMA→GPU close-out as 1 final commit. Pearl 7 is investigation-only (deferred to a separate post-Layer-B task per Q2). +**Commit granularity: 1 commit per pearl** (decision Q1=c). 8 commits in Layer A in this order (resolves Pearl 2's circular dependency on Pearls 1+3 — Pearl 2 lands after both): + +1. Pearl 1 (atom span — provides Q-stats producer that Pearl 2 depends on) +2. Pearl 3 (NoisyNet σ — provides σ that Pearl 2 depends on) +3. Pearl 2 (loss budget — depends on Pearls 1+3 outputs) +4. Pearl 4 (Adam β/β/ε — independent, can land anytime after Layer A starts) +5. Pearl 5 (IQN τ schedule — independent) +6. Pearl 6 (Kelly cap — cross-fold persistent slot range, NOT in fold-reset registry) +7. Pearl 8 (trail distance — independent) +8. Pearl 1-ext (per-branch num_atoms — extends Pearl 1, lands last) Each commit adds: 1. ISV slot constants (per pearl) 2. Producer kernel(s) 3. Pearls A+D wire-up via existing `apply_pearls_ad_kernel` -4. StateResetRegistry entries (sentinel contract: ISV slot AND Wiener triple together) +4. StateResetRegistry entries (sentinel contract: ISV slot AND Wiener triple together) — EXCEPT Pearl 6 (cross-fold persistent, no fold-reset entry) 5. Buffer growth + LAYOUT_FINGERPRINT_SEED bump (per commit accumulating) 6. GPU-gated unit tests -Final state: ~116-120 ISV slots wired (Pearl 7 investigation may add 0-8 in a follow-up), all producers running, no consumers migrated yet (zero behavior change). +Final state: 110 ISV slots wired, all producers running, no consumers migrated yet (zero behavior change). ### Layer B — atomic consumer migration -Single coordinated commit per `feedback_no_partial_refactor`. Migrates ~12 consumers: +Single coordinated commit per `feedback_no_partial_refactor`. Migrates 11 consumers: 1. `atoms_update_kernel.cu` — per-branch atom positions + counts from ISV 2. 4 `apply_*_saxpy` kernels — per-branch budget sub-launches (4 each = 16 sub-launches per step) 3. NoisyLinear forward kernel — per-branch σ scaling -4. 5 Adam launchers — per-group β1/β2/ε from ISV -5. IQL/IQN τ-quantile selection — per-branch τ from ISV +4. 5 Adam launchers — per-group β1/β2/ε from ISV (Pearl 4) +5. IQL/IQN τ-quantile selection — per-branch τ from ISV (Pearl 5) 6. `apply_kelly_cap` — Pearl 6 ISV reads, hardcoded floors removed -7. `check_trailing_stop` — Pearl 8 ISV reads -8. `experience_action_select` Thompson direction branch — Pearl 9 ISV reads -9. (if Phase 7.2) `experience_action_select` magnitude branch — Pearl 7 fix -10. PnL aggregation kernel — Layer A close-out (host→GPU) +7. `check_trailing_stop` callers — Pearl 8 ISV reads for `base_trail_distance` -Single large commit, ~2000-3000 LOC delta. Validates with smoke + L40S regression test post-commit. +(Pearl 9 collapsed to zero migrations — Thompson reads atoms via Pearl 1 already-migrated path.) +(Pearl 7 stays out of Layer B — investigation-only, follow-up if needed.) +(Layer D / host-EMA close-out is its own atomic commit, not in this Layer B.) + +Single large commit, ~1500-2200 LOC delta. Validates with smoke + L40S regression test post-commit. ### Layer C — validation + cleanup 1. Local 16+ GPU unit test pass on RTX 3050 Ti 2. L40S `multi_fold_convergence` smoke (5-epoch, single fold) — basic stability -3. L40S `train-multi-seed-baseline` (3-seed × 50-epoch × 3-fold) — full acceptance gate -4. Audit doc append (single comprehensive Layer A close-out + Layer B atomic + Layer C validation entry) -5. 9 new memory pearls + indices -6. Retire any superseded global slots / config fields +3. L40S `train-multi-seed-baseline` (3-seed × 50-epoch × 3-fold) — full acceptance gate (per acceptance criteria below) +4. Pearl 7 investigation: dispatched AFTER Layer C step 3 completes. If `intent_dist` no longer freezes at Bin(2,0.5), Pearl 7 closes with no code. If pattern persists, separate follow-up spec. +5. Audit doc append (single comprehensive Layer A close-out + Layer B atomic + Layer C validation entry) +6. 8 new memory pearls + indices (1-3, 4, 5, 6, 8, 1-ext, plus 1 cross-fold persistence pearl documenting Kelly carve-out) +7. Retire any superseded global slots / config fields + +### Layer D — host-EMA → GPU close-out (SEPARATE atomic commit, not bundled with Layer B) + +Migrate 5 remaining host-aggregated EMA sites to GPU per `feedback_no_cpu_compute_strict`: +- `training_sharpe_ema` — requires per-step PnL aggregation on GPU +- `max_dd_ema` — same +- `gamma_blend` — host-aggregated eval result, port to GPU +- `LearningHealth` composition pipeline — multi-step host arithmetic, port to GPU +- `HealthEmaTrackers` — q_gap_ema + q_var_ema + grad_norm_ema host-side EMAs + +**Substantial scope:** requires per-step trade-PnL aggregation kernel + multi-step composition kernel. Estimated 2000-3000 LOC across PnL aggregation pipeline (trade_physics outputs) + reward computation + LearningHealth composition. Lands as **single Layer D atomic commit** after Layer B validates. Reduces Layer B's blast radius by separating concerns. + +**Why separate Layer D, not within Layer A close-out:** PnL aggregation pipeline migration touches trade_physics + experience_collector + reward computation, which are distinct architectural concerns from per-branch adaptation. Bundling them into Layer A's "close-out" mis-scoped the work. Layer D as its own atomic commit allows independent validation + revert. ## Acceptance criteria @@ -177,26 +224,37 @@ Single large commit, ~2000-3000 LOC delta. Validates with smoke + L40S regressio ### Layer B acceptance (single commit) -After Layer B atomic commit: -- Multi_fold_convergence smoke succeeds (5 epochs F0) -- Per-branch HEALTH_DIAG shows expected adaptation patterns: - - `var(Q[branch=Mag])` > `σ_mag² × 4` - - `v_half_mag < 1.0` - - Per-fold trade_count > 100 +**Correctness gates (must pass):** +- Multi_fold_convergence smoke succeeds (5 epochs F0, all 3 folds reach epoch 5) - Zero graph capture failures -- All SP4-era smoke kill-criteria pass +- All SP4-era smoke kill-criteria pass (no NaN, no Q-explosion, no fold-boundary-grad-explosion) - New SP5 kill-criterion: `Q-flatness-kill` if `var(Q[b]) < 0.5 × σ[b]²` by F0 ep10 -### Layer C exit gate (full validation) +**Adaptation indicators (informative, NOT blocking):** +- `var(Q[branch=Mag])` shows growth from Layer A baseline (not stuck at 1e-9) +- `v_half_mag` < `v_half_dir` (per-branch atom adaptation visible) +- Per-fold trade_count > 50 (not the trivial 1-trade case from pre-SP5) + +**Layer B does NOT gate on absolute Sharpe** — performance characterization comes at Layer C exit gate. + +### Layer C exit gate (full 3-seed × 50-epoch validation) 3-seed × 50-epoch × 3-fold L40S run completes: -- All 9 fold-runs (3 seeds × 3 folds) reach epoch 50 -- Mean Best Sharpe across seeds positive -- intent_dist drifts epoch-to-epoch (not frozen) -- per-branch HEALTH_DIAG metrics show coherent adaptation -- Trade counts realistic (>100 per fold per seed) + +**Correctness gates (must pass — no NaN, basic stability):** +- All 9 fold-runs (3 seeds × 3 folds) reach epoch 50 without NaN/explosion +- intent_dist drifts epoch-to-epoch (not frozen at exact ratio across 3+ epochs) +- Per-fold trade_count > 100 (no eval-collapse degeneracy) +- Per-branch HEALTH_DIAG shows coherent adaptation (variance grows, atoms shrink for narrow-Q branches) - Memory pearls + audit doc landed +**Performance gates (reasonable bar — does NOT require strict positivity):** +- Mean Best Sharpe across seeds is **finite and not catastrophically negative** (defined as: > -50, equivalent to "not actively losing money at training-end-equity") +- Mean Best Sharpe across seeds is within **2× standard deviation** of pre-SP5 baseline (e.g., if pre-SP5 baseline mean was 25 ± 30, SP5 ≥ -35 is acceptable) +- val Sharpe variance across folds is finite (no degenerate single-trade Sharpe=67 cases — measured by `trade_count > 50`) + +**Performance is informative, not blocking:** SP5's primary goal is architectural correctness (every adaptive value ISV-driven). Performance improvements are expected secondary effect but not gate-able. + ## Architectural rules carryover from SP4 All `feedback_*` rules apply unchanged. Strict zero-tolerance: @@ -215,11 +273,20 @@ After SP5, no known adaptive-parameter deferrals remain in the DQN training loop If anything surfaces post-SP5 (e.g., reward shaping issues exposed by improved magnitude differentiation), separate spec. -## Resolved decisions (post-brainstorming) +## Resolved decisions (post-brainstorming + critical review) -- **Q1 → c**: Layer A commits = 1 per pearl (~9 commits total), no batching. Each pearl independently buildable + revertible. -- **Q2 → a**: Pearl 7 is investigation-only in SP5. Dispatched as task after Pearls 1-3 + Layer B smoke. If `Bin(2,0.5)` resolves incidentally, Pearl 7 closes with zero code. If persists, separate follow-up spec/commit. -- **Q3 → a**: Pearl 4 includes per-group β1/β2/ε with theoretical caveat documented. Mitigation: Pearls A+D smoothing + EPS_CLAMP_FLOOR β envelope. Layer C smoke monitors for destabilization; fall-back to ε-only if observed. +- **Q1 → c**: Layer A commits = 1 per pearl (8 commits total), ordering Pearls 1 → 3 → 2 → 4 → 5 → 6 → 8 → 1-ext to resolve Pearl 2's circular dependency on Pearls 1+3. +- **Q2 → a**: Pearl 7 is investigation-only. Dispatched as Layer C step 4 (AFTER full atomic Layer B + 3-seed × 50-epoch validation). If `Bin(2,0.5)` resolves incidentally, Pearl 7 closes with zero code. If persists, separate follow-up spec/commit. +- **Q3 → a**: Pearl 4 includes per-group β1/β2/ε with 3 concrete risks documented + structural envelopes + ALPHA_META halved + ε-only fall-back path defined. +- **Critical review fixes applied:** + - Pearl 6 cross-fold persistence carve-out (slots 280..286, NOT in fold-reset registry) + - Layer A close-out (host-EMA→GPU) split into separate Layer D (atomic, post-Layer-B) + - Pearl 9 collapsed to zero scope (achieved via Pearl 1) + - Pearl 7 timing clarified (Layer C step 4, post-validation) + - Layer B acceptance loosened: correctness gates required, performance gates loosened to "not catastrophically negative" + "within 2σ of pre-SP5 baseline" + - Pearl 4 mitigations + fall-back path concrete + - Pearl 8 enumeration concretized (4 slots: TRAIL_DIST_PER_DIR[4]) + - Total slot count corrected to 110 (was 120-128 inconsistent) ---