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. The rules it enforces are listed in audit-rule-catalog. 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. The spec’s shape is covered in vault-frontmatter-schema.

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. Check spec_status in the JSON summary before trusting any zero.

Run it from the vault root and reason over the JSON

cd <vault-root> && python3 99-Tools/audit.py --format both

One run writes a human-readable report, a machine-readable report, and a one-line entry in a running log under 99-Tools/audits/, and archives the previous reports. Reason over the JSON: each violation carries a rule id, a severity, a file, a message, and a fix hint. Exit codes carry the same information for CI: 0 clean, 1 warnings present, 2 criticals present. Installing the auditor into a new or existing vault is walked through in bootstrap-a-research-vault.

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.

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. The narrow set of mechanical fixes the auditor may apply on its own is bounded in audit-rule-catalog.

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 the 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 in vault-maintenance is actually happening. In a shared vault, the same run gates every merge, per vault-pull-request-review.