wiki: add pre-commit hook — block new articles missing from SUMMARY.md

The hook fails any commit that adds (or renames) a .md article without a
matching SUMMARY.md entry, addressing the recurring 'article exists but
isn't navigable' drift. Excludes meta files (README/index/SUMMARY,
category index.md, MajorWiki-Deploy-Status). Bypass with --no-verify.

Hook lives in .githooks/ (tracked). Each clone needs:
  git config core.hooksPath .githooks

Companion wrapper ~/bin/wiki-commit (workstation-only, not in repo) does
pull --rebase --autostash + add -A + commit + push so cowork pushes
don't surprise.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marcus Summers 2026-04-30 05:30:05 -04:00
parent 9e96ebb110
commit c4fba631e4

36
.githooks/pre-commit Normal file
View file

@ -0,0 +1,36 @@
#!/usr/bin/env bash
# pre-commit — fail if a newly-added article is not linked from SUMMARY.md.
# Bypass with `git commit --no-verify` if you genuinely need to.
set -euo pipefail
# Articles being added or renamed in this commit (excludes meta/index/README/SUMMARY/MajorWiki-Deploy-Status, and any */index.md).
added=$(git diff --cached --name-only --diff-filter=AR -- '*.md' \
| grep -vE '^(README|index|SUMMARY|MajorWiki-Deploy-Status)\.md$|/index\.md$' \
|| true)
[ -z "$added" ] && exit 0
# Read the staged SUMMARY.md if it's part of the commit; otherwise the working-tree copy.
if git diff --cached --name-only | grep -q '^SUMMARY\.md$'; then
summary=$(git show :SUMMARY.md)
else
summary=$(cat SUMMARY.md)
fi
missing=()
while IFS= read -r article; do
[ -z "$article" ] && continue
if ! grep -qF -- "$article" <<<"$summary"; then
missing+=("$article")
fi
done <<<"$added"
if [ ${#missing[@]} -gt 0 ]; then
echo "✗ pre-commit: new article(s) not linked from SUMMARY.md:" >&2
printf ' %s\n' "${missing[@]}" >&2
echo "" >&2
echo "Add a SUMMARY.md entry for each, or use 'git commit --no-verify' to bypass." >&2
exit 1
fi
exit 0