Reglas de arquitectura
codarch diff puede evaluar una política versionada en .codarch.yml. Las reglas no se guardan en
el snapshot: el snapshot dice cómo es el código; la configuración dice cómo debería ser.
Ejemplo
Sección titulada «Ejemplo»version: 1
layers: - name: domain paths: - src/domain/** - name: application paths: - src/application/** - name: infrastructure paths: - src/infra/**
rules: - name: domain-no-infra type: forbidden from: domain to: infrastructure severity: error message: El dominio no puede depender de infraestructura
- name: complejidad-maxima type: threshold metric: maxComplexity max: 40 severity: warn
- name: sin-ciclos type: cycles severity: errorPerfiles
Sección titulada «Perfiles»Un perfil es una configuración de reglas escrita de antemano. codarch profiles lista el catálogo:
codarch profilescodarch profiles --jsonEl catálogo de hoy:
| Perfil | Para repos con | Capas |
|---|---|---|
capas | src/domain, src/application, src/infra | domain, application, infrastructure |
hexagonal | puertos en el centro y adaptadores fuera | domain, application, adapters |
onion | capa de presentación propia | domain, application, infrastructure, presentation |
ddd | modelo, servicios y repositorios | domain, application, infrastructure |
Los repos que se organizan por módulo o por feature no encajan en ningún perfil estático: sus capas las decide el repositorio, y por eso las propone el generador.
Para usar un perfil, en .codarch.yml:
version: 1profile: capasEl perfil aporta sus capas y sus reglas, y el equipo puede añadir las suyas encima. Lo que trae el
perfil entra como aviso (warn): consulta, no bloquea. Una regla del equipo con el mismo nombre
sustituye a la del perfil, así que endurecerla es escribirla otra vez con severity: error:
version: 1profile: capasrules: - name: dominio-sin-infraestructura type: forbidden from: domain to: infrastructure severity: errorEn el reporte, cada violación dice de dónde sale (source: "config" o source: "profile") y el
reporte lleva el perfil aplicado (rules.profile). Así nadie bloquea un PR por una regla que no
escribió, y endurecer una es una decisión consciente.
Endurecer un perfil
Sección titulada «Endurecer un perfil»Por defecto las reglas de un perfil son avisos. Cuando el código esté preparado, se suben de golpe:
version: 1profile: capasprofile_severity: errorTambién se puede endurecer una sola regla, escribiéndola en el archivo del equipo con el mismo nombre: lo del equipo sustituye a lo del perfil.
Perfiles propios
Sección titulada «Perfiles propios»Un equipo puede guardar sus convenciones como perfil, en el mismo archivo:
version: 1profile: mi-equipoprofiles: - id: mi-equipo title: Convenciones del equipo layers: - name: nucleo patterns: [src/nucleo/**] - name: extras patterns: [src/extras/**] rules: - name: nucleo-sin-extras type: forbidden from: nucleo to: extrasLos perfiles propios tienen la misma forma que los del catálogo y también entran como aviso.
Generar las capas
Sección titulada «Generar las capas»Si el repo no encaja en ningún perfil, codarch suggest deduce la estructura del propio código:
codarch suggest .codarch/snapshot.cc.jsoncodarch suggest .codarch/snapshot.cc.json --jsonAgrupar los ficheros por carpeta, mirar el grafo de dependencias y ordenar las capas de más interior
a más exterior. Con eso propone unas capas y las reglas que las protegerían, en un fragmento listo
para .codarch.yml:
version: 1layers: - name: src/domain paths: - src/domain/** - name: src/infra paths: - src/infra/**rules: - name: src-domain-sin-src-infra type: forbidden from: src/domain to: src/infra severity: warn message: src/domain no debe depender de src/infraEs la versión 0.01 del generador: agrupa por el primer y segundo nivel del directorio y supone que las dependencias van hacia dentro. Los ficheros sueltos en la raíz (los puntos de entrada) no forman capa, y el comando lo dice.
Además dice qué perfil del catálogo encaja con lo que ha deducido, y si el código incumple hoy alguna de sus reglas:
Encaje con el catálogo de perfiles:
capas 2 de 3 capas · cubre el 100% del código hexagonal 2 de 3 capas · cubre el 100% del código onion 2 de 4 capas · cubre el 100% del código
Con el perfil "capas", el código incumple hoy 1 regla: · El dominio no debe depender de la infraestructuraCuando un perfil encaja, la propuesta usa sus capas y reglas, no las que se deducen del código: la convención la pone el perfil. Si no encaja ninguno, la propuesta se deduce del grafo (y entonces el orden de las capas sale de lo que el código ya hace).
Propone, no decide: la salida se revisa y se pega. Como las reglas del perfil, salen como aviso.
patterns(o su aliaspaths) son globs relativos al root del proyecto, con/.- Se evalúan en orden: gana la primera capa que coincide.
- Un fichero sin capa no participa en reglas
forbidden. - Los patrones no pueden ser absolutos. Los
\se normalizan a/. - Para una regla de capas solo cuentan las aristas internas que el analizador pudo resolver.
forbidden
Sección titulada «forbidden»- name: domain-no-infra type: forbidden from: domain to: infrastructure severity: error message: "El dominio no puede depender de infraestructura"Marca cada arista de head que va de from a to. La clave de la violación es la regla y la pareja
de ids de fichero, así que mover el mismo import no crea una violación nueva.
threshold
Sección titulada «threshold»- name: complejidad-maxima type: threshold metric: maxComplexity max: 40 severity: warnEvalúa la métrica por fichero. Se puede usar max, min o ambos; al menos uno es obligatorio. Si
la métrica no existe en un fichero, no se evalúa. Un fichero nuevo que ya nace fuera de rango cuenta
como violación introducida.
maxComplexity incluye todas las funciones implementadas, también los callbacks anónimos. La lente
de símbolos solo lista las declaraciones con nombre; las dos cifras pueden no coincidir.
- name: sin-ciclos type: cycles severity: errorMarca los componentes fuertemente conexos de head (tamaño > 1 o self-loop) del grafo de
ejecución: una arista cuenta si weight > typeOnly. Los imports que solo son de tipos siguen en
el snapshot, pero no cierran un ciclo ni violan esta regla. La clave usa los ids del componente: un ciclo
que cambia de tamaño aparece como uno resuelto y otro introducido.
Severidad y gate
Sección titulada «Severidad y gate»| Severidad | Se muestra | --fail-on violations |
|---|---|---|
info | sí | no |
warn | sí | no |
error | sí | sí, si es introducida |
--fail-on:
none: nunca falla por hallazgos (por defecto).cycles: falla si hay ciclos nuevos.violations: falla si hay violaciones introducidas con severidaderror.hotspots: falla si hay hotspots nuevos.any: combina las tres anteriores.
El código de salida es 2 cuando falla el gate y 1 cuando hay un error de lectura o de
configuración. Así un workflow distingue “el PR rompe la política” de “la herramienta falló”.
Qué se considera nuevo
Sección titulada «Qué se considera nuevo»Se evalúan base y head y se comparan las claves estables de las violaciones:
introduced: está en head y no en base.existing: está en ambos; es deuda previa y no bloquea.resolved: estaba en base y ya no está en head.
Esto permite adoptar reglas en un repo con deuda sin congelar todos los PRs.
codarch diff base.cc.json head.cc.jsonbusca.codarch.ymlo.codarch.yamlen el cwd.--config ruta.ymlusa otra política.--no-configdesactiva las reglas por completo.
La configuración no se copia al snapshot ni al mapa. El reporte incluye un bloque rules con el
resumen y las violaciones; ver modelo.
Alcance
Sección titulada «Alcance»ignore es una lista de patrones con sintaxis de .gitignore, relativa a la raíz del proyecto. No
es una regla: se aplica antes de recorrer,
así que un fichero excluido no entra en el snapshot, las métricas, los ciclos ni el checksum.
codarch analyzeycodarch serveleen el.codarch.ymlde la raíz; el análisis en navegador lee el mismo archivo al abrir el repositorio.codarch analyze --config <file>usa otro archivo;--no-configno lee ninguno.--ignore <patrón>suma una exclusión para esa ejecución; no reemplaza la lista del repo.diff,rendereinspectconsumen el snapshot y no vuelven a filtrar.get_project_configdel MCP devuelveignorepara que un agente explique el alcance.
No hay una exclusión por defecto de tests ni de fixtures: cada repo decide qué es arquitectura.
Límites actuales
Sección titulada «Límites actuales»- No hay reglas a nivel de símbolo ni de carpeta agregada.
- No hay
ignorepor línea en las reglas ni baseline separado; la deuda se reconoce por comparación con base. Elignoredel.codarch.ymles de alcance, no de reglas. - Los globs no entienden el alias
@/de TypeScript: se aplican a rutas ya resueltas del árbol. - Las reglas no modifican el código ni generan arreglos.