Ctrl K
ComunidadGuías…

scripts/ai_guard/commit_msg_hook.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
# git commit-msg hook: enforce [MANUAL-OVERRIDE] tag when protected files are staged.
#
# Why this hook (and not pre-commit):
# - pre-commit runs BEFORE prepare-commit-msg creates COMMIT_EDITMSG.
#   Trying to grep the message in pre-commit always fails (file doesn't exist yet).
# - commit-msg runs AFTER prepare-commit-msg. Git passes the commit message file
#   path as $1. This is the earliest point where we can read the message.
#
# Behavior:
# - If protected files are staged AND commit message lacks [MANUAL-OVERRIDE]:
#   exit 1 (block commit).
# - If protected files are staged AND message has [MANUAL-OVERRIDE]: allow with warning.
# - If no protected files staged: pass through silently.

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$ROOT"

. "$ROOT/scripts/ai_guard/protected_files.sh"

COMMIT_MSG_FILE="$1"
if [ -z "$COMMIT_MSG_FILE" ] || [ ! -f "$COMMIT_MSG_FILE" ]; then
    echo "❌ commit-msg hook invoked without message file (arg \$1 empty or not a file)"
    exit 1
fi

# Detect protected files in staged
PROTECTED_HITS=()
for pf in "${PROTECTED_FILES[@]}"; do
    if git diff --cached --name-only | grep -q "^${pf}$"; then
        PROTECTED_HITS+=("$pf")
    fi
done

if [ "${#PROTECTED_HITS[@]}" -eq 0 ]; then
    exit 0
fi

# Protected files staged — require [MANUAL-OVERRIDE] tag in message
if grep -q "\[MANUAL-OVERRIDE\]" "$COMMIT_MSG_FILE"; then
    echo "⚠️  [MANUAL-OVERRIDE] detected — allowing protected file commit"
    for pf in "${PROTECTED_HITS[@]}"; do
        echo "   ✓ $pf"
    done
    exit 0
fi

# Block + list protected files with explanation
echo "❌ BLOCKED: 受保护文件被修改 without [MANUAL-OVERRIDE]:"
for pf in "${PROTECTED_HITS[@]}"; do
    echo "   - $pf"
done
echo ""
echo "如需人工覆盖,请在 commit message 中添加 [MANUAL-OVERRIDE] 标记。"
echo "或使用 --no-verify 跳过所有 hooks(紧急情况 / 真有 rationale)。"
exit 1