CreaRack-SL

bib_wiki_pending_commits — Tabla D1 · Parking de commits wiki pendientes

bib_wiki_pending_commits

Tipo: Tabla D1 (Cloudflare) Migration: migrations/0036_wiki_pending_commits.sql Introducida en: s80 · 2026-05-22 (commit@bd61e31)


Propósito

Tabla de staging temporal para el sistema Bibliotecario-Ingest Batch. Almacena el contenido .md de las páginas wiki que wiki_create_page y wiki_update_page generan durante el agentic loop de Sonnet, aplazando el commit a GitHub hasta que wiki_flush_pending_commits consolide todo en un único push.


Esquema

CREATE TABLE IF NOT EXISTS bib_wiki_pending_commits (
  id           INTEGER PRIMARY KEY AUTOINCREMENT,
  trigger_ref  TEXT    NOT NULL,                  -- "PR#63", "commit@abc1234"
  slug         TEXT    NOT NULL,                  -- slug kebab-case de la wiki page
  file_path    TEXT    NOT NULL,                  -- "src/content/wiki/<slug>.md"
  body         TEXT    NOT NULL,                  -- contenido completo del .md (front-matter + body)
  operation    TEXT    NOT NULL
               CHECK (operation IN ('create', 'update')),
  commit_message TEXT  NOT NULL,
  created_at   TEXT    DEFAULT (datetime('now')),
  UNIQUE(trigger_ref, slug)
);

CREATE INDEX IF NOT EXISTS idx_wiki_pending_trigger
  ON bib_wiki_pending_commits(trigger_ref);

Constraint UNIQUE(trigger_ref, slug)

Garantiza exactamente una entrada por (trigger, slug). El ON CONFLICT DO UPDATE se comporta diferente en create vs update:

En wikiCreatePage

ON CONFLICT(trigger_ref, slug) DO UPDATE SET
  body             = excluded.body,
  operation        = excluded.operation,
  commit_message   = excluded.commit_message

Gana el último body sin condiciones.

En wikiUpdatePage

ON CONFLICT(trigger_ref, slug) DO UPDATE SET
  body = excluded.body,
  operation = CASE
    WHEN bib_wiki_pending_commits.operation = 'create' THEN 'create'
    ELSE excluded.operation
  END,
  commit_message = excluded.commit_message

Si Sonnet hace create + update sobre el mismo slug en la misma sesión, el campo operation se preserva como 'create' para que ghCommitMultipleFiles sepa que el archivo es nuevo (no requiere SHA previo).


Ciclo de vida de una fila

wiki_create_page(defer_commit=true)
  → INSERT (o ON CONFLICT UPDATE) en bib_wiki_pending_commits

wiki_flush_pending_commits(trigger_ref)
  → SELECT todas las filas con trigger_ref
  → commit a GitHub (ghPutFile o Trees API)
  → DELETE FROM bib_wiki_pending_commits WHERE trigger_ref = ?
     (solo si commit OK — idempotente)

Las filas son efímeras: desaparecen en cuanto el flush tiene éxito. Si el flush falla (red, GH_PAT inválido, race 422), las filas permanecen y se puede reintentar manualmente.


Índice

idx_wiki_pending_trigger sobre (trigger_ref): la query principal en el flush es WHERE trigger_ref = ? — el índice la cubre directamente.


Tablas relacionadas

TablaRelación
bib_wiki_pagesSe escribe simultáneamente con el INSERT pending (metadata D1 inmediata, .md diferido)
bib_wiki_logwiki_flush_pending_commits inserta un registro operation='ingest' tras flush OK

Operaciones de mantenimiento

-- Ver páginas pendientes por trigger
SELECT trigger_ref, slug, operation, created_at
FROM bib_wiki_pending_commits
ORDER BY trigger_ref, id;

-- Limpiar manualmente un trigger atascado (usar con cuidado)
DELETE FROM bib_wiki_pending_commits WHERE trigger_ref = 'PR#XX';

-- Ver páginas envejecidas (>1 hora sin flush — posible flush fallido)
SELECT * FROM bib_wiki_pending_commits
WHERE created_at < datetime('now', '-1 hour');

Véase también

  • [[feature—biblioteca—bib-ingest-batch]]
  • [[entity—mcp—tool—wiki-flush-pending-commits]]