#!/bin/bash # Pre-commit hook: blocks commits that change files without a corresponding task. # Install via: scripts/install-hooks.sh set -e TASKS_DIR="tasks" # Get list of changed files (staged) CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -v "^$TASKS_DIR/" || true) if [ -z "$CHANGED_FILES" ]; then exit 0 fi # Check if any task spec mentions the changed files matches="" for file in $CHANGED_FILES; do basename=$(basename "$file") # Search for the filename or path in all task SPEC.md files if grep -q -r "$basename\|$file" "$TASKS_DIR" --include="SPEC.md" 2>/dev/null; then matches="$matches $file" fi done # Count how many changed files are matched matched_count=$(echo "$matches" | tr ' ' '\n' | sort -u | grep -c . || true) total_count=$(echo "$CHANGED_FILES" | grep -c . || true) if [ "$matched_count" -ge "$total_count" ]; then exit 0 fi # Some files lack task coverage — warn and ask echo "" echo "=== TASK ENFORCEMENT ===" echo "Changed files not covered by any task in $TASKS_DIR/:" for file in $CHANGED_FILES; do if ! echo "$matches" | grep -q "$file"; then echo " - $file" fi done echo "" echo "The .rules.md requires all changes to go through a task." echo "Create a task in $TASKS_DIR/{name}/SPEC.md first," echo "or use 'git commit --no-verify' to bypass this check." echo "" read -p "Continue without a task? (y/N) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo "Commit blocked. Create a task for your changes first." exit 1 fi