Skip to content

Fold Typographic Punctuation in pr_review.py reply --match - #1878

Merged
ptr727 merged 2 commits into
developfrom
feature/auto-1299
Sep 26, 2026
Merged

ptr727 merged 2 commits into
developfrom
feature/auto-1299

Conversation

@ptr727

@ptr727 ptr727 commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Summary

A --match string copied verbatim from a rendered finding fails to select the thread it was copied from when the finding's typographic quotes, dashes, or ellipsis don't survive the copy in ASCII, and NO_MATCH reads identically to the thread being missing or already resolved.

  • matching_threads() now folds both the --match pattern and each candidate thread body through an ASCII table (_TYPOGRAPHIC_FOLD) before the case-insensitive substring compare, covering the typographic single/double quotes, en/em dash, and ellipsis.
  • NO_MATCH now states how many unresolved threads exist on the pull request, so a zero and a several no longer read the same, per the issue's secondary suggestion.
  • A parameterized test checks each of the issue's seven characters independently of the fold table itself, so dropping one from the table still fails the test that covers it, rather than the test silently losing coverage along with the entry.

Closes on promotion: #1299

Two related gaps found during local review are filed separately as out of scope for this fix: #1876 (an ASCII -- and a real em dash still miss each other) and #1877 (a --match pattern copied from this script's own truncated/whitespace-collapsed unresolved: line can still miss).

Test plan

  • python3 -m unittest scripts.tests.test_pr_review (434 tests, all passing)
  • uvx ruff@latest format --check and uvx ruff@latest check clean on both changed files
  • uvx pyright shows only the same 2 pre-existing errors present on develop before this change
  • Reverted the fix locally and confirmed the new tests fail (NO_MATCH / missing count) without it, then restored it and re-confirmed green
  • Local strict review (adversarial subagent pass) run and recorded via scripts/local_review.py

🤖 Generated with Claude Code

A --match string copied verbatim from a rendered finding fails to select the
thread it was copied from when the finding's typographic quotes, dashes, or
ellipsis don't survive the copy in ASCII, and NO_MATCH reads identically to
the thread being missing or already resolved. matching_threads() now folds
both the pattern and each candidate body through an ASCII table before the
substring compare, and NO_MATCH now states how many unresolved threads exist
so a zero and a several no longer read the same. A parameterized test checks
each of the issue's seven characters independently of the fold table itself,
so dropping one from the table still fails the test that covers it.

Closes on promotion: #1299

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Copilot AI lite review requested due to automatic review settings September 26, 2026 05:19
@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Repository: ptr727/ProjectTemplate/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 5429365d-813b-4c42-997e-c4eb9387ec99


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The functional change is small and well-covered by new tests, with only a minor test-robustness improvement suggested.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

This pull request improves scripts/pr_review.py reply --match so it can reliably select threads even when the thread text or the copied --match pattern differs only by typographic punctuation (curly quotes, en/em dashes, ellipsis), and it makes NO_MATCH refusals more actionable by including the total unresolved-thread count.

Changes:

  • Add a typographic-to-ASCII folding table and apply it to both the --match needle and candidate thread bodies before case-insensitive substring matching.
  • Extend the NO_MATCH message to include the total number of unresolved threads on the PR.
  • Add targeted tests covering the fold behavior per character and the improved NO_MATCH message.
File Description
scripts/​pr_review.py Folds typographic punctuation on both sides of --match comparisons; includes unresolved-thread count in NO_MATCH.
scripts/​tests/​test_pr_review.py Adds regression tests for typographic folding and the updated NO_MATCH output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/tests/test_pr_review.py
test_every_documented_character_selects_across_the_ascii_boundary captures
stdout once in setUp and ran all seven fold checks against that same buffer,
so a later iteration's assertIn found an earlier iteration's leftover
REPLIED_AND_RESOLVED output rather than its own. Clearing the buffer at the
start of each subTest makes the assertion specific to its own iteration.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Copilot AI review requested due to automatic review settings September 26, 2026 05:25
@ptr727

ptr727 commented Sep 26, 2026

Copy link
Copy Markdown
Owner Author

Re: the stdout-buffer finding on scripts/tests/test_pr_review.py:5266 (thread already shows resolved, so answering here for the record rather than via reply --resolve, which only targets unresolved threads): fixed in 7818762. Each subTest iteration in test_every_documented_character_selects_across_the_ascii_boundary now clears the shared stdout buffer (self.out.seek(0); self.out.truncate(0)) before wiring and running its own reply, so its assertIn checks only its own iteration's output rather than one accumulated across all seven. Swept the file for the same setUp-captures-stdout-once-then-loops-subTests shape in every other test class (TestCoverageExitCodes, TestCli, CommentCase, ReplyCase) and found no other instance of the same latent bug.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The change is narrowly scoped, covered by new unit tests, and the updated matching behavior is applied symmetrically to both the pattern and candidate text.

Review effort: Lite
Findings: None

Resolved since last review (1)

@ptr727
ptr727 merged commit a50dcc5 into develop Sep 26, 2026
9 checks passed
@ptr727
ptr727 deleted the feature/auto-1299 branch September 26, 2026 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants