# Policy Quality — Phase 0 Baseline Metrics

**Captured against commit:** `0472b9730` (HEAD of `main` at Phase 0 completion; this commit tagged `policy-quality-baseline`)
**Hardware:** RTX 3050 Ti Laptop GPU (local, 4 GB VRAM) — for production-baseline numbers re-run on L40S/H100 per Phase 3
**Data:** `test_data/futures-baseline`, ES.FUT (~176k bars fxcache)
**Smoke-test command template:**
```bash
CARGO_INCREMENTAL=0 SQLX_OFFLINE=true CUBLAS_WORKSPACE_CONFIG=:4096:8 \
  FOXHUNT_TEST_DATA=test_data/futures-baseline \
  cargo test --profile release-test -p ml --lib -- <test_name> --ignored --nocapture
```

> **Status: CAPTURED — all values filled from a clean run on 2026-04-22.**
> All 5 Phase 0 smoke tests PASS. Numbers below are drawn from the epoch-19 HEALTH_DIAG line of a 20-epoch `magnitude_distribution` smoke run plus the per-fold outputs of `multi_fold_convergence` (3 folds × 5 epochs with `dqn-smoketest` profile). "Non-zero" slots reflect the real diagnostic signal; "0.000" slots where the underlying feature is intentionally off in the smoke profile (e.g., PopArt warmup, micro_reward_scale=0) are the honest semantic value, not stubs.

---

## Track 1 — Magnitude

Drawn from `magnitude_distribution.rs` smoke test stdout + `[HEALTH_DIAG]` lines emitted by the trainer.

| Metric | Source | Baseline value (epoch 19) |
|---|---|---|
| `F_Quarter` (tradable-direction mag share) at epoch 20 | `magnitude_distribution` `[MAG_DIST]` | **0.596** |
| `F_Half` at epoch 20 | same | **0.150** (≥ 5% ✓) |
| `F_Full` at epoch 20 | same | **0.255** (≥ 5% ✓) |
| `q_mag_quarter` (mean) | HEALTH_DIAG `mag [q_quarter=…]` | **-0.044** |
| `q_mag_half` | HEALTH_DIAG `mag [q_half=…]` | **-0.046** |
| `q_mag_full` | HEALTH_DIAG `mag [q_full=…]` | **0.050** |
| `var_scale_mean` | HEALTH_DIAG `mag [var_scale=…]` | **0.853** |
| `kelly_f_mean` | HEALTH_DIAG `mag [kelly_f=…]` | **0.000** (degenerate wins/losses at smoke scale) |
| `avg_win_ratio` | HEALTH_DIAG `mag [avg_win_ratio=…]` | **0.000** (degenerate wins/losses) |
| `grad_ratio_mag_dir` | HEALTH_DIAG `mag [grad_ratio_mag_dir=…]` | **0.0000** (mag/dir grad ratio near zero — worth watching in Phase 1) |
| `dist_q` / `dist_h` / `dist_f` (epoch-level mag shares) | HEALTH_DIAG `mag [dist_q=… dist_h=… dist_f=…]` | **0.596 / 0.150 / 0.255** |
| `trail_fire_rate[Q,H,F]` per mag | HEALTH_DIAG `trail [fire_q=… fire_h=… fire_f=…]` | **Q=0.594, H=0.000, F=0.000** (only Quarter-size trades; Half/Full rare in smoke) |
| `hold_at_exit_mean[Q,H,F]` per mag | HEALTH_DIAG `trail [hold_q=… hold_h=… hold_f=…]` | **Q=3.44 bars, H=0.00, F=0.00** |
| `vsn_mag` / `vsn_dir` (VSN proj-weight `|w|` mean) | HEALTH_DIAG `noisy [vsn_mag=… vsn_dir=…]` | **0.010 / 0.010** (surrogate; live mask not materialized) |
| `sigma_mag` / `sigma_dir` (NoisyNets σ) | HEALTH_DIAG `noisy [sigma_mag=… sigma_dir=…]` | **0.0320 / 0.0320** |
| `drift_mag` / `drift_dir` (target weight drift RMS) | HEALTH_DIAG `noisy [drift_mag=… drift_dir=…]` | **0.001 / 0.001** |
| Eval-mode action distribution `eq/eh/ef` | HEALTH_DIAG `eval_dist [eq=… eh=… ef=…]` | **1.000 / 0.000 / 0.000** (eval locks to argmax Quarter — expected with ε=0; Phase 1 investigation target) |

## Track 2 — Reward Contribution

Drawn from `reward_component_audit.rs` smoke output + HEALTH_DIAG `reward_contrib`.

