ExQuality.Stages.Readme (ExQuality v0.16.0)

Copy Markdown View Source

Checks that a package's README.md keeps the shape of an introduction and a map: what the package is, why it exists, how to install it, one basic-usage snippet, and links to the rest grouped by the reader's question.

Nothing else in the gate reads the README as a whole, so a README drifts into a manual one helpful section at a time. This stage checks the shape, not the prose: it reads headings, paragraphs, code blocks and list indentation, and it never judges a sentence.

✓ README: 180 lines, every part present (0.0s)
✓ README: 2 warnings: no_why at README.md:1, over_ceiling at README.md:251 (0.0s)
✗ README: 2 problems (0.0s)

Each finding sits at a file:line in the README:

README.md
  1  [warning] no H2 section reads as the Why: none starts with "Why", "What this is for" or "The problem" (no_why)

Rules

  • no_what - the README has no H1, or no prose paragraph under it before the next heading, or that first paragraph runs over what_max_lines lines. Badge, image, HTML, blockquote, list and table blocks between the H1 and the paragraph are skipped: they are not the What.
  • no_why - no H2 starts with "Why", "What this is for" or "The problem".
  • no_install - no H2 starts with "Install", or the one that does carries no dependency snippet: a code block holding a {:package, ...} tuple.
  • no_basic_usage - no H2 starts with "Quick start" (or "Quickstart"), "Basic usage", "Usage" or "A first", or the first one that does holds no code block, more than one, or a block over forty lines. The section runs to the next H1 or H2, so its H3s are part of it.
  • ungrouped_documentation - an H2 starting with "Documentation" holds a link that is not on a nested list item: every link sits under a group item (- Learn, then the links indented beneath it). The finding is at the first such link and counts the rest.
  • over_ceiling - the README runs over the line ceiling, 250 by default. The finding is at the first line past it.
  • bad_manifest - .claude/diataxis.md exists and its front matter is unclosed, or its readme_max_lines is not a positive integer. The default ceiling applies, so a broken manifest never stops the stage.

Headings are matched on the start of their text, ignoring case. Headings and blocks inside fenced code are not read as structure.

What it does not check

Whether a link resolves. That is the Doc links stage's check (ExQuality.Stages.DocLinks), and this stage does not repeat it: enable both for a README that is shaped right and links right.

What it reads

README.md at the project root, and the front matter of .claude/diataxis.md when that file exists, for one key:

---
readme_max_lines: 300
---

It builds nothing and runs no tool.

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; that is the per-project flip once a README has the shape.

Opt-in

The stage is off by default, so no consumer's gate changes on upgrade. Enable it in .quality.exs:

readme: [enabled: :auto]                    # on when README.md exists
readme: [enabled: true]                     # forced
readme: [enabled: :auto, severity: :error]  # fail on any finding

Summary

Functions

Runs the README stage.

Functions

run(config)

@spec run(keyword()) :: ExQuality.Stage.result()

Runs the README stage.

Config options

  • enabled - false (default) | :auto (on when README.md exists) | true (forced)

  • severity - :warning (default) | :error

  • what_max_lines - the longest the first paragraph under the H1 may run (default: 6)