textmachine/frontend/scripts/githooks/pre-commit

48 lines
2.4 KiB
Bash
Executable file

#!/bin/sh
# The zone pre-commit fragment of frontend/. Run by the dispatcher .git/hooks/pre-commit, which is
# put in place by scripts/githooks/install.mjs (automatically on npm install).
# For commits with no frontend paths it works in milliseconds and stays silent.
# The last-resort bypass (deliberate, and it lands in no log): git commit --no-verify.
staged=$(git diff --cached --name-only)
[ -z "$staged" ] && exit 0
# 1) Files from the "never commit" list (CLAUDE.md, the guardrails): the owner's live brief and the
# personal settings of permissions. START_PROMT.MD is tracked and often modified — a bare
# `git commit -a` would carry it away in silence.
forbidden=$(printf '%s\n' "$staged" | grep -E '^START_PROMT\.MD$|(^|/)\.claude/settings\.local\.json$')
if [ -n "$forbidden" ]; then
echo 'pre-commit: the commit holds a file from the "never commit" list (CLAUDE.md, guardrails):' >&2
printf ' %s\n' "$forbidden" >&2
echo 'Commit in the pathspec form without it: git commit -m "..." -- <your own paths>' >&2
exit 1
fi
# 2) A mixture of frontend/ and somebody else's zone in one commit — the picture of both incidents
# of 02.08 (a bare `git commit` carried away another zone's index, D39.88). The front commits ONLY
# frontend/, the other zones do not commit frontend/ — a legitimate mixture does not exist.
front=$(printf '%s\n' "$staged" | grep -c '^frontend/')
other=$(printf '%s\n' "$staged" | grep -cv '^frontend/')
if [ "$front" -gt 0 ] && [ "$other" -gt 0 ]; then
echo 'pre-commit: the commit mixes frontend/ with another zone — this is how the index of others rides away (D39.88).' >&2
echo 'Split it: git commit -m "..." -- <paths of one zone>' >&2
printf '%s\n' "$staged" | sed 's/^/ /' >&2
exit 1
fi
[ "$front" -eq 0 ] && exit 0
# 3) The quality gate of the zone: the same npm run check that the sessions run by hand — one list
# of tools and not a duplicate (STACK_DECISIONS §3 "one command of checking").
if [ ! -d frontend/node_modules ]; then
echo 'pre-commit: no frontend/node_modules — run npm ci in frontend/ and repeat.' >&2
exit 1
fi
if ! git diff --quiet -- frontend/; then
echo 'pre-commit: frontend/ has uncommitted edits outside the index; check goes over the working tree.' >&2
fi
echo 'pre-commit: npm run check (frontend), ~10 s...' >&2
if ! npm --prefix frontend run check; then
echo 'pre-commit: check is red — the commit is stopped. Fix it, do not go around it.' >&2
exit 1
fi