Adds the project-review workflow for code review independent of the git diff. The scope is parsed from the user instruction: 全面/整个项目 -> whole-project (score every source file), otherwise feature + target keyword (locate the code with semantic search + graph queries). - scoring_tools.py: score_review_func gains all_files=True to score every source file in the graph via store.get_all_files() - main.py: score_review_tool gains all_files param; registers the project_review MCP prompt (prompts 6->7) - prompts.py: project_review_prompt(scope, target) with whole-project and feature branches (fixed a precedence bug that truncated the feature text) - skills.py + skills/project-review/: new read-only project-review skill with shared checklists - .opencode/command/code-review-graph-project-review.md: slash command - tests: test_project_review.py (prompt rendering), TestProjectReviewPrompt, skill count assertions 5->6, all_files wiring checks - docs: prompts (6->7) + project-review entries across COMMANDS, CLAUDE, README (+localized), INDEX, architecture, LLM-OPTIMIZED-REFERENCE, CHANGELOG
97 lines
3.1 KiB
Python
97 lines
3.1 KiB
Python
"""Tests for unified-review MCP tool wiring (registration + docs sections)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from code_review_graph.tools import ( # noqa: E402
|
|
dedupe_findings_func,
|
|
generate_report_func,
|
|
score_review_func,
|
|
)
|
|
from code_review_graph.tools.docs import get_docs_section # noqa: E402
|
|
|
|
|
|
class TestToolRegistration:
|
|
def test_scoring_funcs_exported(self):
|
|
assert callable(score_review_func)
|
|
assert callable(dedupe_findings_func)
|
|
assert callable(generate_report_func)
|
|
|
|
def test_mcp_tools_exposed(self):
|
|
import code_review_graph.main as m
|
|
|
|
for name in (
|
|
"score_review_tool",
|
|
"dedupe_findings_tool",
|
|
"generate_report_tool",
|
|
):
|
|
assert hasattr(m, name), f"{name} not exposed by main module"
|
|
|
|
def test_project_review_prompt_exposed(self):
|
|
import code_review_graph.main as m
|
|
|
|
assert hasattr(m, "project_review"), "project_review prompt not exposed"
|
|
|
|
def test_score_review_has_all_files_param(self):
|
|
import inspect
|
|
|
|
import code_review_graph.main as m
|
|
|
|
sig = inspect.signature(m.score_review_tool)
|
|
assert "all_files" in sig.parameters
|
|
|
|
|
|
class TestDocsSections:
|
|
def test_unified_review_section(self):
|
|
result = get_docs_section("unified-review")
|
|
assert result["status"] == "ok"
|
|
assert "score_review_tool" in result["content"]
|
|
|
|
def test_score_review_section(self):
|
|
result = get_docs_section("score-review")
|
|
assert result["status"] == "ok"
|
|
assert "dedupe_findings_tool" in result["content"]
|
|
|
|
def test_unknown_section(self):
|
|
result = get_docs_section("does-not-exist")
|
|
assert result["status"] == "not_found"
|
|
assert "unified-review" in result["error"]
|
|
|
|
|
|
class TestGenerateSkills:
|
|
def test_unified_review_generated(self, tmp_path):
|
|
from code_review_graph.skills import generate_skills
|
|
|
|
skills_dir = generate_skills(tmp_path)
|
|
skill_file = skills_dir / "unified-review" / "SKILL.md"
|
|
assert skill_file.is_file()
|
|
content = skill_file.read_text(encoding="utf-8")
|
|
assert "score_review_tool" in content
|
|
assert "get_minimal_context" in content
|
|
assert "detail_level" in content
|
|
|
|
def test_project_review_generated(self, tmp_path):
|
|
from code_review_graph.skills import generate_skills
|
|
|
|
skills_dir = generate_skills(tmp_path)
|
|
skill_file = skills_dir / "project-review" / "SKILL.md"
|
|
assert skill_file.is_file()
|
|
content = skill_file.read_text(encoding="utf-8")
|
|
assert "all_files=True" in content
|
|
assert "get_minimal_context" in content
|
|
assert "detail_level" in content
|
|
|
|
def test_uninstall_knows_unified_review(self):
|
|
from code_review_graph.uninstall import _generated_skill_slugs
|
|
|
|
assert "unified-review" in _generated_skill_slugs()
|
|
|
|
def test_uninstall_knows_project_review(self):
|
|
from code_review_graph.uninstall import _generated_skill_slugs
|
|
|
|
assert "project-review" in _generated_skill_slugs()
|