feat(sp18 v2 P1.T3-T6): atomic delete SP13/SP16 hold_cost_scale chain

Deletes the entire reactive Hold-cost controller chain from SP13 P0a / SP16
P2 / SP16 T3 atomically — replaced by the SP18 D-leg structural opportunity-
cost reward landing in Phase 2.

Per DD7(c): observation chain preserved (slots 380, 382). Slot 380 becomes
constructor-init-only diagnostic at HOLD_COST_BASE=0.005, never updated.

18 consumer sites deleted (8 from plan checklist + 10 from A1-A10 audit
expansion):

Production code:
  - 3 reward subtraction sites (replaced with Phase 2 placeholder comments)
  - hold_cost_scale_update_kernel.cu (file deleted)
  - HoldCostScaleUpdateOps struct in gpu_aux_trunk.rs (~120 lines)
  - launch_hold_cost_scale_update in gpu_dqn_trainer.rs (forwarder)
  - Host controller block in training_loop.rs (~60 lines)
  - Slot constants [461..468) in sp14_isv_slots.rs
  - HOLD_COST_CONTROLLER_GAIN/FLOOR/CEIL constants in sp13_isv_slots.rs
  - state_layout.cuh mirror constants for [461..468)
  - build.rs cubin manifest entry
  - 7 fold-reset registry entries + 7 dispatch arms

Tests:
  - sp14_oracle_tests.rs lines 2173-2926 (11 tests + helpers, ~750 lines)
    — these include_bytes! the deleted cubin and cannot survive
  - lock_sp18_v2_pp4_retired_chain test (deleted, no inverse-contract
    replacement — locking a deletion is pointless ceremony per user call)

Layout fingerprint: range [461..468) is RESERVED gap (SP14-C.1 pattern;
ISV_TOTAL_DIM stays at 507 for checkpoint compatibility). Layout fingerprint
seed updated atomically: HOLD_COST_SCALE + HCS_* slots replaced with
RESERVED_GAP_461_TO_468=SP18_P1_RETIRED marker.

INTERIM STATE: 3 reward sites are now missing the per-bar Hold cost. This
is forbidden to L40S-dispatch until Phase 2 lands the
compute_sp18_hold_opportunity_cost device fn that replaces the deleted
subtraction. The audit doc records this hold.

Validation: cargo check --workspace clean; cargo test -p ml --lib passes
(state_reset_registry::every_fold_and_soft_reset_entry_has_dispatch_arm,
sp16_t3_wiener_welford_slot_layout_locked, sp18_combined_slot_layout_locked,
sp18_shrink_perturb_slot_layout_locked, sp18_fold_reset_entries_present —
all OK). Audit fingerprint: per-bar Hold-cost subtraction sites count
13 → 0 (smoking gun for complete deletion).

Plan: docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md
Audit: docs/sp18-wireup-audit.md (full A1-A10 expansion + post-deletion
       fingerprint)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-05-09 09:51:03 +02:00
parent b43413e4d3
commit 3c318953a7
13 changed files with 299 additions and 1814 deletions

View File

