codigo0/manual-tes/TES_Manual_Digital/auditoria_estructura.py
planetazuzu af02a569a2 feat: Aplicación completa Manual TES Digital
- Integración de 93 capítulos del manual completo
- Componente MarkdownViewer para renderizar archivos .md
- Navegación jerárquica completa (ManualIndex)
- Sistema de búsqueda mejorado
- Página ManualViewer con navegación anterior/siguiente
- Scripts de verificación del manual
- Puerto configurado en 8096
- Configuración de despliegue (Vercel, Netlify, GitHub Pages)
- Todos los problemas detectados corregidos
2025-12-17 12:12:10 +01:00

182 lines
6.3 KiB
Python

#!/usr/bin/env python3
"""
Script de auditoría de estructura del Manual TES Digital
Valida orden canónico y detecta archivos fuera de lugar
"""
import os
from pathlib import Path
from collections import defaultdict
def extract_number(filename):
"""Extrae el número de bloque y capítulo para ordenamiento"""
parts = filename.replace('.md', '').split('_')
if len(parts) < 3:
return (999, 999, filename) # Archivos sin patrón claro al final
try:
block = int(parts[1])
chapter_part = parts[2]
# Manejar casos especiales
if chapter_part == 'X':
return (block, 998, filename) # Inventarios antes de cierres
if chapter_part.startswith('X'):
# X2, X3, etc.
try:
x_num = int(chapter_part[1:])
return (block, 997 + x_num, filename)
except:
return (block, 997, filename)
if chapter_part == '99':
return (block, 999, filename) # Cierres al final
# Números normales
try:
chapter = int(chapter_part)
return (block, chapter, filename)
except:
return (block, 998, filename)
except:
return (999, 999, filename)
def audit_structure():
"""Realiza auditoría completa de la estructura"""
base = Path('/home/planetazuzu/protocolo-r-pido/manual-tes/TES_Manual_Digital')
issues = []
warnings = []
info = []
# 1. Verificar archivos en raíz que deberían estar en _DOCUMENTACION_INTERNA
root_docs_expected = {
'INDICE_COMPLETO_MANUAL_TES.md': '00_INDICES_Y_MAPAS',
'MAPA_MAESTRO_MANUAL_TES_DIGITAL.md': '00_INDICES_Y_MAPAS',
'LISTADO_COMPLETO_RUTAS_MD.md': '00_INDICES_Y_MAPAS',
'LISTA_COMPLETA_ARCHIVOS.md': '00_INDICES_Y_MAPAS',
'INFORME_REORGANIZACION_FINAL.md': '02_INFORMES_PROCESO',
'INFORME_NORMALIZACION.md': '02_INFORMES_PROCESO',
'INFORME_BLOQUE_1_BUSQUEDA.md': '02_INFORMES_PROCESO',
'INSTALACION.md': '03_CONVERSION_Y_HERRAMIENTAS',
'README_CONVERSION.md': '03_CONVERSION_Y_HERRAMIENTAS',
}
for doc_file, expected_subdir in root_docs_expected.items():
if (base / doc_file).exists():
issues.append({
'type': 'MISPLACED',
'file': doc_file,
'current': 'RAÍZ',
'expected': f'_DOCUMENTACION_INTERNA/{expected_subdir}',
'severity': 'HIGH'
})
# 2. Verificar orden dentro de cada bloque
bloque_dirs = [d for d in base.iterdir() if d.is_dir() and d.name.startswith('BLOQUE_')]
for bloque_dir in sorted(bloque_dirs):
md_files = list(bloque_dir.glob('*.md'))
if not md_files:
continue
# Ordenar archivos
sorted_files = sorted([f.name for f in md_files], key=extract_number)
actual_files = [f.name for f in sorted(md_files, key=lambda x: x.name)]
# Verificar orden
if sorted_files != actual_files:
issues.append({
'type': 'ORDER',
'block': bloque_dir.name,
'current_order': actual_files,
'expected_order': sorted_files,
'severity': 'MEDIUM'
})
# Verificar que *_99_* está al final
x99_files = [f for f in sorted_files if '_99_' in f]
if x99_files:
last_file = sorted_files[-1]
if not any('_99_' in f for f in [last_file]):
issues.append({
'type': 'ORDER',
'block': bloque_dir.name,
'issue': 'Archivos *_99_* no están al final',
'severity': 'MEDIUM'
})
# 3. Verificar estructura de _DOCUMENTACION_INTERNA
doc_interna = base / '_DOCUMENTACION_INTERNA'
if doc_interna.exists():
expected_subdirs = [
'00_INDICES_Y_MAPAS',
'01_ANALISIS_Y_AUDITORIA',
'02_INFORMES_PROCESO',
'03_CONVERSION_Y_HERRAMIENTAS',
'04_CONTROL_Y_GOBERNANZA'
]
for subdir in expected_subdirs:
if not (doc_interna / subdir).exists():
warnings.append({
'type': 'MISSING_SUBDIR',
'subdir': f'_DOCUMENTACION_INTERNA/{subdir}',
'severity': 'LOW'
})
# 4. Estadísticas
total_md = len(list(base.rglob('*.md')))
bloque_md = len([f for d in bloque_dirs for f in d.glob('*.md')])
doc_interna_md = len(list((base / '_DOCUMENTACION_INTERNA').rglob('*.md'))) if (base / '_DOCUMENTACION_INTERNA').exists() else 0
root_md = len([f for f in base.glob('*.md')])
info.append({
'total_md_files': total_md,
'bloque_md_files': bloque_md,
'doc_interna_md_files': doc_interna_md,
'root_md_files': root_md
})
return {
'issues': issues,
'warnings': warnings,
'info': info
}
if __name__ == '__main__':
results = audit_structure()
print("=" * 80)
print("AUDITORÍA DE ESTRUCTURA - MANUAL TES DIGITAL")
print("=" * 80)
print()
print(f"📊 ESTADÍSTICAS:")
for stat in results['info']:
for key, value in stat.items():
print(f" {key}: {value}")
print()
print(f"❌ PROBLEMAS DETECTADOS: {len(results['issues'])}")
for i, issue in enumerate(results['issues'], 1):
print(f"\n{i}. [{issue['severity']}] {issue['type']}")
if issue['type'] == 'MISPLACED':
print(f" Archivo: {issue['file']}")
print(f" Ubicación actual: {issue['current']}")
print(f" Ubicación esperada: {issue['expected']}")
elif issue['type'] == 'ORDER':
print(f" Bloque: {issue['block']}")
if 'issue' in issue:
print(f" Problema: {issue['issue']}")
else:
print(f" Orden actual vs esperado detectado")
print()
print(f"⚠️ ADVERTENCIAS: {len(results['warnings'])}")
for i, warning in enumerate(results['warnings'], 1):
print(f"\n{i}. [{warning['severity']}] {warning['type']}")
print(f" {warning['subdir']}")
print()
print("=" * 80)