1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# drep's own commit gate.
#
# Install. `pre-commit install` refuses outright ("Cowardly refusing to install
# hooks with `core.hooksPath` set") when any git config level points
# core.hooksPath elsewhere, so clear it around the install:
#
# git config --local core.hooksPath "" \
# && pre-commit install \
# && pre-commit install --hook-type pre-push
# git config --local --unset core.hooksPath
#
# On a fresh clone core.hooksPath is unset and the two `pre-commit install`
# lines are enough on their own.
#
# `pre-commit` is expected on PATH (`uv tool install pre-commit`). Every hook
# below is `language: system`, so pre-commit builds no environments and the tool
# versions are the ones CI runs.
#
# Ordering is deliberate: the instant checks run first, so an obvious lint
# failure does not cost an LLM round-trip.
repos:
- repo: local
hooks:
# `cargo fmt` rewrites in place, so pre-commit sees the modified file and
# fails the commit rather than committing unformatted code.
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: system
types:
require_serial: true
# --all-targets so test code is linted too. Lint levels come from
# [lints] in Cargo.toml, so this agrees with CI and with a plain local
# `cargo clippy` by construction.
#
# Warm-incremental this is ~0.14s, but a cold target dir costs seconds
# and goes cold on every toolchain bump, branch switch and dependency
# change. Move it to pre-push if that starts biting.
- id: cargo-clippy
name: cargo clippy
entry: cargo clippy --all-targets --all-features
language: system
types:
pass_filenames: false
require_serial: true
# A green suite proves the tests ran, not that they would notice if the
# code were wrong. cargo-mutants perturbs the implementation and reports
# mutations no test catches; a surviving mutant IS a non-discriminating
# test. Added after the first full sweep found 11 of them, including one
# on a load-bearing invariant - replacing the executable-bit check in
# resolve_tool with a constant `true` failed no test.
#
# Scoped to the staged diff, so cost is proportional to the change
# (~30s for one file). CI runs the full sweep. The run itself happens on
# strix.local; scripts/mutants-remote.sh falls back to a local run with a
# warning when it cannot be reached.
- id: cargo-mutants
name: cargo mutants (staged diff)
entry: ./scripts/mutants-staged.sh
language: system
types:
pass_filenames: false
require_serial: true
# drep gating drep, at the calibration `drep init` writes and
# .pre-commit-hooks.yaml publishes. `--fail-on error` blocks on an
# unclosed code fence and stays quiet about line length, which this repo
# turns off anyway (MD013: false in .markdownlint.json).
- id: drep-lint-docs
name: drep lint-docs
entry: ./target/release/drep lint-docs --fail-on error
language: system
types:
# Pre-push, not pre-commit: a reasoning model spends minutes and real
# money per file (deepseek-v4-pro ~3.5min and ~$0.16 a file), which is
# fine once per push and intolerable on every commit.
#
# `cargo build --release` is deliberately not run here - the hook uses
# whatever binary is at target/release/drep, and `cargo-clippy` above
# already fails the commit if the tree does not compile.
#
# No --fail-on: deterministic tool findings block on their own, and the
# LLM's findings inform. Passing --fail-on error here opted the LLM back
# into gating and blocked a push with 18 "blocking" findings that were
# model opinions, not tool output.
#
# Read pre-commit's pushed base/tip rather than accepting its filename
# list. Filenames select whole-file mode; refs retain the same diff-hunk
# scope as drep's native pre-push hook.
#
# `--push-gate` first asks the cache. A cold review is completed and
# cached, then exits 3 so Git reconnects instead of resuming the SSH
# transport it opened before this potentially long hook began.
- id: drep-check
name: drep check (LLM code quality)
entry: ./target/release/drep check --push-gate --pre-commit-push
language: system
pass_filenames: false
types:
stages:
require_serial: true