Skip to content

fix: ignore checkboxes inside fenced code blocks in plan parser#329

Merged
umputun merged 2 commits intomasterfrom
fix-fenced-code-block-checkbox-parser
May 4, 2026
Merged

fix: ignore checkboxes inside fenced code blocks in plan parser#329
umputun merged 2 commits intomasterfrom
fix-fenced-code-block-checkbox-parser

Conversation

@umputun
Copy link
Copy Markdown
Owner

@umputun umputun commented May 4, 2026

plans containing markdown fenced code blocks (``` or ~~~) with example - [ ] checkboxes triggered false-positive infinite loops when sub-Claude emitted `ALL_TASKS_DONE`. The parser counted those template examples as real uncompleted tasks, runner re-iterated forever until `--max-iterations` cap.

track fence state during the line scan and skip lines inside fences in both ParsePlan and FileHasUncompletedCheckbox. Closer matching follows CommonMark strictly:

  • same fence character as the opener
  • length at least equal to the opener
  • no info string allowed on the closer (only optional trailing whitespace)

That last rule matters. Without it, an inner ```bash inside an outer ``` fence would close the outer prematurely and leak the inner example checkboxes back as actionable.

Related to #328

Plans containing markdown fenced code blocks (``` or ~~~) with example
[ ] checkboxes triggered false-positive infinite loops when sub-Claude
emitted ALL_TASKS_DONE — the parser counted those template examples as
real uncompleted tasks. Track fence state during the line scan and skip
checkboxes inside fences in both ParsePlan and FileHasUncompletedCheckbox.

Related to #328
Copilot AI review requested due to automatic review settings May 4, 2026 16:31
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 4, 2026

Deploying ralphex with  Cloudflare Pages  Cloudflare Pages

Latest commit: c2c7c7c
Status: ✅  Deploy successful!
Preview URL: https://c26a37c0.ralphex.pages.dev
Branch Preview URL: https://fix-fenced-code-block-checkb.ralphex.pages.dev

View logs

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the plan markdown parser to ignore - [ ]/- [x] checkboxes that appear inside CommonMark fenced code blocks (``` or ~~~), preventing false positives that could cause repeated runner iterations even after receiving <<<RALPHEX:ALL_TASKS_DONE>>>.

Changes:

  • Add fenced code block tracking during line-by-line scans in both ParsePlan and FileHasUncompletedCheckbox.
  • Implement CommonMark-style fence open/close matching rules (same fence char, close length >= open length, no info string on closer).
  • Add comprehensive tests covering backtick/tilde fences, indentation, unclosed fences, and nested opener-with-info-string scenarios.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
pkg/plan/parse.go Adds fence state tracking and skips parsing/counting checkboxes inside fenced code blocks.
pkg/plan/parse_test.go Adds regression tests ensuring fenced-block checkboxes are ignored in parsing and file scanning.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/plan/parse.go Outdated
// fenceClosePattern matches a CommonMark code-fence closer: same as opener but with no info
// string permitted — only optional trailing whitespace. used to avoid treating an inner
// opener-with-info-string (e.g. ```go) as closing an outer fence.
fenceClosePattern = regexp.MustCompile(`^ {0,3}(` + "`" + `{3,}|~{3,})[ \t]*$`)
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

two parts:

  1. The raw string concatenation actually produces a correct regex. `^ {0,3}(` + ""+ ``{3,}|{3,})[ \t]*$ `` evaluates at compile time to ``` ^ {0,3}({3,}|{3,})[ \t]*$ . The `+ "`" +` is Go string concatenation glueing one literal backtick between two raw-string segments, not regex content. The new test `ignores checkboxes inside backtick fenced code blocks` exercises a real ` ` closer and passes, which would not be possible if the regex never matched.

  2. The CRLF concern is valid for FileHasUncompletedCheckbox. It splits on \n, leaves trailing \r on each line, and the closer's [ \t]*$ cannot match. Fixed in c2c7c7c by allowing optional \r before the end anchor ([ \t]*\r?$) and added a CRLF regression test. ParsePlan is unaffected since bufio.Scanner already strips the CR.

FileHasUncompletedCheckbox splits on \n, leaving trailing \r on each
line. The closer regex required `[ \t]*$`, so it would never match a
CRLF-terminated ``` line, the fence stayed open, and any real
unchecked checkbox after the fence was incorrectly skipped (false
negative — runner exits thinking the malformed plan is done).

Allow optional \r before the line end. ParsePlan is unaffected
(bufio.Scanner already strips the CR).
@umputun umputun merged commit 70954ad into master May 4, 2026
5 checks passed
@umputun umputun deleted the fix-fenced-code-block-checkbox-parser branch May 4, 2026 17:02
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