Santo Domingo, República Dominicana

Ernesto Arias Díaz
Infraestructura Linux, SRE y Rust

Más de 15 años manteniendo encendidos sistemas críticos del sector financiero y de pagos, y trabajando con hardware desde el año 2000. Investigador independiente en sistemas de conocimiento con LLMs locales. Escribo sobre lo que mido, incluido lo que sale mal.

Experiencia
15+ años
Kernel
Linux / RHEL
Lenguaje
Rust
Investigación
1,351 vistas

Consejo: abre la terminal y escribe help.

/home/ernesto/notas

/home/ernesto/proyectos

ANIMUS

archivado · v4.0

Sistema autónomo de conocimiento en Rust que construye un grafo de memoria episódica con un LLM local (Gemma 4 E2B sobre llama.cpp CUDA). Su aporte principal fue la auditoría de nodos fantasma y una arquitectura de honestidad epistémica.

Preprint: 10.5281/zenodo.20674981 · 1,351 vistas · 479 descargas

Corpus regulatorio dominicano

publicado

Dataset abierto de normativa bancaria de la República Dominicana, limpio y listo para RAG y evaluación. 142 documentos bajo licencia CC-BY-4.0.

Hugging Face · shellhack · dominican-banking-regulations-corpus

Ingesta ISO 8583

código abierto

Microservicio en Rust (Tokio, canal MPSC, sqlx/PostgreSQL) que absorbe ráfagas de transacciones simuladas, responde ACK/NACK y registra anomalías con su motivo de detección.

Rust · Tokio · PostgreSQL · simulador en Python

DGII Assistant Pro

beta

Asistente sobre normativa tributaria y laboral dominicana en Telegram y WhatsApp, con PostgreSQL y la API de Claude como motor.

Telegram · WhatsApp · PostgreSQL · Claude API

$ pacman -Q --explicit

core/sistemas

  • rhel / linux15+ años
  • windows-serverestable
  • vmwareestable
  • bash / powershellestable
  • hardware / servidoresdesde 2000

extra/automatización

  • ansibleestable
  • kubernetesckad en curso
  • openshiftlabs completos
  • awsestable

extra/middleware

  • ibm-datapowerestable
  • citrix-netscalerestable
  • message-brokersestable
  • iso-85834+ años

community/dev

  • rust (tokio, sqlx)activo
  • pythonestable
  • postgresqlestable
  • splunkestable
  • llama.cpp / cudaactivo

$ git log --reverse=false trayectoria

v15.1 · actual

Director de TI

Responsable del funcionamiento completo del departamento de tecnología: planificar, priorizar, supervisar y responder por sus resultados ante la dirección.

  • Continuidad operativa de sistemas, servidores, dominios y correo, con respaldos y planes ante fallas.
  • Seguridad de la información, control de accesos, certificados e infraestructura.
  • Gestión y desarrollo del equipo de TI.
  • Administración de proveedores: registradores, hosting y licencias.
  • Despliegues ordenados a producción, con ambientes de prueba, respaldos y capacidad de revertir.
  • Inventario y documentación de la infraestructura, y reportes periódicos de avances y riesgos a la dirección.

Logros

  • Implementé respaldos en todas las áreas que no los tenían.
  • Recuperé el control del software de la empresa: migré desde el proveedor externo los repositorios (backend en Rust, frontends web y gestor de cobros), la base de datos de producción del ERP y la configuración de servicios.
  • Eliminé las fallas recurrentes de un punto de venta reemplazando el equipo por una alternativa de bajo costo (RD$11,500), con un proveedor de buena relación calidad-precio.
  • Detecté y frené un conflicto de interés en la compra de equipos, y expliqué el riesgo al equipo.
  • Informé a la dirección desde el inicio sobre el estado de la tecnología, los riesgos y la situación de los respaldos.
  • Acompañamiento técnico al equipo de TI, construyendo una relación de confianza y aprendizaje.
v15.0 · 2026

Infraestructura de sistemas centrales, banca

Administración de gateways de integración, balanceadores, brokers de mensajería y observabilidad con Splunk en un entorno bancario de alta disponibilidad.

v14.x · 2026

Investigación independiente: ANIMUS

Diseño, auditoría y publicación de un sistema autónomo de conocimiento en Rust. Preprint en Zenodo, dataset en Hugging Face y artículos técnicos en dev.to.

v1.0 → v14 · 15+ años

Infraestructura, procesamiento de pagos con tarjeta

  • Operación de infraestructura crítica Linux y Windows para la red de pagos.
  • Alrededor de 4 años a cargo de sistemas de pagos ISO 8583.
v0.1 · 2000

