fb76b53c17
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>
5.3 KiB
5.3 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path, notes
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | notes | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| resolve_pane_ids | function | go | infra | 1.0.0 | impure | func ResolvePaneIDs(socket string, claudePIDs []int) map[int]string | Resuelve el pane_id ("%N") de tmux de cada proceso dado en un socket aislado (tmux -L <socket>), devolviendo un mapa claudePID -> pane_id. Lista los panes con `list-panes -a -F '#{pane_pid} #{pane_id}'` y, para cada PID, sube por el arbol de procesos (PPID en /proc/<pid>/stat) hasta dar con un pane_pid del socket; ese pane es el que aloja al proceso (normalmente pane_pid == PID porque el pane corre `exec claude`, pero un shell que lanzo el proceso como hijo se cubre con el ascenso). El pane_id es estable de por vida del pane, inmune a los swaps de window que mueve el focus de la flota, por eso es el identificador correcto de un agente frente al window_id (@N). Best-effort: socket vacio, sin PIDs o fallo de tmux -> mapa vacio; un PID sin pane resoluble se omite. Capa de control tmux de fleetview / orquestador. |
|
false | error_go_core |
|
map[int]string con clave = PID de entrada y valor = pane_id ('%N') del pane que lo aloja. Un PID sin pane resoluble en su ascendencia se omite (el caller lo degrada a ""). Mapa vacio (sin panic, sin error) si socket viene vacio, claudePIDs viene vacio, o `tmux list-panes -a` falla (socket caido, tmux ausente). | true |
|
functions/infra/resolve_pane_ids_test.go | functions/infra/resolve_pane_ids.go | Build tag //go:build !windows (depende de /proc y de tmux, no portable a Windows). Comparte runTmux (tmux_new_claude_window) y procPPID (tmux_map_claude_panes) con el resto de la capa tmux del paquete infra. El nucleo resolvePaneIDsFrom(tmuxOut, ppidOf, pids) es testeable inyectando la salida de tmux y el resolvedor de PPID, sin procesos reales. El ascenso por el arbol esta acotado (64 saltos, corte en pid<=1) para no colgarse ante un /proc malformado o un ciclo. Hermana de tmux_map_claude_panes_go_infra: aquella mapea PID -> window_id (@N, posicion operativa que migra con el swap); esta mapea PID -> pane_id (%N, identidad estable). Pensada para que list_claude_fleet_go_infra (y consumidores como el orquestador) identifiquen a cada agente por un handle que no baila al hacer focus. |
Ejemplo
package main
import (
"fmt"
"fn-registry/functions/infra"
)
func main() {
// Resolver el pane_id estable de un par de procesos claude en el socket fleet.
byPID := infra.ResolvePaneIDs("fleet", []int{3637133, 3640001})
for pid, paneID := range byPID {
fmt.Printf("pid=%d -> pane=%s\n", pid, paneID) // ej. pid=3637133 -> pane=%8
}
// Un PID sin pane resoluble simplemente no aparece en el mapa.
}
// Patron tipico: cruzar la flota con su pane_id estable.
fleet, _ := infra.ListClaudeFleet()
pids := make([]int, 0, len(fleet))
for _, c := range fleet {
pids = append(pids, c.PID)
}
panes := infra.ResolvePaneIDs("fleet", pids) // map[pid]"%N"
Cuando usarla
Cuando necesites un identificador ESTABLE de un agente de la flota a partir de su PID: el pane_id ("%N") de tmux no cambia durante toda la vida del pane, aunque el pane migre de window al hacer focus (break-pane + join-pane). Usala en vez de referirte al window_id (@N, TmuxWindow), que baila cada vez que el agente entra/sale de la console. La consume list_claude_fleet_go_infra para poblar ClaudeFleet.PaneID, y el orquestador para referirse a un ejecutor por un handle que no se confunde de agente.
Gotchas
- Impura: ejecuta
tmuxy lee/proc. No es determinista entre llamadas (la flota cambia). Solo lectura — no mueve ni mata panes. - Best-effort, nunca crashea. Socket vacio, lista de PIDs vacia, o un
tmux list-panes -aque falla (socket caido, tmux no instalado) devuelven un mapa vacio. Un agente sin pane resoluble (proceso huerfano, pane cerrado) se omite del mapa; el caller lo degrada a "". - Sube por el arbol de procesos. Si el pane corre un shell que lanzo claude como hijo (en vez de
exec claude), el pane_pid no es el claude PID; el ascenso por PPID lo cubre. El ascenso esta acotado a 64 saltos (corte en pid<=1) para no colgarse ante un ciclo o un /proc raro. - Parseo del
commen /proc. El PPID se saca de/proc/<pid>/stattomando lo que hay tras el ULTIMO ')' (el comm va entre parentesis y puede contener espacios y ')'). Reutiliza elprocPPIDrobusto del paquete. - /proc + tmux no portables. Build tag
//go:build !windows; depende de/proc/<pid>/stat(Linux) y del binariotmux. - Opera SIEMPRE sobre el socket aislado (
tmux -L <socket>), escaneando todos sus panes conlist-panes -a. No mira el servidor tmux por defecto del usuario.