Escolha a forma. O harness impõe.
Cada blueprint é um YAML com módulos, depends_on, forbidden_imports, mapa de pacotes e trade-offs obrigatórios. Uma arquitetura nova não toca skill, agente nem prompt, e um job de CI confere isso a cada push.
hexagonalDomínio no centro, portas como interfaces, adaptadores de entrada e saída nas bordas, um módulo Maven por adapter.
Mais de um canal de entrada ou saída: REST, mensageria, batch.
hexagonal-single-moduleOs mesmos ports e adapters como pacotes de um módulo Maven só. Adapters não se importam entre si.
Vários canais, sem um POM por adapter.
clean-architecture-multi-moduleDomínio, aplicação e infraestrutura em três módulos Maven; o build impõe a regra de dependência.
Regras de negócio que precisam ficar isoladas da infraestrutura.
clean-architecture-single-moduleA mesma separação num módulo Maven só; os módulos viram pacotes. É a do bank-app.
Três POMs seriam custo que ninguém amortiza.
layeredcontroller → service → repository, com o vocabulário da maioria dos tutoriais de Spring Boot.
O time já fala essa língua, e porta/adaptador seria só tradução.
onionOs termos do próprio Palermo: Application Core e Gateway, um módulo Maven por anel.
O time prefere esses termos aos de hexagonal ou clean.
onion-single-moduleOs anéis do Palermo como pacotes de um módulo Maven só. Persistência e apresentação seguem estranhas uma à outra.
Application Core e Gateway, sem um POM por anel.
vertical-sliceCódigo agrupado por feature: Command/Query, Handler, Endpoint e Response juntos.
As features divergem mais do que se parecem.
modular-monolithVários contextos num deployável, com fronteira mais forte que um pedido educado.
Contextos que ainda não justificam deploys separados.
custom-templateA sua arquitetura, em YAML.
Nenhuma das nove serve.
forbidden_imports
# blueprints/hexagonal.yaml modules: - id: domain depends_on: [] forbidden_imports: - "org.springframework.." - "jakarta.persistence.." - "jakarta.validation.." - id: application depends_on: [domain, commons] forbidden_imports: - "jakarta.persistence.." - "org.springframework.web.."
domain/CLAUDE.mdo modelo sabe.claude/forbidden-imports.txto hook check bloqueia a escrita, exit 2pom.xml · depends_ono compilador recusa, nos layouts multi-module
Os globs das normas (paths) são reescritos a partir do mapa de pacotes na geração, então uma norma carrega só para os pacotes que este blueprint de fato tem.
Validados como dado, depois gerados e buildados
A cada push, o validate.yml roda estas checagens sobre os blueprints:
- Todo blueprint exporta a mesma árvore duas vezes, sem citação morta.
- Todo
templates.<role>resolve para um arquivo que existe. - Um arquivo de blueprint novo não altera skill, agent nem prompt.
hexagonal-single-modulemantém os adapters separados, e a matriz de dez pacotes está completa.
O validate.yml nunca builda um projeto, então o blueprints.yml builda. Para cada blueprint que uma mudança pode afetar, ele gera um esqueleto a partir do YAML, sem modelo de linguagem, e builda com Maven e com Gradle: nove blueprints, duas ferramentas, 18 jobs.
- O esqueleto é o starter do Initializr, moldado pelo blueprint: um reactor a partir de
modules[]edepends_onquando multi-module, umpackage-info.javapor papel do mapa de pacotes. ArchHook.jar boundary-mapeexportescrevem o.claude/do projeto, depois roda./mvnw verifyou./gradlew build, e odoctor gateprecisa estar verde.- Em seguida, uma classe por regra de fronteira importa o que a regra proíbe: o
doctor gateprecisa falhar citando todos esses arquivos, e ocheckprecisa bloquear um deles com exit 2. - Só roda quando muda um blueprint, o
project-bootstrap, o hook ou o schema. Uma mudança sob um blueprint gera só aquele. Não é check obrigatório.
Nos três blueprints -single-module o compilador não impõe a fronteira. Quem impõe é o hook check a cada edição, o doctor gate no CI do projeto e o ArchUnit. O esqueleto não é a geração completa: o teste escreve os próprios build files mínimos, então os POMs que o project-bootstrap adapta de templates/pom.*.xml.example, as dependências das features e os passos do próprio agente não são provados, e nada aqui afirma uma execução ponta a ponta do /init-project.