| Slot | Term | Class | Baseline value (epoch 19) |
|---|---|---|---|
| 0 | popart | transform (\|Δvar\| / \|var_pre\|) | **0.000** (PopArt in warmup at smoke scale — semantic, not a stub) |
| 1 | cf | sample-selector (CF flip rate) | **0.586** (cf_ratio=0.67 default, healthy) |
| 2 | trail_r | sample-selector (trail rate) | **0.290** |
| 3 | micro | additive (\|Σ\|micro\|\| / \|Σ\|total\|\|) | **0.000** (micro_reward_scale=0 in smoke profile) |
| 4 | la | additive (\|Σ Δclamp\| / \|Σ total\|) | **0.002** (asymmetric clamp rarely fires) |

(Note: Task 0.8 deleted the legacy `seg` slot — `segment_patience` term is not wired in the kernel, so reserving a slot would have been a stub. Final layout is 5 slots.)

## Track 3 — Controller Firing

Drawn from `controller_activity.rs` smoke output + HEALTH_DIAG `controller`. V7 intervention-based detection (epoch counted as a fire only when a controller actually intervened, not on every sigmoid tick).

| Controller | Firing rate across 20 epochs | Load-bearing (> 50%)? |
|---|---|---|
| anti_lr | **0.000** | no |
| tau | **0.033** | no |
| gamma | **0.017** | no |
| grad_clip | **0.200** | no |
| cql_alpha | **0.033** | no |
| cost_anneal | **0.000** (monotone schedule — excluded from load-bearing test by design) | n/a |

All 6 well under 50%; no controller is load-bearing at smoke scale.

## Track 4 — Exploration

Drawn from `exploration_coverage.rs` smoke output (3-fold entropy history) + HEALTH_DIAG `explore`.

| Metric | epoch 5 | epoch 10 | epoch 15 | epoch 19 |
|---|---|---|---|---|
| `ent_mag` (magnitude-branch normalized entropy) fold 0 | 0.990 | 0.997 | 0.990 | 0.985 |
| `ent_mag` fold 1 | 0.982 | 0.987 | 0.976 | 0.975 |
| `ent_mag` fold 2 | 0.852 | 0.814 | 0.785 | 0.866 |
| `ent_dir` (direction-branch) | — | — | — | **0.90** (final epoch) |
| `sigma_mean` (overall NoisyNets σ) | 0.0320 | 0.0320 | 0.0320 | 0.0320 |

Magnitude entropy healthy across all folds; fold 2 shows modest compression (→ 0.7 mid-training) then recovery — worth tracking as Track 4 investigation signal, not a failure.

---

## Smoke test results

All 5 Phase 0 smoke tests PASS on this commit.

| Test | Result | Wall-clock (RTX 3050 Ti) | Key output |
|---|---|---|---|
| `magnitude_distribution` | ✅ PASS | 20.20s | `[MAG_DIST] Quarter=0.596 Half=0.150 Full=0.255` |
| `reward_component_audit` | ✅ PASS | 20.05s | `[REWARD_AUDIT] popart=0.0000 cf_flip=0.6187 trail=0.2897 micro=0.0000 loss_aversion=0.0125` |
| `controller_activity` | ✅ PASS | 20.06s | `[CTRL_FIRE] anti_lr=0.000 tau=0.033 gamma=0.017 clip=0.200 cql=0.033 cost=0.000` |
| `exploration_coverage` | ✅ PASS | 20.12s | `[EXPLORE] entropy @ep5 = 0.987 @ep20 = 0.985` (60-entry history: 20 × 3 folds) |
| `multi_fold_convergence` | ✅ PASS | 353.60s | 3/3 folds produced checkpoints; Best Sharpe 51.05 / 38.80 / 87.38; `best_val_metric` 0.028 / 0.018 / 0.019 |

## Direction × magnitude action distribution (epoch 19)

Raw `summary.action_counts` (12-bin layout: `dir*3 + mag`, after the Phase 0 monitoring cascade fix at `2fb30f098`):

```
indices: [ S_Q S_H S_F | H_Q H_H H_F | L_Q L_H L_F | F_Q F_H F_F ]
counts : [ 701 169 282 | 364   1   5 | 738 193 333 | 405   5   4 ]
```

Per-direction totals:
- **Short** (dir=0): 1152 (38.7%)
- **Hold**  (dir=1): 370  (12.4%)  — magnitude forced to 0 by kernel; H_H / H_F are residual counting artefacts
- **Long**  (dir=2): 1264 (42.4%)
- **Flat**  (dir=3): 414  (13.9%)  — was invisible pre-fix, now correctly counted

Direction entropy is healthy across all four states; the policy is not collapsed.

---

## Phase-0 task completion summary (final)

