feat: dagu backup DAG + pre-commit drift hook + sync 6 apps

Priority 1: Daily backup automation via Dagu DAG (~/dagu/dags/fn_backup.yaml,
schedule "0 3 * * *"). Backs up registry.db, each operations.db, and vaults
via rsync --link-dest. Fixes set -e arithmetic bugs in rotate_backups.sh and
backup_all.sh ((var++) returns 1 when var=0). Fixes && chain set -e bug in
vault rotation.

Priority 2: Pre-commit hook v2 chains scan_secrets + uses_functions audit.
New function git_hook_audit_app_drift_bash_infra blocks commits that touch
app code when that app has uses_functions drift. Allows corrective app.md-only
edits. Installed on fn_registry + 32 sub-repos.

Priority 3: Synced uses_functions in 6 sub-repo apps (commits in their own
repos): dag_engine, script_navegador, deploy_server, docker_tui,
auto_metabase, metabase_registry. Drift went from 7/12 to 4/12 apps.
Remaining drift = audit heuristic limitations (Python nested imports,
Go symbol name detection).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 02:09:33 +02:00
parent 2a3d780347
commit eeff744dfc
5 changed files with 246 additions and 24 deletions
+16 -11
View File
@@ -65,13 +65,13 @@ backup_all() {
app_name="$(basename "$app_dir")"
local snap_ops="/tmp/ops-snap-$$-${app_name}.db"
if backup_sqlite_db "$ops_db" "$snap_ops"; then
rotate_backups "$backup_root/operations/$app_name" "$snap_ops" 7 4 12 || ((partial_errors++))
rotate_backups "$backup_root/operations/$app_name" "$snap_ops" 7 4 12 || partial_errors=$((partial_errors + 1))
rm -f "$snap_ops"
((ops_count++))
ops_count=$((ops_count + 1))
else
echo "WARN: Fallo snapshot de $ops_db — skipped" >&2
rm -f "$snap_ops"
((partial_errors++))
partial_errors=$((partial_errors + 1))
fi
done < <(find "$registry_root/apps" "$registry_root/projects" -name "operations.db" -maxdepth 4 2>/dev/null || true)
@@ -86,11 +86,16 @@ backup_all() {
current_name="${BASH_REMATCH[1]}"
elif [[ "$line" =~ ^[[:space:]]*path:[[:space:]]*(.+)$ && -n "$current_name" ]]; then
local vault_path="${BASH_REMATCH[1]}"
# Strip surrounding quotes ("..." o '...')
vault_path="${vault_path%\"}"
vault_path="${vault_path#\"}"
vault_path="${vault_path%\'}"
vault_path="${vault_path#\'}"
# Expandir ~ si fuera necesario
vault_path="${vault_path/#\~/$HOME}"
if [[ ! -d "$vault_path" ]]; then
echo "WARN: Vault '$current_name' path '$vault_path' no existe — skipped" >&2
((partial_errors++))
partial_errors=$((partial_errors + 1))
current_name=""
continue
fi
@@ -107,7 +112,7 @@ backup_all() {
# Rotacion manual de directorios (7 daily, 4 weekly, 12 monthly)
_rotate_vault_dirs "$vault_dest" 7 4 12
mv "$tmp_dest" "$vault_dest/daily.0"
((vaults_count++))
vaults_count=$((vaults_count + 1))
current_name=""
fi
done < "$vault_yaml"
@@ -143,22 +148,22 @@ _rotate_vault_dirs() {
if [[ "$month_day" == "01" && -d "$dir/weekly.0" ]]; then
for ((i=monthly-1; i>=1; i--)); do
[[ -d "$dir/monthly.$((i-1))" ]] && mv "$dir/monthly.$((i-1))" "$dir/monthly.$i"
if [[ -d "$dir/monthly.$((i-1))" ]]; then mv "$dir/monthly.$((i-1))" "$dir/monthly.$i"; fi
done
[[ -d "$dir/weekly.0" ]] && cp -al "$dir/weekly.0" "$dir/monthly.0"
if [[ -d "$dir/weekly.0" ]]; then cp -al "$dir/weekly.0" "$dir/monthly.0"; fi
fi
if [[ "$week_day" == "7" && -d "$dir/daily.0" ]]; then
for ((i=weekly-1; i>=1; i--)); do
[[ -d "$dir/weekly.$((i-1))" ]] && mv "$dir/weekly.$((i-1))" "$dir/weekly.$i"
if [[ -d "$dir/weekly.$((i-1))" ]]; then mv "$dir/weekly.$((i-1))" "$dir/weekly.$i"; fi
done
[[ -d "$dir/daily.0" ]] && cp -al "$dir/daily.0" "$dir/weekly.0"
if [[ -d "$dir/daily.0" ]]; then cp -al "$dir/daily.0" "$dir/weekly.0"; fi
fi
# Rotar daily
[[ -d "$dir/daily.$((daily-1))" ]] && rm -rf "$dir/daily.$((daily-1))"
if [[ -d "$dir/daily.$((daily-1))" ]]; then rm -rf "$dir/daily.$((daily-1))"; fi
for ((i=daily-1; i>=1; i--)); do
[[ -d "$dir/daily.$((i-1))" ]] && mv "$dir/daily.$((i-1))" "$dir/daily.$i"
if [[ -d "$dir/daily.$((i-1))" ]]; then mv "$dir/daily.$((i-1))" "$dir/daily.$i"; fi
done
}