PRE_COMMIT_AUDIT.md — Mandatory Pre-Commit Gate
This file is a protocol — like AUDIT_PROTOCOL.md but tighter, faster, and run BEFORE EVERY COMMIT. It defines the light audit that gates every change to the vault. Read once; mechanise forever.
1. Why this exists
Every commit must leave the vault in a structurally clean state. Catching gaps after the fact is expensive — by the time the full QC agent runs at end of session, broken wiring may have propagated across multiple commits.
The full AUDIT_PROTOCOL.md agent is slow (3–10 min per invocation) and overkill for the inner-loop check before every commit. This protocol defines the light audit — fast enough to run on every commit (≤5 sec), narrow enough to focus on the structural dimensions where drift causes real damage.
2. The mandate
Every commit MUST run the light audit before being made.
This applies to:
- Manual commits by the human user.
- Commits produced by Claude (the primary agent).
- Commits produced by sub-agents that have commit authority.
Two enforcement layers:
| Layer | Mechanism | Coverage |
|---|---|---|
| Charter | This document + CLAUDE.md §9 mandate | Catches well-behaved agents who follow the charter |
| Git hook | .githooks/pre-commit calls scripts/light_audit.py | Blocks at the git level — even agents that forget |
The git hook is the load-bearing enforcement. The charter document is the explainer.
3. What the audit checks
The light audit is the inner-loop subset of AUDIT_PROTOCOL.md §3. It runs the dimensions where structural drift is fast, mechanical to detect, and expensive to leave festering:
| Dimension | Severity | What it catches |
|---|---|---|
| §3.6 Orphan check | Critical | Content note missing from its subdomain _Index.md OR parent MOC_<Domain>.md. Half-orphans block. |
| §3.3 Tag hygiene | Critical | Note missing any of the 4 required tag prefixes (domain/, type/, status/, priority/). Source notes get a Convention-10 exemption for domain/. |
| §3.4 YAML domain ↔ tag match | Critical | domain: YAML field’s value must equal the domain/<slug> tag’s slug. |
| §3.2 H1 ↔ title match | Critical | The single # H1 heading must equal the YAML title: field exactly. |
| §3.11 Sub-subdomain Index.md existence | Critical | The three known sub-subdomain index files (per the 2026-05-11 first-fire) must exist. |
| §3.1 Description length | Important (over cap) / Minor (under floor) | YAML description: must be 140–160 characters. Over 160 is Important; under 140 is Minor. |
The audit deliberately skips these dimensions, which are too slow or too prose-judgement-dependent for the inner loop:
- §3.5 — Vault-wide wikilink integrity. Spot-checked by writers; full sweep at session-end via
AUDIT_PROTOCOLagent. - §3.7 — Body word cap ≤ 600. Eyeball during writing; full agent enforces.
- §3.8 —
## Related≥ 5 wikilinks. Enforced at writing time per the template. - §3.10 — Hub genericity (P-13 / P-16). Prose-level; needs the three-pass screening + manual read. Full agent.
The full audit (all 11 dimensions, vault-wide) still runs:
- At end of every session (
CLAUDE.md §9mandatory checklist). - Before any large batch landing (writer/wiring/QC agent pipeline).
- On user demand (e.g., “do a full audit”).
4. Verdicts
Per AUDIT_PROTOCOL.md §2, with adjusted thresholds for the inner loop:
| Verdict | Trigger | Effect |
|---|---|---|
| PASS | 0 Critical, 0 Important, 0 Minor | Commit proceeds. |
| PASS-WITH-WARNINGS | 0 Critical, any Important / Minor | Commit proceeds. Warnings printed prominently. Fix in a follow-up commit, not by overriding. |
| FAIL | Any Critical | Commit blocked. Fix the Critical findings or use git commit --no-verify (logged as debt — see §6). |
In strict mode (python3 scripts/light_audit.py --strict), Important findings also block. Useful for high-stakes commits (charter changes, mass rewrites). Off by default — the inner loop should be fast, not fussy.
5. The audit engine
The single source of truth is scripts/light_audit.py in the vault root.
Run manually:
cd <vault root>
python3 scripts/light_audit.pyStrict mode (block on Important too):
python3 scripts/light_audit.py --strictOutput format: Markdown-styled console output with Critical / Important / Minor sections and a final VERDICT line. Returns exit code 0 (PASS / PASS-WITH-WARNINGS) or 1 (FAIL).
6. One-time setup (the hook)
The .githooks/pre-commit shell script invokes the audit on every git commit. Git does not automatically use hooks in custom directories — you must point it at this folder once:
git config core.hooksPath .githooksThis is per-clone configuration (lives in .git/config, not tracked). Every fresh clone needs to run it once.
To verify the hook is active:
git config --get core.hooksPath
# Should print: .githooksTo test the hook fires:
git commit --allow-empty -m "test pre-commit hook"
# You should see the audit output before the commit succeeds.7. Bypass policy
git commit --no-verify bypasses the hook. Every bypass is technical debt:
- Acceptable: emergency commit (broken build, critical security fix) where the audit would falsely block the actual fix.
- NOT acceptable: routine commits, “just this once,” anything you can fix in 5 minutes.
If you bypass, add a follow-up TODO in the commit message: (post-commit-audit-debt: <what to fix>). The end-of-session full audit will catch it; document the rationale there.
If --no-verify becomes routine, the audit is calibrated wrong — file an issue rather than normalising the bypass.
8. Updating the audit
scripts/light_audit.py is vault-quality infrastructure, not research content. It’s permitted in the scripts/ folder per CLAUDE.md §2 Hard Rule 1.
Changes to the audit logic:
- Edit
scripts/light_audit.py. - Run it locally to confirm no regressions on the current vault.
- Update this
PRE_COMMIT_AUDIT.mdif a new dimension is added or thresholds shift. - Commit normally — the audit will run on itself (recursive check is fine; the script doesn’t audit its own source).
When a new audit dimension graduates from the full AUDIT_PROTOCOL.md to the inner loop (because it’s been demonstrated to detect real drift cheaply), add it here and in the script, and bump the script’s docstring header.
9. Relationship to AUDIT_PROTOCOL.md
| Document | Scope | Tempo | Mechanism |
|---|---|---|---|
| PRE_COMMIT_AUDIT.md (this) | Critical + Important structural dimensions only | Every commit (~5 sec) | scripts/light_audit.py + git hook |
| AUDIT_PROTOCOL.md | Full §3.1–§3.11 including prose-level §3.10 | Per batch / per session / on demand (3–10 min) | Sub-agent invocation |
The two are deliberately parallel: the inner loop runs always, the outer loop runs after substantial work. Inner-loop pass + outer-loop pass = the vault is in a known-good state.
10. Why the script lives in the repo
The scripts/ folder is the only code allowed inside the vault per CLAUDE.md §2 Hard Rule 1. The rationale:
- The audit script and the git hook are infrastructure for vault quality, not research content.
- They are distributable — anyone who clones the repo gets the audit for free.
- They are inspectable — the human can read and reason about what’s being enforced.
Putting them outside the repo (in user home, in CI only, in dotfiles) breaks all three properties. Keeping them in scripts/ + .githooks/ is the smallest acceptable footprint.
Created 2026-05-11. The fourth protocol document in the History Vault’s self-improvement system (joining CLAUDE.md, AUDIT_PROTOCOL.md, CONTENT_QUALITY.md, LIBRARIAN_PROTOCOL.md).