feat: prove inventory pagination and worktree state in reviewer reports (#293)
Add assess_inventory_worktree_report verifier to reject partial PR inventory claims, exactly-full first pages without finality proof, legacy scratch-worktree flags that contradict branches/ review worktrees, and contradictory checkout wording. Wire into build_final_report and export from review_proofs. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
@@ -140,3 +140,9 @@ def test_non_mergeable_skip_verifier_exported():
|
||||
from review_proofs import assess_non_mergeable_skip_proof
|
||||
|
||||
assert callable(assess_non_mergeable_skip_proof)
|
||||
|
||||
|
||||
def test_inventory_worktree_verifier_exported():
|
||||
from review_proofs import assess_inventory_worktree_report
|
||||
|
||||
assert callable(assess_inventory_worktree_report)
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
"""Tests for reviewer inventory/worktree verifier (#293)."""
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from reviewer_inventory_worktree import assess_inventory_worktree_report # noqa: E402
|
||||
|
||||
|
||||
def _good_handoff() -> str:
|
||||
return "\n".join([
|
||||
"## Controller Handoff",
|
||||
"- Selected PR: 280",
|
||||
"- Inventory pagination proof: is_final_page: true, has_more: false, total_count: 6",
|
||||
"- Review worktree used: true",
|
||||
"- Review worktree path: branches/review-pr280-feat-issue-275-claim",
|
||||
"- Review worktree inside branches: true",
|
||||
"- Review worktree HEAD state: detached",
|
||||
"- Main checkout branch: master",
|
||||
"- Current status: reviewed PR #280",
|
||||
])
|
||||
|
||||
|
||||
class TestInventoryPaginationProof(unittest.TestCase):
|
||||
def test_no_next_page_proof_passes(self):
|
||||
result = assess_inventory_worktree_report(_good_handoff())
|
||||
self.assertTrue(result["proven"], result["reasons"])
|
||||
self.assertTrue(result["pagination_proven"])
|
||||
|
||||
def test_rejects_partial_first_page_eligibility_claim(self):
|
||||
report = "\n".join([
|
||||
"Oldest eligible PR is #280.",
|
||||
"gitea_list_prs returned 10 open PRs on the first page.",
|
||||
"## Controller Handoff",
|
||||
"- Inventory pagination proof: first page only",
|
||||
])
|
||||
result = assess_inventory_worktree_report(report)
|
||||
self.assertFalse(result["proven"])
|
||||
self.assertTrue(result["block"])
|
||||
self.assertTrue(any("eligible" in r.lower() for r in result["reasons"]))
|
||||
|
||||
def test_rejects_default_page_size_assumption(self):
|
||||
report = (
|
||||
"Inventory exhaustive because fewer than the default Gitea page size "
|
||||
"were returned."
|
||||
)
|
||||
result = assess_inventory_worktree_report(report)
|
||||
self.assertFalse(result["proven"])
|
||||
self.assertTrue(any("page size" in r.lower() for r in result["reasons"]))
|
||||
|
||||
def test_rejects_exactly_full_first_page_without_finality(self):
|
||||
report = "\n".join([
|
||||
"Next eligible PR: #290 based on complete inventory.",
|
||||
"gitea_list_prs returned 50 open PRs.",
|
||||
"## Controller Handoff",
|
||||
"- Inventory pagination proof: returned 50 open PRs",
|
||||
])
|
||||
result = assess_inventory_worktree_report(
|
||||
report,
|
||||
inventory_session={"requested_page_size": 50, "returned_page_size": 50},
|
||||
)
|
||||
self.assertFalse(result["proven"])
|
||||
self.assertTrue(any("full first page" in r.lower() for r in result["reasons"]))
|
||||
|
||||
def test_allows_exact_page_with_session_pagination_complete(self):
|
||||
report = "Oldest eligible PR: #12 after queue inventory."
|
||||
result = assess_inventory_worktree_report(
|
||||
report,
|
||||
inventory_session={"pagination_complete": True},
|
||||
)
|
||||
self.assertTrue(result["proven"], result["reasons"])
|
||||
|
||||
|
||||
class TestWorktreeConsistency(unittest.TestCase):
|
||||
def test_branches_worktree_requires_review_worktree_used_true(self):
|
||||
report = "\n".join([
|
||||
"## Controller Handoff",
|
||||
"- Inventory pagination proof: is_final_page: true",
|
||||
"- Review worktree used: false",
|
||||
"- Review worktree path: branches/review-pr280-feat",
|
||||
"- Scratch worktree used: false",
|
||||
])
|
||||
result = assess_inventory_worktree_report(report)
|
||||
self.assertFalse(result["proven"])
|
||||
joined = " ".join(result["reasons"]).lower()
|
||||
self.assertIn("review worktree used", joined)
|
||||
self.assertIn("scratch worktree", joined)
|
||||
|
||||
def test_rejects_contradictory_detached_and_branch_wording(self):
|
||||
report = "\n".join([
|
||||
"Checkout: Detached HEAD / Branch master",
|
||||
"## Controller Handoff",
|
||||
"- Inventory pagination proof: is_final_page: true",
|
||||
"- Review worktree used: true",
|
||||
"- Review worktree path: branches/review-pr280-feat",
|
||||
"- Review worktree HEAD state: detached",
|
||||
"- Main checkout branch: master",
|
||||
])
|
||||
result = assess_inventory_worktree_report(report)
|
||||
self.assertFalse(result["proven"])
|
||||
self.assertTrue(
|
||||
any("contradictory" in r.lower() for r in result["reasons"])
|
||||
)
|
||||
|
||||
def test_requires_head_state_when_review_worktree_used(self):
|
||||
report = "\n".join([
|
||||
"## Controller Handoff",
|
||||
"- Inventory pagination proof: pagination_complete: true",
|
||||
"- Review worktree used: true",
|
||||
"- Review worktree path: branches/review-pr280-feat",
|
||||
])
|
||||
result = assess_inventory_worktree_report(report)
|
||||
self.assertFalse(result["proven"])
|
||||
self.assertTrue(any("head state" in r.lower() for r in result["reasons"]))
|
||||
|
||||
|
||||
class TestExport(unittest.TestCase):
|
||||
def test_review_proofs_reexport(self):
|
||||
from review_proofs import assess_inventory_worktree_report as exported
|
||||
|
||||
self.assertTrue(callable(exported))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user