Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Pre-push hook: auto-fix fmt drift and commit it as a chore.
#
# Rationale: three fmt-fail CI incidents in the last week. Running
# `cargo fmt --all --check` locally at push time catches drift before
# it reaches CI. Auto-fixing + auto-committing means the developer's
# intent (their original commits) flows unchanged; the fmt fix lands
# as a distinct chore commit on top, preserving audit clarity.
#
# Enable via: scripts/install-hooks.sh (sets core.hooksPath .githooks)

set -e

# Pre-push should run on a clean tree. Unstaged or staged-but-uncommitted
# changes indicate the developer hasn't finished the work they want to
# push; bail rather than silently sweep those up into a fmt commit.
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "[pre-push] uncommitted changes in working tree — commit or stash before pushing."
exit 1
fi

echo "[pre-push] cargo fmt --all --check"
if cargo fmt --all --check 2>/dev/null; then
exit 0 # clean, nothing to do
fi

echo "[pre-push] fmt drift detected; running cargo fmt --all and committing as chore"
cargo fmt --all

# Only stage tracked files; never sweep up untracked files.
git add -u

if git diff --cached --quiet; then
# cargo fmt reported drift via --check but --all produced no diff?
# Shouldn't happen; exit clean rather than commit nothing.
exit 0
fi

git commit -m "chore: apply cargo fmt"
echo "[pre-push] committed fmt fixes — push continuing with the new commit"
exit 0
9 changes: 9 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@ Read these docs before working:
cargo test --workspace --exclude v2-compiler-tests # hand-written tests
cargo test -p v2-compiler-tests # v2 compiler tests
cargo clippy --all-targets -- -D warnings # lint
cargo fmt --all --check # format check (also runs via pre-push hook)
cargo test -p v2-compiler-tests v2_strict_compile_diagnostic_count -- --ignored # stage0 diagnostic ratchet (0 diagnostics)
```

## One-time setup

```bash
scripts/install-hooks.sh # enables .githooks/pre-push
```

The pre-push hook auto-fixes fmt drift: on push, if `cargo fmt --all --check` fails, the hook runs `cargo fmt --all`, stages the changes to tracked files, and lands a `chore: apply cargo fmt` commit on top of the push. Requires a clean working tree (no uncommitted changes) at push time — bails otherwise.

## Cost of Change

When the language grows by one type, one expression, or one transport,
Expand Down
16 changes: 16 additions & 0 deletions scripts/install-hooks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# One-shot: point git at the repo-tracked hooks directory so
# .githooks/* runs on the relevant events.
#
# After this, `git push` will run .githooks/pre-push locally and
# fail fast on fmt drift, before CI runs.

set -e

git config core.hooksPath .githooks

chmod +x .githooks/pre-push

echo "[install-hooks] core.hooksPath set to .githooks"
echo "[install-hooks] .githooks/pre-push is executable"
echo "[install-hooks] Test: try 'git push --dry-run' — the hook should run."
Loading