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:

LayerMechanismCoverage
CharterThis document + CLAUDE.md §9 mandateCatches well-behaved agents who follow the charter
Git hook.githooks/pre-commit calls scripts/light_audit.pyBlocks 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:

DimensionSeverityWhat it catches
§3.6 Orphan checkCriticalContent note missing from its subdomain _Index.md OR parent MOC_<Domain>.md. Half-orphans block.
§3.3 Tag hygieneCriticalNote 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 matchCriticaldomain: YAML field’s value must equal the domain/<slug> tag’s slug.
§3.2 H1 ↔ title matchCriticalThe single # H1 heading must equal the YAML title: field exactly.
§3.11 Sub-subdomain Index.md existenceCriticalThe three known sub-subdomain index files (per the 2026-05-11 first-fire) must exist.
§3.1 Description lengthImportant (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_PROTOCOL agent.
  • §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 §9 mandatory 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:

VerdictTriggerEffect
PASS0 Critical, 0 Important, 0 MinorCommit proceeds.
PASS-WITH-WARNINGS0 Critical, any Important / MinorCommit proceeds. Warnings printed prominently. Fix in a follow-up commit, not by overriding.
FAILAny CriticalCommit 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.py

Strict mode (block on Important too):

python3 scripts/light_audit.py --strict

Output 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 .githooks

This 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: .githooks

To 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:

  1. Edit scripts/light_audit.py.
  2. Run it locally to confirm no regressions on the current vault.
  3. Update this PRE_COMMIT_AUDIT.md if a new dimension is added or thresholds shift.
  4. 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

DocumentScopeTempoMechanism
PRE_COMMIT_AUDIT.md (this)Critical + Important structural dimensions onlyEvery commit (~5 sec)scripts/light_audit.py + git hook
AUDIT_PROTOCOL.mdFull §3.1–§3.11 including prose-level §3.10Per 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).