Hoy no construí una nueva funcionalidad. Hoy limpié la casa.
Después de semanas de avanzar rápido —Ledger, Wealth, Pólizas, Docencia UBO— el repositorio había acumulado deuda técnica visible: 14 archivos Markdown sueltos en la raíz, una copia obsoleta de src/ledger/ que nadie usaba, colores hexadecimales hardcodeados en componentes que debían usar el design system, y cero cobertura de tests.
No era un repositorio roto. Era un repositorio que había crecido sin parar de respirar.
La auditoría
Le pedí a Neo (mi agente de desarrollo) que realizara una auditoría completa antes de continuar con el trabajo en PAIP. La instrucción fue clara: sin nueva funcionalidad. Solo limpieza, estructura y calidad.
Lo que siguió fue una sesión de trabajo metódico que tocó 59 archivos en un solo commit.
Estructura documental
El primer problema era cosmético pero molesto: la raíz del repositorio tenía 14 archivos .md mezclados con el código. AGENTS_MANIFEST.md, SECUENCIA_MAESTRA.md, LEARNINGS.md, SEGURIDAD.md… todos conviviendo al mismo nivel que package.json y CLAUDE.md.
La solución fue implementar la estructura que ya estaba documentada pero nunca ejecutada:
docs/
├── architecture/ → SECUENCIA_MAESTRA.md, AGENTS_MANIFEST.md, NOTION_SCHEMA.md
├── projects/ → handoffs y PRDs
├── operations/ → SEGURIDAD.md, MEMORY.md
├── strategy/ → ESTRATEGIA_WEB.md, PROTOCOLO_CREATIVO.md
└── learnings/ → LEARNINGS.md
La raíz quedó con exactamente 3 archivos Markdown: README.md, CLAUDE.md y TODO.md.
La papelera que faltaba
También creamos trash/ — un directorio para archivos que ya no tienen sentido operacional pero que no queremos eliminar sin pensarlo dos veces.
Ahí fue a parar src/ledger/: una copia completa del backend de Ledger que llevaba meses conviviendo con el resto del código, obsoleta desde que ese proyecto pasó a su propio repositorio externo. También vercel.json (redundante con el adaptador de Astro), monitor_notion.js (sin documentación de uso) y un par de documentos de planificación de Telegram que ya son historia.
La regla de trash/ es clara: nada se borra directamente. Se mueve aquí, se documenta por qué, y solo Javier puede autorizar la eliminación definitiva.
Componentes y calidad de código
La parte más interesante fue el trabajo en src/web/.
Los tres KPI cards del dashboard de Wealth (Cash In, Burn Rate, Capital Acumulado) tenían sus estilos en línea directamente en index.astro. 58 líneas de style="background-color: var(--color-wealth...)" repetidas con mínimas variaciones. El clásico copiar-pegar que funciona pero que duele cada vez que lo lees.
La solución: KpiCard.astro y DemoBanner.astro. Dos componentes nuevos que encapsulan los estilos en CSS con scope, aceptan variantes tipadas ('cash-in' | 'burn' | 'capital') y eliminan completamente los inline styles del template.
También se encontraron colores hexadecimales hardcodeados en TelegramLogs.astro y ProductCard.astro. #7fff7f, #60a5fa, #c084fc, #f87171 — colores que ya estaban definidos en el design system como tokens semánticos pero que alguien (yo, hace semanas) había escrito a mano en lugar de referenciarlos. Corregidos.
Tooling que faltaba
Tres herramientas que deberían haber estado desde el primer día:
Biome: linter y formatter para TypeScript/JavaScript. Un archivo biome.json configurado con las reglas básicas y dos scripts nuevos en package.json: lint y format.
Vitest: el framework de tests. 4 archivos de test, 20 pruebas, todas pasando desde el primer intento. Tests para la validación de email, el generador de emails de bienvenida, la función getWealthConfig() y el schema de agents-status.json.
GitHub Actions: un workflow de CI que en cada push ejecuta lint → test → build. Sin esto, cualquier error que rompa el build puede llegar a producción sin que nadie se dé cuenta.
El bug que encontró Alfred
Aquí viene la parte que más me gustó del proceso.
Después de los cambios, pedí una auditoría de verificación independiente. Alfred revisó cada archivo modificado y encontró un bug real que yo había pasado por alto: el endpoint /api/agents tenía 6 niveles de ../ en un path que necesitaba 5.
// Antes (incorrecto — apuntaba fuera del repositorio)
resolve(thisDir, '../../../../../../pipeline/state.json')
// Después (correcto — 5 niveles desde src/web/src/pages/api/)
resolve(thisDir, '../../../../../pipeline/state.json')
Un error de conteo. Pequeño, pero con consecuencias: el endpoint nunca había leído el estado real del pipeline — siempre caía en el fallback silencioso y devolvía los datos estáticos de agents-status.json. Con la corrección, ahora lee el pipeline/state.json real y muestra el estado actualizado de cada agente.
El resultado
- 59 archivos cambiados en el commit principal
- 20 tests creados, 20 pasando
- 0 errores de build
- 0 errores de Biome después del autoformat
- 1 bug real encontrado y corregido por la auditoría de verificación
- Deploy a producción sin interrupción del servicio
El repositorio no hace nada diferente hoy que ayer para el usuario final. Pero está en un estado desde el que es mucho más fácil construir lo que viene: PAIP, el Portal de Análisis de Ingresos y Patrimonio.
Hay algo satisfactorio en una sesión donde el output no es una nueva feature sino un sistema más ordenado. No es el trabajo glamoroso. Es el trabajo que permite que el trabajo glamoroso exista.