Checks that each page under a documentation quadrant reads as the kind of page its folder says it is: a tutorial teaches, a how-to guide shows the steps to a goal, a reference page describes, an explanation gives reasons.
Pages drift between kinds one helpful paragraph at a time, and a model-based audit catches that only when someone runs it. This stage is the cheap, deterministic half: it counts a fixed list of language cues on each page and reports a page whose cues point clearly at another kind.
✓ Diataxis: 12 pages, each reads as its type (0.0s)
✓ Diataxis: 1 warning: how_to_title at docs/guides/upgrade.md:1 (0.0s)
✗ Diataxis: 2 problems (0.0s)What it reads
The front matter of .claude/diataxis.md, the project's documentation
manifest, for its quadrants: map:
---
quadrants:
tutorials: docs/tutorials
how_to: docs/guides
reference: docs/reference
explanation: docs/explanation
---Then every .md file under each of those paths. A page's declared type is
its folder's quadrant, or the type: key in the page's own front matter
when it has one (tutorial, how-to, reference or explanation). A page
under two quadrant paths belongs to the deeper one. A project without the
manifest has nothing to read, and the stage reports nothing.
How a page is read
Fenced code, inline code and link targets are dropped first. Each cue then scores for one type:
- a cue phrase anywhere on the page scores 1 for each time it appears;
- a cue phrase in the first paragraph under the H1 scores 3 instead (the phrases that open each kind of page);
- an H1 starting "How to" scores 3 for a how-to guide; one starting "About" or "Why", or ending "explained", scores 3 for an explanation;
- "you will" and "you'll", the second-person future, score 1 each for a tutorial;
- imperative steps (list items opening with a verb such as "Run" or "Add") score 2 for a how-to guide when there are at least three and they make up at least a third of the page's paragraphs and list items.
A page reads as a type when that type scores at least 3 and more than twice any other type. A page whose cues are too few or too mixed is not judged.
Rules
type_mismatch- the page reads as a different type from the one it declares. The message carries every type's score.how_to_title- a page declared a how-to guide has an H1 that does not start with "How to", or no H1.bad_type- the page's front matter carries atype:that is not one of the four. Its folder's type applies.bad_manifest-.claude/diataxis.mdhas front matter that never closes, or noquadrants:map with a path in it.
Severity
Findings are warnings by default: the stage reports them, names each one in
its summary line and in the JSON report, and passes. severity: :error
makes every finding an error and fails the stage on any of them.
Opt-in
The stage is off by default, so no consumer's gate changes on upgrade.
Enable it in .quality.exs:
diataxis: [enabled: :auto] # on when .claude/diataxis.md exists
diataxis: [enabled: true] # forced
diataxis: [enabled: :auto, severity: :error] # fail on any finding
Summary
Functions
Runs the Diataxis stage.
Functions
@spec run(keyword()) :: ExQuality.Stage.result()
Runs the Diataxis stage.
Config options
enabled-false(default):auto(on when.claude/diataxis.mdexists) true(forced)severity-:warning(default) |:error