feat: add unified-review workflow (scoring tools + skill)
Adds the unified-review integration that fuses CRG graph context with the ai-code-review scoring methodology and gstack-review fix-first workflow: - scoring.py: objective Layer-2 metrics (sql_risk, exception_coverage, redundancy_rate, high_risk_density, vulnerability_risk) with good/warn/fail grades, plus dedupe_findings (fingerprint merge, multi-source confidence boost, PR quality score) and report data builder - tools/scoring_tools.py + main.py: three new MCP tools (score_review_tool, dedupe_findings_tool, generate_report_tool) - assets/report-template.html: self-contained HTML report template - skills.py + skills/unified-review/: new read-only unified-review skill with language/manual-review/specialist checklists - docs and CHANGELOG updated; tests added (test_scoring, test_report, test_unified_review) and test_skills updated for 5 skills
This commit is contained in:
@@ -33,9 +33,11 @@ from .tools import (
|
||||
apply_refactor_func,
|
||||
build_or_update_graph,
|
||||
cross_repo_search_func,
|
||||
dedupe_findings_func,
|
||||
detect_changes_func,
|
||||
embed_graph,
|
||||
find_large_functions,
|
||||
generate_report_func,
|
||||
generate_wiki_func,
|
||||
get_affected_flows_func,
|
||||
get_architecture_overview_func,
|
||||
@@ -58,6 +60,7 @@ from .tools import (
|
||||
query_graph,
|
||||
refactor_func,
|
||||
run_postprocess,
|
||||
score_review_func,
|
||||
semantic_search_nodes,
|
||||
traverse_graph_func,
|
||||
with_provenance,
|
||||
@@ -686,6 +689,108 @@ async def detect_changes_tool(
|
||||
return await coro
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def score_review_tool(
|
||||
changed_files: Optional[list[str]] = None,
|
||||
base: str = "HEAD~1",
|
||||
include_churn: bool = True,
|
||||
repo_root: Optional[str] = None,
|
||||
detail_level: str = "standard",
|
||||
) -> dict:
|
||||
"""Compute objective Layer-2 review metrics for changed files.
|
||||
|
||||
Runs the git-history / graph risk factors plus the heuristic metrics
|
||||
(SQL risk, exception coverage, redundancy, high-risk density,
|
||||
vulnerability) that back the unified-review scoring. LLM-judged
|
||||
metrics (requirement coverage, logic alignment, trust boundaries) are
|
||||
reported in ``llm_judged`` for the calling agent to fill in.
|
||||
|
||||
Offloaded to a thread via ``asyncio.to_thread`` — runs `git log`
|
||||
subprocesses and graph queries that can take several seconds.
|
||||
|
||||
Args:
|
||||
changed_files: Files to score (auto-detected from git diff if
|
||||
omitted).
|
||||
base: Git ref to diff against. Default: HEAD~1.
|
||||
include_churn: Include git-churn risk factors. Default: True.
|
||||
repo_root: Repository root path. Auto-detected if omitted.
|
||||
detail_level: "standard" for full output, "minimal" for
|
||||
token-efficient summary. Default: standard.
|
||||
"""
|
||||
root = _resolve_repo_root(repo_root)
|
||||
|
||||
def _run() -> dict:
|
||||
return with_provenance(score_review_func(
|
||||
changed_files=changed_files, base=base,
|
||||
include_churn=include_churn, repo_root=root,
|
||||
detail_level=detail_level,
|
||||
), root)
|
||||
|
||||
return await asyncio.to_thread(_run)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def dedupe_findings_tool(
|
||||
findings: list,
|
||||
suppress_prior: Optional[list] = None,
|
||||
repo_root: Optional[str] = None,
|
||||
) -> dict:
|
||||
"""Merge review findings by fingerprint and boost multi-source confidence.
|
||||
|
||||
Findings with the same ``path:line:category`` fingerprint are merged
|
||||
(highest confidence wins); findings confirmed by more than one source
|
||||
(main review + specialist subagents) get confidence +1 (cap 10).
|
||||
Low-confidence findings are routed to the appendix or suppressed, and a
|
||||
PR quality score is computed as ``max(0, 10 - (critical*2 +
|
||||
informational*0.5))``.
|
||||
|
||||
Args:
|
||||
findings: Raw finding dicts with ``path``, ``category``,
|
||||
``severity``, ``confidence`` and optional ``source``/``line``.
|
||||
suppress_prior: Previously user-skipped findings (from a prior
|
||||
review-log) to suppress when their file has not changed.
|
||||
repo_root: Repository root path. Auto-detected if omitted.
|
||||
"""
|
||||
return dedupe_findings_func(
|
||||
findings=findings, suppress_prior=suppress_prior,
|
||||
repo_root=repo_root,
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def generate_report_tool(
|
||||
review_data: dict,
|
||||
output_path: Optional[str] = None,
|
||||
repo_root: Optional[str] = None,
|
||||
) -> dict:
|
||||
"""Generate a self-contained HTML code review report.
|
||||
|
||||
Injects ``review_data`` (output of ``score_review_tool`` plus
|
||||
``dedupe_findings_tool`` results and free-form verdict/tier/scope) into
|
||||
the bundled ``report-template.html`` as ``{{REPORT_DATA}}`` and writes
|
||||
the standalone file (default ``repo_root/code-review-report.html``).
|
||||
|
||||
Offloaded to a thread via ``asyncio.to_thread`` — rendering loads the
|
||||
template asset and writes the output file.
|
||||
|
||||
Args:
|
||||
review_data: Review data dict (metrics, findings, verdict, tier,
|
||||
scope, files, baseline, timestamp, manual_review).
|
||||
output_path: Output file path. Defaults to
|
||||
``<repo_root>/code-review-report.html``.
|
||||
repo_root: Repository root path. Auto-detected if omitted.
|
||||
"""
|
||||
root = _resolve_repo_root(repo_root)
|
||||
|
||||
def _run() -> dict:
|
||||
return with_provenance(generate_report_func(
|
||||
review_data=review_data, output_path=output_path,
|
||||
repo_root=root,
|
||||
), root)
|
||||
|
||||
return await asyncio.to_thread(_run)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def refactor_tool(
|
||||
mode: str = "rename",
|
||||
|
||||
Reference in New Issue
Block a user