From fd6e2f9b64e9cfcc6887d1d0e7216c60d40061ab Mon Sep 17 00:00:00 2001 From: Fahad Date: Mon, 9 Jun 2025 14:37:03 +0400 Subject: [PATCH] refactor: rename review_pending_changes to review_changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Renamed tool from review_pending_changes to review_changes for brevity - Enhanced tool descriptions for better MCP auto-discovery - Updated all references throughout codebase including: - Tool implementation (tools/review_changes.py) - Test files (tests/test_review_changes.py) - Server registration and imports - Documentation in README.md - Tool prompts in prompts/tool_prompts.py - Enhanced review_changes description to emphasize pre-commit usage - All tests pass, linting and formatting checks pass 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 8 +-- prompts/tool_prompts.py | 2 +- server.py | 4 +- ...ding_changes.py => test_review_changes.py} | 56 +++++++++---------- tests/test_server.py | 2 +- tools/__init__.py | 4 +- tools/base.py | 2 +- ...w_pending_changes.py => review_changes.py} | 18 +++--- 8 files changed, 48 insertions(+), 48 deletions(-) rename tests/{test_review_pending_changes.py => test_review_changes.py} (82%) rename tools/{review_pending_changes.py => review_changes.py} (96%) diff --git a/README.md b/README.md index 6b35185..49f4edf 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Claude is brilliant, but sometimes you need: - **A senior developer partner** to validate and extend ideas ([`chat`](#1-chat---general-development-chat--collaborative-thinking)) - **A second opinion** on complex architectural decisions - augment Claude's extended thinking with Gemini's perspective ([`think_deeper`](#2-think_deeper---extended-reasoning-partner)) - **Professional code reviews** with actionable feedback across entire repositories ([`review_code`](#3-review_code---professional-code-review)) -- **Pre-commit validation** with deep analysis that finds edge cases, validates your implementation against original requirements, and catches subtle bugs Claude might miss ([`review_pending_changes`](#4-review_pending_changes---pre-commit-validation)) +- **Pre-commit validation** with deep analysis that finds edge cases, validates your implementation against original requirements, and catches subtle bugs Claude might miss ([`review_changes`](#4-review_changes---pre-commit-validation)) - **Expert debugging** for tricky issues with full system context ([`debug_issue`](#5-debug_issue---expert-debugging-assistant)) - **Massive context window** (1M tokens) - Gemini 2.5 Pro can analyze entire codebases, read hundreds of files at once, and provide comprehensive insights ([`analyze`](#6-analyze---smart-file-analysis)) - **Deep code analysis** across massive codebases that exceed Claude's context limits ([`analyze`](#6-analyze---smart-file-analysis)) @@ -119,7 +119,7 @@ Just ask Claude naturally: - **Need a thinking partner?** → `chat` (brainstorm ideas, get second opinions, validate approaches) - **Need deeper thinking?** → `think_deeper` (extends Claude's analysis, finds edge cases) - **Code needs review?** → `review_code` (bugs, security, performance issues) -- **Pre-commit validation?** → `review_pending_changes` (validate git changes before committing) +- **Pre-commit validation?** → `review_changes` (validate git changes before committing) - **Something's broken?** → `debug_issue` (root cause analysis, error tracing) - **Want to understand code?** → `analyze` (architecture, patterns, dependencies) - **Check models?** → `list_models` (see available Gemini models) @@ -129,7 +129,7 @@ Just ask Claude naturally: 1. [`chat`](#1-chat---general-development-chat--collaborative-thinking) - Collaborative thinking and development conversations 2. [`think_deeper`](#2-think_deeper---extended-reasoning-partner) - Extended reasoning and problem-solving 3. [`review_code`](#3-review_code---professional-code-review) - Professional code review with severity levels -4. [`review_pending_changes`](#4-review_pending_changes---pre-commit-validation) - Validate git changes before committing +4. [`review_changes`](#4-review_changes---pre-commit-validation) - Validate git changes before committing 5. [`debug_issue`](#5-debug_issue---expert-debugging-assistant) - Root cause analysis and debugging 6. [`analyze`](#6-analyze---smart-file-analysis) - General-purpose file and code analysis 7. [`list_models`](#7-list_models---see-available-gemini-models) - List available Gemini models @@ -244,7 +244,7 @@ make any necessary adjustments and show me the final secure implementation." **Triggers:** review code, check for issues, find bugs, security check -### 4. `review_pending_changes` - Pre-Commit Validation +### 4. `review_changes` - Pre-Commit Validation **Comprehensive review of staged/unstaged git changes across multiple repositories** #### Example Prompts: diff --git a/prompts/tool_prompts.py b/prompts/tool_prompts.py index b9254f2..b5993e7 100644 --- a/prompts/tool_prompts.py +++ b/prompts/tool_prompts.py @@ -137,7 +137,7 @@ the ideal thinking partner who helps explore ideas deeply, validates approaches, insights that might be missed in solo analysis. Think step by step through complex problems and don't hesitate to explore tangential but relevant considerations.""" -REVIEW_PENDING_CHANGES_PROMPT = """You are an expert code change analyst specializing in pre-commit review of git diffs. +REVIEW_CHANGES_PROMPT = """You are an expert code change analyst specializing in pre-commit review of git diffs. Your role is to act as a seasoned senior developer performing a final review before code is committed. IMPORTANT: If you need additional context (e.g., related files not in the diff, test files, configuration) diff --git a/server.py b/server.py index 02ccfcf..bb06ada 100644 --- a/server.py +++ b/server.py @@ -26,8 +26,8 @@ from tools import ( AnalyzeTool, ChatTool, DebugIssueTool, + ReviewChanges, ReviewCodeTool, - ReviewPendingChanges, ThinkDeeperTool, ) @@ -45,7 +45,7 @@ TOOLS = { "debug_issue": DebugIssueTool(), "analyze": AnalyzeTool(), "chat": ChatTool(), - "review_pending_changes": ReviewPendingChanges(), + "review_changes": ReviewChanges(), } diff --git a/tests/test_review_pending_changes.py b/tests/test_review_changes.py similarity index 82% rename from tests/test_review_pending_changes.py rename to tests/test_review_changes.py index 49eb8f9..4185e16 100644 --- a/tests/test_review_pending_changes.py +++ b/tests/test_review_changes.py @@ -1,5 +1,5 @@ """ -Tests for the review_pending_changes tool +Tests for the review_changes tool """ import json @@ -7,23 +7,23 @@ from unittest.mock import Mock, patch import pytest -from tools.review_pending_changes import ( - ReviewPendingChanges, - ReviewPendingChangesRequest, +from tools.review_changes import ( + ReviewChanges, + ReviewChangesRequest, ) -class TestReviewPendingChangesTool: - """Test the review_pending_changes tool""" +class TestReviewChangesTool: + """Test the review_changes tool""" @pytest.fixture def tool(self): """Create tool instance""" - return ReviewPendingChanges() + return ReviewChanges() def test_tool_metadata(self, tool): """Test tool metadata""" - assert tool.get_name() == "review_pending_changes" + assert tool.get_name() == "review_changes" assert "REVIEW PENDING GIT CHANGES" in tool.get_description() assert "pre-commit review" in tool.get_description() @@ -37,7 +37,7 @@ class TestReviewPendingChangesTool: def test_request_model_defaults(self): """Test request model default values""" - request = ReviewPendingChangesRequest(path="/some/absolute/path") + request = ReviewChangesRequest(path="/some/absolute/path") assert request.path == "/some/absolute/path" assert request.original_request is None assert request.compare_to is None @@ -77,21 +77,21 @@ class TestReviewPendingChangesTool: assert "./relative/path" in response["content"] @pytest.mark.asyncio - @patch("tools.review_pending_changes.find_git_repositories") + @patch("tools.review_changes.find_git_repositories") async def test_no_repositories_found(self, mock_find_repos, tool): """Test when no git repositories are found""" mock_find_repos.return_value = [] - request = ReviewPendingChangesRequest(path="/absolute/path/no-git") + request = ReviewChangesRequest(path="/absolute/path/no-git") result = await tool.prepare_prompt(request) assert result == "No git repositories found in the specified path." mock_find_repos.assert_called_once_with("/absolute/path/no-git", 5) @pytest.mark.asyncio - @patch("tools.review_pending_changes.find_git_repositories") - @patch("tools.review_pending_changes.get_git_status") - @patch("tools.review_pending_changes.run_git_command") + @patch("tools.review_changes.find_git_repositories") + @patch("tools.review_changes.get_git_status") + @patch("tools.review_changes.run_git_command") async def test_no_changes_found( self, mock_run_git, mock_status, mock_find_repos, tool ): @@ -112,15 +112,15 @@ class TestReviewPendingChangesTool: (True, ""), # unstaged files (empty) ] - request = ReviewPendingChangesRequest(path="/absolute/repo/path") + request = ReviewChangesRequest(path="/absolute/repo/path") result = await tool.prepare_prompt(request) assert result == "No pending changes found in any of the git repositories." @pytest.mark.asyncio - @patch("tools.review_pending_changes.find_git_repositories") - @patch("tools.review_pending_changes.get_git_status") - @patch("tools.review_pending_changes.run_git_command") + @patch("tools.review_changes.find_git_repositories") + @patch("tools.review_changes.get_git_status") + @patch("tools.review_changes.run_git_command") async def test_staged_changes_review( self, mock_run_git, @@ -149,7 +149,7 @@ class TestReviewPendingChangesTool: (True, ""), # unstaged files (empty) ] - request = ReviewPendingChangesRequest( + request = ReviewChangesRequest( path="/absolute/repo/path", original_request="Add hello message", review_type="security", @@ -166,9 +166,9 @@ class TestReviewPendingChangesTool: assert "## Git Diffs" in result @pytest.mark.asyncio - @patch("tools.review_pending_changes.find_git_repositories") - @patch("tools.review_pending_changes.get_git_status") - @patch("tools.review_pending_changes.run_git_command") + @patch("tools.review_changes.find_git_repositories") + @patch("tools.review_changes.get_git_status") + @patch("tools.review_changes.run_git_command") async def test_compare_to_invalid_ref( self, mock_run_git, mock_status, mock_find_repos, tool ): @@ -181,7 +181,7 @@ class TestReviewPendingChangesTool: (False, "fatal: not a valid ref"), # rev-parse fails ] - request = ReviewPendingChangesRequest( + request = ReviewChangesRequest( path="/absolute/repo/path", compare_to="invalid-branch" ) result = await tool.prepare_prompt(request) @@ -190,7 +190,7 @@ class TestReviewPendingChangesTool: assert "No pending changes found in any of the git repositories." in result @pytest.mark.asyncio - @patch("tools.review_pending_changes.ReviewPendingChanges.execute") + @patch("tools.review_changes.ReviewChanges.execute") async def test_execute_integration(self, mock_execute, tool): """Test execute method integration""" # Mock the execute to return a standardized response @@ -212,9 +212,9 @@ class TestReviewPendingChangesTool: assert tool.get_default_temperature() == TEMPERATURE_ANALYTICAL @pytest.mark.asyncio - @patch("tools.review_pending_changes.find_git_repositories") - @patch("tools.review_pending_changes.get_git_status") - @patch("tools.review_pending_changes.run_git_command") + @patch("tools.review_changes.find_git_repositories") + @patch("tools.review_changes.get_git_status") + @patch("tools.review_changes.run_git_command") async def test_mixed_staged_unstaged_changes( self, mock_run_git, @@ -240,7 +240,7 @@ class TestReviewPendingChangesTool: (True, "diff --git a/file2.py..."), # diff for file2.py ] - request = ReviewPendingChangesRequest( + request = ReviewChangesRequest( path="/absolute/repo/path", focus_on="error handling", severity_filter="high", diff --git a/tests/test_server.py b/tests/test_server.py index 95ef86f..08e0038 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -25,7 +25,7 @@ class TestServerTools: assert "debug_issue" in tool_names assert "analyze" in tool_names assert "chat" in tool_names - assert "review_pending_changes" in tool_names + assert "review_changes" in tool_names assert "list_models" in tool_names assert "get_version" in tool_names diff --git a/tools/__init__.py b/tools/__init__.py index 10402ed..1d66a1b 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -6,7 +6,7 @@ from .analyze import AnalyzeTool from .chat import ChatTool from .debug_issue import DebugIssueTool from .review_code import ReviewCodeTool -from .review_pending_changes import ReviewPendingChanges +from .review_changes import ReviewChanges from .think_deeper import ThinkDeeperTool __all__ = [ @@ -15,5 +15,5 @@ __all__ = [ "DebugIssueTool", "AnalyzeTool", "ChatTool", - "ReviewPendingChanges", + "ReviewChanges", ] diff --git a/tools/base.py b/tools/base.py index c71b403..427be1f 100644 --- a/tools/base.py +++ b/tools/base.py @@ -86,7 +86,7 @@ class BaseTool(ABC): f"Please provide the full absolute path starting with '/'" ) - # Check if request has 'path' attribute (for review_pending_changes) + # Check if request has 'path' attribute (for review_changes) if hasattr(request, "path") and request.path: if not os.path.isabs(request.path): return ( diff --git a/tools/review_pending_changes.py b/tools/review_changes.py similarity index 96% rename from tools/review_pending_changes.py rename to tools/review_changes.py index 6916a5e..1cf1c64 100644 --- a/tools/review_pending_changes.py +++ b/tools/review_changes.py @@ -9,15 +9,15 @@ from typing import Any, Dict, Literal, Optional from pydantic import Field from config import MAX_CONTEXT_TOKENS -from prompts.tool_prompts import REVIEW_PENDING_CHANGES_PROMPT +from prompts.tool_prompts import REVIEW_CHANGES_PROMPT from utils.git_utils import find_git_repositories, get_git_status, run_git_command from utils.token_utils import estimate_tokens from .base import BaseTool, ToolRequest -class ReviewPendingChangesRequest(ToolRequest): - """Request model for review_pending_changes tool""" +class ReviewChangesRequest(ToolRequest): + """Request model for review_changes tool""" path: str = Field( ..., @@ -65,11 +65,11 @@ class ReviewPendingChangesRequest(ToolRequest): ) -class ReviewPendingChanges(BaseTool): - """Tool for reviewing pending git changes across multiple repositories.""" +class ReviewChanges(BaseTool): + """Tool for reviewing git changes across multiple repositories.""" def get_name(self) -> str: - return "review_pending_changes" + return "review_changes" def get_description(self) -> str: return ( @@ -86,10 +86,10 @@ class ReviewPendingChanges(BaseTool): return self.get_request_model().model_json_schema() def get_system_prompt(self) -> str: - return REVIEW_PENDING_CHANGES_PROMPT + return REVIEW_CHANGES_PROMPT def get_request_model(self): - return ReviewPendingChangesRequest + return ReviewChangesRequest def get_default_temperature(self) -> float: """Use analytical temperature for code review.""" @@ -106,7 +106,7 @@ class ReviewPendingChanges(BaseTool): # Limit length to avoid filesystem issues return name[:100] - async def prepare_prompt(self, request: ReviewPendingChangesRequest) -> str: + async def prepare_prompt(self, request: ReviewChangesRequest) -> str: """Prepare the prompt with git diff information.""" # Find all git repositories repositories = find_git_repositories(request.path, request.max_depth)