11from pathlib import Path
22from textwrap import dedent
3+ from types import SimpleNamespace
34from unittest .mock import MagicMock
45
56import yaml
89from iac_code .pipeline .engine .pipeline_runner import PipelineRunner
910
1011
11- def _make_runner (tmp_path : Path , on_complete : dict | None = None ) -> PipelineRunner :
12+ def _make_runner (
13+ tmp_path : Path ,
14+ on_complete : dict | None = None ,
15+ permission_mode : str | None = None ,
16+ ) -> PipelineRunner :
1217 body = {
1318 "name" : "test" ,
1419 "context_dependencies" : {
@@ -31,13 +36,15 @@ def _make_runner(tmp_path: Path, on_complete: dict | None = None) -> PipelineRun
3136 (tmp_path / "prompts" ).mkdir ()
3237 (tmp_path / "prompts" / "step.md" ).write_text ("step" , encoding = "utf-8" )
3338
39+ permission_context_getter = (lambda : SimpleNamespace (mode = permission_mode )) if permission_mode is not None else None
3440 return PipelineRunner (
3541 pipeline_dir = tmp_path ,
3642 provider_manager = MagicMock (),
3743 base_tool_registry = MagicMock (),
3844 session_storage = MagicMock (),
3945 session_id = "session" ,
4046 cwd = str (tmp_path ),
47+ permission_context_getter = permission_context_getter ,
4148 )
4249
4350
@@ -133,6 +140,33 @@ def test_build_handoff_summary_requires_new_confirmation_for_resource_release_ex
133140 assert "pipeline-managed automatic cleanup may proceed without this additional confirmation" in summary
134141
135142
143+ def test_build_handoff_summary_uses_permission_confirmation_when_release_tools_are_not_allowed ():
144+ summary = build_handoff_summary (
145+ pipeline_name = "selling" ,
146+ outcome = "completed" ,
147+ context_snapshot = {},
148+ include_fields = [],
149+ release_tools_any_allowed = False ,
150+ )
151+
152+ assert "tool permission confirmation as the sole confirmation" in summary
153+ assert "Do not ask for a separate confirmation in normal chat" in summary
154+ assert "obtain a fresh, explicit confirmation" not in summary
155+
156+
157+ def test_build_handoff_summary_keeps_chat_confirmation_when_a_release_tool_is_allowed ():
158+ summary = build_handoff_summary (
159+ pipeline_name = "selling" ,
160+ outcome = "completed" ,
161+ context_snapshot = {},
162+ include_fields = [],
163+ release_tools_any_allowed = True ,
164+ )
165+
166+ assert "obtain a fresh, explicit confirmation" in summary
167+ assert "tool permission confirmation as the sole confirmation" not in summary
168+
169+
136170def test_runner_should_switch_to_normal_for_completed_policy (tmp_path ):
137171 runner = _make_runner (tmp_path , _switch_policy ("completed" ))
138172
@@ -181,3 +215,36 @@ def test_runner_build_normal_handoff_summary_uses_configured_context_values(tmp_
181215 assert "Outcome: completed" in summary
182216 assert '"summary": "deploy nginx"' in summary
183217 assert "Missing context fields:\n - architecture" in summary
218+
219+
220+ def test_runner_build_normal_handoff_summary_uses_current_permission_rules (tmp_path ):
221+ runner = _make_runner (tmp_path , _switch_policy ("completed" ), permission_mode = "default" )
222+ runner ._permission_context_getter = lambda : SimpleNamespace (
223+ mode = "default" ,
224+ allow_rules = {
225+ "user_settings" : [
226+ "bash(**)" ,
227+ "read_file" ,
228+ ]
229+ },
230+ ask_rules = {"user_settings" : ["ros_stack" , "aliyun_api" ]},
231+ deny_rules = {},
232+ )
233+
234+ summary = runner .build_normal_handoff_summary ({"total_steps" : 1 })
235+
236+ assert "tool permission confirmation as the sole confirmation" in summary
237+
238+
239+ def test_runner_build_normal_handoff_summary_uses_chat_confirmation_when_a_release_tool_is_allowed (tmp_path ):
240+ runner = _make_runner (tmp_path , _switch_policy ("completed" ), permission_mode = "default" )
241+ runner ._permission_context_getter = lambda : SimpleNamespace (
242+ mode = "default" ,
243+ allow_rules = {"user_settings" : ["aliyun_api" ]},
244+ ask_rules = {"user_settings" : ["ros_stack" ]},
245+ deny_rules = {},
246+ )
247+
248+ summary = runner .build_normal_handoff_summary ({"total_steps" : 1 })
249+
250+ assert "obtain a fresh, explicit confirmation" in summary
0 commit comments