Builds the false-positive/true-positive proof the plan requires before the guard can be promoted to blocking, and fixes the one false-positive it surfaced. - test-harness-guard.sh: 12-case matrix in a throwaway repo, runs the REAL guard, asserts WARN/clean for real conflicts/secrets/keys vs legit content (setext underlines, dividers, docs that mention a marker, encrypted sops, public keys, .example templates). - harness-guard.sh: conflict rule now requires a real hunk (BOTH ^<<<<<<< AND ^>>>>>>>), dropping the lone =======$ trigger that false-positived on a 7-char setext underline / divider. Identical true-positive power (git writes all three markers); FP surface -> 0. - /self-check: new harness.guard_selftest runs the matrix in an isolated temp repo (read-only vs the real tree) so guard correctness is continuously proven. Verified 12/12 pass, true positives intact, real-tree FP surface = 0. FATAL flip (todo f1c11d0d, on/after 2026-06-22) is now evidence-backed + one-step. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
3.0 KiB
Bash
68 lines
3.0 KiB
Bash
#!/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
|
|
mapfile -t STAGED < <(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
|