Detect when documentation has drifted from the code: stale-doc signals, automated drift checks, triage, and targeted fixes. Use when someone asks whether docs are accurate, to audit docs before a release, to wire doc-freshness checks into CI, or when a doc example no longer matches the code.
./install.sh doc-staleness-detectionname: "doc_staleness_detection" description: "Detect when documentation has drifted from the code: stale-doc signals, automated drift checks, triage, and targeted fixes. Use when someone asks whether docs are accurate, to audit docs before a release, to wire doc-freshness checks into CI, or when a doc example no longer matches the code."
Find the places where docs and code disagree, rank them by how badly they mislead a reader, and fix the ones that matter. Docs rot in predictable ways: renamed symbols, changed defaults, dead links, API specs nobody re-checks, and examples that stopped working. This skill gives you a repeatable way to catch that drift instead of trusting the docs blindly.
Pick the docs that carry risk: README, install guides, API references, architecture docs, runbooks. Skip changelogs and marketing pages; they drift differently and rarely mislead. Write the scope down so the same set gets re-checked next time.
Use the bundled checker first (bin/check_doc_staleness.py):
bash
python3 bin/check_doc_staleness.py --docs docs/ --src src/ --repo .
It reports, per markdown file:
#anchor that does not resolve to an existing file or heading.Details on the heuristics live in references/signals.md.
For API specs, run the spec-vs-spec and spec-vs-code checks:
bash
oasdiff breaking openapi.base.yaml openapi.current.yaml
spectral lint openapi.current.yaml
See references/signals.md for the CI wiring (GitHub Action recipe with a reviewable override path).
Automation catches identifier drift. It does not catch meaning drift. For each doc in scope, extract its atomic claims and check them against current code. The four claim types that rot silently:
pyproject.toml says 2.9. Check every version number in prose against the manifest.Not every finding deserves a fix. Score each one on two axes: how many readers hit it (README install steps = everyone, internal runbook = few) and how expensive a wrong belief is (wrong auth flow costs days, a dead anchor costs seconds). Fix high-readership or high-cost items in this pass. File the rest as a dated backlog entry with the evidence, so the next audit can re-triage.
Rewrite only the stale claim, not the surrounding page. Every updated claim needs a source-of-truth pointer: a file path and line, a spec URL, or a commit. Then stamp the doc: add or bump a Last verified: YYYY-MM-DD header so the next audit knows how old the check is.
Before/after examples:
markdown
# BEFORE (stale)
We use Redux Toolkit with createSlice for all global state.
# AFTER (verified against src/store/, commit 9f2a1c)
We use Zustand for client-side global state (src/store/, verified 2026-10-08).
markdown
# BEFORE (dead flag)
Run the importer with `--batch-mode` to skip prompts.
# AFTER (verified against src/importer/cli.py)
Run the importer with `--non-interactive` to skip prompts
(src/importer/cli.py:44, flag renamed in v1.7).
A staleness audit returns:
Last verified: YYYY-MM-DD bumped on every audited doc.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.