| 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." |