pa-10 — Analysis

What the engine must get right

  1. Rules return precise violations; Evaluate.Passed is false iff any rule is violated (the CI gate).
  2. Cycle detection (DFS coloring) is sound; clean DAGs pass.
  3. Layering / fan-out rules are data-driven and deterministic.

Design decisions

  • Rule as an interface. New architectural constraints (naming, ownership, coverage, perf budgets) plug in without touching the engine — the same extensibility as a linter.
  • Report aggregates per rule. CI output names which rule failed and where, so the violation is actionable, not just "build red."
  • Deterministic traversal. Sorted iteration makes violations stable across runs (reviewable diffs) — the book's determinism discipline.
  • Templates as deliverables. The ADR + design-review checklist (steps/) are first-class artifacts: the architect's written tools, not afterthoughts.

Tradeoffs worth flagging

  • Fitness functions enforce the objective, not the wise. They catch cycles and layering breaks; they can't judge whether a boundary is in the right place. Use them to free reviews for judgment, not replace judgment.
  • Too-strict rules get disabled. A fitness function that fires on legitimate exceptions trains people to add //nolint. Allow scoped, reviewed exceptions (with an ADR) rather than blanket suppression.
  • Consensus can't be automated. The hardest part of the role (aligning teams) has no unit test; the templates + practices are the leverage.
  • ADRs rot if not maintained. Supersede (don't edit); link related ADRs; keep them in the repo so they're versioned with the code.

What production adds beyond this lab

  • Real fitness-function tooling wired into CI (ArchUnit/import-linter/ depguard) over the actual import/service graph.
  • An ADR log + RFC process + an architecture review forum; a tech radar.
  • Paved roads (templates, libraries, golden paths) so the right thing is the easy default, plus mentorship and code-review standards.