diff --git a/crates/ml-alpha/cuda/rl_confidence_gate.cu b/crates/ml-alpha/cuda/rl_confidence_gate.cu index 6a2562e03..b8862c596 100644 --- a/crates/ml-alpha/cuda/rl_confidence_gate.cu +++ b/crates/ml-alpha/cuda/rl_confidence_gate.cu @@ -34,6 +34,15 @@ #define RL_HOLD_TARGET_FRAC_INDEX 575 #define RL_HOLD_FRAC_EMA_INDEX 576 #define RL_CONF_GATE_MAX_HOLD_FRAC_INDEX 584 +// Phase 7b F5 (2026-06-05) Option A — interop with state-conditional +// action availability mask. When F5 master gate (slot 823) is engaged +// AND position is flat, F5 has DELIBERATELY forced the agent into an +// opening action by masking Hold (and other invalid actions) in +// pi_logits. Overriding that back to Hold here neutralizes F5's +// surfer→trend choice-set forcing and prevents F5-G1 from achieving +// `hold_frac_flat == 0`. The suppression is gated on F5-engaged AND +// flat — in-position safety overrides are preserved verbatim. +#define RL_F5_STATE_MASK_ENABLED_INDEX 823 #define THRESHOLD_MIN 0.05f #define THRESHOLD_MAX 0.95f #define HOLD_EMA_ALPHA 0.1f @@ -118,7 +127,14 @@ extern "C" __global__ void rl_confidence_gate( const float lcb = (mu - v_min) - lambda * sigma; const float conf = fmaxf(0.0f, fminf(lcb / span, 1.0f)); - if (conf < threshold) { + // Phase 7b F5 (2026-06-05) Option A — suppress Hold override when + // F5 is engaged and we are flat. F5 has masked Hold (and other + // invalid actions) in pi_logits, so the sampled action is a + // deliberate F5-allowed opening. The early-return at line above + // (`position_lots != 0 → return`) already restricts us to flat + // here, so checking only the F5 master gate is sufficient. + const bool f5_engaged = (isv[RL_F5_STATE_MASK_ENABLED_INDEX] > 0.5f); + if (conf < threshold && !f5_engaged) { actions[b] = ACTION_HOLD; isv[RL_CONF_GATE_FIRED_COUNT_INDEX] += 1.0f; } diff --git a/crates/ml-alpha/cuda/rl_frd_gate.cu b/crates/ml-alpha/cuda/rl_frd_gate.cu index bb18c8b3e..a7d378cdc 100644 --- a/crates/ml-alpha/cuda/rl_frd_gate.cu +++ b/crates/ml-alpha/cuda/rl_frd_gate.cu @@ -35,6 +35,15 @@ #define RL_FRD_GATE_FIRED_COUNT_INDEX 518 #define RL_GATE_WARMUP_STEPS_INDEX 524 #define RL_STEP_COUNTER_ISV_INDEX 548 +// Phase 7b F5 (2026-06-05) Option A — interop with state-conditional +// action availability mask. When F5 master gate (slot 823) is engaged +// AND position is flat, F5 has DELIBERATELY forced the agent into an +// opening action by masking Hold (and other invalid actions) in +// pi_logits. Overriding that back to Hold here neutralizes F5's +// surfer→trend choice-set forcing and prevents F5-G1 from achieving +// `hold_frac_flat == 0`. The suppression is gated on F5-engaged AND +// flat — in-position safety overrides are preserved verbatim. +#define RL_F5_STATE_MASK_ENABLED_INDEX 823 extern "C" __global__ void rl_frd_gate( int* __restrict__ actions, // [B] IN/OUT @@ -60,6 +69,15 @@ extern "C" __global__ void rl_frd_gate( const int position_lots = *(const int*)(pos_state + b * pos_bytes); if (position_lots != 0) return; + // Phase 7b F5 (2026-06-05) Option A — short-circuit before quality + // computation when F5 is engaged and we are flat. F5 has masked + // Hold in pi_logits so the sampled opening is deliberate; overriding + // here would neutralize F5-G1 (`hold_frac_flat == 0` from flat). + // The early `position_lots != 0 → return` above already restricts + // us to flat, so checking the F5 master gate alone is sufficient. + const bool f5_engaged = (isv[RL_F5_STATE_MASK_ENABLED_INDEX] > 0.5f); + if (f5_engaged) return; + // Horizon 2 logits for this batch. const float* h2 = frd_logits + b * (FRD_N_HORIZONS * FRD_N_ATOMS) + FRD_H2_OFFSET;