Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/cursor-review/build-ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,37 @@ def _load_gate_unresolved():
# post-review.py renders every inline finding as "<emoji> **<Label>** β€” <body>".
# Recovering the severity from that badge is reading back our own structured
# rendering, not inferring a disposition from author prose.
#
# The vocabulary and the badge's shape are re-typed here as literals, NOT shared with
# post-review.py's SEVERITY_LABEL/SEVERITY_EMOJI. `^\S*` swallows ANY leading run of
# non-whitespace β€” today's emoji, one this version has never seen, or none at all β€” so
# the ledger keeps parsing bodies written by an OLDER post-review.py still live on a
# pinned caller ref; sharing the strict formatter would lose that. The tolerance is not
# a check: a forged `<anything>**Critical** β€” ` prefix strips just as happily. What the
# one caller actually enforces on the bodies it feeds here is _consolidated_reviews'
# gate β€” author type Bot, PLUS a marker that this public repo puts within anyone's
# reach β€” so the guarantee is "some Bot wrote it", not "this workflow wrote it". That
# is enough only because clearing that gate already hands the forger the entry's whole
# prose, badge or no badge. Narrow the prefix before pointing _strip_badge at imported
# PR text, where the author is not gated at all.
#
# The literals pin the LABELS and the dash CHARACTER only; the `\s*` runs absorb any
# spacing change. The duplication is pinned by test, not shared: test_build_ledger.py
# drives post-review.py's real renderer through this pattern for every key of
# SEVERITY_EMOJI β€” the table `normalize_severity` actually gates the renderable
# vocabulary on β€” so adding a severity, renaming a label or changing the dash fails
Comment thread
mattmillerai marked this conversation as resolved.
# there rather than silently stopping the strip.
#
# Two editing rules that red test cannot state for you:
# * ADD, never replace. On a label rename, keep the old label in the alternation
# beside the new one β€” rounds already posted by a caller pinned to an older ref
# still carry it. The dash has the IDENTICAL old-ref exposure, so a dash change
# means widening `β€”` to a character class holding both, not swapping it: replace
# it and those rounds stop stripping silently, with nothing left to fail.
# * A new label's lowercase MUST equal its severity key. _strip_badge derives the
# ledger's severity from `match.group(1).lower()`, so a label-only rename (`Nit`
# -> `Nitpick`, key still `nit`) files entries under a severity string none of
# post-review.py's tables use. Rename both, or map label -> key here.
_BADGE_RE = re.compile(r"^\S*\s*\*\*(Critical|High|Medium|Low|Nit)\*\*\s*β€”\s*", re.UNICODE)

# Every character that STARTS A NEW LINE for `str.splitlines()` β€” and so, plausibly,
Expand Down
89 changes: 89 additions & 0 deletions .github/cursor-review/tests/test_build_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def _load(name, filename):

bl = _load("build_ledger", "build-ledger.py")
pr = _load("post_review", "post-review.py")
mcp = _load("review_output_mcp", "review-output-mcp.py")

MARKER = bl.CONSOLIDATED_MARKER

Expand Down Expand Up @@ -1410,5 +1411,93 @@ def test_the_prose_fallback_marker_still_matches_what_post_review_renders(self):
)


# --------------------------------------------------------------------------- #
# The severity badge is WRITTEN in post-review.py and READ BACK by _BADGE_RE #
# --------------------------------------------------------------------------- #


