Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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-<slug>.md(numeracion zero-padded propia, NO comparte condev/issues/). - Estado vivo en frontmatter (
status). - Acceptance checkboxes
[ ]en el body —/flow statuscalcula % 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:
## 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 |
|---|---|---|---|
| <metrica> | `>=N` | `<dashboard URL>` | 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 <X medida.
### Anti-criterios (invalidan DoD aunque checkboxes verdes)
- [ ] solo-en-mi-PC
- [ ] solo-en-sandbox-vacio
- [ ] camino feliz unico (error paths declarados pero nunca ejercitados)
- [ ] dashboard fantasma (no abierto en >30 dias)
- [ ] self-test sin asserts
- [ ] silent-fail
- [ ] approval saltado
Reglas duras para marcar status: done
/flow done rechaza el cierre si:
- Falta alguna de las 3 capas (mecanica + cobertura + vida).
- En Cobertura: <1 golden, <2 edge, <1 error path con evidencia.
- En Vida util: tabla vacia o sin dashboard observable real.
- User-facing usage real <7 dias o <N usos declarados.
- Cualquier anti-criterio marcado como cierto.
## Notassin parrafo onboarding.- Algun item sin comando/URL/log query — solo texto.
Cada flow puede anadir DoD especificos al dominio. El bloque DoD se versiona con el flow — un cambio de DoD requiere bump de updated: en frontmatter.
User-facing surface (regla complementaria)
Si la respuesta a "donde lo ves" es "en una BD" o "en un log" -> 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_runsycall_monitor.callspara 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.
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}.idunico por flow.expectedno vacio.requireddefaulttrue.
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 <id> — NUNCA inventar nombres.
Slash command /flow
| Subcomando | Que hace |
|---|---|
/flow create <slug> |
Scaffold NNNN-<slug>.md desde template.md con siguiente ID libre. |
/flow list |
Tabla resumen desde INDEX.md + checkbox %. |
/flow show <NNNN> |
Imprime el .md. |
/flow status <NNNN> |
Status + acceptance % + ultima run. |
/flow done <NNNN> [--notes "..."] |
Marca status=done, anade notas, mueve a completed/, actualiza INDEX. |
/flow run <NNNN> |
Fase 2 (no implementado). Ejecuta steps automatizables. |
Estructura archivo
---
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: <id>` (registry function)
- `cmd: <bash>`
- `js: <expression>` (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.