#!/bin/bash
# Harness commit guard. Inspects STAGED content for footguns before a commit.
#
# Rollout posture: WARN-ONLY by default (logs + prints, never blocks). This is
# deliberate (Task 4): a guard that fails closed can brick every machine's /save. It is
# promoted to blocking only after a clean warn window across the fleet.
#   - default                       -> warn only, exit 0
#   - HARNESS_GUARD_FATAL=1          -> exit 1 on any issue (caller decides to abort)
#   - SKIP_HARNESS_GUARD=1           -> bypass entirely (logged)
# Detects: conflict markers, unencrypted SOPS / private-key material, and a staged
# submodule gitlink change (informational).
set -uo pipefail

ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0
cd "$ROOT"
LOG="$ROOT/.claude/harness/guard.log"
mkdir -p "$(dirname "$LOG")" 2>/dev/null || true
ts() { date '+%Y-%m-%dT%H:%M:%S' 2>/dev/null || echo "?"; }
warn() { echo "[harness-guard][WARN] $1"; echo "$(ts) WARN $1" >> "$LOG" 2>/dev/null || true; }

if [ "${SKIP_HARNESS_GUARD:-0}" = "1" ]; then
    echo "[harness-guard] bypassed (SKIP_HARNESS_GUARD=1)"
    echo "$(ts) BYPASS SKIP_HARNESS_GUARD=1" >> "$LOG" 2>/dev/null || true
    exit 0
fi

ISSUES=0
STAGED=()
while IFS= read -r file; do
    STAGED+=("$file")
done < <(git diff --cached --name-only --diff-filter=ACM 2>/dev/null)

for f in "${STAGED[@]}"; do
    [ -n "$f" ] || continue
    blob=$(git show ":$f" 2>/dev/null) || continue
    # 1. Conflict markers — require a REAL hunk: both an open (<<<<<<<) AND a close
    #    (>>>>>>>) marker at line start. A lone '=======' line is a markdown setext
    #    underline or a divider, not a conflict, so flagging it alone is a false positive
    #    with no detection value (git always writes all three markers). Requiring the pair
    #    eliminates that vector (verified by test-harness-guard.sh) before FATAL promotion.
    if printf '%s\n' "$blob" | grep -qE '^<<<<<<< ' && printf '%s\n' "$blob" | grep -qE '^>>>>>>> '; then
        warn "conflict markers in staged file: $f"; ISSUES=$((ISSUES + 1))
    fi
    # 2. Unencrypted SOPS vault file
    case "$f" in
        *.sops.yaml|*.sops.json|*.sops.env)
            if ! printf '%s\n' "$blob" | grep -qE 'ENC\[|^sops:'; then
                warn "possible UNENCRYPTED sops file staged: $f"; ISSUES=$((ISSUES + 1))
            fi ;;
    esac
    # 3. Private key material
    if printf '%s\n' "$blob" | grep -qE -- '-----BEGIN [A-Z ]*PRIVATE KEY-----'; then
        warn "private-key material in staged file: $f"; ISSUES=$((ISSUES + 1))
    fi
done

# 4. Submodule gitlink staged (informational — should only happen with --with-submodules)
if git diff --cached --submodule=short 2>/dev/null | grep -q '^Submodule '; then
    warn "submodule gitlink change is staged (intentional only via --with-submodules)"
fi

if [ "$ISSUES" -gt 0 ]; then
    echo "[harness-guard] $ISSUES issue(s) found."
    if [ "${HARNESS_GUARD_FATAL:-0}" = "1" ]; then
        echo "[harness-guard] FATAL mode -> signalling block."
        exit 1
    fi
    echo "[harness-guard] WARN-ONLY mode -> not blocking."
fi
exit 0
