@@ -278,9 +278,95 @@ def test_task_engine_keys_override_config(self):
278278
279279
280280# ===================================================================
281- # _build_prompts_to_run
281+ # CLI model config override
282282# ===================================================================
283283
284+ class TestCliModelConfigOverride :
285+ """Tests for CLI model config overriding taskflow model_config_ref."""
286+
287+ def test_cli_overrides_taskflow_model_config (self ):
288+ """cli_model_config takes precedence over taskflow_doc.model_config_ref."""
289+ taskflow_ref = "taskflow.models.default"
290+ cli_ref = "cli.models.override"
291+
292+ # Simulate the override logic from run_main
293+ model_config_ref = taskflow_ref
294+ if cli_ref :
295+ model_config_ref = cli_ref
296+
297+ assert model_config_ref == cli_ref
298+
299+ def test_taskflow_model_config_used_when_cli_absent (self ):
300+ """Taskflow model_config_ref is used when cli_model_config is None."""
301+ taskflow_ref = "taskflow.models.default"
302+ cli_ref = None
303+
304+ model_config_ref = taskflow_ref
305+ if cli_ref :
306+ model_config_ref = cli_ref
307+
308+ assert model_config_ref == taskflow_ref
309+
310+ def test_cli_model_config_resolves_via_available_tools (self ):
311+ """CLI-provided model config is resolved through _resolve_model_config."""
312+ at = _mock_available_tools ()
313+ at .get_model_config .return_value = _make_model_config (
314+ models = {"fast" : "gpt-4o-mini" },
315+ )
316+ keys , mdict , params , api_type , backend = _resolve_model_config (at , "cli.override.ref" )
317+ at .get_model_config .assert_called_once_with ("cli.override.ref" )
318+ assert mdict == {"fast" : "gpt-4o-mini" }
319+
320+ def test_cli_model_config_persisted_in_session (self ):
321+ """cli_model_config is stored in session for deterministic resume."""
322+ from seclab_taskflow_agent .session import TaskflowSession
323+
324+ session = TaskflowSession (
325+ taskflow_path = "test.flow" ,
326+ cli_model_config = "cli.models.fast" ,
327+ )
328+ assert session .cli_model_config == "cli.models.fast"
329+
330+ def test_session_resume_restores_cli_model_config (self , tmp_path , monkeypatch ):
331+ """Resumed session restores cli_model_config when not overridden."""
332+ monkeypatch .setattr ("seclab_taskflow_agent.session.session_dir" , lambda : tmp_path )
333+ from seclab_taskflow_agent .session import TaskflowSession
334+
335+ session = TaskflowSession (
336+ taskflow_path = "test.flow" ,
337+ cli_model_config = "persisted.models.ref" ,
338+ )
339+ session .save ()
340+
341+ loaded = TaskflowSession .load (session .session_id )
342+
343+ # Simulate the resume logic from run_main
344+ cli_model_config = None # not passed on resume
345+ if not cli_model_config and loaded .cli_model_config :
346+ cli_model_config = loaded .cli_model_config
347+
348+ assert cli_model_config == "persisted.models.ref"
349+
350+ def test_session_resume_cli_override_takes_precedence (self , tmp_path , monkeypatch ):
351+ """Explicit --model-config on resume overrides persisted value."""
352+ monkeypatch .setattr ("seclab_taskflow_agent.session.session_dir" , lambda : tmp_path )
353+ from seclab_taskflow_agent .session import TaskflowSession
354+
355+ session = TaskflowSession (
356+ taskflow_path = "test.flow" ,
357+ cli_model_config = "persisted.models.ref" ,
358+ )
359+ session .save ()
360+
361+ loaded = TaskflowSession .load (session .session_id )
362+
363+ # Simulate the resume logic from run_main with explicit override
364+ cli_model_config = "new.override.ref"
365+ if not cli_model_config and loaded .cli_model_config :
366+ cli_model_config = loaded .cli_model_config
367+
368+ assert cli_model_config == "new.override.ref"
369+
284370class TestBuildPromptsToRun :
285371 """Tests for _build_prompts_to_run (async, run via asyncio.run)."""
286372
0 commit comments