28a53ee357
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>
70 lines
3.2 KiB
Go
70 lines
3.2 KiB
Go
package infra
|
|
|
|
// Termination labels returned by ClassifyFleetTermination. They describe the
|
|
// mechanical termination state of a Claude fleet agent so a cheap (LLM-free)
|
|
// watcher can decide what to do with it.
|
|
const (
|
|
// TerminationReclama means the agent is asking for human input and must be
|
|
// attended first, above any other consideration.
|
|
TerminationReclama = "RECLAMA"
|
|
// TerminationMalLanzado means the agent was launched without a DoD contract
|
|
// — no agent should run without an acceptance criterion.
|
|
TerminationMalLanzado = "MAL_LANZADO"
|
|
// TerminationDiceTerminado means the agent claims it is finished (idle and
|
|
// either phase "hecho" or its DoD status is "met").
|
|
TerminationDiceTerminado = "DICE_TERMINADO"
|
|
// TerminationEstancado means the agent is idle, not finished, and has been
|
|
// inactive at or beyond the stall threshold.
|
|
TerminationEstancado = "ESTANCADO"
|
|
// TerminationTrabajando means the agent is still working (busy, or idle
|
|
// recently below the stall threshold).
|
|
TerminationTrabajando = "TRABAJANDO"
|
|
)
|
|
|
|
// ClassifyFleetTermination mechanically classifies the termination state of a
|
|
// fleet agent. It is pure and deterministic: no I/O, no clock, no global state.
|
|
//
|
|
// Inputs:
|
|
// - status: process state from sessions.json — "idle" | "busy" | "waiting".
|
|
// - phase: work phase from goal.json — "investigando", "planificando",
|
|
// "haciendo", "testeando", "puliendo", "pendiente_revision", "preguntando",
|
|
// "bloqueado", "en_pausa", "hecho", "iterando" or "".
|
|
// - dodContract: fixed acceptance criterion ("" means none was defined).
|
|
// - dodStatus: "pending" | "met" | "failed" | "".
|
|
// - idleSeconds: seconds since the session's last activity.
|
|
// - stallThresholdSeconds: threshold to consider the agent stalled.
|
|
//
|
|
// Precedence (evaluated top to bottom; the first match wins):
|
|
// 1. RECLAMA — the agent is asking for human input (status "waiting" OR phase
|
|
// "preguntando"/"bloqueado"). This dominates everything, even a missing DoD
|
|
// contract: if it asks for input, that is the first thing to handle.
|
|
// 2. MAL_LANZADO — it does not reclaim input but has no DoD contract; no agent
|
|
// should run without one.
|
|
// 3. DICE_TERMINADO — idle AND (phase "hecho" OR dodStatus "met").
|
|
// 4. ESTANCADO — idle AND phase not "hecho" AND idleSeconds >= stall threshold.
|
|
// 5. TRABAJANDO — everything else (busy, or idle recently below the threshold).
|
|
func ClassifyFleetTermination(status, phase, dodContract, dodStatus string, idleSeconds, stallThresholdSeconds int) string {
|
|
// 1. RECLAMA dominates: a request for human input is handled first.
|
|
if status == "waiting" || phase == "preguntando" || phase == "bloqueado" {
|
|
return TerminationReclama
|
|
}
|
|
|
|
// 2. MAL_LANZADO: running without a DoD contract is invalid.
|
|
if dodContract == "" {
|
|
return TerminationMalLanzado
|
|
}
|
|
|
|
// 3. DICE_TERMINADO: idle and self-reporting completion.
|
|
if status == "idle" && (phase == "hecho" || dodStatus == "met") {
|
|
return TerminationDiceTerminado
|
|
}
|
|
|
|
// 4. ESTANCADO: idle, not finished, inactive at/beyond the stall threshold.
|
|
if status == "idle" && phase != "hecho" && idleSeconds >= stallThresholdSeconds {
|
|
return TerminationEstancado
|
|
}
|
|
|
|
// 5. TRABAJANDO: busy, or idle recently below the threshold.
|
|
return TerminationTrabajando
|
|
}
|