# syntax=docker/dockerfile:1.7
# DeepSeek-V4-Flash-DSpark on aidendle94 sparkrun-vllm-ds4-gb10:production-3.8,
# with a root-cause patch for BUG-2026-08-03T204037.
#
# The REAL blocker (found by boot-testing on ds4) is NOT the DeepGEMM
# `t.dim() == N` assertion from the original bug write-up. On this image the
# DSV4 target + drafter load cleanly via the b12x MoE backend — DeepGEMM scale
# packing never fires. Boot instead crashes during KV-cache profiling
# (profile_run -> dummy forward, under torch.compile/AOT), inside
# b12x/integration/residual_kernels.py `_to_kernel_tensor`:
#
#   from_dlpack(tensor, ...) -> tensor.__dlpack__()
#   BufferError: Can't export tensors that require gradient, use tensor.detach()
#
# Under torch.compile the norm parameter carries requires_grad=True (inductor
# keeps an autograd graph), and cutlass's from_dlpack refuses grad-requiring
# tensors. Fix: detach the tensor before dlpack export — a no-op for the
# requires_grad=False case, correct for the compiled case.

FROM aidendle94/sparkrun-vllm-ds4-gb10:production-3.8

# Patch 1: b12x cutlass from_dlpack rejects grad-requiring tensors under
# torch.compile (BufferError during KV-cache profiling). detach() before export.
RUN sed -i \
    's/from_dlpack(tensor, assumed_align=assumed_align)/from_dlpack(tensor.detach(), assumed_align=assumed_align)/' \
    /opt/env/lib/python3.12/site-packages/b12x/integration/residual_kernels.py \
 && grep -n 'from_dlpack(tensor' /opt/env/lib/python3.12/site-packages/b12x/integration/residual_kernels.py

# Patch 2: route the DSpark drafter's wo_a through the fused b12x WO
# projection (same as the main model) so the drafter's numerics are correct and
# DSpark draft acceptance is real (replaces the broken DeepGEMM fp8_einsum).
COPY patches/patch_dspark_b12xwoa.py /tmp/patch_dspark_b12xwoa.py
RUN /opt/env/bin/python3 /tmp/patch_dspark_b12xwoa.py

# Patch 3: DSpark mixed-context batch — pad shorter requests to the batch-max
# effective length so a parallel benchmark (tool-eval-bench --parallel 4) with
# divergent request contexts doesn't kill the engine (see patch script).
COPY patches/patch_dspark_uniform.py /tmp/patch_dspark_uniform.py
RUN /opt/env/bin/python3 /tmp/patch_dspark_uniform.py
