# CRT.train Intervention B — Multi-Timescale EMA Readout (Design v5)

**Date:** 2026-05-21 (v5 — addresses all concerns from v4 review)
**Branch context:** `ml-alpha-phase-a` (HEAD `6d65423e3`)
**Predecessor specs:**
- `2026-05-20-crt-train-output-smoothness-design.md` (intervention A)
- `2026-05-21-crt-train-isv-driven-lambda-controller.md` (controller refinement)
**Predecessor pearl:** [pearl_training_smoothness_does_not_transfer_to_inference](memory/pearl_training_smoothness_does_not_transfer_to_inference.md)
**Status:** v5 — pending review

---

## v5 changelog from v4

| Concern | v4 | v5 fix |
|---|---|---|
| **A** Inference path changes unspecified | Mentioned only in passing | **NEW §4: Inference path design** — `forward_step_into` MTER launch, per-instance h_view state lifecycle, LOB backtest harness integration |
| **B** Multiple golden tests need regeneration, not just heads_bit_equiv | Only `heads_bit_equiv.rs` mentioned | §6.4 enumerates ALL affected golden tests: `heads_bit_equiv.rs`, `forward_step_golden.rs`, `perception_forward_golden.rs`, `forward_graph_capture.rs` |
| **C** Val warmup bias mitigation undecided | Two options listed | **Decided**: post-warmup AUC measurement in val loop. AUC accumulator only counts samples after `events_since_val_start ≥ τ_max`. Cheaper than 5×ing val. |
| **D** Smoothness slot orphaning in gpu_log_ids.h | Not addressed | **Decided**: reclaim slot 0 for `KID_MTER_READOUT`. `KID_SMOOTHNESS_CONTROLLER` removed entirely. Decoders renamed. Other kernel IDs shift down by 1. |
| **E** Commit-1 smoke validation implicit | Not explicit | **§5.4 commit 1 explicitly requires** sequential-vs-random smoke before commit 2 proceeds. Embedded pre-validation. |
| **F** Heads kernel LOC underestimated (250) | +250/-80 | **Bumped to +350-400/-100**. Honest. |
| **G** Multi-fold trainer reuse silent-bug risk | Not addressed | **Added `reset_for_new_fold()` method** + explicit assert in trainer construction that fold transitions reset state. |
| **H** 75-min wall estimate too high | "~75 min" | **Corrected to ~36 min**: 5 build + 18 train + 13 CRT.diag |
| **Minor** Val cfc_h_state attn_pool bootstrap unclear | Not addressed | §4.5 explicit: val_cfc_h_state bootstrapped via attn_pool on val-start, just as a file-boundary bootstrap |

---

## 1. Motivation (unchanged)

Intervention A's smoothness regularizer differentiated horizons at training time (jitter ratio 0.40) but failed inference WIN gate by ~25× (mean_run_len 3.9 vs target ≥100). Per `pearl_training_smoothness_does_not_transfer_to_inference`: position-wise penalty on training `[K, B, 5]` shapes weights only relative to the training geometry; inference's event-by-event `forward_step_into` doesn't inherit the constraint.

## 2. Hypothesis

The trunk already amplifies short-horizon evidence into multi-minute predictions. The bottleneck is the readout stage + the training/inference geometry mismatch. Three structural changes ship together:

1. **Per-horizon EMA readout (MTER)** between trunk and heads, with τ[h] = K_h
2. **Stateful CfC trunk** — drop attn_pool reset at sequence boundaries; use only at file-boundary bootstrap
3. **Stateful MTER** — h_view state persists across sequences AND epochs; reset only at trainer construction + file boundary

Training and inference exercise the SAME continuous trunk_h trajectory through the SAME EMA dynamics.

## 3. Training architecture

### 3.1 Forward (per-event/per-position)

```
α[h] = 1 / τ[h]                        # frozen τ by default
h_view[b, h, :] = (1 - α[h]) · h_view_prev[b, h, :] + α[h] · trunk_h[b, :]
```

τ_init = K_h = `[30, 100, 300, 1000, 6000]`. Frozen by default; `--mter-tau-mode learnable` available as opt-in ablation.

### 3.2 Concatenated head input

Each head reads `[h_view[b, h, :128], trunk_h[b, :128]]` (256-d).

### 3.3 Stateful CfC trunk

CfC `h_old` carries across sequence boundaries within a file. attn_pool used only at file-boundary bootstrap. BPTT remains K-truncated.

