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>
76 lines
5.3 KiB
Markdown
76 lines
5.3 KiB
Markdown
## 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
|
|
|
|
1. **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.
|
|
2. **Paths protegidos**: respetar `dev/autonomous_protected_paths.json` exactamente. Cualquier intento de modificar un path protegido aborta la iteracion y registra `task_runs.status='aborted_protected_path'`.
|
|
3. **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 (queda `pending` para humano).
|
|
- `priority in (low, medium)` -> auto-aplicable. `high|critical` -> requiere humano salvo override `--allow-high`.
|
|
4. **Watchdog**: si la metrica de progreso (`checks_pass / checks_total`) no sube en `N=3` iteraciones consecutivas -> abort. Registrar `task_runs.status='stalled'`.
|
|
5. **Tiempo**: cada `task_run` con timeout default 30 min. Override con `--timeout-min N` hasta max 4h.
|
|
6. **Idempotencia**: re-ejecutar `/autonomous-task <id>` sobre la misma issue reanuda desde la ultima iteracion exitosa, NO reinicia desde cero (lookup en `task_runs` por `issue_id`).
|
|
7. **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.
|
|
8. **No self-modification**: orquestador NUNCA modifica `.claude/agents/`, `.claude/commands/`, `.claude/rules/`, `.claude/scripts/`, `.claude/CLAUDE.md`. Reforzado en `autonomous_protected_paths.json`.
|
|
9. **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 --short` debe permanecer igual al baseline; cualquier diff = `status=sandbox_breach` -> ABORT.
|
|
10. **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-verify` para ESE commit con `task_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_checks` que 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.
|