cd web && npx lint-staged || exit 1 cd .. # ersatztv#521 — decision-record lifecycle structural validator (replaces the old H9 append-only # line guard). Runs the same validator the CI `decisions lifecycle` job uses, over the working # tree (no base/head here, so only structural checks run; the body-diff/no-vanish checks run in # CI where a base ref exists). Fail-open shim — see .claude/hooks/decisions-guard.sh. ./.claude/hooks/decisions-guard.sh || exit 1 # H3 (ersatztv#303) — never commit a screenshot dropped at the repo root. Belt-and-suspenders with # .gitignore (catches a forced `git add -f`). Root-level *.png only; nested paths are legit assets. root_png=$(git diff --cached --name-only --diff-filter=ACM | grep -iE '^[^/]+\.png$' || true) if [ -n "$root_png" ]; then echo "husky - refusing to commit root-level screenshot(s):" printf ' %s\n' $root_png echo " Move it out of the repo root or drop it (root *.png are review/debug artifacts; see .gitignore)." exit 1 fi # dotnet format on staged .cs files (repo root). Uses `whitespace . --folder` — same recipe as # the CI `format` job (ersatztv#469): folder mode checks .editorconfig whitespace + charset (BOM) # without the MSBuild/Roslyn workspace load, so it runs in ~0.5s instead of the old ~20-40s sln # load. Keeping this identical to CI avoids a local hook that blocks on rules CI no longer enforces. # Skip entirely when no .cs is staged (avoids any cost for web-only commits). cs_files=$(git diff --cached --name-only --diff-filter=ACM -- '*.cs') if [ -n "$cs_files" ]; then echo "husky - dotnet format (whitespace verify) on staged .cs files" # shellcheck disable=SC2086 dotnet format whitespace . --folder --verify-no-changes --include $cs_files || { echo "husky - dotnet format found whitespace/BOM issues in staged .cs files; run 'dotnet format whitespace . --folder --include ' to fix" exit 1 } fi