Skip to content

fix(markers): never pair a marker with an example in closed code - #712

Merged
Jamie-BitFlight merged 11 commits into
mainfrom
claude/closed-code-examples
Sep 29, 2026
Merged

Jamie-BitFlight merged 11 commits into
mainfrom
claude/closed-code-examples

Conversation

@Jamie-BitFlight

Copy link
Copy Markdown
Contributor

Description

This PR is stacked on #708, because it reuses #708's unclosed-fence check. Once #708 merges, it retargets to main.

locateSection used a section's one start marker and one end marker wherever the pair sat, even when one side was an example in a later code block. Take a README with one real <!-- start inputs -->, where the only <!-- end inputs --> is inside a fenced example further down. The tool replaced everything between them, including the user's prose and the fence opener. main behaved the same before #704.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Related Issues

Changes Made

  • A marker inside closed code is now always an example and does not count. Closed code means inline code, an indented code block, or a fenced block that its closing fence ends.
  • A marker inside a fence that nothing closes still counts. Such a fence runs to the end of the document, and generated text can hold one, so treating it as code would hide every marker after it.
  • This replaces the single-pair rule, which only stood in for that unclosed-fence case.
  • The last parse is cached, because each section is located more than once in the same document.
  • diagnoseMarkers and scripts/verify-readme-contract.mjs read markers the same way. The verifier has its own implementation.
  • docs/tool-contract.md states the new rule.

Testing

  • All existing tests pass (vp test, vp check, bundled-binary test, markdownlint)
  • Added new tests for new functionality:
    • A start marker with its only end marker in a later code example is unpaired.
    • A pair that exists only as an example in a fence or in inline code is missing.
    • The editor leaves such a README unchanged.
    • The verifier rejects a run that filled between a start marker and an example end marker.
    • All four fail without the fix.
  • Manually tested the changes:
    • This repo's README regenerates unchanged, and the verifier passes on it.
    • Both integration targets give byte-identical output and converge on the second pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t


Generated by Claude Code

A marker whose name misses a section by a letter, and a README with no
section markers at all, both produced a successful run that generated
nothing, with the reason logged at debug level only.

Before any section is written, generate now warns about a marker whose
name is within two edits of a section name, suggesting that section, and
about a README with no marker for any section, pointing at
README.example.md. A name far from every section is left alone: the
template's own [.github/ghadocs/examples/] marker and other tools'
markers use the same syntax. Markers inside code are examples and are
not reported. The exit code is unchanged.

Fixes #644
Fixes #641

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
The mistyped-marker check set aside every marker inside code, so a
single mistyped pair after an unclosed generated fence went unreported.
It now follows locateSection's rule: a single pair counts wherever it
sits, and code only sets aside markers that are not one pair.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
A typo on one side splits a pair across two names, so the pair rule saw
neither side as a pair and set the typo aside when it sat after an
unclosed fence. Markers are now grouped by their section, or the section
a near-miss name was meant to be, before the pair rule is applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
The mistyped-marker check used the single-pair rule as a stand-in for
"the markers sit after an unclosed fence", and each edge case of that
stand-in produced a missed or false warning. It now asks the real
question: a marker inside closed code is an example, and a marker
inside a fence that nothing closes is reported.

The missing-markers warning now checks the sections being generated,
so --sections=inputs against a README with only a title pair warns, and
an empty selection does not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
A section with one start marker and one end marker was located wherever
the pair sat, even when one side was an example in a later code block.
The tool then replaced everything between the real start marker and the
example, including the user's prose.

A marker inside closed code (inline code, an indented block, or a fence
its closing fence ends) is now always an example. A marker inside a
fence that nothing closes still counts, so such a fence cannot hide the
markers after it. The mistyped-marker check and the contract verifier
read markers the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 31 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: bitflight-devops/github-action-readme-generator/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 705c4513-ff92-44ba-a79a-371a01e5b1a3

📥 Commits

Reviewing files that changed from the base of the PR and between 7d6c536 and 04617ee.

📒 Files selected for processing (6)
  • __tests__/markers.test.ts
  • __tests__/readme-editor.test.ts
  • __tests__/verify-readme-contract.test.ts
  • docs/tool-contract.md
  • scripts/verify-readme-contract.mjs
  • src/markers.ts

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.

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 92.13% 1008 / 1094
🔵 Statements 92.29% 1030 / 1116
🔵 Functions 95% 152 / 160
🔵 Branches 85.84% 552 / 643
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/markers.ts 100% 88.6% 100% 100%
Generated in workflow #1052 for commit 04617ee by the Vitest Coverage Report Action

The unclosed-fence check read a code range's kind from its text, so inline
code opened by triple backticks, or an indented block whose first line is
backticks, was taken for a fence that nothing closes, and a mistyped
example inside it was reported. The parser's node kind now decides: only
a fenced code block, whose node starts at its fence, can be unclosed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
…ude/closed-code-examples

# Conflicts:
#	src/markers.ts
Only fenced code blocks reach isUnclosedFence, and a fenced block's node
starts at its fence, so the branch for a missing opener could not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H37LVnd9qB6PmZ5bJi5H2t
…ude/closed-code-examples

# Conflicts:
#	src/markers.ts
@Jamie-BitFlight
Jamie-BitFlight marked this pull request as ready for review September 29, 2026 10:59
Base automatically changed from claude/marker-warnings to main September 29, 2026 10:59
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-09-29T10:59:56.754001Z 782186f Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Jamie-BitFlight
Jamie-BitFlight merged commit 44f4da7 into main Sep 29, 2026
10 checks passed
@Jamie-BitFlight
Jamie-BitFlight deleted the claude/closed-code-examples branch September 29, 2026 11:01
Jamie-BitFlight pushed a commit that referenced this pull request Sep 29, 2026
## [2.0.3](v2.0.2...v2.0.3) (2026-09-29)

### Bug Fixes

* **markers:** never pair a marker with an example in closed code ([#712](#712)) ([44f4da7](44f4da7))
* **readme-generator:** warn about mistyped and missing section markers ([#708](#708)) ([7d6c536](7d6c536))
* **sections:** keep fenced code blocks in a description intact ([#709](#709)) ([47728d4](47728d4))
@Jamie-BitFlight

Copy link
Copy Markdown
Contributor Author

🎉 This PR is included in version 2.0.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

@Jamie-BitFlight Jamie-BitFlight added the released This issue/pull request has been released. label Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released This issue/pull request has been released.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants