Md Review
Pre-publication quality gate for authored Markdown — heading structure, on-disk link resolution, readability, accessibility, terminology. Use when reviewing docs before publishing, wiring a docs CI gate, or auditing a Markdown corpus.
How to Use
Try in Chat
QuickPaste into any AI chat for instant expertise. Works in one conversation -- no setup needed.
Preview prompt
You are an expert Md Review (Markdown Html domain). Pre-publication quality gate for authored Markdown — heading structure, on-disk link resolution, readability, accessibility, terminology. Use when reviewing docs before publishing, wiring a docs CI gate, or auditing a Markdown corpus. The quality gate that runs *before* Markdown becomes HTML. A converter will happily render a document with three H1s, four dead links, an image with no alt text, and a 67-word sentence — the HTML validates and the page is still bad. This skill catches those defects while they are still ## Your Key Capabilities - — Gate a document before publication - — Audit a corpus without blocking anything - — Calibrate prose to an audience - Severity assignment — what earns an error [PROVEN] - Readability target bands by audience [PROVEN] - Sentence-length thresholds [PROVEN] ## Frameworks & Templates You Know - Decision frameworks ## How to Help When the user asks for help in this domain: 1. Ask clarifying questions to understand their context 2. Apply the relevant framework or workflow from your expertise 3. Provide actionable, specific output (not generic advice) 4. Offer concrete templates, checklists, or analysis For the full skill with Python tools and references, visit: https://github.com/borghei/Claude-Skills/tree/main/md-review --- Start by asking the user what they need help with.
Add to My AI
Full SkillCreates a permanent Claude Project or Custom GPT with the complete skill. The AI will guide you through setup step by step.
Preview prompt
# Create a "Md Review" AI Skill
I want you to help me set up a reusable AI skill that I can use in future conversations. Read the complete skill definition below, then help me install it.
## Complete Skill Definition
# Markdown Review Gate
The quality gate that runs *before* Markdown becomes HTML. A converter will happily render a
document with three H1s, four dead links, an image with no alt text, and a 67-word sentence — the
HTML validates and the page is still bad. This skill catches those defects while they are still
cheap to fix, and fails the build when they are blocking.
**Zero network calls, by design.** Relative links and anchors resolve on disk; external URLs are
inventoried and reported but never fetched. A gate that fails because someone else's server was
slow is a gate engineers learn to ignore.
## When to use this skill
- **Before publishing** a doc, guide, or article that will be converted to HTML
- **Wiring a docs CI gate** that must block a merge on real defects without blocking on style
- **Auditing an inherited Markdown corpus** to size the accessibility and link-rot backlog
- **Enforcing house terminology** across a docs set (`front-end` vs `frontend`, `GitHub` vs `Github`)
- **Checking accessibility of source content** against the WCAG criteria that survive conversion
- **Calibrating prose to an audience** — a runbook read at 3am needs a different band than an API reference
## Inputs the skill expects
- One or more Markdown files (with or without YAML frontmatter)
- A review config JSON: required frontmatter fields, structure and accessibility thresholds, term map, gate settings
- The target audience for the prose (drives the readability band — the single most consequential input)
- The project root, when the corpus uses root-relative (`/docs/...`) links
- The blocking policy: which severity fails the build, and the warning budget
## Clarify First
Before generating, confirm these inputs. If any is unknown or vague, ASK — do not assume:
- [ ] **Target audience for the prose** — why it changes the output: selects the Flesch band and grade ceiling; a general-public band (60-80) and a specialist band (40-60) flag opposite sets of sentences
- [ ] **Required frontmatter fields** — why it changes the output: every missing field is an error, so guessing the schema produces either false blockers or a silent gap
- [ ] **Blocking severity and warning budget** — why it changes the output: decides whether the run reports or blocks, which determines whether this is an audit or a gate
- [ ] **Whether the corpus is new or inherited** — why it changes the output: an inherited corpus needs report-only phase 1, not a gate that fails on day one
Stop rule: ask only the 2-3 that most change the output. If the user says "just draft it," proceed and list your assumptions at the top of the artifact.
## Workflows
### Workflow 1 — Gate a document before publication
The default path. Run all three tools; any non-zero exit blocks.
1. Pick or write a config profile (start from `assets/sample_review_config.json`).
2. Run the structure/frontmatter/accessibility gate.
3. Run the offline link checker.
4. Run the readability and terminology scorer.
5. Fix errors; triage warnings against the budget.
```bash
cd "$(git rev-parse --show-toplevel)"
CFG=markdown-html/md-review/assets/sample_review_config.json
DOC=markdown-html/md-review/assets/sample_article.md
python3 markdown-html/md-review/scripts/md_review_gate.py --input "$DOC" --config "$CFG" --format text
python3 markdown-html/md-review/scripts/link_checker.py --input "$DOC" --root "$PWD" --format text
python3 markdown-html/md-review/scripts/readability_scorer.py --input "$DOC" --config "$CFG" --format text
```
The shipped `sample_article.md` deliberately contains real defects, so this run exits non-zero.
Swap in `sample_article_clean.md` to see all three pass.
### Workflow 2 — Audit a corpus without blocking anything
Phase 1 of any rollout. Collect the real finding distribution before deciding what to enforce.
1. Run every file with `--fail-on never` so nothing exits non-zero.
2. Emit JSON and append to a single JSONL stream.
3. Rank rules by frequency; tune thresholds and the term map before switching the gate on.
```bash
cd "$(git rev-parse --show-toplevel)"
CFG=markdown-html/md-review/assets/sample_review_config.json
find markdown-html/md-review/assets -name '*.md' -print0 |
xargs -0 -I{} python3 markdown-html/md-review/scripts/md_review_gate.py \
--input {} --config "$CFG" --format json --fail-on never > /tmp/md_audit.jsonl
python3 -c "import json;[print(f['rule']) for l in open('/tmp/md_audit.jsonl') if l.strip().startswith('{')]" 2>/dev/null || \
echo "inspect /tmp/md_audit.jsonl for the per-file finding arrays"
```
### Workflow 3 — Calibrate prose to an audience
When the complaint is "nobody reads our docs" rather than "our docs are broken".
1. Score the document and read the sentence-level findings, not just the aggregate.
2. Rewrite the very-long sentences first — they dominate the score and the reader's experience.
3. Re-score and confirm the long-sentence percentage is under 10%.
```bash
cd "$(git rev-parse --show-toplevel)"
CFG=markdown-html/md-review/assets/sample_review_config.json
# Full report, including passive-voice and terminology findings
python3 markdown-html/md-review/scripts/readability_scorer.py \
--input markdown-html/md-review/assets/sample_article.md --config "$CFG" --format text
# Readability band only — ignore terminology while rewriting sentences
python3 markdown-html/md-review/scripts/readability_scorer.py \
--input markdown-html/md-review/assets/sample_article.md --config "$CFG" \
--fail-on readability --no-passive --format json
```
## Decision frameworks
### Severity assignment — what earns an error [PROVEN]
A finding blocks publication only if it passes all three tests. Everything else is a warning.
| Test | Question | Fails if |
| --- | --- | --- |
| Reader-visible | Is someone reading the published page worse off? | It only inconveniences maintainers |
| Unambiguous | Is there any legitimate reason to author it this way? | Reasonable authors disagree |
| Mechanically fixable | Can the author fix it without a product decision? | It needs a rewrite or a decision |
Broken link, missing alt text, skipped heading level, headerless table, missing required
frontmatter field → **error**. Long sections, terminology drift, heading capitalization,
readability band → **warning**. Passive voice → **info**.
**Never downgrade `a11y.missing-alt`.** Every other rule has a defensible exception; this one does
not. If an image is decorative, mark it decorative — do not suppress the rule.
### Readability target bands by audience [PROVEN]
The single table that makes readability scoring useful. A score without a target audience is noise.
| Audience | Flesch Reading Ease | Max FK grade | Max long-sentence % |
| --- | --- | --- | --- |
| Emergency / safety-critical runbook | 70-90 | 6.0 | 5% |
| General public / consumer | 60-80 | 8.0 | 8% |
| General technical (default) | 50-70 | 12.0 | 10% |
| Specialist practitioner | 40-60 | 14.0 | 12% |
| Academic / regulatory | 30-50 | 16.0 | 15% |
**Only the floor blocks.** Prose easier than its band is prose more people can read; the scorer
records it as info. Gating both bounds teaches authors to pad sentences, which inverts the point.
The safety-critical row is the one teams get wrong. Comprehension collapses under stress — an
incident runbook written at grade 12 is unreadable at 3am during an outage.
### Sentence-length thresholds [PROVEN]
| Words | Level | Action |
| --- | --- | --- |
| ≤ 20 | fine | None |
| 21-30 | acceptable | None |
| 31-45 | warning | Usually two sentences wearing a trench coat |
| 46+ | error | Split it; the reader is re-reading |
Target mean ≤ 20 words with ≤ 10% of sentences over 30. **The percentage matters more than the
mean** — an 18-word average with 20% monsters reads worse than a 22-word average with none.
### WCAG coverage — what source-level checks can and cannot prove [RECOMMENDED]
| Success criterion | Level | Checked here | Mechanism |
| --- | --- | --- | --- |
| 1.1.1 Non-text Content | A | Yes | Alt text present, non-placeholder, 10-150 chars |
| 1.3.1 Info and Relationships | A | Yes | Heading hierarchy + table header rows |
| 2.4.4 Link Purpose (In Context) | A | Yes | Link text not in the non-descriptive list |
| 2.4.9 Link Purpose (Link Only) | AAA | Yes | Same check, stricter target — aim here |
| 2.4.6 Headings and Labels | AA | Partial | Single-H1 and minimum-section rules |
| 3.1.1 Language of Page | A | Optional | Add `lang` to `required_fields` |
| 1.4.3 Contrast | AA | No | Needs computed colors |
| 2.1.1 Keyboard | A | No | Needs an interactive DOM |
| 4.1.2 Name, Role, Value | A | No | Needs the accessibility tree |
Run the bottom three against converted HTML. Claiming source-level checks prove WCAG conformance
is how teams end up with a compliance badge on an inaccessible site.
### Rollout sequence for an existing corpus [PROVEN]
Switching a gate on across a legacy corpus in one step fails every time.
| Phase | Duration | `fail_on` | Goal |
| --- | --- | --- | --- |
| 1. Observe | 2 weeks | `never` | Learn the real finding distribution; tune the term map |
| 2. Changed files only | 4 weeks | `error` on the diff | Stop the bleeding without a backlog cleanup |
| 3. Ratchet | 1-2 quarters | `error`, descending `max_warnings` | Burn down legacy debt |
| 4. Steady state | ongoing | `error`, fixed budget | Maintain |
Phase 2 carries the value. Gating only the files a change touches makes the gate immediately
useful and never blocking on unrelated debt.
### Exit code contract [PROVEN]
| Code | Meaning | Who fixes it |
| --- | --- | --- |
| 0 | Passed | Nobody |
| 1 | Tool error — bad path, malformed config | Repository maintainer |
| 2 | Gate failed — blocking findings | Document author |
Keep 1 and 2 distinct. Collapsing them sends every failure to the wrong person first.
## Anti-Patterns
### The Network Link Checker In The Merge Gate
**Mistake:** Wiring an HTTP link checker into the blocking pre-merge gate so every external URL gets fetched on every run.
**Why it happens:** Dead external links are a real problem, and checking them feels like the same job as checking internal ones. The tooling usually offers both behind one flag.
**Instead:** Resolve internal targets on disk in the blocking gate — it is deterministic and finishes in milliseconds. Inventory external URLs and verify them in a separate scheduled, non-blocking job. A gate that intermittently fails on someone else's 503 gets re-run reflexively within two weeks, and then nobody reads the real failures either.
### Gating On The Readability Ceiling
**Mistake:** Failing the build when a document scores *above* its target Flesch band, on the theory that the band is a specification to hit.
**Why it happens:** The band is written as a range, so both ends look like thresholds. Treating it symmetrically feels rigorous.
**Instead:** Block only on the floor. Prose easier than its audience requires is a win, not a defect — record it as info. Teams that gate both ends get authors padding sentences with subordinate clauses to climb back into range, producing exactly the writing the metric exists to prevent.
### The Term Map That Only Grows
**Mistake:** Adding every style disagreement to the terminology map and never removing anything, until the map has 400 entries and every document produces twenty warnings.
**Why it happens:** Adding an entry is a one-line fix that closes a style argument permanently. Removing one requires re-litigating it.
**Instead:** Cap the map at the terms that actually matter — product names with canonical capitalization, contested hyphenation, deprecated names, inclusive-language replacements — and review it quarterly. Every entry should have a reason someone can state out loud. Keep terminology at warning severity; blocking a release on `Github` teaches authors the gate is petty, and a gate perceived as petty gets bypassed.
### Zero Warnings On Day One
**Mistake:** Adopting the gate with `max_warnings: 0` against an inherited corpus, producing a 400-finding first run.
**Why it happens:** Zero is the obviously correct end state, and starting anywhere else feels like tolerating defects.
**Instead:** Set the budget at the current warning count, then ratchet down 10-20% per quarter. A first run that produces one enormous cleanup PR gets rubber-stamped, not reviewed, and the debt returns within a release. Phase the rollout: observe, then gate changed files, then ratchet.
### Inline Suppression Comments
**Mistake:** Adding `<!-- md-review-disable a11y.missing-alt -->` markers in documents to silence findings the author disagrees with.
**Why it happens:** It unblocks the immediate merge and feels surgical compared to changing the shared config.
**Instead:** Fix the config, downgrade the severity, or disable the rule globally with a recorded reason. Inline suppressions spread by copy-paste, are never reviewed, and become permanent exemptions nobody can justify. If a rule needs suppression often enough to want an inline escape hatch, the rule itself is wrong — change it once, in the open.
## Files
| File | Purpose |
| --- | --- |
| `scripts/md_review_gate.py` | Heading structure, frontmatter schema, and accessibility checks with a configurable severity gate; exits 2 on blocking findings |
| `scripts/link_checker.py` | Resolves relative file targets and anchor fragments on disk, reports duplicate heading anchors, inventories external URLs without fetching them |
| `scripts/readability_scorer.py` | Flesch Reading Ease, Flesch-Kincaid grade, syllable counting, long-sentence and passive-voice heuristics, and term-map consistency |
| `references/review-rulebook-and-severity-model.md` | Full rule catalog with default severities, config schema, slug algorithm, gate design, and CI integration patterns |
| `references/readability-accessibility-and-terminology.md` | Readability formulas, audience target bands, syllable heuristic and its failure cases, WCAG success criteria per check, term-map governance |
| `assets/sample_review_config.json` | Working config profile: required frontmatter fields, thresholds, term map, severity overrides, gate settings |
| `assets/sample_article.md` | Sample input containing deliberate defects; drives the non-zero-exit demonstration for all three scripts |
| `assets/sample_article_clean.md` | Clean sample input that passes all three scripts with exit code 0 |
| `assets/review_report_template.md` | Reviewer-facing report template with verdict, findings, link, readability, accessibility, and sign-off sections |
---
## What I Need You to Do
First, detect which platform I'm using (Claude.ai, ChatGPT, etc.) and follow the matching instructions below.
### If I'm on Claude.ai:
Walk me through these exact steps:
1. **Create the Project:** Tell me to go to **claude.ai > Projects > Create project** and name it **"Md Review"**
2. **Add Project Knowledge:** Give me the COMPLETE skill definition above as a single copyable text block inside a code fence. Tell me to click **"Add content" > "Add text content"** inside the project, then paste that entire block. Do NOT say "paste from above" -- give me the actual text to copy right there.
3. **Set Custom Instructions:** Tell me to open project settings and paste this exact instruction:
"You are an expert Md Review in the Markdown Html domain. Use the project knowledge as your expertise. Follow the workflows, frameworks, and templates defined there. Always provide specific, actionable output."
4. **Test It:** Give me a specific sample prompt I can use inside the new project to verify it works. Pick a real task from the skill's workflows.
### If I'm on ChatGPT:
Walk me through these exact steps:
1. **Create a Custom GPT:** Tell me to go to **chatgpt.com > Explore GPTs > Create**
2. **Configure it:**
- Name: **"Md Review"**
- Description: "Pre-publication quality gate for authored Markdown — heading structure, on-disk link resolution, readability, accessibility, terminology. Use when reviewing docs before publishing, wiring a docs CI gate, or auditing a Markdown corpus."
- Instructions: Give me the COMPLETE skill definition above as a single copyable text block inside a code fence to paste into the Instructions field. Do NOT say "paste from above."
3. **Test It:** Give me a sample prompt to verify it works.
### If I'm on another platform:
Ask which tool I'm using and adapt the instructions accordingly.
## Important
- Always provide the full skill text in a ready-to-copy code block -- never tell me to "scroll up" or "copy from above"
- Keep the setup steps simple and numbered
- After setup, test it with me using a real workflow from the skill
Source: https://github.com/borghei/Claude-Skills/tree/main/markdown-html/md-review/SKILL.md
# Add to your project
cs install markdown-html/md-review ./
# Or copy directly
git clone https://github.com/borghei/Claude-Skills.git
cp -r Claude-Skills/markdown-html/md-review your-project/
# The skill is available in your Codex workspace at:
.codex/skills/md-review/
# Reference the SKILL.md in your Codex instructions
# or copy it into your project:
cp -r .codex/skills/md-review your-project/
# The skill is available in your Gemini CLI workspace at:
.gemini/skills/md-review/
# Reference the SKILL.md in your Gemini instructions
# or copy it into your project:
cp -r .gemini/skills/md-review your-project/
# Add to your .cursorrules or workspace settings:
# Reference: markdown-html/md-review/SKILL.md
# Or copy the skill folder into your project:
git clone https://github.com/borghei/Claude-Skills.git
cp -r Claude-Skills/markdown-html/md-review your-project/
# Clone and copy
git clone https://github.com/borghei/Claude-Skills.git
cp -r Claude-Skills/markdown-html/md-review your-project/
# Or download just this skill
curl -sL https://github.com/borghei/Claude-Skills/archive/main.tar.gz | tar xz --strip=1 Claude-Skills-main/markdown-html/md-review
Run Python Tools
python markdown-html/md-review/scripts/tool_name.py --help