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>
33 lines
2.5 KiB
Go
33 lines
2.5 KiB
Go
//go:build !windows
|
|
|
|
package infra
|
|
|
|
// ClaudeFleet describes a single Claude Code session process on the local
|
|
// machine, cross-joining the live process state (/proc) with the session and
|
|
// goal metadata that Claude Code persists under ~/.claude.
|
|
//
|
|
// It is the data record consumed by the fleetview TUI. Every field is derived
|
|
// from a single ~/.claude/sessions/<PID>.json entry plus its optional
|
|
// ~/.claude/goals/<sessionId>.json sidecar and the process' own /proc entry.
|
|
type ClaudeFleet struct {
|
|
PID int `json:"pid"`
|
|
KittyPID int `json:"kitty_pid"` // KITTY_PID from the process environ; 0 if not applicable (e.g. remote tmux)
|
|
SessionID string `json:"session_id"` // Claude Code sessionId (UUID)
|
|
Rename string `json:"rename"` // display name: short goal if present, else basename(cwd)
|
|
Target string `json:"target"` // sessionId[:8] + "@" + basename(cwd)
|
|
Goal string `json:"goal"` // from goals/<sessionId>.json .goal ("" if absent)
|
|
Phase string `json:"phase"` // from goals/<sessionId>.json .phase ("" if absent)
|
|
DodContract string `json:"dod_contract"` // from goals .dod_contract: fixed acceptance criterion ("" if absent)
|
|
DodStatus string `json:"dod_status"` // from goals .dod_status: pending|met|failed ("" if absent)
|
|
Role string `json:"role"` // from goals .role: orchestrator|executor ("" if absent; defaults to executor in consumers)
|
|
Emojis string `json:"emojis"` // 3 emojis representing the task (from goals .emojis; "" if absent)
|
|
Name string `json:"name"` // manual rename of the terminal (from goals .rename; "" if none)
|
|
Status string `json:"status"` // idle|busy|waiting (from sessions/<pid>.json)
|
|
Cwd string `json:"cwd"` // working directory of the session
|
|
TmuxWindow string `json:"tmux_window"` // window_id (@N) of the pane: REAL current position, used for focus/send-keys; migrates when the pane is swapped between windows
|
|
PaneID string `json:"pane_id"` // pane_id (%N) of the pane: STABLE identity for the pane's whole life, immune to window swaps; "" if not resolvable. Prefer this as the agent's identifier over TmuxWindow
|
|
Alive bool `json:"alive"` // process alive AND procStart matches (guards against PID recycling)
|
|
UpdatedAt int64 `json:"updated_at"` // from sessions/<pid>.json .updatedAt (epoch millis)
|
|
CtxPct int `json:"ctx_pct"` // context window used %, from runtime/<sessionId>.json; -1 if unknown
|
|
}
|