| Task | Status | Commit |
|---|---|---|
| 0.1 – 0.2  | ✅ | (pre-session) |
| 0.3 Track 1 magnitude Q / var_scale / kelly wiring | ✅ (all stubs eliminated per no-stubs rule) | `83d524f86` |
| 0.4 Per-branch grad norm ratio | ✅ | `bb42c9963` (pre-session) |
| 0.5 Per-magnitude trail fire rate (H6) | ✅ (deterministic per-sample arrays, no atomicAdd) | `48d962ee2` |
| 0.6 VSN + NoisyNets σ + target drift | ✅ | `aa16ca31f` |
| 0.7 Eval-mode action distribution | ✅ | (pre-session) |
| 0.8 Reward term contribution | ✅ (seg slot deleted — term not wired) | `bf8415c5d` → `83d524f86` |
| 0.9 Controller fire-rate tracking | ✅ | (pre-session) + `ed4b30b49` (V7 intervention semantics) |
| 0.10 Exploration entropy + σ | ✅ | `999bb2fa0` |
| 0.11 – 0.15 smoke tests | ✅ (all pass after Phase 0 diagnostic fixes) | various |
| 0.16 surrogate_noise_check | ✅ | `f4ea0f6d1` |
| 0.17 Baseline metrics + tag | ✅ (this doc + `policy-quality-baseline` tag) | this commit |

## Phase-0 root-cause fixes shipped this session

Phase 0's "instrumentation-only" scope turned up several genuine pathologies as its signals came online. All fixed per the no-quickfix rule:

1. **OFI/bars truncation desync** (`2ac956298`) — `data_loading.rs` truncated feature/target vectors to `max_bars` but left `ofi_features` at full length, producing a misleading "fxcache is corrupt" downstream.
2. **Monitoring cascade 9→12 bins** (`2fb30f098`) — kernel uses 4-direction action space (Short/Hold/Long/Flat); monitoring was legacy 9-bin and silently dropped all Flat actions.
3. **HEALTH_DIAG ordering** (`a5f23b28f`) — GPU summary populated `monitor.action_counts` AFTER the HEALTH_DIAG block that read them. Every epoch saw zeros. Reordered the populate block to run first.
4. **Controller fire semantics** (`ed4b30b49`) — delta-based detection over-counted for EMA-ticking grad_clip and sigmoid-ramp cost_anneal; replaced with intervention-based detection (grad_clip fires only on actual clamp events; cost_anneal is a schedule, not a controller).
5. **Multi-fold smoke config** (`0beccd5e8`) — test was invoking `train_baseline_rl` with production-sized config on a 4 GB laptop + default walk-forward windows that yielded only 2 folds. Fixed test invocation to use `dqn-smoketest` profile + 6/2/2/2 months walk-forward windows.
6. **Error hiding in FusedTrainingCtx init** (`e8ecb2f62`) — previously logged-and-continued with `fused_ctx = None`, producing a misleading "collector MUST be active" error downstream. Now propagates via `Err(MLError::...)` so the CUDA root cause surfaces directly.
7. **Weak smoke-test assertions** (`4399a56d7`, `2570fe013`, `0472b9730`) — 5+ smoke tests had `is_finite()`-only or literal-tautology assertions that let regressions pass silently. Strengthened with real thresholds and failure detection.

Combined with the Phase 0 instrumentation commits (`48d962ee2`, `bf8415c5d`, `f4ea0f6d1`, `83d524f86`), the "magnitude collapse" story is resolved: the policy was never collapsed, the diagnostics just couldn't see past their own bugs.

---

## Phase 1 hand-off

Phase 1 investigation tracks (H1–H10 detection signals) are unblocked. The HEALTH_DIAG line is now fully populated and gives signal for every hypothesis. Concrete signals to investigate:

- **grad_ratio_mag_dir ≈ 0.0000** (HEALTH_DIAG `mag`) — H4 detection: magnitude branch receives near-zero gradient relative to direction. Worth confirming whether this is scale-driven (mag Q range smaller than dir Q range — legitimate) or learning-driven (mag branch disconnected from loss).
- **kelly_f_mean = 0.000** (HEALTH_DIAG `mag`) — at smoke scale, win/loss counters are degenerate. Run longer training (≥ 50 epochs) to see if Kelly becomes meaningful.
- **eval_dist [eq=1.000 eh=0 ef=0]** — greedy evaluation always picks Quarter magnitude, even though training-mode distribution is Q=60% H=15% F=25%. H10 target.
- **Fold-2 exploration compression** (ep_mag drops to ~0.7 mid-training in fold 2 only) — worth tracking as a Track 4 signal when folds are run with larger windows.

Phase 1 work proceeds per the V7 plan's four tracks. This baseline is the reference against which Phase 2 interventions are measured.
