feat(author): harden reporting and claim capability per #183

- Add 'mark_issue' to TASK_MAP in resolve_task_capability for exact mutation proof (closes gap on unknown treated as allowed).
- Add assess_controller_handoff and integrate into build_final_report (downgrades missing handoff).
- Add tests for handoff and update existing.
- Update SKILL.md and review-pr.md to mandate exact 'Controller Handoff' section, exact sweep evidence, PR head SHA in reports.
- Author profile used throughout; no review/merge.

Refs #183
This commit is contained in:
2026-07-05 15:35:32 -04:00
parent 601c608c58
commit 9ea2707289
4 changed files with 276 additions and 4 deletions
+135
View File
@@ -21,6 +21,7 @@ import unittest
sys.path.insert(0, str(__import__("pathlib").Path(__file__).resolve().parent.parent))
from review_proofs import ( # noqa: E402
assess_controller_handoff,
assess_inventory_completeness,
assess_self_review_contamination,
assess_validation_report,
@@ -314,6 +315,21 @@ class TestValidationReporting(unittest.TestCase):
)
self.assertEqual(result["verdict"], "strong")
def test_stdout_capture_fix_without_summary_is_weak(self):
result = _good_validation(
is_stdout_capture_fix=True,
normal_pytest_summary=False
)
self.assertEqual(result["verdict"], "weak")
self.assertTrue(any("stdout-capture" in r for r in result["reasons"]))
def test_stdout_capture_fix_with_summary_is_strong(self):
result = _good_validation(
is_stdout_capture_fix=True,
normal_pytest_summary=True
)
self.assertEqual(result["verdict"], "strong")
class TestSelfReviewContamination(unittest.TestCase):
"""Required behavior 5: contamination claims need evidence."""
@@ -380,6 +396,7 @@ class TestFinalReport(unittest.TestCase):
"identity_eligible": True,
"merge_performed": False,
"issue_status_verified": True,
"controller_handoff": "Controller Handoff\n- Task: test",
}
kwargs.update(overrides)
return build_final_report(**kwargs)
@@ -464,6 +481,24 @@ class TestFinalReport(unittest.TestCase):
self.assertNotEqual(report["grade"], "A")
self.assertFalse(report["merge_allowed"])
def test_failed_capability_proof_downgrades(self):
cap_proof = {
"proven": False,
"reasons": ["task mark_issue not allowed"]
}
report = self._report(capability_proof=cap_proof)
self.assertNotEqual(report["grade"], "A")
self.assertTrue(any("capability" in r for r in report["downgrade_reasons"]))
def test_failed_sweep_proof_downgrades(self):
sweep_proof = {
"proven": False,
"reasons": ["method missing"]
}
report = self._report(sweep_proof=sweep_proof)
self.assertNotEqual(report["grade"], "A")
self.assertTrue(any("sweep" in r for r in report["downgrade_reasons"]))
class TestStdoutIsolation(unittest.TestCase):
"""Regression test for #178: tests must not close or corrupt stdout/stderr
@@ -576,5 +611,105 @@ class TestRepoNameDisambiguation(unittest.TestCase):
self.assertTrue(result["can_claim_exhaustive"])
class TestControllerHandoff(unittest.TestCase):
"""#183: every final report must contain the Controller Handoff section."""
def test_report_with_handoff_passes(self):
report = "some details\n\nController Handoff\n- Task: foo"
result = assess_controller_handoff(report)
self.assertTrue(result["present"])
def test_report_without_handoff_downgrades(self):
report = "long details without the section"
result = assess_controller_handoff(report)
self.assertFalse(result["present"])
self.assertTrue(any("Controller Handoff" in r for r in result["reasons"]))
class TestAuthorReporting(unittest.TestCase):
"""Harness assertions for author reporting and capability/sweep proofs (#183)."""
def test_good_capability_proof_passes(self):
resolved = {
"mark_issue": {
"requested_task": "mark_issue",
"required_operation_permission": "gitea.issue.write",
"allowed_in_current_session": True,
}
}
result = assess_capability_proof(resolved)
self.assertTrue(result["proven"])
def test_missing_capability_proof_fails_closed(self):
result = assess_capability_proof({})
self.assertFalse(result["proven"])
self.assertTrue(any("fail closed" in r for r in result["reasons"]))
def test_unresolved_capability_proof_fails_closed(self):
# unknown task resolving to None/unknown requested task
resolved = {
"mark_issue": {
"requested_task": "unknown_task",
"required_operation_permission": None,
"allowed_in_current_session": None,
}
}
result = assess_capability_proof(resolved)
self.assertFalse(result["proven"])
self.assertTrue(any("could not be resolved" in r for r in result["reasons"]))
def test_good_secret_sweep_passes(self):
sweep = {
"method": "git diff | grep -iE 'token|secret'",
"scope": "staged diff relative to master",
"clean": True,
}
result = assess_secret_sweep(sweep)
self.assertTrue(result["proven"])
self.assertEqual(result["verdict"], "strong")
def test_vague_secret_sweep_without_method_is_weak(self):
sweep = {
"method": "",
"scope": "staged diff",
"clean": True,
}
result = assess_secret_sweep(sweep)
self.assertFalse(result["proven"])
self.assertEqual(result["verdict"], "weak")
self.assertTrue(any("method" in r or "scan" in r for r in result["reasons"]))
def test_unconfirmed_secret_sweep_is_invalid(self):
sweep = {
"method": "git diff | grep",
"scope": "staged diff",
"clean": False,
}
result = assess_secret_sweep(sweep)
self.assertFalse(result["proven"])
self.assertEqual(result["verdict"], "weak")
def test_good_author_pr_report_passes(self):
pr = {
"pr_number": 185,
"branch": "feat/issue-184-repo-name-disambiguation",
"head_sha": "e2bccbafeeb93124ba068bfb06058d5aa7467cae",
}
result = assess_author_pr_report(pr)
self.assertTrue(result["complete"])
def test_incomplete_author_pr_report_fails(self):
pr = {
"pr_number": 0,
"branch": "",
"head_sha": "e2bccba",
}
result = assess_author_pr_report(pr)
self.assertFalse(result["complete"])
self.assertTrue(any("number" in r for r in result["reasons"]))
self.assertTrue(any("branch" in r for r in result["reasons"]))
self.assertTrue(any("SHA" in r for r in result["reasons"]))
if __name__ == "__main__":
unittest.main()