diff --git a/python/sglang/srt/arg_groups/pipeline.py b/python/sglang/srt/arg_groups/pipeline.py index 4fd672912..cfe55dfca 100644 --- a/python/sglang/srt/arg_groups/pipeline.py +++ b/python/sglang/srt/arg_groups/pipeline.py @@ -54,11 +54,11 @@ def run_resolution_pipeline(server_args: Any) -> None: for field in dataclasses.fields(server_args) } - # Declaration stash for the override/post-process passes. Set before any - # short-circuit (none/dummy model paths) so run_post_process_pass and - # direct handler invocations can rely on it even when - # _handle_model_specific_adjustments never runs. - server_args._resolved_overrides = [] + # Preserve launcher-stage declarations made before Engine starts. They are + # part of the same resolution result as the declarations accumulated below. + server_args._resolved_overrides = list( + getattr(server_args, "_resolved_overrides", ()) + ) cfg = resolving_view(server_args) diff --git a/test/registered/unit/server_args/test_resolution_declarations.py b/test/registered/unit/server_args/test_resolution_declarations.py index 89ef72d69..622f23f87 100644 --- a/test/registered/unit/server_args/test_resolution_declarations.py +++ b/test/registered/unit/server_args/test_resolution_declarations.py @@ -592,6 +592,22 @@ class TestResolutionDeclarations(CustomTestCase): "does not write back", ) + def test_pre_engine_late_resolution_reaches_the_projection(self): + """A launcher declaration survives the engine's first resolution pass.""" + from sglang.srt.arg_groups.overrides import declare_late_resolution + + server_args = ServerArgs(model_path="dummy") + declare_late_resolution( + server_args, + "launcher", + enable_forward_pass_metrics=True, + ) + + server_args.resolve_once() + + self.assertTrue(resolution_result(server_args, "enable_forward_pass_metrics")) + self.assertFalse(server_args.enable_forward_pass_metrics) + def test_validation_can_still_resolve_before_the_record_is_published(self): """The LoRA checks resolve, so they must precede publish.