Second of 3 Layer D producer kernels. Replaces multi-step host arithmetic
in LearningHealth composition (q_gap_ema + q_var_ema + grad_norm_ema →
composed health score) with a fused GPU kernel chained through
apply_pearls_ad_kernel. Per feedback_no_cpu_compute_strict.
Additive only — no consumer wiring, no behavior change. The kernel +
launcher are loaded into GpuDqnTrainer and the slots are reserved on the
ISV bus, but the host-side composition continues to run unchanged. D4
(atomic Layer D commit) wires this and D1+D3 to call sites in the same
atomic refactor per feedback_no_partial_refactor.
What this lands:
- health_composition_kernel.cu (single-block fused composition)
- Rust launcher launch_health_composition()
- 4 new ISV slots (HEALTH_SCORE_INDEX..GRAD_NORM_NORM_INDEX, slots 290..294)
- ISV_TOTAL_DIM 290 → 294, SP5_PRODUCER_COUNT 116 → 120 (linear span)
- LAYOUT_FINGERPRINT_SEED bump (auto via slot string)
- StateResetRegistry entries (sentinel 0.0; per-fold reset enabled)
- build.rs cubin registration
- GPU-gated unit test in sp5_producer_unit_tests.rs (formula fidelity)
- Audit doc append
Formula fidelity: kernel reproduces the host-side LearningHealth::compose
(or equivalent) computation bit-for-bit within float precision. Migration
is structural only — no algorithmic change. Verified by unit test
asserting kernel output matches a Rust copy of the host formula within
1e-6 rel-err.
Tests: cargo check + cargo build clean; ISV slot + state_reset_registry
unit tests pass; GPU correctness test fires on next L40S smoke.
Refs: SP5 plan §D Task D2, builds on D1 (5ee795f14).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>