Bash · 1698 bytes Raw Blame History
1 #!/usr/bin/env bash
2 # Refuse new "Sprint N" / "audit-N" references in src/dlm/.
3 #
4 # Sprint IDs and audit IDs belong in `.docs/sprints/` and
5 # `.docs/audits/`, not in source code. Code that mentions a sprint by
6 # number rots the moment that sprint's scope shifts. We caught and
7 # swept this multiple times across audits 09 / 11 / 12 — this hook
8 # enforces the norm so the next sweep doesn't have to be mechanical.
9 #
10 # Runs against the staged diff (pre-commit) — only NEW additions are
11 # checked. Existing lines are tolerated (the sweep already cleaned
12 # them up; future sweeps catch any drift the diff misses).
13 #
14 # To run manually:
15 # ./scripts/check-no-sprint-references.sh
16 # To check only what's staged:
17 # ./scripts/check-no-sprint-references.sh --staged
18
19 set -euo pipefail
20
21 PATTERN='([Ss]print[[:space:]]+[0-9]+|[Aa]udit[[:space:]]*-?[[:space:]]*[0-9]+)'
22
23 if [[ "${1:-}" == "--staged" ]]; then
24 diff="$(git diff --cached --no-color --unified=0 -- 'src/dlm/*.py')"
25 # Only inspect added lines (start with '+', not '+++ ').
26 hits="$(printf '%s\n' "$diff" \
27 | grep -E '^\+[^+]' \
28 | grep -E "$PATTERN" || true)"
29 if [[ -n "$hits" ]]; then
30 echo "Refusing commit: new sprint/audit references in src/dlm/." >&2
31 echo "Move them into .docs/sprints/ or .docs/audits/." >&2
32 echo >&2
33 printf '%s\n' "$hits" >&2
34 exit 1
35 fi
36 exit 0
37 fi
38
39 # Full-tree audit (use this in CI / on demand).
40 hits="$(git grep -nE "$PATTERN" -- 'src/dlm/*.py' || true)"
41 if [[ -n "$hits" ]]; then
42 echo "Sprint/audit references found in src/dlm/:" >&2
43 printf '%s\n' "$hits" >&2
44 exit 1
45 fi
46 echo "src/dlm/ clean — no sprint/audit references."