From 5c77065cfe1a93e83373fe59f5f55f4c22f98499 Mon Sep 17 00:00:00 2001 From: Wild Wind Date: Sun, 17 May 2026 18:48:41 -0700 Subject: [PATCH] Parse approved followup headings with colons --- src/coding_review_agent_loop/protocol.py | 6 ++--- tests/test_agent_loop.py | 28 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/coding_review_agent_loop/protocol.py b/src/coding_review_agent_loop/protocol.py index 27f9688..ece7f4b 100644 --- a/src/coding_review_agent_loop/protocol.py +++ b/src/coding_review_agent_loop/protocol.py @@ -11,9 +11,9 @@ PR_RE = re.compile(r"", re.I) GH_PR_URL_RE = re.compile(r"/pull/(\d+)(?:\b|$)") CLARIFY_RE = re.compile(r"", re.I) -SAME_PR_FOLLOWUP_HEADING_RE = re.compile(r"^\s*#{2,6}\s+same[- ]pr follow[- ]ups\s*$", re.I) -FUTURE_FOLLOWUP_HEADING_RE = re.compile(r"^\s*#{2,6}\s+future follow[- ]ups\s*$", re.I) -LEGACY_FOLLOWUP_HEADING_RE = re.compile(r"^\s*#{2,6}\s+non[- ]blocking follow[- ]ups\s*$", re.I) +SAME_PR_FOLLOWUP_HEADING_RE = re.compile(r"^\s*#{2,6}\s+same[- ]pr follow[- ]ups:?\s*$", re.I) +FUTURE_FOLLOWUP_HEADING_RE = re.compile(r"^\s*#{2,6}\s+future follow[- ]ups:?\s*$", re.I) +LEGACY_FOLLOWUP_HEADING_RE = re.compile(r"^\s*#{2,6}\s+non[- ]blocking follow[- ]ups:?\s*$", re.I) ANY_HEADING_RE = re.compile(r"^\s*#{1,6}\s+\S") HTML_COMMENT_RE = re.compile(r"^\s*\s*$") SIGNATURE_RE = re.compile(r"^\s*--\s+\S") diff --git a/tests/test_agent_loop.py b/tests/test_agent_loop.py index cf3d9a7..468303c 100644 --- a/tests/test_agent_loop.py +++ b/tests/test_agent_loop.py @@ -520,6 +520,34 @@ def test_parse_approved_followups_extracts_same_pr_and_future_independently(): ] +def test_parse_approved_followups_accepts_trailing_colons_on_headings(): + review = """ + LGTM with follow-ups. + + ### Same-PR follow-ups: + - Rename the helper for clarity. + + ### Future follow-ups: + - Add an integration fixture later. + + ### Non-blocking follow-ups: + - Legacy future item. + + + -- Google Gemini + """ + + followups = parse_approved_followups(review, reviewer="Gemini") + + assert [(item.reviewer, item.text) for item in followups.same_pr] == [ + ("Gemini", "Rename the helper for clarity.") + ] + assert [(item.reviewer, item.text) for item in followups.future] == [ + ("Gemini", "Add an integration fixture later."), + ("Gemini", "Legacy future item."), + ] + + @pytest.mark.parametrize( "placeholder", [