### 3.4 Stateful MTER

`h_view` persists across K-loop iterations, sequence boundaries, AND epoch boundaries. Reset only at trainer construction + file boundary. Warmup cost: ~0.2% of total training (single τ_max=6000 bootstrap per session) + ~1.6% across 8 file boundaries = ~1.8% total.

### 3.5 Validation loop state isolation

Separate `val_h_view_state_d`, `val_cfc_h_state_d` buffers. At val-start:
- `val_cfc_h_state := attn_pool(val_file_positions_0..K-1)` (treated as a file-boundary bootstrap)
- `val_h_view_state := sentinel-bootstrap on first observation`

Val data walked sequentially. AUC accumulator only counts samples after `events_since_val_start ≥ τ_max` (= 6000 events ≈ 188 sequences). Below that threshold, samples contribute to the forward pass but NOT to AUC.

For val_n_seqs=1000: ~812 sequences contribute to AUC, ~188 are warmup. AUC reflects the equilibrium-distribution measurement.

### 3.6 B = 1 enforcement

Trainer construction errors if `cfg.n_batch != 1`. Multi-batch sequential training is out of scope for v5.

### 3.7 Loader mode

`LoaderMode::Sequential` for MTER training + validation. `Random` preserved for legacy use and the fallback path (per §11).

### 3.8 Multi-fold trainer state

New method `PerceptionTrainer::reset_for_new_fold()`:
- Re-sentinel-bootstraps all stateful buffers (h_view, cfc_h_state, val_*)
- Sets first_obs := 0 across the board
- Re-initializes any cumulative counters

Called by external multi-fold orchestrators. v5 first cut assumes one trainer per Argo run (one fold per trainer); the method exists to support future multi-fold workflows without silent state-leakage bugs.

### 3.9 Heads kernel signature

`multi_horizon_heads_grn_fwd_batched` input:
- Old: `h [B, HIDDEN_DIM=128]`
- New: `h_view [B, N_HORIZONS, HIDDEN_DIM]` + `trunk_h [B, HIDDEN_DIM]`

Per-horizon weights `w1 [N_HORIZONS, HEAD_MID=64, HIDDEN_DIM*2=256]`, `w_skip [N_HORIZONS, HIDDEN_DIM*2]`. Other weights unchanged.

`multi_horizon_heads_grn_bwd_batched`:
- Output old: `grad_h [B, HIDDEN_DIM]` (summed across horizons)
- Output new: `grad_h_view [B, N_HORIZONS, HIDDEN_DIM]` (per-horizon) + `grad_trunk_h_from_skip [B, HIDDEN_DIM]` (summed across horizons from trunk_h half of concat input)

Substantial rewrite of forward Pass 1, Pass 3 + backward Pass 5, Pass 6. Bit-equiv goldens regenerate.

### 3.10 τ_raw update

Frozen mode (default): τ_raw set once at construction, never updated.

Learnable mode: dedicated `mter_tau_update.cu` kernel (5 floats, gradient descent with simple optimizer state) runs OUTSIDE captured graph after each training step. Not integrated into the existing AdamW kernel.

## 4. Inference path design (NEW IN V5 — addresses concern A)

The inference path (`forward_step_into` per-event) needs symmetric MTER + stateful CfC handling so the heads see the same input distribution they trained on.

### 4.1 `forward_step_into` MTER integration

Sequence of operations per event in the captured inference graph:
```
1. snap_feature_assemble_batched           (existing)
2. VSN (variable selection)                (existing)
3. Mamba2 stack 1 step_into                (existing)
4. LN_a step                                (existing)
5. Mamba2 stack 2 step_into                (existing)
6. LN_b step                                (existing)
7. CfC step (h_old from cfc_h_state_step_d) (existing — stateful by default in inference)
8. **MTER forward (NEW)** — read trunk_h (= cfc h_new), update h_view_state_step_d,
   write h_view_step_out
9. heads_grn_fwd_batched (NEW INPUT SHAPE) — reads
   concat(h_view_step_out[h], trunk_h) for each horizon
```

### 4.2 Inference-side state buffers

Add to `PerceptionTrainer` (or whichever struct owns inference):
- `h_view_state_step_d: CudaSlice<f32>` — `[1, N_HORIZONS, HIDDEN_DIM]` per-instance MTER state, persistent across events within a session
- `h_view_first_obs_step_d: CudaSlice<i32>` — `[1, N_HORIZONS]` sentinel
- New `forward_step_into_with_log_ring` variant unchanged from the existing `forward_step_into` except for the new MTER kernel invocation

