"""Tests for exact per-mutation capability proof in reviewer reports (#405).""" import sys import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from reviewer_mutation_capability_proof import assess_mutation_capability_proof from review_proofs import assess_mutation_capability_proof as proofs_assess from final_report_validator import assess_final_report_validator REVIEW_ONLY = """ Review decision: approved Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | resolved before review """ MERGE_PROVEN = """ Review decision: approved Merge result: merged 0123456789ab Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review - gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | resolved before merge """ MERGE_AND_DELETE_PROVEN = """ Review decision: approved Merge result: merged 0123456789ab Remote branch deleted: feat/issue-x Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review - gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | before merge - gitea_delete_branch | delete_branch (gitea.branch.delete) | deleted | before delete """ class TestModule(unittest.TestCase): def test_review_only_with_capability_passes(self): r = assess_mutation_capability_proof(REVIEW_ONLY) self.assertTrue(r["proven"], r["reasons"]) def test_merge_with_exact_capability_passes(self): r = assess_mutation_capability_proof(MERGE_PROVEN) self.assertTrue(r["proven"], r["reasons"]) def test_merge_and_delete_fully_proven_passes(self): r = assess_mutation_capability_proof(MERGE_AND_DELETE_PROVEN) self.assertTrue(r["proven"], r["reasons"]) def test_review_pr_does_not_authorize_merge(self): report = """ Review decision: approved Merge result: merged 0123456789ab Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review """ r = assess_mutation_capability_proof(report) self.assertFalse(r["proven"]) self.assertTrue(any("merge" in x.lower() for x in r["reasons"]), r["reasons"]) def test_merge_pr_does_not_authorize_branch_deletion(self): report = """ Review decision: approved Merge result: merged 0123456789ab Remote branch deleted: feat/issue-x Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review - gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | before merge """ r = assess_mutation_capability_proof(report) self.assertFalse(r["proven"]) self.assertTrue(any("delet" in x.lower() for x in r["reasons"]), r["reasons"]) def test_delete_skipped_when_capability_missing_passes(self): report = """ Review decision: approved Merge result: merged 0123456789ab Branch deletion: skipped — delete_branch capability not available Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review - gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | before merge """ r = assess_mutation_capability_proof(report) self.assertTrue(r["proven"], r["reasons"]) def test_missing_table_when_merging_blocks(self): report = """ Review decision: approved Merge result: merged 0123456789ab merge_pr gitea.pr.merge resolved """ r = assess_mutation_capability_proof(report) self.assertFalse(r["proven"]) self.assertTrue(any("table" in x.lower() for x in r["reasons"]), r["reasons"]) def test_post_hoc_proof_blocks(self): report = """ Review decision: approved Merge result: merged 0123456789ab Mutation capability table: - gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | capability resolved after merge """ r = assess_mutation_capability_proof(report) self.assertFalse(r["proven"]) self.assertTrue(any("after" in x.lower() for x in r["reasons"]), r["reasons"]) def test_review_without_capability_blocks(self): report = "Review decision: approved\nreview submitted\n" r = assess_mutation_capability_proof(report) self.assertFalse(r["proven"]) def test_no_mutation_no_requirement(self): r = assess_mutation_capability_proof("Selected PR: #1\nSkipped, no action.") self.assertTrue(r["proven"], r["reasons"]) class TestWiring(unittest.TestCase): def test_review_proofs_wrapper_matches_module(self): self.assertEqual( proofs_assess(MERGE_PROVEN)["proven"], assess_mutation_capability_proof(MERGE_PROVEN)["proven"], ) def test_final_report_validator_flags_nearby_capability_merge(self): report = """ ## Controller Handoff - Task: review_pr Review decision: approved Merge result: merged 0123456789ab Mutation capability table: - gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review """ result = assess_final_report_validator(report, "review_pr") rule_ids = [f["rule_id"] for f in result.get("findings", [])] self.assertIn("reviewer.mutation_capability_proof", rule_ids) if __name__ == "__main__": unittest.main()