e4a36f1133
capability_groups.md exige que toda funcion de un grupo lleve su tag plano para ser descubrible via fn_search tag='orchestration'. 6 de las funciones del grupo (reboot_all_claudes, classify_fleet_termination, list_claude_fleet, drain_fleet_events, mark_claude_role, set_dod_contract) no lo llevaban. Se anade sin borrar los tags existentes. notify_desktop_go_infra ya llevaba el tag pero no figuraba en la tabla del grupo: se decide que SI pertenece (la usa el orquestador/watcher para avisar de un RECLAMA u otro evento urgente) y se anade a la tabla en orchestration.md (commit anterior), en lugar de quitarle el tag. Resultado: 13 funciones con tag orchestration, identicas a las 13 filas de la tabla del grupo (sin drift). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.9 KiB
4.9 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 | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| list_claude_fleet | function | go | infra | 1.0.0 | impure | func ListClaudeFleetFrom(claudeDir string) ([]ClaudeFleet, error) | func ListClaudeFleet() ([]ClaudeFleet, error) | 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. |
|
|
|
false | error_go_core |
|
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. | true |
|
functions/infra/list_claude_fleet_test.go | functions/infra/list_claude_fleet.go | Misma fuente de verdad que reboot_all_claudes_bash_infra (~/.claude/sessions/<PID>.json de Claude Code 2.1.x: pid, sessionId, cwd, procStart, status, updatedAt). Solo LEE y valida — no relanza ni mata nada. La validacion anti-PID-reciclado replica la del bash (procStart del JSON vs campo 22 de /proc/<pid>/stat) pero parseando de forma robusta el comm (campo 2 entre parentesis, que puede contener espacios y ')'): se toma lo que hay tras el ULTIMO ')' y starttime es el indice 19 de ese resto. TmuxWindow queda "" (se rellena en una fase posterior). Build tag //go:build !windows (depende de /proc, no portable a Windows). |
Ejemplo
package main
import (
"fmt"
"fn-registry/functions/infra"
)
func main() {
fleet, err := infra.ListClaudeFleet() // escanea ~/.claude
if err != nil {
panic(err)
}
for _, c := range fleet {
if !c.Alive {
continue // el caller filtra las sesiones muertas
}
fmt.Printf("[%s] %-20s pid=%d kitty=%d %s\n",
c.Status, c.Rename, c.PID, c.KittyPID, c.Target)
}
}
// Variante testeable: escanea un directorio arbitrario (fixtures en tests).
fleet, _ := infra.ListClaudeFleetFrom("/home/enmanuel/.claude")
fmt.Println(len(fleet), "sesiones conocidas")
Cuando usarla
Cuando necesites enumerar las sesiones de Claude Code vivas en la maquina local para mostrarlas, monitorizarlas o actuar sobre ellas (TUI fleetview, dashboards, automatizaciones). Da el join PID -> sessionId -> cwd -> goal/phase ya resuelto y validado contra /proc, en lugar de reimplementarlo a mano cada vez. Usa ListClaudeFleetFrom en tests (inyectando un directorio con fixtures) y ListClaudeFleet en runtime real.
Gotchas
- Impura: lee el filesystem y /proc. No es determinista entre llamadas (las sesiones nacen y mueren). Solo lectura — nunca mata ni relanza procesos.
- Anti-PID-reciclado.
Alivesolo es true si el proceso existe Y su starttime (campo 22 de/proc/<pid>/stat) coincide con elprocStartdel JSON. Un JSON huerfano cuyo PID fue reasignado a otro proceso se marcaAlive=falseaunque ese PID este vivo. Si el JSON no traeprocStart, basta con que el proceso exista. - Parseo del
commen /proc//stat. El campo 2 (comm) va entre parentesis y puede contener espacios y el caracter ')'. La funcion parsea tomando lo que hay tras el ULTIMO ')'; un split ingenuo por espacios daria un starttime equivocado. - /proc no es portable. Build tag
//go:build !windows; depende de/proc/<pid>/staty/proc/<pid>/environ(Linux). En macOS/BSD no funciona tal cual. - environ ilegible -> KittyPID=0. Si
/proc/<pid>/environno es legible (permisos, proceso de otro usuario, o el proceso ya murio entre el ReadDir y el ReadFile)KittyPIDcae 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-.jsony JSON corrupto se ignoran silenciosamente. - TmuxWindow siempre "". Reservado para una fase posterior; hoy no se rellena.