resources/skills/x-execute-mutation-tests/SKILL.md
Conditional mutation-testing gate (PIT/Stryker) with kill-rate threshold.
npx skillsauth add edercnj/claude-environment x-execute-mutation-testsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Runs mutation testing scoped to application + domain layers, validates the mutation score
against quality.mutation.threshold, enforces quality.mutation.runtime-cap-min, and
blocks merge when score < threshold. Skips gracefully when no language/framework is declared.
| Language / Framework | Tool | Min Version | Container Image |
| :--- | :--- | :--- | :--- |
| Java + Maven | PIT (pitest-maven) | 1.15 | maven:3.9-eclipse-temurin-21 |
| Java + Gradle | PIT (gradle-pitest) | 1.15 | eclipse-temurin:21 |
| JS / TypeScript | Stryker | 8.0 | node:20-slim |
| Python | mutmut | 2.4 | python:3.12-slim |
| Go | go-mutesting | 0.3 | golang:1.22-alpine |
When language is absent or unrecognized: emit WARN "no language declared — skipping mutation", exit 0.
Parsed from quality.mutation block (all fields optional):
quality:
mutation:
enabled: true
threshold: 80 # default 80 — minimum mutation score %
runtime-cap-min: 20 # default 20 — hard abort limit in minutes
exclude-packages: # default list; append to extend
- "**test**"
- "**generated**"
- "**infrastructure/adapter**"
thresholds:
per-package: # optional per-package override
"dev.iadev.domain": 90
"dev.iadev.adapter": 70
tool-versions: # optional pin
pitest: "1.15.3"
stryker: "8.2.6"
Default exclusions (boilerplate generating trivial surviving mutants):
**/test/** — test code itself**/generated/** — generated sources**/infrastructure/adapter/** — JDBC/HTTP adapters killed only by mocks| Code | Numeric | Condition |
| :--- | :--- | :--- |
| SUCCESS | 0 | Score ≥ threshold within time cap |
| MUTATION_SCORE_BELOW_THRESHOLD | 1 | Score < threshold |
| MUTATION_RUNTIME_CAP_EXCEEDED | 2 | Execution time > runtime-cap-min |
| TOOL_NOT_FOUND | 3 | Required mutation tool not on PATH / not in classpath |
| MUTATION_CONFIG_INVALID | 4 | Invalid config (e.g., path traversal in exclude-packages) |
| MUTATION_DISABLED | 50 | quality.mutation.enabled=false — early exit, no error |
Load quality.mutation from project YAML. If enabled=false → exit MUTATION_DISABLED (50).
Reject exclude-packages entries containing ../ or absolute paths:
MUTATION_CONFIG_INVALID with message: "path traversal detected in exclude-packages: <value>".Inspect project YAML language + framework → resolve tooling from dispatch matrix.
If language absent/unrecognized: emit WARN, exit 0.
Verify the resolved tool is available:
mvn pitest:mutationCoverage --version dry-run or mvn help:describe -Dplugin=org.pitest:pitest-maven<tool> --versionOn failure → exit TOOL_NOT_FOUND (3).
Invoke tool with timeout = runtime-cap-min minutes:
Java/Maven (PIT):
timeout $((runtime_cap_min * 60)) mvn pitest:mutationCoverage \
-DtargetClasses="dev.iadev.domain.*,dev.iadev.application.*" \
-DexcludedClasses="$(exclusions_csv)" \
-Dthreads=4 \
--no-transfer-progress
Stryker (JS/TS):
timeout $((runtime_cap_min * 60)) npx stryker run \
--mutate "src/domain/**/*.ts,src/application/**/*.ts" \
--timeoutMS $((runtime_cap_min * 60 * 1000))
mutmut (Python):
timeout $((runtime_cap_min * 60)) mutmut run \
--paths-to-mutate domain/,application/
go-mutesting (Go):
timeout $((runtime_cap_min * 60)) go-mutesting ./domain/... ./application/...
On timeout signal: exit MUTATION_RUNTIME_CAP_EXCEEDED (2), report remaining packages.
Extract mutation score from tool output:
| Tool | Score field |
| :--- | :--- |
| PIT | target/pit-reports/*/mutations.xml → <totals killed>/<totals total> |
| Stryker | reports/mutation/mutation.json → metrics.mutationScore |
| mutmut | mutmut results stdout → Survived:N / Total:T |
| go-mutesting | stdout X of Y mutations have been killed |
Score = (killed / total) * 100. Apply per-package overrides when configured.
If score < threshold:
MUTATION_SCORE_BELOW_THRESHOLD (1).class/method/line.Write mutation report to ai/epics/epic-XXXX/reports/mutation-report-STORY-ID.md
using template _TEMPLATE-MUTATION-PLAN.md.
Report MUST NOT contain:
exclude-packages values are validated before any filesystem access (Step 2).../, / as prefix) → hard reject.This skill activates when ANY of the following capabilities is enabled in the project profile:
quality.mutation.java-pit — Java with PITquality.mutation.stryker — JS/TS with Strykerquality.mutation.mutmut — Python with mutmutquality.mutation.go-mutesting — Go with go-mutestingWhen none is present, the skill is excluded from the generated .claude/skills/ output
(conditional composition via Rule 28 requires-any).
tools
Documentation automation v2: stack-aware generation from documentation.targets.
development
Generates or updates CI/CD pipelines per project stack with actionlint validation.
tools
Generates ADRs from architecture-plan mini-ADRs with sequential numbering and index update.
development
Formats source code; first step of the pre-commit chain (format -> lint -> compile).