State lifecycle:
- Bootstrap: at trainer construction (or first call to forward_step_into after a session reset).
- Updated each event by the MTER kernel inside the captured graph.
- Reset method: `reset_inference_state()` re-sentinels h_view_first_obs_step + re-bootstraps cfc_h_state_step. Called by external orchestrators between independent sessions.

### 4.3 LOB backtest harness integration

The CRT.diag harness (`lob-backtest-sweep` workflow → `fxt-backtest` binary or similar) loads a `PerceptionTrainer` checkpoint and walks events one at a time via `forward_step_into`. Required harness changes:

- Allocate the new inference-side state buffers at startup (same lifecycle as `cfc_h_state_step_d`).
- Bootstrap h_view sentinel on first event.
- The h_view state is naturally per-instance (one ring per `LobSimCuda` instance), parallel to `cfc_h_state_step_d`.

The existing `LobSimCuda::alpha_probs_d_mut` mapped-pinned output buffer is unchanged. MTER adds upstream state but doesn't change the output contract.

If the harness has its own kernel-launch sequence (not via `PerceptionTrainer::forward_step_into`), it needs the MTER launch inserted between CfC and heads — search for "heads_grn_fwd" in the harness codepath and add MTER one launch upstream.

### 4.4 Symmetry verification

The training-time `step_batched` and inference-time `forward_step_into` must produce numerically identical h_view + heads-input given identical inputs. New `tests/forward_step_mter_symmetry.rs`:
- Run K=32 training step with all-deterministic inputs → record h_view_state + heads_input at k=K-1
- Run K=32 individual `forward_step_into` calls with identical state setup → record h_view + heads_input at each step
- Verify step-by-step equivalence within 1e-5

This is the equivalent of the existing `forward_step_golden.rs` but for the new MTER+heads geometry. Catches integration regressions cheaply.

## 5. Mathematical contract

**Forward at (b, h), frozen mode:**
```
If first_obs[b, h] == 0:
    h_view[b, h, :] := trunk_h[b, :]
    first_obs[b, h] := 1
Else:
    h_view[b, h, :] := (1 - 1/τ[h]) · h_view_prev[b, h, :] + (1/τ[h]) · trunk_h[b, :]
```

**Heads input:** `concat(h_view[b, h, :], trunk_h[b, :])` ∈ ℝ²⁵⁶.

**Backward at (b, h):**
```
d_trunk_h[b, :] += (1/τ[h]) · d_h_view[b, h, :]              # from MTER EMA path
d_trunk_h[b, :] += d_trunk_h_from_skip[b, :]                 # from heads' skip-concat path (already summed)
d_h_view_carry[b, h, :] = (1 - 1/τ[h]) · d_h_view[b, h, :]   # to previous step's h_view
```

**Theoretical bound (NOT empirical claim):** under white-noise trunk_h, h_view[h]'s variance scales as 1/(2τ[h]−1). Under colored trunk_h, actual reduction is looser. JSONL trace records actual.

## 6. Implementation surface

### 6.1 NEW files

| File | Description | LOC est. |
|---|---|---|
| `crates/ml-alpha/cuda/mter_readout.cu` | MTER forward + backward kernels | ~300 |
| `crates/ml-alpha/cuda/mter_tau_update.cu` | Tiny optimizer kernel for τ_raw (learnable mode only) | ~80 |
| `crates/ml-alpha/tests/mter_invariants.rs` | 7 invariant tests (see §8.1) | ~300 |
| `crates/ml-alpha/tests/forward_step_mter_symmetry.rs` | Training-vs-inference numerical symmetry (§4.4) | ~200 |

### 6.2 MODIFIED files

