a03675113a
- .claude/agents/fn-orquestador/SKILL.md - .claude/commands/fn_claude.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - .claude/rules/ids_naming.md - CHANGELOG.md - apps/dag_engine/README.md - apps/dag_engine/api.go - apps/dag_engine/dags_migrated/example.yaml - apps/dag_engine/dags_migrated/example_lineage_tracking.yaml - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.3 KiB
5.3 KiB
Bucle autonomo (fn-orquestador + /autonomous-task) — issue 0069
fn-orquestador recorre el ciclo reactivo (CONSTRUIR → EJECUTAR → RECOPILAR → ANALIZAR → MEJORAR) sin intervencion humana, hasta convergencia (suite verde), estancamiento (no progreso N iteraciones), timeout, o tope de iteraciones. Trabaja SIEMPRE en sandbox auto/<issue>, NUNCA merge a master.
Cuando se invoca
- Skill
/autonomous-task <issue_id>(humano lanza explicitamente). - Cron / Dagu (planificable; no implementado por defecto).
- NO se invoca como reaccion a hooks ni a fallos de tests "en caliente". Siempre tarea explicita.
Reglas duras
- Sandbox obligatorio: rama
auto/<issue_id>-<slug>. Si la rama existe -> reset hard contra master y reanudar. NUNCA commits a master, NUNCA push --force-with-lease a master. - Paths protegidos: respetar
dev/autonomous_protected_paths.jsonexactamente. Cualquier intento de modificar un path protegido aborta la iteracion y registratask_runs.status='aborted_protected_path'. - Filtro de proposals auto-aplicables: el orquestador SOLO aplica proposals que cumplen:
kind in (bug_fix, e2e_check_add, doc_update, capability_tag_add)-> auto-aplicable.kind in (new_function, deprecate_function, refactor, schema_change)-> NO auto-aplicable (quedapendingpara humano).priority in (low, medium)-> auto-aplicable.high|critical-> requiere humano salvo override--allow-high.
- Watchdog: si la metrica de progreso (
checks_pass / checks_total) no sube enN=3iteraciones consecutivas -> abort. Registrartask_runs.status='stalled'. - Tiempo: cada
task_runcon timeout default 30 min. Override con--timeout-min Nhasta max 4h. - Idempotencia: re-ejecutar
/autonomous-task <id>sobre la misma issue reanuda desde la ultima iteracion exitosa, NO reinicia desde cero (lookup entask_runsporissue_id). - Trazabilidad: cada decision se persiste en
task_runs.events_json[]con{ts, agent, action, evidence, diff_summary}. El humano puede leer el log entero para auditar. - No self-modification: orquestador NUNCA modifica
.claude/agents/,.claude/commands/,.claude/rules/,.claude/scripts/,.claude/CLAUDE.md. Reforzado enautonomous_protected_paths.json. - NUNCA paths absolutos fuera del worktree. Refuerzo del piloto 1 (2026-05-15): el orquestador uso
/home/lucas/fn_registry/bash/functions/...para fixear hooks bash y contamino el repo principal. Solucion correcta: fix vive solo en el worktree. Post-cada-iteracion:git -C <main_repo> status --shortdebe permanecer igual al baseline; cualquier diff =status=sandbox_breach-> ABORT. - Pre-commit hooks compartidos. Worktrees comparten
.git/hooks/con main. Si un hook llama scripts via path absoluto, ejecutara la version de main. Si el hook bloquea progreso por bug en main: aplica el fix EN EL WORKTREE (commit en auto/*); si el bug del hook excede scope:git commit --no-verifypara ESE commit contask_runs.events_json[].decision="skip_hook"+ razon. NO editar main.
Estructura task_run
Migration fn_operations/migrations/006_task_runs.sql. Campos minimos: id, issue_id, branch, started_at, finished_at, status (running|done|failed|aborted_protected_path|stalled|timeout), iterations, checks_pass, checks_fail, proposals_applied_json, proposals_skipped_json, events_json, final_diff_sha.
Fases por iteracion
loop:
1. fn-constructor (Read+Edit+Write+Bash limitados) - aplica fix segun ultima proposal seleccionada
2. fn-executor - corre build + tests + smoke
3. fn-recopilador - audita operations.db de la app
4. fn-analizador - corre e2e_checks (registra e2e_runs)
5. SI todos los checks pasan -> commit + push rama + abre PR. status=done. exit.
6. SI no progreso N iteraciones -> abort. status=stalled.
7. fn-mejorador - crea proposals desde fallos
8. orquestador filtra proposals auto-aplicables -> selecciona la primera -> goto 1.
Output al humano
=== /autonomous-task 0068 ===
task_run_id: run_e2e_a1b2c3
branch: auto/0068-e2e-validation
iterations: 4
status: done
checks_pass: 8/8
proposals_applied: 3 (run_e2e_run_001, run_e2e_run_002, run_e2e_run_003)
proposals_skipped: 1 (refactor — needs human review)
PR: https://gitea.../pulls/42
Anti-patrones
| Anti-patron | Por que es malo |
|---|---|
Mergear auto/<issue> a master sin PR + humano |
Salta gate, riesgo de regresion |
Auto-aplicar proposal kind=refactor |
Cambios sistemicos requieren revision |
Modificar go.sum, package-lock.json, uv.lock |
Cambios de deps requieren CVE/license review |
| Bucle infinito sin watchdog | Coste descontrolado de tokens |
Borrar archivos sin backup en task_runs.events_json |
Pierde auditoria |
| Override de paths protegidos via env var | Bypass de seguridad |
Relacion con otras reglas
- e2e_validation — fn-analizador (fase 4) lee el contrato
e2e_checksque el orquestador usa como gate. - apps_tbd — el orquestador opera en rama
auto/*, no exenta de TBD. - feature_flags — si el fix no esta terminado, el orquestador puede meterlo detras de flag OFF antes de PR.
- registry_calls — toda invocacion del orquestador y sub-agentes pasa por MCP/
fn run/heredoc canonico, registrada en call_monitor.