- Add GetInitialOnboardingStatusUseCase to retrieve onboarding status. - Implement CompleteInitialOnboardingUseCase for completing onboarding. - Create controllers for handling onboarding requests in Express. - Introduce new repository methods for managing onboarding data. - Set up dependency injection for onboarding services and use cases. - Add tests for onboarding use cases and repository methods. - Define request DTOs for onboarding operations with validation. - Update module composition to include onboarding functionalities.
868 lines
20 KiB
Markdown
868 lines
20 KiB
Markdown
**# AGENTS.md**
|
||
|
||
**## Ámbito**
|
||
|
||
Estas instrucciones se aplican a todo el monorepo, salvo que exista un archivo \`AGENTS.md\` más específico en un subdirectorio.
|
||
|
||
Los archivos \`AGENTS.md\` descendientes deben añadir o restringir reglas para su ámbito, no duplicar innecesariamente este documento.
|
||
|
||
**## Objetivo**
|
||
|
||
Trabajar sobre el ERP mediante cambios:
|
||
|
||
\- correctos;
|
||
|
||
\- mínimos;
|
||
|
||
\- comprobables;
|
||
|
||
\- coherentes con la arquitectura existente;
|
||
|
||
\- fáciles de entender y mantener por otros desarrolladores.
|
||
|
||
Antes de modificar código, revisar las implementaciones y patrones existentes en el área afectada. No introducir patrones nuevos si ya existe una solución equivalente en el proyecto.
|
||
|
||
**## Entorno de ejecución**
|
||
|
||
El entorno de desarrollo canónico es WSL2 con Ubuntu 24.04 LTS.
|
||
|
||
El repositorio canónico es:
|
||
|
||
\`/home/david/dev/uecko-erp\`
|
||
|
||
Todos los comandos de desarrollo deben ejecutarse dentro de WSL2 usando Linux y \`bash\`.
|
||
|
||
No ejecutar Node.js, PNPM, Turborepo, TypeScript, Biome, Git ni tests desde Windows, PowerShell, unidades \`Z:\`, rutas UNC o rutas montadas bajo \`/mnt/c\`.
|
||
|
||
No usar la antigua máquina Ubuntu remota como entorno de desarrollo salvo que la tarea lo requiera expresamente.
|
||
|
||
Codex debe trabajar sobre la distribución WSL \`Ubuntu-24.04\` y abrir el repositorio mediante su ruta Linux real:
|
||
|
||
\`/home/david/dev/uecko-erp\`
|
||
|
||
No abrir el proyecto para tareas de desarrollo mediante rutas Windows equivalentes como \`\\wsl$\\...\`, \`Z:\` o \`C:\`.
|
||
|
||
Antes de trabajar comprobar:
|
||
|
||
\`\`\`bash
|
||
|
||
pwd
|
||
|
||
uname -s
|
||
|
||
uname -r
|
||
|
||
whoami
|
||
|
||
git rev-parse --show-toplevel
|
||
|
||
node --version
|
||
|
||
pnpm --version
|
||
|
||
\`\`\`
|
||
|
||
Se espera:
|
||
|
||
\`\`\`text
|
||
|
||
/home/david/dev/uecko-erp
|
||
|
||
Linux
|
||
|
||
<kernel con microsoft-standard-WSL2>
|
||
|
||
david
|
||
|
||
/home/david/dev/uecko-erp
|
||
|
||
Node.js 24.x
|
||
|
||
pnpm 11.22.0
|
||
|
||
\`\`\`
|
||
|
||
Si el entorno no coincide, no continuar con cambios de código hasta identificar la causa.
|
||
|
||
Los archivos \`.env\` locales ya configurados no deben mostrarse, copiarse a respuestas ni versionarse. No imprimir secretos, tokens, contraseñas o cadenas de conexión completas.
|
||
|
||
La versión de PNPM definida en \`packageManager\` del \`package.json\` raíz es vinculante. No actualizar PNPM ni modificar \`packageManager\` como parte de una tarea no relacionada.
|
||
|
||
**## Stack principal**
|
||
|
||
\- Node.js 24.x
|
||
|
||
\- TypeScript
|
||
|
||
\- PNPM
|
||
|
||
\- Turborepo
|
||
|
||
\- ExpressJS
|
||
|
||
\- React
|
||
|
||
\- MariaDB
|
||
|
||
\- Sequelize v6
|
||
|
||
\- Zod v4
|
||
|
||
\- Biome
|
||
|
||
**## Principios obligatorios**
|
||
|
||
Aplicar de forma pragmática:
|
||
|
||
\- SOLID;
|
||
|
||
\- Clean Code;
|
||
|
||
\- DRY;
|
||
|
||
\- KISS;
|
||
|
||
\- YAGNI;
|
||
|
||
\- SSOT;
|
||
|
||
\- Fail Fast;
|
||
|
||
\- programación defensiva;
|
||
|
||
\- inmutabilidad cuando resulte adecuada;
|
||
|
||
\- idempotencia;
|
||
|
||
\- principio de menor privilegio;
|
||
|
||
\- observabilidad en APIs y servicios.
|
||
|
||
Priorizar siempre:
|
||
|
||
\`\`\`text
|
||
|
||
claridad y explicitud
|
||
|
||
\>
|
||
|
||
abstracción prematura
|
||
|
||
\`\`\`
|
||
|
||
No introducir capas, adaptadores, factories, genéricos, eventos, contenedores DI o abstracciones sin una necesidad real y actual.
|
||
|
||
**## Idioma y convenciones de nombres**
|
||
|
||
\- Código e identificadores en inglés.
|
||
|
||
\- Comentarios y TSDoc en castellano.
|
||
|
||
\- Ficheros y directorios en \`kebab-case\`.
|
||
|
||
\- Clases, tipos e interfaces en \`PascalCase\`.
|
||
|
||
\- Variables, funciones y métodos en \`camelCase\`.
|
||
|
||
\- Constantes globales en \`UPPER\_SNAKE\_CASE\` solo cuando realmente sean constantes globales.
|
||
|
||
\- Mantener la convención de prefijo \`I\` para interfaces cuando el área existente ya la utilice.
|
||
|
||
**## Comentarios y documentación**
|
||
|
||
**### Los comentarios**
|
||
|
||
Deben explicar:
|
||
|
||
\- por qué existe una decisión;
|
||
|
||
\- qué riesgo evita;
|
||
|
||
\- qué contrato debe respetarse;
|
||
|
||
\- qué efectos laterales o errores son relevantes.
|
||
|
||
No deben repetir lo que ya expresa el código.
|
||
|
||
Documentar mediante TSDoc las APIs públicas cuando aporten información sobre:
|
||
|
||
\- propósito;
|
||
|
||
\- parámetros;
|
||
|
||
\- valor devuelto;
|
||
|
||
\- errores;
|
||
|
||
\- efectos laterales;
|
||
|
||
\- invariantes o restricciones.
|
||
|
||
Después de un refactor, actualizar o eliminar los comentarios que hayan quedado obsoletos.
|
||
|
||
**### La documentación del proyecto**
|
||
|
||
\- debe redactarse en castellano.
|
||
|
||
\- Reside en /docs.
|
||
|
||
\- Utilizar ficheros Markdown
|
||
|
||
\- Los nombres de los ficheros deben estar en castellano.
|
||
|
||
Reglas de estilo para documentación:
|
||
|
||
\- usar lenguaje claro;
|
||
|
||
\- evitar redacción excesivamente técnica cuando no sea necesaria;
|
||
|
||
\- usar frases directas;
|
||
|
||
\- evitar frases rebuscadas, largas o ambiguas;
|
||
|
||
\- priorizar explicar qué hace el sistema, por qué existe una regla y qué comportamiento debe esperar el usuario o el desarrollador;
|
||
|
||
\- usar términos técnicos cuando sean necesarios para ser precisos, pero explicarlos de forma sencilla;
|
||
|
||
\- no convertir la documentación en una transcripción del código;
|
||
|
||
\- evitar párrafos densos si una explicación breve y directa es suficiente.
|
||
|
||
**## Disciplina de cambios**
|
||
|
||
\- Realizar cambios incrementales.
|
||
|
||
\- No modificar código no relacionado con la tarea.
|
||
|
||
\- No renombrar, mover o reformatear archivos sin necesidad.
|
||
|
||
\- No introducir dependencias nuevas sin una justificación concreta.
|
||
|
||
\- No copiar código si ya existe una abstracción adecuada y estable.
|
||
|
||
\- No crear una abstracción nueva para eliminar una duplicación pequeña y local.
|
||
|
||
\- Mantener compatibilidad con los contratos existentes salvo que la tarea exija explícitamente romperlos.
|
||
|
||
\- No afirmar que una validación ha pasado si no se ha ejecutado correctamente.
|
||
|
||
\- No ocultar fallos de compilación, lint o tests.
|
||
|
||
\- No añadir supresiones de TypeScript, Biome o ESLint sin justificar el motivo en el código o en la respuesta final.
|
||
|
||
**## Uso de \`Result\`, \`Maybe\` y \`Collection\`**
|
||
|
||
Usar los patrones existentes del proyecto:
|
||
|
||
\- \`Result\` para operaciones que pueden fallar;
|
||
|
||
\- \`Maybe\` para ausencia semántica;
|
||
|
||
\- \`Collection\` para conjuntos de objetos del mismo tipo cuando el dominio requiera comportamiento propio.
|
||
|
||
No sustituirlos por excepciones, \`null\`, arrays o tipos ad hoc si el área existente ya utiliza estos patrones.
|
||
|
||
No usar excepciones para flujo de negocio esperado salvo que el diseño actual del módulo lo establezca expresamente.
|
||
|
||
**## Gestión de operaciones asíncronas**
|
||
|
||
El proyecto aplica la regla de Biome:
|
||
|
||
\`\`\`text
|
||
|
||
lint/complexity/noVoid
|
||
|
||
\`\`\`
|
||
|
||
Está prohibido usar el operador \`void\` para descartar el resultado de una promesa.
|
||
|
||
No generar:
|
||
|
||
\`\`\`ts
|
||
|
||
void handleDuplicate();
|
||
|
||
void handleDownload();
|
||
|
||
void asyncOperation();
|
||
|
||
\`\`\`
|
||
|
||
Toda \`Promise\` debe gestionarse explícitamente mediante una de estas opciones:
|
||
|
||
**### Esperar la operación**
|
||
|
||
\`\`\`ts
|
||
|
||
await handleDuplicate();
|
||
|
||
\`\`\`
|
||
|
||
Usar esta opción cuando la función actual pueda ser \`async\` y el flujo deba esperar el resultado.
|
||
|
||
**### Devolver la promesa**
|
||
|
||
\`\`\`ts
|
||
|
||
return handleDuplicate();
|
||
|
||
\`\`\`
|
||
|
||
Usar esta opción cuando el llamador deba controlar el ciclo de vida de la operación.
|
||
|
||
**### Gestionar expresamente el error**
|
||
|
||
\`\`\`ts
|
||
|
||
handleDuplicate().catch(handleUnexpectedError);
|
||
|
||
\`\`\`
|
||
|
||
Usar esta opción solo cuando la operación sea deliberadamente no bloqueante.
|
||
|
||
Reglas adicionales:
|
||
|
||
\- No eliminar \`void\` dejando una promesa flotante.
|
||
|
||
\- No silenciar errores mediante \`.catch(() => undefined)\` o equivalentes sin justificación explícita.
|
||
|
||
\- Antes de convertir un callback en \`async\`, comprobar si su contrato acepta \`Promise\<void>\` o exige \`void\`.
|
||
|
||
\- Si el contrato exige \`void\`, encapsular la operación asíncrona y gestionar explícitamente su error.
|
||
|
||
\- No usar \`void\` como mecanismo para indicar intención.
|
||
|
||
**## TypeScript**
|
||
|
||
**### Imports de tipos**
|
||
|
||
Usar siempre imports de tipos explícitos en la cabecera del fichero mediante \`import type\`:
|
||
|
||
\`\`\`ts
|
||
|
||
import type { UniqueID } from "@repo/rdx-ddd";
|
||
|
||
import type { Result } from "@repo/rdx-utils";
|
||
|
||
\`\`\`
|
||
|
||
No usar referencias de tipo inline mediante \`import("...").Tipo\`:
|
||
|
||
\`\`\`ts
|
||
|
||
// Prohibido
|
||
|
||
companyId: import("@repo/rdx-ddd").UniqueID;
|
||
|
||
\`\`\`
|
||
|
||
Aplicar estas reglas:
|
||
|
||
\- Usar \`import type { ... } from "..."\` para toda dependencia utilizada exclusivamente como tipo.
|
||
|
||
\- Mantener los imports de tipos en la cabecera del fichero, junto con el resto de imports.
|
||
|
||
\- No mezclar imports de tipo y de runtime cuando puedan separarse con claridad.
|
||
|
||
\- No usar \`import("...").Tipo\` en código fuente ordinario.
|
||
|
||
\- Solo se admite un tipo inline en declaraciones generadas, archivos \`.d.ts\`, module augmentation o casos excepcionales técnicamente justificados y documentados.
|
||
|
||
\- No introducir imports de runtime para símbolos usados únicamente como tipos.
|
||
|
||
Ejemplo correcto:
|
||
|
||
\`\`\`ts
|
||
|
||
import type { UniqueID } from "@repo/rdx-ddd";
|
||
|
||
import type { Result } from "@repo/rdx-utils";
|
||
|
||
export interface IIdentityTenantCompanyFinder {
|
||
|
||
existsActiveById(params: {
|
||
|
||
companyId: UniqueID;
|
||
|
||
transaction?: unknown;
|
||
|
||
}): Promise\<Result\<boolean, Error>>;
|
||
|
||
}
|
||
|
||
\`\`\`
|
||
|
||
\- Evitar \`any\`. Usar \`unknown\` cuando el tipo todavía no sea conocido.
|
||
|
||
\- No usar type assertions salvo que exista una garantía verificable que el compilador no pueda inferir.
|
||
|
||
\- Evitar \`!\` salvo que la invariante esté demostrada localmente.
|
||
|
||
\- Preferir tipos semánticos frente a primitivas genéricas.
|
||
|
||
\- Modelar conjuntos cerrados mediante unions o enums existentes.
|
||
|
||
\- Mantener exhaustividad en \`switch\` cuando el tipo represente un conjunto cerrado.
|
||
|
||
\- No añadir ramas \`default\` que oculten casos no contemplados cuando pueda usarse comprobación exhaustiva.
|
||
|
||
\- No duplicar tipos derivados de schemas Zod.
|
||
|
||
\- No usar \`Partial\<T>\` si el schema o el tipo de entrada ya representa explícitamente la opcionalidad.
|
||
|
||
\- Mantener inmutabilidad en valores y estructuras cuando no exista necesidad de mutación.
|
||
|
||
**## Referencias arquitectónicas normativas**
|
||
|
||
Para reglas completas, consultar y no duplicar:
|
||
|
||
- [Arquitectura backend](docs/architecture/backend-architecture.md)
|
||
- [Inyección de dependencias](docs/architecture/dependency-injection.md)
|
||
- [Flujo HTTP y entrada a Application](docs/architecture/http-request-flow.md)
|
||
- [DTOs y schemas HTTP](docs/architecture/dto-guidelines.md)
|
||
- [Pruebas backend por capa](docs/architecture/testing-guidelines.md)
|
||
|
||
Las reglas resumidas siguientes son recordatorios operativos; las SSOT anteriores prevalecen.
|
||
|
||
**## Zod y DTOs**
|
||
|
||
Zod es la fuente única de verdad para los contratos HTTP.
|
||
|
||
Reglas:
|
||
|
||
\- Inferir tipos con \`z.infer\<typeof Schema>\`.
|
||
|
||
\- No duplicar DTOs mediante interfaces manuales equivalentes.
|
||
|
||
\- Cada endpoint debe tener sus DTOs de request y response.
|
||
|
||
\- Reutilizar subschemas solo cuando sean realmente estables y compartidos.
|
||
|
||
\- No mezclar validación de transporte con lógica de negocio.
|
||
|
||
\- Evitar \`.default()\` y \`.transform()\` en DTOs de negocio salvo necesidad justificada.
|
||
|
||
\- Diferenciar explícitamente entre campo omitido, \`null\`, cadena vacía y colección vacía.
|
||
|
||
\- Usar schemas semánticos para UUID, fechas, timestamps, porcentajes, importes y cantidades.
|
||
|
||
\- Los valores decimales exactos no deben viajar como \`number\`.
|
||
|
||
**## Arquitectura backend**
|
||
|
||
El backend sigue DDD pragmático, Clean Architecture y arquitectura hexagonal.
|
||
|
||
Separación obligatoria:
|
||
|
||
\`\`\`text
|
||
|
||
Domain
|
||
|
||
no conoce Application ni Infrastructure
|
||
|
||
Application
|
||
|
||
depende de Domain, contratos y Core
|
||
|
||
no conoce Express, Sequelize ni modelos ORM
|
||
|
||
Infrastructure
|
||
|
||
depende de Application, Domain y Core
|
||
|
||
\`\`\`
|
||
|
||
No se permite:
|
||
|
||
\- \`Domain -> Application\`;
|
||
|
||
\- \`Domain -> Infrastructure\`;
|
||
|
||
\- \`Application -> Infrastructure\`;
|
||
|
||
\- importar infraestructura interna de otro módulo;
|
||
|
||
\- compartir repositorios entre módulos;
|
||
|
||
\- usar Service Locator;
|
||
|
||
\- introducir DI implícita o mágica.
|
||
|
||
**### Flujo de entrada**
|
||
|
||
Para el flujo normal, usar:
|
||
|
||
\`\`\`text
|
||
|
||
RequestDTO -> UseCase({ dto, context }) -> InputMapper -> Value Objects / Props
|
||
|
||
\`\`\`
|
||
|
||
`RequestMapper -> Command` es opcional y solo procede cuando existe adaptación HTTP propia, por ejemplo para combinar body, params o query. No crear uno solo para renombrar campos que Application volverá a transformar.
|
||
|
||
**### Casos de uso**
|
||
|
||
Los casos de uso deben:
|
||
|
||
\- orquestar;
|
||
|
||
\- gestionar transacciones cuando corresponda;
|
||
|
||
\- delegar en servicios de aplicación;
|
||
|
||
\- devolver \`Result\`;
|
||
|
||
\- construir respuestas mediante builders o mappers de salida.
|
||
|
||
No deben:
|
||
|
||
\- contener lógica HTTP;
|
||
|
||
\- usar Sequelize directamente;
|
||
|
||
\- construir agregados desde DTOs HTTP;
|
||
|
||
\- asumir responsabilidades propias de repositorios o controllers.
|
||
|
||
**### Servicios de aplicación**
|
||
|
||
Preferir servicios pequeños y explícitos con una responsabilidad clara.
|
||
|
||
Evitar nombres genéricos como:
|
||
|
||
\- \`Manager\`;
|
||
|
||
\- \`GenericService\`;
|
||
|
||
\- \`CommandService\`;
|
||
|
||
\- \`BaseRepository\`;
|
||
|
||
\- \`Helper\` sin semántica concreta.
|
||
|
||
**### Repositorios**
|
||
|
||
\- Cada repositorio gestiona un agregado o una responsabilidad concreta.
|
||
|
||
\- Sequelize no debe salir de Infrastructure.
|
||
|
||
\- Los repositorios deben usar mappers de persistencia.
|
||
|
||
\- No crear repositorios base genéricos sin una necesidad demostrada.
|
||
|
||
\- Mantener aislamiento por \`companyId\` y \`branchId\` cuando corresponda.
|
||
|
||
**### Mappers de persistencia**
|
||
|
||
Usar un mapper bidireccional por agregado:
|
||
|
||
\`\`\`ts
|
||
|
||
toPersistence();
|
||
|
||
toDomain();
|
||
|
||
\`\`\`
|
||
|
||
Infrastructure debe reconstruir entidades mediante \`rehydrate()\`.
|
||
|
||
**### \`create()\` y \`rehydrate()\`**
|
||
|
||
Mantener separadas estas operaciones:
|
||
|
||
\`\`\`text
|
||
|
||
create()
|
||
|
||
creación funcional
|
||
|
||
valida invariantes
|
||
|
||
puede fallar
|
||
|
||
devuelve Result
|
||
|
||
rehydrate()
|
||
|
||
reconstrucción desde persistencia
|
||
|
||
no valida reglas de creación
|
||
|
||
no genera eventos
|
||
|
||
no devuelve Result
|
||
|
||
\`\`\`
|
||
|
||
Reglas:
|
||
|
||
\- Infrastructure usa \`rehydrate()\`.
|
||
|
||
\- Application y Domain usan \`create()\` para nuevas instancias.
|
||
|
||
\- \`update()\` no usa \`create()\` ni \`rehydrate()\`.
|
||
|
||
\- Los Value Objects no tienen \`rehydrate()\`; se reconstruyen mediante \`create()\`.
|
||
|
||
**### Comunicación entre módulos**
|
||
|
||
Los módulos solo deben colaborar mediante servicios públicos explícitos.
|
||
|
||
No exponer:
|
||
|
||
\- repositorios;
|
||
|
||
\- modelos Sequelize;
|
||
|
||
\- mappers internos;
|
||
|
||
\- servicios de escritura internos;
|
||
|
||
\- detalles de infraestructura.
|
||
|
||
El composition root de cada módulo debe construir sus dependencias explícitamente.
|
||
|
||
**## Snapshots y builders de respuesta**
|
||
|
||
Los schemas Zod definen el contrato de salida.
|
||
|
||
Los snapshot builders solo materializan ese contrato.
|
||
|
||
Reglas:
|
||
|
||
\- Tipar el builder con el DTO inferido del schema exacto.
|
||
|
||
\- No crear interfaces \`I\*Snapshot\` que dupliquen un DTO.
|
||
|
||
\- El builder debe ser determinista y no contener lógica de negocio.
|
||
|
||
\- Puede convertir \`Maybe\` a \`null\`, Value Objects a primitivas y enums internos a valores de contrato.
|
||
|
||
\- No puede acceder a repositorios ni infraestructura.
|
||
|
||
\- Si cambia el schema, el builder debe fallar en compilación si deja de cumplir el contrato.
|
||
|
||
**## Frontend**
|
||
|
||
\- Mantener React, TanStack Query, TanStack Table, React Hook Form, Zod, shadcn/ui, Tailwind e i18n según los patrones existentes.
|
||
|
||
\- No duplicar estado remoto en estado local sin necesidad.
|
||
|
||
\- Mantener las operaciones de servidor en TanStack Query.
|
||
|
||
\- Centralizar las claves de query siguiendo la convención existente.
|
||
|
||
\- Invalidar o actualizar caché de forma explícita tras mutaciones.
|
||
|
||
\- No introducir efectos para derivar estado que pueda calcularse durante render.
|
||
|
||
\- Evitar componentes monolíticos; extraer responsabilidades cuando exista una frontera clara.
|
||
|
||
\- No extraer componentes triviales que solo oculten JSX sin aportar semántica.
|
||
|
||
\- Mantener accesibilidad, estados disabled, loading, empty y error.
|
||
|
||
\- No eliminar acciones no disponibles si la UX exige mostrarlas deshabilitadas.
|
||
|
||
\- Mantener traducciones en \`es\` y \`en\` cuando se añadan textos visibles.
|
||
|
||
\- No insertar textos de interfaz directamente si el área usa i18n.
|
||
|
||
\- Mantener \`tabular-nums\` en columnas monetarias cuando corresponda.
|
||
|
||
**## APIs y errores**
|
||
|
||
\- Usar errores tipados y predecibles.
|
||
|
||
\- No devolver detalles internos, SQL, stack traces o información sensible.
|
||
|
||
\- Mapear errores de dominio y aplicación a errores HTTP en Infrastructure.
|
||
|
||
\- Mantener contratos de error estables.
|
||
|
||
\- Aplicar idempotencia en operaciones que puedan repetirse.
|
||
|
||
\- Validar autorización y aislamiento tenant antes de acceder o modificar datos.
|
||
|
||
\- No confiar en identificadores de compañía enviados por el cliente sin verificar el contexto autenticado.
|
||
|
||
\- Registrar información suficiente para diagnosticar fallos sin exponer datos sensibles.
|
||
|
||
**## Seguridad**
|
||
|
||
\- Aplicar principio de menor privilegio.
|
||
|
||
\- No introducir secretos, tokens, claves o credenciales en el repositorio.
|
||
|
||
\- No registrar datos sensibles.
|
||
|
||
\- Validar toda entrada externa.
|
||
|
||
\- Usar consultas parametrizadas y APIs seguras de Sequelize.
|
||
|
||
\- Evitar interpolación manual de SQL.
|
||
|
||
\- Revisar autorización además de autenticación.
|
||
|
||
\- Mantener aislamiento multiempresa en todas las consultas y mutaciones.
|
||
|
||
**## Base de datos y Sequelize**
|
||
|
||
\- Mantener nombres de tablas y columnas coherentes con las convenciones existentes.
|
||
|
||
\- No introducir acceso directo a modelos Sequelize fuera de Infrastructure.
|
||
|
||
\- Ejecutar operaciones agregadas dentro de una transacción cuando deban ser atómicas.
|
||
|
||
\- Diseñar migraciones idempotentes cuando el procedimiento del proyecto lo requiera.
|
||
|
||
\- No eliminar columnas, tablas o datos legacy sin una auditoría previa de referencias.
|
||
|
||
\- No confiar únicamente en restricciones de aplicación cuando una invariante crítica pueda reforzarse en base de datos.
|
||
|
||
\- Evitar \`JSON.stringify\` para detectar cambios de dominio.
|
||
|
||
\- Comparar Value Objects semánticamente mediante sus primitivas o métodos de igualdad adecuados.
|
||
|
||
**## Comandos y entorno de ejecución**
|
||
|
||
El código se encuentra físicamente dentro del filesystem Linux de WSL2, en:
|
||
|
||
\`/home/david/dev/uecko-erp\`
|
||
|
||
Ejecutar los comandos directamente en la distribución WSL \`Ubuntu-24.04\`.
|
||
|
||
No ejecutar los comandos del proyecto mediante SSH contra la antigua máquina Ubuntu, salvo que la tarea lo requiera expresamente.
|
||
|
||
No usar como workspace principal rutas Windows, unidades de red, rutas UNC, \`\\wsl$\\...\` ni rutas bajo \`/mnt/c\`.
|
||
|
||
Preferir \`bash\` y herramientas Linux disponibles dentro de WSL.
|
||
|
||
Antes de una tarea de código, comprobar al menos:
|
||
|
||
\`\`\`bash
|
||
|
||
pwd
|
||
|
||
git status --short
|
||
|
||
\`\`\`
|
||
|
||
Ejemplos preferidos:
|
||
|
||
\`\`\`bash
|
||
|
||
pnpm --filter \<workspace> typecheck
|
||
|
||
pnpm --filter \<workspace> lint
|
||
|
||
pnpm --filter \<workspace> test
|
||
|
||
\`\`\`
|
||
|
||
Usar comandos acotados al workspace afectado cuando sea suficiente.
|
||
|
||
Usar comandos globales cuando el cambio pueda afectar contratos compartidos o varios workspaces.
|
||
|
||
**## Validación obligatoria**
|
||
|
||
Antes de finalizar un cambio, ejecutar las comprobaciones relevantes disponibles para el área modificada:
|
||
|
||
\`\`\`bash
|
||
|
||
pnpm typecheck
|
||
|
||
pnpm lint
|
||
|
||
pnpm test
|
||
|
||
\`\`\`
|
||
|
||
Cuando corresponda, ejecutar además:
|
||
|
||
\`\`\`bash
|
||
|
||
pnpm check
|
||
|
||
pnpm build
|
||
|
||
\`\`\`
|
||
|
||
Criterios:
|
||
|
||
\- Preferir validación dirigida al paquete o módulo afectado.
|
||
|
||
\- Ejecutar validación global si se modifican paquetes compartidos, contratos o configuración transversal.
|
||
|
||
\- Informar exactamente qué comandos se ejecutaron.
|
||
|
||
\- Informar claramente cualquier validación no ejecutada y su motivo.
|
||
|
||
\- No considerar completada una tarea con errores conocidos de lint, typecheck o tests salvo que el usuario haya limitado expresamente el alcance.
|
||
|
||
**## Tests**
|
||
|
||
\- Añadir o actualizar tests cuando cambie comportamiento observable.
|
||
|
||
\- No escribir tests que dependan de detalles internos irrelevantes.
|
||
|
||
\- Cubrir casos válidos, inválidos, límites e idempotencia cuando corresponda.
|
||
|
||
\- Mantener tests deterministas.
|
||
|
||
\- No usar esperas arbitrarias.
|
||
|
||
\- No desactivar tests para hacer pasar la suite.
|
||
|
||
**## Refactors**
|
||
|
||
Un refactor debe mantener el comportamiento salvo que se indique lo contrario.
|
||
|
||
Antes de eliminar código legacy:
|
||
|
||
1\. buscar referencias en todo el monorepo;
|
||
|
||
2\. clasificar cada referencia como activa, legacy no cableada, migración, documentación o falso positivo;
|
||
|
||
3\. revisar rutas, composition roots, DI, imports, modelos, repositorios, mappers, tests y scripts;
|
||
|
||
4\. eliminar únicamente lo demostrado como no utilizado;
|
||
|
||
5\. ejecutar typecheck, lint y tests relevantes;
|
||
|
||
6\. documentar referencias residuales y motivos.
|
||
|
||
**## Respuesta final del agente**
|
||
|
||
Al terminar una tarea de código, indicar de forma concisa:
|
||
|
||
\- cambios realizados;
|
||
|
||
\- decisiones relevantes;
|
||
|
||
\- archivos principales modificados;
|
||
|
||
\- comandos de validación ejecutados;
|
||
|
||
\- resultado de las validaciones;
|
||
|
||
\- riesgos o pendientes reales.
|
||
|
||
No afirmar que algo compila, funciona o está probado si no se ha verificado.
|
||
|
||
**## Regla de precedencia**
|
||
|
||
En caso de conflicto, aplicar este orden:
|
||
|
||
1\. instrucciones explícitas del usuario para la tarea actual;
|
||
|
||
2\. \`AGENTS.md\` más cercano al archivo modificado;
|
||
|
||
3\. este \`AGENTS.md\` raíz;
|
||
|
||
4\. convenciones existentes del código;
|
||
|
||
5\. preferencias generales del agente.
|
||
|
||
Si una instrucción contradice la arquitectura o genera un riesgo relevante, señalarlo antes de introducir el cambio.
|