
Some mutants produce the same observable behaviour as the original program. No test can kill them because there is no difference to detect. These are equivalent mutants, and they inflate the survivor count without representing real test gaps.

## Why equivalent mutants exist

A mutation like replacing `x + 0` with `x - 0` changes the bytecode but not the result. The mutant is alive but unkillable. Other examples:

| Example | Why it is equivalent |
|---------|---------------------|
| Negating a variable that is always zero | `x` and `-x` are both `0` |
| Removing a `print()` call in code where output is not tested | No oracle checks stdout |
| Changing a comparison in a branch that is never reached | Dead code, no observable effect |

Every mutation testing tool has this problem. Vary uses heuristics to identify likely-equivalent mutants so they do not distort your score.

## Suspicion heuristics

The equivalence analyzer scores each surviving mutant with multiple independent signals:

| Heuristic | Confidence | What it detects |
|-----------|-----------|-----------------|
| `bytecode_identical` | 1.0 | Mutant bytecode is identical to original (already flagged by bytecode comparison) |
| `trivial_arithmetic` | 0.85 | Identity-preserving arithmetic: `x + 0`, `x * 1`, `x - 0` patterns |
| `dead_branch` | 0.7 | Mutant survived with zero execution time (code path never reached) |
| `semantic_noop` | 0.6 | Statement removal of side-effect-only calls like `print()` or `log()` |
| `untested_path` | 0.4 | Mutant is in a code region with no test coverage at all |

The overall confidence is the maximum signal confidence. Multiple signals reinforce the diagnosis but do not stack numerically.

## Confidence levels and recommendations

| Confidence | Recommendation |
|-----------|---------------|
| 0.9 to 1.0 | Quarantine automatically (almost certainly equivalent) |
| 0.6 to 0.89 | Review recommended, likely equivalent but worth checking |
| 0.4 to 0.59 | Investigate: may be a real test gap in untested code |

## Auto-quarantine

Use `--auto-quarantine <threshold>` to automatically quarantine mutants above a confidence level:

```bash
vary mutate src/ --auto-quarantine 0.9
```

This quarantines high-confidence equivalent mutants without manual review. Quarantined mutants are excluded from the mutation score and survivor lists. They are stored in `.vary/equivalent-mutants.json` and can be reviewed or restored:

```bash
vary mutate src/ --list-quarantined
vary mutate src/ --unquarantine "mutant-id"
```

## Impact on scoring

Equivalent-likely mutants affect the actionable survivor rate but not the kill rate:

| Metric | Includes equivalent-likely? |
|--------|-----------------------------|
| Kill rate | No (denominator includes them) |
| Observability | No |
| Actionable survivor rate | No (subtracted from survivors) |

The actionable survivor rate is the metric to watch: it excludes likely-equivalent mutants so you focus on survivors worth investigating.

## What to do next

| Page | Topic |
|------|-------|
| [Infrastructure](/docs/mutation/infrastructure/) | Quarantine management, policy gates, CLI reference |
| [Lie detection](/docs/mutation/lie-detector/) | Find tests that pass but check nothing |
| [Advanced overview](/docs/mutation/advanced/) | How equivalent mutant handling fits the six-pillar model |
