Skip to content

Docs · Metrics

The opt-in Docs family adds seven metrics on top of the always-on Code family. Each one targets a specific way documentation drifts from the source it describes.

For configuration knobs see Docs › Configuration. For the skills see Docs › Skills.

Metric Layer What it flags Severity
doc_freshness A (paired) source commits since the paired doc last changed floors (default ≥ 5 High, ≥ 20 Critical)
doc_drift A (paired) doc references an identifier no longer in the paired source uniform Critical
doc_coverage A (paired) pair entry whose doc path doesn’t exist on disk uniform Medium
doc_link_health A + B internal relative-path / #anchor link doesn’t resolve uniform High
orphan_pages B (standalone) Layer B doc not linked from anywhere; not paired uniform Medium
todo_density A + B TODO / FIXME / XXX / TBD / [要確認] / [要修正] markers per doc ≥ 3 Medium, ≥ 10 High
doc_hotspot A (paired) paired_src_churn × debt composite — flips hotspot=true on docs-family Findings always Ok (decoration carrier)

Layer A (paired docs) needs a doc ⇔ src mapping in .heal/doc_pairs.json, generated by /heal:setup docs. Layer B (standalone prose docs) is auto-discovered via the [features.docs.standalone] include / exclude globs.

“Has the source moved since the doc was last touched?”

Per-pair source-commits-since-paired-doc count. Distance is measured in git commits, not wall-clock days, so the threshold doesn’t shift as the team’s commit pace changes. Floors live in [features.docs.doc_freshness] — defaults: ≥ 1 Medium, ≥ 5 High, ≥ 20 Critical.

“Does the doc still reference identifiers that exist in the source?”

Scans each Layer A doc, extracts identifier-shaped backtick spans (`Foo::bar`, `processOrder`), and emits a Finding for each one that doesn’t resolve to any identifier in the paired source. Severity: Critical — a reader acting on a missing identifier wastes time looking for code that no longer exists. The fix is mechanical: remove the reference, or restore the identifier under its new name.

Type 2 (signature mismatch) is not implemented yet. Type 3 (semantic drift) ships as doc_drift.semantic when Semantic (Jev) is enabled.

“Does the paired doc actually exist on disk?”

Pair entries whose doc path doesn’t exist. Severity: uniform Medium by design — Critical here would incentivise empty-stub manufacturing. Medium says “consider writing this”, not “you must”. The fix is either real content or heal mark accept recording the “won’t doc” decision.

“Do the internal links in the docs resolve?”

Per-link Findings: MissingPath (relative-path link doesn’t resolve to a file) and MissingAnchor (#anchor doesn’t match any heading in the target). Heading slugs follow the GitHub-style convention (lowercase + non-alnum → -). Severity: High — internal breaks are mechanical to fix and high-impact for readers.

External HTTP links are out of scope — heal is local-only; lychee and similar cover HTTP in CI.

“Which Layer B docs aren’t reached from anywhere?”

Layer B docs that aren’t linked from any other doc and aren’t paired. Conventional entry points (README.md, index.md at any depth) are seeded as “linked” so they don’t trip the metric. Severity: Medium — an orphan doc isn’t broken, just hard to discover; the fix is usually a one-line link from the parent README.

“How many open TODOs is each doc carrying?”

Per-doc count of TODO / FIXME / XXX / TBD / [要確認] / [要修正] markers. Markers inside fenced code blocks (and, by default, backtick-quoted inline code) are excluded so a reference page that describes the marker keywords doesn’t self-flag every paragraph. Severity: ≥ 3 Medium, ≥ 10 High.

When [features.docs] is on, the Duplication observer runs a parallel pass over Markdown / RST files. Findings land under the same duplication metric string as the code-side blocks; the distinguisher is the file extension.

The use case is spotting docs copy-pasted across language mirrors (en + ja), across module-specific READMEs, or across API reference pages with shared boilerplate — the fix is usually a “see also” link plus a single canonical source.

Window length is [metrics.duplication].docs_min_tokens (default 100).

Doc Hotspot — which paired doc is most worth updating

Section titled “Doc Hotspot — which paired doc is most worth updating”

Doc Hotspot is the docs-family analogue of code Hotspot. It ranks paired doc ↔ src entries by paired_src_churn × debt, where debt = src_commits_since_doc + weight_drift × dangling_idents. A pair scores high when the source is moving fast and the doc has fallen behind — “of all your docs, this is the next one worth updating”.

Only paired entries from doc_pairs.json are scored. Standalone docs (READMEs, concept guides) live under orphan_pages / todo_density instead.

Doc Hotspot itself always carries Severity::Ok; it decorates the docs-family Findings (doc_freshness, doc_drift, doc_coverage, doc_link_health, todo_density) so the same 🔥 flag points at the next doc-pair worth updating.

/heal:docs frames findings through the Diátaxis lens, but preserves HEAL’s exact effective Tier, Severity, then descending Docs-family hotspot_score order (missing scores last; metric/path/id ties). Tutorial / How-to / Reference / Explanation informs the diagnosis and remedy, not queue priority. The proposals you approve are applied one commit at a time:

  • doc_link_health → fix the relative path or anchor slug.
  • doc_drift → remove the stale reference, or restore the identifier under its new name on a clear rename.
  • doc_freshness → re-read the paired source and update the doc.
  • orphan_pages → add a link from the parent README, or delete the orphan.
  • todo_density → resolve the resolvable TODOs; escalate the rest to issues.
  • doc_coverage → write a real stub, or heal mark accept if the team decided this source doesn’t need its own doc.

See Docs › Skills for the full contracts.