Reviewer final reports must not claim proof-sensitive workflow steps unless each claim carries explicit command/tool evidence or structured MCP result metadata: - New reviewer_proof_backed_claims.py verifier covering the five claim families from the issue: inventory completeness (explicit pagination metadata required; page-size assumptions rejected), earlier-PR skips (per-PR command/tool or structured mergeability/blocker evidence), baseline validation (worktree path, target SHA, dirty-before, exact command, exact result, dirty-after), master integration (exact merge/rebase/simulation command), and cleanup (final git worktree list proof). - PROOF_PROVENANCE_CLASSES constant distinguishes command actually run, MCP metadata, inherited from previous blocker state, and not checked. - Re-export from review_proofs and wire into build_final_report as a downgrade check with proof_backed_claims_proven/violations fields. - New workflow section 30A documents the rule; contract test locks the marker and an export test locks the re-export. - 13 tests in tests/test_reviewer_proof_backed_claims.py covering the required scenarios: baseline claim without command, skipped-PR claim without evidence, inventory-complete from page-size assumption only, cleanup without final worktree proof, and a fully proof-backed report passing. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
186 lines
7.0 KiB
Python
186 lines
7.0 KiB
Python
"""Tests for proof-backed reviewer handoff claim verification (#395)."""
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from reviewer_proof_backed_claims import ( # noqa: E402
|
|
PROOF_PROVENANCE_CLASSES,
|
|
assess_proof_backed_handoff_report,
|
|
)
|
|
|
|
|
|
def _proof_backed_report():
|
|
"""A review report where every proof-sensitive claim carries evidence."""
|
|
return "\n".join(
|
|
[
|
|
"## Final Report",
|
|
"- Inventory complete: true (has_more=false, is_final_page=true,",
|
|
" inventory_complete=true, total_count=11) [proof: MCP metadata]",
|
|
"- Skipped PR #372: non-mergeable, mergeable: false via gitea_view_pr",
|
|
" re-fetch this session, head 202be15764c173b43e0a571a1ba04d8dbed5f646",
|
|
" [proof: command actually run]",
|
|
"- Baseline validation: baseline worktree branches/baseline-master-pr374,",
|
|
" baseline target SHA 7db8298cddbc18e885fb70c6415f3431333af4aa,",
|
|
" baseline dirty before: clean, command: venv/bin/pytest tests/ -q in",
|
|
" branches/baseline-master-pr374, result: 1290 passed 1 failed,",
|
|
" baseline dirty after: clean [proof: command actually run]",
|
|
"- Master integration: git merge --no-commit prgs/master in",
|
|
" branches/review-pr374, result: clean merge, aborted with",
|
|
" git merge --abort [proof: command actually run]",
|
|
"- Cleanup: session-owned worktrees removed; final git worktree list",
|
|
" shows no session-owned entries [proof: command actually run]",
|
|
]
|
|
)
|
|
|
|
|
|
class TestProofBackedReportPasses(unittest.TestCase):
|
|
def test_fully_proof_backed_report_passes(self):
|
|
result = assess_proof_backed_handoff_report(_proof_backed_report())
|
|
self.assertTrue(result["proven"], result["reasons"])
|
|
self.assertEqual(result["reasons"], [])
|
|
|
|
def test_report_without_proof_sensitive_claims_passes(self):
|
|
result = assess_proof_backed_handoff_report(
|
|
"## Final Report\n- Review decision: REQUEST_CHANGES\n- Blockers: tests fail"
|
|
)
|
|
self.assertTrue(result["proven"], result["reasons"])
|
|
|
|
|
|
class TestInventoryClaims(unittest.TestCase):
|
|
def test_inventory_complete_from_page_size_assumption_fails(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Inventory complete: 13 results were less than page size 50, so no"
|
|
" further pages were assumed.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("page size" in r.lower() for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
def test_inventory_complete_without_pagination_metadata_fails(self):
|
|
report = "## Final Report\n- Inventory complete: all open PRs listed.\n"
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("pagination" in r.lower() for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
def test_inventory_complete_with_metadata_passes(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Inventory complete: true (has_more=false, is_final_page=true,"
|
|
" inventory_complete=true, total_count=11)\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertTrue(result["proven"], result["reasons"])
|
|
|
|
|
|
class TestSkippedPrClaims(unittest.TestCase):
|
|
def test_skipped_pr_conflict_claim_without_evidence_fails(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Skipped PR #372 because it has merge conflicts.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("372" in r for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
def test_skipped_pr_with_structured_mergeability_evidence_passes(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Skipped PR #372: mergeable: false via gitea_view_pr re-fetch"
|
|
" this session.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertTrue(result["proven"], result["reasons"])
|
|
|
|
|
|
class TestBaselineClaims(unittest.TestCase):
|
|
def test_baseline_claim_without_command_fails(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Baseline validation confirmed the failures are pre-existing"
|
|
" on master.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("baseline" in r.lower() for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
def test_baseline_claim_missing_dirty_status_fails(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Baseline validation: baseline worktree branches/baseline-master-pr374,"
|
|
" baseline target SHA 7db8298cddbc18e885fb70c6415f3431333af4aa,"
|
|
" command: venv/bin/pytest tests/ -q, result: 1290 passed.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("dirty" in r.lower() for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
|
|
class TestIntegrationAndCleanupClaims(unittest.TestCase):
|
|
def test_master_integration_claim_without_exact_command_fails(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Master was merged into the review worktree before validation.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("integration" in r.lower() or "merge" in r.lower() for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
def test_cleanup_claim_without_final_worktree_proof_fails(self):
|
|
report = (
|
|
"## Final Report\n"
|
|
"- Cleanup: baseline and review worktrees were removed.\n"
|
|
)
|
|
result = assess_proof_backed_handoff_report(report)
|
|
self.assertFalse(result["proven"])
|
|
self.assertTrue(
|
|
any("worktree list" in r.lower() for r in result["reasons"]),
|
|
result["reasons"],
|
|
)
|
|
|
|
|
|
class TestProvenanceClasses(unittest.TestCase):
|
|
def test_provenance_classes_cover_required_distinctions(self):
|
|
self.assertEqual(
|
|
PROOF_PROVENANCE_CLASSES,
|
|
(
|
|
"command actually run",
|
|
"MCP metadata",
|
|
"inherited from previous blocker state",
|
|
"not checked",
|
|
),
|
|
)
|
|
|
|
|
|
class TestExports(unittest.TestCase):
|
|
def test_review_proofs_reexport(self):
|
|
from review_proofs import (
|
|
assess_proof_backed_handoff_report as exported,
|
|
)
|
|
|
|
self.assertTrue(callable(exported))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|