Files
werkator/docs/prs/2026-10-04-PR104-mutation-crap-limits.md
miandmhoennig 7d445dc673
werkator build succeeded after 01:46
werkator/deploy build succeeded after 00:08
Mutation-CRAP target 15 for Kotlin, red from 12, gate as ratchet (v1.34.1) (#104)
- Target: Mutation-CRAP at most 15 for Kotlin, code city red from 12 (score never below complexity; JaCoCo counts compiler-generated Kotlin branches).
- Gate `maxMutationCrap = 650` as a ratchet (today max 647.55), lowered with every refactoring PR down to 15.
- werkcrappit 0.15.0 -> 0.16.4 for `codeCharta.colorRedFrom`.
- AGENTS.md: rule, ratchet, split along domain steps.

PR-doc: `docs/prs/2026-10-04-PR#104-mutation-crap-limits.md`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #104
2026-10-04 10:14:06 +02:00

74 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> **WARNING:** This document describes only the change applied in this PR.
> It may already be outdated once the next PR is merged.
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
## The Problem
The nightly build `mutation` reports every method's Mutation-CRAP, but it judged nothing: no limit, and the code city coloured by werkcrappit's defaults.
The first full report has 108 methods at 10 or above, the limit used for Java projects.
The score is `C² × (1 − MS)³ + C`, so it never falls below the method's complexity: a limit of 10 is also a complexity limit of 9, however well a method is tested.
JaCoCo counts the branches of the bytecode, and the Kotlin compiler adds branches nobody wrote: the implicit `else` of an exhaustive `when`, the branches of inlined `let` and `takeIf`.
Java's 10 would therefore ask for smaller methods than the same code needs in Java.
![CodeCharta Mutation CRAP Metric before](./.2026-10-04-PR104-mutation-crap-limits/mutation-crap-codecharta-before.png)
## Non-Goals
- No method is changed here; the refactorings follow, one PR per domain area.
- No limit for Java projects: they keep 10.
- `?.` and `?:` stay real branches: a surviving mutant there is a missing test, and the mutation part of the score still says so.
## The Scenarios
### Feature: Werkator's methods aim at a Mutation-CRAP of at most 15
#### Scenario#104.01: The code city shows red from 12
So that the methods to look at next stand out before they reach the limit.
- **Given** the nightly build `mutation`
- **When** werkcrappit writes the code city and its viewer link
- **Then** a method from 12 on is red, from 6 on yellow
##### Verified by
- The build definition `mutation` on werkator.javagil.de, whose code city link carries the colour range.
#### Scenario#104.02: The gate is a ratchet towards 15
So that nothing gets worse while the 45 methods above 15 are refactored, and the nightly build keeps its meaning.
- **Given** today's highest score of 647.55
- **When** the nightly build runs with `maxMutationCrap = 650`
- **Then** it passes today and fails as soon as a method scores above 650
- **And** every refactoring PR lowers the limit to just above the new highest score, until it reaches 15
##### Verified by
- The build definition `mutation` on werkator.javagil.de (`mutationCrapCheck`).
## The Solution
- werkcrappit 0.15.0 → 0.16.4, for `codeCharta.colorRedFrom`.
- `maxMutationCrap = 650` and `colorRedFrom = 12` in `build.gradle.kts`, with the reasoning as a comment.
- `AGENTS.md` states the target, the ratchet, and that a method above 15 is split along its domain steps.
Why 15 and 12:
| Score | Methods at or above | of which by complexity alone | of which by weak tests |
| ----- | ------------------- | ---------------------------- | ---------------------- |
| 10 | 108 | 58 | 50 |
| 12 | 84 | 34 | 50 |
| 15 | 45 | 15 | 30 |
At 15 the complexity cases left are the genuine ones (`BuildExecutor.execute` 40, `SystemMetricsCollector.sample` 35, `BuildDefinition.applyTo` 34); the test gaps stay almost all visible.
NIST SP 500-235 names 10 as the complexity limit and up to 15 as acceptable for experienced teams with well-tested code.
## Additional Changes
- Version 1.34.1 with its release note.
## Follow-up PRs
- The home page's repository card (`HomeCardView.from`, `HomeTexts.meta`), then `BuildExecutor.execute`, `ConfigLoader`, metrics and sizing, the Forgejo export, and the environment probes; each lowers the ratchet.