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.
At a glance
Section titled “At a glance”| 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.
doc_freshness
Section titled “doc_freshness”“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.
doc_drift (Type 1: dangling identifier)
Section titled “doc_drift (Type 1: dangling identifier)”“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.
doc_coverage
Section titled “doc_coverage”“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.
doc_link_health
Section titled “doc_link_health”“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.
orphan_pages
Section titled “orphan_pages”“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.
todo_density
Section titled “todo_density”“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.
Markdown duplication
Section titled “Markdown duplication”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.
Drain pattern
Section titled “Drain pattern”/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, orheal mark acceptif the team decided this source doesn’t need its own doc.
See Docs › Skills for the full contracts.