Fitness Function Design
Kata: Design a fitness function for an architectural rule. Pick a rule from your team's actual codebase - written in an ADR or implicit - and implement a check that runs automatically and gates merges.
Retrieval Prompts
- What is the difference between a unit test and a fitness function?
- Name three shapes a fitness function can take.
- What are the three states for an architectural claim with respect to automation?
- Why is an exemption path required for a fitness function to be usable?
- What does "fitness functions make reviews unnecessary" get wrong?
Compare and Distinguish
- Static checks vs runtime metric thresholds. When is each appropriate?
- Fail-fast (PR CI) vs observe-and-report (nightly). What risks does each mitigate, and what does each miss?
- Enforcing vs documenting a rule. Why does an enforced rule decay slower?
- Claim vs check. Why is the translation lossy, and what does that mean for unmonitored dimensions?
Common Mistake Check
Diagnose the problem in each:
- A fitness function is added to CI but runs only on a subset of the repo (the author's service). (partial coverage becomes proof of absence)
- A rule is recorded as "ADR-0052 says no synchronous billing calls" but no fitness function exists. (documented but not enforced - will rot)
- Exemptions are allowed without expiration. (permanent loophole - rule is effectively off for any module with one exemption)
- A fitness function reports percentages instead of pass/fail, blocking no PRs. (metric without a threshold is not a gate)
- A fitness function duplicates a unit test and adds no architectural value. (misclassified; no one will maintain it)
Mini Application
Design and ship one fitness function:
- Pick a claim. Choose an architectural rule your team cares about. Write it in one sentence.
- State its current enforcement. Doc-only, code-review-only, or automated? Why?
- Pick a shape. Static analysis (ArchUnit, dependency-cruiser, eslint rule), metric threshold (SLI + budget), contract test, or structural test.
- Implement. Write the rule in ~1-3 hours. Target a single repo.
- Gate CI. PR blocks on failure.
- Exemption path. Annotations or waivers must have an expiration; exemptions are listed on a dashboard or README.
- Document. In the ADR (or in a new one if the claim was undocumented), link the fitness function and state where it runs.
Candidate Fitness Functions (Pick or Adapt)
- No direct imports across service boundaries (ArchUnit / dependency-cruiser)
- No cyclic dependencies between modules
- Maximum cyclomatic complexity per function
- All outbound HTTP calls use the configured client (no raw
fetch/http.Get) - Secrets not committed (gitleaks / trufflehog in CI)
- p99 latency under budget for a named endpoint (synthetic probe + alert)
- API schema matches consumer expectations (contract test with consumer snapshots)
- No cross-team DB queries (lint on connection string references)
Critique and Rewrite
Take a fitness function you find in a public repo or a sample project. Critique:
- what claim does it enforce, and is that claim explicitly documented in an ADR?
- where does it run, and what drift would it miss?
- what is the exemption policy, and is it expirable?
- is it a true architectural check, or is it a unit test in disguise?
Evidence Check
This page is complete only when you can:
- translate one architectural claim into an automated check in under 3 hours
- defend the automation shape (static, metric, contract) with one paragraph
- design an exemption path that does not permanently disable the rule
- link the fitness function to the ADR whose claim it enforces
- identify at least one architectural claim you cannot yet automate, with a reason