Kmd lint
Health check for a markdown knowledge base (Obsidian-compatible, the LLM-wiki pattern) — personal or shared. Use whenever asked to lint, audit, check, review, or clean up a KB, on any scheduled hygiene/maintenance run, or when KB quality is in doubt (stale pages, contradictions, broken links, unprocessed sources, index drift). Drift is the KB's primary failure mode; if in doubt whether a lint pass is warranted, it is.From its SKILL.md
npx -y skills add yasik/kmd --skill kmd-lintAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.3 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
kmd-lint — KB health check
A knowledge base rots by default: indexes drift from pages, claims go stale, duplicates accumulate, sources pile up un-ingested. Lint is the counter-force and it is not optional — every production implementation of the LLM-wiki pattern reports drift as the failure mode. Lint runs in two phases: deterministic checks (a script — free, exhaustive) and judgment passes (you — expensive, so spent only where scripts can't reach).
Before you start
Locate the KB root and transport the same way kmd-ingest does (its
references/obsidian-cli-transport.md covers the Obsidian CLI, whose
backlinks/orphans/unresolved commands can corroborate graph
findings when available): a path you were given >
$KMD_ROOT > .kmd.json at the workspace root > a directory containing
schema.md/log.md > the default kb/. The script's --kb flag implements
this resolution. Then check for the org extension: if .kmd.json declares
an "org" key or the workspace has _charter/ORG.md, read
references/org-extension.md — it changes how
findings are routed in Phase 3. Otherwise the core protocol below applies
as written.
Phase 1 — mechanical checks (run the script first)
python3 scripts/lint_mechanical.py --kb <kb-root> --report --agent <your-name-or-agent-id>
This checks: broken wikilinks, invalid/missing frontmatter (including the
provenance rule), modified files under sources/ (append-only violation,
via git — when the KB is not under git the script says so explicitly rather
than implying coverage), unreferenced sources (un-ingested intake), orphan
pages, page updates with no LOG entry, oversized pages, and a missing or
stale index.md (fix: recompile_index.py from kmd-ingest). With
--report it writes a
report skeleton to <kb>/.lint/<date>-mechanical.md (or the report_dir
configured in .kmd.json) with empty Judgment findings and Resolution
sections for you to fill in. Use --format json to process findings
programmatically.
Phase 2 — judgment passes (what scripts cannot catch)
Read index.md (or list pages) to plan the passes; read full pages only
where a pass flags something. Four passes, in order of value:
- Contradictions. Cluster pages that speak about the same entity/topic
(index descriptions and shared tags are good signals). Compare their
claims. Two pages asserting incompatible facts is the highest-severity
finding lint can produce — a KB that contradicts itself is worse than no
KB, because it answers confidently either way. When you find one, mark
both pages with the
> [!contradiction]callout per schema.md's framework (each side's claim, what would resolve it) — that marking IS a direct fix; the resolution itself is an open item unless dates, context, or primary sources settle it on the spot. The mechanical pass counts unresolved callouts on every future run. - Staleness. Pages whose
sources:have newer material filed insources/that they don't yet reflect; pages on volatile topics with oldupdateddates; claims with dates in them that have since passed. Flag, don't silently rewrite — the fix is a re-ingest against the newer source. - Near-duplicates. Pages whose titles/descriptions suggest the same concept split across two homes (the dedup gate at ingest time misses some). Propose a merge direction: which page survives, which becomes a redirect stub or is deleted after its unique content moves.
- Confidence downgrades. Pages marked
confidence: highwhose sources are thin (single bare URL, no filed source) or contradicted elsewhere. Downgrading confidence is a cheap, honest fix you can apply directly.
Phase 3 — triage and resolution
Every finding ends in exactly one of two places (core protocol):
- Fixed directly — mechanical, judgment-free repairs: a broken link whose
target was renamed, a missing frontmatter field derivable from content, a
confidence downgrade, an orphan page linked from the obvious related page.
Every fix you apply is itself a KB write: follow the kmd-ingest protocol
(bump
updated/authoron touched pages, validate, log with--action lint). - Recorded as open items — anything requiring knowledge the linter doesn't have (which side of a contradiction is true, whether a merge loses nuance, whether a stale claim still holds): write it into the report's Resolution section as a concrete, actionable item for the KB owner. Un-ingested sources are open items too — each is a pending ingest.
Org installations route instead of recording — judgment calls go to page authors' inboxes, intake to the owning agent. See references/org-extension.md; the report still records every handoff.
Complete the report (all three sections), then log the pass:
python3 scripts/kb_log.py --action lint --agent <your-name-or-agent-id> \
--title "lint pass: <N> errors, <M> warnings, <K> open items"
(kb_log.py ships with the kmd-ingest skill; a copy of the shared helpers is
bundled here — the log line matters more than which copy writes it.)
What lint never does
- Rewrite page content wholesale — lint repairs structure and surfaces judgment; substantive rewrites are re-ingests
- Touch anything under
sources/(append-only, even for lint) beyond restoring a tampered file to its committed state - Hand-edit
index.md(script-generated) or write log.md by hand - Silently "fix" a contradiction by picking a side — surface it; the owner or a re-ingest against sources decides
Done looks like
Script run clean or findings triaged → judgment passes done over the full page set → report with all three sections filled → open items concrete enough to act on (or handoffs delivered, in org mode) → one LOG entry. A lint pass that only runs the script is half a lint pass.
What ships with it: 4 files
44.6 KB alongside SKILL.md, 3 of them executable
references/
- org-extension.md3.0 KB
scripts/
- kb_common.pyruns22.1 KB
- kb_log.pyruns4.7 KB
- lint_mechanical.pyruns14.8 KB