feat(infra): exponer pane_id (%N) estable en el JSON de la flota
El orquestador identificaba cada agente por el campo tmux_window (@N), pero el window_id de tmux cambia cuando un pane entra/sale de windows (el focus de la flota usa break-pane + join-pane, que recrean windows). El pane_id (%N) en cambio es estable durante toda la vida del pane: es el identificador correcto. - claude_fleet.go: nuevo campo ClaudeFleet.PaneID `json:"pane_id"`. Se mantiene TmuxWindow (lo necesita el focus internamente); esto AÑADE pane_id, no lo reemplaza. - resolve_pane_ids.go (+ .md, .go test): nueva función del registry ResolvePaneIDs(socket, pids) -> map[pid]pane_id. Lista los panes del socket (tmux -L <socket> list-panes -a) y para cada PID sube por el árbol de procesos (PPID en /proc) hasta dar con un pane_pid. Reutiliza runTmux y procPPID del paquete infra. Best-effort: tmux/socket caído o PID sin pane -> "" sin crash. Núcleo testeable con inyección de la salida tmux y del resolvedor de PPID. - list_claude_fleet.go: ListClaudeFleet() puebla PaneID resolviendo cada PID vivo contra $FLEET_SOCKET (default "fleet"). Solo la entrada pública lo hace; ListClaudeFleetFrom() queda intacta (cero coste tmux en tests y en el bucle de render de fleetview). Tag de grupo: orchestration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ purity: impure
|
||||
signature: "func ListClaudeFleetFrom(claudeDir string) ([]ClaudeFleet, error) | func ListClaudeFleet() ([]ClaudeFleet, error)"
|
||||
description: "Lista la flota de procesos Claude Code de la maquina local (Linux). Escanea ~/.claude/sessions/*.json, cruza cada PID vivo contra /proc para validar liveness (anti-PID-reciclado via procStart == campo 22 de /proc/<pid>/stat), une el goal/phase de ~/.claude/goals/<sessionId>.json, extrae KITTY_PID del environ y deriva los campos de display (Target, Rename). Devuelve todas las sesiones ordenadas por status (idle, waiting, busy, otro) y por updatedAt desc; el caller filtra por Alive. Pieza de datos de la app TUI fleetview."
|
||||
tags: [claude-fleet, infra, claude, session, proc, fleet, tui, orchestration]
|
||||
uses_functions: []
|
||||
uses_functions: [resolve_pane_ids_go_infra]
|
||||
uses_types: [claude_fleet_go_infra]
|
||||
returns: [claude_fleet_go_infra]
|
||||
returns_optional: false
|
||||
@@ -17,7 +17,7 @@ imports: []
|
||||
params:
|
||||
- name: "claudeDir"
|
||||
desc: "Directorio raiz de Claude Code a escanear (ej. /home/enmanuel/.claude). ListClaudeFleetFrom lo recibe explicito (testeable con t.TempDir()); ListClaudeFleet lo resuelve via os.UserHomeDir() + .claude."
|
||||
output: "Slice de ClaudeFleet (claude_fleet_go_infra), una entrada por sesion con JSON parseable en sessions/. Cada entrada lleva PID, KittyPID, SessionID, Rename, Target, Goal, Phase, Status, Cwd, TmuxWindow (\"\"), Alive y UpdatedAt. Ordenado por rango de status y luego por UpdatedAt descendente. Devuelve slice vacio (sin error) si la carpeta sessions/ no existe; error si no se puede leer la carpeta por otra causa."
|
||||
output: "Slice de ClaudeFleet (claude_fleet_go_infra), una entrada por sesion con JSON parseable en sessions/. Cada entrada lleva PID, KittyPID, SessionID, Rename, Target, Goal, Phase, Status, Cwd, TmuxWindow (\"\"), PaneID, Alive y UpdatedAt. ListClaudeFleet() puebla PaneID (\"%N\", identificador estable del pane) cruzando cada PID vivo con los panes del socket $FLEET_SOCKET (default \"fleet\") via resolve_pane_ids_go_infra; ListClaudeFleetFrom() deja PaneID \"\" (no hace tmux). Ordenado por rango de status y luego por UpdatedAt descendente. Devuelve slice vacio (sin error) si la carpeta sessions/ no existe; error si no se puede leer la carpeta por otra causa."
|
||||
tested: true
|
||||
tests: ["TestListClaudeFleetFrom", "TestListClaudeFleetFromMissingDir"]
|
||||
test_file_path: "functions/infra/list_claude_fleet_test.go"
|
||||
@@ -69,4 +69,5 @@ Cuando necesites enumerar las sesiones de Claude Code vivas en la maquina local
|
||||
- **/proc no es portable.** Build tag `//go:build !windows`; depende de `/proc/<pid>/stat` y `/proc/<pid>/environ` (Linux). En macOS/BSD no funciona tal cual.
|
||||
- **environ ilegible -> KittyPID=0.** Si `/proc/<pid>/environ` no es legible (permisos, proceso de otro usuario, o el proceso ya murio entre el ReadDir y el ReadFile) `KittyPID` cae a 0 sin error. Tambien es 0 legitimamente cuando claude no corre bajo kitty (ej. tmux remoto).
|
||||
- **Devuelve TODAS las sesiones con JSON parseable**, vivas o muertas. El caller decide filtrar por `Alive`. Archivos no-`.json` y JSON corrupto se ignoran silenciosamente.
|
||||
- **TmuxWindow siempre "".** Reservado para una fase posterior; hoy no se rellena.
|
||||
- **TmuxWindow siempre "".** Esta funcion no resuelve el window_id (@N); lo rellena el consumidor (fleetview) cuando lo necesita para el focus.
|
||||
- **PaneID lo puebla solo `ListClaudeFleet()`, no `ListClaudeFleetFrom()`.** La variante con directorio (usada en tests y en bucles de render calientes) no llama a tmux: deja `PaneID` "". La publica resuelve el pane_id ("%N") contra `$FLEET_SOCKET` (default "fleet") via `resolve_pane_ids_go_infra`. Si el socket no existe o tmux no responde, todos los `PaneID` quedan "" sin error. El pane_id es estable de por vida del pane (inmune a los swaps de window que mueve el focus), a diferencia de `TmuxWindow`.
|
||||
|
||||
Reference in New Issue
Block a user