Architecture Checks¶
Enforce architecture rules from a YAML spec — a project that breaks them fails the build. A component is a layer (controller/service/repository) or a functional module, matched by fully-qualified class-name regex, so one mechanism covers both granularities.
java -jar core/target/aic-cli.jar --scan=<proj> --arch=layered # built-in template
java -jar core/target/aic-cli.jar --scan=<proj> --arch=./my-arch.yaml # your own rules
In the web UI, pick a template from the Architecture dropdown next to the path field; the result shows as a banner (green when compliant, red listing violations).
Or let the project own its rules
A project can enable the architecture check (with a template or an inline spec) in its
aic-check.yaml — then no --arch flag or dropdown selection is needed.
Built-in templates¶
| Template | Idea |
|---|---|
layered |
Web → Service → Repository → Domain |
hexagonal |
Ports & Adapters: Adapter → Application → Domain |
onion |
Onion / Clean: Infrastructure → Application → Domain |
Spec schema¶
name: Layered
components:
- name: Web
matches: ['.*\.controller(\..*)?$', '.*\.web(\..*)?$']
- name: Service
matches: ['.*\.service(\..*)?$']
- name: Repository
matches: ['.*\.repository(\..*)?$', '.*\.repo(\..*)?$']
- name: Domain
matches: ['.*\.domain(\..*)?$', '.*\.model(\..*)?$']
access: # allow-list: a component may depend ONLY on those listed
Web: [Service, Domain]
Service: [Repository, Domain]
Repository: [Domain]
Domain: []
forbidden: # explicit deny edges (independent of access)
- from: Domain
to: Web
naming: # required class simple-name regex per component
Repository: '.*Repository$'
options:
ignoreUnmatched: true
forbidCycles: true
Rules¶
- access — an allow-list per component; depending on anything not listed is a violation.
- forbidden — explicit denied edges, independent of
access. - naming — class simple names in a component must match the regex.
- forbidCycles — no dependency cycle between components.
Defaults when omitted¶
| Spec field | Default |
|---|---|
access |
no allow-list (subject only to forbidden) |
forbidden |
none |
naming |
none |
options.ignoreUnmatched |
true (classes matching no component are skipped). Set to false to flag any first-party class that matches no component as an unmatched violation. |
options.forbidCycles |
false |
Output¶
The result appears under architecture in the JSON envelope (specName,
compliant, violations[]), and any violation makes the CLI exit 1.