diff --git a/CLAUDE.md b/CLAUDE.md index 47727eb..5dc62dd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,8 +18,8 @@ When using code-review-graph MCP tools, follow these rules: - `parser.py` — Tree-sitter multi-language AST parser plus targeted fallbacks for broad source-language and notebook support - `custom_languages.py` — Config-driven custom language support (`.code-review-graph/languages.toml`, see docs/CUSTOM_LANGUAGES.md) - `graph.py` — SQLite-backed graph store (nodes, edges, weighted-score impact analysis) - - `tools/` — 30 MCP tool implementations split by domain - - `main.py` — FastMCP server entry point, registers 30 tools + 5 prompts + - `tools/` — 31 MCP tool implementations split by domain + - `main.py` — FastMCP server entry point, registers 31 tools + 6 prompts - `incremental.py` — Git-based change detection, file watching - `embeddings.py` — Optional vector embeddings (local sentence-transformers, OpenAI-compatible endpoints, Google Gemini, MiniMax) - `visualization.py` — D3.js interactive HTML graph generator @@ -30,7 +30,7 @@ When using code-review-graph MCP tools, follow these rules: - `changes.py` — Risk-scored change impact analysis (detect-changes) - `refactor.py` — Rename preview, dead code detection, refactoring suggestions - `hints.py` — Review hint generation - - `prompts.py` — 5 MCP prompt templates (review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check) + - `prompts.py` — 6 MCP prompt templates (review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check, unified_review) - `wiki.py` — Markdown wiki generation from community structure - `skills.py` — Multi-platform install/config generation and shipped skill metadata - `registry.py` — Multi-repo registry helpers diff --git a/README.hi-IN.md b/README.hi-IN.md index b6d3fc7..303b155 100644 --- a/README.hi-IN.md +++ b/README.hi-IN.md @@ -253,8 +253,8 @@ code-review-graph serve # MCP सर्वर शुरू करे | `list_repos_tool` | रजिस्टर्ड रिपॉज़िटरीज़ की सूची | | `cross_repo_search_tool` | सभी रजिस्टर्ड रिपॉज़िटरीज़ में सर्च करें | -**MCP प्रॉम्प्ट्स** (5 वर्कफ़्लो टेम्प्लेट): -`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check` +**MCP प्रॉम्प्ट्स** (6 वर्कफ़्लो टेम्प्लेट): +`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check`, `unified_review` diff --git a/README.ja-JP.md b/README.ja-JP.md index 9f95454..d036d88 100644 --- a/README.ja-JP.md +++ b/README.ja-JP.md @@ -255,8 +255,8 @@ code-review-graph serve # MCPサーバーの起動 | `list_repos_tool` | 登録済みリポジトリの一覧 | | `cross_repo_search_tool` | 全登録リポジトリを横断検索 | -**MCPプロンプト**(5つのワークフローテンプレート): -`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check` +**MCPプロンプト**(6つのワークフローテンプレート): +`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check`, `unified_review` diff --git a/README.ko-KR.md b/README.ko-KR.md index 1775350..62bb4c9 100644 --- a/README.ko-KR.md +++ b/README.ko-KR.md @@ -255,8 +255,8 @@ code-review-graph serve # MCP 서버 시작 | `list_repos_tool` | 등록된 저장소 목록 | | `cross_repo_search_tool` | 등록된 모든 저장소에서 검색 | -**MCP 프롬프트** (5개 워크플로 템플릿): -`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check` +**MCP 프롬프트** (6개 워크플로 템플릿): +`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check`, `unified_review` diff --git a/README.md b/README.md index 2bb6ae4..c755e83 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,7 @@ The benchmark also runs an honest **co-change mode**: the predictor is seeded wi | **Wiki generation** | Auto-generate markdown wiki from community structure | | **Multi-repo registry** | Register multiple repos, search across all of them | | **Multi-repo daemon** | `crg-daemon` watches multiple repos as child processes, with health checks and auto-restart | -| **MCP prompts** | 5 workflow templates: review, architecture, debug, onboard, pre-merge | +| **MCP prompts** | 6 workflow templates: review, architecture, debug, onboard, pre-merge, unified-review | | **Full-text search** | FTS5-powered hybrid search combining keyword and vector similarity | | **Local storage** | SQLite file in `.code-review-graph/`. Core graph storage needs no external database or cloud service. | | **Watch mode** | Continuous graph updates as you work | @@ -462,7 +462,7 @@ full config reference and all available options.
-30 MCP tools +31 MCP tools
Your AI assistant uses these automatically once the graph is built. @@ -499,9 +499,12 @@ Your AI assistant uses these automatically once the graph is built. | `get_wiki_page_tool` | Retrieve a specific wiki page | | `list_repos_tool` | List registered repositories | | `cross_repo_search_tool` | Search across all registered repositories | +| `score_review_tool` | Objective Layer-2 review metrics (good/warn/fail grades) | +| `dedupe_findings_tool` | Fingerprint dedup + multi-source confidence merge | +| `generate_report_tool` | Render the standalone HTML code review report | -**MCP Prompts** (5 workflow templates): -`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check` +**MCP Prompts** (6 workflow templates): +`review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check`, `unified_review`
@@ -611,7 +614,7 @@ code-review-graph embed --provider voyage --model voyage-code-3 #### Tool Filtering -CRG exposes 30 MCP tools by default. In token-constrained environments, you can +CRG exposes 31 MCP tools by default. In token-constrained environments, you can limit the server to a subset of tools using `--tools` or the `CRG_TOOLS` environment variable: diff --git a/README.zh-CN.md b/README.zh-CN.md index 0a67b59..84eb60f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -253,8 +253,8 @@ code-review-graph serve # 启动 MCP 服务器 | `list_repos_tool` | 列出已注册的仓库 | | `cross_repo_search_tool` | 跨所有注册仓库搜索 | -**MCP 提示模板**(5 种工作流模板): -`review_changes`、`architecture_map`、`debug_issue`、`onboard_developer`、`pre_merge_check` +**MCP 提示模板**(6 种工作流模板): +`review_changes`、`architecture_map`、`debug_issue`、`onboard_developer`、`pre_merge_check`、`unified_review` diff --git a/code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md b/code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md index e3e27d7..22929dd 100644 --- a/code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md +++ b/code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md @@ -35,7 +35,7 @@ score_review_tool returns objective metrics (sql_risk, exception_coverage, redun
Core MCP tools: get_minimal_context_tool, detect_changes_tool, get_review_context_tool, get_impact_radius_tool, query_graph_tool, semantic_search_nodes_tool, get_architecture_overview_tool, get_affected_flows_tool, list_flows_tool, list_communities_tool, refactor_tool, build_or_update_graph_tool, run_postprocess_tool, embed_graph_tool, list_graph_stats_tool, get_docs_section_tool Unified-review MCP tools: score_review_tool, dedupe_findings_tool, generate_report_tool -MCP prompts (5): review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check +MCP prompts (6): review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check, unified_review Skills: build-graph, debug-issue, explore-codebase, refactor-safely, review-changes, review-delta, review-pr, unified-review CLI: code-review-graph [install|init|build|update|status|watch|visualize|serve|mcp|wiki|detect-changes|postprocess|embed|register|unregister|repos|eval|daemon] Token efficiency: Prefer detail_level="minimal" where available. Always call get_minimal_context_tool first. Some review/context tools return compact estimated context_savings metadata. diff --git a/code_review_graph/main.py b/code_review_graph/main.py index a3e4e1d..0f2b518 100644 --- a/code_review_graph/main.py +++ b/code_review_graph/main.py @@ -28,6 +28,7 @@ from .prompts import ( onboard_developer_prompt, pre_merge_check_prompt, review_changes_prompt, + unified_review_prompt, ) from .tools import ( apply_refactor_func, @@ -1124,6 +1125,21 @@ def pre_merge_check(base: str = "HEAD~1") -> list[dict]: return pre_merge_check_prompt(base=base) +@mcp.prompt() +def unified_review(base: str = "HEAD~1", tier: str = "standard") -> list[dict]: + """Three-layer unified review (CRG graph context + scoring + dedupe + report). + + Fuses graph context with the objective scoring metrics, finding merge, + and the standalone HTML report. READ-ONLY: every finding waits for a + manual fix decision. + + Args: + base: Git ref to diff against. Default: HEAD~1. + tier: Review tier (fast / standard / strict). Default: standard. + """ + return unified_review_prompt(base=base, tier=tier) + + def _apply_tool_filter(tools: str | None = None) -> None: """Remove tools not listed in the allow-list. diff --git a/code_review_graph/prompts.py b/code_review_graph/prompts.py index 455a4e6..d7b2742 100644 --- a/code_review_graph/prompts.py +++ b/code_review_graph/prompts.py @@ -1,6 +1,6 @@ """MCP prompt templates for Code Review Graph. -Provides 5 pre-built prompt workflows, all enforcing token-efficient +Provides 6 pre-built prompt workflows, all enforcing token-efficient detail_level="minimal" first patterns with get_minimal_context entry point. 1. review_changes - pre-commit review using detect_changes + affected_flows @@ -8,6 +8,7 @@ detail_level="minimal" first patterns with get_minimal_context entry point. 3. debug_issue - guided debugging using search, flow tracing 4. onboard_developer - new dev orientation using stats, architecture, flows 5. pre_merge_check - PR readiness with risk scoring, test gaps, dead code +6. unified_review - three-layer review: graph context + scoring + dedupe + report """ from __future__ import annotations @@ -157,3 +158,60 @@ def pre_merge_check_prompt(base: str = "HEAD~1") -> list[Message]: "7. Output: GO/NO-GO recommendation with 1-sentence " "justification + list of required follow-ups." ) + + +def unified_review_prompt( + base: str = "HEAD~1", + tier: str = "standard", +) -> list[Message]: + """Three-layer unified review workflow (READ-ONLY). + + Fuses CRG graph context with the objective scoring metrics + (score_review), finding merge (dedupe_findings), and the standalone + HTML report (generate_report). Every finding is presented for a manual + fix decision -- this workflow never modifies code. + + Args: + base: Git ref to diff against. Default: HEAD~1. + tier: Review tier. "fast" (Layer 1 + blockers only), + "standard" (all layers), "strict" (full + per-item + confirmation). Default: standard. + """ + tier_notes = { + "fast": ( + "fast tier: run Layers 1 and the blocker check only; " + "skip Layer 2 metrics and the report." + ), + "strict": ( + "strict tier: full review; every blocker and major finding " + "needs per-item user confirmation before it is recorded." + ), + }.get(tier, "standard tier: run all layers.") + return _user( + f"{_TOKEN_EFFICIENCY_PREAMBLE}\n" + f"## Unified Review Workflow (base={base}, tier={tier})\n" + f"{tier_notes}\n" + "**READ-ONLY.** Present every finding for a manual fix decision. " + "Never modify code, commit, or push.\n" + '1. Call `get_minimal_context(task="unified review")` for the ' + "risk overview.\n" + '2. Call `build_or_update_graph()` to ensure the graph is ' + "current.\n" + '3. Call `detect_changes(detail_level="minimal")` for changed ' + "files, risk score, test gaps and affected flows.\n" + '4. Call `score_review(detail_level="standard")` for the ' + "objective metrics (sql_risk, exception_coverage, redundancy, " + "high-risk density, vulnerability). Trust the tool grades; " + "LLM-judged metrics are in `llm_judged`.\n" + "5. Review the changed source (Layer 1 chain decomposition) and " + "produce findings with severity (blocker/major/minor), " + "confidence (1-10), file:line and a proposed fix.\n" + '6. Call `dedupe_findings(findings=)` to merge ' + "by fingerprint, boost multi-source confidence and compute the " + "PR quality score.\n" + '7. Call `generate_report(review_data=)` to write code-review-report.html.\n' + "8. Output: verdict (✅ PASS / ❌ FAIL), severity counts, each " + "issue with confidence + fix, and the manual-review items. " + "Any blocker → verdict ❌ FAIL." + ) diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index 4b5dc20..f15e927 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -310,7 +310,7 @@ kind: str | None limit: int = 20 ``` -## MCP Prompts (5 workflow templates) +## MCP Prompts (6 workflow templates) ### `review_changes` Pre-commit review workflow using detect_changes, affected_flows, and test gaps. @@ -336,6 +336,16 @@ PR readiness check with risk scoring, test gaps, and dead code detection. base: str = "HEAD~1" ``` +### `unified_review` +Three-layer unified review: CRG graph context + objective scoring +(`score_review`), finding merge (`dedupe_findings`), and the standalone +HTML report (`generate_report`). READ-ONLY: every finding waits for a +manual fix decision. +``` +base: str = "HEAD~1" +tier: str = "standard" # fast | standard | strict +``` + ## CLI Commands ```bash diff --git a/docs/INDEX.md b/docs/INDEX.md index 06562d3..4a6d0da 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -3,7 +3,7 @@ - [USAGE.md](USAGE.md) -- How to install and use - [FAQ.md](FAQ.md) -- How it compares to LSP, RAG, grep, and similar tools; when not to use it - [FEATURES.md](FEATURES.md) -- What's included, changelog -- [COMMANDS.md](COMMANDS.md) -- All 30 MCP tools, 5 MCP prompts, skills, and CLI commands +- [COMMANDS.md](COMMANDS.md) -- All 31 MCP tools, 6 MCP prompts, skills, and CLI commands - [GITHUB_ACTION.md](GITHUB_ACTION.md) -- Risk-scored PR review comments via GitHub Actions - [CUSTOM_LANGUAGES.md](CUSTOM_LANGUAGES.md) -- Bring your own language via `.code-review-graph/languages.toml` - [LLM-OPTIMIZED-REFERENCE.md](../code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md) -- Token-optimized reference for MCP-capable AI coding agents diff --git a/docs/architecture.md b/docs/architecture.md index c3cf056..5a3bd4d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -20,7 +20,7 @@ │ ┌────────────────────────────────────────────┐ │ │ │ MCP Server (stdio or localhost HTTP) │ │ │ │ │ │ -│ │ 30 MCP Tools + 5 MCP Prompts │ │ +│ │ 31 MCP Tools + 6 MCP Prompts │ │ │ │ ├── Core: build, impact, query, review, │ │ │ │ │ search, traverse, embed, stats, docs │ │ │ │ ├── Flows: list, get, affected │ │ diff --git a/tests/test_prompts.py b/tests/test_prompts.py index 1714342..856eb46 100644 --- a/tests/test_prompts.py +++ b/tests/test_prompts.py @@ -8,6 +8,7 @@ from code_review_graph.prompts import ( onboard_developer_prompt, pre_merge_check_prompt, review_changes_prompt, + unified_review_prompt, ) @@ -167,6 +168,52 @@ class TestPreMergeCheckPrompt: assert "dead_code" in _text(result[0]) +class TestUnifiedReviewPrompt: + def test_returns_list_with_messages(self): + result = unified_review_prompt() + assert isinstance(result, list) + assert len(result) >= 1 + + def test_message_has_role_and_content(self): + result = unified_review_prompt() + for msg in result: + assert isinstance(msg, Message) + assert msg.role == "user" + assert _text(msg) + + def test_default_base_and_tier(self): + result = unified_review_prompt() + text = _text(result[0]) + assert "HEAD~1" in text + assert "standard tier" in text + + def test_custom_base_and_tier(self): + result = unified_review_prompt(base="develop", tier="strict") + text = _text(result[0]) + assert "base=develop" in text + assert "strict tier" in text + + def test_mentions_score_review(self): + result = unified_review_prompt() + assert "score_review" in _text(result[0]) + + def test_mentions_dedupe_findings(self): + result = unified_review_prompt() + assert "dedupe_findings" in _text(result[0]) + + def test_mentions_generate_report(self): + result = unified_review_prompt() + assert "generate_report" in _text(result[0]) + + def test_mentions_read_only(self): + result = unified_review_prompt() + assert "READ-ONLY" in _text(result[0]) + + def test_mentions_blocker_rule(self): + result = unified_review_prompt() + assert "FAIL" in _text(result[0]) + + class TestTokenEfficiencyPreamble: """All prompts should include the token efficiency preamble.""" @@ -190,3 +237,7 @@ class TestTokenEfficiencyPreamble: def test_pre_merge_has_preamble(self): result = pre_merge_check_prompt() assert "get_minimal_context" in _text(result[0]) + + def test_unified_review_has_preamble(self): + result = unified_review_prompt() + assert "get_minimal_context" in _text(result[0])