2026-09-19 — nef-silo: plan de errores y mejoras (punto de partida)

Cierra el proceso de investigación/versionado. A partir de aquí: pulir y mejorar el silo-engine (~/nef/nef-silo, repo github.com/[usuario]/nef-silo).

Errores encontrados (y estado)

#ErrorEstado
1Apify devolvía {"demo": true} (no editorial)Descartado como vía; no repetir sin plan pagado
2HDBSCAN TypeError: only 0-dimensional... (sklearn#33219, NumPy≥2.4)Arreglado en news-silo: epsilon=0 + copy=True
3Cuentas PENDIENTE de X: timeout/503 (@fireimages, @gurablo, @lnk, @promakos_, @philosophymemo0)Excluidas de recursos.json (127→122)
4RSS mal formado (Desinformémonos, AI-Era 新智元)Fallback a feedparser en _entradas
5Corrida que se colgaba / se solapaba con cronSILO_TIMEOUT (18s) + flock en run.sh + log por fuente
6silo.jsonl con duplicados tras corridas parcialesPendiente: DB es la fuente de verdad; compactar/rotar jsonl
7home.json desfasadoResuelto: auto-build en hn._cargar_feed
8Calidad de clustering mixta (silos por fuente, no por evento)Pendiente: ver mejoras 5-6
9Sin estado ni métricas por fuente✅ Mejora 1 aplicada
10Dedup solo por URL (se cuelan copias sindicadas)✅ Mejora 2 aplicada
11Corridas de ~17 min si X/RSSHub no responde✅ Timeout corto + cortacircuito

Mejoras (ordenadas por valor/esfuerzo)

  1. Scheduler por fuente + métricas (gestión/escala)

    • Tabla fuentes: last_fetch, etag, last_modified, fallos, next_retry, n_items, ultimo_ok, ultimo_error.
    • Conditional GET (If-None-Match/If-Modified-Since → 304: no parsear).
    • Backoff exponencial; saltar fuentes muertas hasta next_retry.
    • Métricas en estado.json: ingest lag (publicación→captura), éxito por fuente, tasa de error de parseo, items por tema.
  2. Dedup de contenido (MinHash/SimHash) además del de URL, para colapsar la misma noticia en URLs distintas. (Dos etapas, dos momentos.)

  3. Facetas: añadir lang, region, tipo a items + índice FTS5. ✅ Aplicada (c0efc1c): items.lang (zh/en/es) + items.region (MX/CN/INT)

    • items_fts (FTS5) y cmd buscar con filtros de faceta (tema/lang/region/tipo/dias).
  4. Búsqueda híbrida: BM25 (FTS5) + embeddings + RRF(k=60) + rerank.

  5. Clustering incremental: fingerprint + LSH + assign-or-open (no re-cluster completo); job union-find para reparar fragmentación.

  6. Calidad de silos: c-TF-IDF para etiquetar; evaluar KMeans vs HDBSCAN por tipo de corpus (nota previa: KMeans separa mejor en AI).

  7. Robustez/observabilidad: topes por fuente, alerta si una fuente deja de producir, --dry-run, y endpoint/estado consultable.

Siguiente paso

Mejoras 1 y 2 aplicadas y desplegadas (repo nef-silo):

  • Mejora 1 (5d004f2): scheduler por fuente, conditional GET (304), backoff, ingest lag.
  • Mejora 2 (a5656a6): dedup de contenido con MinHash + LSH (64 permutaciones, 16 bandas × 4 filas, Jaccard ≥ 0.6) → tabla duplicados.
  • Extra (125d115): timeout corto (8 s) para X/Telegram + cortacircuito tras 6 fallos.

Verificado en Linode (corrida 22:43): 74 fuentes sin cambios (304), 4 en backoff, 410 duplicados descartados, 13 nuevos, 1101 en silo, 0 errores, corrida acotada.

Mejora 3 aplicada (c0efc1c): facetas lang/region + FTS5 + buscar. Verificado en Linode: 1104 items = 1104 en FTS; lang en 815 / zh 157 / es 132; region INT 849 / CN 157 / MX 98; búsqueda con filtros OK.

Continúa la mejora 4: búsqueda híbrida (BM25 + embeddings + RRF k=60 + rerank).

Mejora 4 aplicada (bf1e422 + ae52ea5): embeddings por hashing de char n-grams (0 deps, 256 dims) + BM25 + RRF k=60; desempate por recencia como rerank barato. Error 6 también cerrado (_compactar_jsonl, 2012→1351). Detalle y verificación: 2026-09-19-nef-silo-busqueda-hibrida.md. Nota de proceso: pull.sh ahora solo baja data/ (antes revertía código local). Mejora 5 aplicada (5d1cd8d): silos por evento incrementales + repair union-find. Ver 2026-09-19-nef-silo-busqueda-hibrida.md (sección 2026-09-21). Siguiente: mejora 6 (c-TF-IDF, calidad de clusters).

Mejora 7 aplicada en local (2026-09-22, sin commit ni deploy): robustez/observabilidad.

  • Topes por fuente: SILO_TOPE_DIA (default 120 items nuevos por fuente/24h); fuentes topeadas se reportan (fuentes_topeadas) y se saltan sin parsear.
  • Alertas: caida (SILO_ALERTA_FALLOS=3 fallos seguidos) y muda (SILO_ALERTA_DIAS_MUDA=7 días sin items nuevos, referencia ultimo_nuevo/primera_vez). Salen en estado.json, en data/salud.json y con cmd salud [--json].
  • capturar --dry-run: recorre, deduplica y clasifica sin escribir items ni estado; reporta silos_nuevos/silos_unidos simulados.
  • Migración idempotente de fuentes (+ultimo_nuevo, primera_vez); bug corregido: _estado_fuente hardcodeaba columnas y descartaba las nuevas.
  • Verificado local sobre réplica de prod (4416 items): dry-run no escribió estado/jsonl, tope dispara, alertas detectan creativereview (403), LWN y philosophymemo0 (503).
  • Pendiente: commit + deploy a Linode (el server sigue con la versión anterior). Siguiente: mejora 6 (c-TF-IDF, calidad de clusters).

Batería de pruebas del plan “un solo engine” (2026-09-22): nef-silo/tests/bateria.py, 8 probes, métrica clave “datos relevantes”. Resultados: 2026-09-22-bateria-engine-resultados.md. Titulares: profundidad = multiplicador (titular 50% → texto 90% de match con el grafo); “un fetch” viable (solape 100% con surtido en la ventana del engine); balance de perspectivas no medible aún (solo 2.9% items con rating). Bugs corregidos de paso: duplicados inflado (URLs ya conocidas) → set urls_db + contador repetidos; _estado_fuente hardcodeaba columnas. Siguiente acordado: F1 (T0 + ratings) antes de mejora 6.