Hardware y soporte técnico

  • Ensamblaje de computadoras clones, diagnóstico y reemplazo de componentes.
  • Instalación y soporte de Windows desde XP, Microsoft Office y antivirus.
  • Instalación y mantenimiento de servidores físicos.
build deps

Formación

  • Universidad del Caribe (UNICARIBE).
  • Becario del programa Full Stack de INDOTEL / Talento Digital RD.
  • Preparación completa RHCSA, RHCE y OpenShift (laboratorios). CKAD en curso.

$ cat /etc/pacman.d/mirrorlist

InvestigaciónZenodo · ANIMUS v4.0
Hugging Faceshellhack
Auditoría · junio 2026

Phantom Nodes: el 52% de mi grafo no existía

Ernesto Arias Díaz · 6 min

ANIMUS llevaba meses corriendo en modo autónomo. Cada ciclo leía una fuente, extraía hechos y los guardaba como nodos en un grafo. El contador subía de forma constante y yo lo usaba como prueba de que el sistema aprendía.

Un día decidí no creerle al contador y revisar los nodos uno por uno.

1,892nodos que el sistema reportaba
911nodos únicos tras deduplicar
52%de inflación no detectada

Cómo se infla un grafo solo

Encontré tres mecanismos. El primero, que el ciclo de "gaps" volvía a investigar el mismo concepto con preguntas casi idénticas y guardaba cada respuesta como un nodo nuevo. El segundo, que el modelo generaba reflexiones sobre sus propias reflexiones, y esas también entraban al grafo como si fueran conocimiento. El tercero, que no había ninguna verificación de igualdad antes de insertar.

Ninguno de los tres producía un error. El sistema funcionaba y el número crecía. Justamente por eso nadie lo notaba.

Lo que cambié

  • Una plantilla de prompt sin canal de razonamiento y con marcadores estructurales obligatorios.
  • Extracción de la respuesta con rfind() sobre el marcador de cierre, para que nada truncado entre al grafo.
  • Un guardián que rechaza respuestas vacías, cortas o con razonamiento filtrado.
  • Scripts de auditoría reproducibles, publicados junto con el preprint.

La lección para cualquier sistema

Una métrica que el sistema reporta sobre sí mismo no es una medición. En operaciones pasa igual: un dashboard verde dice lo que el agente de monitoreo cree, no lo que el usuario vive. Hay que verificar desde fuera.

Metodología y scripts completos en el preprint de Zenodo.

Rust · pagos · julio 2026

Ingesta ISO 8583 asíncrona en Rust con Tokio

Ernesto Arias Díaz · 7 min

Un switch de pagos no puede esperar a que una base de datos termine de escribir. Si la respuesta tarda, la línea se queda ocupada y la cola crece. Por eso este servicio separa dos trabajos: recibir y confirmar, y luego persistir.

La arquitectura

  • Un TcpListener de Tokio acepta conexiones y crea una tarea por socket.
  • Cada tarea lee la línea, la mete en un canal mpsc con capacidad para 10,000 tareas y responde ISO_8583_ACK de inmediato.
  • Un único worker consume el canal y escribe en PostgreSQL solo lo que es anómalo.
  • Si el canal está cerrado, el cliente recibe ISO_8583_NACK y queda un warning en el log. Nunca silencio.

Detectar por campos, no por etiquetas

La primera versión solo guardaba registros que ya venían marcados como anómalos por el simulador. En producción nadie te etiqueta el fraude. La versión actual inspecciona los campos:

fn motivo_ingesta(payload: &str) -> Option<String> {
    let mut motivos = Vec::new();
    let mti = extraer_campo_log(payload, "MTI:");
    let proc_code = extraer_campo_log(payload, "PROC:");

    if payload.contains("UNKNOWN") || payload.contains("ERR_VAL") {
        motivos.push("campo_destructivo");
    }
    match mti.as_deref() {
        None => motivos.push("mti_ausente"),
        Some(m) if !MTIS_VALIDOS.contains(&m) => motivos.push("mti_invalido"),
        _ => {}
    }
    if proc_code.as_deref() == Some("990000") {
        motivos.push("proc_fraude");
    }
    (!motivos.is_empty()).then(|| motivos.join(","))
}

El motivo se guarda junto al registro. Así se puede medir después cuántas detecciones coinciden con la verdad del simulador.

Lo que aprendí

Al principio puse un LLM a dar el veredicto final sobre cada registro. Fue un error de diseño. Las reglas ya estaban en la función de arriba: son deterministas, auditables y cuestan microsegundos. Un modelo de lenguaje en ese camino agrega latencia y no-determinismo donde un regulador exige lo contrario. Los LLMs sirven para explicar una anomalía a un analista, no para decidir si existe.

