# v1.9.10 — mutation testing status

The `validation/invariant_audit.md` (v1.9.9) "what we honestly do
not test" item 2 calls for a full cosmic-ray sweep on `formatter.py`
to surface mutations the hand-rolled `test_mutation_resistance.py`
pilot did not think to write.

## What v1.9.10 ships on this front

The hand-rolled mutation library covers six named mutations: drop
None-guard, leak unknown slugs as Unknown, double counts, swap
streams, return empty string instead of None, case-insensitive
lookup. All six are caught by the existing v1.9.9 test suite, with
named link-back to the test file that catches each one.

The catalog-driven Hypothesis tests (`test_catalog_driven_corpus.py`,
new in v1.9.9) caught a real pre-existing bug at first run: the
`Data & Analytics` category was added to `_CATEGORY_BY_SLUG` in
v1.9.3.9 (with the `looker-studio` slug) but never to
`_SERVICE_CATEGORIES_ORDER`, causing the panel renderer to crash
with `KeyError` whenever the slug fired. v1.9.9 fixed the bug and
added a defensive bucket-creation guard.

That single Hypothesis-found bug is stronger evidence of test-
quality breadth than a clean cosmic-ray sweep would be: the
Hypothesis test searched a larger input space than the hand-curated
fixtures and surfaced a failure mode no hand-written mutation
library would have anticipated.

## What v1.9.10 does NOT ship on this front

A full automated cosmic-ray sweep on `formatter.py`. The reasons:

1. **The bar is harder than the rest of the v1.9.x sequence.** A
   cosmic-ray run takes ~25 minutes on a focused subset and
   substantially longer on the full file. The v1.9.x patches have a
   "ship one milestone per patch" discipline; bundling a multi-hour
   automated mutation sweep into v1.9.10 alongside the stratified
   corpus would conflict with that.
2. **The hand-rolled library + Hypothesis tests already provide real
   evidence.** The cosmic-ray sweep would surface additional
   surviving mutants, but the existing test suite has already
   demonstrated bug-finding power on this codebase (see above).
3. **Cosmic-ray on Windows is slow and the maintainer's primary
   development environment is Windows.** A Linux CI runner is the
   appropriate place for the full sweep; setting that up is a
   separate piece of CI work.

## Plan for v2.0 lock

A full cosmic-ray sweep on `formatter.py` (and ideally `bayesian.py`)
runs as a Linux CI workflow before the v2.0 schema lock. The
workflow:

1. Initializes a session against `formatter.py` (and optionally
   `bayesian.py`).
2. Runs the focused v1.9.9-helper test subset for each mutation
   (~25 minutes on a single runner, parallelizable across multiple
   runners).
3. Reports surviving mutants with file:line and operator-name
   detail.
4. Each survivor is either killed with a new test or explicitly
   accepted in the v2.0 manifesto with a reason.
5. The final report ships at `validation/v2.0-mutation-coverage.md`
   alongside the v2.0 release.

## Why this is documented honestly

A previous version of `validation/invariant_audit.md` named v1.9.10
as the cosmic-ray milestone. v1.9.10 is shipping the stratified
corpus + Bayesian re-validation; cosmic-ray slips to the v2.0 lock.
The slip is a scope decision, not a coverage gap closure: the test
suite's bug-finding capacity is already demonstrated by the
Hypothesis-found `Data & Analytics` bug.

Item 2 of `validation/invariant_audit.md` updated to point at the
v2.0 lock as the cosmic-ray milestone instead of v1.9.10.
