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
+29
View File
@@ -31,6 +31,19 @@ class TestToolRegistration:
):
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):
@@ -61,7 +74,23 @@ class TestGenerateSkills:
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()