8.1 KiB
| name | description |
|---|---|
| polaris-lint | Health-check an Polaris vault: dead links, orphans, frontmatter and workstream-contract gaps, people-tier defects, unsourced reference material, vocabulary violations, misplaced files, stale holds, and an overdue log fold. Flags only — never auto-fixes. Writes exactly one wiki/meta/lint-report-YYYY-MM-DD.md stamped with the git commit it describes; the previous report is archived. Triggers on: lint, health check, audit the vault, check the vault, find orphans, find dead links. |
polaris-lint — vault health check
Flags only. Lint reports; the owner or the next session decides. (Repairs lint surfaces may then be made under the Repair rule in AGENTS.md.)
⛔ Fenced paths (AGENTS.md, Fences) are excluded from every check. Links into them are checked for existence only.
Scope — two kinds of check
The test: would this finding stop being true if nobody ever worked on this file again?
| Answer | Scope | |
|---|---|---|
| Attention | Yes — it's "this needs someone's attention" | Skip paused/closed/archived hubs and everything under 5. Archive/ |
| Integrity | No — it's "this is broken" | Run vault-wide, 5. Archive/ included |
A blanket archive skip on an integrity check hides broken links behind a clean report. Every new check classifies itself before it's written.
Run every check mechanically — glob and grep actual file contents, resolve every candidate. A finding produced by reading a sample and generalising is a hypothesis, not a finding. Spot-check anything surprising (a large round number, a well-known file reported broken) before it goes in the report.
Stamp the tree: record git rev-parse --short HEAD if the vault is a git repo, and say at the top if the working tree is dirty.
Integrity checks — vault-wide
1. Dead links. Every [[target]] / [[target|alias]] that resolves to no file. Strip fenced code blocks and inline code first — documentation examples aren't links. Resolve against full path, then bare filename anywhere in the vault. Report archive findings under their own heading.
2. Link style. Links containing .md ([[file.md]]).
3. Frontmatter contract. Against 6. Templates/_contracts.md:
- Every file below
0. Inbox/root in the numbered folders:type,updated(4. Decisions/usesdate). - Hubs:
typeisprojectorarea(hubis a defect) ·statusin the vocabulary. - Projects:
id,area(value or literalnone),done_whennon-empty ·paused_becausewhen paused · hub filename is<id>_hub.md. - Areas:
id_prefix,workstream_counter·parentnever equals the Area's own name. - Decisions:
date,topic,status. Threads:status,opened. - Exempt:
AGENTS.md,CLAUDE.md,README.mdand other vault-root files ·6. Templates/·0. Inbox/notes (they usedate+tags, notype). - Before reporting a missing field, check whether any file in that folder has ever carried it. A field absent from every file is a convention, not a set of defects.
4. ID integrity. For each Area, every issued ID <PREFIX>-N (in 1. Projects/ and 5. Archive/) has N ≤ workstream_counter. Any duplicate ID anywhere is a defect.
5. Provenance. Every type: reference file has a non-empty source: (or "source unrecorded" in the body). Report path and line count. Never auto-fixable — the owner confirms or strikes the source.
6. Vocabulary. For each row of AGENTS.md's vocabulary table, grep the Never use forms in vault-voice prose. Exempt: the table itself, lint reports, open-questions.md, 0. Inbox/processed/, and verbatim quotes of a source. If both the banned and canonical forms have zero hits, report the row itself as suspect — the table is data to be tested, not the test. An ordinary English word can only be enforced inside a scope the row names; if a row's scope can't be determined mechanically, report the row as unenforceable instead of its hits.
7. Stale index entries. Links in wiki/index.md or wiki/hot.md pointing at files that moved or don't exist.
Attention checks — live material only
8. Orphans. A file in the numbered folders with no inbound [[link]] from any other page. Collect every link target vault-wide (including archived hubs as sources), then test each candidate by full path and bare name. Also count backtick-quoted paths as references — report those separately as "referenced by path, not linked". Exempt: hubs · 4. Decisions/ · 3. Resources/Research/ root · 6. Templates/ · 0. Inbox/ · 5. Archive/ · vault-root files.
9. People tiers.
tier: relationshipwithoutcadenceorfollow_up_by→ defect (it can never flag).tier: contactcarryingcadenceorfollow_up_by→ defect.- A spent
follow_up_by(on or beforelast_contact) is not a defect. - An
organicpage whosefollow_up_byhas been pushed repeatedly with no contact (check git history if available) → finding: that's a cadence that never fires.
10. next: validity. Each entry uses send/wait/build/decide; send/wait name a person. Report every send/wait older than 14 days at the very top of the report, above every structural finding — an unsent message is worth more than all of them.
11. Misplaced files. Hubs outside 1. Projects//2. Areas/ · person pages outside People/ · decisions outside 4. Decisions/ · content files in wiki/ other than hot.md, index.md, log.md, folds/*, meta/* · binaries (pdf, images, office files) anywhere in the vault · a file in 3. Resources/Research/ root carrying an Area tag · reference material inside a Project folder with no Area tag.
12. Standalone Areas. A standing Area with no live Project and updated: older than 30 days. Report as context — it may be quiet on purpose.
13. Holds. An open hold older than 30 days with no end date · an open hold with no start date older than 7 days. A hold never discharges an obligation — report open sends alongside it.
14. Log fold. Unfolded entries (headings minus [folded] pointers) against the threshold of 16 — print the count every run. Also: any unfolded entry sitting below a [folded] pointer is a hole from a middle-window fold.
Report — wiki/meta/lint-report-YYYY-MM-DD.md
Retention 1. Before writing, move any previous lint report to 5. Archive/wiki-meta/.
---
type: meta
title: "Lint report YYYY-MM-DD"
created: YYYY-MM-DD
commit: abc1234
tree_clean: true
supersedes: lint-report-YYYY-MM-DD
tags: [meta, lint]
---
## Outstanding sends — before anything structural
## Summary ← one line per check: count, or "clean"
## Dead links
### Inside 5. Archive/
## Frontmatter & contracts
## IDs
## Provenance
## Vocabulary
## Orphans
## People
## Misplaced files
## Areas & holds
## Log ← "unfolded: N / 16" — always printed
## Carried findings — second cycle
Omit empty sections except Summary and Log.
The two-cycle rule
A finding that survives two consecutive lints without action is a decision nobody has made. Second appearance: list it under Carried findings. Third: remove it from the report and add it to wiki/meta/open-questions.md as a forced binary — **<Question>** — Option A / Option B. Raised YYYY-MM-DD. Then stop reporting it.
Corollary — the more important half: when a check keeps producing the same backlog, suspect the check. A rule nobody ever acts on is usually wrong, not ignored.
Output (to chat)
## Lint — YYYY-MM-DD @ <commit>
Sends > 14 days: N
Integrity: N dead links (N in archive) · N contract gaps · N provenance · N vocabulary
Attention: N orphans · N people defects · N misplaced
Log: N / 16
Report: wiki/meta/lint-report-YYYY-MM-DD.md
Rules
- Flags only. No auto-fix.
- Attention checks skip retired material; integrity checks run everywhere.
- Mechanical, exhaustive, spot-checked. Never estimate.
- Sends outrank structure.
- One report at a time, stamped with its commit.
- Two-cycle rule — and question the check before the files.