Replaces the kernel's hardcoded `ema_alpha` with the shared `pearls_ad_update`
host-side helper. 6 ISV slots retrofit (one per VSN feature group).
- Kernel `vsn_mask_ema_update` signature: drops `(isv, isv_first_index,
ema_alpha)` for `(scratch_buf, scratch_first_index=53)`. Per-group mean
writes to `scratch_buf[53..59)`. Single `__threadfence_system()` after
all 6 groups write.
- 6 ISV slots wired with Pearls A+D: ISV[105..111) (Wiener offsets
159..177). Wiener offset for group g: (53+g)*3.
- Wrapper `GpuDqnTrainer::launch_vsn_mask_ema(_ema_alpha_unused)`: sync
+ Pearls A+D loop over the 6 groups.
- `debug_assert_eq!(SL_NUM_FEATURE_GROUPS, 6)` guards against group-count
changes silently breaking the contiguous scratch layout.
Behavior: stationary signals converge to the same value at adaptive rate.
The 6 slots stay semantically identical (per-group mean of VSN softmax
mask); HEALTH_DIAG mirror + VSN focus monitor consume them unchanged.
Tests: `sp4_vsn_mask_ema_writes_step_obs_via_pearl_a_then_converges_pearl_d`
drives kernel with B=128 num_groups=6 mask `mask[b,g]=(g+1)/21` (rows sum
to 1, per-group mean = (g+1)/21). Asserts each slot ∈ ±1e-5, non-target
slots remain 0; verifies Pearl A bootstrap + Pearl D convergence.
Per `feedback_no_atomicadd.md`,
`feedback_no_htod_htoh_only_mapped_pinned.md`. Build: `cargo check -p ml
--lib --tests --offline` clean (11 pre-existing warnings, no new warnings).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>