class TestSeverityBadgeContract(unittest.TestCase):
"""`_BADGE_RE` re-types post-review.py's severity vocabulary as a literal
alternation, and its `**Label** β€” ` shape as a literal too. post-review.py's own
`strip_severity_badge` avoids that by rebuilding the badge from the tables that
printed it; the ledger deliberately does not, because its tolerant `^\\S*\\s*`
prefix has to keep parsing bodies written by an OLDER post-review.py still live on
a pinned caller ref. So pin the two here instead: adding a severity or renaming a
label would leave post-review.py working while the ledger silently stopped
stripping, carrying badge-prefixed bodies into the prior-review context and
degrading the repeat matching the ledger exists for.

Scope of the pin, so nobody expects more of it than it gives: the LABELS and the
dash CHARACTER are pinned; `_BADGE_RE`'s `\\s*` runs absorb any spacing change
around the dash, so a spacing-only edit stays green here and strips fine.

The badge under test comes from `normalize_comments` β€” the real renderer β€” not
from a format string re-typed here, which would drift with it. The loop runs over
`SEVERITY_EMOJI`, not `SEVERITY_ORDER`: `normalize_severity` gates the renderable
vocabulary on `SEVERITY_EMOJI` membership, so that table β€” not the sort order β€” is
what decides which badges can ever reach the ledger.
"""

PROSE = "the finding's own prose"

def _rendered_body(self, severity: str) -> str:
comments = pr.normalize_comments(
[{"file": "app.py", "line": 12, "severity": severity, "body": self.PROSE}]
)
self.assertEqual(len(comments), 1)
return comments[0]["comment"]["body"]

def test_every_copy_of_the_severity_vocabulary_carries_the_same_keys(self):
"""Guards the loop below, which would pass vacuously over an emptied table β€”
and catches a severity added to EMOJI/LABEL (so post-review.py renders it)
but left out of ORDER, which the sort-order loop would never have exercised.

`review-output-mcp.py`'s SEVERITIES is in here as the fourth copy: it is the
ingress schema deciding what a model may submit at all, so a severity added to
post-review.py's tables and to `_BADGE_RE` but not to it is rejected at
submission and never reaches either end of the badge contract.
"""
self.assertTrue(pr.SEVERITY_EMOJI)
self.assertEqual(set(pr.SEVERITY_EMOJI), set(pr.SEVERITY_LABEL))
self.assertEqual(set(pr.SEVERITY_EMOJI), set(pr.SEVERITY_ORDER))
Comment thread
mattmillerai marked this conversation as resolved.
self.assertEqual(set(pr.SEVERITY_EMOJI), set(mcp.SEVERITIES))

def test_the_default_severity_is_one_post_review_can_render(self):
"""The one relationship here whose breach CRASHES rather than degrades.

`normalize_severity` maps every unknown/missing severity to DEFAULT_SEVERITY
and `normalize_comments` then indexes `SEVERITY_EMOJI[severity]` unguarded, so
a severity key renamed consistently across all three tables leaves the equality
above green while the first model-supplied unknown severity raises KeyError β€”
killing the consolidate job after the whole panel and the judge have run.
"""
self.assertIn(pr.DEFAULT_SEVERITY, pr.SEVERITY_EMOJI)
self.assertEqual(
bl._strip_badge(self._rendered_body("not-a-severity")),
(pr.DEFAULT_SEVERITY, self.PROSE),
)

def test_every_severity_post_review_renders_is_stripped_by_the_ledger(self):
for severity in pr.SEVERITY_EMOJI:
with self.subTest(severity=severity):
body = self._rendered_body(severity)
self.assertEqual(bl._strip_badge(body), (severity, self.PROSE))

def test_the_ledger_recovers_the_severity_of_an_older_or_emojiless_badge(self):
"""The tolerant prefix is the point of not sharing the formatter β€” hold it.

The spaceless entry is not padding: `^\\S*` is greedy, so on `πŸ”΄**Critical** β€” `
it first swallows the label too and only backtracks to the emoji. That is the
behaviour the comment in build-ledger.py leans on, and no other case here
exercises it β€” every other prefix ends in the whitespace `\\s*` consumes.
"""
for prefix in ("", "πŸ”΄ ", "πŸ†• ", "πŸ”΄"):
with self.subTest(prefix=prefix):
self.assertEqual(
bl._strip_badge(f"{prefix}**Critical** β€” {self.PROSE}"),
("critical", self.PROSE),
)


if __name__ == "__main__":
unittest.main()
Loading