From e877e8aefe91ff912a54236890bb9f3cce44139b Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Sat, 9 May 2026 10:43:11 +0200 Subject: [PATCH] =?UTF-8?q?chore(sp18):=20archaeology=20cleanup=20?= =?UTF-8?q?=E2=80=94=20strip=20post-deletion=20markers=20+=20ISV=5FTOTAL?= =?UTF-8?q?=5FDIM=20giant=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure-comment follow-up to SP18 Phase 1 atomic deletion (3c318953a) and Phase 2 device-fn introduction (8da8e2e58). Strips the "DELETED by SP18 Phase 1" markers + "RETIRED" docstrings + per-slot SP3→SP18 archaeology that survived the focused deletion diff. Per feedback_no_legacy_aliases ("avoid backwards-compatibility hacks like removed-comment markers") and CLAUDE.md ("don't add comments that explain what the code does"), git history is the historical record — code shouldn't narrate its own deletion. Three categories cleaned: 1. ISV_TOTAL_DIM giant docstring in gpu_dqn_trainer.rs (Category 1): collapsed ~5000-char slot-by-slot SP3→SP18 history block into a 13-line conceptual definition pointing readers at sp14_isv_slots.rs for the actual range definitions. Layout fingerprint seed (RESERVED_GAP_461_TO_468=SP18_P1_RETIRED;) is load-bearing and preserved. 2. RETIRED markers in sp14_isv_slots.rs + state_layout.cuh (Category 2): deleted "SP16 Phase 2 RETIRED 2026-05-09" header blocks, "HCS_* slots [462..468) RETIRED" markers, "SP13 [380..383)/ SP16 [461..474) ALLOCATED but RETIRED per PP.4" prose, and the test-removal note before the surviving MHT block lock test. Tightened the SP16 T3 Wiener-α comment block to describe only the surviving MIN_HOLD_TEMPERATURE producer. 3. Stale doc-refs across the SP18 audit consumer set (Category 3): updated gpu_experience_collector.rs prose, sp5_isv_slots.rs SP13 v3 description, gpu_dqn_trainer.rs slot-380 constructor block, state_reset_registry.rs HRC_*/MHT_*/TDB_* "mirrors slot N" refs + the registry-block introduction comment + the deleted-test marker at end of file, training_loop.rs launcher-call/diag-emit/ dispatch-arms "DELETED" markers, build.rs cubin manifest "DELETED" marker, gpu_aux_trunk.rs trailing "HoldCostScaleUpdateOps DELETED" block, and tests/sp14_oracle_tests.rs leading "tests DELETED" marker. Production-source grep verification (post-cleanup): zero matches for HOLD_COST_SCALE_INDEX | HCS_TARGET | HCS_DIFF | HCS_PREV | HCS_SAMPLE | HOLD_COST_CONTROLLER_GAIN | HOLD_COST_FLOOR_RATIO | HOLD_COST_CEIL_RATIO | hold_cost_scale_update across crates/ml/src/ *.rs/*.cu/*.cuh. Audit doc + script preserved per design: - scripts/audit_sp18_consumers.sh grep patterns retain HOLD_COST_SCALE / HCS_* — those are the diagnostic tool. - docs/sp18-wireup-audit.md historical sections retain references (audit doc IS the design-history record); fingerprint section regenerated to reflect post-cleanup hit counts (audit --check passes). - docs/superpowers/specs/* + docs/superpowers/plans/* unchanged (spec/plan files retain HOLD_COST_SCALE references unchanged per feedback_trust_code_not_docs corollary — those are the past design-decision record). - docs/dqn-wire-up-audit.md current-state header section gains a 2026-05-09 archaeology-cleanup-pass entry citing the affected files + verification (per Pre-commit Invariant 7). Verification: - cargo check --workspace: clean (warnings only — pre-existing). - cargo test -p ml --lib --no-run: compiles clean. - cargo test --doc -p ml: 21 failures pre-existing (verified via stash; identical 21 failures on parent commit 8da8e2e58 — unrelated to this cleanup). - bash scripts/audit_sp18_consumers.sh --check: passes. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/ml/build.rs | 2 - crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs | 8 -- .../ml/src/cuda_pipeline/gpu_dqn_trainer.rs | 71 +++++++--------- .../cuda_pipeline/gpu_experience_collector.rs | 12 ++- crates/ml/src/cuda_pipeline/sp14_isv_slots.rs | 82 +++++-------------- crates/ml/src/cuda_pipeline/sp5_isv_slots.rs | 11 ++- crates/ml/src/cuda_pipeline/state_layout.cuh | 16 +--- .../src/trainers/dqn/state_reset_registry.rs | 69 ++++++---------- .../src/trainers/dqn/trainer/training_loop.rs | 14 +--- crates/ml/tests/sp14_oracle_tests.rs | 5 -- docs/dqn-wire-up-audit.md | 75 +++++++++++++++++ docs/sp18-wireup-audit.md | 37 +++------ 12 files changed, 180 insertions(+), 222 deletions(-) diff --git a/crates/ml/build.rs b/crates/ml/build.rs index 4696b5b56..f930b30f3 100644 --- a/crates/ml/build.rs +++ b/crates/ml/build.rs @@ -867,8 +867,6 @@ fn main() { // see docs/dqn-wire-up-audit.md § "SP16 Phase 1 (revised)" for // rationale. "min_hold_temperature_update_kernel.cu", - // hold_cost_scale_update_kernel.cu DELETED by SP18 Phase 1 - // (2026-05-09) — see docs/sp18-wireup-audit.md. // SP18 v2 Phase 0 Task 0.1 (2026-05-08): D-leg per-action reward // decomposition diagnostic. Reads `reward_components_per_sample` // ([n_samples × 6]) + `actions` ([n_samples], factored-action diff --git a/crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs b/crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs index be1a4a811..ac1b691ad 100644 --- a/crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs +++ b/crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs @@ -1200,11 +1200,3 @@ impl HS2AuxRmsEmaOps { Ok(()) } } - -// HoldCostScaleUpdateOps DELETED by SP18 Phase 1 (2026-05-09) — the -// SP16 Phase 2 / T3 reactive Hold-cost-scale chain (kernel + ops + 3 -// consumer sites in experience_kernels.cu) is replaced by the SP18 -// D-leg structural Hold opportunity-cost reward (Phase 2 lands the -// `compute_sp18_hold_opportunity_cost` device fn at the SP18-bound caps -// in slots [483..493)). See docs/sp18-wireup-audit.md (A1) for the -// atomic-deletion record. diff --git a/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs b/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs index 8e1c046bf..4a273eaae 100644 --- a/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs +++ b/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs @@ -611,14 +611,8 @@ static SP11_NOVELTY_SIMHASH_PROJ_INIT_CUBIN: &[u8] = /// and writes the resulting fraction `count(Hold) / batch_size ∈ [0, 1]` /// to a 1-element mapped-pinned scratch. The chained /// `apply_fixed_alpha_ema_kernel` (α=0.05, sentinel 0.0) blends the -/// per-step observation into `ISV[HOLD_RATE_OBSERVED_EMA_INDEX=382]`; -/// the host-side Hold-cost controller in `training_loop.rs` reads the -/// EMA + the static target at `ISV[HOLD_RATE_TARGET_INDEX=381]` and -/// writes the priced Hold cost back to `ISV[HOLD_COST_INDEX=380]`. The -/// reward composition site in `experience_kernels.cu` then subtracts -/// the cost on every Hold-action bar — pricing the action so the policy -/// uses Hold deliberately rather than as a free CQL-bias-anchored -/// default. +/// per-step observation into `ISV[HOLD_RATE_OBSERVED_EMA_INDEX=382]`, +/// which feeds the SP16-P1 MIN_HOLD_TEMPERATURE producer at slot 460. /// /// Loaded by `GpuExperienceCollector` (per-step on the action-select /// stream) — the per-step training-time observation is collector-owned @@ -2229,9 +2223,6 @@ pub(crate) static DD_SATURATION_FLOOR_UPDATE_CUBIN: &[u8] = include_bytes!(conca /// launch (same cadence as P0-A REWARD_POS_CAP). pub(crate) static MIN_HOLD_TEMPERATURE_UPDATE_CUBIN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/min_hold_temperature_update_kernel.cubin")); -// HOLD_COST_SCALE_UPDATE_CUBIN DELETED by SP18 Phase 1 (2026-05-09). -// See docs/sp18-wireup-audit.md. - /// SP14 Layer C Phase C.6 (2026-05-08): h_s2_aux RMS EMA producer cubin. /// Single-block 256-thread kernel computing `sqrt(mean(h_s2_aux²))` over /// `h_s2_aux [B, SH2]` (aux trunk final output) and EMA-blending into @@ -2560,7 +2551,20 @@ const ISV_NETWORK_DIM: usize = 23; /// (shifted 112→116 in Plan 4 Task 6 Commit A). /// Written by the constructor; checked at checkpoint load. Fail-fast only — no migration /// path exists. See spec §4.A.2 and `LAYOUT_FINGERPRINT_CURRENT` for structural-hash rationale. -pub(crate) const ISV_TOTAL_DIM: usize = 507; // SP5 + Layer D D1+D2+D3 + SP7 + SP8 + SP9 + SP10 + SP11 + SP13 + SP13 v3 + SP14 (post-C.1) + SP15 + SP14-C aux trunk control plane + SP14-C Phase C.4b aux horizon + Class A P0-A adaptive reward caps + Class A P1-Producer adaptive Bayesian Kelly priors + Class A audit-fix Batch 4-A adaptive DD saturation floor + Class A audit-fix Batch 4-B adaptive plan_threshold floor + adaptive MIN_HOLD_TEMPERATURE + SP16 Phase 2 adaptive Hold cost scale + SP16 T3 Wiener-optimal adaptive α Welford accumulators + SP17 dueling-Q identifiability diagnostics + SP18 v2 combined Hold-attractor fix (D-leg structural Hold opportunity-cost reward + B-leg TD(λ) Q(s') bootstrap diagnostics + PopArt reset gate) + SP18 v2 ISV-adaptive shrink-and-perturb at fold transition. Bumped 505 → 507 by SP18 v2 ISV-adaptive shrink-and-perturb (2026-05-09): added 2 slots [505..507) replacing the hardcoded `α=0.8 / σ=0.01` constants in `fused_training.rs::reset_for_fold`'s `shrink_and_perturb(alpha, sigma)` call. Per `feedback_isv_for_adaptive_bounds` and `feedback_adaptive_not_tuned`, every adaptive bound must be signal-driven from ISV. The driving signal is the relative weight drift `||current_params − best_params||₂ / ||best_params||₂` already computed each epoch by the SP18 v2 weight-drift diagnostic kernel (`weight_drift_diag_kernel.cu`, commit `aab13a83f`) — extended atomically in this commit to also write α and σ into ISV[505] / ISV[506] from the existing two block-tree-reductions (no new kernel — reuses `||best||₂` and `relative_drift` already computed). SHRINK_ALPHA_ADAPTIVE_INDEX (505): drift-driven. Small drift → α near MAX (preserve the converged best-Sharpe weights hard); large drift → α near MIN (shrink hard to escape the divergent region). SHRINK_SIGMA_ADAPTIVE_INDEX (506): scale-aware noise — σ tracks `||best||_RMS` so noise stays scale-relative as weight magnitudes evolve across folds (LayerNorm γ drift, weight-decay relaxation). Pearl-A first-observation bootstrap sentinels α=0.8 / σ=0.01 match the prior hardcoded values for bit-identical cold-start before the first valid weight-drift launch. Bounds [SHRINK_ALPHA_MIN=0.5, SHRINK_ALPHA_MAX=0.95] + [SHRINK_SIGMA_MIN=1e-4, SHRINK_SIGMA_MAX=0.1] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds`. Bilateral clamp per `pearl_symmetric_clamp_audit`. Cold-start case (first fold, no `best_params_snapshot`): host launcher writes drift = 0.0/0.0 directly and skips the kernel; ISV slots remain at sentinels — bit-identical to prior hardcoded behavior. Producer + consumer wired in same commit per `feedback_no_partial_refactor` and `feedback_wire_everything_up`. Bumped 483 → 505 by SP18 v2 Pre-Phase Task PP.2 (2026-05-08): added 22 slots [483..505) split across two atomic legs per `feedback_no_partial_refactor`. D-leg [483..493) — 10 slots: HOLD_REWARD_POS_CAP (483) + HOLD_REWARD_NEG_CAP (484) + HOLD_REWARD_DECOMP_DIAG (485) + HOLD_OPP_COST_FIRE_RATE_EMA (486) + 6 HRC_* Welford accumulators [487..493) for Wiener-α (mirrors SP16 T3 HCS_* layout). The two caps replace the SP13 P0a + SP16 P2 + SP16 T3 reactive per-bar Hold-cost chain (DD7=c) with a structural opportunity-cost reward at the 3 Hold-cost subtraction sites in `experience_kernels.cu`: each Hold-action bar pays `compute_sp18_hold_opportunity_cost(-2 × vol_normalized_next_log_return, neg_cap, pos_cap, shaping_scale)` — counterfactual cost in realised next-bar log-return units, asymmetric-capped via the `hold_reward_cap_update_kernel` adaptive producer (Phase 3) reading `p99(|step_ret|)` over Long/Short trade closes (DD3=b) × HOLD_REWARD_CAP_SAFETY_FACTOR=1.5 → POS, with NEG = -2 × POS (DD5=b mirrored 2:1 loss-aversion ratio matching SP14 P0-A REWARD_POS/NEG_CAP). Wiener-optimal α from Welford accumulators in [487..493) per `pearl_wiener_optimal_adaptive_alpha`. Pearl-A first-observation bootstrap sentinels POS=5.0/NEG=-10.0 match SP14 P0-A REWARD_POS/NEG_CAP_ADAPTIVE for bit-identical cold-start. Bounds [HOLD_REWARD_POS_CAP_MIN_BOUND=0.5, HOLD_REWARD_POS_CAP_MAX_BOUND=50.0] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds`. SP13/SP16 slots [380..383) and [461..474) remain ALLOCATED but RETIRED — sentinel 0.0, no producer launch — preserving checkpoint compatibility (RESERVED-gap pattern from SP14-C.1). B-leg [493..505) — 12 slots: TD_ERROR_MAG_EMA (493) + Q_NEXT_TARGET_P99 (494) + Q_NEXT_MINUS_REWARD_P99 (495) + V_SHARE_TREND_DIAG (496) + POPART_RESET_FLAG (497) + 6 TDB_* Welford accumulators [498..504) + 1 RESERVED (504). The B-leg replaces the `q_next = rewards` self-bootstrap at `gpu_experience_collector.rs:4143` with a real per-branch DDQN `Q_target(s', argmax_a Q_online(s', a))` computed by a target-net forward pass on `next_states` at experience-collection time (Phase 4-5). Reuses existing `target_params_buf` (SP14 P4.T1B-iv Polyak-tracked) — no new target-net infra (B-DD1). HEALTH_DIAG observability (B-DD12): td_error_mag_ema is the B-DD9 ratio-gate input (`avg(|TD-error|) ratio post-fix / pre-fix ∈ [0.5, 5.0]`); q_next_target_p99 is the bootstrap bound check; q_next_minus_reward_p99 sanity-checks magnitude (should be O(1) — proves the fix is doing something AND not blowing up); v_share_trend_diag observes the B-leg synergy hypothesis (bootstrap-bias predicts v_share monotone HD0→HD4). POPART_RESET_FLAG (497, sentinel 1.0) gates the per-fold PopArt slot 63 EMA reset at the SP18 deployment boundary per B-DD11 — switching `q_next` source from rewards-distributed to Q-distributed shifts the PopArt input distribution; cheap insurance is to reset PopArt EMA to identity normalization at the first SP18 epoch. NOT a FoldReset; host writes 1.0 once at deploy, kernel zeroes after consuming. Sentinels for diagnostic slots = 0.0 (Pearl-A direct-replace on first valid observation). 6 TDB_* Welford accumulators mirror HRC_* layout for q_next_target Wiener-α blending. Slot 504 RESERVED for B-leg follow-up. PER priority recomputation NOT migrated (per B-DD4 — already recomputed at training time from current TD-error). Plan: docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md. Bumped 474 → 483 by SP17 (2026-05-08): added 9 slots [474..483) for the dueling-Q identifiability diagnostic chain. With mean-zero advantage projection `A_centered[a, z] = A[a, z] − mean_a A[a, z]` (Phase 1-3 of SP17), V and A become uniquely identifiable: V_share ≈ 0.5 + Var(A_centered) > 0 indicates a healthy dueling decomposition; V_share → 1.0 + Var(A_centered) → 0 signals regression to the pre-SP17 V-dominated regime that the optimizer was free to learn under naive `Q = V + A`. Slots: A_VAR_EMA × 4 branches at [474..478) — per-branch EMA of the over-actions variance of the centered advantage; V_SHARE × 4 branches at [478..482) — per-branch |V| / (|V| + |A_centered|) magnitude share; ADVANTAGE_CLIP_BOUND at [482] — adaptive |A_centered| upper bound producer-tracked from p99(|A_centered|) × safety_factor=1.5 (mirrors SP14 P0-A REWARD_POS_CAP producer pattern; α=0.01 slow per-fold cadence). All Pearl-A first-observation bootstraps with sentinels SENTINEL_A_VAR_EMA=0.0, SENTINEL_V_SHARE=0.5 (cold-start 50/50 split), SENTINEL_ADVANTAGE_CLIP_BOUND=1.0 (cold-start "no effective clipping"). Bounds [ADVANTAGE_CLIP_BOUND_MIN=0.1, ADVANTAGE_CLIP_BOUND_MAX=100.0] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds`: floor 0.1 below which centered advantage is essentially noise (clipping would erase the action signal); ceiling 100.0 above which a single adversarial outlier dominates per-batch EMAs. This commit is additive infrastructure — no consumer change yet; the Phase 1 mean-centering producer (atomic across `compute_expected_q` + `c51_loss` + `c51_grad` + `mag_concat_qdir`) lands in the next 4 commits per `feedback_no_partial_refactor`. Plan: docs/superpowers/plans/2026-05-08-sp17-dueling-q-network.md. Bumped 462 → 474 by SP16 T3 (2026-05-08): added 12 slots [462..474) — 6 Welford accumulators per producer kernel (T1 MIN_HOLD_TEMPERATURE + T2 HOLD_COST_SCALE). Replaces the hardcoded `alpha = 0.05f` EMA constant in both producer kernels (`min_hold_temperature_update_kernel.cu` + `hold_cost_scale_update_kernel.cu`) with a signal-driven Wiener-optimal α per `pearl_wiener_optimal_adaptive_alpha`: α = diff_var / (diff_var + sample_var + ε). Per train-multi-seed-hjzss validation, the SP16 T1+T2 chain was structurally landed but BEHAVIORALLY INERT in 5-epoch smoke (bit-identical to pfh9n baseline through epoch 3) because α=0.05 needs ~60 epochs from cold start to converge. Wiener-optimal α naturally falls in [0, 1] (clamped to [0.01, 0.95] for numerical safety): cold-start (signal jumps 1.0 → 6.4 → 7.0) → diff_var dominates → α ≈ 0.6+ → near-bootstrap responsiveness in epochs 1-3; steady-state → diff_var drops → α decays naturally → smoothing emerges without hardcoded constant. Each producer maintains 6 Welford accumulators contiguously: [HCS_TARGET_MEAN, HCS_TARGET_M2, HCS_DIFF_MEAN, HCS_DIFF_M2, HCS_PREV_TARGET, HCS_SAMPLE_COUNT] at [462..468) and [MHT_TARGET_MEAN, MHT_TARGET_M2, MHT_DIFF_MEAN, MHT_DIFF_M2, MHT_PREV_TARGET, MHT_SAMPLE_COUNT] at [468..474). FoldReset sentinel 0.0 — combined with the cold-start fallback (sample_count < 3 → α = 1.0 REPLACE), the first observation of each fold replaces blended directly, the second seeds diff statistics, the third stabilises Wiener α. Per `feedback_isv_for_adaptive_bounds.md` — α was an adaptive bound being hardcoded; lifting to ISV-driven Wiener-optimal closes that violation. Bumped 461 → 462 by SP16 Phase 2 (2026-05-08): added 1 slot [461..462) — HOLD_COST_SCALE_INDEX (461). Replaces the static `ISV[HOLD_COST_INDEX=380]` per-bar Hold-cost magnitude (~0.006) when over-holding is observed. Producer kernel `hold_cost_scale_update_kernel` reads `ISV[HOLD_RATE_OBSERVED_EMA_INDEX=382]` and `ISV[HOLD_RATE_TARGET_INDEX=381]` (same SP13 hold-pricing chain feeding SP16-P1's MIN_HOLD_TEMPERATURE — same cadence, same input pattern), maps overrun into a [1, 25] multiplier via `target_scale = SCALE_MIN + (SCALE_MAX − SCALE_MIN) × clamp(max(0, observed - target) / max(target, 0.01), 0, 1)`, and Pearl-A-bootstrap + α=0.05 mid-cadence EMA blends into slot 461. Consumer: `experience_kernels.cu` per-bar Hold cost subtractions (3 sites: segment_complete branch line 3089, per-bar positioned-Hold branch line 3553, per-bar flat-Hold branch line 3617) multiply `isv[ISV_HOLD_COST_IDX=380]` by `isv[HOLD_COST_SCALE_INDEX=461]`. Cold-start fallback: when slot 461 is at sentinel 0.0 OR outside [1, 25], the consumer uses scale=1.0 (bit-identical to pre-Phase-2 v3-P0a Hold-cost magnitude). At observed=2× target → scale=25× → effective cost ~0.15/bar competitive with per-bar reward magnitudes ~0.01-0.1 but well below SP12 asymmetric cap [-10, +5]. Bounds [1, 25] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds.md`. Bumped 459 → 461 by Class A audit-fix Batch 4-B (2026-05-08): added 2 slots [459..461) — PLAN_THRESHOLD_FLOOR_ADAPTIVE (459) + MIN_HOLD_TEMPERATURE_ADAPTIVE (460). PLAN_THRESHOLD_FLOOR_ADAPTIVE replaces the hardcoded `0.1f` floor in `plan_threshold_update_kernel.cu:44` (`fmaxf(0.1f, 0.5f * ema)`) — Design Y inline producer (no new kernel; same kernel writes both slot 49 and the slow-EMA-shadow floor at slot 459 in the same launch, then uses the freshly-written floor as the lower bound). Pearl-A bootstrap (sentinel 0.1 matches pre-fix hardcoded value for bit-identical cold-start) + α=0.005 slow EMA (per-fold cadence — the floor is a long-term shadow of `0.5 × readiness_ema` and must move much slower than the readiness EMA itself). Bounds [0.05, 0.50] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds` (probability units). MIN_HOLD_TEMPERATURE_ADAPTIVE replaces the deleted epoch-driven anneal schedule `T_end + (T_start − T_end) × exp(-epoch / decay)` (formerly state_layout.cuh::MIN_HOLD_TEMPERATURE_{START=50, END=5, DECAY=20} + training_loop.rs::min_hold_temperature_for_epoch). Producer kernel `min_hold_temperature_update_kernel` reads `ISV[AUX_DIR_ACC_SHORT_EMA_INDEX=373]` (sp13 fast EMA of binary directional accuracy), maps to a [5, 50] temperature via `temp = TEMP_MIN + (TEMP_MAX − TEMP_MIN) × confusion` where `confusion = 1 − clamp((short_ema − 0.5)/0.5, 0, 1)` (so dir_acc ≈ 0.5 plateau → temp HIGH/permissive exit ramp; dir_acc → 1.0 → temp LOW/strict informed-commitment), and slow-EMA-blends into slot 460. HIGH T = forgiving (`deficit/(deficit+T)` saturation factor → 0); LOW T = sharp (→ 1) per `compute_min_hold_penalty` at trade_physics.cuh:575. Pearl-A bootstrap (sentinel 50.0 matches the deleted MIN_HOLD_TEMPERATURE_START=50 anchor for bit-identical cold-start under both regimes) + α=0.05 mid-cadence EMA. Bounds [5, 50] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds` (matches the original schedule range). Decouples temperature from epoch number — when WR plateaus, the old schedule pinned LOW temp (sharp) at end of training (max punishment exactly when most needed forgiveness); the signal-driven version reacts to actual realized skill. Per `feedback_no_legacy_aliases.md` the legacy schedule constants + helper function are deleted atomically. Bumped 458 → 459 by Class A audit-fix Batch 4-A (2026-05-08): added 1 adaptive-DD-saturation-floor slot [458..459) — DD_SATURATION_FLOOR_ADAPTIVE (458). Replaces the hardcoded `0.25f` saturation floor in `trade_physics.cuh::apply_margin_cap` (the upper end of the linear position-size scaling ramp dd_scale = max(0.05, 1.0 − dd_frac / saturation_floor)). Distinct semantic role from `SP15_DD_THRESHOLD_INDEX=421` (the SP15 quadratic DD-penalty *trigger* threshold, a *lower* bound). Producer kernel `dd_saturation_floor_update_kernel` aggregates per-env DD_MAX from the existing `dd_state_per_env[env*6 + 1]` tile (same source as the SP15 dd_state_kernel writes to), computes p75 estimator via Welford rule (mean + Z_75 × sigma) × safety_factor=1.5, and slow-EMA blends. Pearl-A bootstrap (sentinel 0.25 matches pre-fix hardcoded value for bit-identical cold-start) + α=0.01 slow EMA (DD distribution is a slow-moving fold-volatility property, shouldn't track per-epoch noise). Bounds [0.10, 0.50] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds`. Atomically deleted alongside this slot addition: legacy `compute_drawdown_penalty` device function in trade_physics.cuh + its single caller at experience_kernels.cu:3822 + the `w_dd` and `dd_threshold` kernel args (Item 2 Case A — SP15's quadratic asymmetric DD penalty in `compute_sp15_final_reward_kernel.cu:154` is the production-grade replacement; layering both creates double-counting per `feedback_no_partial_refactor`). Bumped 454 → 458 by Class A P1-Producer (2026-05-08): added 4 adaptive-Bayesian-prior slots [454..458) — KELLY_PRIOR_WINS (454) + KELLY_PRIOR_LOSSES (455) + KELLY_PRIOR_SUM_WINS (456) + KELLY_PRIOR_SUM_LOSSES (457). Per Class A audit, hardcoded `prior_wins=2.0f / prior_losses=2.0f / prior_sum_wins=0.01f / prior_sum_losses=0.01f` (kelly_cap_update_kernel.cu:39-42 + trade_physics.cuh::kelly_position_cap:304-307) was a static "I don't know" Bayesian prior frozen at sprint-1 defaults — the cold-start of every new fold ignored what prior folds had learned about the realized Kelly distribution. Producer kernel `kelly_bayesian_priors_update_kernel` aggregates realized Kelly stats from the existing `portfolio_state[n_envs, PS_STRIDE]` buffer (same source as kelly_cap_update consumes) and slow-EMA blends into the four slots. Pearl-A bootstrap (sentinels 2.0/2.0/0.01/0.01 match pre-P1-Producer hardcoded values for bit-identical cold-start) + α=0.005 slow EMA (per-fold cadence; the Bayesian prior is a *prior belief* and should change slowly across folds). Bounds counts∈[0.5, 100], sums∈[0.001, 1.0] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds`. Bumped 452 → 454 by Class A P0-A (2026-05-08): added 2 adaptive-reward-cap slots [452..454) — REWARD_POS_CAP_ADAPTIVE (452) + REWARD_NEG_CAP_ADAPTIVE (453). Per Class A audit, hardcoded `REWARD_POS_CAP=+5.0f` / `REWARD_NEG_CAP=-10.0f` (state_layout.cuh:266-267) was structurally clipping the upper tail of realized alpha — controller signals (sharpe EMA, var_q, q_gap) all derive from the CAPPED buffer, so the controller cannot select for trades it cannot see. The state_layout comment explicitly deferred Phase 2 (ISV-driven) "IF Phase 1 validation reveals adaptive need"; 11 superprojects of WR-stuck-at-46-48% revealed adaptive need. Producer kernel `reward_cap_update_kernel` computes p99(winning_returns) × safety_factor=1.5 → POS cap and NEG = -2 × POS (preserves Kahneman 2:1 loss-aversion asymmetry per `pearl_audit_unboundedness_for_implicit_asymmetry` — moved from hardcoded scalar to producer-time multiplier, single source of truth). Pearl-A bootstrap (sentinels 5.0/-10.0) + Wiener-α=0.01 slow EMA. Bounds POS∈[1, 50], NEG∈[-100, -2] are Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds`, NOT tuning. Bumped 450 → 452 by SP14 Layer C Phase C.4b (2026-05-08): added 2 aux-prediction-horizon slots [450..452) — AUX_PRED_HORIZON_BARS (450) + AVG_WIN_HOLD_TIME_BARS (451). Aux's original label was (p_{t+1} > p_t), pure HFT-scale microstructure noise — pivoted to (p_{t+H} > p_t) with H read from ISV[450], adaptively driven from observed avg winning hold time via Pearl-A bootstrap + Wiener-α EMA. Case B: existing `hold_at_exit_per_sample` + `trade_profitable_per_sample` per-sample buffers, no aggregate slot — added new aggregate slot 451 to expose the EMA target. Bumped 444 → 450 by SP14 Layer C Phase C.1 (2026-05-08): atomically deleted 9 α-machinery slots in [385..396) AND added 6 aux-trunk control-plane slots [444..450) — AUX_TRUNK_LR (444) + AUX_TRUNK_BETA1 (445) + AUX_TRUNK_BETA2 (446) + AUX_TRUNK_EPS (447) + AUX_TRUNK_GRAD_CLIP (448) + H_S2_AUX_RMS_EMA (449). Per `feedback_no_legacy_aliases` and `feedback_no_partial_refactor`. Deleted slots left as RESERVED gap (NOT compacted) to preserve checkpoint layout fingerprint compatibility — the surviving SP14 q_disagreement_* diagnostic slots (383, 384, 389) keep their original indices. Pre-C.1 base: 173 + 210 (164 SP5 slots @ 174..278/280..340, with 2-slot gap before cross-fold-persistent Kelly block; Layer D D1 PnL outputs at [286..290); Layer D D2 health composition outputs at [290..294); Layer D D3 training metrics EMA at [294..297); SP7 T1 loss-balance Wiener stats at [297..313); SP7 activation-flag fix per-(head,branch) flags at [313..321); SP8 Fix 36 train_active_frac canary @ [321..322) + LB_MAX_BUDGET per-(head,branch) at [322..330); SP9 Fix 37 Kelly warmup floor at [330..331) + Q_VAR_MAG_EMA at [331..332) + INTENT_EVAL_DIVERGENCE at [332..333) + 3 EMA targets at [333..336) + 3 eval_dist mag bins at [336..339); SP10 Fix 38 EVAL_THOMPSON_TEMP at [339..340); SP11 Fix 39 reward-subsystem controller at [340..367) — 6 component weights [340..346) + 4 controller scalar outputs [346..350) + 2 val-sharpe canaries [350..352) + 6 mag-ratio canaries [352..358) + saboteur engagement [358] + PnL magnitude EMA [359] + popart-component magnitude EMA [360, B1b fix-up] + per-component variance EMAs [361..367, B1b smoke-recovery z-score normalization]; SP13 directional-skill instrumentation at [372..380) — TARGET_DIR_ACC [372] + AUX_DIR_ACC_SHORT/LONG_EMA [373..375) + AUX_DIR_PREDICTION [375] + DIR_SKILL_BONUS_ALPHA/BETA [376..378) + LUCK_WIN_DISCOUNT [378] + SKILL_BONUS_CAP_RATIO [379]; SP13 v3 P0a.T3 Hold-pricing controller at [380..383) — HOLD_COST [380] + HOLD_RATE_TARGET [381] + HOLD_RATE_OBSERVED_EMA [382]; SP14 q_disagreement diagnostic at [383..385), [389] — Q_DISAGREEMENT_SHORT/LONG_EMA + Q_DISAGREEMENT_VARIANCE_EMA (slots [385..389) and [390..396) RESERVED gap from C.1 deletion); SP15 [397..444) per Phase 1; SP14-C [444..450) per Phase C.1. Intentional 5-slot boundary gap at [367..372)) +/// Size of the broadcast Internal Signal Vector (ISV) bus in floats. +/// +/// The ISV is the kernel↔kernel signal bus: producers write into it, consumers +/// read from it, and `read_isv_signal_at` exposes a single slot to host code. +/// New slot ranges are appended at the tail (existing indices stay stable so +/// checkpoint layouts are forward-compatible — deleted slot ranges become +/// RESERVED gaps rather than being compacted; see `LAYOUT_FINGERPRINT_CURRENT` +/// + `layout_fingerprint_seed` for the structural-hash contract). +/// +/// Slot index assignments live in `crate::cuda_pipeline::sp{5,13,14,15}_isv_slots` +/// (and the C-side mirrors in `state_layout.cuh`). Bump this constant in the +/// SAME commit that adds the new range, and update `layout_fingerprint_seed` +/// to register the new slot names. +pub(crate) const ISV_TOTAL_DIM: usize = 507; /// Legacy alias preserved for call sites that haven't been audited for the /// network-vs-total split. New code should pick `ISV_NETWORK_DIM` (for weight /// tensor sizing) or `ISV_TOTAL_DIM` (for the broadcast bus buffer). @@ -7819,8 +7823,6 @@ pub struct GpuDqnTrainer { /// boundary launch (same cadence as P0-A REWARD_POS_CAP). min_hold_temperature_update_ops: super::gpu_aux_trunk::MinHoldTemperatureUpdateOps, - // hold_cost_scale_update_ops field DELETED by SP18 Phase 1 (2026-05-09). - // ── Speculative inference cache ── /// Cached trunk output [B, SH2] from between-bar speculative forward. speculative_h_s2: CudaSlice, @@ -15762,10 +15764,6 @@ impl GpuDqnTrainer { Ok(()) } - // launch_hold_cost_scale_update DELETED by SP18 Phase 1 (2026-05-09). - // The SP16 P2/T3 reactive Hold-cost-scale chain is replaced by the - // SP18 D-leg structural Hold opportunity-cost reward (Phase 2). - /// SP8 (Fix 36, 2026-05-03): launch GPU-only `train_active_frac` canary /// producer. /// @@ -20511,16 +20509,11 @@ impl GpuDqnTrainer { // own copy of the cubins from `SP13_HOLD_RATE_OBSERVER_CUBIN` and // `SP13_APPLY_FIXED_ALPHA_EMA_CUBIN`, so the trainer carries no // hold-rate-specific kernel handle or scratch buffer (avoids a - // dead `CudaFunction` field per `feedback_no_stubs.md`). The - // trainer's host-side controller in `training_loop.rs:3604` - // reads the slot-382 EMA + slot-381 target via - // `read_isv_signal_at` at the per-epoch metrics block and - // writes the priced cost to ISV[HOLD_COST_INDEX=380]; the - // reward-composition site in `experience_kernels.cu` consumes - // ISV[380] from the same shared `isv_signals_dev_ptr`. The - // ISV[380] / ISV[381] / ISV[382] sentinels are seeded by - // `state_reset_registry`'s SP13 entries and `seed_static_signals` - // (Invariant-1 anchors at ISV[380, 381]). + // dead `CudaFunction` field per `feedback_no_stubs.md`). Slot 382 + // feeds the SP16-P1 MIN_HOLD_TEMPERATURE producer at slot 460. + // ISV[380] / ISV[381] sentinels are seeded by `seed_static_signals` + // (Invariant-1 anchors); ISV[382] is FoldReset 0.0 via + // `state_reset_registry`. // SP13 Phase 0a P0a.T4 (2026-05-04): fixed-α EMA applicator // kernel handle + aux-pred → ISV[375] tanh producer handle. @@ -23087,16 +23080,14 @@ impl GpuDqnTrainer { *sig_ptr.add(LUCK_WIN_DISCOUNT_INDEX) = LUCK_WIN_DISCOUNT_DEFAULT; *sig_ptr.add(SKILL_BONUS_CAP_RATIO_INDEX) = SKILL_BONUS_CAP_RATIO_DEFAULT; - // SP13 v3 P0a.T3 (2026-05-04): Hold-pricing controller anchors. - // HOLD_COST_INDEX is rewritten every step by the host-side - // controller in `training_loop.rs`; the constructor write - // seeds it with the baseline cost so the first - // `experience_env_step` (before the controller fires) sees - // a meaningful value rather than 0 (which would silently - // disable Hold-pricing on the first batch). HOLD_RATE_TARGET - // is a static MFT default 0.20 — never reaches sentinel 0 - // between folds. The observed-rate EMA at slot 382 is - // FoldReset (sentinel 0.0) and registered separately. + // SP13 v3 P0a.T3 (2026-05-04): Hold-pricing observation + // chain anchors (DD7=c). Slot 380 is a constructor-init-only + // diagnostic anchor surfacing the static base cost — the SP18 + // structural Hold opportunity-cost reward (slots [483..493)) + // does NOT consume slot 380. HOLD_RATE_TARGET is a static MFT + // default 0.20 — never reaches sentinel 0 between folds. The + // observed-rate EMA at slot 382 is FoldReset (sentinel 0.0) + // and registered separately. use crate::cuda_pipeline::sp5_isv_slots::{ HOLD_COST_INDEX, HOLD_COST_BASE, HOLD_RATE_TARGET_INDEX, HOLD_RATE_TARGET_DEFAULT, @@ -24313,9 +24304,6 @@ impl GpuDqnTrainer { let min_hold_temperature_update_ops = super::gpu_aux_trunk::MinHoldTemperatureUpdateOps::new(&stream)?; - // hold_cost_scale_update_ops constructor DELETED by SP18 Phase 1 - // (2026-05-09). - // ── Speculative inference cache ── let speculative_h_s2 = stream.alloc_zeros::(b * sh2) .map_err(|e| MLError::ModelError(format!("speculative_h_s2 alloc: {e}")))?; @@ -25175,7 +25163,6 @@ impl GpuDqnTrainer { dd_saturation_floor_update_ops, // Class A audit-fix Batch 4-B (2026-05-08, Item 4): adaptive MIN_HOLD_TEMPERATURE producer. min_hold_temperature_update_ops, - // hold_cost_scale_update_ops field-init DELETED by SP18 Phase 1. speculative_h_s2, speculative_features, speculative_valid: false, diff --git a/crates/ml/src/cuda_pipeline/gpu_experience_collector.rs b/crates/ml/src/cuda_pipeline/gpu_experience_collector.rs index 22e989331..4e39350bd 100644 --- a/crates/ml/src/cuda_pipeline/gpu_experience_collector.rs +++ b/crates/ml/src/cuda_pipeline/gpu_experience_collector.rs @@ -5576,13 +5576,11 @@ impl GpuExperienceCollector { // when ISV is not yet wired (test scaffold path) — the EMA // would have nowhere to write. // - // The trainer's host-side controller in `training_loop.rs:3604` - // reads slot 382 + slot 381 at the per-epoch metrics block and - // writes the priced cost to ISV[HOLD_COST_INDEX=380]; the - // reward-composition site in `experience_kernels.cu` then - // subtracts the cost on every Hold-action bar — pricing the - // action so the policy uses Hold deliberately rather than as a - // free CQL-bias-anchored default. + // Slot 382 feeds the SP16-P1 MIN_HOLD_TEMPERATURE producer + // (slot 460) at the per-epoch boundary; the SP18 D-leg + // structural Hold opportunity-cost reward (slots [483..493)) + // is the consumer chain that actually shapes Hold-action + // rewards. if self.isv_signals_dev_ptr != 0 && !self.seed_phase_active_cache { use crate::cuda_pipeline::sp13_isv_slots::HOLD_RATE_OBSERVED_EMA_INDEX; diff --git a/crates/ml/src/cuda_pipeline/sp14_isv_slots.rs b/crates/ml/src/cuda_pipeline/sp14_isv_slots.rs index 2878d5c9c..c29e27ba1 100644 --- a/crates/ml/src/cuda_pipeline/sp14_isv_slots.rs +++ b/crates/ml/src/cuda_pipeline/sp14_isv_slots.rs @@ -450,28 +450,11 @@ pub const SENTINEL_HOLD_RATE_OBSERVED: f32 = 0.0; pub const SP14_AUDIT_4B_TEMP_SLOT_BASE: usize = 460; pub const SP14_AUDIT_4B_TEMP_SLOT_END: usize = 461; -// ── SP16 Phase 2 (2026-05-08, RETIRED 2026-05-09 by SP18 Phase 1) ─────── -// Slot 461 (HOLD_COST_SCALE_INDEX) and the per-epoch -// `hold_cost_scale_update_kernel` producer are DELETED atomically with -// the 3 per-bar Hold-cost subtraction sites in `experience_kernels.cu` -// per DD7=c — the reactive multiplicative-cost chain is replaced by the -// SP18 D-leg structural Hold opportunity-cost reward (Phase 2 lands the -// `compute_sp18_hold_opportunity_cost` device fn at the SP18-bound caps -// in slots [483..493)). The slot index [461..468) is now a RESERVED gap -// in the layout fingerprint (SP14-C.1 RESERVED-gap pattern; deleted -// slots are NOT compacted to preserve checkpoint compatibility). -// -// Plan: docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md -// Audit: docs/sp18-wireup-audit.md (A1-A10 expansion). - // ── SP16 T3 (2026-05-08): Wiener-optimal adaptive α — Welford accumulators ─ -// Both T1 (MIN_HOLD_TEMPERATURE producer at slot 460) and T2 (HOLD_COST_SCALE -// producer at slot 461) previously hardcoded `alpha = 0.05f` in their EMA -// blend. train-multi-seed-hjzss validation showed the SP16 chain was -// structurally landed but BEHAVIORALLY INERT in 5-epoch smoke — bit-identical -// to the pfh9n baseline through epoch 3 (hold_cost_scale 1.0→1.0→1.27 vs -// target 7.0; min_hold_temp 0.0→5.0→5.50 vs target 16.0). Root cause: with -// α=0.05 the EMA needs ~60 epochs from cold start to converge. +// The MIN_HOLD_TEMPERATURE producer (T1) at slot 460 previously hardcoded +// `alpha = 0.05f` in its EMA blend. train-multi-seed-hjzss validation showed +// behavior bit-identical to the pfh9n baseline through epoch 3 — with α=0.05 +// the EMA needs ~60 epochs from cold start to converge. // // Per `feedback_isv_for_adaptive_bounds.md` the constant α is itself an // adaptive bound that should not be hardcoded. Per @@ -481,34 +464,24 @@ pub const SP14_AUDIT_4B_TEMP_SLOT_END: usize = 461; // // Where `sample_var` = running variance of the target signal and // `diff_var` = running variance of consecutive one-step differences. -// Cold-start (signal jumps 1.0 → 6.4 → 7.0): diff_var dominates → α ≈ 0.6+ -// → near-bootstrap responsiveness in epochs 1-3. Steady-state: signal -// stabilises, diff_var drops, α decays naturally → smoothing emerges +// Cold-start: diff_var dominates → α ≈ 0.6+ → near-bootstrap responsiveness. +// Steady-state: diff_var drops, α decays naturally → smoothing emerges // without a hardcoded constant. // -// Each producer maintains 6 Welford accumulators (target mean/M2, diff -// mean/M2, prev_target, sample_count). 12 slots total. Pearl-A -// first-observation bootstrap on the prev_blended sentinel (slot 460 sentinel -// 50.0; slot 461 sentinel 0.0). Cold-start fallback when sample_count < 3 -// (insufficient samples for variance estimation): α = 1.0 (REPLACE) so the -// producer remains responsive in early epochs. +// The producer maintains 6 Welford accumulators (target mean/M2, diff +// mean/M2, prev_target, sample_count) at [468..474). Pearl-A +// first-observation bootstrap on the prev_blended sentinel (slot 460 +// sentinel 50.0). Cold-start fallback when sample_count < 3 +// (insufficient samples for variance estimation): α = 1.0 (REPLACE) so +// the producer remains responsive in early epochs. // -// Slot layout chosen to keep T1 and T2 accumulators contiguous in memory -// (one 12-slot block at 462..474), simplifying the FoldReset registry + -// dispatch arm wiring. Each block of 6 mirrors the Welford state machine -// exactly; the only difference between T1 and T2 is which producer kernel -// reads/writes them (selected by passing the corresponding base index). -// -// HCS = HOLD_COST_SCALE (T2 producer); MHT = MIN_HOLD_TEMPERATURE (T1). +// MHT = MIN_HOLD_TEMPERATURE (T1). // // Sentinels: every Welford slot is FoldReset-bootstrap (sentinel 0.0). At // fold start, sample_count = 0 → cold-start path fires (α = 1.0; first // valid observation REPLACES). After first observation, sample_count ≥ 1 // and Welford accumulators take over. -// HCS_* slots [462..468) RETIRED by SP18 Phase 1 (2026-05-09) — the -// HOLD_COST_SCALE producer they fed (slot 461) is deleted; gap reserved. - pub const MHT_TARGET_MEAN_INDEX: usize = 468; // Welford running mean of target_temp pub const MHT_TARGET_M2_INDEX: usize = 469; // Welford sum of squared deviations (target) pub const MHT_DIFF_MEAN_INDEX: usize = 470; // Welford running mean of consecutive diffs @@ -527,11 +500,11 @@ pub const SENTINEL_WELFORD_ZERO: f32 = 0.0; // // - WELFORD_ALPHA_MIN=0.4: non-stationary control-loop floor (2026-05-08). // Wiener-optimal α = diff_var / (diff_var + sample_var + ε) is -// MSE-optimal for *stationary* signals. The SP16 T3 producers -// (min_hold_temperature, hold_cost_scale) track a hold-rate overrun -// driven by the co-adapting policy — the controller's output -// directly shapes the per-bar reward / min-hold penalty that the -// policy is being trained against. Once Welford accumulates 3+ +// MSE-optimal for *stationary* signals. The SP16 T3 producer +// (min_hold_temperature) tracks a hold-rate overrun driven by the +// co-adapting policy — the controller's output directly shapes the +// min-hold penalty that the policy is being trained against. Once +// Welford accumulates 3+ // samples and the policy converges toward target, diff_var → 0 // and α_wiener → 0, leaving the controller unable to catch up // when the policy subsequently drifts back above target. @@ -568,9 +541,8 @@ pub const WELFORD_MIN_SAMPLE_COUNT: f32 = 3.0; // floor in `apply_pearls_ad_kernel` and the SP4 wiener buffer producers. pub const WELFORD_EPS: f32 = 1.0e-6; -// SP16 T3 (2026-05-08, post-SP18 Phase 1 retirement of HCS): the surviving -// Wiener-Welford block is the MHT (MIN_HOLD_TEMPERATURE) producer's 6 -// accumulators at [468..474). The HCS block at [462..468) is RESERVED gap. +// SP16 T3 (2026-05-08): MHT (MIN_HOLD_TEMPERATURE) producer's 6 Wiener-Welford +// accumulators at [468..474). pub const SP16_T3_WIENER_SLOT_BASE: usize = 468; pub const SP16_T3_WIENER_SLOT_END: usize = 474; @@ -663,11 +635,6 @@ pub const SP17_DUELING_SLOT_END: usize = 483; // lands a real cap. Bounds [POS_MIN=0.5, POS_MAX=50.0] are Category-1 // dimensional safety floors per `feedback_isv_for_adaptive_bounds.md`. // -// SP13 [380..383)/SP16 [461..474) slots remain ALLOCATED but RETIRED per -// PP.4 — sentinel 0.0, no producer launch. Slots stay in the layout -// fingerprint to preserve checkpoint compatibility (RESERVED-gap pattern -// established at SP14-C.1). -// // Plan: docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md pub const HOLD_REWARD_POS_CAP_INDEX: usize = 483; pub const HOLD_REWARD_NEG_CAP_INDEX: usize = 484; @@ -1125,14 +1092,9 @@ mod tests { ); } - // SP16 Phase 2 / T3 HCS layout-locked tests removed by SP18 Phase 1 - // (2026-05-09) — the HOLD_COST_SCALE_INDEX (461) and HCS_* (462..468) - // constants no longer exist. The MHT block lock test below survives. - /// Lock SP16 T3 (2026-05-08) Wiener-optimal Welford accumulator slot - /// layout for the surviving MHT (MIN_HOLD_TEMPERATURE) producer. - /// 6 contiguous slots [468..474). The HCS counterpart was retired by - /// SP18 Phase 1 (RESERVED gap [462..468)). + /// layout for the MHT (MIN_HOLD_TEMPERATURE) producer. + /// 6 contiguous slots [468..474). #[test] fn sp16_t3_wiener_welford_slot_layout_locked() { assert_eq!(SP16_T3_WIENER_SLOT_BASE, 468); diff --git a/crates/ml/src/cuda_pipeline/sp5_isv_slots.rs b/crates/ml/src/cuda_pipeline/sp5_isv_slots.rs index 5e302cf2f..b94ff4daf 100644 --- a/crates/ml/src/cuda_pipeline/sp5_isv_slots.rs +++ b/crates/ml/src/cuda_pipeline/sp5_isv_slots.rs @@ -322,12 +322,11 @@ pub const EVAL_THOMPSON_TEMP_INDEX: usize = 339; // [1] eval Thompson se // (re-exported above). // // SP13 v3 (P0a.T3, 2026-05-04): 3 additional slots at ISV[380..383) for the -// Hold-pricing adaptive controller — `HOLD_COST_INDEX=380` (controller output, -// per-bar Hold cost), `HOLD_RATE_TARGET_INDEX=381` (static MFT target 0.20), -// `HOLD_RATE_OBSERVED_EMA_INDEX=382` (per-fold-reset Hold-pick rate EMA from -// `hold_rate_observer_kernel`). Replaces v2's atomic Hold elimination after -// the T3 implementer audited and found `DirectionAction` doesn't exist — the -// 4-way action space stays; Hold becomes priced rather than removed. +// Hold-pricing observation chain — `HOLD_COST_INDEX=380` (constructor-init +// diagnostic anchor at HOLD_COST_BASE=0.005), `HOLD_RATE_TARGET_INDEX=381` +// (static MFT target 0.20), `HOLD_RATE_OBSERVED_EMA_INDEX=382` (per-fold-reset +// Hold-pick rate EMA from `hold_rate_observer_kernel`). Slot 382 feeds the +// SP16-P1 MIN_HOLD_TEMPERATURE producer at slot 460. pub const SP5_SLOT_END: usize = 383; /// Wiener-buffer producer-count constant. Sizes `wiener_state_buf` via diff --git a/crates/ml/src/cuda_pipeline/state_layout.cuh b/crates/ml/src/cuda_pipeline/state_layout.cuh index ee97f9a30..9768b3c46 100644 --- a/crates/ml/src/cuda_pipeline/state_layout.cuh +++ b/crates/ml/src/cuda_pipeline/state_layout.cuh @@ -201,16 +201,6 @@ #define ISV_HOLD_RATE_TARGET_IDX 381 // SP13 v3 target Hold-pick rate (static, default 0.20) #define ISV_HOLD_RATE_OBSERVED_EMA_IDX 382 // SP13 v3 observed Hold-pick rate EMA (per-fold, sentinel 0.0) -// ──────────────────────────────────────────────────────────────────────────── -// === SP16 Phase 2 / T3 HCS SLOTS (RETIRED 2026-05-09 by SP18 Phase 1) === -// Slot 461 (HOLD_COST_SCALE) + [462..468) (HCS_* Welford) are DELETED -// atomically with the producer kernel + 3 consumer sites in -// experience_kernels.cu. Replaced by the SP18 D-leg structural Hold -// opportunity-cost reward at slots [483..493). Range [461..468) is a -// RESERVED gap in the layout fingerprint (SP14-C.1 RESERVED-gap pattern). -// See docs/sp18-wireup-audit.md for the atomic-deletion record. -// ──────────────────────────────────────────────────────────────────────────── - // ──────────────────────────────────────────────────────────────────────────── // === SP16 T3 MHT SLOTS (2026-05-08, Wiener-optimal adaptive α) === // Mirror of crates/ml/src/cuda_pipeline/sp14_isv_slots.rs slots [468..474). @@ -227,9 +217,9 @@ #define ISV_MHT_SAMPLE_COUNT_IDX 473 // Welford counter (T1 producer) // Wiener-α floor for non-stationary control loops (2026-05-08). Wiener- // optimal α = diff_var / (diff_var + sample_var + ε) is MSE-optimal for -// stationary signals. The SP16 T3 producers (min_hold_temperature, -// hold_cost_scale) track a hold-rate overrun driven by a co-adapting -// policy — non-stationary by construction. Once Welford accumulates +// stationary signals. The SP16 T3 producer (min_hold_temperature) tracks +// a hold-rate overrun driven by a co-adapting policy — non-stationary by +// construction. Once Welford accumulates // 3+ samples and the policy converges toward target, diff_var collapses // and α_wiener → 0, leaving the controller unable to react when the // policy subsequently drifts. The 0.4 floor preserves ~2.5-step diff --git a/crates/ml/src/trainers/dqn/state_reset_registry.rs b/crates/ml/src/trainers/dqn/state_reset_registry.rs index 615e9fe6b..dfc99f45c 100644 --- a/crates/ml/src/trainers/dqn/state_reset_registry.rs +++ b/crates/ml/src/trainers/dqn/state_reset_registry.rs @@ -1173,76 +1173,64 @@ impl StateResetRegistry { category: ResetCategory::FoldReset, description: "ISV[PLAN_THRESHOLD_FLOOR_ADAPTIVE_INDEX=459] — Class A audit-fix Batch 4-B adaptive plan_threshold floor (replaces hardcoded `0.1f` in `plan_threshold_update_kernel.cu:44`, the lower bound of the derived plan_threshold = max(floor, 0.5 × readiness_ema)). Design Y inline producer: the same `plan_threshold_update_kernel` writes both ISV[PLAN_THRESHOLD_INDEX=49] and ISV[459] in the same launch — the floor tracks a slow EMA of `0.5 × readiness_ema` (the very expression the kernel uses as its derived threshold target) and the kernel uses the freshly-written floor as the lower bound. FoldReset sentinel SENTINEL_PLAN_THRESHOLD_FLOOR=0.1 — Pearl-A first-observation bootstrap (matches pre-fix hardcoded value for bit-identical cold-start). α=0.005 slow EMA thereafter (per-fold cadence; the floor is a long-term shadow and must move much slower than the readiness EMA itself which adapts at α≈[0.05, 0.10]). Bounds [0.05, 0.50] — Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds.md` (probability units; below 5% the readiness gate is effectively absent, above 50% it is uselessly strict). Distinct from PLAN_THRESHOLD_INDEX=49 (the live derived threshold, fast cadence) — slot 459 is the slow-moving lower bound on slot 49.", }, - // sp16_phase2_hold_cost_scale_adaptive registry entry DELETED - // by SP18 Phase 1 (2026-05-09) — slot 461 is removed from the - // registry; the slot index is now a RESERVED gap with no - // FoldReset bookkeeping (consumers are deleted atomically). RegistryEntry { name: "sp14_audit_4b_min_hold_temperature_adaptive", category: ResetCategory::FoldReset, description: "ISV[MIN_HOLD_TEMPERATURE_ADAPTIVE_INDEX=460] — SP16 Phase 1 (revised, 2026-05-08) adaptive MIN_HOLD_TEMPERATURE (replaces the DELETED epoch-driven anneal schedule `T_end + (T_start − T_end) × exp(-epoch / decay)` formerly at state_layout.cuh::MIN_HOLD_TEMPERATURE_{START=50, END=5, DECAY=20} + training_loop.rs::min_hold_temperature_for_epoch). Producer kernel `min_hold_temperature_update_kernel` reads ISV[HOLD_RATE_OBSERVED_EMA_INDEX=382] and ISV[HOLD_RATE_TARGET_INDEX=381] (sp13 hold-pricing chain) and maps the overrun into a [5, 50] temperature via `target_temp = TEMP_MIN + (TEMP_MAX − TEMP_MIN) × clamp(max(0, observed - target) / max(target, 0.01), 0, 1)`, slow-EMA-blends into slot 460. SIGNAL SWAPPED 2026-05-08 from ISV[AUX_DIR_ACC_SHORT_EMA_INDEX=373] — post-mortem of train-multi-seed-pfh9n showed slot 373 stayed at sentinel 0.5 in Fold 1 (per-step aux producer didn't push it off sentinel quickly enough OR binary classifier converged within ε of 0.5 in noisy environments), so the kernel's early-return-on-sentinel guard pinned slot 460 at 50 for the entire fold. Hold rates are measured per-epoch from realised actions and survive fold reset cleanly. Cold-start sentinel guard preserved: when observed_hold_rate is at SENTINEL_HOLD_RATE_OBSERVED=0.0 (matches sp13_hold_rate_observed_ema fold-reset sentinel), the kernel keeps slot 460 unchanged — consumer falls back to MIN_HOLD_TEMPERATURE_FALLBACK=50.0. FoldReset sentinel SENTINEL_MIN_HOLD_TEMPERATURE=50.0 — Pearl-A first-observation bootstrap (matches the deleted MIN_HOLD_TEMPERATURE_START=50 anchor for bit-identical cold-start; epoch-0 had T=50 under the old schedule too). SP16 T3 (2026-05-08): the hardcoded α=0.05 was replaced with Wiener-optimal α from Welford accumulators in slots [468..474). Bounds [5, 50] — Category-1 dimensional safety floors per `feedback_isv_for_adaptive_bounds.md` (matches the original schedule range). Per `compute_min_hold_penalty` at trade_physics.cuh:575 (`soft_factor = deficit / (deficit + T)`), HIGH T = forgiving (saturates → 0, no exit penalty), LOW T = sharp (saturates → 1, max exit penalty). Over-holding (overrun > 0) pushes temp HIGH (exit ramp); at-or-below target pushes temp LOW (strict commitment). Closed-loop control on the actual Hold-rate symptom rather than the (sentinel-masked) dir_acc proxy. Consumed by experience_kernels.cu via the kernel-passed `min_hold_temperature` scalar — the training loop seeds that scalar per-epoch via `DQNTrainer::read_min_hold_temperature_from_isv` (cold-start fallback to MIN_HOLD_TEMPERATURE_FALLBACK=50.0 when slot is at sentinel).", }, // ── SP16 T3 (2026-05-08): Wiener-optimal Welford accumulators ──── - // 12 ISV slots [462..474) — 6 per producer (HCS for - // HOLD_COST_SCALE/T2 at slot 461, MHT for MIN_HOLD_TEMPERATURE/T1 - // at slot 460). Replace the hardcoded `α = 0.05f` literal in both - // producer kernels with a signal-driven Wiener-optimal α per + // 6 ISV slots [468..474) for the MIN_HOLD_TEMPERATURE (T1) producer. + // Replace the hardcoded `α = 0.05f` literal in the producer kernel + // with a signal-driven Wiener-optimal α per // `pearl_wiener_optimal_adaptive_alpha`: // // α = diff_var / (diff_var + sample_var + ε) // - // Each block of 6 slots holds: - // - target_mean: Welford running mean of the producer's target - // (target_scale for HCS, target_temp for MHT) + // The block of 6 slots holds: + // - target_mean: Welford running mean of `target_temp` // - target_M2: Welford ΣΔ² (sample variance accumulator) // - diff_mean: Welford running mean of consecutive one-step diffs // - diff_M2: Welford ΣΔ² for the diff series // - prev_target: previous-epoch target value (for next diff calc) // - sample_count: Welford counter (number of observations) // - // FoldReset sentinel 0.0 across all 12 slots — combined with the - // cold-start fallback (sample_count < 3 → α = 1.0 REPLACE), this - // means the first observation of each new fold replaces blended - // directly, then the second observation seeds diff statistics, then - // α adapts from the third observation onward. Per + // FoldReset sentinel 0.0 across all 6 slots — combined with the + // cold-start fallback (sample_count < 3 → α = 1.0 REPLACE), the + // first observation of each new fold replaces blended directly, + // the second observation seeds diff statistics, and α adapts from + // the third observation onward. Per // `feedback_isv_for_adaptive_bounds.md` α was an adaptive bound // being hardcoded; this lifts the constant into the producer's - // own statistics, eliminating the 60-epoch convergence lag observed - // in train-multi-seed-hjzss validation. - // 6 sp16_t3_hcs_* registry entries (slots 462..468) DELETED by - // SP18 Phase 1 (2026-05-09). The Welford accumulator slots are - // a RESERVED gap; no FoldReset bookkeeping. The MHT_* entries - // below survive — MIN_HOLD_TEMPERATURE chain is RETAINED per - // DD7=c. + // own statistics. RegistryEntry { name: "sp16_t3_mht_target_mean", category: ResetCategory::FoldReset, - description: "ISV[MHT_TARGET_MEAN_INDEX=468] — SP16 T3 Welford running mean of target_temp for the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; same algorithm as the HCS counterpart at slot 462 but tracks `target_temp ∈ [5, 50]` instead of `target_scale ∈ [1, 25]`.", + description: "ISV[MHT_TARGET_MEAN_INDEX=468] — SP16 T3 Welford running mean of target_temp for the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; tracks `target_temp ∈ [5, 50]`.", }, RegistryEntry { name: "sp16_t3_mht_target_m2", category: ResetCategory::FoldReset, - description: "ISV[MHT_TARGET_M2_INDEX=469] — SP16 T3 Welford ΣΔ² for target_temp in the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; mirrors slot 463 modulo the producer it serves.", + description: "ISV[MHT_TARGET_M2_INDEX=469] — SP16 T3 Welford ΣΔ² for target_temp in the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0.", }, RegistryEntry { name: "sp16_t3_mht_diff_mean", category: ResetCategory::FoldReset, - description: "ISV[MHT_DIFF_MEAN_INDEX=470] — SP16 T3 Welford running mean of consecutive `target_temp` diffs in the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; mirrors slot 464.", + description: "ISV[MHT_DIFF_MEAN_INDEX=470] — SP16 T3 Welford running mean of consecutive `target_temp` diffs in the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0.", }, RegistryEntry { name: "sp16_t3_mht_diff_m2", category: ResetCategory::FoldReset, - description: "ISV[MHT_DIFF_M2_INDEX=471] — SP16 T3 Welford ΣΔ² for the consecutive-diff series in the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; mirrors slot 465.", + description: "ISV[MHT_DIFF_M2_INDEX=471] — SP16 T3 Welford ΣΔ² for the consecutive-diff series in the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0.", }, RegistryEntry { name: "sp16_t3_mht_prev_target", category: ResetCategory::FoldReset, - description: "ISV[MHT_PREV_TARGET_INDEX=472] — SP16 T3 previous-epoch `target_temp` for the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; mirrors slot 466.", + description: "ISV[MHT_PREV_TARGET_INDEX=472] — SP16 T3 previous-epoch `target_temp` for the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0.", }, RegistryEntry { name: "sp16_t3_mht_sample_count", category: ResetCategory::FoldReset, - description: "ISV[MHT_SAMPLE_COUNT_INDEX=473] — SP16 T3 Welford observation counter for the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0; mirrors slot 467. Cold-start fallback (sample_count < 3 → α = 1.0) ensures the first 3 epochs of each fold force REPLACE so the Welford-derived α takes over from epoch 3 onward without a 60-epoch convergence lag.", + description: "ISV[MHT_SAMPLE_COUNT_INDEX=473] — SP16 T3 Welford observation counter for the MIN_HOLD_TEMPERATURE producer kernel. Sentinel 0.0. Cold-start fallback (sample_count < 3 → α = 1.0) ensures the first 3 epochs of each fold force REPLACE so the Welford-derived α takes over from epoch 3 onward without a 60-epoch convergence lag.", }, // ── SP15 Phase 1.2 (2026-05-06): cost-net sharpe slots ──────────── // Two ISV slots [407, 408]: @@ -1905,32 +1893,32 @@ impl StateResetRegistry { RegistryEntry { name: "sp18_hrc_target_mean", category: ResetCategory::FoldReset, - description: "ISV[HRC_TARGET_MEAN_INDEX=487] — SP18 D-leg Welford running mean of target_cap for the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; first valid observation initialises via Welford increment. Combined with the cold-start fallback (sample_count<3 → α=1.0 REPLACE), the first 3 epochs of each fold force REPLACE; from epoch 3 onward Wiener-optimal α emerges from Welford state per `pearl_wiener_optimal_adaptive_alpha`. Mirrors the SP16 T3 HCS_TARGET_MEAN_INDEX=462 pattern.", + description: "ISV[HRC_TARGET_MEAN_INDEX=487] — SP18 D-leg Welford running mean of target_cap for the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; first valid observation initialises via Welford increment. Combined with the cold-start fallback (sample_count<3 → α=1.0 REPLACE), the first 3 epochs of each fold force REPLACE; from epoch 3 onward Wiener-optimal α emerges from Welford state per `pearl_wiener_optimal_adaptive_alpha`.", }, RegistryEntry { name: "sp18_hrc_target_m2", category: ResetCategory::FoldReset, - description: "ISV[HRC_TARGET_M2_INDEX=488] — SP18 D-leg Welford ΣΔ² (sample-variance accumulator) for target_cap in the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; tracks variance of `target_cap` series across each fold. Used to compute `sample_var = M2 / (n - 1)` once `n ≥ 3`. Mirrors HCS_TARGET_M2_INDEX=463.", + description: "ISV[HRC_TARGET_M2_INDEX=488] — SP18 D-leg Welford ΣΔ² (sample-variance accumulator) for target_cap in the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; tracks variance of `target_cap` series across each fold. Used to compute `sample_var = M2 / (n - 1)` once `n ≥ 3`.", }, RegistryEntry { name: "sp18_hrc_diff_mean", category: ResetCategory::FoldReset, - description: "ISV[HRC_DIFF_MEAN_INDEX=489] — SP18 D-leg Welford running mean of consecutive `target_cap` one-step diffs in the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; first diff observation lands when sample_count reaches 2. Mirrors HCS_DIFF_MEAN_INDEX=464.", + description: "ISV[HRC_DIFF_MEAN_INDEX=489] — SP18 D-leg Welford running mean of consecutive `target_cap` one-step diffs in the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; first diff observation lands when sample_count reaches 2.", }, RegistryEntry { name: "sp18_hrc_diff_m2", category: ResetCategory::FoldReset, - description: "ISV[HRC_DIFF_M2_INDEX=490] — SP18 D-leg Welford ΣΔ² for the consecutive-diff series in the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; provides `diff_var` half of the Wiener formula α = diff_var / (diff_var + sample_var + ε). Mirrors HCS_DIFF_M2_INDEX=465.", + description: "ISV[HRC_DIFF_M2_INDEX=490] — SP18 D-leg Welford ΣΔ² for the consecutive-diff series in the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; provides `diff_var` half of the Wiener formula α = diff_var / (diff_var + sample_var + ε).", }, RegistryEntry { name: "sp18_hrc_prev_target", category: ResetCategory::FoldReset, - description: "ISV[HRC_PREV_TARGET_INDEX=491] — SP18 D-leg previous-epoch `target_cap` for the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; written every launch from the freshly-computed `target_cap` so the next launch's diff calculation has a basis. Mirrors HCS_PREV_TARGET_INDEX=466.", + description: "ISV[HRC_PREV_TARGET_INDEX=491] — SP18 D-leg previous-epoch `target_cap` for the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; written every launch from the freshly-computed `target_cap` so the next launch's diff calculation has a basis.", }, RegistryEntry { name: "sp18_hrc_sample_count", category: ResetCategory::FoldReset, - description: "ISV[HRC_SAMPLE_COUNT_INDEX=492] — SP18 D-leg Welford observation counter for the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; incremented every launch (excluding cold-start sentinel-guard early-return). The cold-start fallback (sample_count < WELFORD_MIN_SAMPLE_COUNT=3 → α = 1.0 REPLACE) keeps the producer responsive in epochs 1-2 of each fold while Welford state stabilises. Mirrors HCS_SAMPLE_COUNT_INDEX=467.", + description: "ISV[HRC_SAMPLE_COUNT_INDEX=492] — SP18 D-leg Welford observation counter for the `hold_reward_cap_update_kernel` producer. Sentinel 0.0; incremented every launch (excluding cold-start sentinel-guard early-return). The cold-start fallback (sample_count < WELFORD_MIN_SAMPLE_COUNT=3 → α = 1.0 REPLACE) keeps the producer responsive in epochs 1-2 of each fold while Welford state stabilises.", }, // ── B-leg observability + reset gate slots [493..505) ───────────── RegistryEntry { @@ -1967,12 +1955,12 @@ impl StateResetRegistry { RegistryEntry { name: "sp18_tdb_target_m2", category: ResetCategory::FoldReset, - description: "ISV[TDB_TARGET_M2_INDEX=499] — SP18 B-leg Welford ΣΔ² for q_next_target. Sentinel 0.0; mirrors HRC_TARGET_M2_INDEX=488 and HCS_TARGET_M2_INDEX=463 modulo the producer it serves. Producer wire in Phase 4 — not yet wired.", + description: "ISV[TDB_TARGET_M2_INDEX=499] — SP18 B-leg Welford ΣΔ² for q_next_target. Sentinel 0.0; mirrors HRC_TARGET_M2_INDEX=488 modulo the producer it serves. Producer wire in Phase 4 — not yet wired.", }, RegistryEntry { name: "sp18_tdb_diff_mean", category: ResetCategory::FoldReset, - description: "ISV[TDB_DIFF_MEAN_INDEX=500] — SP18 B-leg Welford running mean of consecutive q_next_target diffs. Sentinel 0.0; mirrors HRC_DIFF_MEAN_INDEX=489 and HCS_DIFF_MEAN_INDEX=464. Producer wire in Phase 4 — not yet wired.", + description: "ISV[TDB_DIFF_MEAN_INDEX=500] — SP18 B-leg Welford running mean of consecutive q_next_target diffs. Sentinel 0.0; mirrors HRC_DIFF_MEAN_INDEX=489. Producer wire in Phase 4 — not yet wired.", }, RegistryEntry { name: "sp18_tdb_diff_m2", @@ -1987,7 +1975,7 @@ impl StateResetRegistry { RegistryEntry { name: "sp18_tdb_sample_count", category: ResetCategory::FoldReset, - description: "ISV[TDB_SAMPLE_COUNT_INDEX=503] — SP18 B-leg Welford observation counter. Sentinel 0.0; cold-start fallback (sample_count < 3 → α = 1.0) ensures the first 3 epochs of each fold force REPLACE so the Welford-derived α takes over from epoch 3 onward. Mirrors HRC_SAMPLE_COUNT_INDEX=492 and HCS_SAMPLE_COUNT_INDEX=467. Producer wire in Phase 4 — not yet wired.", + description: "ISV[TDB_SAMPLE_COUNT_INDEX=503] — SP18 B-leg Welford observation counter. Sentinel 0.0; cold-start fallback (sample_count < 3 → α = 1.0) ensures the first 3 epochs of each fold force REPLACE so the Welford-derived α takes over from epoch 3 onward. Mirrors HRC_SAMPLE_COUNT_INDEX=492. Producer wire in Phase 4 — not yet wired.", }, RegistryEntry { name: "sp18_b_leg_reserved", @@ -2226,9 +2214,4 @@ mod tests { ); } } - - // sp16_t2_t3_slots_marked_retired test DELETED by SP18 Phase 1 - // (2026-05-09) — locking the existence of slots that have been fully - // deleted is pointless ceremony per user call. The slots no longer - // exist in the registry; asserting their existence would panic. } diff --git a/crates/ml/src/trainers/dqn/trainer/training_loop.rs b/crates/ml/src/trainers/dqn/trainer/training_loop.rs index 1c386b324..133202c73 100644 --- a/crates/ml/src/trainers/dqn/trainer/training_loop.rs +++ b/crates/ml/src/trainers/dqn/trainer/training_loop.rs @@ -561,8 +561,6 @@ impl DQNTrainer { // boundary the input has been refreshed N×B times // (N=collector steps, B=batch). Per // `pearl_canary_input_freshness_launch_order.md`. - // launch_hold_cost_scale_update DELETED by SP18 Phase 1 - // (2026-05-09). Replaced by SP18 D-leg in Phase 2. // SP16 Phase 1 (revised) instrumentation: emit the // realised hold-rate overrun + temperature so we can // verify the swap works at Fold 0 + Fold 1 transitions. @@ -614,8 +612,6 @@ impl DQNTrainer { epoch, obs, tgt, overrun_norm, target_temp, temp, alpha, n as u32, ); } - // hold_cost_scale_diag emit DELETED by SP18 Phase 1 - // (2026-05-09). The producer chain is gone; nothing to emit. } // D.8 Plan 2 Task 6C: update TLOB regime focus EMA in ISV at epoch boundary. @@ -8866,11 +8862,6 @@ impl DQNTrainer { ); } } - // sp16_phase2_hold_cost_scale_adaptive + 6 sp16_t3_hcs_* - // dispatch arms DELETED by SP18 Phase 1 (2026-05-09) atomically - // with the registry entries (see state_reset_registry.rs). - // The MHT_* arms below survive — MIN_HOLD_TEMPERATURE chain is - // RETAINED per DD7=c. "sp16_t3_mht_target_mean" => { if let Some(ref fused) = self.fused_ctx { use crate::cuda_pipeline::sp14_isv_slots::{ @@ -9058,8 +9049,9 @@ impl DQNTrainer { ); } } - // HRC_* Welford accumulators — D-leg, mirrors SP16 T3 HCS_* layout. - // All 6 sentinels = 0.0 (SENTINEL_WELFORD_ZERO). + // HRC_* Welford accumulators — D-leg, 6 slots [487..493) for + // hold_reward_cap_update_kernel. All 6 sentinels = 0.0 + // (SENTINEL_WELFORD_ZERO). "sp18_hrc_target_mean" => { if let Some(ref fused) = self.fused_ctx { use crate::cuda_pipeline::sp14_isv_slots::{ diff --git a/crates/ml/tests/sp14_oracle_tests.rs b/crates/ml/tests/sp14_oracle_tests.rs index ba0381364..4fa8f8765 100644 --- a/crates/ml/tests/sp14_oracle_tests.rs +++ b/crates/ml/tests/sp14_oracle_tests.rs @@ -2170,11 +2170,6 @@ mod sp16_phase1_min_hold_temperature_gpu { } } -// SP16 Phase 2 / Phase 3 oracle tests (11 GPU tests + helpers + 1 -// hardcoded-alpha regression test) DELETED by SP18 Phase 1 -// (2026-05-09). The hold_cost_scale_update_kernel cubin they -// include_bytes! is gone. See docs/sp18-wireup-audit.md (A2). - // ═══════════════════════════════════════════════════════════════════════════ // SP16 Phase 0 (2026-05-08) — Q-by-action HEALTH_DIAG diagnostic. // diff --git a/docs/dqn-wire-up-audit.md b/docs/dqn-wire-up-audit.md index acf8a1028..fe433e658 100644 --- a/docs/dqn-wire-up-audit.md +++ b/docs/dqn-wire-up-audit.md @@ -2,6 +2,81 @@ **Status:** Populated during Plan 1 Task 6 (A.5 orphan audit). Updated on every commit per Invariant 7. +## 2026-05-09 — SP18 archaeology cleanup pass (post-Phase 2) + +Pure-comment cleanup follow-up to the SP18 Phase 1 atomic deletion (3c318953a) +and Phase 2 device-fn introduction (8da8e2e58). The Phase 1 implementer left +"DELETED by SP18 Phase 1" archaeology markers + "RETIRED" docstrings in +production source to keep the deletion diff focused; per +`feedback_no_legacy_aliases` ("avoid backwards-compatibility hacks like +removed-comment markers") and CLAUDE.md ("don't add comments that explain +what the code does"), those markers are now stripped — git history is the +historical record, the code itself should not narrate its own deletion. + +Affected files (pure comment edits — no code-path change): + +- `crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs` — collapsed the + ~5000-char `ISV_TOTAL_DIM` const docstring (slot-by-slot SP3→SP18 history) + to a 12-line conceptual definition pointing at `sp14_isv_slots.rs` for the + range definitions. The layout fingerprint seed + (`RESERVED_GAP_461_TO_468=SP18_P1_RETIRED;`) is load-bearing and + preserved. +- `crates/ml/src/cuda_pipeline/sp14_isv_slots.rs` — deleted "SP16 Phase 2 + RETIRED" comment block + the "HCS_* slots [462..468) RETIRED" marker + + "SP13 [380..383)/SP16 [461..474) ALLOCATED but RETIRED per PP.4" prose + inside the SP18 D-leg block + the test-removal note before the surviving + MHT block lock test. The SP16 T3 Welford block comment was tightened to + describe the surviving MHT (T1) producer only. +- `crates/ml/src/cuda_pipeline/state_layout.cuh` — deleted the "SP16 Phase 2 + / T3 HCS SLOTS (RETIRED 2026-05-09)" header block above the surviving + MHT slots; collapsed the WELFORD_ALPHA_MIN comment to reference only the + surviving MIN_HOLD_TEMPERATURE producer. +- `crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs` — deleted the trailing + "HoldCostScaleUpdateOps DELETED by SP18 Phase 1" comment block. +- `crates/ml/src/cuda_pipeline/gpu_experience_collector.rs` — replaced + the stale prose about "the trainer's host-side controller in + training_loop.rs:3604 reads slot 382 + slot 381 and writes the priced + cost to ISV[HOLD_COST_INDEX=380]" with current-state prose pointing at + the SP16-P1 MIN_HOLD_TEMPERATURE producer (slot 460) and SP18 D-leg + reward shaping at slots [483..493). +- `crates/ml/src/cuda_pipeline/sp5_isv_slots.rs` — updated the SP13 v3 + P0a.T3 description to reflect that slot 380 is now a constructor-init + diagnostic anchor, not a controller output. +- `crates/ml/src/trainers/dqn/state_reset_registry.rs` — deleted 7 + "DELETED by SP18 Phase 1" archaeology comments (registry-block + introduction, deleted-test marker at end of file, "mirrors HCS_* + layout" / "mirrors slot N" cross-references in surviving HRC_*/MHT_*/ + TDB_* entries). +- `crates/ml/src/trainers/dqn/trainer/training_loop.rs` — deleted the 3 + "DELETED by SP18 Phase 1" markers at the launch_hold_cost_scale_update + call site, the hold_cost_scale_diag emit site, and the dispatch-arms + block. Tightened the HRC_* dispatch-arm header comment to no longer + mention the deleted SP16 T3 HCS_* layout. +- `crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs` constructor-write site + for slot 380 — replaced "rewritten every step by the host-side + controller in training_loop.rs" with "constructor-init-only diagnostic + anchor" prose reflecting the post-Phase-1 reality (per audit doc A4 + resolution). +- `crates/ml/build.rs` — deleted the `hold_cost_scale_update_kernel.cu + DELETED` comment in the cubin manifest. +- `crates/ml/tests/sp14_oracle_tests.rs` — deleted the multi-line + "11 GPU oracle tests DELETED by SP18 Phase 1" archaeology marker (the + tests themselves were already deleted in commit 3c318953a; the marker + comment was the last residual). + +Verification: +- `grep -rn "HOLD_COST_SCALE_INDEX\|HCS_TARGET\|HCS_DIFF\|HCS_PREV\|HCS_SAMPLE\|HOLD_COST_CONTROLLER_GAIN\|HOLD_COST_FLOOR_RATIO\|HOLD_COST_CEIL_RATIO\|hold_cost_scale_update" crates/ml/src/ --include="*.rs" --include="*.cu" --include="*.cuh"` — empty. +- `cargo check --workspace` clean (warnings only — pre-existing). +- `scripts/audit_sp18_consumers.sh --check` — passes (fingerprint regenerated + in `docs/sp18-wireup-audit.md`). +- Audit-script grep patterns + audit-doc historical / fingerprint sections + retain HOLD_COST_SCALE / HCS_* references by design — the audit script + is the diagnostic tool and the audit doc is the design-history record. +- Markdown spec/plan files in `docs/superpowers/specs/` and + `docs/superpowers/plans/` retain HOLD_COST_SCALE references unchanged + per `feedback_trust_code_not_docs` corollary (spec docs ARE the record + of past design decisions). + ## 2026-05-09 — SP18 v2 Phase 2 Tasks 2.1-2.5: structural Hold opportunity-cost device fn + 3-site migration (INTERIM STATE LIFTED) Atomic introduction of `compute_sp18_hold_opportunity_cost` device function diff --git a/docs/sp18-wireup-audit.md b/docs/sp18-wireup-audit.md index bc5420600..59458b60d 100644 --- a/docs/sp18-wireup-audit.md +++ b/docs/sp18-wireup-audit.md @@ -213,14 +213,13 @@ re-capture is committed as part of Task 1.6 (close-out). ``` === D-leg: Slot 380 (HOLD_COST_INDEX) consumers === - total_hits=43 + total_hits=38 crates/ml/build.rs 1 crates/ml/src/cuda_pipeline/state_layout.cuh 1 - crates/ml/src/cuda_pipeline/gpu_experience_collector.rs 1 crates/ml/src/cuda_pipeline/hold_rate_observer_kernel.cu 1 crates/ml/src/cuda_pipeline/sp5_isv_slots.rs 1 crates/ml/src/cuda_pipeline/sp13_isv_slots.rs 1 - crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 6 + crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 2 crates/ml/src/trainers/dqn/trainer/training_loop.rs 3 crates/ml/src/trainers/dqn/state_reset_registry.rs 1 docs/sp18-wireup-audit.md 5 @@ -229,35 +228,24 @@ re-capture is committed as part of Task 1.6 (close-out). docs/superpowers/plans/2026-05-04-sp13-redefine-success-for-predictive-skill.md 5 docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md 4 === D-leg: Slot 461 (HOLD_COST_SCALE_INDEX) consumers === - total_hits=30 - crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 1 - crates/ml/src/cuda_pipeline/sp14_isv_slots.rs 2 + total_hits=27 docs/sp18-wireup-audit.md 6 docs/dqn-wire-up-audit.md 8 docs/superpowers/plans/2026-05-08-sp16-hold-collapse-structural-fix.md 10 docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md 3 === D-leg: Slots [462..468) (HCS_* Welford) consumers === - total_hits=19 - crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 1 - crates/ml/src/trainers/dqn/state_reset_registry.rs 9 + total_hits=9 docs/dqn-wire-up-audit.md 8 docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md 1 === D-leg: hold_cost_scale_update_kernel references === - total_hits=67 - crates/ml/tests/sp14_oracle_tests.rs 1 - crates/ml/build.rs 1 - crates/ml/src/cuda_pipeline/state_layout.cuh 1 - crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 5 - crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs 1 - crates/ml/src/cuda_pipeline/sp14_isv_slots.rs 3 - crates/ml/src/trainers/dqn/trainer/training_loop.rs 1 + total_hits=54 docs/sp18-wireup-audit.md 11 docs/dqn-wire-up-audit.md 18 docs/superpowers/specs/2026-05-08-sp18-reward-shape-hold-attractor-design.md 4 docs/superpowers/plans/2026-05-08-sp16-hold-collapse-structural-fix.md 9 docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md 12 === D-leg: hold_rate_observer_kernel (RETAINED — diag chain stays per DD7=c) === - total_hits=162 + total_hits=160 crates/ml/tests/sp13_phase0_oracle_tests.rs 19 crates/ml/tests/sp14_oracle_tests.rs 20 crates/ml/build.rs 5 @@ -267,7 +255,7 @@ re-capture is committed as part of Task 1.6 (close-out). crates/ml/src/cuda_pipeline/hold_rate_observer_kernel.cu 4 crates/ml/src/cuda_pipeline/sp5_isv_slots.rs 3 crates/ml/src/cuda_pipeline/sp13_isv_slots.rs 2 - crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 10 + crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs 8 crates/ml/src/cuda_pipeline/gpu_aux_trunk.rs 5 crates/ml/src/cuda_pipeline/sp14_isv_slots.rs 5 crates/ml/src/trainers/dqn/trainer/training_loop.rs 13 @@ -283,14 +271,13 @@ re-capture is committed as part of Task 1.6 (close-out). === D-leg: Per-bar Hold-cost subtraction sites (3 lines we change in Phase 1.5) === total_hits= === D-leg: state_layout.cuh mirror constants (HOLD_COST + HCS) === - total_hits=2 - crates/ml/src/cuda_pipeline/state_layout.cuh 2 + total_hits=1 + crates/ml/src/cuda_pipeline/state_layout.cuh 1 === D-leg: state_reset_registry slot 461 entries === - total_hits=3 - crates/ml/src/trainers/dqn/state_reset_registry.rs 3 + total_hits= === D-leg: Cubin manifest references in build.rs === - total_hits=3 - crates/ml/build.rs 3 + total_hits=2 + crates/ml/build.rs 2 === B-leg: td_lambda_kernel launch sites === total_hits=9 crates/ml/src/cuda_pipeline/gpu_experience_collector.rs 8