feat(orquestador): feed reactivo FLEET-STATE + fix peek de drain_fleet_events
El orquestador no se enteraba de los cambios de estado de su flota: el drenado
era manual y el peek documentado `./fn run drain_fleet_events --advance false`
devolvia un falso `{total_new:0, cursor:0}` porque `fn run` mapea los argumentos
posicionalmente y no parsea flags `--nombre valor` (events_path acababa valiendo
"--advance", una ruta inexistente).
- drain_fleet_events: nuevo helper _normalize_fn_run_flags que renormaliza el
patron `--advance <bool>` aplanado por `fn run`, de modo que el peek funciona
directo desde la CLI sin tocar el runner de Go. Bump 1.1.0 + growth log + tests
del normalizador (unit y end-to-end por HOME).
- summarize_fleet_transitions (nueva, pure, grupo claude-fleet): resume el dict
by_classification de drain en un bloque de una linea con las tres categorias
accionables (terminados / reclaman / estancados), dedup por session_id y
truncado de objetivo.
- hook_fleet_state_inject.sh (UserPromptSubmit): si la sesion es role=orchestrator
(leido de ~/.claude/goals/<session_id>.json), hace peek de la cola sin mover el
cursor y emite el bloque FLEET-STATE cada turno. Degrada limpio si el watcher
esta caido, la cola no existe o la sesion no es orquestador.
El registro del hook va en .claude/settings.local.json (gitignored, fuera de este
commit). Pendiente, lo integra otro agente: documentar el bloque FLEET-STATE en
.claude/commands/orquestador.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,13 @@ def drain_fleet_events(
|
||||
numero de lineas de la cola (cola truncada/rotada): se reinicio
|
||||
desde 0.
|
||||
"""
|
||||
# `fn run` aplana los argumentos posicionalmente y NO parsea flags
|
||||
# `--nombre valor`. Renormalizar el caso del peek documentado antes de
|
||||
# resolver rutas (ver _normalize_fn_run_flags).
|
||||
events_path, cursor_path, advance = _normalize_fn_run_flags(
|
||||
events_path, cursor_path, advance
|
||||
)
|
||||
|
||||
home = os.path.expanduser("~")
|
||||
if events_path is None:
|
||||
events_path = os.path.join(home, ".claude", "fleet", "events.jsonl")
|
||||
@@ -127,3 +134,40 @@ def drain_fleet_events(
|
||||
if reset:
|
||||
result["reset"] = True
|
||||
return result
|
||||
|
||||
|
||||
def _normalize_fn_run_flags(
|
||||
events_path: str | None,
|
||||
cursor_path: str | None,
|
||||
advance: bool,
|
||||
) -> tuple:
|
||||
"""Renormaliza el peek `./fn run drain_fleet_events --advance false`.
|
||||
|
||||
`fn run` mapea los argumentos de la linea de comandos POSICIONALMENTE a los
|
||||
parametros de la funcion y NO entiende flags `--nombre valor`. Por eso
|
||||
invocar `./fn run drain_fleet_events --advance false` asigna
|
||||
events_path="--advance" y cursor_path="false", lo que rompia el peek
|
||||
(events_path apuntaba a una ruta inexistente -> drain vacio con cursor 0).
|
||||
|
||||
Cuando el primer posicional es el flag `--advance`, este helper lo
|
||||
interpreta: el segundo posicional (cursor_path) es su valor booleano y las
|
||||
dos rutas vuelven a su default (None). `--advance false` -> advance=False;
|
||||
`--advance true` o `--advance` sin valor -> advance=True. Una llamada normal
|
||||
por kwargs (events_path/cursor_path reales) pasa sin cambios.
|
||||
|
||||
Returns:
|
||||
tupla (events_path, cursor_path, advance) ya normalizada.
|
||||
"""
|
||||
if (
|
||||
isinstance(events_path, str)
|
||||
and events_path.lstrip("-").replace("-", "_") == "advance"
|
||||
):
|
||||
if cursor_path is None:
|
||||
# `--advance` sin valor: presencia del flag => True (store_true).
|
||||
advance = True
|
||||
else:
|
||||
value = str(cursor_path).strip().lower()
|
||||
advance = value not in ("false", "0", "no", "off", "")
|
||||
events_path = None
|
||||
cursor_path = None
|
||||
return events_path, cursor_path, advance
|
||||
|
||||
Reference in New Issue
Block a user