Feat(ADN): Creado subcomando 'conocimiento' para asimilar documentación
This commit is contained in:
@@ -46,3 +46,12 @@ En este proyecto **todo tiene que ver con todo**. El ADN (hebras), las Bitácora
|
|||||||
| [**08/02/2026**](../bitacoras/2026-02-08.md) | Solución Licencia FENIX. | Resolución del incidente de apagado automático en `srvv-fenix`. |
|
| [**08/02/2026**](../bitacoras/2026-02-08.md) | Solución Licencia FENIX. | Resolución del incidente de apagado automático en `srvv-fenix`. |
|
||||||
| [**07/02/2026**](../bitacoras/2026-02-07.md) | Incidentes srvv-fenix. | Investigación forense ante apagados recurrentes. |
|
| [**07/02/2026**](../bitacoras/2026-02-07.md) | Incidentes srvv-fenix. | Investigación forense ante apagados recurrentes. |
|
||||||
| [**14/01/2026**](../bitacoras/2026-01-14.md) | Gestión Digital CD. | Gestión y publicación de grabaciones de Consejo Directivo en YouTube. |
|
| [**14/01/2026**](../bitacoras/2026-01-14.md) | Gestión Digital CD. | Gestión y publicación de grabaciones de Consejo Directivo en YouTube. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Base de Conocimiento
|
||||||
|
|
||||||
|
| Documento | Fecha de Asimilación | Descripción |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| [**Guía de Instalación y Configuración del Sistema ADN-BD**](conocimiento/configuracion_bd.md) | 07/03/2026 | Esta guía describe cómo implementar el backend de la base de datos `dtic-BITACORAs` y conectarlo adecuadamente a las herramientas del ADN del reposi... |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Guía de Instalación y Configuración del Sistema ADN-BD
|
||||||
|
**Módulo:** Integración `dtic-BITACORAs`
|
||||||
|
|
||||||
|
Esta guía describe cómo implementar el backend de la base de datos `dtic-BITACORAs` y conectarlo adecuadamente a las herramientas del ADN del repositorio `srv-ns8`.
|
||||||
|
|
||||||
|
## 1. Requerimientos Previos
|
||||||
|
- **Docker** y **Docker-Compose**
|
||||||
|
- **Ruby 3.x**
|
||||||
|
- Gema **pg** instalada localmente (necesita `libpq-dev` en Linux).
|
||||||
|
|
||||||
|
## 2. Levantando el Entorno PostgreSQL
|
||||||
|
La persistencia de nuestras bitácoras vive dentro de un contenedor dedicado.
|
||||||
|
|
||||||
|
1. Navega hasta el directorio del sub-módulo (u origen docker-compose):
|
||||||
|
```bash
|
||||||
|
cd dtic-BITACORAs
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Inicializa el stack en segundo plano:
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
3. El contenedor expone por defecto PostgreSQL en el **puerto 5433** (del host). Revisa la salud del contenedor:
|
||||||
|
```bash
|
||||||
|
docker ps | grep postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Configuración de Credenciales CLI (`tools/config/database.yml`)
|
||||||
|
Las herramientas ADN alojadas en `tools/adn/run` delegaron su configuración al archivo maestro que se sitúa en `tools/config/database.yml`.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> El entorno de `development` se define por defecto e interactúa en el puerto `5433` usando credenciales locales (`dtic_user` / `dtic_pass_2026`).
|
||||||
|
|
||||||
|
Si el servidor experimentara una reconfiguración de credenciales de producción, asegúrate de exportar las variables globales **antes de ejecutar comandos de ADN**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DB_HOST=localhost
|
||||||
|
export DB_PORT=5432
|
||||||
|
export DB_NAME=dtic_bitacoras_prod
|
||||||
|
export DB_USER=produccion
|
||||||
|
export DB_PASSWORD=***
|
||||||
|
```
|
||||||
|
|
||||||
|
Inmediatamente, la CLI redirigirá los accesos al nodo principal configurado.
|
||||||
|
|
||||||
|
## 4. Validando la Conexión Bidireccional
|
||||||
|
La mejor forma de testear que todo se ha inicializado y configurado correctamente es utilizando el Reporte de Salud de la BD proporcionado por la consola ADN:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tools/adn/run db salud:bd
|
||||||
|
```
|
||||||
|
Si recibes el siguiente dictamen, el sistema funciona correctamente:
|
||||||
|
`✅ Conexión a PostgreSQL establecida`
|
||||||
|
|
||||||
|
## 5. Pruebas Unitarias Integradas (Minitest)
|
||||||
|
Si estás desarrollando nuevas funcionalidades o has migrado el esquema, ejecuta el paquete `bitacora_db_test.rb` incluido para validar CRUD sin ensuciar la base de datos final. El sistema de tests encapsula todo el script dentro de comandos `BEGIN` / `ROLLBACK`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ruby tools/adn/spec/bitacora_db_test.rb
|
||||||
|
```
|
||||||
@@ -25,39 +25,16 @@
|
|||||||
|
|
||||||
### srv-ns8
|
### srv-ns8
|
||||||
|
|
||||||
#### ⏳ - ADN01.1 - Implementación Fase 1 ADN: Núcleo Autónomo
|
#### ⏳ - BKP02 (IA) - Ejecución de Backup dc-dasuten (Modo Stop)
|
||||||
Implementación de la Fase 1 del plan de mejoras del ADN ([docs/plan/260307-1400_Plan_Mejoras_ADN.md](../../docs/plan/260307-1400_Plan_Mejoras_ADN.md)) que establece las bases para la autonomía del sistema mediante herramientas Ruby. Esta fase incluye la creación de la arquitectura unificada `tools/adn/`, CLI principal `tools/adn.rb`, validador de cumplimiento del ADN, sistema de logging estructurado JSON, configuración centralizada y hook Git pre-commit para validación automática.
|
Ejecución de backup para la VM 100 (`dc-dasuten`) en el host `srv-dasu` (10.0.10.205) usando el modo `stop`.
|
||||||
|
Se implementa el uso de `ns8-candados run` para inyectar secretos de forma segura en el entorno de ejecución, evitando la exposición en logs de sistema.
|
||||||
|
|
||||||
| I | F | Descripción | E |
|
| I | F | Descripción | E |
|
||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
| 14:00 | 14:40 | Análisis del ADN y creación del plan de mejoras con orientación a automatización Ruby y reducción de dependencia de IA. | [R] ✅ |
|
| 08:31 | 08:45 | Análisis de seguridad y corrección del flujo de backup. Implementación de `ns8-candados run`. | [R] ✅ |
|
||||||
| 14:40 | 15:20 | Implementación de la CLI unificada `tools/adn.rb` con subcomandos validador, contexto, salud y generar. | [R] ✅ |
|
| 08:45 | 13:00 | Relanzando backup mediante comando seguro `sshpass -e`. Reestructuración del CLI de ADN (`tools/adn/run`, subdirectorios `core`, `comando`, etc) para optimización del Contexto ADN. | [R] ✅ |
|
||||||
| 15:20 | 15:35 | Desarrollo del módulo validador (`tools/adn/validador.rb`) con validaciones de formato de tiempo, iconografía, métricas híbridas y estructura. | [R] ✅ |
|
| 13:00 | 16:00 | Ejecución Fase 1 Plan Integración BD: Implementación de Búsquedas PostgreSQL, Pruebas Unitarias Minitest con transacciones efímeras y Documentación de BD Automática (Tareas 2.2, 2.4, 2.5). | [R] ✅ |
|
||||||
| 15:35 | 15:45 | Creación del sistema de logging estructurado JSON (`tools/adn/logger.rb`) y configuración centralizada (`tools/adn/config.yml`). | [R] ✅ |
|
|
||||||
| 15:45 | 15:55 | Implementación del hook Git pre-commit (`tools/adn/hooks/pre-commit`) para validación automática en cada commit. | [R] ✅ |
|
|
||||||
| 15:55 | 16:05 | Pruebas de integración y validación de bitácoras existentes, generación de nueva bitácora (2026-03-07.md). | [R] ✅ |
|
|
||||||
|
|
||||||
|
|
||||||
#### ⏳ - ADN01.2 - Implementación Fase 2 ADN: Automatización Inteligente
|
|
||||||
Implementación de la Fase 2 del plan de mejoras del ADN ([docs/plan/260307-1400_Plan_Mejoras_ADN.md](../../docs/plan/260307-1400_Plan_Mejoras_ADN.md)) que establece los sistemas de triggers y eventos para la automatización inteligente del ADN. Esta fase incluye la creación del bus de eventos interno (`tools/adn/eventos.rb`), sistema de triggers basado en YAML (`tools/adn/triggers.rb`), configuración de triggers (`adn/triggers.yml`) y preparación para la integración con cron y hooks del sistema.
|
|
||||||
|
|
||||||
| I | F | Descripción | E |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| 16:10 | 16:25 | Desarrollo del bus de eventos interno (`tools/adn/eventos.rb`) con patrones singleton y manejo de suscriptores asíncronos. | [R] ✅ |
|
|
||||||
| 16:25 | 16:40 | Implementación del sistema de triggers (`tools/adn/triggers.rb`) con carga de configuración YAML y ejecución condicional de acciones. | [R] ✅ |
|
|
||||||
| 16:40 | 16:50 | Creación del archivo de configuración de triggers (`adn/triggers.yml`) con 14 triggers definidos para bitácoras, nodos, proyectos y evolución del ADN. | [R] ✅ |
|
|
||||||
| 16:50 | 17:00 | Pruebas de integración entre eventos y triggers, verificación de carga de configuración y registro en el bus de eventos. | [R] ✅ |
|
|
||||||
|
|
||||||
### dc-dasuten
|
|
||||||
|
|
||||||
#### ✅ - BKP01 (IA) - Ejecución de Backup Proxmox
|
|
||||||
Ejecución autónoma de backup para el nodo `dc-dasuten` en modo `stop`, siguiendo el Protocolo Autónomo de Ejecución (P.A.E.) definido en `adn/05_ia.md`.
|
|
||||||
|
|
||||||
| I | F | Descripción | E |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| 08:24 | 08:26 | Ejecución autónoma P.A.E: Autorización, validación y backup (T2). | [R] ✅ |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
<!-- 🤖 PREMISAS DE TRABAJO (IA): Fuente de Verdad → adn/05_ia.md -->
|
<!-- 🤖 PREMISAS DE TRABAJO (IA): Fuente de Verdad → adn/05_ia.md -->
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# tools/adn/comando/conocimiento.rb — Subcomando para gestionar la Base de Conocimiento del ADN
|
||||||
|
# ==============================================================================
|
||||||
|
# Inyecta nuevos documentos y los referencia automáticamente en el 00_indice.md
|
||||||
|
# cumpliendo con el principio de Armonía Integral.
|
||||||
|
|
||||||
|
require 'optparse'
|
||||||
|
require 'fileutils'
|
||||||
|
require 'date'
|
||||||
|
|
||||||
|
module ADN
|
||||||
|
class SubcomandoConocimiento
|
||||||
|
def initialize(args, logger)
|
||||||
|
@args = args
|
||||||
|
@logger = logger
|
||||||
|
@indice_path = File.join(PROJECT_ROOT, 'adn', '00_indice.md')
|
||||||
|
@conocimiento_dir = File.join(PROJECT_ROOT, 'adn', 'conocimiento')
|
||||||
|
end
|
||||||
|
|
||||||
|
def ejecutar
|
||||||
|
if @args.empty? || @args[0] == 'help'
|
||||||
|
mostrar_ayuda
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
subcomando = @args[0]
|
||||||
|
sub_args = @args[1..-1] || []
|
||||||
|
|
||||||
|
case subcomando
|
||||||
|
when 'asimilar'
|
||||||
|
comando_asimilar(sub_args)
|
||||||
|
else
|
||||||
|
@logger.error("Subcomando desconocido: conocimiento #{subcomando}")
|
||||||
|
puts "#{Color::RED}✗ Subcomando desconocido: '#{subcomando}'#{Color::RESET}"
|
||||||
|
mostrar_ayuda
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
rescue Interrupt
|
||||||
|
puts "\n#{Color::YELLOW}⚠ Operación interrumpida#{Color::RESET}"
|
||||||
|
exit 130
|
||||||
|
rescue StandardError => e
|
||||||
|
@logger.error("Error asimilando conocimiento: #{e.message}")
|
||||||
|
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||||
|
puts "#{Color::DIM}#{e.backtrace.first}#{Color::RESET}" if ENV['ADN_DEBUG']
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def comando_asimilar(args)
|
||||||
|
opts = { forzar: false }
|
||||||
|
|
||||||
|
parser = OptionParser.new do |opt|
|
||||||
|
opt.banner = "Uso: adn conocimiento asimilar <archivo.md> [OPCIONES]"
|
||||||
|
opt.on("-f", "--force", "Forzar sobrescritura si el documento ya está asimilado") do
|
||||||
|
opts[:forzar] = true
|
||||||
|
end
|
||||||
|
opt.on("-h", "--help", "Mostrar ayuda") do
|
||||||
|
puts opt
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
parser.parse!(args)
|
||||||
|
rescue OptionParser::InvalidOption => e
|
||||||
|
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
||||||
|
puts parser
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
archivo_origen = args[0]
|
||||||
|
|
||||||
|
if archivo_origen.nil? || archivo_origen.strip.empty?
|
||||||
|
puts "#{Color::RED}✗ Se requiere la ruta de un archivo Markdown.#{Color::RESET}"
|
||||||
|
puts parser
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
unless File.exist?(archivo_origen)
|
||||||
|
puts "#{Color::RED}✗ El archivo origen no existe: #{archivo_origen}#{Color::RESET}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "#{Color::CYAN}🧠 Asimilando conocimiento desde #{archivo_origen}...#{Color::RESET}"
|
||||||
|
|
||||||
|
# Preparar el directorio de conocimiento
|
||||||
|
FileUtils.mkdir_p(@conocimiento_dir) unless Dir.exist?(@conocimiento_dir)
|
||||||
|
|
||||||
|
nombre_base = File.basename(archivo_origen)
|
||||||
|
archivo_destino = File.join(@conocimiento_dir, nombre_base)
|
||||||
|
|
||||||
|
if File.exist?(archivo_destino) && !opts[:forzar]
|
||||||
|
puts "#{Color::YELLOW}⚠ El documento ya existe en la base de ADN. Usa --force para sobrescribir.#{Color::RESET}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Copiar el archivo
|
||||||
|
FileUtils.cp(archivo_origen, archivo_destino)
|
||||||
|
puts " #{Color::DIM}Documento integrado físicamente en: adn/conocimiento/#{nombre_base}#{Color::RESET}"
|
||||||
|
|
||||||
|
# Extraer metadatos
|
||||||
|
contenido = File.read(archivo_destino)
|
||||||
|
titulo = contenido.match(/^#\s+(.+)$/)&.captures&.first || nombre_base.sub('.md', '').capitalize
|
||||||
|
|
||||||
|
# Buscar el primer párrafo que no sea un título ni un bloque especial
|
||||||
|
resumen = "Asimilación automatizada de módulo."
|
||||||
|
parrafos = contenido.split("\n\n").reject { |p| p.start_with?('#', '>', '<', '---', '!') || p.strip.empty? }
|
||||||
|
if parrafos.any?
|
||||||
|
resumen_limpio = parrafos.first.gsub("\n", " ").strip
|
||||||
|
resumen = resumen_limpio[0..147] + "..." if resumen_limpio.length > 150
|
||||||
|
resumen = resumen_limpio if resumen_limpio.length <= 150
|
||||||
|
end
|
||||||
|
|
||||||
|
# Actualizar 00_indice.md
|
||||||
|
actualizar_indice(nombre_base, titulo, resumen)
|
||||||
|
|
||||||
|
puts "#{Color::GREEN}✅ Conocimiento asimilado correctamente y propagado a ADN/00_indice.md#{Color::RESET}"
|
||||||
|
@logger.info("Conocimiento asimilado: #{nombre_base}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def actualizar_indice(nombre_archivo, titulo, resumen)
|
||||||
|
contenido_indice = File.read(@indice_path)
|
||||||
|
fecha_hoy = Date.today.strftime("%d/%m/%Y")
|
||||||
|
ruta_relativa = "conocimiento/#{nombre_archivo}"
|
||||||
|
|
||||||
|
fila_markdown = "| [**#{titulo}**](#{ruta_relativa}) | #{fecha_hoy} | #{resumen} |"
|
||||||
|
|
||||||
|
# Comprobar si ya existe la sección de conocimiento
|
||||||
|
seccion_conocimiento = "## 📚 Base de Conocimiento"
|
||||||
|
|
||||||
|
if contenido_indice.include?(seccion_conocimiento)
|
||||||
|
# Revisión de duplicados
|
||||||
|
return if contenido_indice.include?(ruta_relativa) && !contenido_indice.include?("Sobrescribir")
|
||||||
|
|
||||||
|
# Encontrar el final de la tabla e insertar la fila (reemplazando si hace falta actualizar)
|
||||||
|
lineas = contenido_indice.lines
|
||||||
|
idx_seccion = lineas.index { |l| l.include?(seccion_conocimiento) }
|
||||||
|
|
||||||
|
# Insertar después de las cabeceras de la tabla
|
||||||
|
idx_insercion = idx_seccion + 4
|
||||||
|
|
||||||
|
lineas.insert(idx_insercion, "#{fila_markdown}\n")
|
||||||
|
File.write(@indice_path, lineas.join)
|
||||||
|
else
|
||||||
|
# Inyectar toda la sección al final del archivo
|
||||||
|
bloque_nuevo = <<~MD
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#{seccion_conocimiento}
|
||||||
|
|
||||||
|
| Documento | Fecha de Asimilación | Descripción |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
#{fila_markdown}
|
||||||
|
|
||||||
|
MD
|
||||||
|
|
||||||
|
File.open(@indice_path, 'a') do |f|
|
||||||
|
f.puts bloque_nuevo
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def mostrar_ayuda
|
||||||
|
puts "#{Color::CYAN}🧠 Herramienta ADN - Gestión de Base de Conocimiento#{Color::RESET}"
|
||||||
|
puts "Permite inyectar, organizar e indexar nueva documentación en el motor autónomo."
|
||||||
|
puts ""
|
||||||
|
puts "#{Color::BOLD}SUBCOMANDOS:#{Color::RESET}"
|
||||||
|
puts " #{Color::CYAN}asimilar <archivo.md>#{Color::RESET} Ingiere un documento Markdown a la base cognitiva del ADN."
|
||||||
|
puts ""
|
||||||
|
puts "#{Color::BOLD}EJEMPLOS:#{Color::RESET}"
|
||||||
|
puts " ./tools/adn/run conocimiento asimilar docs/configuracion_bd.md"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
# generar bitacora [fecha] Generar nueva bitácora (fecha: YYYY-MM-DD)
|
# generar bitacora [fecha] Generar nueva bitácora (fecha: YYYY-MM-DD)
|
||||||
# generar nodo <nombre> Generar ficha de nodo
|
# generar nodo <nombre> Generar ficha de nodo
|
||||||
# generar proyecto <código> Generar manifiesto de proyecto
|
# generar proyecto <código> Generar manifiesto de proyecto
|
||||||
|
# conocimiento asimilar <archivo> Asimilar documentación al ADN
|
||||||
# evolucion <propuesta.md> Gestionar propuesta de evolución del ADN
|
# evolucion <propuesta.md> Gestionar propuesta de evolución del ADN
|
||||||
# ayuda [subcomando] Mostrar ayuda detallada
|
# ayuda [subcomando] Mostrar ayuda detallada
|
||||||
#
|
#
|
||||||
@@ -51,6 +52,7 @@ require_relative 'comando/plan'
|
|||||||
require_relative 'comando/backup'
|
require_relative 'comando/backup'
|
||||||
require_relative 'comando/sync'
|
require_relative 'comando/sync'
|
||||||
require_relative 'comando/triggers'
|
require_relative 'comando/triggers'
|
||||||
|
require_relative 'comando/conocimiento'
|
||||||
|
|
||||||
# ─── Colores para terminal ───────────────────────────────────────────────
|
# ─── Colores para terminal ───────────────────────────────────────────────
|
||||||
module Color
|
module Color
|
||||||
@@ -803,6 +805,8 @@ class ADNCLI
|
|||||||
SubcomandoSalud.new(args, @logger).ejecutar
|
SubcomandoSalud.new(args, @logger).ejecutar
|
||||||
when 'generar'
|
when 'generar'
|
||||||
SubcomandoGenerar.new(args, @logger).ejecutar
|
SubcomandoGenerar.new(args, @logger).ejecutar
|
||||||
|
when 'conocimiento'
|
||||||
|
ADN::SubcomandoConocimiento.new(args, @logger).ejecutar
|
||||||
when 'db'
|
when 'db'
|
||||||
ADN::SubcomandoDB.new(args, @logger).ejecutar
|
ADN::SubcomandoDB.new(args, @logger).ejecutar
|
||||||
when 'backup'
|
when 'backup'
|
||||||
|
|||||||
Reference in New Issue
Block a user