CreaRack-SL

Reconciliación D1 ← repo del Bibliotecario-Ingest

User value

Cualquier edición directa a src/content/wiki/*.md (sea manual de Edu/Dani, de un subagente, de un script) queda automáticamente reflejada en la base de datos D1 sin necesidad de pasar por Sonnet. Antes de este fix, ediciones masivas del repo (típicamente en commits supercontext: o docs:) provocaban drift D1↔repo: el lint reportaba orphans y stale fantasma mientras el repo estaba correcto. La reconciliación cierra ese gap de forma determinista, gratuita y sin tocar el LLM.

Problema observado (sesión 18, 2026-04-23)

Durante el enriquecimiento de 18 pages hub (commit c4eaaff) para cerrar las 15 orphans detectadas por wiki_lint_bulk, el Ingest hizo skip pre-LLM (correctamente: el commit era supercontext:). Resultado: el repo tenía related enriquecido con backlinks a las 15 orphans, pero bib_wiki_pages.related en D1 seguía con el valor antiguo. El lint siguió reportando las mismas 15 orphans aunque el Obsidian graph view sí las mostraba conectadas.

Causa raíz: los dos únicos caminos que actualizan D1 son (a) Sonnet procesando el commit vía MCP wiki_update_page, (b) skills/curator invocando tools MCP explícitamente. Ninguno se dispara en un skip pre-LLM o Haiku, aunque el commit haya tocado páginas wiki.

Diseño

Nuevo branch en bib_ingest.py que se ejecuta tras cualquier skip y propaga campos metadata del front-matter del repo a D1 vía MCP:

  • Parser YAML minimalista (stdlib re, sin PyYAML): soporta campos string simples y arrays inline [a, b] + multi-línea con - item. Ignora mappings anidados como sources: de objetos (no necesarios para reconcile).
  • Whitelist de campos reconciliados: title, status, owner, supersedes, last_verified (meta) + tags, related (lists). El resto se ignora.
  • Patch object sin content: la tool MCP wiki_update_page acepta patch como objeto parcial de metadata. Si no se envía content, no hace commit al repo → no hay loop push→ingest→push.
  • Silencio en legacy: pages no presentes en D1 (ej. las 7 pages migradas en el backfill sesión 17 que quedaron solo-repo) devuelven “Page not found” y se contabilizan como skipped_not_in_d1 sin ser error.

Integración

Llamada en los dos puntos de skip del pipeline 3-tier:

  • Tier 1 skip pre-LLM: commits chore:, docs:, supercontext: sin paths ricos.
  • Tier 2 skip Haiku: cambios que el triage Haiku decidió no escalar a Sonnet.

El summary del skip se enriquece con | reconcile: N D1 pages synced cuando N > 0, visible en el Pulse en tiempo real.

Validación end-to-end (sesión 18)

Tres commits de test progresivos sobre el workspace:

  • 190c376 — toque de 1 hub (concept--biblioteca--supercontexto) → [Reconcile] D1 sync: 1 updated, 0 legacy-skip, 0 failed. Orphans 15 → 9.
  • 203ae4a — bulk touch de 17 hubs → [Reconcile] D1 sync: 10 updated, 7 legacy-skip, 0 failed (los 7 legacy son pages del backfill solo-repo). Orphans 9 → 2.
  • 0603b55 — cierre de las 2 orphans restantes editando 4 hubs D1 adicionales → [Reconcile] D1 sync: 4 updated, 0 legacy-skip, 0 failed. Orphans 2 → 0.

En total, 15 pages pasaron de “orphan en D1” a conectadas sin un solo token LLM gastado en el propio reconcile.

Decisiones

  • Reconcile solo en branch skip, no en éxito Sonnet: Sonnet ya escribe en D1 vía MCP cuando procesa; reconcile encima sería doble escritura y ruido de log. Si un día Sonnet procesa sin tocar un .md que sí cambió, saldrá en el lint semanal y se corregirá con un commit posterior.
  • Sin content en el patch: crucial para evitar loop. El commit al repo ya está hecho por quien editó; reconcile solo propaga metadata a D1.
  • Parser stdlib-only: no se añade PyYAML como dependencia. El mini-parser cubre el 100% de los campos Supercontexto relevantes; lo que no cubre (sources anidados) tampoco es campo reconciliado.
  • Paridad en los 3 repos: el mismo patch se aplicó a bib_ingest.py del workspace y de CreaRack-Pro + doc canónica en claude-method/biblioteca/prompts/ingest.md. CreaRack-Pro nunca edita src/content/wiki/, pero mantener paridad de código reduce drift futuro.

Limitaciones conocidas

  • Pages que no existen en D1 (como las 7 legacy del backfill sesión 17) no se sincronizan — siguen solo-repo. Para resolverlo, indexarlas con wiki_create_page (tarea aparte).
  • sources: no se reconcilia. Raramente cambia sin tocar el body; si emerge el caso, extender el parser con soporte de mapping anidado.

Véase también

  • [[concept—biblioteca—supercontexto]]
  • [[feature—supercontext—bibliotecario-lint-fase-5]]
  • [[feature—supercontext—fase-4-query-con-cierre]]
  • [[feature—supercontext—fase-6-metricas-utility]]
  • [[entity—mcp—tool—wiki-lint-bulk]]
  • [[entity—mcp—tool—wiki-curator-review]]
  • [[incident—20260421—d1-bind-overflow-silent]]