feat(sp22-vnext): Phase F-3c — HEALTH_DIAG snap + console line for K=3 CE EMA

Completes the F-3 observability story. Smoke runs now print
aux_trade_outcome_ce_ema every epoch in the standard HEALTH_DIAG output
— no ISV inspector required.

Changes:

health_diag.rs:
- New field aux_trade_outcome_ce: f32 appended at END of
  HealthDiagSnapshot per "Field order is stable; adding fields
  appends to the end" doc rule. Existing fields' byte offsets
  preserved → no kernel-side word offset re-validation.
- snapshot_size_is_stable pin: 149 × 4 → 150 × 4 = 600 bytes.

health_diag_kernel.cu:
- New WORD_AUX_TRADE_OUTCOME_CE = 149 (appended at end).
- WORD_TOTAL = 150 (was 149); static_assert bumped.
- New kernel arg aux_trade_outcome_ce_idx appended after
  moe_lambda_eff_idx.
- New mirror write after the existing MoE mirrors. Stream-implicit
  ordering: aux_outcome_ce_ema_update (F-3b) fires before
  health_diag_isv_mirror, so the read picks up the just-updated EMA.

gpu_health_diag.rs:
- launch_isv_mirror gets new aux_trade_outcome_ce_idx: i32 arg.

gpu_dqn_trainer.rs:
- launch_health_diag_isv_mirror passes
  AUX_TRADE_OUTCOME_CE_EMA_INDEX as the new arg.

training_loop.rs:
- Per-epoch metrics push appends ("aux_trade_outcome_ce_ema",
  ISV[538]) to the standard out vec. Console / CSV automatically
  includes the new column.

End-to-end F-3 chain now closed:
  K=3 fwd → aux_to_loss_scalar_buf → aux_outcome_ce_ema_update
  → ISV[538] → health_diag_isv_mirror → snap.aux_trade_outcome_ce
  → training_loop metrics → console.

Operator sees CE every epoch:
- Cold-start: 0.000
- After bootstrap: ~1.098 (= ln(3))
- After training: ideally 0.5-0.7 (head learning)

Phase F end-to-end ready. The vNext stack has:
- Full GPU kernel chain (A2-A5 + D + plan-conditioning)
- Full Rust wireup (B0-B4, B4b-1/2, C-1/C-2, B5b)
- Real labels reaching trainer
- K=3 → policy via state slots + atom-shift
- End-to-end CE observability

Verification:
- cargo check -p ml clean.
- cargo test -p ml --lib → 1016/0 green (incl. bumped
  snapshot_size_is_stable byte-size pin test).

Audit: docs/dqn-wire-up-audit.md Phase F-3c section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-05-14 12:22:43 +02:00
parent 02479c885d
commit cdd3dc6edb
6 changed files with 112 additions and 5 deletions

View File

@@ -18294,3 +18294,54 @@ Completes the Phase F-3 observability chain. The kernel + ISV slot landed in F-3
- Smoke observability: F-3 + F-3b ✓
**Phase F deployment** (next): push branch + `argo-train.sh` smoke run. Decisive test of the spec's hypothesis. Spec falsification criterion (per the original spec doc): if smoke produces WR ≈ 0.4346 ± 0.005, the trade-outcome hypothesis is falsified; the conclusion would be "WR is data-determined at this bar resolution + horizon, not a model architecture issue", and future work explores different data sampling / different prediction target.
#### Phase F-3c — HEALTH_DIAG snap + console line for K=3 CE EMA (2026-05-14)
Completes the observability story. Smoke runs now print `aux_trade_outcome_ce_ema` every epoch in the standard HEALTH_DIAG output — no ISV inspector required.
**Changes**:
`health_diag.rs` (struct):
- New field `aux_trade_outcome_ce: f32` appended at END of `HealthDiagSnapshot` per the documented "Field order is stable; adding fields appends to the end" rule. Existing fields' byte offsets preserved → no kernel-side word offset re-validation needed.
- `snapshot_size_is_stable` test pin bumped 149 × 4 → 150 × 4 = 600 bytes.
`health_diag_kernel.cu`:
- New `WORD_AUX_TRADE_OUTCOME_CE = 149` (appended at end).
- `WORD_TOTAL = 150` (was 149); static_assert updated.
- New kernel arg `aux_trade_outcome_ce_idx` appended after `moe_lambda_eff_idx`.
- New mirror write `snap[WORD_AUX_TRADE_OUTCOME_CE] = isv[aux_trade_outcome_ce_idx]` after the existing MoE mirrors. Stream-implicit ordering: the `aux_outcome_ce_ema_update` producer (Phase F-3b) fires before `health_diag_isv_mirror` in the per-step training graph, so the read picks up the just-updated EMA.
`gpu_health_diag.rs`:
- `launch_isv_mirror` Rust launcher gets new `aux_trade_outcome_ce_idx: i32` arg threaded through.
`gpu_dqn_trainer.rs`:
- `launch_health_diag_isv_mirror` passes `AUX_TRADE_OUTCOME_CE_EMA_INDEX as i32` as the new arg.
`training_loop.rs`:
- Per-epoch metrics push appends `("aux_trade_outcome_ce_ema", ISV[538])` to the standard `out` vec. The downstream metrics output (CSV, console, etc.) automatically includes the new column.
**End-to-end Phase F-3 chain now closed**:
```
K=3 forward (D + B5b) → aux_to_loss_scalar_buf[0]
→ aux_outcome_ce_ema_update (F-3a kernel) → ISV[538]
→ health_diag_isv_mirror (F-3c kernel ext) → snap.aux_trade_outcome_ce
→ training_loop metrics push (F-3c Rust ext) → console output
```
Operator now sees CE every epoch:
- Cold-start: `aux_trade_outcome_ce_ema=0.000`
- After bootstrap: `aux_trade_outcome_ce_ema≈1.098` (= ln(3))
- After training: ideally `aux_trade_outcome_ce_ema≈0.5-0.7`
**Verification**:
- `cargo check -p ml` clean.
- `cargo test -p ml --lib`**1016/0 green** (including the bumped `snapshot_size_is_stable` byte-size pin test).
**Phase F end-to-end ready**. The trade-outcome vNext stack now has:
- Full GPU kernel chain (A2-A5 + D + plan-conditioning)
- Full Rust wireup (B0-B4, B4b-1/2, C-1/C-2, B5b)
- Real labels reaching the trainer (B4b-2 direct-path gather)
- K=3 → policy via TWO paths (state slots + atom-shift)
- End-to-end CE observability (F-3 + F-3b + F-3c)
Spec-falsification criterion (per docs/plans/2026-05-14-sp22-h6-vNext-trade-outcome-aux.md): if the smoke produces WR ≈ 0.4346 ± 0.005 AND CE drops meaningfully (showing the head IS learning the labels), the spec is FALSIFIED — trade-outcome prediction is learnable but doesn't influence policy effectively. If CE pinned AND WR pinned, the spec is INCONCLUSIVE — label noise or under-capacity, head couldn't learn the signal so we don't know if the signal would have helped.