Skip to content
Development
Skill

/mutation-testing

Use when adding or reviewing a gate, guard rule, CI grep, or test assertion in this plugin's own scripts — and whenever a suite is green and you need to know whether that means anything. Runs scripts/mutate.sh, which breaks the code on purpose and reports which assertions failed

From plugin
app-dev-team
432 skills30 agents27 commands2 hooks
Install
$ npx -y skills add vmobifystudio/app-dev-team --skill mutation-testing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/mutation-testing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when adding or reviewing a gate, guard rule, CI grep, or test assertion in this plugin's own scripts — and whenever a suite is green and you need to know whether that means anything. Runs scripts/mutate.sh, which breaks the code on purpose and reports which assertions failed

SKILL.md

mutation-testing.SKILL.md
name: mutation-testing
description: Use when adding or reviewing a gate, guard rule, CI grep, or test assertion in this plugin's own scripts — and whenever a suite is green and you need to know whether that means anything. Runs scripts/mutate.sh, which breaks the code on purpose and reports which assertions failed to notice. Triggers from code-reviewer, verification-engineer, and any change under scripts/ or hooks/.

Mutation testing

`defect-hunting` §3 says a new rule is not done until you have watched it fail, in three steps. That instruction was followed by hand, when someone remembered. On 2026-07-29 the suite read **385 passed, 0 failed** while containing a `grep -E` with a PCRE lookahead (a syntax error, stderr to `/dev/null`, `|| ok` every time), two doctor assertions that a demoted gate could not turn red, and a hook that stood down in exactly the incident it was written for.

**A green suite is evidence only to the extent its assertions can go red.** `scripts/mutate.sh` is that, executable.

Running it

sh scripts/mutate.sh                # all 16 catalogued mutations (~1 min each — the whole suite runs)
sh scripts/mutate.sh --list         # the catalogue, plus what it cannot test and why
sh scripts/mutate.sh --only M04     # one mutation, while you iterate on an assertion
sh scripts/mutate.sh --sample 4     # what CI runs on every PR

Exit `0` all caught · `1` something SURVIVED · `2` could not run (baseline not green, anchor drifted).

Three verdicts matter:

  • **CAUGHT (n assertions)** — the gate bites.
  • **SURVIVED** — the gate can be deleted and the suite stays green. **That is a hole**, and it is a

finding at the same severity as the bug the gate was supposed to catch.

  • **CAUGHT, but NOT by the assertion written for it** — some unrelated assertion noticed. Not a hole

today; the named guard is decorative, and the next refactor that touches the unrelated one takes the coverage away silently. Fix the named assertion.

The rule

**A new gate ships with a mutation proving its assertion bites.** Adding a check to `board-doctor`, `ship-gate`, `verify-done`, `spawn-gate`, a hook, or `scripts/test.sh` is not done until `scripts/mutate.sh --only <your-id>` prints CAUGHT and names *your* assertion.

Adding one is four fields in the catalogue at the top of `scripts/mutate.sh`:

M17@@scripts/your-gate.sh@@<exact text to break>@@<replacement>@@<the test.sh label that must fail>
  • The find text must occur **exactly once** in the file. Zero or many exits 2 — a mutation anchored

at an arbitrary one of several sites proves nothing, and a drifted anchor must be loud rather than a phantom survivor.

  • Break the *behaviour*, not the message. Inverting an exit code, demoting a finding to a warning,

flipping `-gt` to `-lt`, `if false`, neutering a regex, or returning the fallback instead of refusing are the seven shapes in the catalogue — all seven are things that really shipped here.

  • The last field is a substring of the real label in `scripts/test.sh`, so the tool can tell

"the suite noticed" from "the assertion I wrote noticed".

When you cannot test it

Some assertions need Xcode, a simulator, or a network. **Do not fake coverage.** Add them to `excluded()` in `scripts/mutate.sh` with the reason; they are printed with every score and counted in neither numerator nor denominator. A mutation score that quietly omits the untestable parts is the same lie as a green suite full of decorative assertions.

A gate with no fixture that reaches it belongs there too, with that reason — reporting it as a hole would be a false alarm, and a tool that cries wolf gets switched off.

Safety

Mutations are applied to a copy in `$TMPDIR`; the real tree is never written to. `.git` is not copied (in a worktree it points at the real repository). Restore is a trap, and on exit the tool compares `git status --porcelain` against the snapshot it took at start and fails loudly if it moved.

Manual fallback

No Node or a hostile environment: pick the assertion you doubt, edit the line it guards to invert it, run `sh scripts/test.sh`, and confirm **that assertion by name** is in the FAIL list. Then `git checkout -- <the one file you edited>` — never a repo-wide revert. That is `defect-hunting` §3's three steps done by hand: confirm the edit landed, confirm the fixture reaches it, watch it go red and green again.

Read more
Ships withapp-dev-team

Describe your app idea in one line. Get a shipped iOS & Android app. AI App Studio is a team of 30 AI specialists — a CEO, product manager, designers, iOS/Android engineers, a code reviewer, QA, and a release manager — that works like a real software studio.

Get the whole plugin

Other skills on app-dev-team.