diff --git a/python/sglang/srt/layers/attention/deepseek_v4_backend.py b/python/sglang/srt/layers/attention/deepseek_v4_backend.py index eff734c6c..5830a02a4 100644 --- a/python/sglang/srt/layers/attention/deepseek_v4_backend.py +++ b/python/sglang/srt/layers/attention/deepseek_v4_backend.py @@ -506,7 +506,11 @@ class DeepseekV4AttnBackend( def shared_read_boundary(self, forward_mode: ForwardMode) -> SharedReadBoundary: # Breakable-graph verify rereads shared state across segments. + # DSPARK verify replays one full (non-breakable) graph that honors the + # out-graph/in-graph init contract, so the base IN_REPLAY bound holds. if forward_mode.is_target_verify(): + if self.model_runner.spec_algorithm.is_dspark(): + return SharedReadBoundary.IN_REPLAY return SharedReadBoundary.POST_REPLAY return super().shared_read_boundary(forward_mode) diff --git a/python/sglang/srt/speculative/spec_info.py b/python/sglang/srt/speculative/spec_info.py index 7d19a18d3..dbe2f566f 100644 --- a/python/sglang/srt/speculative/spec_info.py +++ b/python/sglang/srt/speculative/spec_info.py @@ -128,8 +128,10 @@ class SpeculativeAlgorithm(Enum): return self.is_dflash_family() def is_war_publish_phase(self, forward_mode) -> bool: - # The step's last shared-buffer-reading phase owns the WAR read-done publish. - if self.is_dflash_family(): + # The step's last shared-buffer-reading phase owns the WAR read-done + # publish. DSPARK has no draft_extend: its draft samples inside the + # verify graph, so verify is that last phase. + if self.is_dflash_family() or self.is_dspark(): return forward_mode.is_target_verify() return forward_mode.is_draft_extend_v2()