| File | Action | LOC est. |
|---|---|---|
| `crates/ml-alpha/cuda/multi_horizon_heads.cu` | Heads kernels accept per-horizon concat input. Forward Pass 1/3 loop bounds, backward Pass 5/6 grad split + accumulation. Substantial rewrite. | **+350-400 / -100 (delta)** |
| `crates/ml-alpha/cuda/gpu_log_ids.h` | `KID_SMOOTHNESS_CONTROLLER` removed; slot 0 reclaimed by `KID_MTER_READOUT`; other KIDs shift down by 1 (KID_OUTPUT_SMOOTHNESS unused → also removed) | ~10 |
| `crates/ml-alpha/build.rs` | Register `mter_readout`, `mter_tau_update`; deregister `output_smoothness`, `smoothness_lambda_controller`; bump cache-bust v14 → v15 | ~10 |
| `crates/ml-alpha/src/heads.rs` | `TAU_INIT_PER_HORIZON`, `HEAD_INPUT_DIM = 2 * HIDDEN_DIM`, `MTerTauMode` enum; remove `SMOOTHNESS_LAMBDA_RATIO` | ~30 / -15 |
| `crates/ml-alpha/src/trainer/perception.rs` | (a) New fields: `h_view_state_d`, `h_view_first_obs_d`, `tau_raw_d`, `grad_h_view_carry_d`, `val_h_view_state_d`, `val_h_view_first_obs_d`, `val_cfc_h_state_d`. (b) Inference-side fields: `h_view_state_step_d`, `h_view_first_obs_step_d`. (c) `reset_for_new_fold()` method. (d) `reset_inference_state()` method. (e) Constructor allocates + bootstraps. (f) Stateful CfC h_old carry (drop attn_pool reset at sequence boundaries). (g) `step_batched`: MTER fwd between CfC and heads; MTER bwd between heads_grn_bwd and CfC bwd. h_view persists across sequences + epochs. Validation uses separate state with post-warmup AUC accumulator. B=1 enforcement. (h) `forward_step_into`: MTER kernel launch added between CfC step and heads launch; h_view_state_step buffers updated each event. (i) New kernel-step-trace records for `KID_MTER_READOUT`. (j) Remove smoothness wiring (kernel handles, launch calls, telemetry buffers, accessor) | +400 / -250 |
| `crates/ml-alpha/src/data/loader.rs` | `LoaderMode::Sequential` variant; sequential cursor advancement; `is_file_boundary()` method; `next_val_sequence()` sequential variant | ~150 |
| `crates/ml-alpha/src/gpu_log.rs` | Replace smoothness decoders with MTER decoders (RT_INPUT/STATE/OUTPUT) | ~30 / -50 |
| `crates/ml-alpha/examples/alpha_train.rs` | New flags: `--loader-mode {random|sequential}` (default sequential), `--mter-tau-mode {frozen|learnable}` (default frozen), `--mter-tau-init <comma-floats>` (optional). Drop `--smoothness-base-lambda`. Drop `final_smooth_loss_per_horizon` summary; replace with `final_h_view_norm_per_horizon` (telemetry from JSONL → summary aggregate). | +40 / -15 |
| `infra/k8s/argo/alpha-perception-template.yaml` | New workflow params: `loader-mode`, `mter-tau-mode`, `mter-tau-init`. Drop `smoothness-base-lambda`. | +20 / -10 |

### 6.3 DELETED files (in the same commit chain)

| File | Reason |
|---|---|
| `crates/ml-alpha/cuda/output_smoothness.cu` | Superseded by MTER |
| `crates/ml-alpha/cuda/smoothness_lambda_controller.cu` | Superseded by MTER |
| `crates/ml-alpha/tests/smoothness_lambda_controller_invariants.rs` | Tests for deleted kernel |
| `crates/ml-alpha/tests/output_smoothness_grad_finite_diff.rs` | Tests for deleted kernel |

### 6.4 REGENERATED test goldens

All four golden-value tests need regeneration because both heads kernel signature AND inference path change:

| Test | What regenerates |
|---|---|
| `tests/heads_bit_equiv.rs` | Heads kernel output goldens (new input shape `[B, N_HORIZONS, HIDDEN_DIM]` + `trunk_h`) |
| `tests/forward_step_golden.rs` | Inference path's per-event output (MTER kernel now part of the chain) |
| `tests/perception_forward_golden.rs` | Full training forward goldens (MTER + new heads + stateful CfC) |
| `tests/forward_graph_capture.rs` | CUDA Graph captured-inference goldens (same as forward_step_golden but graph-captured) |

The bit-equiv tests are REGRESSION GATES, not correctness gates. After kernel rewrites, capture new goldens from a reference run + commit them. Each golden file ~1-10 KB.

### 6.5 Total scope

- New: ~880 LOC (kernels + tests + symmetry test)
- Modified: ~660 LOC delta
- Deleted: ~150 LOC
- Test goldens regenerated: 4 files
- **Net: ~1390 LOC** (+200 over v4 due to inference path + symmetry test)

Estimated dev time: 2-3 days. One L40S retrain cycle for validation.

