From claude-swe-workflows
Runs mutation testing workflow: mutates source code, executes tests per mutation, identifies survivors, generates tests for them, commits per module. Multi-session progress tracking in .test-mutations.json.
npx claudepluginhub chrisallenlane/claude-swe-workflows --plugin claude-swe-workflowsThis skill uses the workspace's default tool permissions.
Systematically introduces small changes (mutations) to source code, runs the test suite after each, and reports which mutations survive (tests don't catch them). Surviving mutations reveal genuine test coverage gaps that line coverage misses.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Systematically introduces small changes (mutations) to source code, runs the test suite after each, and reports which mutations survive (tests don't catch them). Surviving mutations reveal genuine test coverage gaps that line coverage misses.
Mutation score > line coverage. A test that executes code but doesn't assert on results gives 100% line coverage and 0% mutation score. Mutation testing answers the real question: if a bug were introduced here, would the tests catch it?
Multi-session by design. Mutation testing is slow — each mutation requires a full test run. Progress is tracked in .test-mutations.json so you can work through a codebase incrementally across sessions.
Autopilot by default. After initial setup, the workflow runs unattended through all in-scope modules. It addresses all surviving mutations, commits after each module, and moves on. Human intervention is only needed during setup (scope selection, test command verification) and if an unrecoverable error occurs.
┌─────────────────────────────────────────────────────┐
│ TEST MUTATE │
├─────────────────────────────────────────────────────┤
│ SETUP (interactive) │
│ 1. Initialize (load or create tracking file) │
│ 2. Detect test command (first run only) │
│ 3. Determine scope (user selects, default: all) │
│ │
│ EXECUTION (autopilot — no user interaction) │
│ For each module in scope: │
│ 4. Spawn qa-test-mutator agent │
│ 5. Update tracking file with results │
│ 6. Spawn SME to write tests for ALL survivors │
│ 7. Verify (new tests pass + re-mutate confirms) │
│ 8. Commit changes │
│ 9. Final summary │
└─────────────────────────────────────────────────────┘
Check for .test-mutations.json in the project root.
If the file exists:
If the file doesn't exist:
.test-mutations.json to version control, or add it to .gitignore?"Try in order:
Makefile with a test target → make testpackage.json with a test script → npm testgo.mod present → go test ./...pyproject.toml or pytest.ini or setup.cfg with pytest config → pytestCargo.toml → cargo testbuild.gradle or build.gradle.kts → gradle testIf none detected: Ask the user: "What command runs your test suite?"
Verify the command works by running it once. If it fails, report the error and ask the user for the correct command.
Store the test command in the tracking file.
Use Glob to find source files in the project. Exclude:
*_test.go, test_*.py, *.test.js, *.spec.ts, etc.)vendor/, node_modules/, .venv/, target/)// Code generated)For each source file, attempt to identify covering test files using naming conventions:
auth.go → auth_test.goauth.py → test_auth.py or auth_test.pyAuth.ts → Auth.test.ts or Auth.spec.tsStore discovered modules in the tracking file with status pending.
Present the current state to the user:
## Mutation Testing Progress
Overall: 3/10 modules tested (mutation score: 87%)
### Completed
- src/auth.go — score: 100% (45 mutations)
- src/config.go — score: 92% (24 mutations, 2 survivors)
### In Progress
- src/payment.go — score: 80% (20/50 mutations tested)
### Pending
- src/api/handler.go
- src/models/user.go
- src/utils/parser.go
- ...
Scope? Enter file names/numbers, or press Enter to test all pending modules.
User can:
Default: All pending modules, processed in alphabetical order. If a module is in-progress, it is processed first.
After scope is confirmed, the workflow enters autopilot mode. No further user interaction occurs until the run completes or an unrecoverable error is encountered.
Spawn a qa-test-mutator agent with the selected source file and test command:
Apply mutation testing to the following source file:
- Source file: [path]
- Test command: [command]
Systematically mutate the source code, run tests after each mutation,
and report which mutations are killed vs survived.
Wait for the agent to complete and collect its results.
Parse the mutator agent's results and update .test-mutations.json:
completed (or in_progress if the agent reported partial coverage)mutations_by_type with results grouped by mutation typeexamples arraysmutation_score for the moduleglobal_statistics (recalculate totals and overall score)last_updated timestampWrite the updated tracking file.
If no survivors (100% mutation score): Log the result and proceed to step 8 (commit).
If survivors exist: Write tests for ALL surviving mutations.
Detect the appropriate SME based on project language:
swe-sme-golangswe-sme-dockerswe-sme-makefileswe-sme-graphqlswe-sme-ansibleswe-sme-zigswe-sme-typescriptswe-sme-javascriptswe-sme-htmlswe-sme-cssFor languages without a dedicated SME, implement the tests directly as orchestrator.
Prompt the SME with:
Write tests to catch the following surviving mutations in [source file]:
1. Line 42: `amount + fee` → `amount - fee`
The test must verify that the fee is ADDED, not subtracted.
2. Line 78: `price > 0` → `price >= 0`
The test must verify behavior when price is exactly 0.
3. Line 103: `valid && active` → `valid || active`
The test must verify that BOTH conditions are required.
Each test should:
- Target the specific behavior that the mutation would break
- Follow the project's existing test conventions
- Be focused and minimal (one assertion per concern)
- Have a clear name indicating what it verifies
Run the test suite to confirm new tests pass with the correct (unmutated) code.
If new tests fail: Give the SME (or yourself) one chance to fix. If still failing, log the failure, revert the failing tests (git restore), and continue with the next module.
Re-mutate to confirm kills: For each addressed surviving mutation:
git restore)If a re-applied mutation still survives: Log it as an unresolved survivor and continue. Do not retry or prompt the user.
Update the tracking file: mark confirmed kills, update mutation score.
Automatically commit the changes for this module:
git add [test files] .test-mutations.json
git commit -m "$(cat <<'EOF'
test: improve mutation coverage for [module]
Mutation score: X% → Y%
- Added tests targeting N surviving mutations
- [brief description of what the new tests verify]
EOF
)"
Print a short progress line before moving to the next module:
[3/8] src/payment.go — score: 85% → 95%, 4 tests added. Continuing...
Then loop back to step 4 with the next module in scope.
After all modules in scope have been processed:
## Mutation Testing Complete
### Modules Tested This Session
| Module | Before | After | Tests Added | Unresolved |
|--------------------|--------|-------|-------------|------------|
| src/auth.go | — | 100% | 0 | 0 |
| src/payment.go | — | 95% | 4 | 2 |
| src/config.go | — | 88% | 3 | 3 |
### Project Progress
- Modules complete: 8/10
- Overall mutation score: 91%
### Unresolved Survivors
- src/payment.go:92 — `maxRetries = 3` → `maxRetries = 4` (constant)
- src/payment.go:103 — removed `audit.Log(transaction)` (statement deletion)
- src/config.go:45 — `timeout > 0` → `timeout >= 0` (relational)
- ...
### Commits Made
- abc1234 test: improve mutation coverage for auth module
- def5678 test: improve mutation coverage for payment module
- ghi9012 test: improve mutation coverage for config module
Report any modules that were skipped due to errors (SME failures, test failures, etc.) and why.
File: .test-mutations.json in project root.
{
"version": "1.0",
"test_command": "go test ./...",
"last_updated": "2026-02-12T15:30:00Z",
"modules": {
"src/auth.go": {
"status": "completed",
"covering_tests": ["src/auth_test.go"],
"last_tested": "2026-02-12T15:30:00Z",
"mutations_by_type": {
"arithmetic": {
"total": 12,
"killed": 11,
"survived": 1,
"examples": [
{
"line": 42,
"original": "count + 1",
"mutated": "count - 1",
"result": "survived",
"test_that_caught_it": null
}
]
}
},
"mutation_score": 91.7,
"insights": []
}
},
"global_statistics": {
"total_modules": 10,
"completed_modules": 3,
"total_mutations": 150,
"total_killed": 135,
"total_survived": 15,
"overall_score": 90.0
}
}
Field notes:
examples should include all surviving mutations (for reporting) and a few representative killed mutations (for insight). Don't store every killed mutation — just survivors and notable kills.insights are human-readable observations the mutator agent provides (e.g., "Strong error handling coverage" or "No tests for boundary conditions").global_statistics are recalculated from module data on each update.All subagents MUST be executed sequentially — NEVER in parallel. Mutation testing works by modifying source files and running tests against those modifications. Parallel agents will simultaneously edit the same files, corrupt each other's mutations, and produce meaningless results. This applies to every agent spawn in this workflow: mutator agents, SME agents, and verification steps. One agent at a time, wait for it to finish, then spawn the next.
State management:
Abort workflow if:
git restore (warn user, ask them to commit or stash first)Do NOT abort for:
> /test-mutation
No tracking file found. Detecting test command...
Found go.mod — using `go test ./...`
Verified: tests pass.
Discovered 8 source files to mutate.
Created .test-mutations.json
Commit tracking file to git, or add to .gitignore?
> Commit
## Mutation Testing Progress
8 modules pending.
Scope? Enter file names/numbers, or press Enter to test all pending.
1. src/api/handler.go
2. src/auth.go
3. src/config.go
4. src/middleware.go
5. src/models/user.go
6. src/payment.go
7. src/router.go
8. src/utils/parser.go
> [Enter]
Starting autopilot run for 8 modules...
[1/8] Spawning qa-test-mutator for src/api/handler.go...
Score: 92% (46/50 killed). Writing tests for 4 survivors...
3 killed, 1 unresolved. Score: 92% → 98%.
Committed: "test: improve mutation coverage for handler module"
[2/8] Spawning qa-test-mutator for src/auth.go...
Score: 100% (38/38 killed). No survivors.
Committed: "test: record mutation coverage for auth module"
[3/8] Spawning qa-test-mutator for src/config.go...
Score: 88% (21/24 killed). Writing tests for 3 survivors...
2 killed, 1 unresolved. Score: 88% → 96%.
Committed: "test: improve mutation coverage for config module"
...
[8/8] Spawning qa-test-mutator for src/utils/parser.go...
Score: 90% (27/30 killed). Writing tests for 3 survivors...
3 killed, 0 unresolved. Score: 90% → 100%.
Committed: "test: improve mutation coverage for parser module"
## Mutation Testing Complete
### Modules Tested This Session
| Module | Before | After | Tests Added | Unresolved |
|------------------------|--------|-------|-------------|------------|
| src/api/handler.go | — | 98% | 3 | 1 |
| src/auth.go | — | 100% | 0 | 0 |
| src/config.go | — | 96% | 2 | 1 |
| src/middleware.go | — | 94% | 2 | 1 |
| src/models/user.go | — | 100% | 1 | 0 |
| src/payment.go | — | 95% | 4 | 2 |
| src/router.go | — | 91% | 3 | 2 |
| src/utils/parser.go | — | 100% | 3 | 0 |
### Project Progress
- Modules complete: 8/8
- Overall mutation score: 96%
### Unresolved Survivors (7 total)
- src/api/handler.go:88 — removed `log.Info(request)` (statement deletion)
- src/config.go:45 — `timeout > 0` → `timeout >= 0` (relational)
- ...
### Commits Made (8)
- abc1234 test: improve mutation coverage for handler module
- def5678 test: record mutation coverage for auth module
- ...