---
id: "0120"
title: "fn-orquestador: piloto verde end-to-end sobre chart_demo"
status: pendiente
type: chore
domain:
  - meta
  - registry-quality
scope: agent
priority: alta
depends: []
blocks:
  - "0121"
  - "0122"
  - "0123"
related:
  - "0069"
  - "0068"
created: 2026-05-18
updated: 2026-05-18
tags: [orquestador, autonomous, e2e_checks, piloto]
---

# 0120 — Piloto verde de fn-orquestador

## Problema

`fn-orquestador` (issue 0069) tiene spec completa con 11 reglas duras, worktree aislado, paths protegidos y watchdog. Pero `task_runs` esta vacio: ningun piloto verde documentado. Memoria del "piloto 1" registra contaminacion del main repo (origen de las reglas 9/10/11). Sin un task_run con `status=done` y PR mergeado, el comando `/autonomous-task` es promesa, no herramienta. Las olas 0121-0123 dependen de que esto funcione.

## Decision

Ejecutar `/autonomous-task` sobre un target acotado y verificable: anadir bloque `e2e_checks` minimo al `app.md` de `chart_demo` y validar que `fn-analizador` corre la suite verde. Documentar el `task_run` entero (iteraciones, proposals, eventos) para auditar comportamiento real del orquestador.

### Target

`apps/chart_demo/` — app C++ ImGui pequeña, sin `e2e_checks` declarado, con `--self-test` ya implementado por el framework `fn::run_app`.

### Bloque `e2e_checks` esperado

```yaml
e2e_checks:
  - id: build
    cmd: "cmake --build cpp/build/windows --target chart_demo -j"
    timeout_s: 300
  - id: binary_exists
    cmd: "test -f cpp/build/windows/apps/chart_demo/chart_demo.exe"
    timeout_s: 5
```

(Inicialmente se planteo `--self-test` pero `fn::run_app` no parsea argv; el dry-run del orquestador 2026-05-18 lo detecto como R1 bloqueador. Sustituido por check estructural de binario construido. Implementar `--self-test` real es scope futuro fuera del piloto.)

## Tareas

1. Confirmar pre-condiciones del orquestador (migration 006, autonomous_protected_paths.json, gh auth, master limpio).
2. Lanzar `/autonomous-task 0120 --dry-run` para audit.
3. Lanzar `/autonomous-task 0120 --max-iterations 5 --max-minutes 30`.
4. Recoger output: `task_run_id`, branch `auto/0120-*`, log de iteraciones, proposals aplicadas/skipped, URL del PR draft.
5. Verificar `git -C /home/lucas/fn_registry status --short` igual a baseline (regla 11 sandbox breach).
6. Post-mortem: si fallo en alguna iteracion, anotar en seccion `## Hallazgos` y refinar `fn-orquestador/SKILL.md` o `autonomous_loop.md` si corresponde.

## Acceptance

- [ ] `sqlite3 apps/deploy_server/operations.db "SELECT id, task_id, status FROM task_runs WHERE task_id LIKE '0120%'"` devuelve >=1 fila con `status=converged` (schema real: `task_id`, no `issue_id`).
- [ ] `apps/chart_demo/app.md` contiene bloque `e2e_checks:` con al menos `build` + `binary_exists`.
- [ ] `fn-analizador` corrida sobre `chart_demo` reporta `checks_pass=checks_total` (todo verde).
- [ ] PR draft existe en Gitea con branch `auto/0120-*` apuntando a `master`.
- [ ] `git -C /home/lucas/fn_registry status --short` antes/despues del piloto identico (excluyendo solo este `.md` cerrado).
- [ ] Documento de post-mortem en `## Hallazgos` con: iteraciones totales, tiempo total, proposals creadas, decisiones del orquestador.

## DoD

User-facing surface:
- **Donde**: PR draft visible en Gitea `dataforge/fn_registry/pulls`.
- **Latencia**: <30 min total.
- **Como vuelve**: lectura del `task_run` via `mcp__registry__fn_doctor` o tab Monitor del registry_dashboard.
- **Onboarding (1 parrafo)**: "Para lanzar orquestador autonomo sobre un issue trivial, ejecuta `/autonomous-task <NNNN>`. Tras converger, abre PR draft. Si falla, lee `task_runs.events_json` para reconstruir las decisiones."

## Hallazgos

Ejecucion: 2026-05-18, `task_b3069559f34415c3`.

### Resultado

- status: **converged**
- iteraciones: 2/5 (CONSTRUIR + ANALIZAR, sin necesidad de MEJORAR)
- duracion: 2m 28s / 30min
- branch: `auto/0120-chart-demo-e2e` (en sub-repo `dataforge/chart_demo`, NO en `fn_registry`)
- PR draft: https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/chart_demo/pulls/1
- e2e_run: `e2e_61557e2ba1cc67ac` checks_pass=2 checks_total=2 (build 6742ms + binary_exists 1ms)
- sanity check regla 11: baseline `git status --short` identico a post-run (sin contaminacion del main repo)

### Hallazgos

1. **Arquitectura sub-repo**: para issues `add_e2e_check` que editan `app.md`, el orquestador opera DIRECTAMENTE en el sub-repo Gitea de la app target (`dataforge/chart_demo`), NO en el worktree del repo padre. Razon: `apps/*/` esta gitignored en `fn_registry` (regla `apps_subrepo`). El worktree padre se crea por protocolo pero queda sin uso. Implicacion: PR draft sale al sub-repo, no al repo padre — humano revisa+mergea en el sub-repo.

2. **R3 (Gitea API) confirmado**: orquestador usa `curl + pass gitea/dataforge-git-token` para crear PR. NO usa `gh pr create`. Documentar en `autonomous_loop.md` que la pre-condicion `gh auth status` es smoke check; mecanismo real es Gitea API.

3. **R4 (schema task_runs) confirmado**: campos reales `id, task_id, started_at, finished_at, status, iterations, last_phase, last_run_id, branch, worktree_path, pr_url, progress_json`. Status `converged` (no `done` como dice la spec antigua de `autonomous_loop.md`). Acceptance del issue debe usar `task_id LIKE '0120%'` y `status='converged'`.

4. **Convergencia rapida**: 2 iter sin MEJORAR. Check `binary_exists` paso porque `chart_demo.exe` ya existia en `cpp/build/windows/` (build incremental cmake reutiliza objetos). Para apps sin binario previo, se esperaria 1 iter extra de build real.

5. **Paths protegidos respetados**: ni `.claude/`, ni `dev/issues/`, ni `.env*` tocados durante la run. Regla 8 verde.

### Siguientes pasos

- [ ] Revisar PR `dataforge/chart_demo/pulls/1` (humano).
- [ ] Mergear PR a `master` del sub-repo cuando aprobado.
- [ ] Cerrar este issue: `mv dev/issues/0120-orquestador-piloto-verde.md dev/issues/completed/`.
- [ ] Lanzar `/autonomous-task 0121` (desbloqueado).
