A working mine keeps two things: the coal and the ledger. The ledger is the written record β and a mine with a wrong ledger is lying to everyone who reads it. This one keeps your DOCS healthy: CoalMine for documentation.
A docs-health canary suite β 6+1 canaries that catch the six ways a doc goes bad (wrong Β· incomplete Β· stale Β· contradictory Β· broken Β· unreadable, plus config-gated leaked), detection through a vendored CommonMark+GFM AST engine so things that render fine are never flagged, severity judged by context, and fixes always behind a choice-gated menu β never auto-applied.
Changelog Β· Security Β· Privacy Β· Releases
Part of TheColliery β siblings: CoalMine (quality canaries) Β· CoalTipple (model/effort routing) Β· CoalBoard (consensus board) Β· CoalHearth (warm-resume) Β· CoalFace (fan-out discipline) Β· CoalWash (memory defrag).
Code has linters, tests, and CI; docs mostly have hope. A README that drifted from the code, a translated doc that stopped matching its counterpart, a dead install link, a stale version badge β each is silent breakage a reader trusts. CoalLedger is the docs-side mirror of CoalMine's code canaries: a cheap, always-available health scan for ANY document β a README, a spec, a report, a translation β not just developer docs. The source of truth a doc is checked against is whatever it renders: the code, the data, an original text, or reality.
Seven canaries, one distinct failure mode each:
| # | Canary | Catches | Layer |
|---|---|---|---|
| 1 | doc-grounding |
WRONG β claims β their source of truth (code Β· data Β· original text Β· reality); verified real-time, multi-source; offline degrades to β οΈ unverified |
semantic + mechanical recompute |
| 2 | doc-standard |
INCOMPLETE β missing vs the doc kind's standard (required sections, undocumented public surface) | semantic + mechanical |
| 3 | doc-rot |
STALE β old versions/dates/badges, dead TODOs, superseded instructions | mechanical age-markers + semantic |
| 4 | doc-consistency |
CONTRADICTORY β docs disagreeing, terminology drift, cross-language drift | semantic |
| 5 | doc-structure |
BROKEN β links/anchors/headings/tables/refs, via the AST engine | mechanical |
| 6 | doc-quality |
UNREADABLE / MALFORMED β bloat, unclear prose, language mechanics (typo Β· grammar Β· spelling Β· orthography) | semantic + mechanical |
| 7 | doc-leak (config-gated) |
LEAKED β prose-level sensitive content in a public-facing doc; token-shaped secrets stay gitleaks' job | semantic, SUSPECTED-only |
Two tiers, one discipline:
- Quick = the mechanical layers β deterministic, ~free, report-only.
- Full = the semantic layers β model judgment, paid, always a separate consent.
- Detection is mechanical; severity never is. A broken link in an archive is LOW; the same link in an install step is CRITICAL β every finding is judged in context, and CONFIRMED findings are reported separately from SUSPECTED ones (anti-cry-wolf).
- Fixes are choice-gated. Every report ends in a menu (apply safe fixes / let me pick / report only); a live doc is never auto-edited.
Important
CoalLedger checks docs-HEALTH, not content correctness. It verifies only what it can fetch or recompute; a claim needing formal verification β a proof, high-precision math, an error-not-allowed decision β escalates to CoalBoard. And the AST engine's honest ceiling is CommonMark+GFM fidelity, not "100% GitHub-pixel fidelity" β known host-specific quirks are flagged as limits, not silently guessed.
Multilingual by construction: the mechanical layers are language-agnostic (an AST does not care what language the prose is; sections are detected by structure, never an English keyword), and the semantic layers work in the doc's own language, degrading to low-confidence flags β never false alarms β on a poorly-handled one. Cross-language drift between a doc and its translation is a first-class check.
Cross-agent by design β the canaries are plain SKILL.md contracts and the engine is zero-dependency Node scripts any agent can run. The activation ladder is capability-keyed, never a platform table: has lifecycle hooks β wire the shipped session-start conductor (Claude Code today) and the canaries offer themselves at the right moment; no hooks β best-effort agent-driven (an always-loaded instruction can offer the right canary β probabilistic, not hook parity); always β manual (invoke doc-structure, doc-grounding, β¦ or ask for a docs scan).
Claude Code β one command pair (also wires the session-start conductor):
claude plugin marketplace add TheColliery/CoalLedger
claude plugin install coalledger@coalledgerOther agents β file-copy: copy skills/ (the seven canary contracts) and scripts/lib/ (the AST engine) into your platform's skill directory, keeping the relative layout (each SKILL.md resolves the engine at ../../scripts/lib). The conductor hook is Claude-Code-only; elsewhere invoke the canaries manually. No API keys, no network, no npm install.
Every tool in the series supports two config levels β a global ~/.claude/.coalledger.json and a per-project .coalledger.json override (project wins) β so a globally-installed skill can be tuned or shut off per project (coalledgerMode: "off" is the off-switch; a project can also disable single canaries or raise the severity floor instead). The keys:
| Key | Default | What it does |
|---|---|---|
coalledgerMode |
auto |
Conductor switch: auto = session-start conductor offers the canaries Β· manual = the conductor stays silent, invoke canaries yourself Β· off = the conductor never runs. (Orthogonal: the self-update nudge has its own switch β updateMode: "off" β so manual silences the canary offers, not the periodic update check.) |
language |
auto |
Language for prompts and reports (auto | th | en | ja | zh | es); technical terms stay verbatim |
disabledCanaries |
[] |
Canary names to disable (e.g. ["doc-quality"]); "conductor" or "all" silences the conductor entirely |
severityFloor |
low |
Report findings at or above this severity (judged by context, never mechanically) |
quickVsFull |
quick |
Default scan tier for mixed canaries: quick = mechanical only (~free) Β· full = adds the semantic layer (paid; always a separate consent) |
docLeak |
true |
The #7 doc-leak canary's gate β a private-only project (docs never published) turns it off |
publicMode |
false |
Treat this project's docs as public-facing (raises leak/grounding stakes in severity context) |
updateMode |
ask |
Self-update behavior at session start (ask | auto | remind | off) |
updateCheckDays |
14 |
Days between self-update checks/reminders |
Full key reference: every key + default lives in scripts/lib/config-schema.mjs and the commented template platform-configs/.coalledger.json.
Not yet measured β CoalLedger launches unbenchmarked rather than with an invented number. The engine's mechanical layer is fixture-gated in-repo (planted defects found, clean decoys silent β scripts/verify.mjs runs it); the first published benchmark (recall on seeded doc-defect fixtures, canary-by-canary, dated + versioned) will live at TheColliery/.github/benchmarks like every sibling's.
CoalLedger is the docs-health member of the mining series, alongside CoalMine (quality canaries), CoalTipple (model/effort routing), CoalBoard (consensus & debate), CoalHearth (session warm-resume), CoalFace (fan-out discipline), and CoalWash (memory defrag). CoalMine + CoalLedger form the broad, cheap health layer (code + docs); CoalBoard is the deep verify they escalate the error-not-allowed slice to. Install one and it stands alone; install all and they compose without conflict. Shared doctrine: Phoenix-13 hooks (zero-dependency, no network, fail-silent), single-source-of-truth config schemas, consent-gated spend, and a strict no-overkill discipline. Series doctrine: TheColliery/.github.
Zero-dependency, offline by default, no API keys.
Apache License 2.0. See LICENSE.