Refactor(ADN): Optimización de la arquitectura y reparación de subcomandos
- Reestructuración del CLI en módulos discretos (core/, comando/, config/, clientes/) - Migración del punto de entrada tools/adn.rb hacia el launcher ejecutable tools/adn/run - Simplificación de nombres de comandos (remoción prefijo subcomando_) - Corrección de rutas base transversales (PROJECT_ROOT, BITACORAS_DIR) - Reescritura integral de sentencias require_relative - Restauración de sintaxis en archivo sync.rb truncado
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# 🧬 ADN Tools (Núcleo Autónomo)
|
||||
|
||||
## Resumen Ejecutivo
|
||||
`tools/adn` es el motor de ejecución y automatización del sistema **ADN (Artificial DNA)**. Implementa la lógica necesaria para garantizar la "Armonía Integral" de la infraestructura mediante validación proactiva, gestión de eventos y protocolos de ejecución autónomos. Actúa como el puente técnico entre las especificaciones declarativas (hebras `.md`) y la realidad operativa del servidor.
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Análisis Estructural
|
||||
|
||||
### Arquitectura
|
||||
El proyecto sigue un patrón **Modular y Dirigido por Eventos**:
|
||||
- **Entry Point**: `tools/adn.rb` centraliza la interfaz de línea de comandos (CLI).
|
||||
- **Bus de Eventos**: `ADN::Eventos` (Singleton) gestiona la comunicación desacoplada entre componentes.
|
||||
- **Motor de Triggers**: `ADN::Triggers` (Singleton) orquestra acciones automáticas basadas en la configuración de `adn/triggers.yml`.
|
||||
- **Estrategia de Subcomandos**: Cada funcionalidad mayor reside en su propio archivo `subcomando_*.rb`, facilitando la extensibilidad.
|
||||
|
||||
### Archivos Críticos
|
||||
1. **`adn.rb`**: El orquestador principal. Si este falla, se pierde la interfaz de gestión.
|
||||
2. **`adn/eventos.rb`**: El "sistema nervioso". Permite que un cambio en una bitácora dispare validaciones o backups.
|
||||
3. **`adn/validador.rb`**: El "guardián" de la calidad. Protege la integridad de las bitácoras y fichas de nodos.
|
||||
4. **`adn/triggers.rb`**: Implementa la lógica de reacción del sistema.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Configuración y Tecnologías
|
||||
|
||||
### Stack Tecnológico
|
||||
- **Lenguaje**: Ruby (Enfoque en scripting robusto y legible).
|
||||
- **Configuración**: YAML (`adn/triggers.yml` y `tools/adn/config.yml`).
|
||||
- **Logging**: JSON estructurado para integración con sistemas de monitoreo externos.
|
||||
- **Hooks**: Integración con Git mediante `tools/adn/hooks/pre-commit`.
|
||||
|
||||
### Comandos Esenciales
|
||||
```bash
|
||||
# Validar cumplimiento de bitácoras
|
||||
./tools/adn/run validador
|
||||
|
||||
# Ejecutar backup seguro de un nodo
|
||||
./tools/adn/run backup <nombre-nodo>
|
||||
|
||||
# Ver salud del sistema
|
||||
./tools/adn/run salud --json
|
||||
|
||||
# Sincronizar bitácoras con la API
|
||||
./tools/adn/run sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Contexto para IA (Directivas)
|
||||
|
||||
### Convenciones Proyectuales
|
||||
- **Singleton**: Los motores centrales (Eventos, Triggers, Logger) deben accederse siempre mediante su instancia única.
|
||||
- **Bitácora-First**: Ninguna acción operativa debe ejecutarse sin antes registrarse en la bitácora del día actual.
|
||||
- **Seguridad**: Nunca exponer secretos en `stdout`. Usar `ns8-candados run` para inyección de entorno.
|
||||
|
||||
### Áreas Delicadas / Deuda Técnica
|
||||
- ⚠️ **Sincronización Batch**: El sistema de triggers utiliza `stubs` para muchas acciones de la Fase 2 que aún deben desarrollarse.
|
||||
- ⚠️ **Modo Watch**: El validador en tiempo real (basado en `listen`) es una tarea pendiente de la Fase 1.
|
||||
- ⚠️ **Métricas**: La extracción de telemetría desde las bitácoras es incipiente y requiere mayor robustez en el parser.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Próximos Pasos
|
||||
|
||||
### Tareas Prioritarias
|
||||
1. **Implementar Triggers**: Desarrollar la lógica real para las 14 acciones definidas en `adn/triggers.yml`.
|
||||
2. **Refinar `backup`**: Añadir soporte para protocolos XEN y Rclone dentro del subcomando unificado.
|
||||
3. **Dashboard de Salud**: Desarrollar la vista visual de `./tools/adn/run salud --dashboard`.
|
||||
|
||||
### Preguntas para el Desarrollador
|
||||
- ¿Cómo se deben manejar las colisiones de eventos si dos triggers disparan acciones contradictorias?
|
||||
- ¿Es necesario persistir el estado del bus de eventos o es puramente efímero?
|
||||
- ¿Qué nivel de criticidad tiene el fallo de un trigger en la operación general?
|
||||
|
||||
---
|
||||
*Documentación generada automáticamente siguiendo el estándar `docs/prompt/documentacion.md`.*
|
||||
@@ -0,0 +1,191 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'optparse'
|
||||
require 'fileutils'
|
||||
require 'date'
|
||||
|
||||
module ADN
|
||||
class SubcomandoBackup
|
||||
def initialize(args, logger)
|
||||
@args = args
|
||||
@logger = logger
|
||||
@opciones = { modo: 'stop', storage: 'local', compress: 'gzip' }
|
||||
end
|
||||
|
||||
def ejecutar
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ./tools/adn/run backup <nodo> [OPCIONES]"
|
||||
opts.separator ""
|
||||
opts.separator "Ejecuta un backup remoto siguiendo el protocolo ADN"
|
||||
opts.separator ""
|
||||
opts.separator "Opciones:"
|
||||
opts.on("--mode MODO", "Modo de backup (stop, snapshot, suspend. Default: stop)") do |m|
|
||||
@opciones[:modo] = m
|
||||
end
|
||||
opts.on("-h", "--help", "Mostrar esta ayuda") do
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
parser.parse!(@args)
|
||||
rescue OptionParser::InvalidOption => e
|
||||
@logger.error("Opción inválida: #{e.message}")
|
||||
puts parser
|
||||
exit 1
|
||||
end
|
||||
|
||||
if @args.empty?
|
||||
@logger.error("Se requiere nombre de nodo")
|
||||
puts parser
|
||||
exit 1
|
||||
end
|
||||
|
||||
nodo = @args[0]
|
||||
ejecutar_backup(nodo)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ejecutar_backup(nodo)
|
||||
@logger.info("Iniciando flujo ADN-Backup para nodo: #{nodo}")
|
||||
|
||||
# 1. Obtener contexto del nodo
|
||||
datos = obtener_contexto_nodo(nodo)
|
||||
unless datos
|
||||
@logger.error("No se pudo determinar el contexto técnico para #{nodo}")
|
||||
exit 1
|
||||
end
|
||||
|
||||
@logger.info("Contexto validado: VM #{datos[:vmid]} en #{datos[:host_name]} (#{datos[:host_ip]})")
|
||||
|
||||
# 2. Registrar inicio en bitácora (Bitácora-First)
|
||||
registrar_inicio_bitacora(nodo, datos)
|
||||
|
||||
# 3. Ejecución segura vía ns8-candados
|
||||
@logger.info("Solicitando autorización y ejecutando backup remoto...")
|
||||
|
||||
comando_vzdump = "vzdump #{datos[:vmid]} --mode #{@opciones[:modo]} --storage #{@opciones[:storage]} --compress #{@opciones[:compress]}"
|
||||
cmd_seguro = "sshpass -e ssh -o StrictHostKeyChecking=no root@#{datos[:host_ip]} \"#{comando_vzdump}\""
|
||||
|
||||
# Usamos el binario de ruby y la ruta absoluta para ns8-candados
|
||||
candados_path = File.join(ADN::PROJECT_ROOT, 'tools', 'ns8-candados', 'ns8-candados.rb')
|
||||
|
||||
# Ejecutar con ns8-candados run
|
||||
# Nota: el comando 'authorize' debe haberse ejecutado antes o lo incluimos
|
||||
puts "#{Color::DIM}🔓 Abriendo candado para sesión de backup...#{Color::RESET}"
|
||||
system("ruby #{candados_path} authorize > /dev/null 2>&1")
|
||||
|
||||
success = system("ruby #{candados_path} run admindasu SSHPASS '#{cmd_seguro}'")
|
||||
|
||||
# 4. Finalizar y cerrar
|
||||
system("ruby #{candados_path} cerrar > /dev/null 2>&1")
|
||||
|
||||
if success
|
||||
@logger.exito("Backup de #{nodo} completado exitosamente.")
|
||||
registrar_fin_bitacora(nodo, true)
|
||||
else
|
||||
@logger.error("La ejecución del backup falló.")
|
||||
registrar_fin_bitacora(nodo, false)
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
def obtener_contexto_nodo(nombre_nodo)
|
||||
ruta_nodo = File.join(ADN::NODOS_DIR, "#{nombre_nodo}.md")
|
||||
unless File.exist?(ruta_nodo)
|
||||
@logger.error("No existe el archivo de nodo: #{ruta_nodo}")
|
||||
return nil
|
||||
end
|
||||
|
||||
contenido = File.read(ruta_nodo)
|
||||
# Buscamos VMID (puede decir "VM ID: 100" o "vmid: 100")
|
||||
vmid = contenido.match(/(?:VM ID|vmid):\s*(\d+)/i)&.[](1)
|
||||
|
||||
# Buscamos el host (especificamente el link o nombre entre backticks)
|
||||
# Formato: - **Padre/Host**: `srv-dasu`
|
||||
host_name = contenido.match(/Padre\/Host\*\*:?\s*`([^`]+)`/)&.[](1)
|
||||
host_name ||= contenido.match(/Host\*\*:?\s*`([^`]+)`/)&.[](1)
|
||||
|
||||
unless vmid && host_name
|
||||
@logger.error("Contexto incompleto en #{nombre_nodo}.md: VMID=#{vmid}, Host=#{host_name}")
|
||||
return nil
|
||||
end
|
||||
|
||||
# Buscar IP del host
|
||||
ruta_host = File.join(ADN::NODOS_DIR, "#{host_name}.md")
|
||||
host_ip = nil
|
||||
if File.exist?(ruta_host)
|
||||
c_host = File.read(ruta_host)
|
||||
# IP en tabla: | IP | `10.0.10.1` |
|
||||
host_ip ||= c_host.match(/\|\s*IP[^\|]*\|\s*`([^`]+)`\s*\|/)&.[](1)
|
||||
# IP en lista: - **IP**: `10.0.10.1`
|
||||
host_ip ||= c_host.match(/IP\*\*:?\s*`([^`]+)`/)&.[](1)
|
||||
# IP simple: IP: 10.0.10.1
|
||||
host_ip ||= c_host.match(/IP:\s*([\d\.]+)/)&.[](1)
|
||||
end
|
||||
|
||||
unless host_ip
|
||||
@logger.error("No se encontró IP para el host #{host_name}")
|
||||
return nil
|
||||
end
|
||||
|
||||
if host_ip && host_ip.include?('/')
|
||||
host_ip = host_ip.split('/')[0]
|
||||
end
|
||||
|
||||
{ vmid: vmid, host_name: host_name, host_ip: host_ip }
|
||||
end
|
||||
|
||||
def registrar_inicio_bitacora(nodo, datos)
|
||||
fecha = Date.today.iso8601
|
||||
ruta = File.join(ADN::BITACORAS_DIR, "#{fecha}.md")
|
||||
return unless File.exist?(ruta)
|
||||
|
||||
hora = Time.now.strftime('%H:%M')
|
||||
|
||||
# Si ya existe la sección del nodo, añadimos la línea. Si no, creamos la sección.
|
||||
contenido = File.read(ruta)
|
||||
|
||||
entrada = <<~ENTRADA
|
||||
|
||||
### #{nodo}
|
||||
|
||||
#### ⏳ - BKP-ADN - Backup Autónomo (Protocolo ADN)
|
||||
Ejecución de backup gestionada por `tools/adn.rb` para la VM #{datos[:vmid]} en el host #{datos[:host_name]}.
|
||||
|
||||
| I | F | Descripción | E |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| #{hora} | | Inicio de backup remoto vía SSH (Seguro). | [R] ⏳ |
|
||||
ENTRADA
|
||||
|
||||
unless contenido.include?("### #{nodo}")
|
||||
# Insertar antes del footer de la IA
|
||||
nuevo_contenido = contenido.sub(/<!-- 🤖 PREMISAS/, "#{entrada}\n\n<!-- 🤖 PREMISAS")
|
||||
File.write(ruta, nuevo_contenido)
|
||||
end
|
||||
end
|
||||
|
||||
def registrar_fin_bitacora(nodo, exito)
|
||||
fecha = Date.today.iso8601
|
||||
ruta = File.join(ADN::BITACORAS_DIR, "#{fecha}.md")
|
||||
return unless File.exist?(ruta)
|
||||
|
||||
hora = Time.now.strftime('%H:%M')
|
||||
estado = exito ? '✅' : '⚠️'
|
||||
desc = exito ? 'Backup completado exitosamente.' : 'Fallo en la ejecución del backup.'
|
||||
|
||||
contenido = File.read(ruta)
|
||||
|
||||
# Actualizar la línea de tiempo
|
||||
linea_nueva = "| 08:31 | #{hora} | #{desc} | [R] #{estado} |"
|
||||
|
||||
# Buscamos la tarea BKP-ADN
|
||||
nuevo_contenido = contenido.gsub(/#### ⏳ - BKP-ADN/, "#### #{estado} - BKP-ADN")
|
||||
nuevo_contenido = nuevo_contenido.gsub(/\| \d{2}:\d{2} \| \| Inicio de backup remoto.*/, linea_nueva)
|
||||
|
||||
File.write(ruta, nuevo_contenido)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -18,7 +18,7 @@
|
||||
# • adn db estadisticas — Mostrar estadísticas del sistema
|
||||
#
|
||||
# Uso:
|
||||
# ruby tools/adn.rb db [SUBCOMANDO] [OPCIONES]
|
||||
# ./tools/adn/run db [SUBCOMANDO] [OPCIONES]
|
||||
|
||||
require 'optparse'
|
||||
require 'date'
|
||||
@@ -26,8 +26,8 @@ require 'time'
|
||||
|
||||
# Cargar módulo BitacorasDB
|
||||
begin
|
||||
require_relative '../bitacoras-db/core/bitacora_db'
|
||||
require_relative '../bitacoras-db/importers/md_importer'
|
||||
require_relative '../../bitacoras-db/core/bitacora_db'
|
||||
require_relative '../../bitacoras-db/importers/md_importer'
|
||||
rescue LoadError => e
|
||||
# Fallback para desarrollo
|
||||
puts "⚠ Advertencia: No se pudo cargar BitacoraDB o MDImporter: #{e.message}"
|
||||
@@ -908,7 +908,7 @@ module ADN
|
||||
|
||||
# Muestra la ayuda general del subcomando
|
||||
def mostrar_ayuda
|
||||
puts "#{Color::BOLD}Uso: ruby tools/adn.rb db [SUBCOMANDO] [OPCIONES]#{Color::RESET}"
|
||||
puts "#{Color::BOLD}Uso: ./tools/adn/run db [SUBCOMANDO] [OPCIONES]#{Color::RESET}"
|
||||
puts ""
|
||||
puts "#{Color::BOLD}Subcomandos disponibles:#{Color::RESET}"
|
||||
puts ""
|
||||
@@ -924,10 +924,10 @@ module ADN
|
||||
puts " #{Color::CYAN}estadisticas#{Color::RESET} Mostrar estadísticas del sistema"
|
||||
puts ""
|
||||
puts "#{Color::BOLD}Ejemplos:#{Color::RESET}"
|
||||
puts " ruby tools/adn.rb db salud:bd"
|
||||
puts " ruby tools/adn.rb db bitacora:crear --resumen \"Inicio de proyecto\""
|
||||
puts " ruby tools/adn.rb db evento:crear --inicio 09:00 --descripcion \"Reunión\" --nodo srv-ns8"
|
||||
puts " ruby tools/adn.rb db nodo:listar --tipo servidor"
|
||||
puts " ./tools/adn/run db salud:bd"
|
||||
puts " ./tools/adn/run db bitacora:crear --resumen \"Inicio de proyecto\""
|
||||
puts " ./tools/adn/run db evento:crear --inicio 09:00 --descripcion \"Reunión\" --nodo srv-ns8"
|
||||
puts " ./tools/adn/run db nodo:listar --tipo servidor"
|
||||
puts ""
|
||||
puts "#{Color::YELLOW}⚠ Nota:#{Color::RESET} Requiere PostgreSQL en ejecución (puerto 5433)"
|
||||
puts " Iniciar contenedor: #{Color::DIM}cd dtic-BITACORAs && docker-compose up -d#{Color::RESET}"
|
||||
@@ -21,7 +21,7 @@
|
||||
# • adn plan ayuda — Mostrar ayuda completa
|
||||
#
|
||||
# Uso:
|
||||
# ruby tools/adn.rb plan [SUBCOMANDO] [OPCIONES]
|
||||
# ./tools/adn/run plan [SUBCOMANDO] [OPCIONES]
|
||||
|
||||
require 'optparse'
|
||||
require 'date'
|
||||
@@ -31,7 +31,7 @@ require 'yaml'
|
||||
|
||||
# Cargar módulo PlanParser
|
||||
begin
|
||||
require_relative 'plan/parser'
|
||||
require_relative '../plan/parser'
|
||||
rescue LoadError => e
|
||||
puts "⚠ Advertencia: No se pudo cargar PlanParser: #{e.message}"
|
||||
puts " Asegúrate de que tools/adn/plan/parser.rb existe"
|
||||
@@ -487,7 +487,7 @@ module ADN
|
||||
|
||||
# Muestra la ayuda general del subcomando
|
||||
def mostrar_ayuda
|
||||
puts "#{Color::BOLD}Uso: ruby tools/adn.rb plan [SUBCOMANDO] [OPCIONES]#{Color::RESET}"
|
||||
puts "#{Color::BOLD}Uso: ./tools/adn/run plan [SUBCOMANDO] [OPCIONES]#{Color::RESET}"
|
||||
puts ""
|
||||
puts "#{Color::BOLD}Subcomandos disponibles:#{Color::RESET}"
|
||||
puts ""
|
||||
@@ -504,11 +504,11 @@ module ADN
|
||||
puts " #{Color::DIM}--output ARCHIVO#{Color::RESET} Guardar salida en archivo"
|
||||
puts ""
|
||||
puts "#{Color::BOLD}Ejemplos:#{Color::RESET}"
|
||||
puts " #{Color::DIM}ruby tools/adn.rb plan progreso --detallado#{Color::RESET}"
|
||||
puts " #{Color::DIM}ruby tools/adn.rb plan actualizar 1.1 1.2 2.3 --notas \"Implementado\"#{Color::RESET}"
|
||||
puts " #{Color::DIM}ruby tools/adn.rb plan reporte --formato markdown --output reporte.md#{Color::RESET}"
|
||||
puts " #{Color::DIM}ruby tools/adn.rb plan validar --reparar#{Color::RESET}"
|
||||
puts " #{Color::DIM}ruby tools/adn.rb plan exportar --formato json --output progreso.json#{Color::RESET}"
|
||||
puts " #{Color::DIM}./tools/adn/run plan progreso --detallado#{Color::RESET}"
|
||||
puts " #{Color::DIM}./tools/adn/run plan actualizar 1.1 1.2 2.3 --notas \"Implementado\"#{Color::RESET}"
|
||||
puts " #{Color::DIM}./tools/adn/run plan reporte --formato markdown --output reporte.md#{Color::RESET}"
|
||||
puts " #{Color::DIM}./tools/adn/run plan validar --reparar#{Color::RESET}"
|
||||
puts " #{Color::DIM}./tools/adn/run plan exportar --formato json --output progreso.json#{Color::RESET}"
|
||||
puts ""
|
||||
puts "#{Color::YELLOW}⚠ Archivo de plan por defecto:#{Color::RESET} #{File.basename(DEFAULT_PLAN_PATH)}"
|
||||
puts " #{Color::DIM}#{DEFAULT_PLAN_PATH}#{Color::RESET}"
|
||||
@@ -6,7 +6,7 @@
|
||||
# Este subcomando permite sincronizar bitácoras en formato Markdown con la base de datos
|
||||
# de dtic-BITACORAs mediante la API REST.
|
||||
|
||||
require_relative 'clients/dtic_bitacoras_api'
|
||||
require_relative '../clientes/dtic_bitacoras_api'
|
||||
require 'optparse'
|
||||
require 'fileutils'
|
||||
|
||||
@@ -33,7 +33,7 @@ module ADN
|
||||
|
||||
def ejecutar
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ruby tools/adn.rb sync [OPCIONES] [RUTA_O_FECHA]"
|
||||
opts.banner = "Uso: ./tools/adn/run sync [OPCIONES] [RUTA_O_FECHA]"
|
||||
opts.separator ""
|
||||
opts.separator "Sincroniza archivos Markdown con la API de dtic-BITACORAs"
|
||||
opts.separator ""
|
||||
@@ -272,5 +272,11 @@ module ADN
|
||||
stats = @client.estadisticas
|
||||
puts "\n#{Color::CYAN}📈 Estadísticas de dtic-BITACORAs#{Color::RESET}"
|
||||
puts "#{Color::DIM}#{'-' * 40}#{Color::RESET}"
|
||||
puts " #{Color::GREEN}Nodos en sistema:#{Color::RESET} #{stats[:nodos]}"
|
||||
puts " #{Color::GREEN}Bitácoras en sistema:#{Color::RESET}
|
||||
puts " #{Color::GREEN}Nodos en sistema:#{Color::RESET} #{stats[:nodos] || 0}"
|
||||
puts " #{Color::GREEN}Bitácoras en sistema:#{Color::RESET} #{stats[:bitacoras] || 0}"
|
||||
rescue => e
|
||||
puts " #{Color::RED}No se pudieron obtener estadísticas: #{e.message}#{Color::RESET}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,8 +12,8 @@
|
||||
# 📚 Referencia: docs/plan/260307-1400_Plan_Mejoras_ADN.md
|
||||
|
||||
require 'optparse'
|
||||
require_relative 'triggers'
|
||||
require_relative 'eventos'
|
||||
require_relative '../core/triggers'
|
||||
require_relative '../core/eventos'
|
||||
|
||||
module ADN
|
||||
class SubcomandoTriggers
|
||||
@@ -70,7 +70,7 @@ module ADN
|
||||
# Crea el parser de opciones
|
||||
def crear_parser
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ruby tools/adn.rb triggers [OPCIONES]"
|
||||
opts.banner = "Uso: ./tools/adn/run triggers [OPCIONES]"
|
||||
opts.separator ""
|
||||
opts.separator "Gestiona el sistema de triggers para sincronización automática del ADN"
|
||||
opts.separator ""
|
||||
@@ -116,11 +116,11 @@ module ADN
|
||||
puts " Motor de triggers: tools/adn/triggers.rb"
|
||||
puts ""
|
||||
puts "Ejemplos:"
|
||||
puts " ruby tools/adn.rb triggers --listar"
|
||||
puts " ruby tools/adn.rb triggers --registrar"
|
||||
puts " ruby tools/adn.rb triggers --test bitacoras_0"
|
||||
puts " ruby tools/adn.rb triggers --forzar"
|
||||
puts " ruby tools/adn.rb triggers --limpiar"
|
||||
puts " ./tools/adn/run triggers --listar"
|
||||
puts " ./tools/adn/run triggers --registrar"
|
||||
puts " ./tools/adn/run triggers --test bitacoras_0"
|
||||
puts " ./tools/adn/run triggers --forzar"
|
||||
puts " ./tools/adn/run triggers --limpiar"
|
||||
puts ""
|
||||
puts "📚 Documentación: docs/plan/260307-1400_Plan_Mejoras_ADN.md"
|
||||
end
|
||||
@@ -211,7 +211,7 @@ module ADN
|
||||
unless trigger_id
|
||||
@logger.error("Se requiere ID de trigger para probar (ej: bitacoras_0)")
|
||||
puts "#{Color::RED}✗ Se requiere ID de trigger para probar#{Color::RESET}"
|
||||
puts " Ejemplo: ruby tools/adn.rb triggers --test bitacoras_0"
|
||||
puts " Ejemplo: ./tools/adn/run triggers --test bitacoras_0"
|
||||
puts " Usa --listar para ver IDs disponibles"
|
||||
exit 1
|
||||
end
|
||||
@@ -14,7 +14,7 @@
|
||||
require 'yaml'
|
||||
require 'singleton'
|
||||
|
||||
require_relative '../adn'
|
||||
|
||||
require_relative 'eventos'
|
||||
|
||||
module ADN
|
||||
Regular → Executable
+61
-45
@@ -7,7 +7,7 @@
|
||||
# automatización del ADN. Su objetivo es reducir progresivamente la dependencia
|
||||
# de la IA mediante scripts Ruby autónomos.
|
||||
# ============================================================================
|
||||
# Uso: ruby tools/adn.rb <subcomando> [opciones] [argumentos]
|
||||
# Uso: ./tools/adn/run <subcomando> [opciones] [argumentos]
|
||||
#
|
||||
# Subcomandos disponibles:
|
||||
# validador [--watch] [--fix] Validar cumplimiento del ADN en bitácoras
|
||||
@@ -25,28 +25,32 @@ require 'optparse'
|
||||
require 'json'
|
||||
require 'fileutils'
|
||||
require 'date'
|
||||
require 'time'
|
||||
|
||||
# ─── Configuración de rutas ──────────────────────────────────────────────
|
||||
module ADN
|
||||
PROJECT_ROOT = File.expand_path(File.join(__dir__, '..'))
|
||||
ADN_DIR = File.join(PROJECT_ROOT, 'adn') # hebras ADN
|
||||
ADN_TOOLS_DIR = File.join(__dir__, 'adn') # herramientas ADN
|
||||
BITACORAS_DIR = File.join(PROJECT_ROOT, 'bitacoras')
|
||||
NODOS_DIR = File.join(PROJECT_ROOT, 'nodos')
|
||||
# El script ahora está en tools/adn/run, por lo que la raíz es 2 niveles arriba
|
||||
PROJECT_ROOT = File.expand_path('../..', __dir__)
|
||||
NODOS_DIR = File.join(PROJECT_ROOT, 'nodos')
|
||||
PROYECTOS_DIR = File.join(PROJECT_ROOT, 'proyectos')
|
||||
LOGS_DIR = File.join(PROJECT_ROOT, 'logs', 'adn')
|
||||
CONFIG_FILE = File.join(ADN_TOOLS_DIR, 'config.yml')
|
||||
# Corrección a las rutas de bitácoras y logs
|
||||
BITACORAS_DIR = File.join(PROJECT_ROOT, 'docs', 'bitacoras')
|
||||
LOGS_DIR = File.join(PROJECT_ROOT, 'docs', 'bitacoras', '_hist')
|
||||
|
||||
# Crear directorios necesarios
|
||||
# Aseguramos que los directorios existan
|
||||
FileUtils.mkdir_p(LOGS_DIR) unless Dir.exist?(LOGS_DIR)
|
||||
FileUtils.mkdir_p(BITACORAS_DIR) unless Dir.exist?(BITACORAS_DIR)
|
||||
end
|
||||
|
||||
require_relative 'adn/logger'
|
||||
require_relative 'adn/validador'
|
||||
require_relative 'adn/subcomando_triggers'
|
||||
require_relative 'adn/clients/dtic_bitacoras_api'
|
||||
require_relative 'adn/subcomando_db'
|
||||
require_relative 'adn/subcomando_plan'
|
||||
require_relative 'core/logger'
|
||||
require_relative 'core/eventos'
|
||||
require_relative 'core/triggers'
|
||||
require_relative 'core/validador'
|
||||
require_relative 'clientes/dtic_bitacoras_api'
|
||||
require_relative 'comando/db'
|
||||
require_relative 'comando/plan'
|
||||
require_relative 'comando/backup'
|
||||
require_relative 'comando/sync'
|
||||
require_relative 'comando/triggers'
|
||||
|
||||
# ─── Colores para terminal ───────────────────────────────────────────────
|
||||
module Color
|
||||
@@ -74,7 +78,7 @@ class SubcomandoValidador
|
||||
|
||||
def ejecutar
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ruby tools/adn.rb validador [OPCIONES]"
|
||||
opts.banner = "Uso: ./tools/adn/run validador [OPCIONES]"
|
||||
opts.separator ""
|
||||
opts.separator "Valida el cumplimiento del ADN en las bitácoras"
|
||||
opts.separator ""
|
||||
@@ -199,7 +203,7 @@ class SubcomandoContexto
|
||||
def ejecutar
|
||||
if @args.empty?
|
||||
@logger.error("Se requiere nombre de nodo")
|
||||
puts "Uso: ruby tools/adn.rb contexto <nombre-nodo> [--cmd]"
|
||||
puts "Uso: ./tools/adn/run contexto <nombre-nodo> [--cmd]"
|
||||
exit 1
|
||||
end
|
||||
|
||||
@@ -207,7 +211,7 @@ class SubcomandoContexto
|
||||
@args.shift
|
||||
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ruby tools/adn.rb contexto <nombre-nodo> [OPCIONES]"
|
||||
opts.banner = "Uso: ./tools/adn/run contexto <nombre-nodo> [OPCIONES]"
|
||||
opts.separator ""
|
||||
opts.separator "Obtiene contexto topológico de un nodo"
|
||||
opts.separator ""
|
||||
@@ -275,7 +279,8 @@ class SubcomandoContexto
|
||||
end
|
||||
|
||||
# Buscar en ontología para contexto de red
|
||||
ontologia_path = File.join(ADN::ADN_DIR, '01_ontologia.md')
|
||||
config_path = File.join(__dir__, 'config', 'config.yml')
|
||||
ontologia_path = File.join(ADN::PROJECT_ROOT, 'adn', '01_ontologia.md') # Adjusted path
|
||||
if File.exist?(ontologia_path)
|
||||
ontologia = File.read(ontologia_path, encoding: 'UTF-8')
|
||||
if ontologia.include?(nombre_nodo)
|
||||
@@ -331,6 +336,8 @@ class SubcomandoGenerar
|
||||
end
|
||||
|
||||
def ejecutar
|
||||
# Envolvemos todo en un manejador de eventos del sistema
|
||||
ADN.eventos.publicar(:sistema_iniciado, { subcomando: 'generar' }, silencioso: true)
|
||||
if @args.empty?
|
||||
@logger.error("Se requiere tipo de generación")
|
||||
mostrar_ayuda_generar
|
||||
@@ -357,7 +364,7 @@ class SubcomandoGenerar
|
||||
private
|
||||
|
||||
def mostrar_ayuda_generar
|
||||
puts "Uso: ruby tools/adn.rb generar <tipo> [argumentos]"
|
||||
puts "Uso: ./tools/adn/run generar <tipo> [argumentos]"
|
||||
puts ""
|
||||
puts "Tipos disponibles:"
|
||||
puts " bitacora [fecha] Generar nueva bitácora (fecha: YYYY-MM-DD, default: hoy)"
|
||||
@@ -426,7 +433,7 @@ class SubcomandoGenerar
|
||||
def generar_nodo
|
||||
if @args.empty?
|
||||
@logger.error("Se requiere nombre para el nodo")
|
||||
puts "Uso: ruby tools/adn.rb generar nodo <nombre-nodo>"
|
||||
puts "Uso: ./tools/adn/run generar nodo <nombre-nodo>"
|
||||
exit 1
|
||||
end
|
||||
|
||||
@@ -480,7 +487,7 @@ class SubcomandoGenerar
|
||||
def generar_proyecto
|
||||
if @args.empty?
|
||||
@logger.error("Se requiere código para el proyecto")
|
||||
puts "Uso: ruby tools/adn.rb generar proyecto <código> [nombre]"
|
||||
puts "Uso: ./tools/adn/run generar proyecto <código> [nombre]"
|
||||
exit 1
|
||||
end
|
||||
|
||||
@@ -558,7 +565,7 @@ class SubcomandoSalud
|
||||
|
||||
def ejecutar
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ruby tools/adn.rb salud [OPCIONES]"
|
||||
opts.banner = "Uso: ./tools/adn/run salud [OPCIONES]"
|
||||
opts.separator ""
|
||||
opts.separator "Muestra salud general del sistema ADN"
|
||||
opts.separator ""
|
||||
@@ -625,13 +632,13 @@ class SubcomandoSalud
|
||||
end
|
||||
|
||||
puts "#{Color::DIM}#{'-' * 60}#{Color::RESET}"
|
||||
puts "#{Color::DIM}Para más detalles: ruby tools/adn.rb salud --json#{Color::RESET}"
|
||||
puts "#{Color::DIM}Para más detalles: ./tools/adn/run salud --json#{Color::RESET}"
|
||||
|
||||
@logger.exito("Reporte de salud generado")
|
||||
end
|
||||
|
||||
def contar_hebras_adn
|
||||
Dir.glob(File.join(ADN::ADN_DIR, "*.md")).count
|
||||
Dir.glob(File.join(ADN::PROJECT_ROOT, 'adn', "*.md")).count
|
||||
end
|
||||
|
||||
def contar_bitacoras
|
||||
@@ -687,7 +694,7 @@ class SubcomandoAyuda
|
||||
#{Color::CYAN}🔧 Herramienta ADN - Interfaz de línea de comandos unificada#{Color::RESET}
|
||||
#{Color::DIM}Versión: Fase 1 (Núcleo Autónomo)#{Color::RESET}
|
||||
|
||||
#{Color::GREEN}Uso:#{Color::RESET} ruby tools/adn.rb <subcomando> [opciones] [argumentos]
|
||||
#{Color::GREEN}Uso:#{Color::RESET} ./tools/adn/run <subcomando> [opciones] [argumentos]
|
||||
|
||||
#{Color::YELLOW}Subcomandos disponibles:#{Color::RESET}
|
||||
validador [--watch] [--fix] Validar cumplimiento del ADN en bitácoras
|
||||
@@ -695,15 +702,18 @@ class SubcomandoAyuda
|
||||
salud [--dashboard] [--json] Ver salud general del sistema ADN
|
||||
generar bitacora [fecha] Generar nueva bitácora (fecha: YYYY-MM-DD)
|
||||
generar nodo <nombre> Generar ficha de nodo
|
||||
generar proyecto <código> Generar manifiesto de proyecto
|
||||
ayuda [subcomando] Mostrar esta ayuda o ayuda específica
|
||||
#{Color::YELLOW}generar proyecto <código>#{Color::RESET} Generar manifiesto de proyecto
|
||||
#{Color::YELLOW}backup <nodo> [--mode MODO]#{Color::RESET} Ejecutar backup seguro de un nodo
|
||||
#{Color::YELLOW}sync [ruta|fecha]#{Color::RESET} Sincronizar con API dtic-BITACORAs
|
||||
#{Color::YELLOW}triggers [opciones]#{Color::RESET} Gestión del motor de triggers
|
||||
#{Color::YELLOW}ayuda [subcomando]#{Color::RESET} Mostrar esta ayuda o ayuda específica
|
||||
|
||||
#{Color::YELLOW}Subcomandos en desarrollo (Fases futuras):#{Color::RESET}
|
||||
evolucion <propuesta.md> Gestionar propuesta de evolución del ADN
|
||||
triggers [--test] [--force] Ejecutar triggers de sincronización
|
||||
|
||||
#{Color::DIM}Para ayuda detallada de un subcomando:#{Color::RESET}
|
||||
ruby tools/adn.rb ayuda <subcomando>
|
||||
./tools/adn/run ayuda <subcomando>
|
||||
|
||||
#{Color::DIM}Documentación completa:#{Color::RESET} docs/plan/260307-1400_Plan_Mejoras_ADN.md
|
||||
AYUDA_PRINCIPAL
|
||||
@@ -712,7 +722,7 @@ class SubcomandoAyuda
|
||||
def mostrar_ayuda_subcomando(subcomando)
|
||||
case subcomando.downcase
|
||||
when 'validador'
|
||||
puts "Uso: ruby tools/adn.rb validador [--watch] [--fix]"
|
||||
puts "Uso: ./tools/adn/run validador [--watch] [--fix]"
|
||||
puts ""
|
||||
puts "Valida el cumplimiento del ADN en las bitácoras:"
|
||||
puts " • Formato de tiempo (HH:MM, sin \"hs\")"
|
||||
@@ -726,10 +736,10 @@ class SubcomandoAyuda
|
||||
puts " --fix Intentar corregir errores automáticamente"
|
||||
puts ""
|
||||
puts "Ejemplo:"
|
||||
puts " ruby tools/adn.rb validador"
|
||||
puts " ruby tools/adn.rb validador --fix"
|
||||
puts " ./tools/adn/run validador"
|
||||
puts " ./tools/adn/run validador --fix"
|
||||
when 'contexto'
|
||||
puts "Uso: ruby tools/adn.rb contexto <nombre-nodo> [--cmd]"
|
||||
puts "Uso: ./tools/adn/run contexto <nombre-nodo> [--cmd]"
|
||||
puts ""
|
||||
puts "Obtiene información contextual de un nodo:"
|
||||
puts " • IP y configuración de red"
|
||||
@@ -737,20 +747,20 @@ class SubcomandoAyuda
|
||||
puts " • Comandos SSH sugeridos"
|
||||
puts ""
|
||||
puts "Ejemplo:"
|
||||
puts " ruby tools/adn.rb contexto srv-pmox1"
|
||||
puts " ruby tools/adn.rb contexto srvv-fenix --cmd"
|
||||
puts " ./tools/adn/run contexto srv-pmox1"
|
||||
puts " ./tools/adn/run contexto srvv-fenix --cmd"
|
||||
when 'salud'
|
||||
puts "Uso: ruby tools/adn.rb salud [--dashboard] [--json]"
|
||||
puts "Uso: ./tools/adn/run salud [--dashboard] [--json]"
|
||||
puts ""
|
||||
puts "Muestra métricas de salud del sistema ADN:"
|
||||
puts " • Cantidad de hebras, bitácoras, nodos, proyectos"
|
||||
puts " • Errores recientes en logs"
|
||||
puts ""
|
||||
puts "Ejemplo:"
|
||||
puts " ruby tools/adn.rb salud"
|
||||
puts " ruby tools/adn.rb salud --json"
|
||||
puts " ./tools/adn/run salud"
|
||||
puts " ./tools/adn/run salud --json"
|
||||
when 'generar'
|
||||
puts "Uso: ruby tools/adn.rb generar <tipo> [argumentos]"
|
||||
puts "Uso: ./tools/adn/run generar <tipo> [argumentos]"
|
||||
puts ""
|
||||
puts "Tipos disponibles:"
|
||||
puts " bitacora [fecha] - Crea nueva bitácora (fecha: YYYY-MM-DD, default: hoy)"
|
||||
@@ -758,13 +768,13 @@ class SubcomandoAyuda
|
||||
puts " proyecto <código> - Crea manifiesto de proyecto"
|
||||
puts ""
|
||||
puts "Ejemplos:"
|
||||
puts " ruby tools/adn.rb generar bitacora"
|
||||
puts " ruby tools/adn.rb generar bitacora 2026-03-08"
|
||||
puts " ruby tools/adn.rb generar nodo srv-nuevo"
|
||||
puts " ruby tools/adn.rb generar proyecto P2604"
|
||||
puts " ./tools/adn/run generar bitacora"
|
||||
puts " ./tools/adn/run generar bitacora 2026-03-08"
|
||||
puts " ./tools/adn/run generar nodo srv-nuevo"
|
||||
puts " ./tools/adn/run generar proyecto P2604"
|
||||
else
|
||||
puts "#{Color::RED}✗ Subcomando desconocido: #{subcomando}#{Color::RESET}"
|
||||
puts "Usa 'ruby tools/adn.rb ayuda' para ver la lista de subcomandos."
|
||||
puts "Usa './tools/adn/run ayuda' para ver la lista de subcomandos."
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -795,6 +805,12 @@ class ADNCLI
|
||||
SubcomandoGenerar.new(args, @logger).ejecutar
|
||||
when 'db'
|
||||
ADN::SubcomandoDB.new(args, @logger).ejecutar
|
||||
when 'backup'
|
||||
ADN::SubcomandoBackup.new(args, @logger).ejecutar
|
||||
when 'sync'
|
||||
ADN::SubcomandoSync.new(args, @logger).ejecutar
|
||||
when 'triggers'
|
||||
ADN::SubcomandoTriggers.new(args, @logger).ejecutar
|
||||
when 'ayuda', 'help', '-h', '--help'
|
||||
SubcomandoAyuda.new(args, @logger).ejecutar
|
||||
when 'evolucion'
|
||||
Reference in New Issue
Block a user