Files
fn_registry/dev/issues/0068-e2e-validation-loop-fn4-fn5.md

201 lines
8.2 KiB
Markdown

---
id: "0068"
title: "Cerrar bucle reactivo — fn-analizador (fase 4) y fn-mejorador (fase 5) con contrato e2e_checks"
status: completado
type: feature
domain:
- meta
scope: multi-app
priority: alta
depends: []
blocks: []
related:
- "22"
- "23"
- "0028"
created: 2026-05-09
updated: 2026-05-17
tags: []
---
## Cierre 2026-05-14
Toda infra implementada y operativa:
- Migration `fn_operations/migrations/005_e2e_runs.sql` aplicada.
- Funcion `e2e_run_checks_go_infra` (Cmd/Health/Ref con expect_exit/stdout_contains, background via `&`). Tipos `E2ECheck_go_infra` + `CheckResult_go_infra`.
- Subagentes `fn-analizador` (Fase 4) y `fn-mejorador` (Fase 5) en `.claude/agents/`.
- `fn-recopilador` extendido con modo `design-e2e <app_id>`.
- Skill `/validate-app <app_id>` orquesta cadena completa.
- Regla `.claude/rules/e2e_validation.md` documenta contrato + patrones por stack.
- Pilotos: `apps/kanban/app.md` y `projects/osint_graph/apps/graph_explorer/app.md` declaran `e2e_checks`.
---
## Contexto
El bucle reactivo del registry (CONSTRUIR → EJECUTAR → RECOPILAR → ANALIZAR → MEJORAR) tiene agentes para fases 1-3:
- **Fase 1 — CONSTRUIR**: `fn-constructor` (existe)
- **Fase 2 — EJECUTAR**: `fn-executor` (existe)
- **Fase 3 — RECOPILAR**: `fn-recopilador` (existe)
- **Fase 4 — ANALIZAR**: falta agente
- **Fase 5 — MEJORAR**: falta agente
Sin fases 4 y 5 el bucle no cierra. Cada app sigue requiriendo iteracion manual: el humano lanza, mira, decide si funciona, y propone fixes. Objetivo: que apps lleguen a master correctas sin esa iteracion manual.
## Objetivo
Disponer de un gate automatico pre-merge que valide end-to-end cualquier app del registry, y un mejorador que proponga cambios cuando la validacion falla. Capacidad reutilizable, no especifica de un proyecto.
## Diseno
### Contrato `e2e_checks` en `app.md`
Cada app declara su validacion end-to-end en el frontmatter:
```yaml
e2e_checks:
- id: build
cmd: "cd frontend && pnpm build && cd .. && CGO_ENABLED=1 go build -tags fts5 -o kanban ."
timeout_s: 120
- id: smoke
cmd: "./kanban --port 8095 --db /tmp/kanban_e2e.db &"
health: "http://127.0.0.1:8095/api/board"
timeout_s: 10
- id: ops_audit
ref: "fn-recopilador:apps/kanban"
- id: migrations
cmd: "sqlite3 /tmp/kanban_e2e.db 'SELECT version FROM schema_migrations;'"
expect_exit: 0
```
Tipos de check:
- `cmd` — comando shell, exit 0 = OK.
- `health` — espera `cmd` en background, hace GET y verifica 200.
- `ref` — apunta a otro agente/funcion del registry (ej. `fn-recopilador`, `fn-doctor`).
- `expect_exit`, `expect_stdout_contains`, `expect_stdout_json` — predicados sobre la salida.
### fn-analizador (fase 4)
Subagente nuevo. Input: `app_id`. Pasos:
1. Lee `e2e_checks` del `app.md`.
2. Ejecuta cada check en orden, captura stdout/stderr/exit/duration.
3. Eval assertions activas via `fn ops assertion eval --react`.
4. Compara `executions.metrics` actual vs ventana historica (drift > umbral = warning).
5. Diff golden outputs si app declara `tests/golden/`.
6. Persiste resultado en nueva tabla `e2e_runs` de `operations.db`.
7. Devuelve veredicto caveman:
```
build ✓ 42s
smoke ✓ 0.8s
ops_audit ✓
assertion:R1 ✗ warning duration drift +47% vs p50
```
Tools: Read, Bash, Grep, Glob. Escribe SOLO `assertion_results`, `entity.status`, `e2e_runs`. NO toca registry.db.
### fn-mejorador (fase 5)
Subagente nuevo. Input: salida de `fn-analizador` + `app_id`. Pasos:
1. Filtra fallos: `critical` → `kind=bug`, `warning` → `kind=optimization`.
2. Por cada fallo, busca contexto en registry: funciones tocadas, ultimas N proposals.
3. Crea proposal con `created_by=reactive_loop`, `evidence=[assertion_id, execution_id, e2e_run_id]`.
4. Sugiere fix concreto (parametro, funcion a partir, refactor) — texto, NO codigo.
5. Si fallo recurrente (>3 veces misma assertion) → `priority=high`.
Tools: Read, Bash, Grep. Escribe SOLO `proposals` en registry.db. Nunca modifica funciones.
### Skill `/validate-app <app_id>`
Orquesta cadena: `fn-executor` → `fn-recopilador` → `fn-analizador` → `fn-mejorador`. Devuelve tabla pass/fail + IDs de proposals creadas.
### Migracion `006_e2e_runs.sql`
```sql
CREATE TABLE IF NOT EXISTS e2e_runs (
id TEXT PRIMARY KEY,
app_id TEXT NOT NULL,
started_at INTEGER NOT NULL,
finished_at INTEGER,
status TEXT NOT NULL, -- pass|fail|partial
checks_total INTEGER NOT NULL,
checks_pass INTEGER NOT NULL,
checks_fail INTEGER NOT NULL,
summary_json TEXT NOT NULL -- detalle por check
);
CREATE INDEX IF NOT EXISTS e2e_runs_app_idx ON e2e_runs(app_id, started_at DESC);
```
### Funciones nuevas del registry
Delegables a `fn-constructor`:
| ID | Domain | Que hace |
|---|---|---|
| `e2e_run_checks_go_infra` | infra | Ejecuta lista de checks, devuelve `[]CheckResult` |
| `golden_diff_go_core` | core | Compara archivo vs golden con umbral |
| `metrics_drift_go_datascience` | datascience | p50/p95 historico vs actual |
| `proposal_from_failure_go_infra` | infra | Formatea evidencia → proposal |
| `health_probe_go_infra` | infra | GET con timeout, retry, codigo esperado |
Tipos:
| ID | Que |
|---|---|
| `E2ECheck_go_infra` | struct check (id, cmd, ref, health, expect_*) |
| `CheckResult_go_infra` | struct resultado (id, status, duration_ms, stdout, stderr, exit) |
### fn-recopilador como diseñador de checks
`fn-recopilador` se extiende para **proponer e2e_checks por app** (modo design):
- Inspecciona `app.md` (lang, framework, entry_point, uses_functions).
- Detecta patrones conocidos:
- Go service con frontend Vite → propone build (pnpm + go), smoke (puerto + endpoint health).
- C++ ImGui app → propone build (cmake), smoke (`--self-test` o lanzar y matar tras N segundos).
- Python pipeline → propone run con args dummy y verificar exit 0.
- Audita `operations.db` y deriva `ops_audit` automatico.
- Escribe propuesta en `app.md` como bloque `e2e_checks_suggested:` para que humano apruebe → renombre a `e2e_checks:`.
Comando: `fn-recopilador design-e2e <app_id>`.
Asi `fn-analizador` recibe contratos completos de fabrica y solo necesita ejecutar.
## Plan de ejecucion
| Paso | Tarea | Estado |
|---|---|---|
| 1 | Contrato `e2e_checks` en `docs/templates/app.md` + 2 apps piloto (kanban, graph_explorer) | en curso |
| 2 | Funciones registry: `e2e_run_checks`, `golden_diff`, `metrics_drift`, `proposal_from_failure`, `health_probe` | pendiente |
| 3 | Migracion `006_e2e_runs.sql` en `fn_operations/migrations/` | pendiente |
| 4 | Subagente `fn-analizador` + skill `/validate-app` | pendiente |
| 5 | Extender `fn-recopilador` con modo `design-e2e` | pendiente |
| 6 | Subagente `fn-mejorador` | pendiente |
| 7 | Gate opcional en `/git-push` para apps con `e2e_checks` declarado | pendiente |
## Criterios de aceptacion
- [x] Template `docs/templates/app.md` con seccion `e2e_checks` documentada.
- [x] `apps/kanban/app.md` declara `e2e_checks` (build_frontend + build_backend + smoke + tests + ops_audit).
- [x] `projects/osint_graph/apps/graph_explorer/app.md` declara `e2e_checks` (build + self_test + pytest + enricher smoke).
- [x] `fn-recopilador` puede sugerir `e2e_checks` para una app dada (modo `design-e2e`).
- [x] `fn-analizador` corre los checks y devuelve veredicto caveman.
- [x] `fn-mejorador` crea proposals con evidencia cuando hay fallos.
- [x] Skill `/validate-app <app_id>` orquesta la cadena completa.
- [x] Documentacion en `.claude/rules/e2e_validation.md`.
## Riesgos
- **Golden tests para C++/UI son caros**. Empezar build+smoke+assertions; goldens solo donde aporten (graph_explorer ya tiene capture system).
- **Apps sin operations.db** (kanban usa `kanban.db` propia, no `operations.db`). El check `ops_audit` debe aceptar BD alternativa o saltarse.
- **Smoke tests con puertos en uso**. Los pilotos deben usar puertos efimeros (`--port 0` o range alto) y BDs en `/tmp/`.
- **Adopcion gradual**. Apps sin `e2e_checks` no se validan (y no bloquean merge). Visible en `fn doctor`.
## Out of scope
- Reemplazar `fn doctor` (que sigue siendo diagnostico read-only del estado).
- Tests unitarios de funciones (siguen en `*_test.go`, `pytest`, etc.).
- Performance benchmarks formales (los `metrics_drift` son aproximacion, no benchmark).