feat(orchestration): fleet_send_text — nudge fiable por pane_id estable
El nudge del orquestador apuntaba al window_id (@N) de tmux, que migra cuando el focus-swap de FleetView recrea windows (break-pane/join-pane): el texto acababa en el window equivocado o en otro agente (a veces no llega). Ademas, texto y Enter en la misma invocacion hacian que el TUI no interpretara el submit. Nueva funcion fleet_send_text_bash_infra (grupo orchestration) que: - resuelve el pane_id (%N) estable fresco justo antes de enviar (sessionId/PID a pane via tmux list-panes -a + walk de ancestros /proc), no el @N volatil; - manda texto literal y Enter en invocaciones separadas; - verifica con capture-pane que el texto llego antes del submit, con reintento; - guards anti-self y error claro si el target no resuelve a un pane vivo. Test (19/19) sobre socket tmux propio: confirma que tras break-pane el pane_id no migra y el reenvio sigue llegando. orchestration.md (seccion Nudge + catalogo) actualizado para usar la funcion en lugar del send-keys -t <@N> manual. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,10 +73,11 @@ el sidecar a mano — filtra por el `role` que ya trae cada fila.
|
||||
`fleet_list` del MCP lo expone como el único identificador y **omite a propósito el `tmux_window`
|
||||
("@N")**, que migra cuando el focus-swap mueve el pane entre windows y por eso nunca debe usarse ni
|
||||
mostrarse como id (la persona no tiene referencia mental de "@4"). Las operaciones internas que sí
|
||||
necesitan la window viva — `focus`, `send-keys`/nudge y `kill` — la resuelven BAJO DEMANDA contra
|
||||
tmux a partir del session_id/PID (`kill_fleet_agent` y `fleetview focus` la recalculan por llamada);
|
||||
para el nudge, lee `tmux_window` del binario `fleetview list --json` (que sí lo conserva como campo
|
||||
interno), nunca del payload del MCP.
|
||||
necesitan la window/pane viva — `focus`, `send-keys`/nudge y `kill` — la resuelven BAJO DEMANDA contra
|
||||
tmux a partir del session_id/PID (`kill_fleet_agent` y `fleetview focus` la recalculan por llamada).
|
||||
Para el **nudge** NO leas ni caches el `@N`: usa `fleet_send_text` (grupo `orchestration`), que resuelve
|
||||
el `pane_id` (`%N`) ESTABLE fresco a partir del `sessionId`/PID en el momento del envío — el `@N` migra
|
||||
con el focus-swap y mandaría el texto al agente equivocado (ver sección Nudge).
|
||||
|
||||
Mantén una **tabla de seguimiento**, una fila por secundario, y actualízala en cada turno:
|
||||
|
||||
@@ -262,18 +263,24 @@ verificas → `kill_fleet_agent` libera el slot. No uses `pkill`/`killall` ni `k
|
||||
### Nudge — `ESTANCADO`
|
||||
|
||||
Agente idle con `dod_contract` sin cumplir y sin actividad > umbral (10 min). Empújalo a cerrar SU DoD
|
||||
inyectando en su pane tmux:
|
||||
inyectando texto en su pane con la función `fleet_send_text` (grupo `orchestration`):
|
||||
|
||||
```bash
|
||||
tmux -L "${FLEET_SOCKET:-fleet}" send-keys -t <window_id> \
|
||||
"Sigues idle con tu DoD-contrato sin cerrar. Falta: <gap>. Cierra el golden+edge+error con evidencia, o reporta el bloqueo concreto." Enter
|
||||
./fn run fleet_send_text <sessionId> \
|
||||
"Sigues idle con tu DoD-contrato sin cerrar. Falta: <gap>. Cierra el golden+edge+error con evidencia, o reporta el bloqueo concreto." \
|
||||
--socket "$FLEET_SOCKET"
|
||||
```
|
||||
|
||||
El `window_id` es el campo `tmux_window` (p.ej. `@20`) de `apps/fleetview/fleetview list --json`:
|
||||
`fleet_send_text` resuelve el **`pane_id` (`%N`) ESTABLE FRESCO** del agente justo antes de enviar (a
|
||||
partir del `sessionId` → PID → pane, leyendo `tmux list-panes -a` en el momento), y manda el texto
|
||||
literal y el `Enter` en invocaciones **separadas**, verificando con `capture-pane` que el texto llegó
|
||||
antes de hacer submit (reintenta si no). Acepta el target por `sessionId` (exacto o prefijo) o por PID.
|
||||
|
||||
```bash
|
||||
apps/fleetview/fleetview list --json | jq -r '.[] | select(.session_id|startswith("<sid>")) | .tmux_window'
|
||||
```
|
||||
**NO uses `tmux send-keys -t <window_id @N>` a mano para esto.** El `window_id` (`@N`, p.ej. `@20`) que
|
||||
expone `fleetview list --json` MIGRA cuando el focus-swap recrea windows (`break-pane`+`join-pane`):
|
||||
`@32` → `@34`. Enviar al `@N` viejo (cacheado por el bloque `FLEET-STATE` o leído un instante antes)
|
||||
manda el texto al window equivocado o a otro agente — esa era la causa de "el nudge a veces no llega al
|
||||
agente correcto". `fleet_send_text` nunca usa `@N`; usa el `pane_id` (`%N`), que no migra.
|
||||
|
||||
**Solo a idle/ESTANCADO. JAMÁS a un agente en `waiting`/`preguntando`** — esos te reclaman a TI, no un
|
||||
empujón del bot.
|
||||
@@ -331,6 +338,7 @@ en lote.
|
||||
| `mark_claude_role_py_infra` | Marcar `role` (orchestrator/executor) en el goal.json de un Claude resolviendo PID→sessionId |
|
||||
| `mark_claude_parent_py_infra` | Marcar `parent_orchestrator` (sessionId del orquestador que lo lanzó) en el goal.json de un ejecutor resolviendo PID→sessionId. Lo invoca `spawn_fleet_agent --parent`; habilita el routing del watcher al pane del orquestador padre |
|
||||
| `kill_fleet_agent_bash_infra` | Cierre dirigido de UN ejecutor: SIGTERM al claude + kill-window de su window tmux. Guards anti-orquestador y anti-self. Lo usa el orquestador para liberar el slot idle tras verificar `met` (auto-kill) |
|
||||
| `fleet_send_text_bash_infra` | Empujar texto al input de UN agente (nudge) resolviendo su `pane_id` (`%N`) ESTABLE FRESCO justo antes de enviar — NO el `window_id` (`@N`), que migra con el focus-swap y manda el texto al agente equivocado. Texto literal + `Enter` en invocaciones separadas, verificado con `capture-pane` + reintento. Guard anti-self. Reemplaza el `tmux send-keys -t <@N>` manual del nudge |
|
||||
| `notify_desktop_go_infra` | Notificación de escritorio del fleet (`notify-send --app-name=fleetview`, degradación silenciosa si no hay `notify-send`). La usa el orquestador/watcher para avisar a la persona de un `RECLAMA` u otro evento urgente cuando no está mirando la terminal |
|
||||
|
||||
**Cómo invocarlas.** Las Bash y Python del grupo se lanzan con `./fn run <id> [args]` (verificado:
|
||||
|
||||
Reference in New Issue
Block a user