---
title: "Check each architecture decision with a · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/system-architecture/fitness-functions
id: ARC-87
level: Recommended
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1164
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Check each architecture decision with a fitness function

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [System architecture](https://agentwranglers.se/playbook/architecture/system-architecture.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: ARC-87
- Level: Recommended
- Chapter: [System architecture](https://agentwranglers.se/playbook/architecture/system-architecture.md)
- Rule: Turn each architecture decision that code can break into a test the build runs, called a fitness function. Module borders inside one app get one first.
- Check: Each accepted decision record names its fitness function or says why code cannot break it. A pull request that imports another module's internal file fails the build.
- How: A decision record says what the system must keep true, but only a test keeps it true when people and agents change the code. Module borders inside one deployable app are the first case. Each module is reached only through its public entry point, as [Split off a service only for a written reason](https://agentwranglers.se/playbook/architecture/structure/split-services-for-a-reason.md) needs. Use the dependency tools from [Point dependencies inward](https://agentwranglers.se/playbook/architecture/structure/layers-point-inward.md) for the rule. Other decisions get their own tests, such as a speed budget from a [quality scenario](https://agentwranglers.se/playbook/architecture/system-architecture/quality-scenarios.md). You may replace an old part piece by piece, as [Rewrite behind the old interface](https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor/rewrite-behind-interface.md) says. Then a test counts the calls still going to the old part and fails when the count grows.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Java example

```java
// ArchUnit: other modules reach orders only through its api package
@ArchTest
static final ArchRule ordersInternalsArePrivate = noClasses()
    .that().resideOutsideOfPackage("com.example.shop.orders..")
    .should().dependOnClassesThat().resideInAPackage("com.example.shop.orders.internal..");
```

### TOML example

```toml
# import-linter in pyproject.toml: other modules may not import orders internals
[[tool.importlinter.contracts]]
name = "Orders internals are private"
type = "forbidden"
source_modules = ["shop.billing", "shop.shipping"]
forbidden_modules = ["shop.orders.internal"]
```

### TypeScript example

```ts
// dependency-cruiser: only orders/index.ts may be imported from outside orders/
export default {
  forbidden: [{
    name: 'orders-internals-private',
    severity: 'error',
    from: { pathNot: '^src/orders/' },
    to: { path: '^src/orders/', pathNot: '^src/orders/index\\.ts$' },
  }],
};
```

## Sources

- [Microsoft: Strangler Fig pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig)

## Related rules

- ARC-86 [Write each quality goal as a scenario with a number](https://agentwranglers.se/playbook/architecture/system-architecture/quality-scenarios.md) in Clean code and architecture
- ARC-85 [Split off a service only for a written reason](https://agentwranglers.se/playbook/architecture/structure/split-services-for-a-reason.md) in Clean code and architecture
- ARC-63 [Point dependencies inward](https://agentwranglers.se/playbook/architecture/structure/layers-point-inward.md) in Clean code and architecture
- TKO-14 [Rewrite behind the old interface](https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor/rewrite-behind-interface.md) in Codebase takeover

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/architecture/system-architecture/fitness-functions">Agent Wranglers clean code and architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Write each quality goal as a scenario with a number](https://agentwranglers.se/playbook/architecture/system-architecture/quality-scenarios.md)
- Next: [Choose how fresh each piece of shared data must be](https://agentwranglers.se/playbook/architecture/system-architecture/consistency-model.md)
- [System architecture](https://agentwranglers.se/playbook/architecture/system-architecture.md)
