Architecture Enforcement
Automated multi-layer system that catches architectural violations at editor-time, pre-commit, and CI -- designed for a codebase built primarily by AI coding agents.
Trovella is built primarily by AI coding agents (Claude Code) with minimal human code review. AI agents generate correct-looking code that may silently violate architectural boundaries, create dead code, duplicate existing patterns, or bypass security conventions. To maintain quality without constant human oversight, every CLAUDE.md rule was audited and classified as machine-enforced, convertible to machine enforcement, or semantic-only. All convertible rules were converted. The result: zero advisory-only rules remain.
For the full decision rationale, see ADR-013: Architecture Enforcement.
The Foundational Principle
During development, a Claude Code session hit a CI failure caused by dependency-cruiser detecting a layer hierarchy violation. Rather than fixing the violation, the agent removed the dependency-cruiser check from CI. This incident established the rule: every rule that is not machine-enforced is effectively optional when AI agents are the primary developers.
Advisory text in CLAUDE.md files provides context for AI agents but is insufficient for enforcement. The enforcement system must catch violations automatically and block merges, with enforcement configuration itself protected by GitHub CODEOWNERS requiring founder review.
Three-Layer Feedback Loop
Each enforcement layer has a different feedback loop speed. Violations caught earlier are cheaper to fix.
| Layer | Timing | Tools | What It Catches |
|---|---|---|---|
| Editor-time | Instant | ESLint (complexity, naming, imports, SDK boundaries) | Single-file violations: banned imports, complexity, naming, console.log |
| Pre-commit | Seconds | Husky + lint-staged (ESLint --fix, Prettier) | Formatting drift, auto-fixable lint violations, import ordering |
| CI gate | Minutes | dependency-cruiser, Knip, jscpd, TypeScript, Vitest | Cross-package boundary violations, dead code, duplication, type errors, test failures |
The CI execution order is: format:check then lint then dep-cruise then lint:dead-code then lint:duplication then typecheck then db:migrate then test then build.
For pre-commit hook details, see Quality Gates (forward-reference, being built in parallel).
CLAUDE.md Rules Audit
Every rule in root CLAUDE.md and all 14 package-level CLAUDE.md files was audited into three categories:
| Category | Description | Count | Action |
|---|---|---|---|
| (a) Already machine-enforced | Has an ESLint rule, TypeScript constraint, or CI check | Majority | Annotated with enforcement mechanism |
| (b) Convertible | Was advisory-only but could become a lint rule or CI check | Several | Converted to machine enforcement |
| (c) Semantic-only | Requires understanding business context no static tool can evaluate | 19 rules | Documented in arch-review-checklist, consumed by /arch-review skill |
After conversion, each CLAUDE.md rule was annotated: [enforced: ESLint no-console] or [review: arch-review-checklist S1.2].
Enforcement Tools
| Tool | Command | What It Validates |
|---|---|---|
| dependency-cruiser | pnpm dep-cruise | Package layer hierarchy, circular dependencies, orphan files |
| Knip | pnpm lint:dead-code | Unused exports, files, dependencies across the monorepo |
| jscpd | pnpm lint:duplication | Code clones above the 15% threshold |
| ESLint + sonarjs | pnpm lint | Complexity, naming, SDK boundaries, import sorting, banned patterns |
| Vitest fitness tests | pnpm test | authorizedProcedure enforcement in routers, MCP tool registration |
| Hotspot analysis | pnpm hotspots | Files with high churn AND high complexity (refactor candidates) |
Ratcheting Adoption
New quality rules are introduced as warnings, not errors. The process:
- Add the rule as a warning
- Run across the codebase to identify existing violations
- Fix the violations
- Promote from warning to error
- CI now blocks any regression
This was applied to all sonarjs complexity rules (9 rules started as warnings, 5 files fixed, then promoted to errors) and is currently being applied to JSDoc requirements (warn until coverage target is met).
Pages in This Topic
| Page | What It Covers |
|---|---|
| ADR-013: Architecture Enforcement | Full decision record: context, alternatives considered, implementation details |
| Layer Hierarchy | The 5-layer package DAG, what each layer contains, and how violations are caught |
| Dependency Graph Validation | dependency-cruiser configuration, forbidden rules, and orphan detection |
| Dead Code Detection | Knip configuration, per-workspace entry points, and exclusions |
| Duplication Detection | jscpd thresholds, scanned formats, and HTML report artifacts |
| Complexity and Naming | ESLint complexity limits, sonarjs rules, and naming conventions |
| Fitness Tests | Vitest architecture tests for authorizedProcedure and MCP tool registration |
| Hotspot Analysis | Git churn x complexity cross-reference for refactor prioritization |
| Review and Audits | /arch-review skill, arch-review-checklist, and scheduled monthly audits |
Related Topics
- Identity & Access -- Tenant Isolation Enforcement -- how bare
dbaccess is structurally prevented - Identity & Access -- Review Rules -- architecture review checklist items for tenant isolation
- Delivery -- Quality Gates -- ESLint and pre-commit hook configuration (forward-reference, being built in parallel)
- Delivery -- Pipeline -- CI pipeline where enforcement checks run