diff --git a/.gemini/agents/tier1-orchestrator.md b/.gemini/agents/tier1-orchestrator.md index 410a79d..b8238e1 100644 --- a/.gemini/agents/tier1-orchestrator.md +++ b/.gemini/agents/tier1-orchestrator.md @@ -7,6 +7,10 @@ tools: - list_directory - discovered_tool_search_files - grep_search + - discovered_tool_get_file_summary + - discovered_tool_get_python_skeleton + - discovered_tool_get_code_outline + - discovered_tool_get_git_diff - discovered_tool_web_search - discovered_tool_fetch_url - activate_skill diff --git a/.gemini/agents/tier2-tech-lead.md b/.gemini/agents/tier2-tech-lead.md index 8b9f70d..7924ce4 100644 --- a/.gemini/agents/tier2-tech-lead.md +++ b/.gemini/agents/tier2-tech-lead.md @@ -9,6 +9,10 @@ tools: - list_directory - discovered_tool_search_files - grep_search + - discovered_tool_get_file_summary + - discovered_tool_get_python_skeleton + - discovered_tool_get_code_outline + - discovered_tool_get_git_diff - discovered_tool_web_search - discovered_tool_fetch_url - activate_skill diff --git a/.gemini/agents/tier3-worker.md b/.gemini/agents/tier3-worker.md index 5ba0689..4889193 100644 --- a/.gemini/agents/tier3-worker.md +++ b/.gemini/agents/tier3-worker.md @@ -9,6 +9,10 @@ tools: - list_directory - discovered_tool_search_files - grep_search + - discovered_tool_get_file_summary + - discovered_tool_get_python_skeleton + - discovered_tool_get_code_outline + - discovered_tool_get_git_diff - discovered_tool_web_search - discovered_tool_fetch_url - activate_skill diff --git a/.gemini/agents/tier4-qa.md b/.gemini/agents/tier4-qa.md index f78ebb8..fd16830 100644 --- a/.gemini/agents/tier4-qa.md +++ b/.gemini/agents/tier4-qa.md @@ -7,6 +7,10 @@ tools: - list_directory - discovered_tool_search_files - grep_search + - discovered_tool_get_file_summary + - discovered_tool_get_python_skeleton + - discovered_tool_get_code_outline + - discovered_tool_get_git_diff - discovered_tool_web_search - discovered_tool_fetch_url - activate_skill diff --git a/mcp_client.py b/mcp_client.py index 79b126a..6ae74ad 100644 --- a/mcp_client.py +++ b/mcp_client.py @@ -281,6 +281,31 @@ def get_code_outline(path: str) -> str: return f"ERROR generating outline for '{path}': {e}" +def get_git_diff(path: str, base_rev: str = "HEAD", head_rev: str = "") -> str: + """ + Returns the git diff for a file or directory. + base_rev: The base revision (default: HEAD) + head_rev: The head revision (optional) + """ + import subprocess + p, err = _resolve_and_check(path) + if err: + return err + + cmd = ["git", "diff", base_rev] + if head_rev: + cmd.append(head_rev) + cmd.extend(["--", str(p)]) + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True, encoding="utf-8") + return result.stdout if result.stdout else "(no changes)" + except subprocess.CalledProcessError as e: + return f"ERROR running git diff: {e.stderr}" + except Exception as e: + return f"ERROR: {e}" + + # ------------------------------------------------------------------ web tools @@ -407,7 +432,7 @@ def get_ui_performance() -> str: # ------------------------------------------------------------------ tool dispatch -TOOL_NAMES = {"read_file", "list_directory", "search_files", "get_file_summary", "get_python_skeleton", "get_code_outline", "web_search", "fetch_url", "get_ui_performance"} +TOOL_NAMES = {"read_file", "list_directory", "search_files", "get_file_summary", "get_python_skeleton", "get_code_outline", "get_git_diff", "web_search", "fetch_url", "get_ui_performance"} def dispatch(tool_name: str, tool_input: dict) -> str: @@ -426,6 +451,12 @@ def dispatch(tool_name: str, tool_input: dict) -> str: return get_python_skeleton(tool_input.get("path", "")) if tool_name == "get_code_outline": return get_code_outline(tool_input.get("path", "")) + if tool_name == "get_git_diff": + return get_git_diff( + tool_input.get("path", ""), + tool_input.get("base_rev", "HEAD"), + tool_input.get("head_rev", "") + ) if tool_name == "web_search": return web_search(tool_input.get("query", "")) if tool_name == "fetch_url": @@ -551,6 +582,31 @@ MCP_TOOL_SPECS = [ "required": ["path"], }, }, + { + "name": "get_git_diff", + "description": ( + "Returns the git diff for a file or directory. " + "Use this to review changes efficiently without reading entire files." + ), + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Path to the file or directory.", + }, + "base_rev": { + "type": "string", + "description": "Base revision (e.g. 'HEAD', 'HEAD~1', or a commit hash). Defaults to 'HEAD'.", + }, + "head_rev": { + "type": "string", + "description": "Head revision (optional).", + } + }, + "required": ["path"], + }, + }, { "name": "web_search", "description": "Search the web using DuckDuckGo. Returns the top 5 search results with titles, URLs, and snippets. Chain this with fetch_url to read specific pages.", diff --git a/mma-orchestrator/SKILL.md b/mma-orchestrator/SKILL.md index 70ee3bc..80a6085 100644 --- a/mma-orchestrator/SKILL.md +++ b/mma-orchestrator/SKILL.md @@ -26,13 +26,17 @@ If you run a test or command that fails with a significant error or large traceb 1. **DO NOT** analyze the raw logs in your own context window. 2. **DO** spawn a stateless Tier 4 agent to diagnose the failure. 3. *Command:* `uv run python scripts/mma_exec.py --role tier4-qa "Analyze this failure and summarize the root cause: [LOG_DATA]"` -4. Avoid direct reads to files, use file summaries or ast skeletons for files if they are code and we have a tool for parsing them. +4. **Mandatory Research-First Protocol:** Avoid direct `read_file` calls for any file over 50 lines. Use `get_file_summary`, `get_python_skeleton`, or `get_code_outline` first to identify relevant sections. Use `git diff` to understand changes. ## 3. Persistent Tech Lead Memory (Tier 2) Unlike the stateless sub-agents (Tiers 3 & 4), the **Tier 2 Tech Lead** maintains persistent context throughout the implementation of a track. Do NOT apply "Context Amnesia" to your own session during track implementation. You are responsible for the continuity of the technical strategy. -## 4. AST Skeleton Views -To minimize context bloat for Tier 2 & 3, use "Skeleton Views" of dependencies (extracted via `mcp_client.py` or similar) instead of full file contents, unless the Tier 3 worker is explicitly modifying that specific file. +## 4. AST Skeleton & Outline Views +To minimize context bloat for Tier 2 & 3: +1. Use `get_code_outline` to map out the structure of a file. +2. Use `get_python_skeleton` to understand the interface and docstrings of dependencies. +3. Only use `read_file` with `start_line` and `end_line` for specific implementation details once target areas are identified. +4. Tier 3 workers MUST NOT read the full content of unrelated files. ### Example 1: Spawning a Tier 4 QA Agent diff --git a/scripts/mma_exec.py b/scripts/mma_exec.py index 57f0948..4360073 100644 --- a/scripts/mma_exec.py +++ b/scripts/mma_exec.py @@ -177,14 +177,15 @@ def execute_agent(role: str, prompt: str, docs: list[str]) -> str: system_directive = "STRICT SYSTEM DIRECTIVE: You are a stateless Tier 3 Worker (Contributor). " \ "Your goal is to implement specific code changes or tests based on the provided task. " \ "You have access to tools for reading and writing files (e.g., read_file, write_file, replace), " \ - "codebase investigation (codebase_investigator), and web tools (discovered_tool_web_search, discovered_tool_fetch_url). " \ + "codebase investigation (discovered_tool_get_code_outline, discovered_tool_get_python_skeleton), " \ + "version control (discovered_tool_get_git_diff), and web tools (discovered_tool_web_search, discovered_tool_fetch_url). " \ "You CAN execute PowerShell scripts via discovered_tool_run_powershell for verification and testing. " \ "Follow TDD and return success status or code changes. No pleasantries, no conversational filler." elif role in ['tier4', 'tier4-qa']: system_directive = "STRICT SYSTEM DIRECTIVE: You are a stateless Tier 4 QA Agent. " \ "Your goal is to analyze errors, summarize logs, or verify tests. " \ - "You have access to tools for reading files, exploring the codebase (codebase_investigator), " \ - "and web tools (discovered_tool_web_search, discovered_tool_fetch_url). " \ + "You have access to tools for reading files, exploring the codebase (discovered_tool_get_code_outline, discovered_tool_get_python_skeleton), " \ + "version control (discovered_tool_get_git_diff), and web tools (discovered_tool_web_search, discovered_tool_fetch_url). " \ "You CAN execute PowerShell scripts via discovered_tool_run_powershell for diagnostics. " \ "ONLY output the requested analysis. No pleasantries." else: @@ -208,11 +209,11 @@ def execute_agent(role: str, prompt: str, docs: list[str]) -> str: # Use subprocess with input to pipe the prompt via stdin, avoiding WinError 206. # We use -p 'mma_task' to ensure non-interactive (headless) mode and valid parsing. # Whitelist tools to ensure they are available to the model in headless mode. - # Using 'discovered_tool_run_powershell' as it's the confirmed name for shell access. - allowed_tools = "read_file,write_file,replace,list_directory,glob,grep_search,discovered_tool_search_files,discovered_tool_get_file_summary,discovered_tool_run_powershell,activate_skill,codebase_investigator,discovered_tool_web_search,discovered_tool_fetch_url" + # Using 'discovered_tool_*' names as they are provided by tool_discovery.py + allowed_tools = "read_file,write_file,replace,list_directory,glob,grep_search,discovered_tool_search_files,discovered_tool_get_file_summary,discovered_tool_get_python_skeleton,discovered_tool_get_code_outline,discovered_tool_get_git_diff,discovered_tool_run_powershell,activate_skill,codebase_investigator,discovered_tool_web_search,discovered_tool_fetch_url" ps_command = ( f"if (Test-Path 'C:\\projects\\misc\\setup_gemini.ps1') {{ . 'C:\\projects\\misc\\setup_gemini.ps1' }}; " - f"gemini -p 'mma_task' --allowed-tools {allowed_tools} --output-format json --model {model}" + f"gemini -p 'mma_task' --allowed-tools {allowed_tools} --approval-mode yolo --output-format json --model {model}" ) cmd = ['powershell.exe', '-NoProfile', '-Command', ps_command]