#!/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