CreaRack-SL

MCP Tool · wiki_lint_bulk

MCP Tool: wiki_lint_bulk

Supercontexto Fase 5 — Bibliotecario-Lint

Tool MCP que itera todas las páginas wiki con status: active y genera un reporte de tres categorías de problemas: páginas stale, orphans y broken sources. Diseñado para ejecutarse desde cron o manualmente con 0 llamadas LLM.


Firma

wiki_lint_bulk(args: {
  stale_days?:         number;   // default 60
  limit?:              number;   // default 200
  apply_stale?:        boolean;  // default false
  check_sources?:      boolean;  // default FALSE ⚠️
  max_source_fetches?: number;   // default 30
}): Promise<string>  // JSON

Parámetros

ParámetroTipoDefaultDescripción
stale_daysnumber60Páginas con last_verified anterior a N días se marcan stale
limitnumber200Máximo de páginas a escanear por invocación
apply_stalebooleanfalseSi true, actualiza status:'stale' en D1 vía db.batch()
check_sourcesbooleanfalseSi verifica existencia de archivos code en GitHub API. Default OFF — riesgo de exceder límite subrequests CF Workers
max_source_fetchesnumber30Límite de fetches a GitHub cuando check_sources=true

Respuesta JSON

{
  "scanned": 63,
  "stale": [{ "slug": "...", "age_days": 90, "title": "..." }],
  "orphans": [{ "slug": "...", "title": "..." }],
  "broken_sources": [{ "slug": "...", "missing": ["path/to/file.ts"] }],
  "sources_checked": 12,
  "sources_budget_exhausted": false,
  "applied_stale": 0
}

Algoritmo (6 pasadas)

Rediseñado en commit 2319b6c (2026-04-22) para evitar el patrón N+1 que causaba fallos en CF Workers con 60+ páginas:

Pass 1  → SELECT bulk de todas las pages active (1 query D1)
Pass 2  → Reverse-index de backlinks en memoria JS (0 subrequests)
Pass 3  → Code refs con IN chunked a ≤90 bind params por query D1
Pass 4  → Evaluación staleness + orphans en memoria
Pass 5  → [Opcional] Check sources en GitHub, limitado por max_source_fetches
Pass 6  → apply_stale via db.batch() (1 subrequest para todos los UPDATEs)
const referenced = new Set<string>();
for (const p of allPages) {
  if (p.supersedes) referenced.add(p.supersedes);
  const rel = JSON.parse(p.related || '[]') as string[];
  for (const r of rel) referenced.add(r);
}

Una página es orphan si !referenced.has(slug) && !codeReferenced.has(slug).

Pass 3 — IN chunked (detalle)

D1 tiene límite de ~100 bind params por query. Se fragmenta en chunks de 90:

const slugs = allPages.map(p => `doc:wiki:${p.slug}`);
for (let i = 0; i < slugs.length; i += 90) {
  const chunk = slugs.slice(i, i + 90);
  const placeholders = chunk.map(() => '?').join(',');
  await db.prepare(`SELECT ... WHERE n.qualified_name IN (${placeholders})`)
    .bind(...chunk).all();
}

Footguns resueltos (2026-04-22 · commit 2319b6c)

Ver también: concept--infra--cf-workers-d1-footguns

1. “Too many subrequests” (CF Workers Free, límite 50)

Causa: bucle for (const p of pages) hacía 1 query D1 por página para calcular orphans. Con 60+ páginas → >50 subrequests → crash.

Fix: query global única (Pass 1) + reverse-index JS (Pass 2).

2. “D1_ERROR: LIKE pattern too complex”

Causa: WHERE related LIKE '%"slug"%' con slugs complejos disparaba error de D1.

Fix: eliminado completamente. Backlinks calculados parseando related en memoria.

3. apply_stale en bucle (N UPDATEs)

Causa: loop for (const s of stale) { await db...run() } hacía N subrequests.

Fix: db.batch(statements) — 1 subrequest para todos los UPDATEs.


Cron: wiki-lint.yml

# Fragmento relevante tras el fix (commit 2319b6c)
wiki_lint_bulk:
  check_sources: false   # ← cambiado de true a false
  limit: 200

wiki_lint_contradictions:
  max_pairs_per_community: 5   # ← reducido de 10
  max_total_pairs: 15          # ← reducido de 40

⚠️ check_sources: true solo debería activarse desde el cron semanal y siempre acompañado de un max_source_fetches bajo (≤30) para respetar el presupuesto de subrequests.


Ubicación en el código

ArtefactoRuta
Handler principalfunctions/api/mcp/handlers/wiki.ts → función wikiLintBulk() aprox. línea 1010
Definición tool schemafunctions/api/mcp/tools.ts → TOOLS[] entrada wiki_lint_bulk
Cron workflow.github/workflows/wiki-lint.yml

Trabajo pendiente

  • Sesión 11: aplicar el mismo refactor (bulk query + reverse-index) a wikiLintContradictions. Actualmente sigue con posibles N+1.

Véase también

  • [[feature—supercontext—bibliotecario-lint-fase-5]] — fase del Supercontexto que introdujo esta tool
  • [[entity—mcp—tool—wiki-lint-contradictions]] — tool hermana que corre en el mismo cron diario del Lint
  • [[entity—mcp—tool—wiki-utility-recompute]] — tool complementaria del set wiki-lint/curator/utility
  • [[concept—biblioteca—supercontexto]] — arquitectura global del sistema de bibliotecarios latentes
  • [[concept—infra—cf-workers-d1-footguns]] — footguns de CF Workers/D1 que motivaron el refactor bulk+IN chunked