fix(class-a-audit-batch-4a): DD saturation floor adaptive + legacy DD path Case A

Per Class A audit-fix Batch 4-A (deferred from P1-wiring/P1-producer due to
audit-doc errors). Fixes 2 of 4 deferred items; Batch 4-B handles plan_threshold
floor + MIN_HOLD_TEMPERATURE in a separate commit.

Item 1: DD saturation floor (the upper end of the DD ramp at trade_physics.cuh:154
in apply_margin_cap, NOT line 548 as the audit doc claimed — that line is a
magnitude action constant; the actual saturation floor lives in apply_margin_cap)
  - NEW slot DD_SATURATION_FLOOR_ADAPTIVE_INDEX=458
  - Producer dd_saturation_floor_update_kernel.cu — p75(per-env DD_MAX) × 1.5
    via Welford `mean + Z_75 × sigma` estimator with `max(p75, mean)` robustness
    guard, mirrors P0-A REWARD_POS_CAP producer pattern (Pearl-A bootstrap +
    Welford α=0.01)
  - Cold-start fallback: 0.25f (DD_SATURATION_FLOOR_DEFAULT in state_layout.cuh)
  - Bounds: [0.10, 0.50] (Category-1 dimensional safety)
  - Distinct from SP15_DD_THRESHOLD_INDEX=421 (the SP15 quadratic DD-penalty
    *trigger* threshold, a *lower* bound; this slot is the *upper* end of the
    linear position-size scaling ramp dd_scale = max(0.05, 1.0 − dd_frac/floor))
  - Threaded `isv_signals_ptr` into `apply_margin_cap` with NULL-tolerant
    cold-start fallback to DD_SATURATION_FLOOR_DEFAULT
  - 4 oracle tests (Pearl-A bootstrap, no-DD guard, bounds clamp, Welford EMA)

Item 2: Legacy compute_drawdown_penalty path → Case A (DELETED)
  - Decision rationale: SP15's quadratic asymmetric DD penalty
    (compute_sp15_final_reward_kernel.cu:154 via sp15_dd_penalty helper) runs
    unconditionally as a post-modifier on the SP11-composed reward with
    ISV-driven λ_dd (slot 420) and DD threshold (slot 421). Layering the legacy
    linear-ramp penalty inside the SP11 composer on top of the SP15 quadratic
    creates double-counting of DD shaping — exactly the code-smell the Class A
    audit was designed to eliminate. Per `feedback_no_legacy_aliases.md` and
    `feedback_no_partial_refactor.md`.
  - Atomic deletion across:
      - `compute_drawdown_penalty` device function (trade_physics.cuh)
      - Single call site at experience_kernels.cu:3822
      - `dd_threshold` and `w_dd` kernel arguments
      - `w_dd` Rust config field (gpu_experience_collector.rs +
        trainers/dqn/config.rs DQNHyperparameters)
      - `w_dd` profile section + dispatch (training_profile.rs RewardSection,
        OptimizableParameterRanges, FixedRewardParameters, ParamLookup
        dispatch, profile→hyperparam mapping, test assertion)
      - `w_dd *= rki` risk-intensity multiplier (config.rs)
      - `w_dd` TOML keys (dqn-hyperopt.toml × 2, dqn-localdev.toml,
        dqn-production.toml, dqn-smoketest.toml)
      - Stale doc comments on hyperopt/adapters/dqn.rs + config.rs
        risk_intensity field
  - `config.dd_threshold` SURVIVES (still consumed by `launch_sp15_dd_state`
    as the dd_budget for DD_PCT scaling). Documented in field comment.

ISV_TOTAL_DIM: 458 → 459 (Item 1 adds 1 slot; Item 2 is pure deletion)

Cumulative WR-plateau fix series (this is commit 7):
- Class C bug 1 + P0-B (8f218cab2)
- P0-C (316db416b)
- P0-A (394de7d43)
- P1 wiring (c4b6d6ef2) — 1 of 4 wireable
- P0-A downstream (657972a4b)
- P1 producer (87d597d5d)
- audit-fix 4-A (this commit)

Verification: 16 sp14_oracle_tests pass (incl. 4 new), 36 sp15_phase1_oracle_tests
pass, 12 sp14_isv_slots layout tests pass, 4 state_reset_registry tests pass
(every-FoldReset-arm-has-dispatch contract holds), workspace cargo check clean.

Per feedback_isv_for_adaptive_bounds + feedback_no_partial_refactor +
feedback_no_legacy_aliases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-05-08 10:41:07 +02:00
parent 87d597d5d7
commit 7e9a8f6ef1
21 changed files with 1191 additions and 93 deletions

View File

@@ -827,6 +827,35 @@ fn main() {
// Block-tree-reduce (no atomicAdd) per
// `feedback_no_atomicadd.md`. Per-epoch boundary launch.
"kelly_bayesian_priors_update_kernel.cu",
// Class A audit-fix Batch 4-A (2026-05-08): adaptive DD saturation
// floor producer. Single-block 256-thread kernel that sweeps the
// per-env DD trajectory tile `dd_state_per_env[n_envs * 6]`
// (populated by `dd_state_kernel`), aggregates DD_MAX (offset 1)
// across envs via Welford `mean + Z_75 × sigma` p75 estimator
// with `max(p75, mean)` robustness guard × 1.5 safety factor,
// and slow-EMA blends into ISV[DD_SATURATION_FLOOR_ADAPTIVE_INDEX
// =458]. Pearl-A first-observation bootstrap (sentinel 0.25
// matches pre-fix hardcoded `0.25f` in
// `trade_physics.cuh::apply_margin_cap` for bit-identical cold-
// start); α=0.01 slow EMA thereafter (DD distribution is a slow-
// moving fold-volatility property — same cadence as P0-A
// REWARD_POS_CAP). Bounds [0.10, 0.50] are Category-1 dimensional
// safety floors per `feedback_isv_for_adaptive_bounds`. Replaces
// the hardcoded saturation floor (the upper end of the linear
// position-size scaling ramp `dd_scale = max(0.05, 1.0
// dd_frac/saturation_floor)`). Distinct from
// `SP15_DD_THRESHOLD_INDEX=421` (the SP15 quadratic DD-penalty
// *trigger* threshold, a *lower* bound). 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` Rust config field +
// the `dd_threshold` and `w_dd` 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).
// Block-tree-reduce (no atomicAdd) per `feedback_no_atomicadd.md`.
// Per-epoch boundary launch.
"dd_saturation_floor_update_kernel.cu",
// SP14 Layer C Phase C.6 (2026-05-08): h_s2_aux RMS EMA producer.
// Single-block 256-thread kernel computing RMS = sqrt(mean(x²))
// over `h_s2_aux [B, SH2]` (aux trunk final output, no activation)