#!/usr/bin/env bash # supervise_fleetview_tui — bucle supervisor que mantiene viva la TUI fleetview. # # Lanza el binario fleetview y, si sale (crash, panic, kill de su proceso o de su # pane), lo relanza tras un pequeno backoff. Asi el panel de control de la flota # NUNCA se pierde por un fallo puntual: es la pieza que hace resiliente al pane # izquierdo de la sesion tmux FleetView (lo invoca launch_fleetclaude). # # Dos valvulas de escape para no hacer respawn infinito: # - Sentinel file: si tras una salida existe el fichero centinela, se borra y # el bucle termina (parada voluntaria solicitada por el usuario). El default # es $HOME/.claude/fleet/tui_stop_; pararla a mano: `touch ` # y dejar que la TUI salga (o matar su proceso). # - Crash-loop guard: si la TUI sale demasiado rapido (uptime < min_uptime # segundos) muchas veces seguidas (>= max_fast_exits), el supervisor se rinde # y devuelve != 0, para no quemar CPU relanzando un binario roto en caliente. # Un arranque que dura >= min_uptime resetea el contador. # # Funcion IMPURA: lanza un proceso en bucle y lee/escribe un fichero centinela. # # Overrides de entorno (testabilidad, no para uso normal): # FLEET_SOCKET socket del perfil; fija el nombre del sentinel por defecto. set -euo pipefail IFS=$' \t\n' supervise_fleetview_tui() { local bin="" socket="" sentinel="" backoff=1 min_uptime=2 max_fast_exits=5 while [[ $# -gt 0 ]]; do case "$1" in --bin) shift; bin="${1:-}" ;; --socket) shift; socket="${1:-}" ;; --sentinel) shift; sentinel="${1:-}" ;; --backoff) shift; backoff="${1:-1}" ;; --min-uptime) shift; min_uptime="${1:-2}" ;; --max-fast-exits) shift; max_fast_exits="${1:-5}" ;; -h|--help) cat <<'USAGE' Uso: supervise_fleetview_tui --bin [opciones] Bucle supervisor: corre el binario fleetview y lo relanza si sale, para que el panel de la flota nunca se pierda por un crash/kill puntual. Opciones: --bin Ruta al binario fleetview (obligatorio). --socket Socket del perfil FleetView. Default: $FLEET_SOCKET o "fleet". --sentinel Fichero centinela de parada voluntaria. Default: $HOME/.claude/fleet/tui_stop_. --backoff Segundos de espera antes de relanzar. Default: 1. --min-uptime Umbral (s) para considerar una salida "rapida". Default: 2. --max-fast-exits Salidas rapidas seguidas tras las que el supervisor se rinde (crash-loop guard). Default: 5. -h, --help Esta ayuda. Parar el bucle a mano: `touch ` y dejar que la TUI salga (o matar su proceso); en el siguiente ciclo el supervisor ve el sentinel, lo borra y termina. Salida: 0 parada voluntaria (sentinel); 1 binario no ejecutable / uso incorrecto; 3 el supervisor se rindio por crash-loop (demasiadas salidas rapidas seguidas). USAGE return 0 ;; --*) echo "supervise_fleetview_tui: opcion desconocida '$1' (usa -h)" >&2 return 1 ;; *) if [[ -z "$bin" ]]; then bin="$1" else echo "supervise_fleetview_tui: argumento extra '$1' (bin ya es '$bin')" >&2 return 1 fi ;; esac shift done [[ -z "$bin" ]] && { echo "supervise_fleetview_tui: falta --bin al binario fleetview. Usa -h." >&2 return 1 } [[ -z "$socket" ]] && socket="${FLEET_SOCKET:-fleet}" [[ -z "$sentinel" ]] && sentinel="$HOME/.claude/fleet/tui_stop_${socket}" mkdir -p "$(dirname "$sentinel")" 2>/dev/null || true if [[ ! -x "$bin" ]]; then echo "supervise_fleetview_tui: binario '$bin' no es ejecutable. Compila la TUI: cd apps/fleetview && go build -o fleetview ." >&2 return 1 fi # Limpiar un sentinel huerfano de una sesion anterior, para no parar al arrancar. [[ -f "$sentinel" ]] && rm -f "$sentinel" 2>/dev/null || true local fast_exits=0 while true; do local start end uptime code start=$(date +%s) set +e "$bin" code=$? set -e end=$(date +%s) uptime=$(( end - start )) # Valvula 1 — parada voluntaria por sentinel. if [[ -f "$sentinel" ]]; then rm -f "$sentinel" 2>/dev/null || true echo "[fleetview: parada solicitada via sentinel ($sentinel) — fin del supervisor]" return 0 fi # Valvula 2 — crash-loop guard. if [[ "$uptime" -lt "$min_uptime" ]]; then fast_exits=$(( fast_exits + 1 )) else fast_exits=0 fi if [[ "$fast_exits" -ge "$max_fast_exits" ]]; then echo "[fleetview: $fast_exits salidas rapidas seguidas (ultimo code=$code) — el supervisor se rinde para no hacer respawn infinito. Inspecciona el binario y relanza.]" >&2 return 3 fi echo "[fleetview salio (code=$code, uptime=${uptime}s) — relanzando en ${backoff}s. Para parar: touch $sentinel, o Ctrl-C.]" sleep "$backoff" done } # Permitir ejecutar el archivo directamente (no solo como funcion sourced). if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then supervise_fleetview_tui "$@" fi