Otros detalles: credenciales fuera del código mediante DATABASE_URL, migraciones idempotentes con ADD COLUMN IF NOT EXISTS y columnas TEXT donde antes un VARCHAR(4) rechazaba justo el MTI inválido que se quería capturar.

Datos · julio 2026

259 documentos que nunca entraron: un umbral silencioso

Ernesto Arias Díaz · 4 min

El corpus tenía 817 PDFs de normativa bancaria dominicana. El pipeline los procesaba todos sin errores. Cuando crucé la lista de archivos contra los nodos del grafo, faltaban 262.

817PDFs en el corpus
262nunca ingeridos (32%)
259recuperados con OCR

La causa

El procesador descartaba cualquier documento cuyo texto extraído tuviera menos de 100 caracteres. La regla tenía sentido para filtrar archivos vacíos. Pero los PDFs escaneados no tienen capa de texto: la extracción devolvía casi nada y el documento desaparecía sin dejar rastro en ningún log.

El arreglo

Cuando la extracción nativa no supera el umbral, el documento pasa por OCR con pytesseract antes de decidir. De los 262, se recuperaron 259. Los tres restantes eran ilegibles de verdad.

Después agregué 738 enlaces entre documentos relacionados, porque el grafo tenía forma de estrella: todo apuntaba a un nodo central y nada conectaba los documentos entre sí.

La regla que me llevo

Todo filtro que descarta datos debe contar lo que descarta y decirlo en voz alta. Un continue sin log es un agujero negro.

LLM · GPU · junio 2026

De 3.5 a 79 tokens/s en hardware de consumo

Ernesto Arias Díaz · 5 min

ANIMUS siempre corrió en una laptop: primero una i5 sin GPU dedicada, después una Dell Precision con una RTX 3050 de 4 GB. Cambié el motor de inferencia tres veces.

MotorHardwareVelocidad
Llama 3.2 3B ajustado (QLoRA, Q4_K_M)CPU3.5 tok/s
BitNet b1.58 2B (i2_s)CPU19 tok/s
Gemma 4 E2B (UD-Q4_K_XL)RTX 3050, CUDA76.8–79.3 tok/s

Lo que la velocidad no arregló

Medí la latencia completa de una consulta: mediana de 11.45 segundos. La generación era la parte pequeña. El arranque en frío, unos 7 segundos, dominaba todo. Optimizar tokens por segundo cuando el cuello de botella es otro es un buen recordatorio de por qué hay que medir de punta a punta.

Lo que empeoró

Un modelo más fluido no es un modelo más correcto. Gemma confabulaba con fluidez de experto, algo más peligroso que las alucinaciones torpes de los modelos anteriores, porque convence. Eso obligó a construir la capa de validación estructural antes de dejarle escribir en el grafo.

Notas de operación

  • llama-server persistente, con chequeo de /health antes de enviar trabajo.
  • Reinicio automático del proceso si el servidor deja de responder.
  • Benchmarks con mediana de 10 iteraciones, no con la mejor corrida.
Postmortem · octubre 2026

Postmortem: por qué archivo ANIMUS

Ernesto Arias Díaz · 5 min

ANIMUS empezó en febrero de 2026 con una idea: un sistema que aprende solo, ciclo tras ciclo, y construye su propia memoria. Ocho meses después lo archivo. Este es el porqué.

Lo que dijeron los datos

Comparé ANIMUS contra un RAG vectorial simple y contra GraphRAG de Microsoft, con el mismo modelo generador y 36 preguntas verificadas.

SistemaPuntaje total
ANIMUS58.3%
GraphRAG56.9% (0% de alucinación)
RAG vectorial50.0%

Con 36 preguntas, la diferencia entre ANIMUS y GraphRAG está dentro del ruido. Ninguno dominó. El techo lo ponía un modelo de 2B parámetros, no la arquitectura.

Lo que no funcionó

  • El ciclo autónomo se alimentaba de su propio texto. Más ciclos producían más ruido, no más conocimiento. Ese fue el origen de los nodos fantasma.
  • Lo que parecía emergencia era, mirado de cerca, conteo de coocurrencias.
  • Mientras tanto, los asistentes comerciales incorporaron memoria persistente, búsqueda y tareas programadas. Lo que en febrero era raro hoy viene incluido.

Lo que sobrevive

  • El método de auditoría de Phantom Nodes y sus scripts reproducibles.
  • El corpus regulatorio dominicano, publicado como dataset abierto.
  • Un servicio de ingesta en Rust y mucha experiencia operando LLMs locales.

Cerrar un proyecto con datos es parte del trabajo. Lo más valioso que construí no fue el sistema, fue el hábito de auditarlo.