feat(episode): TRAZA_fix-over-count-en-migration-manifestpy_S20260518.R4_XX.ops.2.hot_inf.in.cc.es.000.MGQ_J.PMCFK_E.SGNFD

Skill: NONE | Type: chronicle
Summary: EPISODIO 4 — BLINDADAS: Fix: over-count en `migration-manifest.py`
This commit is contained in:
Ember 2026-05-19 03:20:20 +00:00
parent fd6ae0f1e1
commit de507b5339

View file

@ -0,0 +1,50 @@
---
episode_id: "7287b0bf-3a1e-459e-8fe1-fc28bfeba306"
puente_flat: "TRAZA_fix-over-count-en-migration-manifestpy_S20260518.R4_XX.ops.2.hot_inf.in.cc.es.000.MGQ_J.PMCFK_E.SGNFD"
session_code: "S20260518.PIPELINE_FIXES"
acto_dialogico: "informar"
actor_flujo: "multi_actor"
criticidad_aegis: "low"
skill_dominante: "NONE"
fase_proyecto: "operations"
tipo_semantico: "chronicle"
summary_one_line: "EPISODIO 4 — BLINDADAS: Fix: over-count en `migration-manifest.py`"
source_type: "claude_code"
trust_boundary: "internal"
created_at: "2026-05-19T03:20:18.371764+00:00"
relectura_tagged: false
forgejo_commit_sha: "pending"
---
**Fix completo y verificado end-to-end.** El manifest en disco bajó de **127.474 → 4.190 tokens** — la migración de John ahora es genuinamente limpia.
## Fix: over-count en `migration-manifest.py`
**Causa raíz (una frase):** `generate_manifest()` armaba las secciones 2/3 concatenando `chronicle_state.json` (109+95) con `push_guard_state.json` — cuyo `files_created` acumula **1195** rutas cross-sesión nunca reseteadas (incluye paths fuera del proyecto) — sin acotar a la sesión ni aplicar cap.
**Qué cambié** (4 ediciones disjuntas, RELOJERO: contrato I/O en docstrings, micro-mecanismos ≤40 líneas):
| # | Cambio |
|---|--------|
| Helper `_session_scoped_files()` | Lee `session_summary.artifacts_created` (lista per-instancia con `action`+`timestamp`) — la única fuente *realmente* acotada a la sesión. Elegí esto sobre `git diff` porque git arrastraría el backlog de ~1224 untracked. |
| Helper `_render_file_list()` | Cap defensivo a **50** items + línea `… y N más`. Piso de seguridad: el manifest no puede bloatarse ni en el peor caso. |
| Secciones 2/3 | Usan la fuente scoped; fallback a chroniclepush **también capado** si falta `artifacts_created` (sesiones legacy). |
**Verificación empírica (FASE 7):**
| Métrica | Antes | Después |
|---|---|---|
| Manifest en disco | ~127.474 tokens (ilegible en 1 Read) | **4.190 tokens** ✅ legible en 1 llamada |
| Sección 2 "creados" | **1303** (acumulador) | **15** (scoped a la sesión real) |
| Sección 3 "modificados" | **435** | **14** |
| Tests helpers | — | **5/5 PASS** (scoped+dedup, fallback, cap-200→51 líneas, undercap/empty, checksums) |
`session_code` y la firma `generate_manifest() → (str, str)` intactos → `mega-hook-session.py` (único caller) no se rompe. Rollback disponible: `migration-manifest.py.20260518_215037.bak`.
## Estado de tu migración
El `docs/MIGRATION_MANIFEST_S20260518.PIPELINE_FIXES.md` ya está **regenerado en disco con el fix** — la instancia nueva lo lee de un tirón. La migración sigue siendo: cerrar terminal → reabrir en la misma carpeta.
**Commit (tu decisión — no toco git):** el cambio significativo es un solo archivo:
**Notas menores:** (1) el chip `spawn_task` que disparé el turno anterior quedó **redundante** — lo hice aquí; puedes descartarlo. (2) El header `CONTRACT:` de `migration-manifest.py` tiene `[FILL]` sin llenar (deuda pre-existente, fuera del bug). (3) Opcional: `test_migration_manifest.py` committed para regresión — los 5 tests existen y pasan, pero ejecutados inline, no en archivo versionado.