Pre-commit System¶
The pre-commit system enforces three core principles through three defense layers, each operating at a different level of the stack:
Performance is king – no regressions in GPU-first execution
Zero-copy by default – data stays on device until explicit materialization
Agent-first discoverability – all code is routable through the intake system
Quick Start¶
uv run python scripts/install_githooks.py
That’s it. The git hook runs deterministic checks on every commit and prints
a reminder about the AI review commands. The skill and hook layers are
configured automatically via .claude/settings.json and .claude/skills/.
Layer 1: Deterministic Checks (git pre-commit hook)¶
Runs on every commit for all contributors. No network, no AI, no GPU
required. Total runtime: ~3-5 seconds. Enforced by .githooks/pre-commit.
Order |
Check |
Script |
Rules |
|---|---|---|---|
1 |
Ruff lint |
|
E, F, W, I, UP, B, PERF, RUF |
2 |
Doc refresh |
|
Auto-refresh generated headers |
3 |
Doc validate |
|
Header budgets, routing sections |
4 |
Architecture |
|
ARCH001-006 |
5 |
Zero-copy |
|
ZCOPY001-003 |
6 |
Performance |
|
VPAT001-004 |
7 |
Maintainability |
|
MAINT001-003 |
After checks pass, a non-blocking reminder prints the AI review commands. This works in terminals, VS Code git output, and CI alike.
Zero-Copy Rules (ZCOPY)¶
Code |
Rule |
Example |
|---|---|---|
ZCOPY001 |
No ping-pong D/H transfers in same function |
|
ZCOPY002 |
No per-element D/H transfers in loops |
|
ZCOPY003 |
Functions using device APIs must not return host data |
Public function calls |
Performance Rules (VPAT)¶
Code |
Rule |
Example |
|---|---|---|
VPAT001 |
No Python for-loops over geometry objects |
|
VPAT002 |
No Shapely imports in kernel modules |
|
VPAT003 |
No |
|
VPAT004 |
No |
|
Maintainability Rules (MAINT)¶
Code |
Rule |
Example |
|---|---|---|
MAINT001 |
New modules in |
Missing from |
MAINT002 |
New ADRs must be indexed |
Missing from |
MAINT003 |
New scripts must be in AGENTS.md |
Missing from project shape section |
Layer 2: Pre-Land Review Skill (Claude Code, proactive)¶
The pre-land-review skill (.claude/skills/pre-land-review/SKILL.md) fires
proactively when Claude detects intent to commit or land work. Unlike
AGENTS.md instructions which can be compressed away in long conversations,
skills are matched against current context on every turn by their description
field. The skill fires on keywords like “commit”, “land”, “done”, “ship it”,
“wrap up”, and “let’s finish”.
When triggered, the skill loads the full pre-land checklist fresh into context, regardless of how long the conversation has been running.
Workflow¶
Make your changes in a Claude Code session
When you’re ready to land, say “commit” or “let’s land this”
The skill fires automatically and runs the full checklist
If verdict is LAND, the skill writes
.claude/.review-completedmarkergit commit– deterministic checks run,commit-msghook verifies markerCommit completes
Available commands¶
You can also invoke the review commands explicitly:
Command |
Purpose |
|---|---|
|
Skill: full checklist, orchestrates all enforcers |
|
Skill: 6-pass GPU kernel review (auto-invoked by pre-land-review when GPU code touched) |
|
Command: GPU utilization, tier compliance, regression risk |
|
Command: device residency, transfer path tracing |
|
Command: intake routing, doc coherence |
Suppressing the pre-commit reminder¶
The reminder is non-blocking. To suppress it:
VIBESPATIAL_SKIP_AI_REMINDER=1 git commit -m "message"
Layer 3: PreToolUse Hooks (Claude Code, mechanical)¶
Two PreToolUse hooks run outside the LLM context window – they cannot
be compressed away, forgotten, or skipped by the model.
Bash guard (.claude/hooks/pre-land-gate.sh)¶
Fires on every Bash tool call. Returns a hard block ({"decision":"block"})
for commands that would bypass or tamper with enforcement infrastructure:
Pattern |
What it blocks |
|---|---|
|
Skipping all git hooks |
|
Redirecting hooks away from |
|
Inline hook path override |
|
Tampering with git hooks |
|
Tampering with Claude hooks |
|
Removing hook registrations |
For git commit commands that pass the above checks, the hook injects a
system message reminding Claude to complete /pre-land-review first.
File guard (.claude/hooks/file-guard.sh)¶
Fires on every Edit and Write tool call. Returns a hard block for
writes to enforcement-critical paths:
Protected path |
Reason |
|---|---|
|
Git hook scripts |
|
Claude hook scripts |
|
Hook registrations |
|
Local hook overrides |
|
Review skill definition |
To modify any of these files, edit them manually outside Claude Code.
Configuration¶
Both hooks are registered in .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{"matcher": "Bash", "hooks": [{"type": "command", "command": ".claude/hooks/pre-land-gate.sh"}]},
{"matcher": "Edit", "hooks": [{"type": "command", "command": ".claude/hooks/file-guard.sh"}]},
{"matcher": "Write", "hooks": [{"type": "command", "command": ".claude/hooks/file-guard.sh"}]}
]
}
}
## Layer 4: commit-msg Gate (Content-Addressable Marker)
The `commit-msg` hook (`.githooks/commit-msg`) is the **hard gate** for
Claude-assisted commits. It checks the commit message for a
`Co-Authored-By: ... Claude` line:
- **Present**: the review marker `.claude/.review-completed` must exist,
be less than 1 hour old, contain a `staged_hash` that matches the current
`git diff --cached | sha256sum`, and have a `verdict` of `LAND`.
If any check fails, the commit is blocked.
- **Absent**: human-only commit, passes unconditionally.
The marker is a JSON file written by the `/pre-land-review` skill after a
LAND verdict. It binds the review to the exact staged diff via SHA-256 hash,
so a stub file (`touch .claude/.review-completed`) or a marker from a
different staging state will not pass. If you stage additional changes after
the review, the hash breaks and you must re-run `/pre-land-review`.
## How The Layers Interact
The four layers form a defense-in-depth chain:
Layer 2: Skill fires on “commit” / “land” / “done” intent –> Loads full checklist, Claude runs AI analysis –> Writes .claude/.review-completed marker on LAND verdict –> Layer 3: Bash guard hard-blocks –no-verify, hook tampering –> Layer 3: File guard hard-blocks Edit/Write to enforcement files –> Layer 3: Bash guard injects commit reminder if checks above pass –> Layer 1: Pre-commit hook runs deterministic checks –> Layer 4: commit-msg hook checks Co-Author + marker –> Blocks if Claude co-authored without review
Each layer catches what the previous one might miss:
| Failure mode | Caught by |
|--------------|-----------|
| Agent forgets to review before committing | Layer 2 (skill) |
| Long context compresses skill trigger away | Layer 3 (bash guard reminder) |
| Agent uses `--no-verify` to skip git hooks | Layer 3 (bash guard hard block) |
| Agent redirects `core.hooksPath` | Layer 3 (bash guard hard block) |
| Agent `rm`/`sed`/`chmod` on hook files via Bash | Layer 3 (bash guard hard block) |
| Agent edits hook files via Edit/Write tools | Layer 3 (file guard hard block) |
| Agent ignores skill and hook, commits anyway | Layer 4 (commit-msg gate) |
| Agent creates stub marker file (`touch ...`) | Layer 4 (missing JSON / hash) |
| Agent stages new changes after review | Layer 4 (hash mismatch) |
| Claude Code not available (human contributor) | Layer 1 (pre-commit, no gate) |
| Non-interactive environment (CI, VS Code) | Layer 1 (pre-commit, no gate) |
## Ratchet Baseline System
The ZCOPY, VPAT, and MAINT checks use a **ratchet** to handle pre-existing
violations without blocking new work:
- Each script has a `_VIOLATION_BASELINE` constant (the known debt count).
- The check **passes** if `current_count <= baseline`.
- The check **fails** if `current_count > baseline` (new violations introduced).
- When debt is paid down, the script prints a reminder to tighten the baseline.
This means:
- **New code** must comply from day one.
- **Existing debt** doesn't block commits but can only shrink, never grow.
- **Paying down debt** is encouraged with a visible nudge.
### Updating baselines
When a script says "Debt reduced! Update `_VIOLATION_BASELINE` to N":
```bash
# Find and update the constant in the script
grep -n _VIOLATION_BASELINE scripts/check_zero_copy.py
# Edit the number, commit the change
Do not increase baselines without documenting why (new code should comply, not get an exemption).
Adding New Checks¶
To add a new lint rule to an existing enforcer:
Add a
check_*function in the appropriatescripts/check_*.pyAdd it to the
run_checks()functionRun the script – if new violations appear, decide:
Fix them (preferred)
Increase the baseline with a comment explaining why
Update the rule table in this doc
Run
uv run python scripts/check_docs.py --refreshto update headers
To add an entirely new enforcer:
Create
scripts/check_<name>.pyfollowing the existing patternAdd it to
.githooks/pre-commitin the Layer 1 blockAdd it to AGENTS.md project shape and verification sections
Add a corresponding command in
.claude/commands/for AI-powered analysisDocument it in this file
Troubleshooting¶
Pre-commit hook not running¶
# Check that hooks are installed
git config --local core.hooksPath
# Should print: .githooks
# Reinstall if needed
uv run python scripts/install_githooks.py
Deterministic check fails on pre-existing code¶
The ratchet baseline should prevent this. If it happens:
Run the failing script standalone to see all violations
Check if
_VIOLATION_BASELINEwas accidentally loweredIf a dependency update introduced new violations, raise the baseline with a comment explaining the cause
Skill not firing in Claude Code¶
The skill triggers on keywords in the conversation. If it doesn’t fire:
Say
/pre-land-reviewexplicitly to invoke itCheck that
.claude/skills/pre-land-review/SKILL.mdexistsVerify the skill appears in Claude Code’s skill list
Hook not injecting reminder¶
Check that
.claude/settings.jsonhas thePreToolUsehook configuredVerify
.claude/hooks/pre-land-gate.shis executable (chmod +x)Test manually:
echo '{"command":"git commit -m test"}' | .claude/hooks/pre-land-gate.sh
Skipping hooks entirely¶
The --no-verify flag is hard-blocked for AI agents by the Bash guard
hook. It cannot be used from within Claude Code sessions.
For human contributors working outside Claude Code, --no-verify still works
in a plain terminal. Use sparingly – it bypasses ALL checks including
deterministic ones.