167 lines
6.8 KiB
Python
167 lines
6.8 KiB
Python
"""Tests for reviewer final-report schema verification (#391)."""
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from review_final_report_schema import assess_review_final_report_schema # noqa: E402
|
|
|
|
|
|
def _minimal_review_report(**overrides):
|
|
lines = [
|
|
"## Controller Handoff",
|
|
"",
|
|
"- Task: review PR #203",
|
|
"- Repo: Scaled-Tech-Consulting/Gitea-Tools",
|
|
"- Role: reviewer",
|
|
"- Identity: sysadmin / prgs-reviewer",
|
|
"- Issue/PR: #182 / PR #203",
|
|
"- Branch/SHA: feat/x @ 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
|
|
"- Files changed: review_proofs.py",
|
|
"- Validation: pass: pytest tests/test_review_proofs.py -q in branches/review-203",
|
|
"- Reviewed head SHA: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
|
|
"- Final live head SHA before approval: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
|
|
"- Final live head SHA before merge: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
|
|
"- Push occurred during validation: no",
|
|
"- Mutations: review only",
|
|
"- File edits by reviewer: none",
|
|
"- Worktree/index mutations: none",
|
|
"- Git ref mutations: git fetch prgs master",
|
|
"- MCP/Gitea mutations: review submitted",
|
|
"- Review mutations: request_changes submitted",
|
|
"- Merge mutations: none",
|
|
"- Cleanup mutations: none",
|
|
"- External-state mutations: none",
|
|
"- Read-only diagnostics: gitea_view_pr, gitea_view_issue",
|
|
"- Current status: PR open",
|
|
"- Next actor: author",
|
|
"- Next action: Fix",
|
|
"- Next prompt: Fix",
|
|
"- Blockers: none",
|
|
"- Next: await author",
|
|
"- Safety: no self-review; no self-merge",
|
|
"- Selected PR: #203",
|
|
"- Reviewer eligibility: eligible",
|
|
"- Candidate head SHA: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
|
|
"- Worktree path: branches/review-203",
|
|
"- Worktree dirty: clean",
|
|
"- Pinned reviewed head: none",
|
|
"- Scratch worktree used: none",
|
|
"- Unrelated local mutations: none",
|
|
"- Review decision: request_changes",
|
|
"- Merge result: not attempted",
|
|
"- Linked issue: #182",
|
|
"- Linked issue live status: open (gitea_view_issue)",
|
|
"- Cleanup status: none",
|
|
]
|
|
text = "\n".join(lines)
|
|
for key, value in overrides.items():
|
|
prefix = f"- {key}:"
|
|
replaced = False
|
|
new_lines = []
|
|
for line in text.splitlines():
|
|
if line.strip().startswith(prefix):
|
|
new_lines.append(f"{prefix} {value}")
|
|
replaced = True
|
|
else:
|
|
new_lines.append(line)
|
|
text = "\n".join(new_lines)
|
|
if not replaced:
|
|
text += f"\n{prefix} {value}"
|
|
return text
|
|
|
|
|
|
class TestReviewFinalReportSchema(unittest.TestCase):
|
|
def test_clean_report_passes(self):
|
|
result = assess_review_final_report_schema(
|
|
_minimal_review_report(),
|
|
linked_issue_lock={"issue_number": 182, "pr_number": 203},
|
|
)
|
|
self.assertFalse(result["blocked"])
|
|
self.assertIn(result["grade"], ("A", "downgraded"))
|
|
|
|
def test_legacy_pinned_reviewed_head_blocks(self):
|
|
report = _minimal_review_report(**{"Pinned reviewed head": "abc123"})
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.legacy_stale_field", rule_ids)
|
|
|
|
def test_reviewed_head_without_validation_blocks(self):
|
|
report = _minimal_review_report().replace(
|
|
"- Validation: pass: pytest tests/test_review_proofs.py -q in branches/review-203",
|
|
"- Validation: not run",
|
|
)
|
|
report += "\n- Pinned reviewed head: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9"
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.reviewed_head_without_validation", rule_ids)
|
|
|
|
def test_merged_without_proof_blocks(self):
|
|
report = _minimal_review_report() + "\n\nPR #203 merged successfully."
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.merged_without_proof", rule_ids)
|
|
|
|
def test_issue_closed_without_live_proof_blocks(self):
|
|
report = _minimal_review_report(
|
|
**{
|
|
"Linked issue live status": "closed",
|
|
"Read-only diagnostics": "gitea_view_pr only",
|
|
}
|
|
)
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.issue_closed_without_live_proof", rule_ids)
|
|
|
|
def test_full_suite_pass_with_ignored_tests_blocks(self):
|
|
report = (
|
|
_minimal_review_report()
|
|
+ "\nFull test suite passed with 0 failed; some tests ignored."
|
|
)
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.full_suite_pass_ignored_tests", rule_ids)
|
|
|
|
def test_blocked_handoff_replay_blocks(self):
|
|
report = (
|
|
_minimal_review_report(**{"Blockers": "capability stop"})
|
|
+ "\nSafe next action: run gitea_merge_pr to finish."
|
|
)
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.blocked_handoff_replay", rule_ids)
|
|
|
|
def test_narrative_handoff_drift_blocks(self):
|
|
report = (
|
|
_minimal_review_report()
|
|
+ "\n## Summary\nVerdict: APPROVE this PR."
|
|
)
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.narrative_handoff_drift", rule_ids)
|
|
|
|
def test_pending_vs_approved_blocks(self):
|
|
report = _minimal_review_report(
|
|
**{"Review decision": "PENDING official review submitted approve"}
|
|
)
|
|
result = assess_review_final_report_schema(report)
|
|
rule_ids = [f["rule_id"] for f in result["findings"]]
|
|
self.assertIn("reviewer.pending_vs_approved", rule_ids)
|
|
|
|
def test_exported_from_review_proofs(self):
|
|
from review_proofs import assess_review_final_report_schema as exported
|
|
|
|
self.assertTrue(callable(exported))
|
|
|
|
|
|
class TestMcpValidateReviewFinalReport(unittest.TestCase):
|
|
def test_mcp_tool_callable(self):
|
|
import gitea_mcp_server
|
|
|
|
result = gitea_mcp_server.gitea_validate_review_final_report(
|
|
_minimal_review_report()
|
|
)
|
|
self.assertIn("grade", result)
|
|
self.assertIn("findings", result)
|
|
self.assertFalse(result["blocked"]) |