feat: require canonical next-action state comments (#495)

Add canonical issue/PR/discussion state comment templates and validators,
final-report rules for STATE/WHO_IS_NEXT/NEXT_ACTION/NEXT_PROMPT, and
queue-controller guidance. Posting enforcement remains in #496.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
2026-07-08 03:17:38 -04:00
co-authored by Claude Opus 4.8
parent 48cf3a334b
commit 9235f3a23c
8 changed files with 757 additions and 1 deletions
+86
View File
@@ -345,6 +345,92 @@ class TestReconciliationRules(unittest.TestCase):
)
class TestCanonicalStateUpdateRules(unittest.TestCase):
def test_claimed_state_comment_without_block_blocks(self):
report = _reconcile_handoff() + "\nPosted canonical state comment on PR #99."
result = assess_final_report_validator(report, "reconcile_already_landed")
self.assertTrue(result["blocked"])
self.assertTrue(
any(f["rule_id"] == "shared.canonical_state_update" for f in result["findings"])
)
def test_state_comment_missing_next_prompt_blocks(self):
report = (
_reconcile_handoff()
+ """
## Canonical PR State
STATE:
needs-review
WHO_IS_NEXT:
reviewer
NEXT_ACTION:
Review PR #99.
NEXT_PROMPT:
ISSUE:
#98
HEAD_SHA:
0fdc8f582026b72a229d59a172c0a63ac4aaeaf9
REVIEW_STATUS:
none
MERGE_READY:
no
"""
)
result = assess_final_report_validator(report, "reconcile_already_landed")
self.assertTrue(result["blocked"])
reasons = " ".join(f["reason"] for f in result["findings"])
self.assertIn("NEXT_PROMPT", reasons)
def test_valid_state_comment_claim_passes_shared_rule(self):
report = (
_reconcile_handoff()
+ """
## Canonical PR State
STATE:
needs-review
WHO_IS_NEXT:
reviewer
NEXT_ACTION:
Review PR #99 against the pinned head.
NEXT_PROMPT:
Load the review workflow and review PR #99.
ISSUE:
#98
HEAD_SHA:
0fdc8f582026b72a229d59a172c0a63ac4aaeaf9
REVIEW_STATUS:
none
MERGE_READY:
no
BLOCKERS:
none
"""
)
result = assess_final_report_validator(report, "reconcile_already_landed")
self.assertFalse(
any(f["rule_id"] == "shared.canonical_state_update" for f in result["findings"])
)
class TestCanonicalReconcileSchema(unittest.TestCase):
"""Issue #307: reconciliation workflows emit only the canonical schema."""