## 7. Commit boundaries (phased — addresses concern E)

8 commits, each buildable + testable:

1. **Loader**: `LoaderMode::Sequential` + file-boundary detection + sequential val support. **Required smoke after this commit**: run a no-MTER training with `--loader-mode sequential` and verify trunk converges to within `random_baseline_AUC[h] − 0.02` per horizon (12 epochs, ~20 min L40S). If regression observed: STOP — MTER plan blocks. (~150 LOC)
2. **MTER forward kernel** + Rust wiring + invariant tests 1-3. (~600 LOC)
3. **Heads kernel forward reshape** + heads_bit_equiv.rs golden regenerate. (~200 LOC + golden file)
4. **MTER backward kernel** + Rust wiring + invariant tests 4-7. (~450 LOC)
5. **Heads kernel backward reshape** + MTER backward integration. (~250 LOC)
6. **Stateful CfC trunk** + stateful MTER state across sequences/epochs + val state isolation + B=1 enforcement + post-warmup AUC accumulator. (~300 LOC)
7. **Inference path** (forward_step_into MTER integration) + LOB backtest harness integration + `forward_step_mter_symmetry.rs` + golden regenerations for `forward_step_golden.rs`, `perception_forward_golden.rs`, `forward_graph_capture.rs`. (~250 LOC + 3 golden files)
8. **Smoothness machinery deletion** + CLI/Argo template plumbing + `gpu_log_ids.h` reclaim of slot 0 + decoder rename. (~100 LOC + ~150 LOC deletion)

Each commit ships independently testable code. Commit 8 finalizes the architecture.

## 8. Memory rules + horizon_lambda interaction

### 8.1 Memory rules (unchanged from v4)

All preserved. `feedback_no_atomicadd`, `feedback_no_htod_htoh_only_mapped_pinned`, `feedback_no_nvrtc`, `pearl_no_host_branches_in_captured_graph`, `pearl_cudarc_disable_event_tracking_for_graph_capture`, `pearl_first_observation_bootstrap`, `pearl_blend_formulas_must_have_permanent_floor`, `feedback_no_partial_refactor` (atomic per commit), `feedback_wire_everything_up`, `feedback_single_source_of_truth_no_duplicates`, `feedback_no_feature_flags` (no Cargo features; runtime CLI mode flags only), `feedback_no_quickfixes` (structural), `feedback_no_functionality_removal` (smoothness removed because superseded; rollback via git revert).

### 8.2 horizon_lambda interaction

λ[h] applied in heads_grn_bwd BEFORE the split into d_h_view and d_trunk_h_from_skip. Both downstream paths inherit λ[h] scaling. Controller's stability range [0.5, 2.0] preserved. Invariant test #5 verifies.

## 9. Validation gates

### 9.1 Pre-MTER trunk validation (embedded in commit 1)

After commit 1 (loader change), smoke a no-MTER 12-epoch run with `--loader-mode sequential`. **Gate**: per-horizon val AUC within `random_baseline_AUC[h] − 0.02`. If pass, MTER proceeds (commits 2-8). If fail, MTER blocked.

### 9.2 Local invariant tests (`mter_invariants.rs` + `forward_step_mter_symmetry.rs`)

1. **Sentinel bootstrap** — first_obs=0 + arbitrary trunk_h → h_view := trunk_h exactly.
2. **EMA equilibrium** — constant trunk_h for 10τ steps → h_view ≈ trunk_h within 1e-3.
3. **Per-horizon timescale separation** — step-change in trunk_h; settling-time ratio (h6000:h30) ≈ τ ratio within 20%.
4. **Backward finite-diff** — analytic d_trunk_h, d_h_view_carry match FD within 5e-3.
5. **horizon_lambda × MTER** — λ=[1,1,1,1,2]; d_trunk_h via h6000 path is exactly 2× the unweighted case.
6. **Stateful training across sequences** — h_view at step 6000 ≈ true 6000-event EMA within 1e-2.
7. **CfC stateful across sequences** — sequence-boundary h_old = previous h_new at k=K-1; attn_pool used only at file boundaries.
8. **Training/inference symmetry** (separate file) — `step_batched` and `forward_step_into` produce numerically identical h_view + heads_input within 1e-5.

### 9.3 MTER training MUST gate

- Per-horizon val AUC within `lnfwd_baseline_AUC[h] − 0.02` (baseline h6000 = 0.7157).
- No NaN/divergence within 12 epochs.

