# Flows Casos de uso end-to-end **reutilizables** que prueban el sistema multi-app del registry. Un flow describe una secuencia de pasos que atraviesa varias apps (`navegator_dashboard`, `dag_engine`, `data_factory`, `agents_and_robots`, ...) para producir valor real (extraer datos, sincronizar, notificar). ## Convencion - Archivo por flow: `NNNN-.md` (numeracion zero-padded propia, NO comparte con `dev/issues/`). - Estado vivo en frontmatter (`status`). - Acceptance checkboxes `[ ]` en el body — `/flow status` calcula % completado. - **Definition of Done OBLIGATORIA** — ver seccion abajo. Sin DoD el flow NO puede crearse. - Cerrados se mueven a `completed/`. ## Definition of Done (OBLIGATORIA — triada) Cada flow al crearse DEBE declarar un bloque `## Definition of Done` distinto de `## Acceptance`. Sin el, `/flow create` rechaza el scaffold y `/flow done` rechaza el cierre. **Regla absoluta**: DoD no es checkbox que se marca a mano. Cada item lleva **evidencia ejecutable** (comando, e2e_check, dashboard URL con datos frescos, log query, screenshot link). Si no puedes probarlo, no es DoD: es deseo. Ver `.claude/rules/dod_quality.md` para la regla completa. **Diferencia con `## Acceptance`:** | `## Acceptance` | `## Definition of Done` | |---|---| | Checks task-level del flow (el flow corre una vez) | Contrato global de calidad: el flow sobrevive uso real | | Pueden quedar `[ ]` mientras iteras | TODAS las capas verdes con evidencia antes de mover a `completed/` | | Verifica que el flow CORRE | Verifica que el flow es REPETIBLE, OBSERVABLE, MANTENIBLE y USADO | ### Las 3 capas obligatorias **1. Mecanica** (pre-requisito, NO es DoD por si misma): Build verde, tests verdes, `fn index` limpio, `fn doctor` verde, `uses_functions` sin drift. Hacer compilar la cosa NO es haberla terminado. **2. Cobertura de comportamiento**: Tabla `escenario | tipo | comando | resultado esperado`. Minimo 1 golden + 2 edge + 1 error path con assert real, no smoke "no peto". Cuando aplique, las pruebas dejan entry en `e2e_runs` de la app afectada. **3. Vida util validada**: Tabla `metrica | umbral | dashboard | ventana`. El flow sobrevive **>=7 dias de uso real** sin romperse silenciosamente. Crashes = 0, huecos en audit chains = 0, error_rate < umbral declarado, dashboard observable abierto periodicamente. **El humano usa la cosa en su PC, en su contexto real, >=N veces variadas, no en sandbox aislado**. ### Plantilla obligatoria Ver `template.md` para el esqueleto completo. Bloques: ```markdown ## Definition of Done ### Mecanica - [ ] Build verde (`cmd: ...`) - [ ] Tests verdes (`cmd: ...`) - [ ] fn index limpio - [ ] fn doctor verde - [ ] uses_functions auditado ### Cobertura de comportamiento | Escenario | Tipo | Comando | Resultado esperado | |---|---|---|---| | Golden: ... | unit/e2e | `cmd` | output concreto | | Edge 1: ... | unit/e2e | `cmd` | comportamiento concreto | | Error 1: ... | e2e | `cmd que rompe` | fallo manejado, no crash | | Error 2: ... | e2e | `cmd` | degradacion graceful + log | ### Vida util validada | Metrica | Umbral | Donde se observa | Ventana | |---|---|---|---| | | `>=N` | `` | 7 dias | | crashes | `0` | `journalctl ...` | 7 dias | ### User-facing (reforzado) - [ ] User-facing surface (lugar concreto, NO BD ni log). - [ ] User-facing usage real: >=N veces en >=7 dias, en PC real, con inputs reales. - [ ] User-facing variado: >=3 capabilities/casos distintos. - [ ] User-facing onboarding (parrafo en `## Notas`). - [ ] User-facing latencia 30 dias) - [ ] self-test sin asserts - [ ] silent-fail - [ ] approval saltado ``` ### Reglas duras para marcar `status: done` `/flow done` rechaza el cierre si: 1. Falta alguna de las 3 capas (mecanica + cobertura + vida). 2. En Cobertura: <1 golden, <2 edge, <1 error path con evidencia. 3. En Vida util: tabla vacia o sin dashboard observable real. 4. User-facing usage real <7 dias o NO vale. Tiene que ser una superficie usada por el humano (UI de app, sala Matrix, dashboard, Metabase card, repo Gitea, archivo en vault abierto a mano). Si el output solo lo consume otra app/flow, esa app/flow declara su propia user-facing surface. ### Antipatrones documentados | Antipatron | Por que es malo | |---|---| | Marcar `done` porque pasa una vez | Tarea "hecha" se rompe al primer uso real | | Checkbox sin evidencia ejecutable | DoD se convierte en placebo, no en gate | | Test que solo verifica camino feliz | El error path es donde se pierden datos en produccion | | Observabilidad declarada pero dashboard no abierto en 30 dias | Telemetria muerta = ceguera | | "Repetible 3 veces consecutivas" con BD efimera | No prueba comportamiento sobre datos reales acumulados | | Aprobacion saltada en algun camino | Security gate roto pero invisible | | Error path manejado solo "en teoria" | Cuando ocurra en produccion el manejo no existe | ### Validacion programatica de DoD (TBD) `/flow done` ejecuta checks programaticos: - Parsea bloques `### Mecanica`, `### Cobertura`, `### Vida util`, `### User-facing`, `### Anti-criterios`. - Verifica que cada item tiene `cmd:` / URL / log query / e2e_check_id asociado. - Cuenta filas en Cobertura: >=1 golden + >=2 edge + >=1 error. - Cruza con `e2e_runs` y `call_monitor.calls` para confirmar evidencias en BDs reales. - Aborta cierre si falta cobertura o algun anti-criterio esta marcado. Hoy parte de esto es manual (revision humana). Ver `audit_dod_schema_go_infra` (issue 0114) + `fn doctor dod`. ### DoD evidence schema (issue 0114, opcional) Ademas de los checkboxes humanos del bloque `## Definition of Done`, cada flow puede declarar en su frontmatter un bloque `dod_evidence_schema:` con la version maquinable de la DoD: lista de evidencias con id unico, `kind` cerrado, `expected` libre y `required` bool. Auditable con `fn doctor dod`. ```yaml dod_evidence_schema: - id: surface_dashboard kind: url expected: "https://metabase.organic-machine.com/dashboard/12 muestra ultimo refresh hoy" required: true - id: matrix_room_msg kind: screenshot expected: "sala matrix #flows recibe mensaje con resumen del run" required: true - id: data_factory_run kind: cmd expected: "sqlite3 data_factory.db 'SELECT count(*) FROM runs WHERE flow=NNNN' > 0" required: true - id: error_path_log kind: log expected: "fallar collector intencional deja entry status=error sin crash" required: false ``` Reglas: - `kind` ∈ {`screenshot`, `log`, `url`, `cmd`}. - `id` unico por flow. - `expected` no vacio. - `required` default `true`. Ejemplos por kind: | kind | que pones en `expected` | |---|---| | `screenshot` | "frame de la app/sala mostrando estado Y" | | `log` | "fichero contiene linea con texto Z" | | `url` | "GET devuelve 200 con campo W" o "dashboard tal carga ultima fila < 24h" | | `cmd` | comando shell con exit 0 (incluido SQL via sqlite3) | Plantilla canonica: `docs/templates/flow.md`. Validador: `fn doctor dod` + `audit_dod_schema_go_infra`. ## Para agentes / LLMs Antes de crear o editar un flow, lee `AGENT_GUIDE.md`. Define: - donde buscar funciones (capability groups, MCP search por tag, etc.), - mapa actual de apps / projects / vaults disponibles, - reglas duras para recomendar piezas reales del registry, - plantilla de prompt para el agente cuando recibe `/flow create`. Cada flow debe citar IDs reales del registry. Si una pieza no existe, marcarla `FALTA: crear ` — NUNCA inventar nombres. ## Slash command `/flow` | Subcomando | Que hace | |---|---| | `/flow create ` | Scaffold `NNNN-.md` desde `template.md` con siguiente ID libre. | | `/flow list` | Tabla resumen desde `INDEX.md` + checkbox %. | | `/flow show ` | Imprime el `.md`. | | `/flow status ` | Status + acceptance % + ultima run. | | `/flow done [--notes "..."]` | Marca status=done, anade notas, mueve a `completed/`, actualiza INDEX. | | `/flow run ` | **Fase 2** (no implementado). Ejecuta steps automatizables. | ## Estructura archivo ```yaml --- name: hn-top-stories id: 0001 status: pending # pending | running | done | failed | deferred created: 2026-05-16 updated: 2026-05-16 priority: high # low | medium | high risk: low # low | medium | high (sensibilidad de datos) related_issues: [0097, 0098] apps: [navegator_dashboard, dag_engine, data_factory, agents_and_robots] trigger: manual # manual | cron | webhook schedule: "" expected_runtime_s: 60 tags: [scraping, news] --- ## Goal Una frase: que estamos probando. ## Pre-requisitos - Lista de requisitos manuales (ej. Chrome con remote-debugging). ## Flow Pasos numerados. Cada paso puede ser: - texto libre (manual) - `function: ` (registry function) - `cmd: ` - `js: ` (en tab Chrome) ## Acceptance - [ ] Checklist - [ ] ... ## Telemetria esperada Que cambia en call_monitor / data_factory.runs / dag_engine. ## Notas Hallazgos tras correr. ``` ## Numeracion + status workflow ``` pending --create--> in-progress --run OK--> done --move--> completed/ | ^ v | failed -----------fix-----+ ``` `deferred` para flows fuera de scope actual pero que conservas. ## Trazabilidad Cada `function: X` invocado dentro de un flow pasa por hook PostToolUse -> queda en `call_monitor.calls`. Si la funcion graba en `data_factory.runs` (ej. `cdp_extract_recipe_py_pipelines`), tienes cadena: ``` flow 0001 -> /flow run -> ./fn run cdp_extract_recipe -> call_monitor.calls \-> data_factory.runs ``` Asi la observabilidad cross-app es gratis. ## Cuando crear flow vs issue | Caso | Donde | |---|---| | Bug del registry / funcion | `dev/issues/NNNN-...` | | Feature de una app | `dev/issues/NNNN-...` | | Caso de uso real que cruza N apps | **`dev/flows/NNNN-...`** | | Trabajo recurrente reutilizable | **`dev/flows/NNNN-...`** | | Refactor de codigo | `dev/issues/NNNN-...` | Un flow puede generar issues secundarios si descubres bugs corriendo el flow.