feat: cerebro reactivo del meta-orquestador (flow 0012, fase 2)
Primitivas (python/functions/infra): - drain_fleet_events: consume la cola del watcher (~/.claude/fleet/ events.jsonl) desde un cursor, agrupa por clasificacion, marca urgentes. 7 tests. - set_dod_contract: escribe el DoD-contrato fijo (dod_contract/dod_status) en el goal.json de un agente sin pisar el resto (escritura atomica). 5 tests. Skill /orquestador evolucionado (sin romper lo existente): vigila la flota por su DoD (no por 'esta vivo'). Nueva seccion 'Consumo de la cola de la flota': DoD-contrato obligatorio al lanzar, drenar la cola, politicas por clasificacion (RECLAMA escala / DICE_TERMINADO verifica / ESTANCADO nudge / MAL_LANZADO re-DoD), verificador independiente del ejecutor (lee el report vs dod_contract), splitter con tope de fan-out, y cadencia (drain al actuar + heartbeat). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: orquestador
|
||||
description: "Modo orquestador: el Claude principal NO hace el trabajo pesado — descompone la tarea y lanza Claudes SECUNDARIOS interactivos, cada uno en su propia terminal kitty con un prompt autonomo y aislamiento git impuesto. El humano habla solo con el orquestador, ve a los secundarios en sus kitties y puede saltar a cualquiera. El orquestador sigue la flota, lee sus reports e integra. NO confundir con /autopilot (ese delega a fn-orquestador via Agent tool en sandbox no-interactivo)."
|
||||
description: "Modo orquestador: el Claude principal NO hace el trabajo pesado — descompone la tarea y lanza Claudes SECUNDARIOS interactivos, cada uno en su propia terminal con un prompt autonomo, aislamiento git impuesto y un DoD-contrato fijo. El humano habla solo con el orquestador, ve a los secundarios y puede saltar a cualquiera. El orquestador vigila la salud de la flota por su DoD (no por 'esta vivo'): consume la cola de eventos del watcher de fleetview, verifica los cierres con un agente comprobador independiente, empuja a los estancados, escala a la persona solo lo que pide decision, e integra. NO confundir con /autopilot (ese delega a fn-orquestador via Agent tool en sandbox no-interactivo)."
|
||||
---
|
||||
|
||||
# /orquestador — coordinar Claudes secundarios interactivos en kitty
|
||||
@@ -118,6 +118,11 @@ el prompt debe ser **autocontenido**. Incluye SIEMPRE:
|
||||
`delegation.md`).
|
||||
6. **La coletilla**: *"reporta tu progreso en esta terminal"* — para que el humano que mire la
|
||||
kitty vea el estado sin abrir el report.
|
||||
7. **DoD-contrato** — el criterio de aceptación **fijo y verificable** del secundario (golden +
|
||||
edge + error path con evidencia ejecutable, `dod_quality.md`), redactado por ti. Va en el
|
||||
prompt Y se escribe en el `goal.json` del secundario con `set_dod_contract` en cuanto conozcas
|
||||
su `sessionId` (paso 5). Es el blanco estable contra el que el verificador juzgará el cierre.
|
||||
Sin `dod_contract`, el agente se clasifica `MAL_LANZADO`. Ver "Consumo de la cola de la flota".
|
||||
|
||||
Mira `/tmp/unibus_agent_*.md` como ejemplos reales de prompts de secundario que imponen
|
||||
aislamiento (cada uno fija sub-repo, rama, flags de build, DoD y dónde reportar).
|
||||
@@ -180,6 +185,85 @@ Cuando un secundario termina (rama pusheada + report verde):
|
||||
Regla práctica: si el humano va a querer hablar con ello o mirarlo trabajar → kitty. Si es una
|
||||
sub-tarea que devuelve un resultado y se acabó → Agent tool.
|
||||
|
||||
## Consumo de la cola de la flota — el cerebro reactivo (flow 0012)
|
||||
|
||||
Seguir la flota (paso 5) no es solo "¿quién vive?". Es **vigilar la salud por el DoD**: cada agente termina lo que empieza, o sabes por qué no. La métrica es el **throughput de DoD cumplidos**, no el número de agentes vivos — 30 agentes que no cierran nada no sirven. La fuente es la cola del **watcher embebido en fleetview** (`~/.claude/fleet/events.jsonl`): una línea por **transición** de estado de un agente (edge-triggered, sin ruido de nivel). El orquestador la drena cada vez que actúa y aplica una política por clasificación.
|
||||
|
||||
### DoD-contrato fijo al lanzar (regla dura)
|
||||
|
||||
Ningún secundario arranca sin **DoD-contrato**: el criterio de aceptación FIJO contra el que se evalúa su terminación. Es distinto del campo `dod` (resumen móvil que el hook GOAL-TRACKER reescribe con cada prompt). Tras lanzar y conocer el `sessionId`:
|
||||
|
||||
```bash
|
||||
./fn run set_dod_contract <sessionId> "Golden: <caso feliz+evidencia>. Edge: <2 bordes>. Error: <1 fallo manejado>." pending
|
||||
```
|
||||
|
||||
El contrato sigue `dod_quality.md` (golden + edge + error con evidencia ejecutable), no un checkbox vago. Sin él, el agente es `MAL_LANZADO`.
|
||||
|
||||
### Drenar la cola
|
||||
|
||||
```bash
|
||||
./fn run drain_fleet_events # consume nuevos (avanza cursor), agrupa por clasificación, marca urgentes
|
||||
./fn run drain_fleet_events --advance false # peek sin consumir (inspección)
|
||||
```
|
||||
|
||||
Devuelve `{total_new, events, by_classification, urgent, cursor}`. La clasificación de cada agente la produce `classify_fleet_termination` (pura) desde su estado (status + phase + dod_contract + dod_status + segundos ociosos).
|
||||
|
||||
### Políticas por clasificación
|
||||
|
||||
| Transición a… | Qué hace el orquestador |
|
||||
|---|---|
|
||||
| `RECLAMA` (urgent) | **Escalar a la persona**: resumen corto de QUÉ decisión se necesita + `/fleet focus <sid>` para llevarla al agente. Si no está presente, `PushNotification`. NUNCA decidir tú por ella en un RECLAMA. |
|
||||
| `DICE_TERMINADO` | Lanzar **verificador independiente** (abajo). No confiar en el autodeclarado. |
|
||||
| `ESTANCADO` | **Nudge** al agente (abajo). Solo idle; jamás waiting. |
|
||||
| `MAL_LANZADO` | Escribir `dod_contract` retroactivo (`set_dod_contract`) o re-lanzar con DoD. |
|
||||
| `TRABAJANDO` | No molestar. |
|
||||
| `GONE` | Limpiar de la tabla de seguimiento (terminó o murió; si tenía DoD sin cumplir, anótalo). |
|
||||
|
||||
### Verificador — cierre de `DICE_TERMINADO` (cero auto-aprobación)
|
||||
|
||||
Cuando un agente se autodeclara terminado, **no se confía**: lanzas un **verificador independiente** del ejecutor (Agent efímero), que compara el **report** del ejecutor (en `reports/`, con evidencia ejecutable) contra su `dod_contract`:
|
||||
|
||||
```
|
||||
Agent(subagent_type="general-purpose", prompt:
|
||||
"Verifica de forma ADVERSARIAL si el trabajo cumple su DoD-contrato. NO ejecutaste tú la tarea.
|
||||
DoD-contrato: <contract>
|
||||
Report del ejecutor: <ruta del reports/NNNN-*.md>
|
||||
Comprueba CADA cláusula (golden + edge + error) contra la evidencia citada en el report; re-ejecuta
|
||||
los comandos de verificación si puedes. Devuelve {verdict: met|failed, gaps: [...], evidence: [...]}.
|
||||
Por defecto failed si la evidencia no respalda una cláusula.")
|
||||
```
|
||||
|
||||
- `met` → el orquestador **cierra/reasigna** el agente y lo informa a la persona. Marca `set_dod_contract <sid> "<contract>" met`.
|
||||
- `failed` → **nudge** al ejecutor con el gap concreto (no cerrar). `set_dod_contract <sid> "<contract>" failed` (vuelve a pending tras el nudge si reabre trabajo).
|
||||
|
||||
### 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:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
El `window_id` lo da `list_claude_fleet`/`fleetview list --json`. **Solo a idle/ESTANCADO. JAMÁS a un agente en `waiting`/`preguntando`** — esos te reclaman a TI, no un empujón del bot.
|
||||
|
||||
### Splitter — tarea demasiado grande
|
||||
|
||||
Si una sub-tarea sigue siendo grande para un solo agente, antes de lanzarla pásala por un **splitter** (Agent efímero) que devuelve un plan de sub-tareas atómicas, cada una con su `dod_contract` y sus dependencias:
|
||||
|
||||
```
|
||||
Agent(subagent_type="Plan", prompt:
|
||||
"Descompón esta tarea en sub-tareas ATÓMICAS, cada una cerrable por UN agente en una sesión, con
|
||||
su propio DoD-contrato (golden+edge+error) y dependencias (cuáles son paralelas y cuáles
|
||||
secuenciales). Máximo 6 sub-tareas. Tarea: <...>. Devuelve [{tarea, dod_contract, deps:[...]}].")
|
||||
```
|
||||
|
||||
El orquestador lanza un ejecutor por sub-tarea respetando las dependencias (paralelas a la vez, secuenciales encadenadas). **Tope de fan-out** para no explotar la flota.
|
||||
|
||||
### Cadencia
|
||||
|
||||
El orquestador no hace polling caro: drena la cola **cuando actúa** (cuando la persona le habla) y, para vigilancia desatendida, con un heartbeat largo (`ScheduleWakeup` 20-30 min) o cuando el watcher empuja un urgente. Lo urgente (`RECLAMA`) sube al instante; el resto (cierres, estancados) se procesa en lote.
|
||||
|
||||
## Reglas duras del modo
|
||||
|
||||
- **El orquestador no hace el trabajo pesado.** Descompone, lanza, sigue, integra. Si te
|
||||
@@ -213,6 +297,10 @@ sub-tarea que devuelve un resultado y se acabó → Agent tool.
|
||||
| `launch_claude_agent_kitty_bash_infra` | Lanzar un secundario en kitty con prompt autónomo + `--dangerously-skip-permissions` |
|
||||
| `list_claude_agents_bash_infra` | Listar la flota de Claudes vivos (PID, sessionId, cwd, status, kitty) para seguirla |
|
||||
| `reboot_all_claudes_bash_infra` | Reiniciar/parar la flota retomando sesiones; `--exclude-current` para no tocarte |
|
||||
| `set_dod_contract_py_infra` | Escribir el DoD-contrato fijo (`dod_contract`/`dod_status`) en el `goal.json` de un secundario al lanzarlo |
|
||||
| `drain_fleet_events_py_infra` | Consumir la cola de transiciones del watcher (`~/.claude/fleet/events.jsonl`), agrupada por clasificación + urgentes |
|
||||
| `classify_fleet_termination_go_infra` | Clasificar el estado de terminación de un agente (RECLAMA/MAL_LANZADO/DICE_TERMINADO/ESTANCADO/TRABAJANDO) — lo usa el watcher |
|
||||
| `list_claude_fleet_go_infra` | Fleet tipado con goal/phase/`dod_contract`/`dod_status`/`role` + window tmux (alimenta `/fleet` y el watcher) |
|
||||
|
||||
## Ejemplo end-to-end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user