diff --git a/manual_slop.toml b/manual_slop.toml index fc304ea..8f0b00b 100644 --- a/manual_slop.toml +++ b/manual_slop.toml @@ -43,6 +43,25 @@ search_files = true get_file_summary = true web_search = true fetch_url = true +py_get_skeleton = true +py_get_code_outline = true +get_file_slice = true +py_get_definition = true +py_get_signature = true +py_get_class_summary = true +py_get_var_declaration = true +get_git_diff = true +py_find_usages = true +py_get_imports = true +py_check_syntax = true +py_get_hierarchy = true +py_get_docstring = true +get_tree = true +get_ui_performance = true +set_file_slice = false +py_update_definition = false +py_set_signature = false +py_set_var_declaration = false [gemini_cli] binary_path = "C:\\projects\\manual_slop\\.venv\\Scripts\\python.exe C:\\projects\\manual_slop\\tests\\mock_gemini_cli.py" diff --git a/project_manager.py b/project_manager.py index 5b21bb0..0356741 100644 --- a/project_manager.py +++ b/project_manager.py @@ -102,7 +102,26 @@ def default_project(name: str = "unnamed") -> dict[str, Any]: "search_files": True, "get_file_summary": True, "web_search": True, - "fetch_url": True + "fetch_url": True, + "py_get_skeleton": True, + "py_get_code_outline": True, + "get_file_slice": True, + "py_get_definition": True, + "py_get_signature": True, + "py_get_class_summary": True, + "py_get_var_declaration": True, + "get_git_diff": True, + "py_find_usages": True, + "py_get_imports": True, + "py_check_syntax": True, + "py_get_hierarchy": True, + "py_get_docstring": True, + "get_tree": True, + "get_ui_performance": True, + "set_file_slice": False, + "py_update_definition": False, + "py_set_signature": False, + "py_set_var_declaration": False, } }, "discussion": { diff --git a/tests/test_arch_boundary_phase2.py b/tests/test_arch_boundary_phase2.py new file mode 100644 index 0000000..dd1ea63 --- /dev/null +++ b/tests/test_arch_boundary_phase2.py @@ -0,0 +1,57 @@ +""" +Tests for architecture_boundary_hardening_20260302 — Phase 2. +Tasks 2.1-2.4: MCP tool config exposure + MUTATING_TOOLS + HITL enforcement. +""" +import tomllib +import pytest +from project_manager import default_project + +MUTATING_TOOLS = {"set_file_slice", "py_update_definition", "py_set_signature", "py_set_var_declaration"} +ALL_DISPATCH_TOOLS = { + "run_powershell", "read_file", "list_directory", "search_files", "get_file_summary", + "web_search", "fetch_url", "py_get_skeleton", "py_get_code_outline", "get_file_slice", + "py_get_definition", "py_update_definition", "py_get_signature", "py_set_signature", + "py_get_class_summary", "py_get_var_declaration", "py_set_var_declaration", "get_git_diff", + "py_find_usages", "py_get_imports", "py_check_syntax", "py_get_hierarchy", + "py_get_docstring", "get_tree", "get_ui_performance", "set_file_slice", +} + + +# --------------------------------------------------------------------------- +# Task 2.1: manual_slop.toml and default_project() expose all tools +# --------------------------------------------------------------------------- + +def test_toml_exposes_all_dispatch_tools(): + """manual_slop.toml [agent.tools] must list every tool in mcp_client.dispatch().""" + with open("manual_slop.toml", "rb") as f: + config = tomllib.load(f) + toml_tools = set(config["agent"]["tools"].keys()) + missing = ALL_DISPATCH_TOOLS - toml_tools + assert not missing, f"Tools missing from manual_slop.toml: {missing}" + + +def test_toml_mutating_tools_disabled_by_default(): + """Mutating tools must default to false in manual_slop.toml.""" + with open("manual_slop.toml", "rb") as f: + config = tomllib.load(f) + tools = config["agent"]["tools"] + for tool in MUTATING_TOOLS: + assert tool in tools, f"{tool} missing from toml" + assert tools[tool] is False, f"Mutating tool '{tool}' should default to false" + + +def test_default_project_exposes_all_dispatch_tools(): + """default_project() agent.tools must list every tool in mcp_client.dispatch().""" + proj = default_project() + project_tools = set(proj["agent"]["tools"].keys()) + missing = ALL_DISPATCH_TOOLS - project_tools + assert not missing, f"Tools missing from default_project(): {missing}" + + +def test_default_project_mutating_tools_disabled(): + """Mutating tools must default to False in default_project().""" + proj = default_project() + tools = proj["agent"]["tools"] + for tool in MUTATING_TOOLS: + assert tool in tools, f"{tool} missing from default_project" + assert tools[tool] is False, f"Mutating tool '{tool}' should default to False"