#!/usr/bin/env bash set -euo pipefail # Backs up everything SignalScope needs to restore its configuration, # feedback rules, baselines, and incident history: the whole state/ # directory. SQLite databases are backed up live via `sqlite3 .backup` # (a consistent snapshot even while the monitor is writing to them) # instead of a plain file copy, which can capture a torn/inconsistent # write. JSON files (config, feedback, incidents, caches) are already # written atomically by SignalScope (temp file + rename), so a plain # copy of those is safe. ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" STATE_DIR="${FGAI_STATE_DIR:-$ROOT_DIR/state}" BACKUP_ROOT="${1:-$ROOT_DIR/backups}" STAMP="$(date -u +%Y%m%dT%H%M%SZ)" DEST_DIR="$BACKUP_ROOT/signalscope-state-$STAMP" if [ ! -d "$STATE_DIR" ]; then printf 'State directory not found: %s\n' "$STATE_DIR" >&2 exit 1 fi mkdir -p "$DEST_DIR" shopt -s nullglob for db in "$STATE_DIR"/*.sqlite3; do name="$(basename "$db")" if command -v sqlite3 >/dev/null 2>&1; then sqlite3 "$db" ".backup '$DEST_DIR/$name'" else printf 'Warning: sqlite3 CLI not found, falling back to plain copy for %s (may be inconsistent if the monitor is running)\n' "$name" >&2 cp "$db" "$DEST_DIR/$name" fi done for json_file in "$STATE_DIR"/*.json; do cp "$json_file" "$DEST_DIR/$(basename "$json_file")" done shopt -u nullglob ARCHIVE="$BACKUP_ROOT/signalscope-state-$STAMP.tar.gz" tar -czf "$ARCHIVE" -C "$BACKUP_ROOT" "signalscope-state-$STAMP" rm -rf "$DEST_DIR" printf 'Backed up %s to %s\n' "$STATE_DIR" "$ARCHIVE"