@@ -134,6 +134,27 @@ def test_dispatch_installed_tool_runs(self, mock_run, _mock_installed):
134134 cmd = mock_run .call_args [0 ][0 ]
135135 assert "api_contract_guardian" in cmd
136136
137+ @mock .patch ("devforge.cli._is_tool_installed" , return_value = True )
138+ @mock .patch ("devforge.cli.subprocess.run" )
139+ def test_dispatch_forwards_tool_flags (self , mock_run , _mock_installed ):
140+ """Tool flags (e.g. `--config file.yaml`) must reach the underlying CLI.
141+
142+ Regression guard for the silent-failure trap where typer rejected any
143+ argument beginning with `-` as 'No such option' before the tool ran.
144+ With ignore_unknown_options/allow_extra_args, such flags are forwarded
145+ via ctx.args.
146+ """
147+ mock_run .return_value = mock .MagicMock (returncode = 0 )
148+ with mock .patch ("devforge.cli.sys.exit" ):
149+ runner .invoke (app , ["guard" , "--config" , "x.yaml" , "--verbose" ])
150+ mock_run .assert_called_once ()
151+ cmd = mock_run .call_args [0 ][0 ]
152+ # Underlying module is launched...
153+ assert "api_contract_guardian" in cmd
154+ # ...and the tool flags are forwarded, not swallowed by typer.
155+ assert "--config" in cmd
156+ assert "x.yaml" in cmd
157+ assert "--verbose" in cmd
137158
138159 @mock .patch ("devforge.cli._is_tool_installed" , return_value = False )
139160 def test_dispatch_install_hint_escapes_extra_brackets (self , _mock ):
0 commit comments