feat(episode): TRAZA_la-orquestacin-funcion-bloque-un-fix-que_S20260618.R8_XX.ops.2.hot_inf.in.cc.es.000.MGQ_J.PMCFK_E.SGNFD

Skill: NONE | Type: troubleshooting
Summary: EPISODIO 8 — MNEMO Pipeline: La orquestación funcionó: bloqueó un fix que se veí
This commit is contained in:
Ember 2026-06-19 00:01:21 +00:00
parent 7686964753
commit 4a2b9961f8

View file

@ -0,0 +1,49 @@
---
episode_id: "730c1edc-404d-409c-ace5-e1d36355f1d8"
puente_flat: "TRAZA_la-orquestacin-funcion-bloque-un-fix-que_S20260618.R8_XX.ops.2.hot_inf.in.cc.es.000.MGQ_J.PMCFK_E.SGNFD"
session_code: "S20260618.VERIFY_FIRST_PASSPORT_FIX"
acto_dialogico: "informar"
actor_flujo: "multi_actor"
criticidad_aegis: "low"
skill_dominante: "NONE"
fase_proyecto: "operations"
tipo_semantico: "troubleshooting"
summary_one_line: "EPISODIO 8 — MNEMO Pipeline: La orquestación funcionó: bloqueó un fix que se veía bien pe"
source_type: "claude_code"
trust_boundary: "internal"
created_at: "2026-06-19T00:01:04.599728+00:00"
relectura_tagged: false
forgejo_commit_sha: "pending"
---
Verificación cerrada — y resuelve el último bloqueante limpiamente. Tengo el cuadro **completo y verificado**, John.
## La orquestación funcionó: bloqueó un fix que se veía bien pero estaba incompleto
El `code-validator` dio **BLOCKED** por una razón real que yo había pasado por alto: el patch de 4 líneas arregla los episodios FUTUROS, pero las **165 atascadas NO se drenan solas** — el claim filter (`outbox_worker_base.py:179`) solo reclama filas con algún store en `pending/failed`, y esas 165 ya tienen nextcloud+forgejo en `success`, así que ningún worker las vuelve a tocar. Mi "auto-completan en el próximo poll" era **falso**. *Esto es exactamente el valor de orquestar que me señalaste — la cadena cazó lo que yo no vi.*
## Cerré el último unknown (BLOQUEANTE-3) en vivo
- **Productor confirmado:** el trigger `trg_episode_after_write_outbox` → `fn_episode_after_write_outbox_v2()` crea **ambas** filas (`episode_outbox` + `episode_sync_status`) en el mismo trigger, con `NEW.puente_flat` como clave. → el join `o.puente=s.puente` es **sano por construcción**, sin huérfanas.
- **Drenado verificado:** `outbox_partial=171 · with_sync=171 · drainable=171`. **Los 171 son alcanzables** por el backfill terminal (todos con nextcloud+forgejo en success).
## El paquete corregido y verificado (deploy Opción Y)
| Pieza | Estado |
|---|---|
| **Patch** `_maybe_complete_outbox` → `SELECT nextcloud_state, forgejo_state` (4 líneas) | ✅ validador re-corrió pytest + leyó la función: lógica correcta, RELOJ-AP limpio |
| **Backfill terminal** (lo que faltaba) — drena los 171 YA | ✅ verificado seguro (171/171 drainable, join sano) |
| **Deploy-ordering** | ✅ sin ventana de pérdida (Qdrant/Neo4j siempre inline por crisol) |
| Tests tautológicos (stub) | ⚠️ a rehacer para el registro, pero el validador ya confirmó la lógica empíricamente |
**Backfill terminal (la pieza que la cadena exigió):**
**Runbook de deploy (Opción Y, NO toca crisol ni el unit file):**
1. Backup `outbox_worker_base.py` en servidor → `~/backups/`
2. `sftp_upload` del archivo parcheado (copia local ya tiene el patch)
3. Correr el backfill terminal (drena los 171)
4. `systemctl --user restart ember-outbox`
5. Smoke: `SELECT status,count(*) FROM episode_outbox GROUP BY status` → esperar `partial=0`
6. Rollback listo: restaurar `.bak` + restart
**Opción X (sprint siguiente):** crisol marca qdrant/neo4j en el ledger + podar `neo4j` del `--only` → mata el doble-write + ledger 5-store honesto (el backfill X condicionado a `qdrant_status=='OK'`, no a `created_at` — otra cosa que la cadena corrigió).