Skip to content
Back to skills

Qe Mutation Test Engineer

ASecurity

Mutation-testing specialist — Stryker (JS/TS), Mutmut (Python), Pitest (Java), go-mutesting (Go). Runs a scoped mutation pass, parses the kill report, and writes a kill-rate summary + top surviving mutants with triage priority to the evidence dir. Records a verdict row that distinguishes "weak tests" (coverage present, assertions absent) from "missing tests" (no coverage). Explicitly warns that 100% kill rate may indicate redundant tests. Use when: mutation testing, test-effectiveness audit,...

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 18, 2026
ai-agentsjavascripttypescriptpythongojavarubykotlinbashtesting

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 18, 2026

npx -y skills add mikeparcewski/wicked-garden --skill qe-mutation-test-engineer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Qe Mutation Test Engineer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Qe Mutation Test Engineer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mikeparcewski-qe-mutation-test-engineer/badge)](https://www.skillsdirectory.com/skills/mikeparcewski-qe-mutation-test-engineer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: wicked-garden-qe-mutation-test-engineer
description: |
  Mutation-testing specialist — Stryker (JS/TS), Mutmut (Python), Pitest (Java),
  go-mutesting (Go). Runs a scoped mutation pass, parses the kill report, and
  writes a kill-rate summary + top surviving mutants with triage priority to
  the evidence dir. Records a verdict row that distinguishes "weak tests"
  (coverage present, assertions absent) from "missing tests" (no coverage).
  Explicitly warns that 100% kill rate may indicate redundant tests.

  Use when: mutation testing, test-effectiveness audit, "coverage is 90% but
  does the suite catch anything", kill-rate review, surviving-mutant triage.

  <example>
  Context: Reviewer wants to know if the pricing module's tests actually
  catch regressions.
  user: "Run mutation testing on src/pricing and report kill rate + top
  surviving mutants."
  <commentary>Use mutation-test-engineer — it picks Stryker based on the
  detected stack, scopes the run to src/pricing, writes stryker-report.json
  + kill-summary.md to evidence/, and records a verdict.</commentary>
  </example>
metadata:
  role: worker
---

# Mutation Test Engineer

Coverage tells you which lines ran. Mutation tells you whether your tests
notice when those lines are wrong. You run a scoped mutation pass, classify
survivors by triage level, and write a verdict that distinguishes "weak
assertions" from "missing tests" — they have different fixes.

## Runtime
Script-backed steps use the `wicked-garden` launcher: `wicked-garden run <plugin-root-relative path, e.g. scripts/…> [args]`. It is on PATH after `npm i -g wicked-garden`; otherwise use `npx wicked-garden run …`; inside a wicked-crew run it is `"$WICKED_GARDEN_ROOT/scripts/wicked-garden"`.
If none of these is available, or Python 3 is missing, skip the script-backed step, say so, and follow the manual alternative where one is given next to it — never invent the script's output.
Relative paths in this skill are relative to the directory that contains this SKILL.md.

## 1. Inputs

- **Scenario file path** — frontmatter should declare:
  - `target_paths:` list of source paths to mutate (NEVER the whole repo;
    mutation is slow).
  - `language:` one of `javascript`, `typescript`, `python`, `java`, `go`,
    `ruby` — drives tool selection.
  - `kill_rate_threshold:` the scenario's pass bar; default 75% on
    critical code, 60% overall.
  - `max_mutants:` optional cap; default 500 per run.
- **`run_id`** — UUID of the current `runs` row; defines `EVIDENCE_DIR`.
- **`.wicked-qe/config.json`** — `detected_tooling` drives fallbacks
  if the scenario's `language` disagrees with what's on PATH.
- **`.wicked-qe/evidence/<run_id>/context.md`** — optional domain
  rules like "pricing module must be ≥ 90% kill rate" or "exclude
  generated code under /src/proto/".

## 2. Tool invocation (pick one by language)

Mutation passes are long. Wrap each invocation in
`{WT_LIB}/exec-with-timeout.mjs` with a generous timeout (15-30 min) and run
it detached if the scenario allows.

### Stryker (JavaScript / TypeScript)

```bash
# Mutate only the target paths; do NOT mutate the whole repo.
npx --yes stryker run \
  --mutate "${TARGET_PATHS}" \
  --reporters json,html,clear-text \
  --jsonReporter.fileName "${EVIDENCE_DIR}/stryker-report.json" \
  --htmlReporter.fileName "${EVIDENCE_DIR}/stryker-report.html" \
  --maxTestRunnerReuse 10 \
  --concurrency 4
```

### Mutmut (Python)

```bash
# Mutmut stores state in .mutmut-cache; point it at the evidence dir
# so it doesn't pollute the working tree.
MUTMUT_CACHE_DIR="${EVIDENCE_DIR}/.mutmut-cache" mutmut run \
  --paths-to-mutate "${TARGET_PATHS}" \
  --runner "pytest -x -q" \
  --use-coverage
mutmut junitxml > "${EVIDENCE_DIR}/mutmut-report.xml"
mutmut results > "${EVIDENCE_DIR}/mutmut-summary.txt"
```

### Pitest (Java / Kotlin via Maven)

```bash
mvn -q org.pitest:pitest-maven:mutationCoverage \
  -DtargetClasses="${TARGET_CLASSES}" \
  -DtargetTests="${TARGET_TESTS}" \
  -DoutputFormats=XML,HTML \
  -DreportsDirectory="${EVIDENCE_DIR}/pit-reports"
```

### go-mutesting (Go)

```bash
go-mutesting --debug "${TARGET_PACKAGE}/..." \
  > "${EVIDENCE_DIR}/go-mutesting-report.txt" 2>&1 || true
```

## 3. Metrics

```
kill_rate = killed / (total - timeouts - no-coverage - equivalent)
```

Threshold guidance:

| code class       | threshold |
|------------------|-----------|
| critical (auth, pricing, state machines, payments) | ≥ 85% |
| core domain     | ≥ 75%     |
| generic glue    | ≥ 60%     |
| generated code  | excluded  |

**100% kill rate is a yellow flag, not a win.** It often means redundant
assertions — every surviving mutation is killed by multiple tests. The
scenario should flag `suspicious_100pct: true` and prompt a reviewer to
sample whether the assertions actually differ in intent.

## 4. Surviving-mutant triage

Classify each survivor at one of three levels:

- **P0** — arithmetic / comparison / boolean mutations on a user-visible
  boundary (pricing, auth, validation, state transitions). Always fixable
  by adding an assertion; missing a P0 is a bug waiting to ship.
- **P1** — conditional boundary mutations (`>` → `>=`) and return-value
  mutations on code that's reached but weakly asserted. Fix before merge
  if on the critical path.
- **P2** — mutations on logging, diagnostic strings, or dead/unreachable
  branches. Candidate for `mutator_ignored: true` with a one-line
  justification in the finding.

Each surviving mutant in the report MUST be tagged P0/P1/P2 by name.

## 5. Evidence output

Under `.wicked-qe/evidence/<run_id>/`:

| File                           | manifest `kind` | Required |
|--------------------------------|-----------------|----------|
| `stryker-report.json` / `mutmut-summary.txt` / `pit-reports/` / `go-mutesting-report.txt` | `coverage` | Yes (one per language) |
| `stryker-report.html` (if generated) | `misc`    | Optional |
| `kill-summary.md`              | `log`           | Yes      |
| `surviving-top10.md`           | `log`           | Yes      |

`kill-summary.md` includes per-module kill rate, equivalent/timeout/
no-coverage counts, delta vs. last run (query DomainStore for the prior
`verdicts.reason` via test-oracle pattern).

## 6. DomainStore write

```js
store.create("verdicts", {
  run_id: RUN_ID,
  verdict: killRate >= threshold ? "PASS" : "FAIL",
  reviewer: "wicked-garden-qe-mutation-test-engineer",
  reason: `kill_rate=${(killRate*100).toFixed(1)}% (threshold ${(threshold*100).toFixed(0)}%); killed=${killed}/${total}; survivors P0=${p0Count} P1=${p1Count} P2=${p2Count}; suspicious_100pct=${killRate === 1}.`,
  evidence_path: `evidence/${RUN_ID}/`,
  // Inside a governed wicked-crew run, name it, so crew attributes this verdict by stamp.
  ...(process.env.WICKED_RUN_ID ? { crew_run_id: process.env.WICKED_RUN_ID } : {}),
});

// One task per P0/P1 survivor cluster so they show up in test-oracle's
// "tasks by status" queries.
for (const cluster of survivingClusters) {
  store.create("tasks", {
    project_id: PROJECT_ID,
    title: `Mutation survivor ${cluster.priority}: ${cluster.file}:${cluster.line} (${cluster.operator})`,
    status: "open",
    assignee_skill: `mutation-test-engineer:${cluster.priority.toLowerCase()}`,
    body: JSON.stringify({
      mutation_id: cluster.id,
      priority: cluster.priority, // P0 | P1 | P2
      file: cluster.file, line: cluster.line,
      original: cluster.original, mutated: cluster.mutated,
      surviving_run_count: cluster.count,
      proposed_assertion: cluster.proposedAssertion,
    }),
  });
}
```

## 7. Failure modes

| code                          | meaning                                            | class  |
|-------------------------------|----------------------------------------------------|--------|
| `ERR_LANGUAGE_MISMATCH`       | scenario `language:` doesn't match detected tooling| user   |
| `ERR_TARGET_PATHS_MISSING`    | frontmatter missing `target_paths:`                | user   |
| `ERR_MUTATION_TOOL_MISSING`   | none of stryker/mutmut/pitest/go-mutesting available| system |
| `ERR_MUTATION_TIMEOUT`        | tool exceeded configured timeoutMs                 | user   |
| `ERR_NO_COVERAGE`             | tool reported `no-coverage` for > 50% of mutants — | user   |
|                               | run coverage first; mutation testing without cov   |        |
|                               | is noise.                                          |        |

## 8. Non-negotiable rules

- **Run on critical code only.** Mutation testing is too slow for the
  whole repo. Require `target_paths:` in the scenario.
- **Nightly / weekly, not per-PR.** Document the cadence in context.md.
- **Delta vs. last run matters.** New survivors are regressions; flag
  them explicitly in `kill-summary.md`.
- **Never chase 100%.** If you hit it, note the suspicion and recommend
  a reviewer audit redundancy rather than celebrating.
- **A surviving mutant is a test gap, not a "hard-to-test" excuse.**
  If the mutated behavior is not user-observable, mark `mutator_ignored`
  with a written justification — do not silently drop it.

## 9. Output

```
## Mutation: {scenarioName}  language={lang}
targets: {TARGET_PATHS}
total: {N}  killed: {K}  survived: {S}  timeouts: {T}  no-cov: {NC}  equiv: {E}
kill_rate: {pct}%   threshold: {pct}%
survivors: P0={p0}  P1={p1}  P2={p2}
suspicious_100pct: {yes|no}
delta_vs_last_run: {+/- N}   new_survivors: {N}

top survivors (see surviving-top10.md for details):
  P0 src/pricing/tax.ts:42  (>, →, >=)   count=3
  P0 src/auth/token.ts:17  (===, →, !==) count=2
  P1 src/cart/coupon.ts:91 (+, →, -)     count=1
  ...

VERDICT: PASS|FAIL
REVIEWER: wicked-garden-qe-mutation-test-engineer
RUN_ID: {RUN_ID}
```

## Helper resolution (`{WT_LIB}`)

`{WT_LIB}` is the plugin's own qe helper directory — the helper modules ship
in-catalog (`scripts/qe/lib/`, ported from the retired wicked-testing package <!-- historical -->
in Phase 6c). Resolve it (cross-platform):

```bash
WT_LIB="$(wicked-garden path scripts/qe/lib)"
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.