Add assess_linked_issue_consistency to review_proofs: reviewer final reports must report a "Linked issue status" that matches the issue(s) the selected PR was live-verified to link this session. Without live proof the field may only say "not verified in this session"; with proof, every linked issue must be named, and any other "Issue #N" mention anywhere in the report fails as stale leakage from a previous PR (the PR #280 / Issue #260-vs-#275 incident). Missing field fails closed. Tests cover correct linked issue, stale previous issue in both the status field and diagnostics, missing proof, unverified wording, multiple linked issues, and PR-number mentions not being mistaken for issue mentions. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
119 lines
4.2 KiB
Python
119 lines
4.2 KiB
Python
"""Tests for linked-issue consistency verifier (#314).
|
|
|
|
Reviewer reports must verify the linked issue live for the selected PR;
|
|
stale issue numbers from a previous PR must not leak into the final
|
|
report, and linked-issue status must never be claimed without live proof.
|
|
"""
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from review_proofs import assess_linked_issue_consistency # noqa: E402
|
|
|
|
|
|
class TestCorrectLinkedIssue(unittest.TestCase):
|
|
def test_matching_linked_issue_passes(self):
|
|
report = (
|
|
"Selected PR: 280\n"
|
|
"Linked issue status: Issue #275 open, closes on merge\n"
|
|
)
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275]
|
|
)
|
|
self.assertTrue(result["complete"])
|
|
self.assertFalse(result["downgraded"])
|
|
self.assertEqual(result["reasons"], [])
|
|
|
|
def test_multiple_linked_issues_all_reported_passes(self):
|
|
report = (
|
|
"Linked issue status: Issue #275 and Issue #276 both open\n"
|
|
)
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275, 276]
|
|
)
|
|
self.assertTrue(result["complete"])
|
|
|
|
def test_multiple_linked_issues_one_missing_fails(self):
|
|
report = "Linked issue status: Issue #275 open\n"
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275, 276]
|
|
)
|
|
self.assertFalse(result["complete"])
|
|
self.assertTrue(
|
|
any("276" in r for r in result["reasons"])
|
|
)
|
|
|
|
|
|
class TestStaleIssueLeak(unittest.TestCase):
|
|
def test_stale_issue_in_status_field_fails(self):
|
|
# #314 observed behavior: PR #280 links Issue #275 but the report
|
|
# carries Issue #260 from the previous PR.
|
|
report = "Linked issue status: Issue #260 open\n"
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275]
|
|
)
|
|
self.assertFalse(result["complete"])
|
|
self.assertTrue(any("260" in r for r in result["reasons"]))
|
|
|
|
def test_stale_issue_in_diagnostics_fails(self):
|
|
report = (
|
|
"Linked issue status: Issue #275 open\n"
|
|
"Read-only diagnostics: viewed Issue #260 status\n"
|
|
)
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275]
|
|
)
|
|
self.assertFalse(result["complete"])
|
|
self.assertTrue(
|
|
any("stale" in r.lower() and "260" in r for r in result["reasons"])
|
|
)
|
|
|
|
def test_selected_pr_number_mention_is_not_stale(self):
|
|
# "PR #280" mentions must not be confused with issue mentions.
|
|
report = (
|
|
"Selected PR: 280\n"
|
|
"Validation: ran tests at PR #280 head\n"
|
|
"Linked issue status: Issue #275 open\n"
|
|
)
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275]
|
|
)
|
|
self.assertTrue(result["complete"])
|
|
|
|
|
|
class TestMissingProof(unittest.TestCase):
|
|
def test_status_claim_without_live_proof_fails(self):
|
|
report = "Linked issue status: Issue #275 open\n"
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=None
|
|
)
|
|
self.assertFalse(result["complete"])
|
|
self.assertTrue(
|
|
any("live proof" in r.lower() for r in result["reasons"])
|
|
)
|
|
|
|
def test_unverified_wording_without_proof_passes(self):
|
|
report = (
|
|
"Linked issue status: not verified in this session\n"
|
|
)
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=None
|
|
)
|
|
self.assertTrue(result["complete"])
|
|
|
|
def test_missing_field_fails(self):
|
|
report = "Selected PR: 280\n"
|
|
result = assess_linked_issue_consistency(
|
|
report, selected_pr=280, linked_issues=[275]
|
|
)
|
|
self.assertFalse(result["complete"])
|
|
self.assertTrue(
|
|
any("linked issue status" in r.lower() for r in result["reasons"])
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|