22 KiB
Refactorización general del repositorio
Revisa y refactoriza de forma sistemática todo el código propio del repositorio para que cumpla las buenas prácticas, convenciones, arquitectura y reglas definidas en AGENTS.md.
AGENTS.md es la referencia normativa principal para esta tarea.
Antes de modificar código:
- Lee
AGENTS.mdcompleto. - Lee la documentación de arquitectura y estándares a la que haga referencia.
- Comprueba el entorno y estado del repositorio conforme a las instrucciones de
AGENTS.md. - Realiza una inspección suficientemente amplia del repositorio antes de empezar a modificar archivos.
- Identifica la estructura general, paquetes, módulos, dependencias internas, patrones existentes y áreas principales.
- Establece un orden razonable de revisión y refactorización.
No empieces a corregir el primer problema que encuentres sin conocer antes suficientemente el contexto general del repositorio.
Objetivo
El objetivo no es reescribir el proyecto desde cero.
Debes:
- identificar incumplimientos reales de
AGENTS.md; - corregirlos cuando pueda hacerse de forma segura;
- mejorar claridad, mantenibilidad, tipado, separación de responsabilidades y coherencia;
- mantener la arquitectura existente;
- conservar el comportamiento funcional salvo que detectes claramente un bug;
- evitar cambios puramente cosméticos sin beneficio real;
- evitar introducir nuevas abstracciones innecesarias.
La tarea consiste en revisar TODO el código propio relevante del repositorio, no únicamente los archivos modificados recientemente.
No te limites a generar un informe de problemas: corrige los problemas que puedan resolverse de forma segura.
No te detengas después de revisar o corregir una única área. Continúa de forma progresiva hasta completar la revisión del código propio relevante del repositorio, salvo que exista un bloqueo real que requiera una decisión del usuario.
Código excluido
No revisar, refactorizar, reformatear, reorganizar ni modificar código perteneciente a terceros, código vendor o paquetes que hayan sido incorporados al repositorio como biblioteca externa.
Queda expresamente excluido:
packages/shadcn-ui
Considera packages/shadcn-ui código de terceros/vendor aunque forme parte físicamente del monorepo.
No apliques sobre este paquete las reglas de estilo, estructura, TypeScript, React, nombres de fichero, separación de componentes ni ninguna otra refactorización definida en AGENTS.md.
No modifiques archivos dentro de packages/shadcn-ui, ni siquiera para:
- corregir lint;
- corregir formato;
- reducir warnings;
- cambiar tipos;
- separar componentes;
- reorganizar archivos;
- cambiar imports;
- eliminar código aparentemente no utilizado;
- homogeneizarlo con el resto del proyecto.
Puedes consultar únicamente su API pública, exports, componentes y contratos cuando sea necesario para utilizarlo correctamente desde código propio.
Si una validación global falla exclusivamente por código existente dentro de packages/shadcn-ui, indícalo claramente en el informe final y no modifiques ese paquete para hacer pasar la validación.
Si durante la revisión aparecen otros directorios claramente correspondientes a código generado, dependencias externas o vendor, no los refactorices salvo que AGENTS.md indique expresamente lo contrario.
Estrategia de trabajo
Trabaja progresivamente por paquetes, módulos o áreas funcionales coherentes.
Antes de modificar cada área:
- Examina su estructura.
- Identifica sus dependencias y consumidores.
- Busca implementaciones equivalentes dentro del repositorio.
- Consulta la documentación normativa aplicable.
- Identifica los incumplimientos de
AGENTS.md. - Distingue entre problemas reales y simples preferencias estilísticas.
- Determina la solución más pequeña y segura que respete la arquitectura existente.
Después realiza las refactorizaciones necesarias.
No hagas una refactorización masiva sin control.
Después de cada conjunto coherente de cambios:
- revisa el diff;
- comprueba imports y referencias;
- comprueba que no has ampliado innecesariamente el alcance;
- ejecuta las validaciones dirigidas apropiadas;
- corrige cualquier regresión introducida antes de continuar.
Cuando completes un módulo o área importante, ejecuta las pruebas, typecheck y lint correspondientes cuando resulte razonable.
TypeScript
Revisa especialmente:
- usos de
any; - assertions innecesarias;
- non-null assertions;
- tipos excesivamente débiles;
- duplicación de tipos;
- tipos que puedan derivarse de schemas existentes;
- uso incorrecto de
Partial; - opcionalidad mal representada;
- discriminated unions incompletas;
switchno exhaustivos cuando deberían serlo;- casts usados como sustituto de validación;
- datos externos tratados como confiables sin validación;
- imports de tipos incorrectos;
- genéricos innecesarios;
- aliases sin semántica;
- estructuras mutables cuando no deberían serlo.
Prioriza:
unknownfrente aanypara datos todavía no validados;- narrowing frente a casts;
import type;- discriminated unions;
- exhaustividad;
- inferencia cuando sea clara;
- contratos explícitos cuando formen parte de APIs internas o públicas;
- schemas como fuente normativa cuando corresponda.
No debilites TypeScript para conseguir que el código compile.
Corrige el origen del problema de tipos siempre que sea posible.
Asincronía
Revisa:
- promesas flotantes;
voidusado para descartar promesas;catchque ocultan errores;- callbacks convertidos incorrectamente a
async; - operaciones asíncronas no esperadas;
- errores asíncronos ignorados;
- flujos donde una operación debería devolverse, esperarse o manejar explícitamente su error.
Toda promesa debe:
- esperarse;
- devolverse;
- o tener su error gestionado explícitamente.
No ocultes errores para conseguir que el flujo continúe artificialmente.
Node.js
Revisa especialmente:
- I/O síncrono dentro del flujo normal del servidor;
- accesos dispersos a
process.env; - configuración sin validar;
- recursos externos sin timeout;
- operaciones cancelables sin mecanismo de cancelación cuando corresponda;
- estado mutable global dependiente de peticiones;
- errores de infraestructura silenciados;
- cierre incorrecto de recursos;
- responsabilidades mezcladas.
La configuración debe cargarse, validarse y normalizarse en los puntos definidos por la arquitectura.
No disperses lecturas directas de process.env por la aplicación.
No bloquees el event loop innecesariamente.
Express
Revisa especialmente:
- routers con demasiada lógica;
- controladores demasiado grandes;
- lógica de negocio dentro de controladores;
- acceso directo al ORM desde capas HTTP cuando contradiga la arquitectura;
- validación insuficiente de
params,query,headersybody; - manejo repetitivo o incorrecto de errores;
- exposición de información interna;
- middleware demasiado genérico;
- middleware con varias responsabilidades;
- ramas que puedan producir más de una respuesta HTTP;
- código HTTP mezclado con dominio o persistencia.
Los controladores deben actuar principalmente como adaptadores entre HTTP y la aplicación.
La lógica de negocio debe permanecer en las capas definidas por la arquitectura.
Centraliza el tratamiento de errores según los patrones existentes.
No expongas:
- stack traces;
- SQL;
- secretos;
- credenciales;
- detalles internos innecesarios.
React 19
Revisa todo el código React propio.
Comprueba especialmente:
- componentes demasiado grandes;
- varios componentes relevantes agrupados en un único fichero;
- responsabilidades mezcladas;
- efectos innecesarios;
- estado redundante;
- valores derivados almacenados en estado;
- props copiadas a estado sin necesidad;
- acceso a datos mezclado con presentación;
- custom hooks innecesarios;
- hooks con responsabilidades ambiguas;
useMemoouseCallbackutilizados preventivamente;- incumplimientos de las Rules of Hooks;
- efectos secundarios durante render;
- mutación de props o estado;
- duplicación de estado remoto gestionado por TanStack Query;
- carga remota implementada mediante
useEffect; - patrones visuales repetidos que deberían reutilizar componentes existentes.
Organización de componentes React
Como norma general:
- un fichero
.tsxdebe contener un único componente React principal; - no agrupes varios componentes React relevantes en un mismo fichero por comodidad.
Extrae un componente a su propio fichero cuando tenga alguna de estas características:
- props propias;
- estado;
- hooks;
- lógica de interacción;
- lógica de renderizado significativa;
- responsabilidad semántica identificable;
- posibilidad razonable de reutilización;
- tamaño suficiente para dificultar la lectura del componente principal.
Un subcomponente puede permanecer en el mismo fichero únicamente cuando sea:
- pequeño;
- puramente presentacional;
- estrechamente ligado al componente principal;
- sin lógica relevante;
- sin estado;
- sin hooks significativos;
- y su extracción no mejore realmente la comprensión.
Si un fichero contiene varios subcomponentes privados con responsabilidad propia, reconsidera la estructura y extráelos.
No fragmentes JSX trivial en componentes artificiales simplemente para reducir el número de líneas.
La separación debe basarse en responsabilidades, semántica y mantenibilidad.
Diálogos, modales y ventanas emergentes
Durante la revisión identifica todas las ventanas modales, cuadros de diálogo, formularios modales, paneles emergentes y componentes equivalentes.
No te limites a buscar componentes llamados Dialog o FormDialog.
Revisa especialmente implementaciones construidas mediante:
Dialog;AlertDialog;Sheet;Drawer;FormDialog;- wrappers propios;
- cualquier otra primitiva que represente una interacción modal o superpuesta.
Toda ventana modal o cuadro de diálogo con contenido y responsabilidad propios debe extraerse a un componente React independiente y vivir en su propio fichero .tsx.
Considera especialmente como componentes independientes los diálogos de:
- alta;
- edición;
- eliminación;
- confirmación;
- selección;
- cambio de estado;
- detalle;
- ayuda;
- configuración;
- asignación;
- acciones que requieran interacción adicional.
Como norma general, una página o listado no debe contener internamente grandes bloques de JSX correspondientes a diálogos funcionales.
El componente padre debe coordinar:
- apertura;
- cierre;
- datos necesarios;
- callbacks;
- acciones posteriores.
El componente del diálogo debe encapsular:
- su estructura visual;
- contenido;
- formulario cuando corresponda;
- lógica de interacción propia;
- estados locales propios.
No mantengas formularios completos ni bloques grandes de DialogContent dentro de páginas o listados cuando representen una unidad funcional reconocible.
Un formulario utilizado dentro de un diálogo puede separarse además en otro componente cuando tenga suficiente complejidad, reutilización o responsabilidad propia.
No extraigas mecánicamente un diálogo trivial compuesto únicamente por unas pocas líneas de contenido estático sin lógica, estado, formulario ni responsabilidad propia.
Estado y efectos React
Mantén el estado mínimo necesario.
No almacenes en estado valores que puedan calcularse correctamente durante render a partir de:
- props;
- otro estado;
- resultados de consultas;
- constantes;
- datos derivados.
No utilices useEffect para sincronizar estado React con otro estado React cuando el valor pueda derivarse.
No utilices useEffect para reaccionar a una acción directa del usuario cuando esa lógica deba ejecutarse desde el event handler correspondiente.
Utiliza efectos para sincronización real con:
- sistemas externos;
- APIs imperativas;
- suscripciones;
- listeners;
- timers;
- recursos externos.
Todo efecto que cree recursos debe realizar el cleanup correspondiente.
No introduzcas useMemo ni useCallback preventivamente.
Úsalos solo cuando exista una necesidad concreta:
- rendimiento demostrado;
- profiling;
- estabilidad referencial exigida por un contrato;
- comportamiento de una dependencia que lo requiera.
TanStack Query y acceso a datos
Revisa:
- query keys dispersas;
- duplicación de estado remoto;
- invalidaciones excesivamente amplias;
fetchdirecto desde componentes cuando exista una capa apropiada;- carga remota mediante
useEffect; - funciones de API dependientes de React;
- mutaciones que no actualicen correctamente la caché;
- errores de carga no representados;
- ausencia de estados de carga o vacío.
Mantén las query keys centralizadas conforme a los patrones del proyecto.
Después de una mutación, invalida o actualiza únicamente aquello que realmente se vea afectado.
No invalide indiscriminadamente toda la caché para evitar razonar sobre dependencias.
Formularios
Revisa:
- duplicación de validación;
- estado duplicado;
- formularios demasiado acoplados a páginas;
- formularios modales incluidos directamente dentro de grandes componentes;
- errores de campos mal representados;
- errores globales mezclados con errores de validación;
- envíos duplicados;
- cierres del diálogo antes de confirmar éxito.
Utiliza React Hook Form y Zod conforme a los patrones definidos en el proyecto.
Mantén una única fuente normativa de validación cuando sea posible.
No cierres ni limpies un formulario hasta confirmar correctamente la operación que lo requiera.
Componentes visuales y reutilización
Antes de crear un componente nuevo:
- Busca si ya existe uno equivalente.
- Comprueba
@repo/shadcn-ui. - Revisa componentes compartidos del proyecto.
- Busca patrones equivalentes en otras pantallas.
No dupliques estructura, comportamiento ni patrones visuales existentes.
Extrae componentes comunes únicamente cuando exista repetición real o una responsabilidad compartida clara.
Mantén los componentes genéricos independientes de:
- DTO específicos;
- endpoints;
- Sequelize;
- lógica de dominio concreta;
- detalles internos de Metis Desk,
si esa dependencia no es necesaria para cumplir su función.
Estructura de archivos
Revisa:
- archivos excesivamente grandes;
- archivos con varias responsabilidades;
utils.ts;helpers.ts;types.ts;common.ts;constants.ts;
cuando se hayan convertido en cajones de sastre.
Mantén tipos, constantes y utilidades cerca del dominio o funcionalidad a la que pertenecen.
Muévelos a ubicaciones compartidas únicamente cuando existan consumidores reales en diferentes áreas.
No crees barrels index.ts indiscriminadamente.
Evita barrels que:
- oculten dependencias;
- provoquen ciclos;
- hagan difícil localizar el origen de un símbolo.
No reorganices directorios únicamente por preferencias personales.
Abstracciones
Revisa y evita abstracciones innecesarias como:
BaseService;BaseRepository;- repositorios genéricos;
- factories genéricas;
- wrappers sin valor semántico;
- clases abstractas sin necesidad;
- eventos internos sin consumidores reales;
- contenedores DI innecesarios;
- genéricos anticipatorios;
- configuraciones altamente parametrizables sin consumidores reales.
No introduzcas extensibilidad hipotética.
Aplica YAGNI.
Las abstracciones deben aparecer porque exista una necesidad real, no porque puedan resultar útiles en el futuro.
Duplicación
Busca duplicación real de:
- lógica;
- validaciones;
- transformaciones;
- componentes;
- estructuras de formularios;
- patrones de interacción;
- consultas;
- tratamiento de errores.
No elimines duplicación de manera mecánica.
Dos bloques similares no requieren necesariamente una abstracción común si representan conceptos diferentes o evolucionarán de manera independiente.
Extrae únicamente cuando exista una responsabilidad compartida real.
Código muerto
Identifica:
- funciones sin uso;
- componentes sin consumidores;
- exports innecesarios;
- tipos obsoletos;
- código comentado;
- compatibilidad interna que ya no tenga consumidores;
- implementaciones duplicadas antiguas.
Antes de eliminar código:
- busca todas sus referencias en el monorepo;
- identifica posibles usos dinámicos;
- comprueba tests y documentación;
- confirma que no forme parte de un contrato público.
No elimines legado basándote únicamente en una búsqueda superficial.
Dependencias
No añadas una dependencia nueva salvo que exista una necesidad clara.
Antes de hacerlo:
- comprueba APIs nativas;
- comprueba dependencias ya instaladas;
- comprueba utilidades existentes;
- justifica la incorporación.
No reemplaces una dependencia establecida por otra equivalente únicamente por preferencia.
No actualices versiones de dependencias salvo que sea necesario para esta tarea o exista instrucción expresa.
Seguridad
Durante la refactorización conserva y mejora cuando corresponda:
- validación de entrada;
- autenticación;
- autorización;
- aislamiento de clientes;
- consultas parametrizadas;
- transacciones;
- restricciones de base de datos;
- protección de secretos;
- privacidad de logs;
- idempotencia.
No confíes en identificadores enviados por el navegador para determinar permisos o pertenencia.
No introduzcas regresiones de seguridad en nombre de simplificar código.
Tests
Revisa los tests relacionados con el código refactorizado.
Prioriza tests de comportamiento observable.
No escribas tests únicamente para aumentar cobertura.
Evita tests excesivamente acoplados a detalles internos.
Cuando corrijas un bug reproducible, considera añadir una prueba que:
- falle con el comportamiento anterior;
- pase con la corrección.
Los tests deben ser deterministas.
No introduzcas:
- esperas arbitrarias;
- sleeps;
- retries para ocultar inestabilidad;
- desactivaciones de tests para conseguir que la suite pase.
Cambios fuera de alcance
No amplíes una refactorización para corregir indiscriminadamente cualquier problema que encuentres.
Si detectas un problema no relacionado con el área que estás trabajando:
- corrígelo únicamente si es trivial, seguro y necesario para completar correctamente el cambio actual;
- en caso contrario, déjalo documentado como pendiente.
No hagas reformateos globales ni renombres masivos sin necesidad.
No cambies APIs públicas, contratos HTTP, schemas, persistencia o comportamiento funcional salvo que sea necesario para resolver un problema real.
Si un cambio afecta contratos compartidos:
- identifica todos los consumidores;
- actualízalos conjuntamente;
- valida el comportamiento completo.
No mantengas compatibilidad artificial con APIs internas antiguas cuando todos los consumidores puedan actualizarse de forma segura dentro del mismo cambio.
Criterios para detener una refactorización concreta
No improvises cuando la corrección requiera:
- una decisión funcional;
- una decisión arquitectónica significativa;
- cambios de negocio no documentados;
- una migración de datos con implicaciones desconocidas;
- modificar contratos públicos sin poder determinar los consumidores;
- asumir comportamiento no verificable.
En estos casos deja el problema claramente identificado como pendiente indicando:
- fichero o área;
- problema encontrado;
- impacto;
- motivo por el que no debe corregirse automáticamente;
- solución recomendada.
Esto no implica detener la revisión completa del repositorio si puedes continuar con otras áreas independientes.
Validación
Después de cada conjunto coherente de cambios ejecuta las comprobaciones dirigidas apropiadas.
Al finalizar la refactorización completa ejecuta, como mínimo, las validaciones globales definidas en AGENTS.md.
Salvo que AGENTS.md indique otra cosa, incluye:
pnpm typecheckpnpm lintpnpm testpnpm checkpnpm build
No afirmes que una validación ha pasado si no la has ejecutado.
Si una comprobación falla:
- determina si el fallo ha sido introducido por la refactorización;
- corrígelo si es responsabilidad del código propio;
- vuelve a ejecutar la comprobación;
- si corresponde a código excluido o a un problema previo no relacionado, documenta claramente la causa.
Revisión final
Antes de dar la tarea por terminada:
- Revisa el diff completo.
- Comprueba que no se hayan modificado áreas excluidas.
- Busca imports no utilizados.
- Busca casts añadidos innecesariamente.
- Busca supresiones nuevas de TypeScript, lint o Biome.
- Comprueba que no haya promesas flotantes.
- Comprueba que no hayas añadido
useEffect,useMemoouseCallbackinnecesarios. - Revisa los archivos
.tsxmodificados para detectar varios componentes relevantes en el mismo fichero. - Comprueba que los diálogos funcionales hayan sido extraídos cuando corresponda.
- Comprueba que no hayas creado abstracciones sin consumidores reales.
- Comprueba que no hayas duplicado tipos, schemas o lógica.
- Comprueba que no quede código temporal, comentado o de depuración.
- Ejecuta las validaciones finales.
Informe final
Al finalizar proporciona un resumen estructurado y concreto indicando:
- áreas y módulos revisados;
- áreas expresamente excluidas;
- principales incumplimientos encontrados;
- principales refactorizaciones realizadas;
- componentes React extraídos;
- diálogos o formularios modales extraídos;
- mejoras relevantes de TypeScript;
- mejoras de Node.js/Express;
- duplicaciones eliminadas;
- código muerto eliminado;
- archivos o módulos especialmente modificados;
- tests añadidos o modificados;
- comandos ejecutados;
- resultado de cada validación;
- problemas detectados que hayan quedado pendientes;
- decisiones que requieran revisión humana.
No afirmes:
- haber revisado un área que no hayas inspeccionado;
- haber corregido un problema que siga presente;
- haber ejecutado una comprobación que no hayas ejecutado.
El resultado debe dejar el código propio del repositorio progresivamente alineado con AGENTS.md, manteniendo el comportamiento existente y evitando refactorizaciones especulativas.