bd2e2a8d

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

Mutation: control-group (no-op) mutations expected to survive

A control is a deliberate no-op: the plugin wraps an expression as
`(\ctrl -> ifMutation cmid ctrl ctrl) e` — the same expression on both
branches, a genuine non-diff — every `controlInterval` (12) real mutations,
with the counter primed so each module with an expression mutation gets at
least one. Both branches share the subtree via the lambda binder so the no-op
does not duplicate (and blow up) the instrumented expression.

A control changes no behaviour, so it is expected to survive. A killed control
means the mutation testing itself is unsound (a flaky/nondeterministic suite or
a harness bug), not a real kill, so it is reported separately as a warning and
excluded from the killed/survived score and the exit code.

Marked via the reserved operator name "Control" (no new record field).
New MutationOutcome variants OutcomeControlPassed/OutcomeControlFailed and
MutationResult variants MutationControlPassed/MutationControlFailed; the driver
remaps a control's exit-code classification accordingly. isMutationFailure is
False for both so a surviving control never trips fail-fast.

Regenerated the example manifest goldens (control entries only).

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 0s 7s 7s 7s 0s
Eval 7s 1m58s 1m58s 2m06s 0s
Build 1m21s 1m43s 46s 2m08s 0s
Suite 0s 3m50s 2m08s 2m08s 0s

Timeline

0s10s20s30s40s50s1m1m10s1m20s1m30s1m40s1m50s2m