First Stryker pass over the changed lines (Entity.cs: Absorb/DamageHull;
FireControl.cs: Apply, Splash) killed 584/844 candidate mutants; these
six survivors on the cut's own diff get real behavioural tests instead:
- Entity.Absorb's `d > 0f` and `d > 0.1f` guards, and DamageHull's
`damage > .1f` guard, each had their boundary flipped to `>=` and
survived -- at the exact boundary (0 incoming, or exactly the .1f
carry-forward threshold), real code does nothing while the mutant
fires an extra event or spends an extra fraction. Not a rare float
coincidence: a spent lane routinely reaches a cell with exactly 0
remaining, and an authored penetration/armour value can land exactly
on .1f.
- FireControl.Apply's `target.IncomingHit.OnNext(shot.Source)` (moved
here from the deleted Entity.ApplyHit) had no test that it still fires.
- FireControl.Apply's two `walked[li] > 0` checks (metalLanes counting,
and the absorb-loop entry) both flipped to `>= 0` and survived, since a
lane count can never be negative -- a real bug class (a lane entirely
off the hull would dilute the split and leak a damage share to the
hull) that a hull no wider than the spread now catches.
- The penetration cutoff's `>= shot.Penetration` flipped to `>` survived
at the exact boundary -- an axis-aligned lane's entry values are exact
integers, so an authored integer penetration routinely lands exactly on
a cell's own entry difference.
Recorded, not chased: `shot.Outcome.Lateral - (li - n)` (the lane-offset
sign) is an equivalent mutant -- 2n+1 lanes built symmetrically around n
cover the same SET of offsets either way, just enumerated in reverse, and
the loop's own per-lane work is order-independent. The missing
`ArrayPool<LaneCell>.Return` survivor is a perf-hygiene gap (GC pressure,
not a spec'd invariant -- only the forecast path is zero-allocation), not
yet reached by a dedicated allocation test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>