# 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 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)

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.

**Diferencia:**

| `## Acceptance` | `## Definition of Done` |
|---|---|
| Checks task-level del flow (ejecucion concreta) | Contrato global de calidad para considerar el flow CERRADO |
| Pueden quedar `[ ]` mientras iteras | TODOS deben estar `[x]` antes de mover a `completed/` |
| Verifica que el flow CORRE | Verifica que el flow es REPETIBLE, OBSERVABLE y MANTENIBLE |

**Plantilla minima de DoD** (anadir/ajustar segun flow):

```markdown
## Definition of Done

- [ ] **Repetibilidad**: el flow corre N veces consecutivas (N declarado en el flow, default 3) sin intervencion manual.
- [ ] **Observabilidad**: queda trazado en `call_monitor.calls` + `data_factory.runs` + dashboard correspondiente.
- [ ] **Error-path**: al menos 1 modo de fallo probado y manejado (no crash silencioso).
- [ ] **Idempotencia**: re-ejecutar no duplica datos ni rompe estado (clave en sinks).
- [ ] **Secrets**: cero credenciales en disco fuera de `pass`/vaults; cero datos sensibles fuera de `risk` declarado.
- [ ] **Docs**: `## Notas` rellenado con hallazgos reales + comandos para reproducir.
- [ ] **Registry-first**: todas las piezas reutilizables existen como funciones del registry (no inline en apps).
- [ ] **INDEX + status**: `status: done` en frontmatter + fila actualizada en `INDEX.md` + archivo movido a `completed/`.
```

Cada flow puede anadir DoD especificos al dominio (ej. `bbva-movimientos`: "datos NUNCA cruzan a registry.organic-machine"). El bloque DoD se **versiona con el flow** — un cambio de DoD requiere bump de `updated:` en frontmatter.

### User-facing surface (sub-bloque OBLIGATORIO dentro de DoD)

"DoD verde" sin valor visible al humano = plumbing limpio sin razon de existir. Cada DoD DEBE incluir, al menos, estos cuatro checks tipo `User-facing`:

```markdown
- [ ] **User-facing**: <accion concreta del humano + lugar exacto donde ve/usa el output>.
- [ ] **User-facing repeat**: el humano vuelve manana al mismo lugar y ve datos frescos sin conocer el flow.
- [ ] **User-facing onboarding**: parrafo en `## Notas` que explica "para ver/usar esto: hacer X" — sin leer el flow.
- [ ] **User-facing latencia**: el humano percibe el cambio en <X segundos|minutos> tras el evento (X declarado por flow).
```

Regla: 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 una 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 es quien debe declarar su propia user-facing surface.

`/flow done` rechaza el cierre si falta alguno de los 4 user-facing checks o si `## Notas` no contiene parrafo onboarding.

### 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 <path> contiene linea con texto Z" |
| `url` | "GET <url> 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

```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: <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.
