IQN graph now captures the FULL pipeline in one graph:
- decode_actions + fwd/loss + backward + grad_norm + Adam
- trunk gradient (cuBLAS backward into shared weights)
- target EMA (tau from GPU-resident tau_buf, async HtoD before replay)
- IQN→PER loss DtoD copy
IQN EMA kernel changed: float tau → const float* tau_buf (device read).
tau_buf added to GpuIqnHead with async cuMemcpyHtoDAsync per step.
This was the last scalar parameter preventing full graph capture.
regime_scale_td_errors moved into graph_adam submit sequence.
Runs after Adam unflatten, before PER priority update.
Per-step: 7 graph replays + ~9 ungraphed ops
Ungraphed ops (genuinely can't be graphed — batch ptrs change):
- upload_batch_gpu: 6 DtoD + 2 pad_states (batch-specific pointers)
- HER relabel: 1-2 kernels (donor from batch next_states)
- PER priority update: 1 kernel (indices from batch)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>