feat(infra): modelo de datos del meta-orquestador de flota (flow 0012)
Fase 1, piezas 1+2: - ClaudeFleet + list_claude_fleet ganan DodContract/DodStatus/Role, leidos de goals/<sessionId>.json (.dod_contract/.dod_status/.role). Aditivo: fleetview sigue compilando. - classify_fleet_termination (pura): clasifica el estado de terminacion de un agente (RECLAMA/MAL_LANZADO/DICE_TERMINADO/ESTANCADO/TRABAJANDO) con precedencia fija, para que un watcher sin LLM decida. 34 tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
---
|
||||
name: classify_fleet_termination
|
||||
kind: function
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func ClassifyFleetTermination(status, phase, dodContract, dodStatus string, idleSeconds, stallThresholdSeconds int) string"
|
||||
description: "Clasifica MECANICAMENTE el estado de terminacion de un agente Claude de la flota para que un watcher barato sin LLM decida que hacer. Pura y determinista. Devuelve una de RECLAMA, MAL_LANZADO, DICE_TERMINADO, ESTANCADO o TRABAJANDO segun precedencia fija: RECLAMA (pide input humano) manda sobre todo, luego MAL_LANZADO (sin DoD-contrato), luego DICE_TERMINADO, ESTANCADO y TRABAJANDO."
|
||||
tags: [fleet, claude-fleet, classification, watcher, termination, orchestrator, pure, infra]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
params:
|
||||
- name: status
|
||||
desc: "estado del proceso Claude leido de sessions.json: idle | busy | waiting"
|
||||
- name: phase
|
||||
desc: "fase de trabajo del goal.json: investigando | planificando | haciendo | testeando | puliendo | pendiente_revision | preguntando | bloqueado | en_pausa | hecho | iterando | (vacio)"
|
||||
- name: dodContract
|
||||
desc: "criterio de aceptacion fijo del agente; cadena vacia significa que no se definio DoD-contrato (agente mal lanzado)"
|
||||
- name: dodStatus
|
||||
desc: "estado de cumplimiento del DoD: pending | met | failed | (vacio)"
|
||||
- name: idleSeconds
|
||||
desc: "segundos transcurridos desde la ultima actividad de la sesion"
|
||||
- name: stallThresholdSeconds
|
||||
desc: "umbral en segundos a partir del cual un agente idle no terminado se considera ESTANCADO (comparacion >=, inclusiva)"
|
||||
output: "una etiqueta string: RECLAMA | MAL_LANZADO | DICE_TERMINADO | ESTANCADO | TRABAJANDO (constantes exportadas TerminationReclama, TerminationMalLanzado, TerminationDiceTerminado, TerminationEstancado, TerminationTrabajando)"
|
||||
tested: true
|
||||
tests:
|
||||
- "waiting reclama input"
|
||||
- "phase preguntando reclama"
|
||||
- "phase bloqueado reclama"
|
||||
- "waiting manda aunque sin dodContract"
|
||||
- "preguntando manda aunque sin dodContract"
|
||||
- "bloqueado manda aunque idle estancado"
|
||||
- "sin dodContract busy"
|
||||
- "sin dodContract idle reciente"
|
||||
- "sin dodContract idle estancado"
|
||||
- "sin dodContract phase hecho"
|
||||
- "sin dodContract dodStatus met"
|
||||
- "idle phase hecho"
|
||||
- "idle dodStatus met"
|
||||
- "idle hecho y met"
|
||||
- "idle met aunque estancado por tiempo"
|
||||
- "idle hecho aunque estancado por tiempo"
|
||||
- "idle no hecho en umbral exacto"
|
||||
- "idle no hecho por encima del umbral"
|
||||
- "idle iterando estancado"
|
||||
- "idle dodStatus failed estancado"
|
||||
- "idle en_pausa estancado"
|
||||
- "busy trabajando"
|
||||
- "busy aunque idleSeconds alto"
|
||||
- "idle reciente bajo umbral"
|
||||
- "idle reciente cero segundos"
|
||||
- "idle no hecho justo bajo umbral"
|
||||
- "busy phase vacia con dodContract"
|
||||
- "umbral cero idle no hecho => estancado"
|
||||
- "idle hecho con umbral cero => dice terminado"
|
||||
- "dodStatus met con status busy NO termina"
|
||||
- "phase hecho con status busy NO termina"
|
||||
- "idle pendiente_revision bajo umbral trabajando"
|
||||
- "idle pendiente_revision sobre umbral estancado"
|
||||
- "waiting con dodStatus met sigue reclamando"
|
||||
test_file_path: "functions/infra/classify_fleet_termination_test.go"
|
||||
file_path: "functions/infra/classify_fleet_termination.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
// Agente idle que dice estar terminado.
|
||||
label := ClassifyFleetTermination("idle", "hecho", "tests verdes + indexado", "met", 30, 600)
|
||||
// label == "DICE_TERMINADO" (== TerminationDiceTerminado)
|
||||
|
||||
// Agente idle, no terminado, parado 12 minutos con umbral de 10 minutos.
|
||||
label = ClassifyFleetTermination("idle", "haciendo", "tests verdes", "pending", 720, 600)
|
||||
// label == "ESTANCADO"
|
||||
|
||||
// Agente que reclama input humano: manda sobre todo, aunque le falte DoD.
|
||||
label = ClassifyFleetTermination("waiting", "haciendo", "", "", 5, 600)
|
||||
// label == "RECLAMA"
|
||||
|
||||
switch label {
|
||||
case TerminationReclama:
|
||||
// notificar al humano
|
||||
case TerminationMalLanzado:
|
||||
// matar y relanzar con DoD-contrato
|
||||
case TerminationDiceTerminado:
|
||||
// pasar a verificacion de DoD
|
||||
case TerminationEstancado:
|
||||
// empujar / reiniciar / escalar
|
||||
case TerminationTrabajando:
|
||||
// dejar trabajar
|
||||
}
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Usala en el watcher del meta-orquestador de flota (dev/flows/0012-fleet-orchestrator-dod.md) cuando barras cada agente Claude y necesites decidir mecanicamente, sin gastar LLM, en que cubo cae (reclama input / mal lanzado / dice terminado / estancado / trabajando) a partir de sessions.json + goal.json. Es el paso de triaje barato antes de cualquier accion costosa.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Precedencia estricta de arriba a abajo.** RECLAMA gana siempre, incluso si el agente no tiene `dodContract` o ya esta idle y estancado. Si tu logica espera que MAL_LANZADO domine, esta funcion no hace eso a proposito: un agente que pide input se atiende primero.
|
||||
- **El umbral es inclusivo (`>=`).** `idleSeconds == stallThresholdSeconds` ya cuenta como ESTANCADO. Con `stallThresholdSeconds == 0` cualquier agente idle no terminado es ESTANCADO al instante.
|
||||
- **`status == "busy"` nunca termina ni se estanca.** Aunque `dodStatus == "met"` o `phase == "hecho"`, si el proceso esta busy se clasifica como TRABAJANDO (la condicion de terminacion/estancamiento exige idle).
|
||||
- **Strings exactos, case-sensitive.** Valores fuera de los esperados (ej. "Idle", "WAITING", una phase desconocida) caen a TRABAJANDO salvo que disparen otra rama. Normaliza las entradas antes de llamar si tus fuentes no garantizan el casing.
|
||||
Reference in New Issue
Block a user