Root cause identified: bf16_weight_ptrs called device_ptr() inside
CUDA graph capture, which records cudarc events — not allowed during
capture. Created bf16_weight_ptrs_from_base() that takes pre-resolved
u64 base pointer from CachedPtrs (no device_ptr calls, graph-safe).
Replaced ALL 12 bf16_weight_ptrs calls in gpu_dqn_trainer with
bf16_weight_ptrs_from_base using self.ptrs.params_buf/target_params_buf.
Debug forward (no graph) confirms cuBLAS GemmEx produces valid logits.
Q-value divergence persists in graph mode — Adam or readback issue TBD.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>