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:
@@ -0,0 +1,68 @@
|
||||
---
|
||||
name: set_dod_contract
|
||||
kind: function
|
||||
lang: py
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def set_dod_contract(session_id: str, contract: str, status: str = 'pending', goals_dir: str | None = None) -> dict"
|
||||
description: "Escribe un DoD-contrato fijo y su estado en el sidecar goal.json de una sesion Claude (~/.claude/goals/<session_id>.json). Preserva TODOS los campos existentes (goal, phase, dod, history, prompts) y solo actualiza dod_contract y dod_status. Usado por el meta-orquestador de flota para fijar el criterio de aceptacion estable contra el que se evalua la terminacion de un agente. Escritura atomica via tmp + os.replace."
|
||||
tags: [fleet, claude-fleet, dod, goals, orchestrator, sidecar, json]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: ["os", "json"]
|
||||
params:
|
||||
- name: session_id
|
||||
desc: "ID de la sesion Claude; da nombre al archivo <session_id>.json dentro de goals_dir"
|
||||
- name: contract
|
||||
desc: "criterio de aceptacion estable (DoD-contrato) contra el que se evalua la terminacion del agente; no puede ser vacio"
|
||||
- name: status
|
||||
desc: "estado del contrato; uno de 'pending' | 'met' | 'failed' (default 'pending'); otro valor -> ValueError"
|
||||
- name: goals_dir
|
||||
desc: "directorio de sidecars de goal; default ~/.claude/goals; en tests apuntar a tmp_path para no tocar el real"
|
||||
output: "dict con session_id, path (ruta del goal.json escrito), dod_contract, dod_status y written=True"
|
||||
tested: true
|
||||
tests:
|
||||
- "Escribe contrato en goal.json existente y preserva otros campos"
|
||||
- "Crea el archivo si no existe"
|
||||
- "Status invalido lanza ValueError sin escribir"
|
||||
- "Contract vacio lanza ValueError sin escribir"
|
||||
- "Re-escribir actualiza sin duplicar claves"
|
||||
test_file_path: "python/functions/infra/set_dod_contract_test.py"
|
||||
file_path: "python/functions/infra/set_dod_contract.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
from infra.set_dod_contract import set_dod_contract
|
||||
|
||||
# El meta-orquestador fija el criterio de aceptacion al lanzar un agente.
|
||||
res = set_dod_contract(
|
||||
session_id="a1b2c3d4-5678-90ab-cdef-1234567890ab",
|
||||
contract="Los tests de python/functions/infra/ pasan en verde y fn doctor uses-functions no reporta drift",
|
||||
status="pending",
|
||||
)
|
||||
print(res)
|
||||
# {'session_id': 'a1b2c3d4-...', 'path': '/home/enmanuel/.claude/goals/a1b2c3d4-....json',
|
||||
# 'dod_contract': '...', 'dod_status': 'pending', 'written': True}
|
||||
|
||||
# Mas tarde, al evaluar la terminacion: marcar el contrato cumplido (preserva goal/phase/dod).
|
||||
set_dod_contract("a1b2c3d4-5678-90ab-cdef-1234567890ab", res["dod_contract"], status="met")
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Usala cuando el meta-orquestador de flota lance un agente y necesite fijar el DoD-contrato estable, y cada vez que reevalue la terminacion para mover `dod_status` a `met` o `failed`. Es la unica via correcta para tocar `dod_contract`/`dod_status` sin pisar el resto del sidecar goal.json.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- El hook GOAL-TRACKER reescribe la clave `dod` del goal.json (el DoD de trabajo, volatil) en cada turno, pero NO debe tocar `dod_contract` ni `dod_status` (el contrato FIJO de aceptacion). Esta funcion solo escribe esas dos claves y preserva `dod` tal cual la dejo el hook.
|
||||
- `status` solo acepta "pending" | "met" | "failed". Cualquier otro valor lanza ValueError ANTES de escribir: el archivo en disco queda intacto.
|
||||
- `contract` vacio o solo whitespace lanza ValueError sin escribir.
|
||||
- Escritura atomica (tmp + os.fsync + os.replace): si el proceso muere a mitad, el goal.json original no se corrompe.
|
||||
- Si el goal.json existente es JSON corrupto o ilegible, se parte de un dict vacio (no se aborta) — se pierde el contenido viejo ilegible pero se preserva el contrato nuevo. Es deliberado: un sidecar ya roto no debe bloquear al orquestador.
|
||||
- `goals_dir` default es `~/.claude/goals` (real). En tests SIEMPRE pasar `goals_dir=str(tmp_path)` para no tocar las sesiones vivas.
|
||||
Reference in New Issue
Block a user