Overview
A vault without an auditor degrades invisibly. Orphans accumulate, required fields go missing, verification dates go stale, and none of it announces itself. The auditor is a script that lives in the vault (99-Tools/audit.py), reads the vault spec, and reports structural and schema violations deterministically. Judgment-level defects are a separate pass, covered in semantic-audit.
Split the checks into three buckets and automate the first two
- Bucket 1, structural. Orphans, broken links, missing frontmatter, filename convention, folder placement. Framework-agnostic.
- Bucket 2, schema. Framework-specific requirements: an ADR without alternatives, a theme atom with too few linked data points, a result atom with no hypothesis.
- Bucket 3, semantic. Is this title actually a claim? Does this atom hold one idea? Was this pre-decision section rewritten? Requires reading.
Buckets 1 and 2 are code and should never be done by hand or by a model. Bucket 3 is the only place judgment belongs.
Configure the audit from the vault spec, not from flags
The auditor reads vault-spec.yaml at the vault root for note types, required fields, folder mapping, thresholds, and severity overrides. Adding a note type or making a field required is a spec edit that the auditor picks up with no code change.
Treat a missing spec as a failed audit, not a clean one. An auditor running on built-in defaults is checking someone else’s vault: it should print a loud warning, emit a meta finding, and exit non-zero, so a “clean” result can never be a spec that failed to load.
Know the rule catalog and its severities
The rule ids are the shared vocabulary between the script, the triage step, and the agent acting on the report.
| Rule | Finding | Severity |
|---|---|---|
| C000 | Frontmatter unparseable | critical |
| C001 | Orphan atom, no inbound or outbound links | warning |
| C002 | Broken wikilink | warning |
| C003 | Missing frontmatter | warning |
| C005 | Decision modified after its decision date | critical |
| C007 | Decision past its expected resolution date | warning |
| C008 | Required field missing or empty | warning |
| C009 | Atom past the atomicity byte threshold | warning |
| C011 | Publishable claim failing the corroboration or review gate | critical |
| C012 | Stale verification on a decision-relevant claim | warning |
| C014 | Note filed outside its type’s folder | warning |
| C015 | Content note with an absent or unmappable type | warning |
C015 matters more than it looks: without it, a note with no type silently evades every per-type check, so the cleanest way to pass the audit is to strip the field that makes a note checkable.
Exit codes carry the same information for CI: 0 clean, 1 warnings, 2 criticals.
Triage by root cause, not by rule id
A flat list of 30 violations is noise. The same 30 grouped by cause is a work plan.
- Eight orphans clustering on one theme: a missing MOC, not eight missing links.
- Five unsourced claims from one book: one source-backfill session.
- Three overdue decisions in one class: one resolution-review session.
- Many atomicity violations in one folder: a domain that grew too fast, so one refactor session.
- One hindsight rewrite: handle it alone, immediately.
Present criticals first and individually, warnings grouped by cluster with a proposed batch action, and info items as a list for the next review.
Autofix only the mechanical tier
An autofix pass should repair what it can derive with certainty and nothing else: adding a frontmatter block with the type derived from an unambiguous folder, filling id from the filename and dates from file mtime, and repairing a broken link when exactly one filename matches.
Everything semantic is left alone. An autofix that invents a title, a source, or a confidence value is fabricating research provenance. Dry run by default, require an explicit apply flag to write, and refuse to write an un-versioned vault without a further override, because there is no undo otherwise.
Pause before bulk structural changes
Bulk renames, folder moves, and schema migrations that touch dozens of notes get a scope freeze: state the exact path list, state what undo looks like, and get explicit approval before applying. Operations that look obviously correct from a report are the ones most likely to sever a link network.
Never silently mutate a vault you audited. The report proposes; the owner accepts. This is doubly true when the auditor is being run by an agent, per vault-orchestration.
Re-run and show the delta
After fixes, run the audit again. Report resolved findings by rule id, new findings introduced (adding a link can create a broken one), and the net change per severity.
Append every run to a log so the numbers become a trend. “Orphans down four, unsourced atoms up two this week” is worth more than any single snapshot, and it is what tells you whether the weekly review is actually happening. In a shared vault, run the auditor as a pull request check with criticals blocking merge, per team-vaults and the workflow patterns in github-actions.