wiki-lint: Wiki Health Check
Run lint after every 10-15 ingests, or weekly. Ask before auto-fixing anything. Output a lint report to wiki/meta/lint-report-YYYY-MM-DD.md.
Transport (v1.7+)
Lint primarily reads, then writes a single report file. Both follow the standard transport policy. Read .vault-meta/transport.json (auto-created by bash scripts/detect-transport.sh):
- cli —
obsidian-cli read "$VAULT" "$NOTE"for individual reads;obsidian-cli backlinks "$VAULT" "$NOTE"natively handles backlink graph (avoids re-rolling it via Grep); seeskills/wiki-cli/SKILL.md - mcp-obsidian / mcpvault —
mcp__obsidian-vault__read_multiple_notes,list_all_tags - filesystem — Claude's
Read/Glob/Grep(final floor; current v1.6 behavior)
Full decision tree: wiki/references/transport-fallback.md. DragonScale Mechanism 3 tiling lint is a separate code path (Python script) and bypasses transport selection.
Lint Checks
Work through these in order:
- Orphan pages. Wiki pages with no inbound wikilinks. They exist but nothing points to them.
- Dead links. Wikilinks that reference a page that does not exist.
- Stale claims. Assertions on older pages that newer sources have contradicted or updated.
- Missing pages. Concepts or entities mentioned in multiple pages but lacking their own page.
- Missing cross-references. Entities mentioned in a page but not linked.
- Frontmatter gaps. Pages missing required fields (type, status, created, updated, tags).
- Empty sections. Headings with no content underneath.
- Stale index entries. Items in
wiki/index.mdpointing to renamed or deleted pages. - Address validity (DragonScale Mechanism 2). For every page that has an
address:frontmatter field, validate the format. See the Address Validation section below. - Semantic tiling (DragonScale Mechanism 3, opt-in). Flag candidate duplicate pages (across all scanned types, not just concepts) via embedding cosine similarity. See the Semantic Tiling section below.
Lint Report Format
Create at wiki/meta/lint-report-YYYY-MM-DD.md:
---
type: meta
title: "Lint Report YYYY-MM-DD"
created: YYYY-MM-DD
updated: YYYY-MM-DD
tags: [meta, lint]
status: developing
---
# Lint Report: YYYY-MM-DD
## Summary
- Pages scanned: N
- Issues found: N
- Auto-fixed: N
- Needs review: N
## Orphan Pages
- [[Page Name]]: no inbound links. Suggest: link from [[Related Page]] or delete.
## Dead Links
- [[Missing Page]]: referenced in [[Source Page]] but does not exist. Suggest: create stub or remove link.
## Missing Pages
- "concept name": mentioned in [[Page A]], [[Page B]], [[Page C]]. Suggest: create a concept page.
## Frontmatter Gaps
- [[Page Name]]: missing fields: status, tags
## Stale Claims
- [[Page Name]]: claim "X" may conflict with newer source [[Newer Source]].
## Cross-Reference Gaps
- [[Entity Name]] mentioned in [[Page A]] without a wikilink.
Naming Conventions
Enforce these during lint:
| Element | Convention | Example |
|---|---|---|
| Filenames | Title Case with spaces | Machine Learning.md |
| Folders | lowercase with dashes | wiki/data-models/ |
| Tags | lowercase, hierarchical | #domain/architecture |
| Wikilinks | match filename exactly | [[Machine Learning]] |
Filenames must be unique across the vault. Wikilinks work without paths only if filenames are unique.
Writing Style Check
During lint, flag pages that violate the style guide:
- Not declarative present tense ("X basically does Y" instead of "X does Y")
- Missing source citations where claims are made
- Uncertainty not flagged with
> [!gap] - Contradictions not flagged with
> [!contradiction]
Dataview Dashboard
Create or update wiki/meta/dashboard.md with these queries:
---
type: meta
title: "Dashboard"
updated: YYYY-MM-DD
---
# Wiki Dashboard
## Recent Activity
```dataview
TABLE type, status, updated FROM "wiki" SORT updated DESC LIMIT 15
```
## Seed Pages (Need Development)
```dataview
LIST FROM "wiki" WHERE status = "seed" SORT updated ASC
```
## Entities Missing Sources
```dataview
LIST FROM "wiki/entities" WHERE !sources OR length(sources) = 0
```
## Open Questions
```dataview
LIST FROM "wiki/questions" WHERE answer_quality = "draft" SORT created DESC
```
Canvas Map
Create or update wiki/meta/overview.canvas for a visual domain map:
{
"nodes": [
{
"id": "1",
"type": "file",
"file": "wiki/overview.md",
"x": 0, "y": 0,
"width": 300, "height": 140,
"color": "1"
}
],
"edges": []
}
Add one node per domain page. Connect domains that have significant cross-references. Colors map to the CSS scheme: 1=blue, 2=purple, 3=yellow, 4=orange, 5=green, 6=red.
Address Validation (DragonScale Mechanism 2 MVP)
Opt-in feature. Address Validation runs only if the vault is using DragonScale, detected by:
if [ -x ./scripts/allocate-address.sh ] && [ -f ./.vault-meta/address-counter.txt ]; then
DRAGONSCALE_ADDRESSES=1
else
DRAGONSCALE_ADDRESSES=0
fi
When DRAGONSCALE_ADDRESSES=0, skip this entire section. Missing address: fields are not flagged, not even informationally. Pages that happen to have an address: field are passed through unvalidated (treat as user-managed metadata).
When DRAGONSCALE_ADDRESSES=1, proceed with the rollout baseline and checks below.
Rollout baseline: 2026-04-23 (Phase 2 ship date in vaults that adopted DragonScale on that day). Vaults that adopted DragonScale later should override this baseline by setting the earliest created: date of any addressed page as their personal rollout date. Record the chosen baseline at the top of .vault-meta/legacy-pages.txt as a commented line: # rollout: YYYY-MM-DD.
Classification rule (applied per page)
Before validating anything, classify the page:
| Classification | Criteria |
|---|---|
| Meta / fold / excluded | File is in wiki/folds/ OR filename in {_index.md, index.md, log.md, hot.md, overview.md, dashboard.md, dashboard.base, Wiki Map.md, getting-started.md}. Address not required. |
| Post-rollout (must have address) | type is not meta/fold AND frontmatter created: date is >= 2026-04-23 AND file path is NOT in the legacy baseline manifest. |
| Legacy (backfill-eligible) | type is not meta/fold AND frontmatter created: date is < 2026-04-23 OR file path IS in the legacy baseline manifest. Address not required until backfill. |
Legacy baseline manifest: optional file at .vault-meta/legacy-pages.txt, one relative path per line. Pages listed there are treated as legacy regardless of created: date. Use this to grandfather pages whose created: metadata is wrong or missing.
Validation checks (run in order)
-
Format check: any page with
address:set must match one of:^c-[0-9]{6}$— post-rollout creation address.^l-[0-9]{6}$— legacy-backfill address.- Pages under
wiki/folds/usefold_id, notaddress; do not apply thec-/l-regex there.
-
Uniqueness check: no two pages share the same address value. Report both paths.
-
Counter consistency:
./scripts/allocate-address.sh --peekreturns the next counter value. Every observedc-NNNNNNmust satisfyNNNNNN < peek_value. Violation = counter drift. -
Post-rollout enforcement: every page classified as "post-rollout (must have address)" that LACKS the
address:field is a lint error, not informational. This prevents the silent-regression path where a new page skips address assignment. -
Legacy identification: every page classified as "legacy" that LACKS an address is informational. The lint report lists them under "Pending backfill" with total count.
-
Address-map consistency (
.raw/.manifest.json):