docs(flows): DoD obligatorio con user-facing surface + abrir issues 0100-0103 (taxonomia, frontmatter migration, dev_console, work dashboard)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,6 +68,33 @@ Probar end-to-end el stack: navegator AutoExtract -> recipe -> dag_engine schedu
|
||||
- `dag_engine.dag_step_results`: step `extract` con `function_id='cdp_extract_recipe_py_pipelines'`.
|
||||
- `call_monitor.calls`: chain function call.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: corre 3 veces consecutivas via cron sin intervencion.
|
||||
- [ ] **Observabilidad**: `call_monitor.calls` registra `cdp_extract_recipe_py_pipelines` + `data_factory.runs` muestra `node_id=hn_top_stories`.
|
||||
- [ ] **Error-path**: si Chrome :9222 cae, el step falla con mensaje claro (no crash silencioso del DAG).
|
||||
- [ ] **Idempotencia**: dedup `dedup_duckdb_table_by_hash_py_pipelines` corre tras extract; mismo HTML 2x = 0 filas nuevas.
|
||||
- [ ] **Secrets**: N/A (HN publico).
|
||||
- [ ] **Docs**: `## Notas` con comandos para reproducir + onboarding.
|
||||
- [ ] **Registry-first**: extract sin codigo inline en el DAG.
|
||||
- [ ] **INDEX + status**: `status: done` + `INDEX.md` + movido a `completed/`.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario abre `data_factory.exe` → tab "All Runs" filtra `node_id=hn_top_stories` → ve >=30 filas con rank/title/url/points.
|
||||
- [ ] **User-facing repeat**: vuelve manana al mismo tab, ve runs frescos (cada 30 min) y tabla actualizada.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para ver HN top: lanzar `data_factory.exe` → tab Extractors → `hn_top_stories`. DuckDB en `apps/data_factory/data/hn_top_stories.duckdb` tabla `hn_stories`."
|
||||
- [ ] **User-facing latencia**: cron `*/30 * * * *` → datos frescos en <31 min p95.
|
||||
|
||||
### Custom
|
||||
|
||||
- [ ] 7/7 campos cubiertos en TODOS los runs ultimas 24h (rank/title/url/points/author/age/comments).
|
||||
- [ ] Latencia extract <30s p95 (cdp_extract_recipe + render).
|
||||
|
||||
## Notas
|
||||
|
||||
(rellenas tras correr)
|
||||
|
||||
@@ -63,6 +63,33 @@ Probar path HTTP-only (sin Chrome/CDP). Extractor REST -> data_factory -> sink g
|
||||
- `data_factory.runs`: 24 entries/dia.
|
||||
- `data_factory.databases.last_seen_at` actualizado por sink.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: cron `0 * * * *` corre 3h consecutivas sin error.
|
||||
- [ ] **Observabilidad**: extractor en `call_monitor.calls`, runs en `data_factory.runs`, fila en `databases.last_seen_at`.
|
||||
- [ ] **Error-path**: AEMET 5xx → 3 reintentos exp-backoff, despues marca run failed (no crash).
|
||||
- [ ] **Idempotencia**: re-run mismo timestamp = upsert PostGIS, sin duplicar puntos.
|
||||
- [ ] **Secrets**: API key AEMET en `pass aemet/api-key`, nunca en el DAG.
|
||||
- [ ] **Docs**: `## Notas` con comandos + onboarding.
|
||||
- [ ] **Registry-first**: extractor AEMET creado como funcion del registry (`aemet_get_madrid_observations_py_*` o reuso de `http_get_json_*`), nada inline.
|
||||
- [ ] **INDEX + status**: `status: done` + INDEX + movido.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario abre `footprint_geo_stack` → preset `madrid-weather` → ve overlay tiles con puntos meteo + tooltip (temp/humidity).
|
||||
- [ ] **User-facing repeat**: mismo preset manana muestra datos refrescados; tooltip ultima hora.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para ver weather Madrid: `footprint_geo_stack.exe` → File → Open preset `madrid-weather`. Tile server local en :3000."
|
||||
- [ ] **User-facing latencia**: cron 1h → mapa refleja datos en <61 min.
|
||||
|
||||
### Custom
|
||||
|
||||
- [ ] PostGIS schema via `migrations/NNN_*.sql` (no `CREATE TABLE` inline).
|
||||
- [ ] Tile overlay sirve en <3s desde click.
|
||||
|
||||
## Notas
|
||||
|
||||
- Sin LLM/CDP. Mas barato que flow 0001.
|
||||
|
||||
@@ -61,6 +61,36 @@ Caso de uso REAL con auth + datos sensibles. Probar persistencia local (duckdb e
|
||||
- `data_factory.runs`: 1 entry status=success.
|
||||
- `auto_metabase`: 1 card creado.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing. **Risk=high** -> DoD strict obligatorio.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: re-login + extraccion mensual reproducible (no flaky por DOM changes inesperados).
|
||||
- [ ] **Observabilidad**: `call_monitor.calls` muestra ejecucion sin valores; `data_factory.runs` registra ambos nodos.
|
||||
- [ ] **Error-path**: sesion expirada → mensaje claro al usuario para re-login (no datos corruptos).
|
||||
- [ ] **Idempotencia**: re-extraer mismo mes = upsert por `movimiento_id`, 0 duplicados.
|
||||
- [ ] **Secrets**: credenciales BBVA solo en `pass bbva/login`; vault `~/vaults/finanzas/` gitignored verificado.
|
||||
- [ ] **Docs**: `## Notas` con onboarding + procedimiento de rotacion mensual.
|
||||
- [ ] **Registry-first**: recipe + persistencia duckdb usan funciones del registry.
|
||||
- [ ] **INDEX + status**: `status: done` + INDEX + movido.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario abre Metabase LOCAL :3000 → dashboard `Finanzas personales` → card `Gasto mensual` con grafico actualizado.
|
||||
- [ ] **User-facing repeat**: misma URL manana muestra movimientos del mes hasta hoy; despues de re-login mensual, mes nuevo aparece automatico.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para revisar gasto: abrir http://localhost:3000 (creds en `pass metabase/local`) → dashboard `Finanzas personales`. Re-login BBVA: lanzar navegator → recipe `bbva_movimientos` → click Run."
|
||||
- [ ] **User-facing latencia**: tras re-login + run manual, card actualizada en <2 min.
|
||||
|
||||
### Custom (risk=high)
|
||||
|
||||
- [ ] **No-leak**: `fn sync` NO sube duckdb (verificado: `pc_locations` registra path, sync no transmite bytes).
|
||||
- [ ] **No-leak**: recipe extrae solo campos minimos (fecha, concepto, importe, categoria); NO DNI, NO saldo, NO IBAN completo.
|
||||
- [ ] **No-leak**: Metabase corre LOCAL; verificar `auto_metabase.app.md` declara `tags: [local-only]`.
|
||||
- [ ] **Rotacion**: re-login mensual probado sin perder datos historicos.
|
||||
- [ ] **Red-team**: ningun log/screenshot/traza del flow contiene valores sensibles (grep IBAN/saldo en `call_monitor.calls`, `data_factory.runs`, `~/.cache/`).
|
||||
|
||||
## Notas
|
||||
|
||||
- **NO commitear** `~/vaults/finanzas/` (gitignored por defecto).
|
||||
|
||||
@@ -61,6 +61,34 @@ Probar webhooks como trigger (no cron, no manual). Cada push a un repo `dataforg
|
||||
- Por repo: 1 nodo extractor.
|
||||
- Matrix: 1 msg por push.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: 3 pushes test distintos disparan 3 mensajes Matrix sin intervencion.
|
||||
- [ ] **Observabilidad**: `data_factory.runs` con `trigger=webhook` + `call_monitor.calls` chain por push.
|
||||
- [ ] **Error-path**: payload invalido → 4xx + entry en log + NO crash receptor.
|
||||
- [ ] **Idempotencia**: recepcion duplicada (Gitea retry) → 1 mensaje, no N.
|
||||
- [ ] **Secrets**: webhook secret en `pass gitea/webhook-secret`; HMAC verificado por receptor.
|
||||
- [ ] **Docs**: `## Notas` con setup webhook + onboarding.
|
||||
- [ ] **Registry-first**: receptor reusa `http_post_json_*` + `matrix_send_message_*`.
|
||||
- [ ] **INDEX + status**: `status: done` + INDEX + movido.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario lee mensaje en sala Matrix `#fn-registry-news` con formato `[<repo>] <author> pushed <N> commits to <branch>` + link al commit.
|
||||
- [ ] **User-facing repeat**: cada push real a `dataforge/*` dispara mensaje; sala es la fuente diaria de actividad multi-repo.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para enterarse de pushes: unirse a sala Matrix `#fn-registry-news`. Para anadir un repo nuevo: `gitea_create_webhook_bash_infra <owner> <repo> <url> <secret>`."
|
||||
- [ ] **User-facing latencia**: push → mensaje en <5s p95.
|
||||
|
||||
### Custom
|
||||
|
||||
- [ ] >=3 repos cubiertos (no solo 1).
|
||||
- [ ] Rate-limit: max 1 mensaje/repo/minuto (no flood si N pushes seguidos).
|
||||
- [ ] Health endpoint `/webhook/health` retorna 200 + lista repos suscritos.
|
||||
|
||||
## Notas
|
||||
|
||||
- Webhook secret debe estar en `pass gitea/webhook-secret` o env var.
|
||||
|
||||
@@ -58,6 +58,35 @@ Probar paralelismo (multiples scraping jobs concurrentes) + agregacion a grafo.
|
||||
- `operations.db` de osint_graph: entities += N, relations += N.
|
||||
- `function_stats.claude_cli_prompt_py_infra`: calls += 1.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing. **Risk=medium** -> attention en datos personales.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: 3 lookups distintos (3 personas test) producen reports completos sin re-config.
|
||||
- [ ] **Observabilidad**: 3 jobs visibles en `odr_console.operations.db` + `call_monitor.calls` chain por job.
|
||||
- [ ] **Error-path**: si LinkedIn devuelve 429 → job marcado failed, otros 2 continuan (no aborta el flow entero).
|
||||
- [ ] **Idempotencia**: re-lookup misma persona → upsert por `snippet_hash`, no duplica nodos Person.
|
||||
- [ ] **Secrets**: creds Twitter/GitHub en `pass`; LinkedIn usa sesion del navegador (cookie via navegator).
|
||||
- [ ] **Docs**: `## Notas` con onboarding + check legal.
|
||||
- [ ] **Registry-first**: recipes + agregacion + render reusan funciones registry.
|
||||
- [ ] **INDEX + status**: `status: done` + INDEX + movido.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario abre `graph_explorer.exe` → File → Load dataset `osint/<persona>` → ve grafo Person + N Snippets navegable (zoom, click → snippet content).
|
||||
- [ ] **User-facing repeat**: persona nueva → comando lanza job, dataset aparece en lista de graph_explorer en <5min.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para investigar persona: `/flow run 0005 --target '<nombre>'` (o `odr_console.exe` → New Job → 3 recipes). Esperar ~5min. Abrir `graph_explorer.exe` → Load `osint/<nombre>`. Resumen LLM en `report.md` del repo."
|
||||
- [ ] **User-facing latencia**: job lanzado → grafo listo en <5min (3 jobs paralelos).
|
||||
|
||||
### Custom
|
||||
|
||||
- [ ] Paralelismo medido: 3 jobs concurrentes <60s wall vs ~180s en serie.
|
||||
- [ ] Race-condition test: 2 corridas simultaneas del flow no corrompen operations.db.
|
||||
- [ ] Red-team: nada de menores/info no publica en snippets capturados.
|
||||
- [ ] Report `.md` firmado por commit en repo `osint_graph`.
|
||||
|
||||
## Notas
|
||||
|
||||
- Consideracion legal: extracciones publicas (perfiles abiertos). NO bypassear paywalls/captchas.
|
||||
|
||||
@@ -72,6 +72,35 @@ Probar flujo INVERSO al tipico: extraer estado de un servicio interno (Metabase)
|
||||
- 1 run/dia en data_factory.
|
||||
- 7 commits en metabase_registry repo (1 semana baseline).
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: cron diario 02:00 corre 7 dias consecutivos sin error.
|
||||
- [ ] **Observabilidad**: `data_factory.runs` + 1 commit en repo `metabase_registry` por dia (o `NO_CHANGES`).
|
||||
- [ ] **Error-path**: token Metabase expirado → healthcheck pre-pull falla con mensaje claro, no silencio.
|
||||
- [ ] **Idempotencia**: NO_CHANGES no genera commit vacio en git.
|
||||
- [ ] **Secrets**: token Metabase en `pass metabase/api-token`.
|
||||
- [ ] **Docs**: `## Notas` con onboarding + rollback procedure.
|
||||
- [ ] **Registry-first**: pull/diff/push reusan funciones registry.
|
||||
- [ ] **INDEX + status**: `status: done` + INDEX + movido.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario navega a `https://gitea.../dataforge/metabase_registry/commits/master` → ve commits diarios con diff YAML de dashboards/cards.
|
||||
- [ ] **User-facing repeat**: misma URL manana muestra commit nuevo (o `NO_CHANGES` skip); rollback con click derecho en commit → restore.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para auditar cambios Metabase: abrir Gitea repo `dataforge/metabase_registry`. Rollback: revertir commit en Gitea → push trigger DAG manual → Metabase restaurado. Matrix bot diario en `#fn-registry-ops` a las 09:00."
|
||||
- [ ] **User-facing latencia**: cambio manual en Metabase → commit visible al dia siguiente 02:00.
|
||||
|
||||
### Custom
|
||||
|
||||
- [ ] Rollback E2E probado: revertir commit → siguiente run aplica YAML viejo → Metabase restaura dashboard.
|
||||
- [ ] Diff YAML estable: keys ordenadas, no churn aleatorio.
|
||||
- [ ] Dashboards eliminados → commit `DELETED:`, no tombstone huerfano.
|
||||
- [ ] Backup adicional a vault (no solo git).
|
||||
|
||||
## Notas
|
||||
|
||||
- Riesgo: si Metabase token expira, el DAG falla silenciosamente. Anadir healthcheck pre-pull.
|
||||
|
||||
@@ -71,6 +71,34 @@ Tres triggers distintos, mismo sink.
|
||||
- `function_stats.matrix_send_message_*`: calls dependientes de eventos reales.
|
||||
- Sala Matrix recibe mensajes de los 3 origenes.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Ver `README.md` seccion DoD + user-facing.
|
||||
|
||||
### Generico
|
||||
|
||||
- [ ] **Repetibilidad**: 3 triggers (node fail / DAG fail / violations) disparan mensaje cada uno, 100x sin perdida.
|
||||
- [ ] **Observabilidad**: cada envio en `call_monitor.calls`; cola persistente registra envios pendientes si Matrix down.
|
||||
- [ ] **Error-path**: Matrix down → cola en operations.db; al reconectar drena en orden.
|
||||
- [ ] **Idempotencia**: dedup: misma alerta 10x en 1min → 1 mensaje agregado, no flood.
|
||||
- [ ] **Secrets**: bot token en `pass matrix/bot-token`.
|
||||
- [ ] **Docs**: `## Notas` con onboarding + comandos para provocar trigger de prueba.
|
||||
- [ ] **Registry-first**: `matrix_send_message_py_infra` registrado + reusado.
|
||||
- [ ] **INDEX + status**: `status: done` + INDEX + movido.
|
||||
|
||||
### User-facing
|
||||
|
||||
- [ ] **User-facing**: usuario lee alerta en sala Matrix `#fn-registry-ops` con prefix emoji severidad + nombre app + link al dashboard de la app fallida.
|
||||
- [ ] **User-facing repeat**: cada fallo real dispara mensaje en la sala; sala es el feed de salud diario del stack.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas`: "Para enterarse de fallos: unirse a `#fn-registry-ops` (creds Matrix en `pass matrix/user`). Heartbeat 09:00 confirma bot vivo. Probar trigger: `./fn run inject_synthetic_violation`."
|
||||
- [ ] **User-facing latencia**: evento → mensaje en <3s p95 (medido sobre 100 envios).
|
||||
|
||||
### Custom
|
||||
|
||||
- [ ] Severity routing: `critical` → `#fn-registry-ops`; `warning` → `#fn-registry-dev`.
|
||||
- [ ] Self-test diario 09:00: bot envia heartbeat si vivo; ausencia heartbeat = alerta meta.
|
||||
- [ ] Mensaje formateado con link al dashboard (no solo texto plano).
|
||||
|
||||
## Notas
|
||||
|
||||
- Throttling: max 1 mensaje/minuto por origen para evitar spam.
|
||||
|
||||
@@ -21,6 +21,13 @@ Al recibir "crea flow para <X>" o `/flow create <slug>`:
|
||||
4. **Marca riesgo** (low/medium/high) por sensibilidad de datos.
|
||||
5. **Sugiere schedule** (cron / webhook / manual) basado en el tipo de fuente.
|
||||
6. **Sugiere apps** del stack que encajan, sin inflar — solo las que realmente tocara.
|
||||
7. **REDACTA `## Definition of Done` OBLIGATORIO**. No scaffold sin DoD. Empieza por la plantilla minima del `README.md` y anade DoD especificos al dominio del flow (ej. "datos NO viajan a registry.organic-machine", "geo: tiles sirven en <3s", "matrix bot tarda <5s en mensaje"). Acceptance != DoD: Acceptance = "corre"; DoD = "esta listo para vivir solo".
|
||||
8. **DECLARA USER-FACING SURFACE**. Dentro del DoD, los 4 checks `User-facing` son OBLIGATORIOS y concretos. Responde antes de scaffold:
|
||||
- **donde** lo ve el humano? (app concreta + tab/panel, sala Matrix, dashboard URL, Metabase card, repo Gitea con commits, archivo en vault). NUNCA "en la BD" o "en un log".
|
||||
- **cuanto tarda** en aparecer? (declara latencia en segundos/minutos).
|
||||
- **como vuelve** a verlo manana? (URL bookmark? slash command? cron + dashboard?).
|
||||
- **que parrafo onboarding** ira en `## Notas` para que un humano nuevo lo use sin leer el flow.
|
||||
Si la unica respuesta es "lo consume otro flow/app", devuelve el flow a borrador — falta superficie humana.
|
||||
|
||||
## Mapa de discovery — donde mirar para cada decision
|
||||
|
||||
|
||||
+11
-9
@@ -2,20 +2,22 @@
|
||||
|
||||
Tabla de casos de uso multi-app. Mantenida por `/flow create` y `/flow done`.
|
||||
|
||||
| ID | Slug | Apps | Status | Risk | Updated |
|
||||
|----|------|------|--------|------|---------|
|
||||
| [0001](0001-hn-top-stories.md) | hn-top-stories | navegator_dashboard, dag_engine, data_factory, agents_and_robots | pending | low | 2026-05-16 |
|
||||
| [0002](0002-aemet-madrid.md) | aemet-madrid | dag_engine, data_factory, footprint_geo_stack | pending | low | 2026-05-16 |
|
||||
| [0003](0003-bbva-movimientos.md) | bbva-movimientos | navegator_dashboard, dag_engine, data_factory, auto_metabase | pending | high | 2026-05-16 |
|
||||
| [0004](0004-gitea-releases-monitor.md) | gitea-releases-monitor | registry_api, data_factory, agents_and_robots | pending | low | 2026-05-16 |
|
||||
| [0005](0005-osint-person-lookup.md) | osint-person-lookup | navegator_dashboard, odr_console, graph_explorer | pending | medium | 2026-05-16 |
|
||||
| [0006](0006-metabase-versioning.md) | metabase-versioning | auto_metabase, dag_engine | pending | medium | 2026-05-16 |
|
||||
| [0007](0007-matrix-telemetry-bot.md) | matrix-telemetry-bot | data_factory, dag_engine, call_monitor, agents_and_robots | pending | low | 2026-05-16 |
|
||||
| ID | Slug | Pattern | Apps | Status | Risk | DoD % | Updated |
|
||||
|----|------|---------|------|--------|------|-------|---------|
|
||||
| [0001](0001-hn-top-stories.md) | hn-top-stories | smoke-cron | navegator_dashboard, dag_engine, data_factory, agents_and_robots | pending | low | 0% | 2026-05-16 |
|
||||
| [0002](0002-aemet-madrid.md) | aemet-madrid | smoke-cron | dag_engine, data_factory, footprint_geo_stack | pending | low | 0% | 2026-05-16 |
|
||||
| [0003](0003-bbva-movimientos.md) | bbva-movimientos | prod-data | navegator_dashboard, dag_engine, data_factory, auto_metabase | pending | high | 0% | 2026-05-16 |
|
||||
| [0004](0004-gitea-releases-monitor.md) | gitea-releases-monitor | event-driven | registry_api, data_factory, agents_and_robots | pending | low | 0% | 2026-05-16 |
|
||||
| [0005](0005-osint-person-lookup.md) | osint-person-lookup | manual-deep | navegator_dashboard, odr_console, graph_explorer | pending | medium | 0% | 2026-05-16 |
|
||||
| [0006](0006-metabase-versioning.md) | metabase-versioning | gitops | auto_metabase, dag_engine | pending | medium | 0% | 2026-05-16 |
|
||||
| [0007](0007-matrix-telemetry-bot.md) | matrix-telemetry-bot | event-driven | data_factory, dag_engine, call_monitor, agents_and_robots | pending | low | 0% | 2026-05-16 |
|
||||
|
||||
## Leyenda
|
||||
|
||||
- **Status**: `pending` (no arrancado) / `running` / `done` / `failed` / `deferred`.
|
||||
- **Risk**: `low` (datos publicos), `medium` (auth pero no sensible), `high` (datos personales/financieros).
|
||||
- **Pattern**: `smoke-cron` / `prod-data` / `event-driven` / `manual-deep` / `gitops` / `realtime-loop` — ver `README.md`.
|
||||
- **DoD %**: ratio de checks `[x]` en el bloque `## Definition of Done` del flow. `/flow done` exige 100%.
|
||||
|
||||
## Completados
|
||||
|
||||
|
||||
@@ -9,8 +9,53 @@ Un flow describe una secuencia de pasos que atraviesa varias apps (`navegator_da
|
||||
- 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.
|
||||
|
||||
## Para agentes / LLMs
|
||||
|
||||
Antes de crear o editar un flow, lee `AGENT_GUIDE.md`. Define:
|
||||
|
||||
@@ -71,6 +71,30 @@ Pasos numerados. Cada paso puede ser:
|
||||
- [ ] Criterio 1.
|
||||
- [ ] Criterio 2.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Contrato global de cierre. TODOS marcados antes de mover a `completed/`. Ver README.md seccion "Definition of Done".
|
||||
|
||||
- [ ] **Repetibilidad**: corre 3 veces consecutivas sin intervencion manual.
|
||||
- [ ] **Observabilidad**: trazado en `call_monitor.calls` + `data_factory.runs` + dashboard relevante.
|
||||
- [ ] **Error-path**: >=1 modo de fallo probado y manejado.
|
||||
- [ ] **Idempotencia**: re-ejecucion no duplica ni corrompe sinks.
|
||||
- [ ] **Secrets**: cero credenciales fuera de `pass`/vaults; risk declarado coincide con datos reales.
|
||||
- [ ] **Docs**: `## Notas` con hallazgos + comandos reproducibles.
|
||||
- [ ] **Registry-first**: piezas reutilizables viven como funciones del registry.
|
||||
- [ ] **INDEX + status**: `status: done` + `INDEX.md` actualizado + movido a `completed/`.
|
||||
|
||||
### User-facing (obligatorio)
|
||||
|
||||
- [ ] **User-facing**: <accion concreta del humano + lugar exacto donde ve/usa el output>.
|
||||
- [ ] **User-facing repeat**: humano vuelve manana al mismo lugar, ve datos frescos sin conocer el flow.
|
||||
- [ ] **User-facing onboarding**: parrafo en `## Notas` explica "para ver/usar esto: hacer X" sin leer el flow.
|
||||
- [ ] **User-facing latencia**: humano percibe el cambio en <Xs|Xmin> tras el evento (X declarado).
|
||||
|
||||
### Custom (opcional, dominio-especifico)
|
||||
|
||||
- [ ] _(custom)_ <DoD especifica al dominio si aplica>.
|
||||
|
||||
## Telemetria esperada
|
||||
|
||||
- `call_monitor.calls`: que aparece.
|
||||
|
||||
Reference in New Issue
Block a user