Share the Fixed Fence Parser Across All Three Callers - #903
Conversation
…tions CodeRabbit, on PR #901: unfenced_text() now handles fence marker family, length, and indentation correctly, but extract_section() and strip_sections() still toggled on any marker regardless. A ~~~ line nested inside a ``` block made both exit the fenced state early, so a following ## line could truncate a verbatim section (extract_section is what the byte-for-byte check hashes) or end a strip_sections region short, exposing what followed as if it were the repo's own prose. Verified both against the actual code before fixing. Extracted the corrected per-line fence-state logic from unfenced_text into _fence_step(), a single pure function all three now call, so the fence-matching rule exists in exactly one place. Added a regression case covering the nested-marker scenario for both functions.
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
PR Summary by QodoShare CommonMark fence parsing across audit section utilities
AI Description
Diagram
High-Level Assessment
Files changed (1) |
There was a problem hiding this comment.
🟡 Changes recommended
A newly added comment uses a mid-sentence semicolon, which violates the repository's no-semicolon prose rule for agent-authored comments.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors the CommonMark fence parsing logic so extract_section(), strip_sections(), and unfenced_text() share one consistent implementation, preventing nested/mismatched fence markers from prematurely ending fenced regions and truncating section extraction.
Changes:
- Extracted the per-line fence state transition into
_fence_step()and updated all three callers to use it. - Updated
extract_section()andstrip_sections()to avoid the prior naive toggle-on-any-marker behavior. - Added a selftest regression covering a mismatched fence marker nested inside another fenced block.
File summaries
| File | Description |
|---|---|
| spec/audit.py | Centralizes fence parsing in _fence_step() and adds a regression test to prevent section truncation due to nested/mismatched fences. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Uh oh!
There was an error while loading. Please reload this page.
Copilot: prose style forbids semicolons in agent-authored comments. Recast as one comma-joined sentence.
Code Review by Qodo
1. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
🟢 Approval recommended
The shared _fence_step() implementation is consistently applied across all three callers and the added regression selftest directly covers the reported failure mode.
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
qodo-code-review: caught a spaced-hyphen dash carried over from the docstring this text was adapted from. Recast as sentence breaks.
There was a problem hiding this comment.
🟢 Approval recommended
The shared _fence_step() logic is consistently applied across all three callers and is covered by an added regression selftest targeting the previously verified failure mode.
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
Uh oh!
There was an error while loading. Please reload this page.
## Summary Follow-up to #903, addressing a finding raised on the #900 -> #901 promotion PR review (CodeRabbit). Per CommonMark, a backtick-fenced opener's info string may not itself contain a backtick (the spec's own reasoning: otherwise inline code spans could be misread as a new fence). \`_fence_step()\` accepted an opener like `` ```md` `` regardless, so a heading right after it was hidden from the scan. Verified independently against the actual code before fixing. A tilde fence has no such restriction and is unaffected. Also split the two over-25-word docstring sentences flagged in the same review round. ## Verification - `python3 spec/audit.py --selftest` -> `SELFTEST PASS`, including 3 new regression cases and the full pre-existing suite unchanged - `python3 spec/validate.py` -> `Spec validation OK` - `ruff check .` / `ruff format --check .` -> clean - `python3 scripts/prose_lint.py --diff origin/develop spec/audit.py` -> clean ## A note on scope This is the fourth follow-up PR (#901 -> #902 -> #903 -> this one) chasing progressively deeper CommonMark fence-parsing edge cases that CodeRabbit's automated review keeps finding one round at a time against `_fence_step()`. Each one has been real and independently verified, but I want to flag the pattern rather than silently keep going: CommonMark has more edge cases than these four (unterminated fences at EOF, tab expansion in indentation, and others), and a sufficiently persistent automated reviewer may keep surfacing them. Worth a decision on where "correct enough" is for a fleet-internal audit tool versus a full CommonMark implementation.
Summary
Follow-up to #902, addressing a finding raised on the #900 -> #901 promotion PR review (CodeRabbit).
unfenced_text()(fixed in #902) now handles fence marker family, length, and indentation correctly, butextract_section()andstrip_sections()still used the original naive toggle-on-any-marker logic. Verified independently before fixing: a~~~line nested inside a```block made both exit the fenced state early, so a following##line could end the region short.This is not cosmetic for
extract_section(): it is what the verbatim byte-for-byte section check hashes, so a nested example inside a fenced code sample could silently truncate what gets compared against the hub canonical.Extracted the corrected per-line fence logic from
unfenced_text()into_fence_step(), a single pure function all three now call, so the fence-matching rule lives in exactly one place instead of three near-duplicates that can drift apart the way the first two already had. Added a regression case covering the nested-marker scenario for both functions, on top of the existingextract_sectionandstrip_sections(viatemplate_ref_outside_verbatim) coverage, which still passes unchanged.Verification
python3 spec/audit.py --selftest->SELFTEST PASS, including the new nested-fence regression and the full pre-existing suite unchangedpython3 spec/validate.py->Spec validation OKruff check ./ruff format --check .-> cleanpython3 scripts/prose_lint.py --diff origin/develop spec/audit.py-> clean