一键导入
mutation-testing
// Set up and run mutation testing with Stryker, including full-project and diff-against-main runs, then use surviving mutants to strengthen weak or missing tests.
// Set up and run mutation testing with Stryker, including full-project and diff-against-main runs, then use surviving mutants to strengthen weak or missing tests.
Turn broad requirements, large stories, epics, features, initiatives, or backlog items into small end-to-end child stories without turning them into technical component tasks. Use when refining a backlog, decomposing epics, planning an MVP or walking skeleton, looking for vertical slices, reducing story size, applying SPIDR/Hamburger/capability slicing, avoiding scatter-gather/component stories, or deciding the first valuable story before implementation planning.
Adversarially review written stories, plans, acceptance criteria, specs, and design mocks to surface missing states, unhandled edge cases, unstated assumptions, unverifiable criteria, and slices that are still too broad or horizontal — then work interactively with the user, one question at a time, to turn each gap into a new acceptance criterion, plan update, mock-state spec, or recommendation to use story-splitting. Use when an existing artifact needs tightening before planning or coding.
Planning work as vertical slices in small, known-good increments. Use when starting significant work, turning already-split stories into PR-sized implementation plans, planning PRs, or sequencing complex tasks. If the input is a broad story, epic, feature idea, or backlog item that still needs product slicing, use story-splitting first.
Test-Driven Development workflow. Use for ALL code changes - features, bug fixes, refactoring. TDD is non-negotiable.
Produce a mock-audit storyboard — a single HTML page embedding every UX surface in a scope of work side-by-side, with per-mock audit checklists, a flow diagram, and gap cards for missing mocks. Use before any feature touching multiple UX surfaces begins implementation. Also use when the user says "make it easy for me to see all these mocks in one place", "audit the mocks", or "I want to review the whole flow".
Create an application-specific production parity skill by inspecting an app's docs, source, tests, CI, deployment, infrastructure, config, auth, and environment setup, then asking targeted harness questions only for source-unanswerable decisions. Use when local, CI, PR, preview, staging, or other non-production environments may drift from production behavior; when production-only auth, config, identity-provider groups, feature flags, infrastructure, backing services, or policy differences caused bugs; or when a team wants a reusable skill that detects, documents, tests, and helps fix parity drift for one specific application.
| name | mutation-testing |
| description | Set up and run mutation testing with Stryker, including full-project and diff-against-main runs, then use surviving mutants to strengthen weak or missing tests. |
For writing good tests (factories, behavior-driven patterns), load the testing skill. This skill focuses on verifying test effectiveness.
Mutation testing answers the question: "Are my tests actually catching bugs?"
Code coverage tells you what code your tests execute. Mutation testing tells you if your tests would detect changes to that code. A test suite with 100% coverage can still miss 40% of potential bugs.
Default posture: use an automated mutation harness first. For JavaScript and TypeScript projects, recommend Stryker as the starting point if it is not already set up. Use manual/mental mutations only as a fallback, a teaching aid, or a focused follow-up for subtle survivors.
Deep-dive resources are in the resources/ directory. Load them on demand:
| Resource | Load when... |
|---|---|
mutator-rules.md | Planning tests, scanning changed code for likely gaps, manually applying mutations, or interpreting surviving/equivalent mutants |
The Mutation Testing Process:
The Insight: A surviving mutant represents a bug your tests wouldn't catch.
Use mutation testing analysis when:
Integration with planning and TDD:
FOR EACH STEP:
├─► CONFIRM: Human approves observable acceptance criteria
├─► RED: Write failing test, using mutator rules to spot likely gaps
├─► GREEN: Make it pass
├─► Run mutation testing
├─► KILL MUTANTS: Strengthen tests for worthwhile survivors
├─► REFACTOR: If valuable
└─► STOP: Present work, mutation report, and wait for commit approval
PRE-PR QUALITY GATE:
└─► Re-run mutation testing for the branch/repo scope
Mutation testing is not a replacement for RED-GREEN-MUTATE-KILL MUTANTS-REFACTOR. It verifies the tests created during those increments are strong enough to catch real behavioral regressions before refactoring and before PR.
When analyzing code on a branch, prove test effectiveness with Stryker whenever practical. Do not stop at reasoning about whether a test would catch a mutation; run the harness, then use the report to drive focused test improvements.
rg --files | rg '(^|/)(package.json|stryker\.config\.(mjs|cjs|js|json)|stryker\.conf\.(js|json))$'
git diff main...HEAD --name-only
main, substitute that branch in all diff commands.Use the official initializer as the starting point:
npm init stryker@latest
Then inspect and adapt the generated stryker.config.*:
vitest, jest, mocha, etc.). Use the generic command runner only when no tighter integration is practical.@stryker-mutator/typescript-checker so type-invalid mutants are reported as compile errors instead of wasting test time..gitignore entries for Stryker temp/report output only when the project needs them.Suggest project scripts for full-project, cached, and branch-diff mutation runs:
{
"scripts": {
"mutation": "stryker run",
"mutation:incremental": "stryker run --incremental",
"mutation:diff": "node scripts/stryker-diff.mjs main"
}
}
The mutation:diff helper should:
main.git diff --name-only --diff-filter=ACMRTUXB <base>...HEAD.stryker run --incremental --force --mutate <comma-separated-files>.Prefer a small Node helper over dense shell inside package.json; quoting *, !, and command substitution is fragile across shells. For quick local use, this POSIX one-liner is acceptable:
CHANGED=$(git diff --name-only --diff-filter=ACMRTUXB main...HEAD -- '*.ts' '*.tsx' '*.js' '*.jsx' | grep -Ev '(^|/)(__tests__|test|tests|fixtures|generated)/|\.(test|spec|d)\.' | paste -sd, -)
test -n "$CHANGED" && npx stryker run --incremental --force --mutate "$CHANGED"
Use exact line ranges for tiny follow-up checks when the report points to a specific survivor:
npx stryker run --incremental --force --mutate src/example.ts:42-57
Start with mutation:diff for branch feedback. Run mutation across the full project when introducing Stryker, changing shared test infrastructure, preparing CI gates, or validating a broad test-strengthening pass.
Categorize Stryker findings:
| Category | Description | Action Required |
|---|---|---|
| Killed | Test failed when mutant was applied | None - tests are effective |
| Survived | Tests passed with mutant active | Add/strengthen test, unless equivalent |
| No Coverage | No test exercises this code | Add behavior test |
| Equivalent | Mutant produces same behavior | None - not a real bug |
Fix obvious issues immediately:
Use the harness's ask-question facility for subtle survivors that require human judgment. Ask one concise question with concrete choices, explain the mutation, and describe the tradeoff. Use this when behavior is intentionally unspecified, the correct domain rule is unclear, the test would be expensive or brittle, or the mutant may be equivalent but you are not certain.
For each survivor worth killing:
Avoid overfitting tests to implementation details. Strong mutation tests assert observable behavior: return values, persisted state, emitted events, permissions, messages, or meaningful collaborator calls.
Stryker should be the normal entry point for JS/TS mutation testing.
Prefer stryker.config.mjs or the format generated by the initializer. A typical starting point:
export default {
testRunner: "vitest",
coverageAnalysis: "perTest",
reporters: ["html", "clear-text", "progress"],
mutate: [
"src/**/*.{ts,tsx,js,jsx}",
"!src/**/*.test.{ts,tsx,js,jsx}",
"!src/**/*.spec.{ts,tsx,js,jsx}",
"!src/**/*.d.ts"
]
}
Adapt testRunner, mutate, testFiles, build commands, and checker plugins to match the project. Do not cargo-cult this exact config into a repo with a different layout.
If Stryker is unavailable or cannot target the code under review, load resources/mutator-rules.md and manually apply the relevant operators. Always revert each mutation before the next one. Manual mutation should still follow the same loop: mutate, run tests, classify, fix obvious gaps, ask about judgment calls, and report the result.
The key question for every line of code:
"If I introduced a bug here, would my tests catch it?"
For each test, verify it would catch:
Remember:
resources/mutator-rules.md