Files
TSYSGroupAIOS/hooks/enforce-rules.sh
T
mrcharles 374288a105 feat: bootstrap meta — cross-project best-practices template
Extract patterns from 18 projects across two machines (12 local infra +
6 remote personal/business via ssh survey). Ship a reusable Gitea template
with AGENTS.md, 5 Crush PreToolUse hooks, git pre-commit/pre-push, a
generalized rules engine, shared bash library, Makefile, lifecycle scripts,
and gardening loop. Includes the canonical BASELINE-PROMPT.md (13 sections)
and PATTERNS.md (standardization scorecard).

The repo self-applies: it passes its own shellcheck (zero info-level),
make fast, and all check-rules.sh checks.

💘 Generated with Crush

Assisted-by: Crush via Crush <crush@charm.land>
2026-08-07 11:17:53 -05:00

43 lines
1.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Hook: enforce-rules (PreToolUse, matcher: ^(edit|write|multiedit)$)
# Inspects the target file path of every edit/write/multiedit and:
# 1. Blocks edits to banned file types in production paths.
# 2. Injects a "did you write a failing test first?" reminder for source edits.
#
# Banned file types are configurable via PROJECT_BANNED_SUFFIXES (regex alternation)
# and PROJECT_BANNED_ALLOW (regex of paths that are exempt, e.g. vendored code).
set -euo pipefail
PATH_PREFIX="${CRUSH_WORKING_DIR:-/work}"
FILE_PATH="${CRUSH_TOOL_INPUT_FILE_PATH:-}"
# Strip common prefixes to get a repo-relative path.
REL_PATH="${FILE_PATH#"$PATH_PREFIX"/}"
REL_PATH="${REL_PATH#/}"
BANNED_SUFFIXES="${PROJECT_BANNED_SUFFIXES:-}"
BANNED_ALLOW="${PROJECT_BANNED_ALLOW:-^$}"
# --- 1. Banned file types ---------------------------------------------------
if [ -n "$BANNED_SUFFIXES" ] && printf '%s' "$REL_PATH" | grep -qE "\.($BANNED_SUFFIXES)$"; then
if ! printf '%s' "$REL_PATH" | grep -qE "$BANNED_ALLOW"; then
echo "BLOCKED: AGENTS.md language policy — $REL_PATH is a banned file type in production. Allowed only under: $BANNED_ALLOW" >&2
exit 2
fi
fi
# --- 2. TDD reminder for source-file edits ----------------------------------
# Toggle via PROJECT_SOURCE_SUFFIXES (regex). Default: none (opt-in).
SOURCE_SUFFIXES="${PROJECT_SOURCE_SUFFIXES:-}"
TEST_PATTERN="${PROJECT_TEST_PATTERN:-_test\.}"
if [ -n "$SOURCE_SUFFIXES" ] && printf '%s' "$REL_PATH" | grep -qE "\.($SOURCE_SUFFIXES)$"; then
if ! printf '%s' "$REL_PATH" | grep -qE "$TEST_PATTERN"; then
cat <<'EOF'
{"context": "You are editing a source file. TDD is mandatory: did you write a FAILING test first? If not, stop and write the test before editing this file."}
EOF
exit 0
fi
fi
echo '{}'