9365def3dd
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>
368 lines
23 KiB
Markdown
368 lines
23 KiB
Markdown
---
|
|
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 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
|
|
|
|
Activa un **modo de comportamiento** persistente. Mientras estás dentro, tú eres el
|
|
**orquestador**: el Claude principal con el que el humano habla. Tu trabajo no es hacer la
|
|
tarea grande tú mismo, sino **descomponerla** y delegar cada pieza a un Claude **secundario**
|
|
que arranca en su propia terminal kitty, con un prompt autónomo inyectado y un dir de trabajo
|
|
aislado. El humano ve a esos secundarios en sus terminales, puede saltar a cualquiera para
|
|
iterar en directo, y tú los coordinas: los lanzas, sigues su progreso, lees sus reports y los
|
|
integras cuando terminan.
|
|
|
|
El modo permanece activo en todos los turnos siguientes hasta que el humano escriba `salir
|
|
orquestador` o `fin orquestador`. No hay hook: el modo se sostiene por estas instrucciones
|
|
mientras estén en contexto. Si el comportamiento se diluye tras muchos turnos, el humano puede
|
|
re-invocar `/orquestador` para reanclarlo.
|
|
|
|
Al entrar, responde con una sola línea de confirmación y queda a la espera de la tarea grande:
|
|
|
|
```
|
|
MODO ORQUESTADOR activo. Dame la tarea grande; la descompongo y lanzo secundarios. 'fin orquestador' para terminar.
|
|
```
|
|
|
|
## Qué NO es: diferencia con `fn-orquestador` / `/autopilot`
|
|
|
|
Hay dos cosas con nombre parecido. No las confundas:
|
|
|
|
| | **Modo orquestador** (este comando) | **`fn-orquestador`** (subagent / `/autopilot`) |
|
|
|---|---|---|
|
|
| Mecanismo | Lanza Claudes **interactivos** en terminales **kitty** | Lanza un sub-agente via el **Agent tool** (no interactivo) |
|
|
| Visibilidad | El humano **ve y habla** con cada secundario en su kitty | El sub-agente corre headless; el humano no lo ve |
|
|
| Persistencia | El secundario **vive en su terminal**, se puede retomar (`claude --resume`) | El sub-agente termina y devuelve su texto final |
|
|
| Aislamiento | worktree / sub-repo / scope de archivos, impuesto en el prompt | worktree `auto/<issue>` gestionado por el propio `fn-orquestador` |
|
|
| Gobierno | El humano coordina via el orquestador; iteración en vivo | Bucle autónomo CONSTRUIR→EJECUTAR→...→MEJORAR hasta converger, PR draft |
|
|
| Regla de referencia | esta página | `.claude/rules/autonomous_loop.md` |
|
|
|
|
Resumen: **`fn-orquestador` (issue 0069) es para autonomía no supervisada con PR al final**; el
|
|
**modo orquestador es para trabajo largo que el humano quiere ver y poder retomar**, con varios
|
|
Claudes humanos-en-el-loop a la vez. Si el humano quiere fan-out autónomo y barato sin mirar,
|
|
usa el Agent tool o `/autopilot`; si quiere una flota de Claudes interactivos que él supervisa,
|
|
usa este modo.
|
|
|
|
## El ciclo del orquestador (8 pasos)
|
|
|
|
### 1. Descomponer
|
|
|
|
Parte la tarea grande en **sub-tareas independientes** que puedan correr en paralelo **sin
|
|
pisarse**. El criterio de independencia es sobre todo de **git**: dos sub-tareas que escriben
|
|
los mismos archivos NO son independientes (ver paso 3). Buenas líneas de corte: una app/sub-repo
|
|
distinto por secundario; un dominio de funciones distinto; un módulo o paquete disjunto; el
|
|
frontend vs el backend; documentación vs código. Si dos piezas comparten archivos, o las fusionas
|
|
en un secundario, o las serializas (una después de otra), o las das scopes de archivos disjuntos.
|
|
|
|
### 2. Lanzar cada secundario
|
|
|
|
Comando canónico de lanzamiento (memoria `lanzar-agentes-skip-permissions`), **siempre** con
|
|
`--dangerously-skip-permissions` porque los secundarios trabajan autónomos y desatendidos y los
|
|
prompts de permiso en cada Bash los atascarían:
|
|
|
|
```bash
|
|
setsid nohup kitty --title "<PROYECTO> · <subtarea>" --directory <dir-aislado> \
|
|
zsh -ic 'claude --dangerously-skip-permissions "$(cat /tmp/orq_<slug>.md)"; exec zsh' \
|
|
>/tmp/orq_<slug>_kitty.log 2>&1 & disown
|
|
```
|
|
|
|
`setsid nohup ... & disown` hace que la kitty sobreviva al cierre de la terminal padre. El
|
|
`zsh -ic '...; exec zsh'` deja una shell interactiva viva cuando el claude termina, para que el
|
|
humano siga en esa terminal. El log de `/tmp/orq_<slug>_kitty.log` es donde se ve el arranque.
|
|
|
|
**Prefiere la función del registry** en vez de teclear el one-liner a mano (registry-first,
|
|
queda en telemetría):
|
|
|
|
```bash
|
|
./fn run launch_claude_agent_kitty "<PROYECTO> · <subtarea>" <dir-aislado> /tmp/orq_<slug>.md
|
|
```
|
|
|
|
- `launch_claude_agent_kitty_bash_infra(title, directory, prompt_file)` — lanza el secundario con
|
|
el comando canónico exacto y devuelve el log donde se ve el arranque. Valida que el dir y el
|
|
prompt_file existan y que kitty esté instalado.
|
|
|
|
### 3. Aislamiento git obligatorio por secundario (regla de oro)
|
|
|
|
**Dos Claudes en el MISMO working tree comparten `HEAD` y el índice; sus `git checkout` se
|
|
interleavean y los commits caen en la rama equivocada** (memoria `multi-agent-git-race-same-repo`,
|
|
caso real del 06/06/2026: los commits de un agente acabaron en la rama del otro y su propia rama
|
|
quedó vacía). Por eso **cada secundario trabaja en un espacio aislado**, y el orquestador elige
|
|
cuál y se lo **impone** en el prompt del secundario:
|
|
|
|
| Opción | Cómo | Cuándo |
|
|
|---|---|---|
|
|
| **(a) Sub-repo Gitea propio** | El secundario trabaja dentro de `apps/<x>/`, `analysis/<x>/`, `projects/<p>/...` — cada uno tiene su `.git` independiente (regla `apps_subrepo.md`) | Cuando las sub-tareas caen en apps/analyses/projects distintos. Es el aislamiento natural del monorepo. |
|
|
| **(b) git worktree** | `git worktree add /tmp/<slug> -b <rama> master` y el secundario hace TODO ahí. Worktrees comparten objetos pero **no** HEAD/índice | Cuando varios secundarios tocan el repo padre `fn_registry` a la vez (funciones, reglas, docs). |
|
|
| **(c) Scope de archivos disjunto** | Mismo working tree pero cada secundario commitea **solo sus paths**: `git add <paths-específicos>`, **nunca** `git add -A` | Último recurso, solo si los scopes están garantizados disjuntos y no hay `git checkout` de rama de por medio. Frágil; prefiere (a) o (b). |
|
|
|
|
Para (b), crea el worktree **tú** (el orquestador) antes de lanzar, desde el working tree
|
|
principal, y pásale al secundario el path del worktree como `<dir-aislado>`.
|
|
|
|
### 4. El prompt de cada secundario
|
|
|
|
Lo escribes tú en `/tmp/orq_<slug>.md` antes de lanzar. El secundario **no ve este historial**;
|
|
el prompt debe ser **autocontenido**. Incluye SIEMPRE:
|
|
|
|
1. **Objetivo claro** — qué construir/arreglar, acotado y verificable.
|
|
2. **Dónde trabaja** — el dir aislado exacto (worktree, sub-repo o dir), por path absoluto.
|
|
3. **Reglas de aislamiento git** — qué NO tocar (otros repos/worktrees, el working tree
|
|
principal `~/fn_registry`), en qué rama commitear, y **cómo**: commits atómicos con `git add`
|
|
de paths específicos, nunca `git add -A`; si es worktree, push de la rama al terminar, sin
|
|
merge a master (lo integra el orquestador).
|
|
4. **Qué entrega y dónde** — un **report** en `reports/` (o `projects/<p>/reports/`) con
|
|
evidencia ejecutable (comandos + salida cruda), siguiendo `.claude/rules/reports.md` y
|
|
`.claude/rules/dod_quality.md`. Reports son artefacto local gitignored: se escriben, no se
|
|
commitean.
|
|
5. **Que puede delegar** — recuérdale que es full-capaz: puede spawnar `fn-constructor`,
|
|
`fn-executor`, etc. via el Agent tool, y debe seguir registry-first (`registry_calls.md`,
|
|
`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).
|
|
|
|
### 5. Seguir la flota
|
|
|
|
Mantén una **tabla de agentes vivos** y actualízala en cada turno. La fuente de verdad del
|
|
mapeo PID→sessionId→cwd son los archivos `~/.claude/sessions/<PID>.json` (memoria
|
|
`claude-session-pid-mapping`). Usa la función del registry para listarla:
|
|
|
|
```bash
|
|
./fn run list_claude_agents # tabla: PID, STATUS, ETIME, KITTY, SELF, SESSION_ID, CWD
|
|
./fn run list_claude_agents --json # para parsear y decidir
|
|
```
|
|
|
|
- `list_claude_agents_bash_infra([--json] [--exclude-current])` — cruza `pgrep -x claude` con los
|
|
`sessions/<PID>.json` (con validación anti-PID-reciclado), marca tu propia sesión como `SELF`,
|
|
y reporta cwd + sessionId de cada secundario (para retomar con `claude --resume <sessionId>`).
|
|
|
|
Tu tabla de seguimiento, una fila por secundario:
|
|
|
|
| slug | título kitty | PID | cwd / dir aislado | rama | log | report | estado |
|
|
|---|---|---|---|---|---|---|---|
|
|
| docs | fn_registry · docs | 3637133 | /tmp/orq_docs_wt | orq/docs | /tmp/orq_docs_kitty.log | reports/00NN-…-docs.md | en curso |
|
|
|
|
Cuando un secundario parezca terminado, confirma: ¿pusheó la rama? ¿escribió el report? Lee el
|
|
report (`reports/`), revisa los commits de su rama (`git -C <dir> log --oneline`).
|
|
|
|
### 6. NUNCA `pkill`/`killall` sobre claude
|
|
|
|
Un `pkill claude` o `killall claude` **te mata a ti mismo** (el orquestador) junto con la flota.
|
|
Para parar un secundario:
|
|
|
|
- **Kill por PID exacto** del secundario (lo tienes en la tabla / `list_claude_agents`):
|
|
`kill <PID>` (o `kill <KITTY_PID>` para cerrar su ventana). Verifica que NO es tu `SELF`.
|
|
- **`reboot_all_claudes_bash_infra`** para reiniciar la flota retomando sesiones; tiene
|
|
`--exclude-current` para no tocarte a ti. Es dry-run por defecto; `--go` para ejecutar.
|
|
|
|
### 7. Integrar
|
|
|
|
Cuando un secundario termina (rama pusheada + report verde):
|
|
|
|
1. **Revisa** su diff y su report. Si el report no trae evidencia ejecutable o falla la DoD,
|
|
devuélvele trabajo (el humano puede saltar a su kitty, o tú le mandas otro prompt).
|
|
2. **Mergea si procede** desde el **working tree principal** (ahí suele estar `master`
|
|
checked-out): `git -C ~/fn_registry merge --no-ff <rama>` para apps con TBD, o el flujo que
|
|
corresponda al sub-repo. Para funciones nuevas del registry padre, sus archivos viajan en la
|
|
rama y el merge los lleva a master.
|
|
3. **Informa al humano** y **resume el estado de la flota** en cada turno: quién terminó, quién
|
|
sigue, qué se integró, qué falta.
|
|
|
|
### 8. kitty vs Agent tool — cuándo cada uno
|
|
|
|
- **kitty (este modo)**: trabajo **largo e interactivo** que el humano quiere **ver** y poder
|
|
**retomar** — implementar una feature de horas, depurar en vivo, una sesión que evoluciona.
|
|
- **Agent tool directo**: fan-out **acotado y no interactivo** — buscar en el codebase, crear
|
|
una función con `fn-constructor`, auditar N apps con `fn-recopilador`. Más barato, sin
|
|
terminal, sin supervisión humana. Para esto NO lances kitty: usa `Agent(...)` y ya.
|
|
|
|
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
|
|
encuentras escribiendo tú la feature, párate: ¿no debería ser un secundario?
|
|
- **Cada secundario, su aislamiento.** Nunca lances dos secundarios sobre el mismo working tree
|
|
sin worktrees/sub-repos/scopes disjuntos. Es la causa nº1 de commits perdidos.
|
|
- **El prompt del secundario lleva SIEMPRE las reglas de aislamiento.** Un prompt sin "trabaja
|
|
aquí, no toques aquello, commitea así" es un secundario que contaminará otro repo.
|
|
- **Nunca `git add -A` en un secundario** salvo que su dir aislado sea exclusivamente suyo
|
|
(worktree/sub-repo). En scope compartido, paths específicos.
|
|
- **Nunca `pkill`/`killall claude`.** Kill por PID exacto o `reboot_all_claudes --exclude-current`.
|
|
- **El humano habla contigo.** Tú resumes la flota; no le hagas perseguir 5 terminales.
|
|
|
|
## Anti-patrones
|
|
|
|
| Anti-patrón | Por qué es malo | En su lugar |
|
|
|---|---|---|
|
|
| `pkill claude` para parar la flota | Te mata a ti (el orquestador) también | Kill por PID exacto / `reboot_all_claudes --exclude-current` |
|
|
| Dos secundarios en el mismo working tree | Comparten HEAD/índice → commits dispersos, ramas vacías | worktree / sub-repo / scope disjunto por secundario |
|
|
| Prompt de secundario sin reglas de aislamiento | El secundario contamina el repo padre u otro worktree | El prompt fija dir, qué NO tocar, rama y cómo commitear |
|
|
| `git add -A` en scope compartido | Arrastra cambios de otra sub-tarea al commit | `git add <paths-específicos>` |
|
|
| Lanzar kitty para un fan-out trivial | Caro y sin supervisión que aporte | Agent tool directo (`fn-constructor`, `Explore`, …) |
|
|
| Hacer tú la feature "porque es rápido" | Pierdes el sentido del modo; el humano no lo ve evolucionar | Descompón y lanza un secundario |
|
|
| Lanzar sin `--dangerously-skip-permissions` | El secundario se atasca pidiendo permiso en cada Bash | Siempre `--dangerously-skip-permissions` (riesgo asumido) |
|
|
| Mergear desde el dir del secundario | Master suele estar en el working tree principal; colisión de HEAD | Mergear desde `~/fn_registry` |
|
|
|
|
## Funciones del registry que usa este modo (grupo `orchestration`)
|
|
|
|
| Función | Para qué |
|
|
|---|---|
|
|
| `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
|
|
|
|
Tarea grande: *"añade un endpoint `/api/health` al backend de la app `kanban` y, en paralelo,
|
|
documenta el grupo de capacidad `deploy` en `docs/capabilities/deploy.md`"*. Dos piezas
|
|
independientes: una toca el sub-repo `apps/kanban` (su propio `.git`), la otra toca el repo
|
|
padre `fn_registry` (docs). Aislamiento natural distinto para cada una.
|
|
|
|
```bash
|
|
# 1. Descomponer → 2 secundarios independientes:
|
|
# A) health endpoint → sub-repo apps/kanban (aislamiento (a))
|
|
# B) doc capability → worktree del padre (aislamiento (b))
|
|
|
|
# 2. Preparar aislamiento de B (worktree del padre; A ya está aislado por su sub-repo):
|
|
git -C ~/fn_registry worktree add /tmp/orq_capdoc -b orq/cap-deploy master
|
|
|
|
# 3. Escribir los prompts autónomos (autocontenidos, con reglas de aislamiento):
|
|
# /tmp/orq_health.md → "trabaja en apps/kanban (sub-repo propio), rama issue/health,
|
|
# commits atómicos de tus paths, push al terminar, report en reports/. No toques el
|
|
# repo padre. Reporta tu progreso en esta terminal."
|
|
# /tmp/orq_capdoc.md → "trabaja SOLO en /tmp/orq_capdoc (worktree), rama orq/cap-deploy,
|
|
# toca solo docs/capabilities/deploy.md, git add de ese path, push al terminar, report
|
|
# en reports/. No toques ~/fn_registry. Reporta tu progreso en esta terminal."
|
|
|
|
# 4. Lanzar ambos secundarios (cada uno su kitty, su dir aislado):
|
|
./fn run launch_claude_agent_kitty "kanban · health endpoint" \
|
|
~/fn_registry/apps/kanban /tmp/orq_health.md
|
|
./fn run launch_claude_agent_kitty "fn_registry · doc deploy" \
|
|
/tmp/orq_capdoc /tmp/orq_capdoc.md
|
|
|
|
# 5. Seguir la flota (cada turno):
|
|
./fn run list_claude_agents
|
|
# → tabla con los 2 secundarios vivos (PID, cwd, sessionId, status) + tu SELF.
|
|
# Lee /tmp/orq_*_kitty.log para el arranque; cuando terminen, lee sus reports/.
|
|
|
|
# 7. Integrar (desde el working tree principal):
|
|
git -C ~/fn_registry/apps/kanban merge --no-ff issue/health # sub-repo de la app
|
|
git -C ~/fn_registry merge --no-ff orq/cap-deploy # repo padre (la doc)
|
|
git -C ~/fn_registry worktree remove /tmp/orq_capdoc # limpiar worktree
|
|
|
|
# Resumen al humano: A integrado (endpoint + test verde), B integrado (doc),
|
|
# flota vacía. Tarea grande hecha.
|
|
```
|
|
|
|
## Salida del modo
|
|
|
|
Cuando el humano escriba `salir orquestador` o `fin orquestador`, cierra con un resumen de la
|
|
flota: secundarios lanzados, cuáles terminaron e integraste, cuáles siguen vivos (con su kitty
|
|
para que el humano decida), y los reports generados. Si quedan secundarios vivos, recuérdale que
|
|
`list_claude_agents` los lista y que para pararlos es kill por PID exacto, nunca `pkill`.
|
|
|
|
## Relación con otras reglas
|
|
|
|
- `.claude/rules/autonomous_loop.md` — `fn-orquestador` (Agent tool, sandbox no-interactivo). Es
|
|
lo que este modo **no** es; tenlas claras separadas.
|
|
- `.claude/rules/apps_subrepo.md` — apps/analyses/projects son sub-repos Gitea (`apps/*`
|
|
gitignored): el aislamiento natural (opción (a)) y el gotcha de `git init` antes de limpiar un
|
|
worktree con una app nueva dentro.
|
|
- `.claude/rules/reports.md` + `.claude/rules/dod_quality.md` — qué entrega cada secundario:
|
|
report con evidencia ejecutable + gaps.
|
|
- `.claude/rules/delegation.md` + `.claude/rules/registry_calls.md` — los secundarios siguen
|
|
registry-first y delegan a `fn-constructor` igual que tú.
|
|
- Memorias: `lanzar-agentes-skip-permissions`, `multi-agent-git-race-same-repo`,
|
|
`claude-session-pid-mapping`, `prefiere-kitty-terminal`.
|