@@ -2229,32 +2229,8 @@ 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"));
/// SP16 Phase 2 (2026-05-08): adaptive Hold cost scale producer cubin.
/// Single-thread cold-path kernel mirroring the SP16-P1
/// `min_hold_temperature_update_kernel` driver pattern. Reads
/// `ISV[HOLD_RATE_OBSERVED_EMA_INDEX=382]` and
/// `ISV[HOLD_RATE_TARGET_INDEX=381]` (same input chain as SP16-P1) and
/// maps the overrun into a [1, 25] multiplier:
///
/// overrun = max(0, observed target)
/// overrun_norm = clamp(overrun / max(target, 0.01), 0, 1)
/// target_scale = SCALE_MIN + (SCALE_MAX SCALE_MIN) × overrun_norm
///
/// then Pearl-A-bootstrap + Welford-α=0.05 EMA blends into
/// `ISV[HOLD_COST_SCALE_INDEX=461]`. The 3 consumer sites in
/// `experience_kernels.cu` multiply `isv[ISV_HOLD_COST_IDX=380]` by
/// `isv[461]` to scale the per-bar Hold cost when over-holding is
/// observed. Cold-start fallback: when slot 461 is at sentinel 0.0 OR
/// outside [1, 25], the consumer uses scale=1.0 (bit-identical
/// pre-Phase-2 behaviour). Per-mortem of train-multi-seed-pfh9n showed
/// realised Hold-rate climbing 0.25 → 0.52 with cost magnitude ~0.006
/// (~100× smaller than per-bar reward magnitudes); the adaptive scale
/// pushes effective cost to ~0.15/bar at 100% overrun, competitive with
/// per-bar reward magnitudes ~0.01-0.1 but well below SP12 cap [-10, +5].
/// Pearl-A first-observation bootstrap (sentinel 0.0 → REPLACE). α=0.05
/// mid-cadence EMA. Loaded by `gpu_aux_trunk::HoldCostScaleUpdateOps`.
/// Per-epoch boundary launch (same cadence as SP16-P1 producer).
pub(crate) static HOLD_COST_SCALE_UPDATE_CUBIN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/hold_cost_scale_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
@@ -3661,9 +3637,7 @@ const fn layout_fingerprint_seed() -> &'static [u8] {
KELLY_PRIOR_WINS=454;KELLY_PRIOR_LOSSES=455;KELLY_PRIOR_SUM_WINS=456;KELLY_PRIOR_SUM_LOSSES=457;\
DD_SATURATION_FLOOR_ADAPTIVE=458;\
PLAN_THRESHOLD_FLOOR_ADAPTIVE=459;MIN_HOLD_TEMPERATURE_ADAPTIVE=460;\
HOLD_COST_SCALE=461;\
HCS_TARGET_MEAN=462;HCS_TARGET_M2=463;HCS_DIFF_MEAN=464;\
HCS_DIFF_M2=465;HCS_PREV_TARGET=466;HCS_SAMPLE_COUNT=467;\
RESERVED_GAP_461_TO_468=SP18_P1_RETIRED;\
MHT_TARGET_MEAN=468;MHT_TARGET_M2=469;MHT_DIFF_MEAN=470;\
MHT_DIFF_M2=471;MHT_PREV_TARGET=472;MHT_SAMPLE_COUNT=473;\
SLOT_474_A_VAR_EMA_DIR=474;\
@@ -7845,12 +7819,7 @@ pub struct GpuDqnTrainer {
/// boundary launch (same cadence as P0-A REWARD_POS_CAP).
min_hold_temperature_update_ops: super::gpu_aux_trunk::MinHoldTemperatureUpdateOps,
/// SP16 Phase 2 (2026-05-08): per-epoch adaptive Hold cost scale
/// producer. Pre-loads the `CudaFunction` handle at construction
/// per `pearl_no_host_branches_in_captured_graph.md`. Per-epoch
/// boundary launch (same cadence as SP16-P1
/// MIN_HOLD_TEMPERATURE — same input chain).
hold_cost_scale_update_ops: super::gpu_aux_trunk::HoldCostScaleUpdateOps,
// 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.
@@ -15793,89 +15762,9 @@ impl GpuDqnTrainer {
Ok(())
}
/// SP16 Phase 2 (2026-05-08): launch GPU-only adaptive Hold cost
/// scale producer.
///
/// Reads `ISV[HOLD_RATE_OBSERVED_EMA_INDEX=382]` and
/// `ISV[HOLD_RATE_TARGET_INDEX=381]` (same input chain as SP16-P1
/// MIN_HOLD_TEMPERATURE), maps overrun into a [1, 25] multiplier,
/// and Pearl-A-bootstrap + α=0.05 EMA blends into
/// `ISV[HOLD_COST_SCALE_INDEX=461]`. Consumed by 3 sites in
/// `experience_kernels.cu` (segment_complete + per-bar positioned-
/// Hold + per-bar flat-Hold) which multiply
/// `isv[ISV_HOLD_COST_IDX=380]` by `isv[461]` to scale the
/// per-bar Hold cost when over-holding is observed.
///
/// Why this kernel exists (post-mortem of train-multi-seed-pfh9n):
/// realised Hold rate climbed 0.25 → 0.52 across training while the
/// cost penalty stayed at ~0.006 — ~100× smaller than per-bar
/// reward magnitudes (popart=0.97, cf=0.65). Hold became
/// effectively free. The adaptive scale pushes effective cost to
/// ~0.15/bar at 100% overrun (observed=2× target), competitive
/// with per-bar reward magnitudes (~0.01-0.1) but well below the
/// SP12 asymmetric cap [-10, +5] so no clamp interaction.
///
/// Per `feedback_isv_for_adaptive_bounds.md` the bounds [1, 25] are
/// Category-1 dimensional safety floors (NOT tuning).
///
/// Per `feedback_no_partial_refactor.md` the kernel + launcher + 3
/// consumer sites + tests + audit doc land in the same atomic commit.
///
/// Per `pearl_canary_input_freshness_launch_order.md` this launch
/// MUST fire AFTER the per-step `hold_rate_observer` chain (which
/// updates the input slot 382 every step) — same launch ordering
/// constraint as the sibling `launch_min_hold_temperature_update`.
///
/// # Pearls applied
/// - `pearl_first_observation_bootstrap.md` (sentinel 0.0 → REPLACE)
/// - `pearl_no_host_branches_in_captured_graph.md`
/// - `pearl_symmetric_clamp_audit.md` (bilateral clamp on
/// target_scale + post-blend)
/// - `feedback_isv_for_adaptive_bounds.md` (bounds [1, 25] are
/// dimensional safety floors, not tuning)
/// - `feedback_no_atomicadd.md` (single-thread kernel)
pub(crate) fn launch_hold_cost_scale_update(
&self,
) -> Result<(), MLError> {
use crate::cuda_pipeline::sp14_isv_slots::{
HOLD_COST_SCALE_INDEX, HOLD_COST_SCALE_MAX,
HOLD_COST_SCALE_MIN, SENTINEL_HOLD_COST_SCALE, SENTINEL_HOLD_RATE_OBSERVED,
HCS_TARGET_MEAN_INDEX, HCS_TARGET_M2_INDEX,
HCS_DIFF_MEAN_INDEX, HCS_DIFF_M2_INDEX,
HCS_PREV_TARGET_INDEX, HCS_SAMPLE_COUNT_INDEX,
};
use crate::cuda_pipeline::sp13_isv_slots::{
HOLD_RATE_OBSERVED_EMA_INDEX, HOLD_RATE_TARGET_INDEX,
};
debug_assert!(
self.isv_signals_dev_ptr != 0,
"launch_hold_cost_scale_update: isv_signals_dev_ptr must be allocated"
);
// SP16 T3 (2026-05-08): hardcoded `α=0.05` removed — α is now
// Wiener-optimal, derived from Welford accumulators in slots
// [462..468). Per `pearl_wiener_optimal_adaptive_alpha`.
self.hold_cost_scale_update_ops.launch(
&self.stream,
self.isv_signals_dev_ptr,
HOLD_COST_SCALE_INDEX as i32,
HOLD_RATE_OBSERVED_EMA_INDEX as i32,
HOLD_RATE_TARGET_INDEX as i32,
HCS_TARGET_MEAN_INDEX as i32,
HCS_TARGET_M2_INDEX as i32,
HCS_DIFF_MEAN_INDEX as i32,
HCS_DIFF_M2_INDEX as i32,
HCS_PREV_TARGET_INDEX as i32,
HCS_SAMPLE_COUNT_INDEX as i32,
SENTINEL_HOLD_COST_SCALE,
SENTINEL_HOLD_RATE_OBSERVED,
HOLD_COST_SCALE_MIN,
HOLD_COST_SCALE_MAX,
)?;
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.
@@ -24424,14 +24313,8 @@ impl GpuDqnTrainer {
let min_hold_temperature_update_ops =
super::gpu_aux_trunk::MinHoldTemperatureUpdateOps::new(&stream)?;
// SP16 Phase 2 (2026-05-08): adaptive Hold cost scale producer.
// Pre-loads the `CudaFunction` handle at construction per
// `pearl_no_host_branches_in_captured_graph.md`. Per-epoch
// boundary launch (same cadence and input chain as SP16-P1
// MIN_HOLD_TEMPERATURE — they share slots 382 + 381 as input
// and write to slots 460 + 461 respectively).
let hold_cost_scale_update_ops =
super::gpu_aux_trunk::HoldCostScaleUpdateOps::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::<f32>(b * sh2)
@@ -25292,8 +25175,7 @@ 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,
// SP16 Phase 2 (2026-05-08): adaptive Hold cost scale producer.
hold_cost_scale_update_ops,
// hold_cost_scale_update_ops field-init DELETED by SP18 Phase 1.
speculative_h_s2,
speculative_features,
speculative_valid: false,