Implicitly tests stateful CfC training; if MUST passes, trunk training is acceptable.

### 9.4 MTER training WIN gate (intermediate)

Theoretical bound: under colored trunk noise, training-time h6000_jitter / h30_jitter ∈ [0.05, 0.4]. Real differentiation = inside this range.

### 9.5 Inference WIN gate (THE gate)

- **MUST**: h6000 mean_run_len ≥ 100 events.
- **MUST**: h6000/h30 mean_run_len ratio ≥ 10×.
- **STRETCH**: CRT.1 controller smoke shows mean PnL monotonically rises with conviction OR (win_rate rises AND mean_pnl at highest-conviction bucket > -10).

By construction (τ[h6000] = 6000-event integration + stateful training matches inference distribution), h6000's per-event output should change on the order of 100s of events. WIN target should be achievable.

## 10. Risks

| Risk | Severity | Mitigation |
|---|---|---|
| Commit-1 sequential-sampling smoke fails (trunk regresses) | **High** | MTER plan blocks. Diagnose: trunk's training dynamics specifically depend on random sampling. Alternative: per-horizon CfC branches with random sampling (Option 1 from earlier reviews). Documented as explicit fork. |
| MTER kernel orchestration more complex than estimated | Medium | Phased 8-commit implementation in §7 limits any broken state to one commit. |
| Heads kernel rewrite breaks bit-equiv goldens | High (planned) | Golden values regenerated at commit 3 + 7. Tests are regression gates, not correctness gates. |
| Inference path integration with LOB backtest harness | Medium | `forward_step_mter_symmetry.rs` (test #8) catches numerical drift between training and inference. Harness integration tested in commit 7. |
| File-boundary attn_pool bootstrap creates regime-mismatched h_view warmup | Low | ~1.6% of total training. h_view's slow horizons filter out the discontinuity. |
| Smoothness deletion makes rollback non-trivial | Medium | `git revert <MTER-commit-chain>` is rollback. Diagnostic JSONL from prior runs preserved on MinIO. Phased commits enable partial rollback. |
| Val state warmup bias on AUC measurement | Low | Post-warmup AUC accumulator (samples only count after `events_since_val_start ≥ τ_max`). Trivial change. |
| Multi-fold trainer reuse causes state leakage | Low | `reset_for_new_fold()` method added explicitly. Current Argo workflow is one-fold-per-trainer; method is for future workflows. |
| Frozen τ is suboptimal vs learnable | Low | Default frozen for safety. Learnable available via `--mter-tau-mode learnable` as opt-in post-WIN ablation. |
| 12-epoch L40S retrain wall | Negligible | ~36 min total (5 build + 18 train + 13 CRT.diag) for the validation cycle. |

## 11. Open questions

1. Drop attn_pool entirely (use zero-init at file boundaries)? Preserve for now.
2. ISV-driven τ controller for learnable mode. Defer until learnable τ proven insufficient.
3. Per-dimension τ vectors. Defer.
4. B > 1 sequential training. Out of scope.
5. Val sequence count tuning. Default `n_val_seqs=1000` + post-warmup AUC accumulator. May need ↑ if h6000 AUC measurement is too noisy.

## 12. Out of scope

- Per-dimension τ vectors
- Cross-horizon attention at readout
- ISV-driven τ controller
- B > 1 sequential training
- Dropping attn_pool entirely

## 13. Predecessor and successor

**Predecessor:**
- `pearl_training_smoothness_does_not_transfer_to_inference`
- `pearl_state_amplifies_short_horizon_into_long_horizon`
- `pearl_separate_aux_trunk_when_shared_starves`

**Successor (if commit-1 smoke fails):**
- MTER shelved. Alternative path: per-horizon CfC branches with random sampling. Bigger architectural change. Write separate spec.

**Successor (if MTER training MUST + WIN pass):**
- No follow-on; this IS the architecture.
- Ablation candidates: learnable τ, ISV-driven τ.
- Resume CRT.1 controller on differentiated h_view outputs.

**Successor (if training passes but inference WIN fails):**
- JSONL trace localizes: τ collapse (learnable mode), h_view non-equilibration, model over-reliance on trunk_h skip-path, stateful CfC training degeneracy.
- Likely path: zero-init the trunk_h half of heads' w1 (force heads to use h_view primarily).
- Fallback: redefine inference WIN gate from mean_run_len to conviction × outcome.

---

**End of CRT.train Intervention B v5 design. Awaiting review.**
