Saltar a contenido

Runbook

Estado real vs. plan

Esta página describía el cron del sistema completo (post Fase 5). El código hoy solo tiene Fase 0 y parte de Fase 1: ejecutar_ingesta, renormalizar, seed_fuentes, generar_reporte. diff_proyectos, extraer_documentos, puntuar y check_debarment son ítems sin marcar en fases.md — no existen como comandos todavía. Verificado contra inteligencia/management/commands/ el 2026-09-18.

Operación normal (hoy)

Cuándo Qué corre
Diario 06:00 UTC ejecutar_ingesta para fuentes de cadencia diaria (carril A)
Lunes 06:00 UTC ejecutar_ingesta semanales (carril B, ingesta silenciosa)
Lunes 08:00 UTC generar_reporte
Jueves 08:00 UTC generar_reporte

Operación objetivo (Fase 4-5, no construido)

Cuándo Qué correría
Diario 07:00 UTC extraer_documentos, puntuar
Diario 07:30 UTC Evaluación de alertas por ventana corta
Lunes 06:00 UTC diff_proyectos

Por qué la ingesta es diaria y el reporte no

Si solo buscamos cuando reportamos, ampliamos la ventana y perdemos avisos cortos. Ingesta diaria, reporte dos veces por semana, alerta por evento.

El reporte salió vacío

Diagnóstico en orden:

  1. Revisar la tabla ingestas: ¿alguna fuente falló o devolvió cero?
  2. Si una fuente devolvió cero varias corridas seguidas → probablemente cambió su contrato. Correr los tests de normalizador contra un payload fresco
  3. Si todas devolvieron datos pero el reporte está vacío → los filtros duros están descartando de más. Revisar el panel de calibración

Silencio ≠ no hubo avisos

Es el modo de fallo más peligroso del sistema. Una fuente que devuelve cero silenciosamente parece funcionar. Por eso existe la alerta de ultimo_ok.

Una fuente cambió su contrato

  1. Capturar un payload fresco y guardarlo como fixture nuevo en tests/fixtures/<fuente>/<fecha>.json
  2. No borrar el fixture viejo. El histórico guardado en crudo tiene la forma antigua y el normalizador debe seguir manejándola
  3. Actualizar el normalizador para manejar ambas formas
  4. Correr renormalizar --fuente=<x> sobre el histórico
  5. Verificar que el conteo de registros no cambió inesperadamente

Ingesta manual / re-ingesta

python manage.py ejecutar_ingesta --fuente-id=<id>

Idempotente por fuente_id + id_nativo. Sin --fuente-id corre todas las fuentes activas.

No hay backfill por ventana de fechas todavía

ejecutar_ingesta no acepta --desde/--hasta. Descarga lo que el endpoint devuelva con los params fijos guardados en el registro Fuente (ver seed_fuentes.py). Un backfill real requiere editar esos params a mano o ampliarlos en código.

Ojo con las cuotas: SAM.gov e IATI tienen límites duros (fuentes aún no dadas de alta, ver fases.md Fase 6). Revisar la página de la fuente antes de ampliar rows.

Reprocesar tras mejorar un normalizador

python manage.py renormalizar

Sin argumentos: reprocesa todos los avisos con crudo guardado, no admite filtrar por --fuente. No vuelve a descargar.

puntuar (scoring LLM) es Fase 5, no existe todavía.

Antes de firmar con un socio o prime

Comando pendiente de construir (Fase 3)

check_debarment no existe como comando de gestión. Hoy es una consulta SQL manual contra el dataset de sancionados del BID — ver docs/inteligencia/fuentes/bid.md. Un socio inhabilitado nos contamina en todo el sistema multilateral (inhabilitación cruzada Banco Mundial, BAD, BAfD y BERD). No saltarse este paso solo porque el comando no esté listo.

Revisión trimestral

  • Muestra manual de descartes automáticos: ¿los filtros duros se están equivocando en silencio?
  • Auditoría de recall: consultar adjudicaciones AR IV y contar cuántas de nuestro nicho el sistema nunca vio
  • Medir la mediana de días entre primera detección y fecha límite. Debe crecer
  • Revisar Pendientes de verificación: ¿qué se confirmó, qué sigue abierto?