Skip to content
SQA Cockpit

ADR-0018 — Clean Code and Clean Architecture as load-bearing standard

ADRsUpdated 6 min readEdit on GitHub ↗
4 sections··

ADR-0018 — Clean Code and Clean Architecture as load-bearing standard #

  • Status: Accepted
  • Date: 2026-05-07
  • Deciders: Natan
  • Source: Robert C. Martin, Clean Code (2nd ed., 2025) and

Clean Architecture (2017). Audit and synthesis captured in PRD-04 ↗.

Context

Context #

Through ADR-0017 we have accumulated 17 architectural decisions that overlap heavily with Robert C. Martin's Clean Code and Clean Architecture. We've made the choices independently — but the books name them with names other contributors already know: the Stepdown Rule, the Dependency Rule, ADP/SDP/SAP, the F.I.R.S.T. test properties, the five-outcome envelope as a generalisation of JUnit's pass/fail/error/skipped.

A May 2026 audit of the codebase against the books surfaced three classes of issue:

  1. Conformance is high but uneven. Most lib and component

code obeys the books' rules; a few files (e.g. src/components/s3/ready.ts's 5-arg ready(), src/components/api/version.ts's boolean return) contradict rules already implicit in our ADRs.

  1. The rules aren't pinned anywhere. A reviewer who hasn't

read the books can't cite a "Stepdown Rule violation" because the rule has no name in our docs. Disagreements default to taste rather than to a chapter and an ADR.

  1. Drift is invisible. No mechanical gate catches process.env.X

in lib/, framework imports outside their assigned home, file- size inflation, or commented-out code on its way in. make gate (LLM doc-sync) is broad but not laser-focused on these.

We considered three options.

  1. Don't ratify. Keep the audit as informational; rely on

reviewer judgement. Cheap, but the project loses the recurring ability to point at "rule N, see chapter M" when the same drift reappears in a year.

  1. Ratify the books wholesale. Adopt every rule as binding.

Concise, but several rules don't translate to TypeScript (e.g. the abstract-class density metric A from CA Ch. 14 is shaky under structural typing) and a few are taste calls Martin himself flags as opinion.

  1. Ratify a project-specialised subset. Adopt the rules that

fit the codebase's shape, name where they specialise existing ADRs, list the rules we explicitly don't take, and back them with mechanical gates where mechanically checkable.

Decision

Decision #

Adopt option 3. Clean Code (2nd ed., 2025) and Clean Architecture (2017) become the named source for code-quality and architectural standards in this project. The specialised rules, their sources, and their enforcement live in docs/concepts/code-standards.md; the mechanical subset is enforced by make standards (see scripts/checks/standards.ts).

Concretely:

What this ADR commits us to #

  • The Dependency Rule (CA Ch. 22) is binding. Source-code

dependencies in src/ point inward only: index.tssystems/components/lib/config/. Mechanically enforced.

  • Pure-function checks (ADR-0012) stand. Every probe and

segment returns a Result; no throws across boundaries. src/components/api/version.ts's boolean return is the one documented violation, scheduled for remediation in PRD-04.

  • Frameworks are details (CA Ch. 32). Third-party SDKs are

imported in exactly one file each. Mechanically enforced.

  • Function size, argument count, and file size follow CC's

thresholds: ~12-line comfort, 20-line soft cap, 50-line warning, 80-line failure for functions; ≤3 args; 200-line sweet spot, 500-line hard cap for files. Mechanically enforced where possible.

  • Comment discipline (CC Ch. 5 + DOC-STD §3) is binding. No

commented-out code, no journals, no TODOs in source. Mechanically enforced.

  • F.I.R.S.T. tests are the standard. Component and lib

modules without tests are flagged by make standards.

  • docs/concepts/code-standards.md is the canonical reference

for the named rules. make gate (the LLM doc-sync hook) reads it.

What this ADR explicitly does not adopt #

  • The A (abstractness) metric and Main Sequence (CA Ch. 14).

Useful for large multi-package systems; this is a single- package CLI under 10K lines. Revisit if the project ever splits into multiple deployable components.

  • **Hexagonal/Ports & Adapters as the canonical architecture

vocabulary.** The three-layer split named by ADR-0001 plus the Dependency Rule does the same job with vocabulary the team already shares.

  • TDD as a requirement. Tests are required for lib/ and

components/; the order of writing them is left to the author. ADR-0012's purity contract is what makes tests cheap, not TDD itself.

  • 100% coverage as a hard target. CC Ch. 18 frames it as an

asymptote; we read it the same way and don't gate merges on a coverage number.

  • Acceptance tests as requirements documents (CC Ch. 16).

PRDs do that job here; replicating it would duplicate scope.

Falsifiability #

This ADR holds if and only if:

  • (a) Concrete rule violations get cited by name and chapter

in PR review (e.g. "Stepdown Rule, CC Ch. 7"), not by hand-wave taste. Predicted because ratifying the names is the point.

  • (b) make standards catches at least one real regression

before it lands on master within six months of adoption. Predicted because the audit found 8+ surface drift items already.

  • (c) A new contributor with no prior context can read

code-standards.md once and review code against it. Predicted because the file is structured around named rules, each with a source, an enforcer, and a project specialisation.

Revisit if any of (a)/(b)/(c) doesn't hold within six months. If (a) fails the rules aren't sinking in — the doc is too long or the names are wrong. If (b) fails either the gate is too lax or the audit was wrong about the project's drift surface. If (c) fails the doc has rotted relative to the code — sweep it before discarding.

Consequences

Consequences #

  • Pro: Reviewers and contributors share a named vocabulary

for code quality, anchored in two widely-read books. Cite CC Ch. 7 or CA Ch. 22 and a reader knows where to look.

  • Pro: make standards makes drift visible at commit time,

not at review time. A reviewer's job shifts from spotting mechanical issues to evaluating the design ones the gate can't see.

  • Pro: code-standards.md plus this ADR plus PRD-04 form a

stable triangle: rule, ratification, remediation. Future audits start by re-reading this triangle, not by re-reading the books.

  • Con: New mechanical rules can over-fire on legitimate

exceptions. Mitigated by an explicit STANDARDS_ALLOW comment in the file under audit (// STANDARDS_ALLOW: <rule> — <reason>) and a documented entry in code-standards.md.

  • Con: Two-source documentation (a paid book and an internal

doc) has higher rot risk than one. Mitigated by treating code-standards.md as the source of truth for what we adopt; the book is cited but not duplicated.

  • Con: make standards is one more thing that can fail in

CI. Mitigated by making it advisory in dev (make standards exits 0 with warnings) and binding only in make ci (where warnings escalate to failures via a --strict flag).

See also

See also #

the rule list this ADR ratifies.

the mechanical gate.

the audit findings as dispatchable sub-items.

this ADR maps onto Clean Architecture's concentric circles.

make standards enforces.

invariant make standards enforces.

make standards enforces.

Result-envelope contract this ADR ratifies as canonical.

  • Clean Code, Robert C. Martin, 2nd ed., 2025.
  • Clean Architecture, Robert C. Martin, 2017.
Was this page helpful?