Sync Cascade — propagación automática de mirrors entre páginas wiki
Sync Cascade es la funcionalidad de la Biblioteca (Fase 2) que mantiene sincronizadas las páginas mirror de la wiki: cuando una página fuente (source) cambia, el sistema detecta sus mirrors registrados en el frontmatter (mirrors: [slug-mirror]) y propone o aplica automáticamente los cambios correspondientes en las copias, preservando el contexto local de cada perfil.
Motivación
Algunos documentos del corpus wiki (onboardings, team-processes, perfiles de dev) existen en múltiples variantes adaptadas por audiencia o entorno. Mantenerlas a mano genera drift. Sync Cascade automatiza la propagación sin borrar las adaptaciones locales.
Arquitectura del flujo
commit wiki → bib_ingest.py (TIER 1/2/3)
↓
reconcile_wiki_to_d1() ← fuerza coherencia frontmatter repo↔D1
↓
wikiPropagateMirrorChanges() ← marca mirrors como "pending" en D1
↓
wikiProposeMirrorUpdate() ← Haiku genera proposed_body quirúrgico
↓
ghCommitMultipleFiles() ← abre PR con el cuerpo propuesto
Componentes clave
reconcile_wiki_to_d1 (bib_ingest.py)
Función de reconciliación que sincroniza el frontmatter del .md del repo (incluidos los campos mirrors: y mirror_reason: de Sync Cascade) con el registro correspondiente en D1. Se invoca en tres momentos del pipeline:
- Skip pre-LLM (TIER 1): siempre.
- Skip Haiku (TIER 2): siempre.
- Proceso profundo Sonnet (TIER 3): añadido en s82 (fix #64). Antes solo corría en los dos skips, generando drift silencioso entre repo y D1 para commits que pasaban a proceso profundo.
wikiProposeMirrorUpdate (wiki.ts, handler CF Workers)
Llama a Haiku para generar el proposed_body del mirror a partir del diff de la fuente. Parámetros críticos (historial de cambios):
| Versión | MAX_BODY | ABORT_BODY | max_tokens output | Motivo |
|---|---|---|---|---|
| pre-s80 | 8 000 | — | 8 000 | Inicial |
| s80 | 32 000 | 50 000 | 8 000 | Fix PRs destructivos #66+#67 (onboardings 20-60KB, Haiku veía solo 8KB) |
| s82 | 120 000 | 180 000 | 24 000 | Los mirrors reales pesan ~42KB; con 32K se perdían los últimos ~10KB (76% del body, safety-check 0.5x dejaba pasar) |
Safety-check anti-truncado (invariante desde s80): si proposed_body.length < mirror_body.length × 0.5, se descarta la propuesta y se loguea para revisión manual. Este check se mantiene como última línea de defensa.
wikiPropagateMirrorChanges (wiki.ts)
Recibe una lista de source_slugs, consulta D1 por los mirrors asociados y los marca como pending_sync. Devuelve log de targets marcados.
Frontmatter de mirrors
Una página fuente declara sus mirrors en el frontmatter:
mirrors:
- slug-mirror-perfil-a
- slug-mirror-perfil-b
mirror_reason: "Onboarding adaptado por perfil de dev"
El campo mirrors: es el que persiste en D1 y habilita el pipeline de propagación.
Fix s82 — Bug #64: reconcile en TIER 3
Problema: run_ingest() solo llamaba a reconcile_wiki_to_d1() en los caminos de skip (TIER 1 y TIER 2). Un commit que activaba el proceso profundo Sonnet (TIER 3) terminaba sin reconciliar → los campos mirrors:, related:, tags: actualizados quedaban solo en el .md del repo, nunca en D1. El siguiente tick de Sync Cascade no podía ver los mirrors nuevos.
Fix: añadida la llamada a reconcile_wiki_to_d1(changed_files, trigger_ref, mcp_token) al final de run_ingest() en el camino TIER 3, con el mismo patrón de logging que los skips.
# bib_ingest.py — añadido en s82
recon = reconcile_wiki_to_d1(changed_files, trigger_ref, mcp_token)
if any(recon[k] for k in ("reconciled", "indexed_new", "skipped_not_in_d1", "failed")):
log(f"[Reconcile] D1 sync (TIER 3): {recon['reconciled']} updated, ...")
Hardening s82 — #65: MAX_BODY cubre onboardings
Problema: con MAX_BODY=32000, Haiku veía solo los primeros 32KB de un documento de ~42KB. El safety-check de 0.5x (32/42 = 76%) lo dejaba pasar, resultando en un proposed_body que perdía los ~10KB finales del mirror.
Fix: MAX_BODY subido a 120 000 chars (Haiku 4.5 admite 200K tokens de input), ABORT_BODY a 180 000, max_tokens de output a 24 000 (≈84KB). Validado en vivo con par profile-biz → profile-dev: body completo con cambio quirúrgico, should_propose=true, coste $0.005.
Historial de incidentes relacionados
- s80 (22-05-2026): PRs destructivos #66+#67 por
MAX_BODY=8000— Haiku devolvía solo el fragmento inicial como body completo. Ver [[incident—20260522—mirrors-destructivos-max-body]]. - s82 (24-05-2026): gap residual con
MAX_BODY=32000para docs de ~42KB. Cerrado en este commit.
Véase también
- [[incident—20260522—mirrors-destructivos-max-body]]