Skip to content

Repository files navigation

📒 CoalLedger

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), structure 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.

version license status

Claude Code: validated Antigravity: wired Cursor: manual Codex: manual Gemini CLI: manual Cline: manual Copilot: manual claude.ai: manual

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).


📒 What it is

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.

⚙️ How it works

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.

Docs memory-drift reminder

Separate from the canaries — it scans nothing and reports nothing. If documentation files (.md .mdx .markdown .rst .txt .adoc .asciidoc .org) were edited but MEMORY.md has not been updated this session, CoalLedger emits one quiet reminder to the agent when the agent finishes responding: no findings, no fix menu, and it never blocks. Update MEMORY.md once and it stays quiet for the rest of the session. It fires only where the project uses the MEMORY.md convention (a MEMORY.md at the project root), and docsDriftNudge: false silences it. Capability-keyed like everything else here — it needs a stop hook that can pass context back to the model, which today means Claude Code (Antigravity's engine documents no such channel).

This is the DOCS half of a pair: CoalMine's memoryDriftNudge covers CODE edits, CoalLedger's covers DOC edits. The two watch disjoint file extensions, and a single MEMORY.md update satisfies both.

🧭 Compatibility

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 — validated; Antigravity — wired via a ported adapter, live delivery not yet validated) 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).

Support tiers, honestly labeled: Claude Code — validated (live plugin, launched + dogfooded 2026-07-09) · Antigravity — wired (the conductor's offers ride AG 2.0's PreInvocation hook through a ported adapter, built and hermetically tested against the current AG contract — see Install for the wiring caveat) · every other skill-reading platform — manual (the file-copy install below suffices, because read/analyze canaries need only a platform that reads SKILL.md — but nothing has been run end-to-end there, so no higher claim). Gemini CLI is business-tier only (Standard/Enterprise — individual tiers ended 2026-06-18).

🚀 Install

Claude Code — one command pair (also wires the session-start conductor and the quiet docs memory-drift reminder):

claude plugin marketplace add TheColliery/CoalLedger
claude plugin install coalledger@coalledger

Antigravity — file-copy: copy the built skill folders from plugin/skills/ into ~/.gemini/config/skills/ (global) or <workspace>/.agents/skills/ (project). Each folder is self-contained — doc-structure carries the AST engine beside itself in its own lib/, so nothing else has to travel with it. (Copy from plugin/skills/, not the repo's skills/: the latter holds the contracts only, without the engine.)

Auto conductor on AG (wired — live AG validation pending): AG 2.0 shipped a real hook engine, so the canary offers can ride Antigravity's PreInvocation too, through hooks/ag-conductor.js (requires its sibling hooks/coalledger-conductor.js — one offer text for both platforms). The conductor is the one piece that needs more than a skill folder: copy hooks/ and scripts/lib/ side by side (the hooks resolve the shared config library at ../scripts/lib), then copy platform-configs/hooks.json into place and replace __COALLEDGER_DIR__ with the directory holding them. Known caveat: the wire location itself regressed on an AG update (2026-07-12 → 07-16) — the two previously-documented locations (global ~/.gemini/config/hooks.json, project <workspace>/.agents/hooks.json) stopped executing, and the AG state dir moved — so re-derive the current hooks.json location from AG's own docs before wiring (the template carries the same note). Wiring at a dead path is inert-harmless: the adapter simply never runs, and manual canary invocation is unaffected either way. Once wired, the directive fires at most once per session; delivery into the agent is not yet live-validated. The self-update nudge is deliberately not ported (its payload is Claude-Code plugin machinery); on AG, update by re-copying.

Other agents — the same file-copy from plugin/skills/ into your platform's skill directory. No install.mjs step — the canaries are plain SKILL.md contracts over the zero-dep engine.

claude.ai — read/analyze skills (like CoalLedger's canaries) upload as a custom skill: ZIP one folder from plugin/skills/ (already complete — doc-structure includes its engine) and add it in claude.ai's skill settings (paid plan with code execution on). Per-surface — an upload doesn't sync across surfaces.

The conductor hook wires automatically on Claude Code (validated) and, once you complete the AG wiring above, on Antigravity (wired, pending live validation); every other surface runs the canaries manually (invoke doc-structure, doc-grounding, … or ask for a docs scan). No API keys, no network, no npm install.

Commands

Command What it does
/coalledger:doc-structure Runs one doc canary on the files you name. The other six take the same form — /coalledger:doc-grounding, /coalledger:doc-standard, /coalledger:doc-rot, /coalledger:doc-consistency, /coalledger:doc-quality, /coalledger:doc-leak — and what each one catches is the table in How it works.
/coalledger:stats Reports the scans run and findings this session by canary and severity, plus which canaries are enabled here and at what severity floor. Read-only, session-local.
/coalledger:update Checks for a newer CoalLedger version and offers to apply it, or sets how updates are handled.

Slash commands are the Claude Code form. Everywhere else the canaries are invoked the way your agent invokes a skill — by name (doc-structure, doc-grounding, …) or by just asking for a docs scan.

🔧 Configure

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) — a skill you don't need in a given project stops loading (and burning tokens) there. 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)
docsDriftNudge true The off-switch for the quiet docs memory-drift reminder; set false to silence it
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.

Permissions

Reads the docs you name (plus the files their links point at, to verify those links) and your .coalledger.json. Writes only its own scratch: two session files in your temp dir, a self-update date stamp under ~/.claude/, and on Antigravity a once-per-session marker. Runs up to three things locally: the bundled zero-dependency AST engine (node ./lib/md-checks.mjs, read-only), a git stash/commit checkpoint before any fix (a file copy where git is absent), and — only if you consent — a documented example a doc claims works.

Never edits a doc on its own. Every fix is a choice-gated menu item you pick; no file is ever deleted, and CoalLedger spawns no subagents, so nothing runs with more power than the session you started. Network is opt-in only: the paid Full tier's real-time source verification (doc-grounding, doc-standard) and the self-update check, each consented separately — offline they degrade to ⚠️ unverified, never a guess.

Full series matrix + the must-fail set: Permission Matrix

📊 Benchmark

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 digest at benchmarks/CoalLedger/RESULTS.md will fill in from the first dated, versioned run (recall on seeded doc-defect fixtures, canary-by-canary), like every sibling's.

🧭 Part of TheColliery

CoalLedger is the docs-health member of the mining series:

Install one, it stands alone; install all, they compose without conflict. CoalMine + CoalLedger form the broad, cheap health layer (code + docs); CoalBoard is the deep verify they escalate the error-not-allowed slice to.

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 — "by default" because the consent-gated Full tier's source verification (doc-grounding, doc-standard) and the self-update check go online; the hooks and the engine never do.


📄 License

Apache License 2.0. See LICENSE.

About

Docs-health canary suite for AI coding agents - CoalMine for documentation. 6+1 canaries, with doc-structure detected by a zero-dep CommonMark+GFM AST engine; severity by context, fixes choice-gated, never auto-applied. Also nudges quietly when docs change but MEMORY.md does not. Part of TheColliery.

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages