feat(doctor): add fn doctor CLI + 14 functions for system management
Adds `fn doctor` read-only diagnostic command with subcommands artefacts, services, sync, uses-functions, unused, and --json flag for agents. Each subcommand wraps a registry function in functions/infra/. New functions: - artefact_doctor, services_status, pc_locations_drift, audit_uses_functions, find_unused_functions (Go diagnostics) - backup_sqlite_db, rotate_backups, wait_for_http, wait_for_port, port_kill, tail_journal, pre_commit_hook_install (bash utilities) - notify_telegram (Go HTTP) - backup_all pipeline (tag launcher) Plus prior session leftovers (scan_secrets_in_dirty, append_diary_entry, git utilities, http_session_cookie_middleware, compile/full-git pipelines). Fixes pc_locations_drift filepath.Join bug with absolute dir_path. Documents fn doctor in CLAUDE.md, .claude/rules/fn_doctor.md (rule 23), docs/architecture.md, CHANGELOG.md (2026-05-07), and diary entry. First fn doctor uses-functions run found drift in 7/12 apps (deuda para sincronizar app.md con imports reales). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
# pre_commit_hook_install — instala hook pre-commit que invoca scan_secrets_in_dirty
|
||||
|
||||
pre_commit_hook_install() {
|
||||
local repo_dir="$1"
|
||||
local force=0
|
||||
|
||||
shift
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--force) force=1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
local hooks_dir="$repo_dir/.git/hooks"
|
||||
local hook_path="$hooks_dir/pre-commit"
|
||||
local marker="# fn_registry-pre-commit-v1"
|
||||
|
||||
if [[ ! -d "$hooks_dir" ]]; then
|
||||
echo "[pre_commit_hook_install] ERROR: '$repo_dir' no es un repo git valido (falta .git/hooks)" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -f "$hook_path" ]]; then
|
||||
if grep -qF "$marker" "$hook_path"; then
|
||||
if [[ $force -eq 0 ]]; then
|
||||
echo "SKIP $hook_path (already installed)"
|
||||
return 0
|
||||
else
|
||||
local backup="$hook_path.bak.$(date +%s)"
|
||||
cp "$hook_path" "$backup"
|
||||
echo "[pre_commit_hook_install] Backup: $backup" >&2
|
||||
fi
|
||||
else
|
||||
if [[ $force -eq 0 ]]; then
|
||||
echo "[pre_commit_hook_install] ERROR: '$hook_path' existe y no es nuestro. Usa --force para sobreescribir." >&2
|
||||
return 2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cat > "$hook_path" <<'HOOK'
|
||||
#!/usr/bin/env bash
|
||||
# fn_registry-pre-commit-v1
|
||||
set -e
|
||||
|
||||
# Localizar fn_registry root: env var FN_REGISTRY_ROOT o asumir mismo repo si tiene registry.db en raiz
|
||||
REGISTRY_ROOT="${FN_REGISTRY_ROOT:-}"
|
||||
if [ -z "$REGISTRY_ROOT" ]; then
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
if [ -f "$REPO_ROOT/registry.db" ]; then
|
||||
REGISTRY_ROOT="$REPO_ROOT"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$REGISTRY_ROOT" ] || [ ! -f "$REGISTRY_ROOT/bash/functions/cybersecurity/scan_secrets_in_dirty.sh" ]; then
|
||||
echo "[pre-commit] fn_registry no localizable; saltando scan de secrets" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Ejecutar scan en repo actual (cwd)
|
||||
bash "$REGISTRY_ROOT/bash/functions/cybersecurity/scan_secrets_in_dirty.sh" "$(git rev-parse --show-toplevel)"
|
||||
HOOK
|
||||
|
||||
chmod +x "$hook_path"
|
||||
echo "INSTALLED $hook_path"
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user