Bugs corregidos (12): B1-B12 — crashes, tipos, métodos, logger Ejecutor reescrito: evento web → heartbeat 30s → cierre automático copiloto.rb y novato.rb deprecados → redirigen a dron lanzar Plan P009 v3.2 — Fase 1.5 100%% completa
37 KiB
A01.P009 - Evolución del Ecosistema ADN al Concepto de Dron
Estado: 🟢 Fase 1.5 completada
Pertenece a: A01 - Ecosistema ADN
Fecha: 2026-04-09
Responsable: Lic. Ricardo MONLA
Versión: 3.2 — Fase 1.5 completada, sistema dual eliminado
📈 Progreso
Fase 0: ██████████ 100% Infraestructura de Datos (tablas internas) ✅
Fase 1: ██████████ 100% Atomicidad (bugs corregidos) ✅
Fase 1.5: ██████████ 100% Visibilidad Bitácora Web + Corrección Bugs ✅
Fase 2: ░░░░░░░░░░ 0% Composición — Orquestación de Flujos
Fase 3: ░░░░░░░░░░ 0% Planificación — Drones Programados
Fase 4: ░░░░░░░░░░ 0% Inteligencia de Colmena
Fase 5: ░░░░░░░░░░ 0% Observabilidad — Dashboard y Métricas
📋 Resumen Ejecutivo
Este plan define la evolución del ecosistema ADN hacia una arquitectura de Inteligencia de Colmena basada en AtomicDrones — drones atómicos especializados que, compuestos, forman una maquinaria autónoma integral.
Filosofía de Diseño:
| Principio | Descripción |
|---|---|
| 🧬 AtomicDrones | Cada dron hace UNA cosa y la hace bien. Sin monolitos. |
| 🤖 Inteligencia de Colmena | La solución emerge de la composición de drones simples. |
| ⚙️ Engranajes Especializados | Drones ejecutores, vigilantes, sanadores, planificadores. |
| 🚫 No FrankenDrones | Rechazar drones que intentan hacer todo mal. |
Concepto de Dron ADN:
- Atómico: Una responsabilidad única (Single Responsibility)
- Componible: Se ensambla con otros drones para soluciones complejas
- Auto-bitácora: Registra inicio/fin automáticamente
- Observable: Estado visible vía
dron flotay dashboard web - Efímero: Nace, ejecuta, muere (sin estado persistente innecesario)
🎯 Objetivo
Evolucionar el ecosistema ADN hacia una colonia de AtomicDrones especializados que, compuestos, resuelven problemas complejos mediante inteligencia de colmena.
Meta: Reducir la fricción operativa mediante drones atómicos que se especializan en una tarea única y se componen para flujos complejos.
🐝 Tipos de AtomicDrones (Especialización)
Cada tipo de dron tiene una única responsabilidad. La composición de múltiples drones resuelve problemas complejos.
| Tipo | Símbolo | Responsabilidad | Ejemplo |
|---|---|---|---|
| Ejecutor | 🛠️ |
Ejecuta un comando y reporta resultado | dron_ejecutor |
| Vigilante | 👁️ |
Monitorea estado de otros drones | dron_vigilante |
| Sanador | 🩹 |
Repara drones zombies/fallidos | dron_sanador |
| Planificador | 📅 |
Lanza drones según cron | dron_planificador |
| Mensajero | 📨 |
Notifica resultados (Slack, email) | dron_mensajero |
| Orquestador | 🎼 |
Compone múltiples drones en flujo | dron_orquestador |
Ejemplo de Composición (Inteligencia de Colmena)
Problema: Backup nocturno de SQL + sync a nube + notificación
Solución FrankenDron (❌ rechazar):
# Un solo dron que hace todo (monolito frágil)
dron_backup_nocturno.rb # 500 líneas, 7 responsabilidades
Solución AtomicDrones (✅ adoptar):
# Orquestador compone 4 drones especializados
dron_orquestador \
--step "dron_ejecutor --cmd 'vzdump 103'" \
--step "dron_ejecutor --cmd 'rclone sync /bkps oneDrive:'" \
--step "dron_vigilante --check exit_code" \
--step "dron_mensajero --notify slack 'Backup OK'"
📡 Medio de Comunicación: Bitácora Web como Registro Central
La Bitácora Web es el medio de comunicación donde los drones dejan registro de su actividad. El sistema sigue el principio DB-First con capas de visibilidad.
Principio de Codificación: Atomisidad
Atomisidad es el principio de código compartido que aplica "Menos es Más" a la implementación de drones:
┌─────────────────────────────────────────────────────────────┐
│ Dron::Base (módulo compartido) │
│ - logger: Logger único para todos los drones │
│ - db_query: Ejecución de SQL con resultados │
│ - db_exec: Ejecución de SQL sin resultados │
│ - formato_duracion: Utilitario común │
│ - slice_safe: Manejo seguro de strings │
│ - blank?: Verificación de nil/empty │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Ejecutor │ │ Vigilante │ │ Sanador │
│ extend Base │ │ extend Base │ │ extend Base │
└──────────────┘ └──────────────┘ └──────────────┘
Beneficios:
- Un solo lugar para corregir errores comunes
- ~40% menos líneas de código
- Nuevos drones heredan funcionalidad automáticamente
Arquitectura de Registros
┌─────────────────────────────────────────────────────────────────┐
│ DRONES (Ejecutores, Vigilantes, Sanadores, etc.) │
│ Cada dron deja registro al ejecutar │
└────────────┬────────────────────────────────────────────────────┘
│ registra
▼
┌─────────────────────────────────────────────────────────────────┐
│ CAPA 1: Tablas Internas (NO visibles directamente) │
│ - bitacoras.dron_logs: Logs detallados de cada dron │
│ - bitacoras.dron_avances: Progreso paso-a-paso │
│ - bitacoras.dron_metricas: Métricas de rendimiento │
│ - bitacoras.dron_errores: Errores y reintentos │
└────────────┬────────────────────────────────────────────────────┘
│
│ dron_vigilante consolida
▼
┌─────────────────────────────────────────────────────────────────┐
│ CAPA 2: Bitácora Web (Resumen visible) │
│ - events: Eventos consolidados por flujo/orquestación │
│ - Descripción: Resumen legible del progreso │
│ - Estado: ⏳ En ejecución | ✅ Completado | ❌ Fallido │
│ - URL: http://localhost:5174/bitacoras/ │
└─────────────────────────────────────────────────────────────────┘
Tablas Internas (Esquema bitacoras)
-- Logs detallados de cada dron (NO visible en web directamente)
CREATE TABLE bitacoras.dron_logs (
id SERIAL PRIMARY KEY,
dron_id VARCHAR(50) NOT NULL, -- ej: dron_083045_123
flujo_id VARCHAR(50), -- ID de orquestación (si aplica)
tipo VARCHAR(20) NOT NULL, -- ejecutor|vigilante|sanador|planificador|mensajero
estado VARCHAR(20) NOT NULL, -- pending|running|completed|failed|zombie
cmd TEXT, -- Comando ejecutado
output TEXT, -- Salida del comando
exit_code INTEGER, -- Código de retorno
started_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP,
heartbeat TIMESTAMP DEFAULT NOW(), -- Último heartbeat
reintentos INTEGER DEFAULT 0,
metadata JSONB DEFAULT '{}'::jsonb -- Metadata adicional
);
-- Avances paso-a-paso (para flujos multi-paso)
CREATE TABLE bitacoras.dron_avances (
id SERIAL PRIMARY KEY,
dron_id VARCHAR(50) NOT NULL,
paso INTEGER NOT NULL, -- Número de paso en flujo
descripcion TEXT NOT NULL, -- Qué se está haciendo
estado VARCHAR(20) NOT NULL, -- pending|running|completed|failed
started_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP,
metadata JSONB DEFAULT '{}'::jsonb
);
-- Métricas de rendimiento (agregaciones)
CREATE TABLE bitacoras.dron_metricas (
id SERIAL PRIMARY KEY,
fecha DATE NOT NULL,
dron_tipo VARCHAR(20) NOT NULL,
total_ejecuciones INTEGER DEFAULT 0,
completados INTEGER DEFAULT 0,
fallidos INTEGER DEFAULT 0,
zombies INTEGER DEFAULT 0,
tiempo_promedio INTERVAL,
reintentos_total INTEGER DEFAULT 0,
UNIQUE(fecha, dron_tipo)
);
-- Índices para consultas eficientes
CREATE INDEX idx_dron_logs_estado ON bitacoras.dron_logs(estado);
CREATE INDEX idx_dron_logs_heartbeat ON bitacoras.dron_logs(heartbeat);
CREATE INDEX idx_dron_logs_flujo ON bitacoras.dron_logs(flujo_id);
CREATE INDEX idx_dron_avances_dron ON bitacoras.dron_avances(dron_id);
Dron Vigilante: El Monitor de Flotas
El dron_vigilante es responsable de:
- Escanear flota: Lee
bitacoras.dron_logspara detectar drones activos - Detectar zombies:
heartbeat > 5min→ marca como zombie - Registrar avances: Inserta en
bitacoras.dron_avancesel progreso - Consolidar resumen: Crea/actualiza evento en
bitacoras.events(visible en web) - Alertar anomalías: Si detecta >5 fallos en 1h → notifica
# Ejemplo: dron_vigilante escanea y registra avances
class DronVigilante
def escanear_flota
drones_activos = DronDB.where("estado = 'running' AND heartbeat < ?", 5.minutes.ago)
drones_activos.each do |dron|
# Marcar como zombie
dron.update(estado: 'zombie')
# Registrar en avances
DronAvance.create(
dron_id: dron.id,
paso: -1,
descripcion: "Dron detectado como zombie (heartbeat > 5min)",
estado: 'failed'
)
# Consolidar resumen en events (visible en Bitácora Web)
consolidar_resumen(dron.flujo_id)
end
end
def consolidar_resumen(flujo_id)
# Obtener todos los logs del flujo
logs = DronLog.where(flujo_id: flujo_id)
# Calcular estado consolidado
estado = if logs.all? { |l| l.estado == 'completed' }
'completed'
elsif logs.any? { |l| l.estado == 'failed' }
'failed'
else
'running'
end
# Actualizar/crear evento resumen (visible en Bitácora Web)
Evento.find_or_create_by(flujo_id: flujo_id).update(
descripcion: "Flujo #{flujo_id}: #{logs.count} drones - #{estado}",
estado: estado
)
end
end
Bitácora Web: Lo que el Usuario Ve
La Bitácora Web (http://localhost:5174/bitacoras/) muestra:
| Columna | Contenido |
|---|---|
| ID | ID del evento resumen |
| I | Hora de inicio del flujo |
| F | Hora de fin (si completado) |
| Descripción | Resumen consolidado (ej: "Backup nocturno: 4 drones completados") |
| J | Modo (P=Presencial, R=Remoto, A=Automático) |
| E | Estado (⏳, ✅, ❌) |
| Acc. | Acciones (ver detalle, reintentar) |
Al hacer clic en "ver detalle":
- Muestra tabla con drones individuales y su estado
- Muestra avances paso-a-paso del flujo
- Muestra métricas de rendimiento (tiempo, reintentos)
📊 Estado Actual (Línea Base — Auditoría 2026-04-09)
Herramientas Existentes
| Herramienta | Ubicación | Tipo | Estado |
|---|---|---|---|
dron.rb |
adn/tools/cli/dron.rb |
Dispatcher | ✅ Refactorizado |
dron/ejecutor.rb |
adn/tools/cli/dron/ejecutor.rb |
Ejecutor atómico | ⚠️ Bugs en bitácora web |
dron/vigilante.rb |
adn/tools/cli/dron/vigilante.rb |
Vigilante atómico | ⚠️ Bugs en consolidación |
dron/sanador.rb |
adn/tools/cli/dron/sanador.rb |
Sanador atómico | ⚠️ Bugs en reintentos |
dron/bitacora.rb |
adn/tools/cli/dron/bitacora.rb |
Bitácora atómica | ✅ Implementado |
dron/base.rb |
adn/tools/cli/dron/base.rb |
Módulo compartido | ✅ Implementado |
dron_db.rb |
adn/tools/db/core/dron_db.rb |
Acceso a DB | ⚠️ 3 bugs críticos |
dispatcher.rb |
adn/tools/cli/dron/dispatcher.rb |
Routing subcomandos | ⚠️ 1 bug crítico |
Capacidades Actuales
# Ejecutor (lanzar tarea con auto-bitácora)
./adn/tools/run dron lanzar --evento AUTO --nota "Backup" -- <cmd>
# Vigilante (ver flota)
./adn/tools/run dron flota
./adn/tools/run dron salud
./adn/tools/run dron estado <dron_id>
# Sanador (health check + limpiar + reintentar)
./adn/tools/run dron sanear --dry-run
./adn/tools/run dron limpiar
./adn/tools/run dron reintentar
🐛 Deuda Técnica Detectada (Auditoría 2026-04-09)
Bugs Críticos (crashes directos)
| # | Archivo | Línea | Bug | Impacto |
|---|---|---|---|---|
| B1 | dispatcher.rb |
214 | BitacorasDB::BitacoraDB.ejecutar() — método inexistente (debe ser .with_connection { |db| db.execute() }) |
dron estado <ID> crashea con NoMethodError |
| B2 | dron_db.rb |
178-179 | incrementar_reintentos hace doble .first (.first.to_h → Hash, luego .first sobre Hash = par [k,v]) |
Sanador crashea al reintentar drones |
| B3 | dron_db.rb |
231-232 | obtener_metricas mismo patrón de doble .first |
Consulta de métricas crashea |
Bugs Medios (fallan en ciertos flujos)
| # | Archivo | Línea | Bug | Impacto |
|---|---|---|---|---|
| B4 | dron_db.rb |
337-345 | limpiar_antiguos — DELETE sin RETURNING intenta leer ['count'] inexistente |
Limpieza reporta 0 siempre |
| B5 | dron_db.rb |
253 | actualizar_metricas — pasa Float donde PG espera INTERVAL |
Error de tipo al guardar métricas |
| B6 | sanador.rb |
27 | Time.now - dron['completed_at'] — el campo viene como String, no Time |
TypeError al calcular backoff |
| B7 | sanador.rb |
41 | Dron::Ejecutor.lanzar(...) sin require_relative 'ejecutor' |
NameError si se llama directamente |
Bugs Bajos (edge cases)
| # | Archivo | Línea | Bug | Impacto |
|---|---|---|---|---|
| B8 | sanador.rb |
41 | dron.dig('metadata', 'nota') — metadata es String JSON, no Hash |
Nota de reintento siempre nil |
| B9 | ejecutor.rb |
42-75 | Timeout nunca se aplica (falta Timeout.timeout() wrapping) |
Drones largos nunca se frenan |
| B10 | vigilante.rb |
141,143 | BitacorasDB::BitacoraDB.crear_evento(...) como método de clase (es de instancia) |
Consolidación de flujos falla silenciosamente |
| B11 | ejecutor.rb |
82-131 | registrar_bitacora con rescue genérico silencia todos los errores |
Fallos de bitácora web invisibles |
| B12 | dron.rb / base.rb |
30 / 27 | Logger: .instance (singleton) vs .new (instancia separada) |
Logs inconsistentes |
🔍 Brecha Principal: Visibilidad en Bitácora Web
Problema crítico: Los drones escriben en tablas internas (dron_logs) pero la Bitácora Web (bitacoras.events) no refleja su actividad.
CAPA 1 (dron_logs) CAPA 2 (events → Web)
┌─────────────────┐ ┌─────────────────┐
│ ✅ Drones │ ──?──→ │ ❌ La web no ve │
│ escriben acá │ │ nada │
└─────────────────┘ └─────────────────┘
↑
La flecha "vigilante consolida"
NO FUNCIONA por bugs B1, B10, B11
Causas raíz:
- El heartbeat solo actualiza
dron_logs.heartbeat(tabla interna), nuncaevents - El ejecutor tiene lógica de bitácora web pero falla silenciosamente (B11)
- El vigilante llama métodos de clase inexistentes (B10)
- Coexiste un sistema antiguo de scripts
.sh(que sí funcionaba) con el nuevo Ruby (que no)
Limitaciones Futuras (post-corrección)
| # | Limitación | Tipo | Impacto | Prioridad |
|---|---|---|---|---|
| 1 | Sin orquestación de flujos | Orquestador | No hay composición multi-paso | Media |
| 2 | Sin planificación (cron) | Planificador | Requiere lanzamiento manual | Alta |
| 3 | Sin notificaciones | Mensajero | Alertas manuales | Media |
| 4 | Sin dashboard web dedicado | Observabilidad | Solo CLI + Bitácora Web | Baja |
🗺️ Fases de Implementación
Fase 0: Infraestructura de Datos (Dron 0.5) — ✅ COMPLETA
Objetivo: Crear tablas internas para registro detallado de drones.
| ID | Tarea | Descripción | Estado |
|---|---|---|---|
| F0.T1 | Migración 003_dron_logs.sql |
Tabla bitacoras.dron_logs |
✅ Completa |
| F0.T2 | Migración 004_dron_avances.sql |
Tabla bitacoras.dron_avances |
✅ Completa |
| F0.T3 | Migración 005_dron_metricas.sql |
Tabla bitacoras.dron_metricas |
✅ Completa |
| F0.T4 | adn/tools/db/core/dron_db.rb |
Acceso a datos de drones | ✅ Completa |
| F0.T5 | Hooks DB-First | Auto-registro en dron_logs al lanzar | ✅ Completa |
Criterio de éxito: ✅ Drones registran actividad en tablas internas sin tocar events directamente.
Fase 1: Atomicidad — Separación de Responsabilidades (Dron 1.0) — ⚠️ CON DEUDA TÉCNICA
Objetivo: Refactorizar el monolito dron.rb en módulos atómicos especializados.
| ID | Tarea | Tipo de Dron | Estado |
|---|---|---|---|
| F1.T1 | dron/ejecutor.rb |
Ejecutor — lanza y monitorea comando | ⚠️ Bugs B9, B11 |
| F1.T2 | dron/vigilante.rb |
Vigilante — escanea flota, detecta zombies | ⚠️ Bug B10 |
| F1.T3 | dron/sanador.rb |
Sanador — re-intenta, limpia, notifica fallos | ⚠️ Bugs B6, B7, B8 |
| F1.T4 | dron/bitacora.rb |
Registrador — auto-bitácora (inicio/fin) | ✅ Completa |
| F1.T5 | dron/dispatcher.rb |
Dispatcher — routing de subcomandos | ⚠️ Bug B1 |
| F1.T6 | dron/base.rb |
Módulo compartido (atomisidad) | ✅ Completa |
| F1.T7 | dron_db.rb |
Capa de datos para drones | ⚠️ Bugs B2, B3, B4, B5 |
Criterio de éxito original: ✅ Cada módulo tiene una única responsabilidad. ~40% menos código.
Criterio revisado: ⚠️ La estructura atómica es correcta pero 12 bugs impiden operación confiable. Corregidos en Fase 1.5.
Fase 1.5: Visibilidad en Bitácora Web + Corrección de Bugs (Dron 1.1) — ✅ COMPLETA
Objetivo: Que los drones sean visibles desde la Bitácora Web y corregir toda la deuda técnica de Fase 1.
Problema que resuelve: Actualmente los drones son "fantasmas" — ejecutan tareas pero el usuario no puede ver su progreso desde la interfaz web principal. Solo escriben en tablas internas (dron_logs) pero nunca actualizan bitacoras.events de forma confiable.
Lo que el usuario debería ver en Bitácora Web:
┌─────┬───────┬───────┬─────────────────────────────────────────────┬───┬───┐
│ ID │ I │ F │ Descripción │ J │ E │
├─────┼───────┼───────┼─────────────────────────────────────────────┼───┼───┤
│1420 │ 02:00 │ │ 🛸 Backup nocturno (dron_020000_123) │ A │ ⏳│
│ │ │ │ ├─ Ejecutando: vzdump 103 --mode stop │ │ │
│ │ │ │ └─ ❤️ Heartbeat: hace 45s │ │ │
├─────┼───────┼───────┼─────────────────────────────────────────────┼───┼───┤
│1419 │ 01:30 │ 01:45 │ 🛸 Sync rclone (dron_013000_456) — ✅ 15m │ A │ ✅│
│ │ │ │ └─ Aterrizaje limpio — 2.3GB sincronizados │ │ │
└─────┴───────┴───────┴─────────────────────────────────────────────┴───┴───┘
| ID | Tarea | Descripción | Estado |
|---|---|---|---|
| F1.5.T1 | Corregir bugs críticos | Bugs B1, B2, B3 — crashes directos en dispatcher y dron_db | ✅ |
| F1.5.T2 | Corregir bugs medios | Bugs B4, B5, B6, B7 — fallos en sanador y métricas | ✅ |
| F1.5.T3 | Simplificar registrar_bitacora |
Reescribir el método del ejecutor: crear evento → heartbeat → cierre limpio | ✅ |
| F1.5.T4 | Heartbeat visible en web | Que el heartbeat cada 30s actualice events.descripcion con progreso |
✅ |
| F1.5.T5 | Eliminar sistema dual .sh/Ruby |
copiloto.rb y novato.rb deprecados, tmp/dron/ limpiado |
✅ |
| F1.5.T6 | Corregir bugs bajos | Bugs B8-B12 — edge cases y consistencia | ✅ |
Flujo corregido del Ejecutor:
Ejecutor.lanzar(cmd, nota)
│
├─ 1. Registrar en dron_logs (tabla interna) ──→ DronDB
├─ 2. Crear evento en events (Bitácora Web) ──→ 🌐 VISIBLE
│
├─ 3. Ejecutar comando con heartbeat thread:
│ loop cada 30s:
│ ├─ Actualizar dron_logs.heartbeat ──→ DronDB
│ └─ Actualizar events.descripcion ──→ 🌐 VISIBLE
│
├─ 4. Comando finaliza
├─ 5. Registrar fin en dron_logs ──→ DronDB
└─ 6. Cerrar evento en events (estado + hora fin) ──→ 🌐 VISIBLE
Criterio de éxito:
- Cada dron lanzado aparece inmediatamente en la Bitácora Web como evento
⏳ - El heartbeat actualiza la descripción del evento en web cada 30 segundos
- Al finalizar, el evento se cierra con
✅o❌, hora de fin, y duración dron estado <ID>,dron flota, ydron saludfuncionan sin crashes- Cero bugs críticos, cero bugs medios
Fase 2: Composición — Orquestación de Flujos (Dron 1.5)
Objetivo: Permitir composición de drones para flujos multi-paso.
| ID | Tarea | Descripción | Estado |
|---|---|---|---|
| F2.T1 | dron/orquestador.rb |
Ejecuta pasos secuenciales (--step) |
⏳ |
| F2.T2 | Condicionales | --on-error continue|abort|retry |
⏳ |
| F2.T3 | Paralelismo | --parallel para pasos independientes |
⏳ |
| F2.T4 | Contexto compartido | Variables entre pasos ($DRON_OUTPUT_N) |
⏳ |
Ejemplo:
./adn/tools/run dron orquestar \
--step "dron_ejecutor --cmd 'vzdump 103'" \
--step "dron_ejecutor --cmd 'rclone sync /bkps oneDrive:'" \
--step "dron_mensajero --notify 'Backup OK'" \
--on-error abort
Criterio de éxito: Flujos complejos se expresan como composición de drones simples.
Fase 3: Planificación — Drones Programados (Dron 2.0)
Objetivo: Ejecución automática según cron.
| ID | Tarea | Tipo de Dron | Estado |
|---|---|---|---|
| F3.T1 | dron/planificador.rb |
Planificador — lee cron y lanza drones | ⏳ |
| F3.T2 | Persistencia de schedules | ~/.claude/scheduled_tasks.json |
⏳ |
| F3.T3 | CLI schedules | schedule add|list|remove |
⏳ |
| F3.T4 | Integración CronCreate | SDK de Claude Code | ⏳ |
Criterio de éxito: Tareas recurrentes se lanzan automáticamente.
Fase 4: Inteligencia de Colmena — Comunicación entre Drones (Dron 3.0)
Objetivo: Drones se comunican y coordinan para resolver problemas.
| ID | Tarea | Descripción | Estado |
|---|---|---|---|
| F4.T1 | Cola de eventos | Redis o archivo compartido para eventos | ⏳ |
| F4.T2 | Publicar/ Suscribirse | Drones publican eventos, otros reaccionan | ⏳ |
| F4.T3 | Patrones de reacción | on failed → sanador, on completed → mensajero |
⏳ |
| F4.T4 | Feromonas digitales | Señales químicas virtuales (/tmp/dron_pheromones/) |
⏳ |
Ejemplo de flujo emergente:
1. Ejecutor falla → publica "failed" en cola
2. Sanador escucha → re-intenta (máx 3 veces)
3. Si falla → publica "critical"
4. Mensajero escucha → notifica por Slack
Criterio de éxito: Soluciones complejas emergen sin orquestador central.
Fase 5: Observabilidad — Dashboard y Métricas (Dron 4.0)
Objetivo: Visibilidad completa de la colonia.
| ID | Tarea | Tipo de Dron | Estado |
|---|---|---|---|
| F5.T1 | API /api/drones |
Endpoint para listar drones | ⏳ |
| F5.T2 | API /api/drones/:id/avances |
Endpoint para avances de un dron | ⏳ |
| F5.T3 | Dashboard web | http://localhost:5174/drones |
⏳ |
| F5.T4 | Gráficas | Tareas por día, tasa de éxito, tiempos | ⏳ |
| F5.T5 | Alertas proactivas | dron_vigilante detecta anomalías |
⏳ |
Criterio de éxito: Visibilidad completa vía web dashboard y métricas históricas.
🏗️ Arquitectura de Colmena
Diagrama de Flujo (Inteligencia de Colmena)
┌──────────────────────────────────────────────────────────────────┐
│ Dron::Base (módulo compartido - Atomisidad) │
│ - logger: Logger único │
│ - db_query/db_exec: Acceso a DB │
│ - utilidades: formato_duracion, slice_safe, blank? │
└─────────────┬────────────────────────────────────────────────────┘
│ extend Base (todos los drones)
┌─────────┼─────────┬─────────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│EJECUTOR│ │VIGILANTE│ │SANADOR│ │BITÁCORA │
│🛠️ │ │👁️ │ │🩹 │ │📝 │
│lanzar │ │flota │ │sanear │ │iniciar │
│ │ │salud │ │limpiar│ │finalizar │
└───┬────┘ └───┬────┘ └───┬────┘ └────┬─────┘
│ │ │ │
│ │ │ │ registra
│ │ │ ▼
│ │ │ ┌─────────────┐
│ │ │ │bitacoras. │
│ │ │ │events │
│ │ │ └─────────────┘
│ │ │
│ │ └─→ Re-intenta (máx 3, backoff)
│ │
│ └─→ Detecta zombies (heartbeat > 5min)
│ Consolida en events
│
└─→ Ejecuta cmd
Heartbeat cada 30s
Registra en dron_logs + events
Principios de Diseño
| Principio | Aplicación |
|---|---|
| Single Responsibility | Cada dron hace UNA cosa |
| Composability | Drones se ensamblan en flujos |
| Event-Driven | Comunicación vía cola de eventos |
| Stateless | Drones no guardan estado (efímeros) |
| Observable | Todo evento se registra en DB |
🔧 Componentes Implementados
Base Compartido (adn/tools/cli/dron/base.rb) — Atomisidad
| Componente | Propósito |
|---|---|
Base.logger |
Logger único para todos los drones |
Base.db_query |
Ejecuta SQL y retorna resultados |
Base.db_exec |
Ejecuta SQL sin retornar resultados |
Base.formato_duracion |
Formatea segundos a "Xmin Ys" |
Base.slice_safe |
Slice seguro de strings (evita nil) |
Base.blank? |
Verifica si string es nil/vacío |
Ejecutor (adn/tools/cli/dron/ejecutor.rb)
| Componente | Propósito |
|---|---|
Ejecutor.lanzar |
Ejecuta comando, heartbeat, reporta resultado |
Ejecutor#heartbeat |
Actualiza heartbeat cada 30s |
Ejecutor#registrar_bitacora |
Crea/actualiza evento en bitácora |
Vigilante (adn/tools/cli/dron/vigilante.rb)
| Componente | Propósito |
|---|---|
Vigilante.escanear_flota |
Lee dron_logs, muestra resumen |
Vigilante.salud |
Health check, detecta zombies y anomalías |
Vigilante.dashboard |
Dashboard compacto de la flota |
Vigilante.consolidar_flujo |
Consolidar estado de flujo en events |
Sanador (adn/tools/cli/dron/sanador.rb)
| Componente | Propósito |
|---|---|
Sanador.reintentar_fallidos |
Re-lanza failed (máx 3, backoff exponencial) |
Sanador.limpiar_antiguos |
Elimina completados > N días |
Sanador.sanear |
Saneamiento completo (reintentar + limpiar) |
Bitácora (adn/tools/cli/dron/bitacora.rb)
| Componente | Propósito |
|---|---|
Bitacora.iniciar |
Crea evento ⏳ en bitácora |
Bitacora.finalizar |
Actualiza evento con ✅ o ❌ |
Bitacora.auto |
Modo AUTO: inicia, ejecuta, finaliza |
Persistencia
| Archivo/Tabla | Tipo | Propósito | Visibilidad |
|---|---|---|---|
bitacoras.dron_logs |
Tabla DB | Logs detallados de cada dron | 🔒 Interna |
bitacoras.dron_avances |
Tabla DB | Progreso paso-a-paso de flujos | 🔒 Interna |
bitacoras.dron_metricas |
Tabla DB | Agregaciones y estadísticas | 🔒 Interna |
bitacoras.events |
Tabla DB | Eventos consolidados (resumen) | ✅ Bitácora Web |
/tmp/dron_flota/*.json |
Archivo | Estado de drones activos (runtime) | 🔒 CLI |
/tmp/dron_queue/*.json |
Archivo | Cola de eventos (por tipo) | 🔒 Drones |
/tmp/dron_pheromones/ |
Directorio | Señales químicas virtuales | 🔒 Drones |
~/.claude/scheduled_tasks.json |
Archivo | Schedules persistentes (cron) | 🔒 Planificador |
Modificar
| Archivo | Cambio |
|---|---|
adn/tools/cli/dron.rb |
Refactorizar → dispatcher que importa módulos |
adn/tools/run |
Registrar subcomandos: dron lanzar, dron orquestar, etc. |
adn/tools/db/core/bitacora_db.rb |
Hook para eventos AUTO (dron_bitacora) |
📝 Comandos por Tipo de Dron
Ejecutor
# Lanzar tarea simple (auto-bitácora)
./adn/tools/run dron lanzar --evento AUTO --nota "Backup SQL" -- vzdump 103
# Lanzar sin registro (efímero)
./adn/tools/run dron lanzar --no-bitacora --nota "Test rápido" -- echo hola
# Lanzar con timeout
./adn/tools/run dron lanzar --timeout 300 --nota "Sync larga" -- rclone sync ...
Orquestador (Composición)
# Flujo secuencial (backup → sync → notificar)
./adn/tools/run dron orquestar \
--step "dron lanzar --nota 'Backup' -- vzdump 103" \
--step "dron lanzar --nota 'Sync' -- rclone sync /bkps oneDrive:" \
--step "dron notificar --msg 'Backup completado'" \
--on-error abort
# Flujo paralelo (múltiples backups simultáneos)
./adn/tools/run dron orquestar \
--parallel \
--step "dron lanzar --nota 'Backup SQL' -- vzdump 103" \
--step "dron lanzar --nota 'Backup DC' -- vzdump 100" \
--step "dron lanzar --nota 'Backup PCV' -- vzdump 104"
Planificador (Cron)
# Agendar backup nocturno
./adn/tools/run dron schedule add \
--cron "0 2 * * *" \
--cmd "dron lanzar --evento AUTO --nota 'Backup nocturno' -- ./adn/tools/run bkps run C4 --batch"
# Listar schedules
./adn/tools/run dron schedule list
# Eliminar schedule
./adn/tools/run dron schedule remove <id>
Vigilante (Monitoreo)
# Dashboard de flota
./adn/tools/run dron flota
# Estado detallado de un dron
./adn/tools/run dron estado <tarea_id>
# Métricas históricas
./adn/tools/run dron metricas [--desde 2026-04-01] [--hasta 2026-04-07]
Sanador (Reparación)
# Health check (detecta zombies)
./adn/tools/run dron salud
# Reintentar fallidos
./adn/tools/run dron sanear --reintentar
# Limpiar completados
./adn/tools/run dron limpiar --mayor-a 24h
Mensajero (Notificaciones)
# Notificar por Slack
./adn/tools/run dron notificar --slack "#backups" "Backup completado ✅"
# Notificar por email
./adn/tools/run dron notificar --email "admin@frlr.utn.edu.ar" "Alerta de fallo"
🎯 Criterios de Éxito
Atomicidad (Fase 1)
- ✅ Cada dron tiene una única responsabilidad (Single Responsibility)
- ✅ Sin código duplicado entre módulos
- ✅ Tests independientes por tipo de dron
Composición (Fase 2)
- ✅ Flujos multi-paso se expresan como composición de drones
- ✅ Orquestador permite secuencial/paralelo/condicional
Inteligencia de Colmena (Fase 4)
- ✅ Drones se comunican vía cola de eventos
- ✅ Patrones de reacción emergen (failed → sanador → notificar)
- ✅ Sin orquestador central para reacciones automáticas
Observabilidad (Fase 5)
- ✅ Dashboard web muestra estado en tiempo real
- ✅ Histórico consultable vía CLI y web
- ✅ Alertas proactivas ante anomalías
📚 Referencias
Internas (ADN)
- Herramienta actual:
adn/tools/cli/dron.rb - A01.P006: Sensor de Mejora Continua — Dron como evolución del sensor
- A01 (dtic-ADN): Manifiesto de Ámbito — Marco de trabajo
- adn/06_gobernanza.md: Principios Rectores — Menos es Más
Externas (Inspiración)
- Swarm Intelligence: Comportamiento emergente en colonias de insectos
- Unix Philosophy: "Do one thing and do it well"
- Microservices: Servicios pequeños, composables, independientes
- Event-Driven Architecture: Comunicación asíncrona vía eventos
- CronCreate: SDK de Claude Code para schedules persistentes
DB-First
- Todas las métricas se almacenan en PostgreSQL (
bitacoras.dron_logs) - Dashboard web consume API → DB
🔄 Armonía Integral
Última actualización: 2026-04-09 — Auditoría + Fase 1.5 planificada
| Documento | Estado | Notas |
|---|---|---|
A01_dtic-ADN.md |
📍 Pendiente | Agregar A01.P009 a tabla de planes |
adn/07_proyectos.md |
📍 Pendiente | Referenciar nuevo plan |
docs/contexto/IA.md |
📍 Pendiente | Actualizar sección de drones |
adn/06_gobernanza.md |
✅ Alineado | Principio "Menos es Más" — AtomicDrones + Atomisidad |
📦 Entregables
Fase 1 (Estructura atómica — con deuda técnica)
| Archivo | Líneas | Descripción | Estado |
|---|---|---|---|
adn/tools/cli/dron/base.rb |
66 | Módulo compartido (atomisidad) | ✅ |
adn/tools/cli/dron/dispatcher.rb |
284 | Routing de subcomandos | ⚠️ B1 |
adn/tools/cli/dron/ejecutor.rb |
171 | Ejecutor atómico | ⚠️ B9, B11 |
adn/tools/cli/dron/vigilante.rb |
151 | Vigilante atómico | ⚠️ B10 |
adn/tools/cli/dron/sanador.rb |
85 | Sanador atómico | ⚠️ B6, B7, B8 |
adn/tools/cli/dron/bitacora.rb |
76 | Bitácora atómica | ✅ |
adn/tools/db/core/dron_db.rb |
351 | Acceso a datos DB | ⚠️ B2-B5 |
adn/tools/db/migrations/003_create_dron_tables.rb |
232 | Migración DB | ✅ |
Fase 1.5 (Pendiente — Visibilidad + Corrección)
Entregables esperados:
- Corrección de los 12 bugs detectados
- Heartbeat visible en Bitácora Web
- Eliminación del sistema dual
.sh/Ruby - Flujo ejecutor→events→web funcional y probado