diff --git a/docs/superpowers/specs/2026-04-16-introspective-state-vector-design.md b/docs/superpowers/specs/2026-04-16-introspective-state-vector-design.md index 45d6c6817..6fb3dd813 100644 --- a/docs/superpowers/specs/2026-04-16-introspective-state-vector-design.md +++ b/docs/superpowers/specs/2026-04-16-introspective-state-vector-design.md @@ -809,6 +809,175 @@ Note: This requires passing `states_buf` pointer and `state_dim` to the kernel. --- +## Phase 3: Dynamic Inference Brain — Feature Gating + Temporal Routing + +Phases 1-2 give the model self-awareness (ISV) and market awareness (regime signals). Phase 3 uses the ISV embedding to dynamically modulate **what the model attends to** and **how much history it uses** — creating a model whose computational behavior adapts at inference without weight updates. + +### The Complete Adaptive Pathway + +At inference, without any gradient updates, the model dynamically adjusts 7 pathways: + +``` + ISV Embedding [8] + │ + ┌───────┬───────┼───────┬───────┬──────────┬──────────┐ + │ │ │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ ▼ ▼ + Feature Temporal Branch Gamma Risk Mamba2 Branch + Gating Routing Gating Mod Budget Decay Confidence + │ │ │ │ │ │ │ + WHICH HOW WHICH HOW HOW HOW HOW +features much branches FAR MUCH MUCH CERTAIN + matter history matter plan risk memory each + to use ahead to take to keep branch is +``` + +**Critical insight:** At inference, training dynamics signals (grad_norm, td_error, loss) freeze at their last training EMA values. But market signals (regime_velocity, regime_disagreement, Q-drift, ensemble_var) are LIVE — they're computed from the current market state. So the model adapts to unseen regimes through the live signals while retaining training-learned behavior through the frozen signals. + +### PEARL: Feature-Level ISV Gating (P6) + +The ISV embedding modulates WHICH features in h_s2 the branches should attend to. A single projection produces a per-feature gate: + +``` +feature_gate [SH2] = sigmoid(w_feature_gate @ isv_embedding + b_feature_gate) +h_s2_gated = h_s2 * feature_gate // element-wise +``` + +Applied AFTER Mamba2 enrichment, BEFORE branch heads. During trends, momentum features (OFI signals) get amplified. During mean-reversion, depth imbalance features get amplified. The model learns the mapping. + +This piggybacks on the existing Variable Selection Network (VSN, indices 26-33) which already does per-branch feature selection. ISV feature gating acts as a **pre-VSN filter** — it modulates which features reach the VSN at all. + +```cuda +extern "C" __global__ void isv_feature_gate( + float* __restrict__ h_s2, /* [B, SH2] in-place */ + const float* __restrict__ isv_embedding, /* [8] shared */ + const float* __restrict__ w_feature_gate, /* [SH2, 8] */ + const float* __restrict__ b_feature_gate, /* [SH2] */ + int B, int SH2 +) { + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= B) return; + + for (int j = 0; j < SH2; j++) { + float gate_val = b_feature_gate[j]; + for (int k = 0; k < 8; k++) + gate_val += w_feature_gate[(long long)j * 8 + k] * isv_embedding[k]; + float gate = 1.0f / (1.0f + expf(-gate_val)); + h_s2[(long long)i * SH2 + j] *= gate; + } +} +``` + +**Init:** b_feature_gate = 2.0 (sigmoid(2)≈0.88 — near pass-through at start). The model only deviates when it helps. No feature is aggressively gated initially. + +### GEM: Per-Feature Temporal Routing (G6) + +Different features need different amounts of history. Momentum (OFI) is autocorrelated in trends but noise in ranges. Mean-reversion signals are the opposite. The ISV embedding controls how much Mamba2 temporal context each feature gets: + +``` +temporal_weight [SH2] = sigmoid(w_temporal_route @ isv_embedding + b_temporal_route) +h_enriched[j] = h_s2[j] + temporal_weight[j] * temporal_context[j] +``` + +This replaces the current fixed residual `h_enriched = h_s2 + temporal_context` in `mamba2_temporal_scan` with a per-feature weighted residual. Some features get full temporal enrichment, others get none — controlled by ISV. + +Implementation: modify `mamba2_temporal_scan` to accept `temporal_weight [SH2]` buffer. The final line (59) changes: + +```cuda + /* Current: */ + out[j] = h_current[j] + ctx; + + /* With temporal routing: */ + out[j] = h_current[j] + temporal_weight[j] * ctx; +``` + +Where `temporal_weight` is pre-computed by a separate `isv_temporal_route` kernel: + +```cuda +extern "C" __global__ void isv_temporal_route( + const float* __restrict__ isv_embedding, /* [8] shared */ + const float* __restrict__ w_temporal_route, /* [SH2, 8] */ + const float* __restrict__ b_temporal_route, /* [SH2] */ + float* __restrict__ temporal_weight, /* [SH2] output */ + int SH2 +) { + if (threadIdx.x != 0) return; + for (int j = 0; j < SH2; j++) { + float val = b_temporal_route[j]; + for (int k = 0; k < 8; k++) + val += w_temporal_route[(long long)j * 8 + k] * isv_embedding[k]; + temporal_weight[j] = 1.0f / (1.0f + expf(-val)); + } +} +``` + +**Init:** b_temporal_route = 2.0 (≈0.88 — mostly use temporal context at start, learn to suppress when appropriate). + +### NOVEL: Dynamic Inference Adaptation to Unseen Data (N8) + +The combination of all pathways creates a model that handles unseen market conditions through a principled cascade: + +1. **Unseen regime appears** → regime_velocity spikes, regime_stability drops +2. **Mamba2 decay shortens** (N6) → model forgets old-regime patterns within 2-3 bars +3. **Feature gate shifts** (P6) → model amplifies features relevant to the new dynamics +4. **Temporal routing changes** (G6) → momentum features lose history weight, stable features keep it +5. **Branch gating shifts** → branches re-weight based on ISV's response to new signals +6. **Gamma shortens** → model focuses on near-term (doesn't extrapolate stale Q-values) +7. **Risk budget drops** → position size reduces until the model "understands" the new regime + +All 7 steps happen within 2-3 bars of the regime change, without any weight updates. The model's INFERENCE BEHAVIOR adapts in real-time. This is the "dynamic brain" — not just a policy network but a **self-modifying inference system**. + +### NOVEL: Inference Cold Start Graceful Degradation (N9) + +At inference start, ISV history is empty (all zeros). The model gracefully handles this: +- Feature gate: sigmoid(b=2.0) ≈ 0.88 → near pass-through (no gating) +- Temporal routing: sigmoid(b=2.0) ≈ 0.88 → full temporal context +- Branch gate: softmax(0,0,0,0) = [0.25, 0.25, 0.25, 0.25] → uniform +- Gamma mod: 0.5 + 0.5*sigmoid(0) = 0.75 → slightly conservative horizon +- Risk budget: neutral ISV → moderate risk + +Within 4-8 bars, ISV accumulates enough signal to start meaningful adaptation. The cold-start behavior is conservative-by-default — the model doesn't take large positions until it has enough self-awareness to justify them. This is the correct behavior for a trading system encountering new data. + +### Phase 3 Weight Tensors + +NUM_WEIGHT_TENSORS: 78 → 82 (4 new tensors). + +| Index | Name | Shape | Purpose | +|-------|------|-------|---------| +| 78 | `w_feature_gate` | [SH2, 8] | ISV → per-feature amplitude gate | +| 79 | `b_feature_gate` | [SH2] | Feature gate bias (init=2.0) | +| 80 | `w_temporal_route` | [SH2, 8] | ISV → per-feature temporal depth | +| 81 | `b_temporal_route` | [SH2] | Temporal route bias (init=2.0) | + +With SH2=256: 2048 + 256 + 2048 + 256 = **4608 new params**. + +### Phase 3 Forward Pass + +``` +1. trunk forward (cuBLAS) → h_s2 [B, SH2] +2. isv_temporal_route() → temporal_weight [SH2] +3. mamba2_temporal_scan(temporal_weight) → h_enriched [B, SH2] (weighted residual) +4. isv_forward() → embedding, gate, gamma_mod +5. isv_feature_gate() → h_s2_gated [B, SH2] (applied to h_enriched) +6. recursive_confidence_forward() → predicted_error [B] +7. fill_gamma_buf() → gamma_buf [B] +8. risk_budget_forward() → risk_budget [B] +9. branch heads (cuBLAS) → Q values +10. branch_confidence_routing() → gated Q +11. apply_risk_budget() → scaled Q +12. action selection +``` + +Steps 2, 5 are new in Phase 3. Step 3 is modified (adds temporal_weight parameter). + +### Implementation Order (Phase 3) + +15. **ISV feature gating** — write `isv_feature_gate` kernel. Add w_feature_gate [SH2,8] + b_feature_gate [SH2] at indices 78-79. Wire after Mamba2, before branch heads. NUM_WEIGHT_TENSORS: 78→82 (add all 4 at once). +16. **Per-feature temporal routing** — write `isv_temporal_route` kernel. Add w_temporal_route [SH2,8] + b_temporal_route [SH2] at indices 80-81. Modify `mamba2_temporal_scan` to accept + use temporal_weight buffer. +17. **Final verification (Phase 3)** — compute-sanitizer 0 errors, smoke test, full suite. + +--- + ## Risks and Mitigations | Risk | Mitigation | @@ -828,3 +997,8 @@ Note: This requires passing `states_buf` pointer and `state_dim` to the kernel. | Regime signals from sample 0 only (not batch mean) | Sample 0 is representative for ADX/CUSUM which are market-level (same for all samples in a time window). For per-sample variation, the regime flows through h_s2 → branches already. | | Regime-conditioned Mamba2 decay changes temporal context | Bounded by regime_stability ∈ [0, 1]. Stable regime: no change. Transition: faster decay (recent bars weighted more). Gradual — never drops to 0. | | Risk branch input grows again SH2+9→SH2+13 | Same atomic update pattern as Phase 1. All offset callers updated together. | +| Feature gate collapse (all 1s or all 0s) | Init b_feature_gate=2.0 → sigmoid≈0.88 (near pass-through). Model only deviates when it helps. | +| Temporal routing interference with Mamba2 | Init b_temporal_route=2.0 → ≈0.88 (mostly use temporal). Soft start, model adjusts gradually. | +| Too many ISV-conditioned pathways → single "ISV mode" | Each pathway has own learned projection (different W matrices). They CAN respond differently to same ISV state. | +| Inference cold start (no ISV history) | All gates initialize to near pass-through. Model starts conservative, adapts in 4-8 bars as ISV accumulates. | +| Phase 3 adds 4608 params → overfitting risk | 4608 / ~580K existing = 0.8%. Feature gate and temporal route are regularized by near-pass-through init. |