feat: add project-review workflow (whole-project / single-feature review)

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
This commit is contained in:
dev
2026-08-06 13:56:54 +08:00
parent 6f0e6f0775
commit 307d2fd471
45 changed files with 1339 additions and 131 deletions
+60
View File
@@ -0,0 +1,60 @@
"""Tests for the project-review workflow (whole-project / feature scope)."""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from fastmcp.prompts.prompt import Message # noqa: E402
from code_review_graph.prompts import project_review_prompt # noqa: E402
def _text(msg: Message) -> str:
return msg.content.text
class TestProjectReviewPromptRendering:
def test_whole_project_renders_full_workflow(self):
text = _text(project_review_prompt()[0])
# Header + shared steps 1-4 must all be present.
assert "## Project Review Workflow" in text
assert "scope=whole-project" in text
assert "1. Call" in text
assert "4. Locate high-risk" in text
# whole-project branch uses all_files=True.
assert "all_files=True" in text
assert "get_knowledge_gaps" in text
def test_feature_renders_feature_branch(self):
text = _text(project_review_prompt(scope="feature", target="checkout")[0])
assert "scope=feature" in text
assert "target=checkout" in text
# Shared steps 1-4 must still be present (no truncation).
assert "4. Locate high-risk" in text
# Feature branch: semantic search + impact radius, not all_files.
assert "semantic_search_nodes" in text
assert "get_impact_radius" in text
assert "all_files=True" not in text
def test_default_scope_is_whole_project(self):
text = _text(project_review_prompt()[0])
assert "scope=whole-project" in text
def test_read_only_present(self):
text = _text(project_review_prompt()[0])
assert "READ-ONLY" in text
def test_both_branches_have_preamble(self):
assert "get_minimal_context" in _text(project_review_prompt()[0])
assert "get_minimal_context" in _text(
project_review_prompt(scope="feature", target="auth")[0]
)
def test_both_branches_end_with_report_step(self):
whole = _text(project_review_prompt()[0])
feat = _text(project_review_prompt(scope="feature", target="x")[0])
assert "generate_report" in whole
assert "generate_report" in feat