#!/usr/bin/env bash # pre-push-checks.sh — Optional pre-push hook for Red Bear OS. # # Usage: # cp local/scripts/pre-push-checks.sh .git/hooks/pre-push # chmod +x .git/hooks/pre-push # # Or invoke manually: # ./local/scripts/pre-push-checks.sh # fail on any drift # ./local/scripts/pre-push-checks.sh --soft # warn only # # Runs the critical pre-flight checks: sync-versions, verify-fork-versions, # verify-patch-content, verify-collision-detection, and a self-test of the # collision-detection algorithm. # 1. sync-versions.sh --check (Cat 0 + Cat 1 + Cat 2 versions) # 2. verify-fork-versions.sh (Cat 2 fork supremacy) # 3. verify-patch-content.sh (no orphan patches) # 4. verify-collision-detection.py (no config-vs-package conflicts) # # The hook is opt-in. Operators who don't want it should NOT install it. # This is documented in local/docs/HOOKS.md (Phase 4.5+). # # Per AGENTS.md "Daily-upstream-safe workflow", these checks are the # minimum safety net against silent drift. Without the hook, drift can # only be caught at next build, which is too late for patches that # have been silently moved/deleted. set -euo pipefail ROOT="$(cd "$(dirname "$0")/../.." && pwd)" cd "$ROOT" soft_mode=0 if [ "${1:-}" = "--soft" ]; then soft_mode=1 fi fails=0 run_check() { local name="$1" local cmd="$2" local label="$3" echo ">>> $name" if eval "$cmd" >"/tmp/pre-push-${name}.out" 2>&1; then echo " OK" else local rc=$? echo " FAIL (exit $rc)" head -10 "/tmp/pre-push-${name}.out" | sed 's/^/ /' fails=$((fails + 1)) fi } echo "=== Red Bear OS — pre-push safety net ===" echo " (4 critical pre-flight checks)" echo "" # 1. sync-versions run_check "sync-versions" \ "bash local/scripts/sync-versions.sh --check" \ "Cat 0 + Cat 1 + Cat 2 versions match branch" # 2. verify-fork-versions run_check "verify-fork-versions" \ "bash local/scripts/verify-fork-versions.sh" \ "Cat 2 fork supremacy + content check" # 3. verify-patch-content run_check "verify-patch-content" \ "python3 local/scripts/verify-patch-content.py" \ "No orphan patches in local/patches/" # 3a. verify-patch-content --report action (Phase 6.4: decision-tree # auto-suggestions for any orphans the operator must triage) run_check "verify-patch-content-action" \ "python3 local/scripts/verify-patch-content.py --report action" \ "Orphan-patch decision-tree (INTEGRATED/SUPERSEDED/etc.)" # 3b. verify-patch-content --selftest (Phase 6.5: regression tests) run_check "verify-patch-content-selftest" \ "python3 local/scripts/verify-patch-content.py --selftest" \ "Patch-content audit algorithm regression tests" # 4. verify-collision-detection run_check "verify-collision-detection" \ "python3 local/scripts/verify-collision-detection.py" \ "No config [[files]] vs package install collisions" # 4a. verify-collision-detection --selftest (Phase 5.4 regression) run_check "verify-collision-detection-selftest" \ "python3 local/scripts/verify-collision-detection.py --selftest" \ "Collision detection algorithm regression tests" echo "" if [ $fails -gt 0 ]; then echo "=== RESULT: $fails check(s) failed ===" if [ $soft_mode -eq 0 ]; then echo "Push BLOCKED. To override: $0 --soft (or: REDBEAR_SKIP_PRE_PUSH=1 git push ...)" exit 1 else echo "Push allowed (--soft mode). $fails drift(s) present." exit 0 fi else echo "=== RESULT: all 4 checks pass ===" echo "Push allowed." exit 0 fi