Refactor(ADN): Migración de tools/adn a adn/tools en busca de la Armonía Integral del DIIAA

This commit is contained in:
Ricardo Monla
2026-03-10 22:25:01 -03:00
parent 174ef7d53c
commit 78006032eb
69 changed files with 432 additions and 671 deletions
+121
View File
@@ -0,0 +1,121 @@
# frozen_string_literal: true
# adn/tools/db/cli/verificar_migracion.rb
# ================================================
# Verifica que todas las bitácoras MD existentes estén correctamente
# migradas en la base de datos. Reporta faltantes y discrepancias.
#
# Uso:
# ruby adn/tools/db/cli/verificar_migracion.rb
# — o vía enjambre —
# ./adn/tools/run db verificar
require 'date'
require_relative '../core/bitacora_db'
module BitacorasDB
module CLI
class VerificarMigracion
COLORES = {
reset: "\e[0m", bold: "\e[1m", red: "\e[31m",
green: "\e[32m", yellow: "\e[33m", cyan: "\e[36m", dim: "\e[2m"
}.freeze
def initialize(bitacoras_dir)
@bitacoras_dir = bitacoras_dir
@resultados = { ok: [], sin_entradas: [], no_migrada: [], sin_md: [] }
end
def ejecutar
puts "#{COLORES[:cyan]}🔍 Verificación de migración MD ↔ DB#{COLORES[:reset]}\n\n"
archivos_md = Dir.glob(File.join(@bitacoras_dir, '*.md')).sort
puts "#{COLORES[:dim]}Archivos MD encontrados: #{archivos_md.size}#{COLORES[:reset]}"
BitacorasDB::BitacoraDB.with_connection do |db|
# 1. Validar cada MD contra la DB
archivos_md.each do |archivo|
fecha = File.basename(archivo, '.md')
bitacora = db.find_bitacora_by_fecha(fecha)
unless bitacora
@resultados[:no_migrada] << fecha
next
end
entradas = db.execute(
"SELECT COUNT(*) as total FROM bitacoras.entradas WHERE bitacora_id = $1",
[bitacora['id']]
)
total = entradas.first['total'].to_i
if total > 0
@resultados[:ok] << { fecha: fecha, entradas: total }
else
@resultados[:sin_entradas] << fecha
end
end
# 2. Bitácoras en DB que no tienen MD
todas_db = db.list_bitacoras(limit: 500)
fechas_md = archivos_md.map { |a| File.basename(a, '.md') }
todas_db.each do |b|
f = b['fecha'].to_s
f = f.split('T').first if f.include?('T') # por si viene con timestamp
@resultados[:sin_md] << f unless fechas_md.include?(f)
end
end
mostrar_resultados
end
private
def mostrar_resultados
puts "\n#{COLORES[:bold]}📊 Resultado de verificación:#{COLORES[:reset]}\n"
# OK
puts "#{COLORES[:green]}✅ Migradas correctamente: #{@resultados[:ok].size}#{COLORES[:reset]}"
@resultados[:ok].each do |r|
puts " #{COLORES[:dim]}#{r[:fecha]} (#{r[:entradas]} entradas)#{COLORES[:reset]}"
end
# Sin entradas
if @resultados[:sin_entradas].any?
puts "\n#{COLORES[:yellow]}⚠ En DB pero sin entradas: #{@resultados[:sin_entradas].size}#{COLORES[:reset]}"
@resultados[:sin_entradas].each { |f| puts " #{f}" }
end
# No migradas
if @resultados[:no_migrada].any?
puts "\n#{COLORES[:red]}❌ No migradas (MD existe, DB no): #{@resultados[:no_migrada].size}#{COLORES[:reset]}"
@resultados[:no_migrada].each { |f| puts " #{f}" }
puts " #{COLORES[:dim]}Ejecuta: ./adn/tools/run db migrar:md FECHA#{COLORES[:reset]}"
end
# Sin MD
if @resultados[:sin_md].any?
puts "\n#{COLORES[:cyan]} En DB sin archivo MD: #{@resultados[:sin_md].size}#{COLORES[:reset]}"
@resultados[:sin_md].each { |f| puts " #{f}" }
puts " #{COLORES[:dim]}Ejecuta: ./adn/tools/run db exportar:md FECHA#{COLORES[:reset]}"
end
total = @resultados[:ok].size + @resultados[:sin_entradas].size
total_md = @resultados[:ok].size + @resultados[:sin_entradas].size + @resultados[:no_migrada].size
pct = total_md > 0 ? ((@resultados[:ok].size.to_f / total_md) * 100).round(1) : 0
puts "\n#{COLORES[:bold]}📈 Cobertura: #{pct}% (#{@resultados[:ok].size}/#{total_md})#{COLORES[:reset]}"
if @resultados[:no_migrada].empty? && @resultados[:sin_entradas].empty?
puts "#{COLORES[:green]}#{COLORES[:bold]}🎉 ¡Migración completa! Todas las bitácoras están en la DB.#{COLORES[:reset]}"
end
end
end
end
end
# Ejecución directa
if __FILE__ == $0
bitacoras_dir = File.expand_path('../../../docs/bitacoras', __dir__)
BitacorasDB::CLI::VerificarMigracion.new(bitacoras_dir).ejecutar
end