Cuando la lógica de negocio se testea contra un repositorio fake en memoria, la implementación real (SQL, EF Core) puede quedar sin probar — queries que no traducen bien, constraints que el fake no reproduce. La solución es un puñado de tests que ejercitan esa implementación real contra un Postgres real con Testcontainers.
Una suite de Playwright que arranca contra el código fuente o `vite dev` no ejercita el Dockerfile, nginx ni el entrypoint que inyecta configuración en tiempo de arranque — todo eso puede romperse solo en la imagen empaquetada. La solución corre Playwright contra la imagen Docker del frontend ya construida y el mecanismo api-lite como backend, verificando el artefacto que de verdad se despliega.
Un backend se despliega como imagen Docker, pero los tests contra el código fuente nunca ejercitan el Dockerfile, las variables de entorno del contenedor ni si las migraciones corren al arrancar. La solución es un proyecto de tests separado, sin dependencia de código fuente, que levanta esa imagen ya construida junto a sus dependencias reales con Testcontainers y la estimula solo por sus interfaces públicas.
Un contrato OpenAPI generado del código nadie lo escribe ni lo revisa a propósito, así que un refactor puede cambiarlo como efecto secundario sin que nadie se entere hasta que se rompe en producción. La solución versiona ese contrato como snapshot aprobado, lo compara en un test automatizado, y solo un comando explícito puede actualizarlo tras revisión.
Un agente que da una tarea por terminada en cuanto el diff "tiene buena pinta" puede dejar pasar bugs reales o, al contrario, sobre-verificar corriendo infraestructura innecesaria. La solución convierte la verificación en una decisión basada en una matriz de riesgo, con un script de comandos deterministas y una skill que elige la evidencia mínima necesaria.
Un agente que levanta un proyecto en local redescubre cada vez qué variables necesita, en qué orden arrancar y qué superficie hace falta, y suele levantar de más o de menos. La solución separa un script determinista con modos explícitos de una skill que le dice al agente cuándo usar cada modo.
Un frontend Vite plancha sus variables de entorno en el bundle durante el build, obligando a construir una imagen distinta por cada entorno. La solución inyecta esas variables en el arranque del contenedor con envsubst, para que una sola imagen construida sirva a todos los entornos.
Cuando frontend, backend y admin viven en repos separados, cualquier cambio que cruce esa frontera exige coordinar varios PRs y decidir el orden de merge y de deploy entre repos. La solución empaqueta todas las apps del producto en un único repositorio, con un pipeline independiente por app gateado por un glob de rutas.
Sin fronteras reales entre piezas, cualquier clase puede depender de cualquier otra, lo que impide testear en aislamiento y obliga a cargar contexto de todo el sistema para tocar una sola funcionalidad. La solución construye la app como un host casi vacío que enchufa módulos con una interfaz narrow pública y una implementación deep interna al ensamblado.
Usar excepciones tanto para denegaciones de negocio esperadas como para fallos técnicos de infraestructura mezcla ambos casos en el mismo mecanismo y deja que cada controlador invente su propio mapeo a HTTP. La solución es un tipo Result<T>/ApplicationError que representa los fracasos esperados como valores de retorno, con un único punto que los mapea a su respuesta HTTP.
Levantar en local o en tests una API que exige OIDC real obliga a gestionar credenciales de un proveedor externo, o lleva a saltarse la autenticación y dejar de ejercitar el pipeline real. La solución es un proveedor OIDC de mentira que habla el subconjunto real del protocolo, para login determinista tanto en desarrollo como en tests de aceptación.
En una arquitectura modular sin fronteras forzadas por el compilador, un import de conveniencia puede cruzar una frontera prohibida o crear un ciclo sin que nadie lo note hasta meses después. La solución versiona la matriz de dependencias entre módulos como snapshot aprobado y la compara en cada build, exigiendo revisión consciente ante cualquier cambio.
Las tareas de mantenimiento puntuales (backfills, purgas, recálculos) suelen acabar como SQL suelto que salta las invariantes de dominio, o como un programa aparte que diverge con el tiempo de la configuración real. La solución son comandos descubiertos por reflection que reutilizan el mismo bootstrap de DI/config que la app real, sin levantar HTTP.
Llegar a mano a un estado de negocio concreto (un pedido rechazado por scoring, una verificación fallida) exige arrastrar el flujo real por integraciones externas lentas o que no se pueden disparar a demanda en local. La solución es un CLI aparte que borra y repuebla Postgres local con un catálogo fijo de escenarios, dejando el sistema en un estado conocido y reproducible.
Un CLAUDE.md que vuelca arquitectura, reglas de negocio y contrato de API crece sin límite y se desincroniza, porque nada obliga a actualizarlo en el mismo commit que invalida su contenido. La solución es un CLAUDE.md corto que apunta a la documentación real y dice cuándo leer cada documento, sin explicarla.
Cuando el dominio llama directamente a la base de datos o al framework web, los casos de uso dejan de ser testeables sin infraestructura real y la frontera arquitectónica se erosiona sin que el compilador lo note. La solución aísla el core en un proyecto sin dependencias de infraestructura, exponiendo puertos primarios y secundarios que implementan proyectos separados.
En una SPA React sin fronteras internas, la lógica de negocio, el estado y el JSX se mezclan en el mismo componente, encareciendo los tests y acoplando negocio a UI. La solución separa cuatro capas — API, store, casos de uso y componentes presentacionales — cada una testeable con la herramienta más barata que le sirve.
Un frontend o una suite de Playwright que depende del backend real arrastra Postgres, colas y proveedores externos, haciendo el desarrollo lento y los tests no deterministas. API Lite es un segundo host de la misma API con toda la infraestructura sustituida por implementaciones en memoria, para desarrollo y tests deterministas.