clawd/scripts/git-audit.sh

80 lines
2.3 KiB
Bash
Executable File

#!/bin/bash
# Git audit: check ~/dev/ repos for unpushed changes
# Hourly: only fetch repos with local changes (dirty or ahead)
# --full: fetch all repos (daily at 6am)
# Reports anomalies only — silence = healthy
DEV_DIR="/home/johan/dev"
CLAWD_DIR="/home/johan/clawd"
STATE_FILE="/home/johan/clawd/memory/git-audit-lastfull.txt"
ANOMALIES=""
FULL=false
# Full sweep if --full flag or last full was >20h ago
if [ "${1:-}" = "--full" ]; then
FULL=true
elif [ -f "$STATE_FILE" ]; then
LAST=$(cat "$STATE_FILE")
NOW=$(date +%s)
AGE=$(( NOW - LAST ))
[ "$AGE" -gt 72000 ] && FULL=true
else
FULL=true
fi
audit_repo() {
local dir="$1"
local repo=$(basename "$dir")
# Check for remote
if ! git -C "$dir" remote get-url origin >/dev/null 2>&1; then
ANOMALIES+="$repo: NO REMOTE\n"
return
fi
# Uncommitted changes
local DIRTY=$(git -C "$dir" status --porcelain 2>/dev/null)
local DIRTY_COUNT=0
if [ -n "$DIRTY" ]; then
DIRTY_COUNT=$(echo "$DIRTY" | wc -l)
fi
# Current branch
local BRANCH=$(git -C "$dir" rev-parse --abbrev-ref HEAD 2>/dev/null)
local AHEAD=0
if [ -n "$BRANCH" ] && git -C "$dir" rev-parse "origin/$BRANCH" >/dev/null 2>&1; then
AHEAD=$(git -C "$dir" rev-list --count "origin/$BRANCH..HEAD" 2>/dev/null || echo 0)
fi
# Only fetch if full mode OR repo has local changes
if $FULL || [ "$DIRTY_COUNT" -gt 0 ] || [ "$AHEAD" -gt 0 ]; then
timeout 5 git -C "$dir" fetch origin --quiet 2>/dev/null || true
# Recheck ahead after fetch
if [ -n "$BRANCH" ] && git -C "$dir" rev-parse "origin/$BRANCH" >/dev/null 2>&1; then
AHEAD=$(git -C "$dir" rev-list --count "origin/$BRANCH..HEAD" 2>/dev/null || echo 0)
fi
fi
# NOTE: auto-commit and auto-push removed (C-007) — audit only, no mutations
# Commits must have meaningful messages written by the agent doing the work
[ "$DIRTY_COUNT" -gt 0 ] && ANOMALIES+="⚠️ $repo: $DIRTY_COUNT uncommitted file(s)\n"
[ "$AHEAD" -gt 0 ] && ANOMALIES+="🔺 $repo: $AHEAD unpushed commit(s) on $BRANCH\n"
}
for dir in "$DEV_DIR"/*/; do
[ -d "$dir/.git" ] || continue
audit_repo "$dir"
done
[ -d "$CLAWD_DIR/.git" ] && audit_repo "$CLAWD_DIR"
$FULL && date +%s > "$STATE_FILE"
if [ -n "$ANOMALIES" ]; then
echo -e "Git audit found issues:\n$ANOMALIES"
exit 1
else
exit 0
fi