fix(review): strip inline code spans delimiter-aware in the decline re-check - #702
Conversation
…e-check Replace the DOUBLE_BACKTICK_SPAN / SINGLE_BACKTICK_SPAN regex passes in RebuttalContradiction.assertedText with a small delimiter-aware scanner: an opening run of N backticks closes at the next run of exactly N (per CommonMark), an unclosed run stays literal text, the closer must sit within a 1000-character bound, and the body may cross at most one line ending. Spans whose body carries a longer backtick run and spans holding one newline are now stripped whole, so quoted claim text no longer reopens a correct decline. Anything the scan cannot classify is left in place — under-fire, the keep-the-decline direction. Blockquote lines are still dropped before span stripping. Closes #697
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
🤖 ThrillhouseBot PR SummaryWhat this PR doesReplaces the DOUBLE_BACKTICK_SPAN/SINGLE_BACKTICK_SPAN regex passes in RebuttalContradiction.assertedText with a delimiter-aware scanner (stripInlineSpans) that closes an N-backtick span at the next run of exactly N backticks, permits one line ending in the span body, treats unclosed runs as literal text, and bounds the closer search at 1000 characters; adds six tests covering the new span shapes and a CHANGELOG entry.
|
| File | Change | Summary |
|---|---|---|
CHANGELOG.md |
Modified | Adds an [Unreleased] Fixed entry describing the delimiter-aware span stripping change for #697. |
src/main/java/dev/thiagogonzaga/thrillhousebot/review/RebuttalContradiction.java |
Modified | Replaces the two inline-span regex passes with delimiter-aware stripInlineSpans and helpers closingRunStart/endOfBacktickRun |
src/test/java/dev/thiagogonzaga/thrillhousebot/review/RebuttalContradictionTest.java |
Modified | Adds six tests: longer-run-in-body span stripped, one-newline span stripped, two-newline/unclosed/end-of-reply runs literal, distant closer beyond bound does not swallow. |
Risk Assessment
| Risk | Count |
|---|---|
| 🔴 Critical | 0 |
| 🟠 High | 0 |
| 🟡 Medium | 0 |
| 🔵 Low | 2 |
Key Findings
- LOW: SPAN_BODY_BOUND is off by one: a closer exactly 1000 chars from the opener is never found (body max 999, old regex stripped 1000) (
src/main/java/dev/thiagogonzaga/thrillhousebot/review/RebuttalContradiction.java:463)
Things to double-check
1 lower-confidence finding
- LOW: Ordering Javadoc overclaims: the filter can also make a span close, and the "under-fire, keep-the-decline" label is inverted (
src/main/java/dev/thiagogonzaga/thrillhousebot/review/RebuttalContradiction.java:386) (low confidence — verify before acting)
⚠️ Required CI Checks Status
Some required checks are still pending or have failed:
| Check | Type | Status | Detail |
|---|---|---|---|
| test | check-run | ⏳ Pending | - |
| trivy | check-run | ⏳ Pending | - |
| frontend | check-run | ⏳ Pending | - |
| format | check-run | ⏳ Pending | - |
| dependency-review | check-run | ⏳ Pending | - |
Automated review by ThrillhouseBot. Reply with /review to re-run.
There was a problem hiding this comment.
ThrillhouseBot noted 1 lower-confidence item(s) under Things to double-check in the PR summary (not posted as inline threads):
- LOW: Ordering Javadoc overclaims: the filter can also make a span close, and the "under-fire, keep-the-decline" label is inverted (
src/main/java/dev/thiagogonzaga/thrillhousebot/review/RebuttalContradiction.java:386)
The new Javadoc states: "The order can only leave a span unstripped in the other direction — an opener whose closer lived on a dropped blockquote line no longer closes and stays literal — which is the under-fire, keep-the-decline direction." Both halves are contradicted by the code in this diff and by the PR's own tests. (1) The scanner closes a span whose body has at most one line ending (if (c == '\n' && ++newlines > 1) { return -1; }). When a dropped blockquote line sat BETWEEN an opener and its closer — e.g. the original reply "a\n> quote\nb" — the filter drops the middle line and the join produces "a\nb", i.e. one line ending, so the span now CLOSES and is stripped (and a dropped middle line can likewise bring a distant closer inside the 1000-char bound). That is the opposite of "can only leave a span unstripped", and before this PR the regexes never crossed a newline, so such text was never stripped. (2) An unstripped span leaves the quoted claim text in assertedText, and that text is exactly what makes the re-check fire and reopen a correct decline — the over-fire direction per the linked issue. The PR's own test shouldTreatAnUnclosedBacktickRunAsLiteralText asserts contradiction.isPresent() for an unclosed run left literal, demonstrating the re-check fires in the "stays literal" configuration the comment calls "under-fire, keep-the-decline". The direction label in both this Javadoc and the PR description is therefore backwards. Verify the blockquote filter drops whole lines (not just the '>' prefix) in the assertedText loop above this hunk.
…ing javadoc
A closer exactly SPAN_BODY_BOUND characters past the opener is now found,
matching the {0,1000} body the replaced regexes stripped, with a boundary
test. The assertedText ordering javadoc no longer claims the blockquote
drop can only leave a span unstripped, and drops the inverted under-fire
label from the stays-in-place direction.
|
@thrillhousebot resolved src/main/java/dev/thiagogonzaga/thrillhousebot/review/RebuttalContradiction.java:386 — Ordering Javadoc overclaims: the filter can also make a span close, and the "under-fire, keep-the-decline" label is inverted |
|
The next review will close every previous finding this comment names by its |
🤖 ThrillhouseBot — changes since the last review
|
…avadoc FENCED_BLOCK only pairs fences within its 10000-character bound and runs before the blockquote filter, so a paired triple run can still reach the span scan and be closed there; say so instead of claiming every paired fence was consumed.
🤖 ThrillhouseBot — changes since the last review
|
|



What type of PR is this?
Description
RebuttalContradiction.assertedTextstripped inline code spans with two regexes (DOUBLE_BACKTICK_SPAN,SINGLE_BACKTICK_SPAN) that missed two CommonMark-valid span shapes, so quoted claim text could be matched as the maintainer's own assertion and reopen a correct decline:`ab` `` is one single-backtick span per CommonMark, but the regex body class stopped at the interior backticks).\n).This PR replaces the regex passes with a small delimiter-aware scanner (
stripInlineSpans): an opening run of N backticks closes at the next run of exactly N (the CommonMark rule), an unclosed run is literal text, the closer must sit within a 1000-character bound so a stray backtick cannot swallow the reply, and the body may cross at most one line ending. Anything the scan cannot classify stays in place — under-fire is the safe, keep-the-decline direction.Blockquote lines are still dropped before span stripping; that ordering can now only leave a span unstripped (an opener whose closer lived on a dropped blockquote line no longer closes), which is again the under-fire direction.
Related Issues
Closes #697
How Has This Been Tested?
New tests: backtick-run-in-body span stripped whole, one-newline span stripped, two-newline pair stays literal, unclosed run stays literal (mid-text and at end of reply), closer beyond the length bound does not swallow the reply. All existing #652/#686-round span tests (bridging probe, blockquote-tail probe, double-backtick unit strip, half-strip guard) stay green.
./mvnw verifyclean; JaCoCo shows zero missed lines/branches on the changed file.Checklist
Screenshots / Logs
N/A
Additional Notes
CHANGELOG.md gains a
[Unreleased]Fixed entry referencing #697. This mirrors the delimiter-aware direction #651 sets for the diff-line comment scan.