Skip to content

chore: add markdownlint and fix violations across all markdown files - #1349

Open
snimu wants to merge 5 commits into
mainfrom
chore/markdownlint
Open

chore: add markdownlint and fix violations across all markdown files#1349
snimu wants to merge 5 commits into
mainfrom
chore/markdownlint

Conversation

@snimu

@snimu snimu commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds markdownlint-cli2 (same tool and rule baseline as research-environments and verifiers) and fixes all existing violations.

Config (.markdownlint-cli2.yaml): MD013 (line length) off, MD024 siblings-only (CHANGELOG ### Fixed repeats per version), MD041 off (several docs open with a callout or centered branding), MD060 compact tables, inline-HTML allowlist for the README branding headers. node_modules and packages/coding-agent/dist ignored.

Wiring: npm run check:md, included in npm run check (~0.6s), so the existing pre-commit hook and CI enforce it without workflow changes.

Fixes (96 files linted, was ~1400 violations): almost entirely mechanical via --fix — blank lines around headings/lists/fences, table pipe spacing, bare URLs wrapped in angle brackets. Manual: language tags on 37 unlabeled code fences, one broken anchor in docs/rpc.md (#message-types#types), and two duplicate sibling ### Added sections merged in packages/ai/CHANGELOG.md 0.17.0. No prose changes.

No CHANGELOG bullet: tooling/docs formatting only, no user-visible behavior.


Note

Low Risk
Dev-only lint tooling and documentation formatting; no application code or security-sensitive paths changed.

Overview
Introduces markdownlint-cli2 with a repo config (.markdownlint-cli2.yaml) aligned with sibling projects: line length off, sibling-only duplicate headings, compact tables, selective inline HTML allowed, plus a custom no-hard-wraps rule so prose stays on single logical lines.

CI enforcement comes from npm run check:md on **/*.md, wired into the root npm run check so existing pre-commit/CI paths pick it up without workflow edits.

The bulk of the diff is mechanical markdown cleanup across READMEs, CONTRIBUTING, agent docs, and CHANGELOGs: table formatting, fence language tags (often text), reflowed paragraphs, and a few targeted fixes (e.g. duplicate ### Added sections in packages/ai/CHANGELOG.md, minor anchor/format tweaks). No product runtime behavior changes.

Reviewed by Cursor Bugbot for commit 95b8a1c. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add markdownlint and fix violations across all markdown files

  • Adds markdownlint-cli2 as a devDependency and wires it into the check script via a new check:md task in package.json
  • Configures rules in .markdownlint-cli2.yaml: disables MD013 and MD041, sets MD024 siblings_only, allows specific HTML elements, ignores node_modules and packages/coding-agent/dist
  • Adds custom rule PA001 in scripts/markdownlint/no-hard-wraps.cjs that flags hard-wrapped prose lines continuing across lines without an explicit hard break
  • Fixes violations repo-wide: reflows paragraphs and bullets onto single lines, normalizes table header separators with spaced pipes, wraps bare URLs in angle brackets, and annotates plain-text code fences as text
  • Risk: npm run check now runs markdown linting, so CI will fail on new violations; PA001 flags any non-structural prose line that continues to the next line, so contributors must keep paragraphs on single lines unless a hard break is intended
📊 Macroscope summarized 95b8a1c. 23 files reviewed, 2 issues evaluated, 0 issues filtered, 2 comments posted

🗂️ Filtered Issues

Adds markdownlint-cli2 with the same rule baseline as
research-environments/verifiers (MD013 off, MD024 siblings-only,
MD041 off, MD060 compact tables, inline-HTML allowlist for README
branding). Wired into 'npm run check' as 'check:md' (~0.6s), so the
existing pre-commit hook and CI enforce it without workflow changes.

File changes are almost entirely mechanical (--fix): blank lines
around headings/lists/fences, table pipe spacing, bare URLs wrapped.
Manual: language tags on 37 unlabeled code fences, a broken anchor in
docs/rpc.md, two duplicate '### Added' siblings merged in
packages/ai/CHANGELOG. No prose changes.
Comment thread packages/coding-agent/docs/termux.md Outdated
Comment thread package.json Outdated
snimu added 2 commits August 13, 2026 13:54
The unmatched fence before '## Limitations' made everything below it
render as a code block (pre-existing; the MD040 pass had labeled it
bash instead of noticing it was unmatched). Removing it exposed two
mechanical blanks-around violations below, fixed with --fix. Also
dedupes the accidental double 'check:md' invocation in npm run check.
…ing docs

One logical line per paragraph/bullet: hard wraps distort line counts
and make one-word edits touch whole paragraphs in diffs. Custom rule
in scripts/markdownlint/no-hard-wraps.cjs (skips code fences, HTML
blocks, tables, headings, blockquotes, reference definitions, and
deliberate trailing-double-space/backslash breaks). 372 wrapped
continuation lines joined across 22 files; word-level diff is
whitespace-only.
Comment thread packages/coding-agent/skills/agent-message/SKILL.md
lineNumber: i + 2,
detail: "Continuation of the previous line; keep one logical line per paragraph/bullet.",
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wrap rule flags YAML and fences

High Severity

PA001 treats YAML frontmatter keys as wrappable prose and closes an outer fence when it sees a shorter inner fence of the same character. That produced the collapsed frontmatter and joined nested samples, and it will still fail check:md on remaining valid files such as prime-intellect/SKILL.md and planner.md.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 173e387. Configure here.

Comment on lines +24 to +35
let inFence = false;
let fenceMarker = "";
for (let i = 0; i < lines.length - 1; i++) {
const line = lines[i];
const fence = line.match(/^\s*(`{3,}|~{3,})/);
if (fence) {
if (!inFence) {
inFence = true;
fenceMarker = fence[1][0];
} else if (fence[1][0] === fenceMarker) {
inFence = false;
}

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.

🟡 Medium markdownlint/no-hard-wraps.cjs:24

The linter closes a four-backtick fenced block with a later three-backtick line, and it also closes a block on an in-fence line such as ```javascript; the remaining code is then scanned as prose and can produce false PA001 errors. The closing check must require the same fence character, a length at least as long as the opener, and only whitespace after the fence.

 	let inFence = false;
 	let fenceMarker = "";
+	let fenceLength = 0;
 	for (let i = 0; i < lines.length - 1; i++) {
 		const line = lines[i];
-		const fence = line.match(/^\s*(`{3,}|~{3,})/);
+		const fence = line.match(/^\s*(`{3,}|~{3,})(.*)$/);
 		if (fence) {
 			if (!inFence) {
 				inFence = true;
 				fenceMarker = fence[1][0];
-			} else if (fence[1][0] === fenceMarker) {
+				fenceLength = fence[1].length;
+			} else if (
+				fence[1][0] === fenceMarker &&
+				fence[1].length >= fenceLength &&
+				/^\s*$/.test(fence[2])
+			) {
 				inFence = false;
 			}
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @scripts/markdownlint/no-hard-wraps.cjs around lines 24-35:

The linter closes a four-backtick fenced block with a later three-backtick line, and it also closes a block on an in-fence line such as [code fence]javascript; the remaining code is then scanned as prose and can produce false `PA001` errors. The closing check must require the same fence character, a length at least as long as the opener, and only whitespace after the fence.

Evidence trail:
scripts/markdownlint/no-hard-wraps.cjs:24-38 (REVIEWED_COMMIT); https://spec.commonmark.org/0.28/#fenced-code-blocks

Comment on lines +55 to +85
termux-open file.pdf # Opens with default app termux-open -c image.jpg # Choose app
```

## Clipboard

```bash
termux-clipboard-set "text" # Copy
termux-clipboard-get # Paste
termux-clipboard-set "text" # Copy termux-clipboard-get # Paste
```

## Notifications

```bash
termux-notification -t "Title" -c "Content"
```

## Device Info

```bash
termux-battery-status # Battery info
termux-wifi-connectioninfo # WiFi info
termux-telephony-deviceinfo # Device info
termux-battery-status # Battery info termux-wifi-connectioninfo # WiFi info termux-telephony-deviceinfo # Device info
```

## Sharing

```bash
termux-share -a send file.txt # Share file
```

## Other Useful Commands

```bash
termux-toast "message" # Quick toast popup
termux-vibrate # Vibrate device
termux-tts-speak "hello" # Text to speech
termux-camera-photo out.jpg # Take photo
termux-toast "message" # Quick toast popup termux-vibrate # Vibrate device termux-tts-speak "hello" # Text to speech termux-camera-photo out.jpg # Take photo

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.

🟡 Medium docs/termux.md:55

The Opening Files, Clipboard, Device Info, and Other Useful Commands examples execute only their first command when copied into a shell, so users cannot perform the documented operations. The commands were collapsed into lines where # comments out everything after the first command; restore each command to its own line.

-termux-open file.pdf          # Opens with default app termux-open -c image.jpg      # Choose app
+termux-open file.pdf          # Opens with default app
+termux-open -c image.jpg      # Choose app
-termux-clipboard-set "text"   # Copy termux-clipboard-get          # Paste
+termux-clipboard-set "text"   # Copy
+termux-clipboard-get          # Paste
-termux-battery-status         # Battery info termux-wifi-connectioninfo    # WiFi info termux-telephony-deviceinfo   # Device info
+termux-battery-status         # Battery info
+termux-wifi-connectioninfo    # WiFi info
+termux-telephony-deviceinfo   # Device info
-termux-toast "message"        # Quick toast popup termux-vibrate                # Vibrate device termux-tts-speak "hello"      # Text to speech termux-camera-photo out.jpg   # Take photo
+termux-toast "message"        # Quick toast popup
+termux-vibrate                # Vibrate device
+termux-tts-speak "hello"      # Text to speech
+termux-camera-photo out.jpg   # Take photo
Also found in 1 other location(s)

packages/coding-agent/docs/skills.md:377

The two documented Brave Search invocations were collapsed onto one shell line: ./search.js &#34;query&#34; --content is now part of the comment after #. Copying the documented command therefore only runs the basic search and never enables the advertised --content option, so users cannot follow the example to retrieve page content.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/coding-agent/docs/termux.md around lines 55-85:

The `Opening Files`, `Clipboard`, `Device Info`, and `Other Useful Commands` examples execute only their first command when copied into a shell, so users cannot perform the documented operations. The commands were collapsed into lines where `#` comments out everything after the first command; restore each command to its own line.

Evidence trail:
packages/coding-agent/docs/termux.md:52-85 at 173e387f68

Also found in 1 other location(s):
- packages/coding-agent/docs/skills.md:377 -- The two documented Brave Search invocations were collapsed onto one shell line: `./search.js "query" --content` is now part of the comment after `#`. Copying the documented command therefore only runs the basic search and never enables the advertised `--content` option, so users cannot follow the example to retrieve page content.

Comment thread packages/coding-agent/skills/attach-image/SKILL.md Outdated

@jonaowen jonaowen left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The mechanical unwrap changed significant literal bytes inside inline code spans, contradicting the “no prose changes” claim.

Examples on exact head 173e387f6:

  • packages/ai/CHANGELOG.md 0.2.2 previously documented dropping the suffix ` (Prime Inference)` (including the leading space). The rewrite now says `(Prime Inference)`, which is a different suffix.
  • packages/coding-agent/CHANGELOG.md previously documented connectors `├ ` / `└ ` and replacements `├─ ` / `└─ ` with significant trailing spaces. The rewrite removes every trailing space and now documents different strings.

These are user-facing historical/behavioral claims, not style. A formatter/lint rule must preserve whitespace inside code spans and other literal regions. Restore the exact literals and add focused regression fixtures for inline code with leading/trailing spaces (including spans split by historical hard wraps) before applying this rule repo-wide. Please also audit all 67 changed Markdown files for the same class; a green Markdown lint cannot detect semantic byte loss it caused.

@jonaowen

Copy link
Copy Markdown

Additional binding evidence from the PR's own required CI: Test (coding-agent 2/3) is red with 9 failures. The unwrap collapsed YAML frontmatter fields in bundled SKILL.md files onto one line, e.g. name: agent-message description: ..., producing “Nested mappings are not allowed in compact mappings.” Bundled agent-message/observe, compact, rlm-heartbeat, edit, websearch, and other skills disappear from resource loading; 11 warnings are shown. This is runtime/product behavior, not formatting. The custom rule claims to skip several literal regions but has no frontmatter state and no focused tests. Restore every frontmatter record byte-semantically, make the rule parse/skip YAML frontmatter and literal regions, and require the complete CI suite green before reconsideration.

@jonaowen

Copy link
Copy Markdown

Fresh independent review found three further semantic classes on the same head:

  • Executable examples were joined into invalid single shell lines: docs/skills.md:377; docs/termux.md:55,61,73,85 (later commands are swallowed by the first # comment); docs/rpc.md:547 merges two output records.
  • no-hard-wraps.cjs:28-35 tracks only fence character, not opening length/valid CommonMark closer, so an inner triple fence falsely closes an outer quadruple fence and institutionalizes the corruption.
  • Procedure numbering is reset at docs/themes.md:51,118 and examples/extensions/plan-mode/README.md:33-35, changing visible step semantics.

The corrupted subagent reviewer frontmatter also collapses tools: bash and model, so this crosses an authority/profile boundary. These need exact restoration and regression coverage in addition to the bundled-skill failures above.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 95b8a1c. Configure here.

description: Code review specialist for quality and security analysis
tools: bash
model: claude-sonnet-4-5
name: reviewer description: Code review specialist for quality and security analysis tools: bash model: claude-sonnet-4-5

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Example agent frontmatter is invalid YAML

Medium Severity

The reviewer agent header was collapsed into one YAML line, so name, description, tools, and model are no longer separate keys. parseFrontmatter will throw, and loadAgentsFromDir skips agents without both name and description, so this example agent never loads.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 95b8a1c. Configure here.

Comment thread AGENTS.md

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.

🟡 Medium

- After code changes (not documentation changes): `npm run check` (get full output, no tail). Fix all errors, warnings, and infos before committing.

npm run check can rewrite other agents’ unstaged files because the root script runs Biome with --write across the entire worktree. This makes the mandated post-change command violate the shared-worktree safety rules; use a non-mutating check command or limit writes to the files being changed.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @AGENTS.md around line 25:

`npm run check` can rewrite other agents’ unstaged files because the root script runs Biome with `--write` across the entire worktree. This makes the mandated post-change command violate the shared-worktree safety rules; use a non-mutating check command or limit writes to the files being changed.

Evidence trail:
AGENTS.md:25, 205-227 at 95b8a1c89f958ca372294eeb73fb61c305c3360f; package.json:17 at REVIEWED_COMMIT

Comment thread AGENTS.md

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.

🟢 Low

tmux send-keys -t prime-agent-test "cd /Users/kevin/pi/prime-agent && ./prime-agent.sh" Enter

The runbook fails to start ./prime-agent.sh for checkouts outside /Users/kevin/pi/prime-agent because the hard-coded cd command fails. Replace that path with the current repository path or a clearly documented placeholder.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @AGENTS.md around line 87:

The runbook fails to start `./prime-agent.sh` for checkouts outside `/Users/kevin/pi/prime-agent` because the hard-coded `cd` command fails. Replace that path with the current repository path or a clearly documented placeholder.

Evidence trail:
AGENTS.md:82-90 at REVIEWED_COMMIT

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