muharmutation harness
Pages

Output and exit codes

muhar's stdout is a report meant to be read by people and parsed by scripts. Its format is fixed: everything on this page is taken from the code that prints it. The suite's own output goes to stderr (Streams).

A healthy run

Commandmuhar -spec mutations.json
Exit0
Harness healthy: baseline GREEN, positive control CAUGHT.
  CAUGHT         zero is accepted as an amount
  CAUGHT         the limit ignores what was already spent today
  NOT_CAUGHT       a withdrawal that lands exactly on the limit is refused
  COULD_NOT_MUTATE stale anchor  (mutation "stale anchor": Old text not found in limits.go — edit did not land)
Totals: 2 caught, 1 NOT CAUGHT, 1 could-not-mutate.
NOTE: could-not-mutate is NOT a clean gate — those guards were never actually tested.
LineFormatPresent
HealthHarness healthy: baseline GREEN, positive control CAUGHT.Always, first.
VerdictTwo spaces, the verdict left-aligned in a 16-character field, one space, the mutation's name. A COULD_NOT_MUTATE line adds two spaces and the reason in parentheses.One per mutation, in spec order.
TotalsTotals: <c> caught, <n> NOT CAUGHT, <m> could-not-mutate.Always, after the verdicts.
NoteNOTE: could-not-mutate is NOT a clean gate — those guards were never actually tested.Only when <m> is above 0.

The verdict words are CAUGHT, NOT_CAUGHT and COULD_NOT_MUTATE, with underscores. The Totals: line spells the middle count NOT CAUGHT, with a space; grep for exactly what is printed. The reasons are listed in the spec reference.

With -shard, the counts cover the shard's own mutations only.

A broken run

Commandmuhar -spec mutations.json
Exit2
HARNESS BROKEN — run discarded.
  baseline suite is RED on pristine source — cannot distinguish a caught mutation from a pre-existing failure; discard the run

A broken run prints two lines: HARNESS BROKEN — run discarded. and the reason, indented two spaces. It prints no verdicts and no Totals: line, because those verdicts are exactly what cannot be trusted. A gate that looks for a Totals: line will therefore never pass a broken run, even if it ignores the exit status.

ReasonCause
baseline suite is RED on pristine source — cannot distinguish a caught mutation from a pre-existing failure; discard the runThe suite failed before anything was mutated. Fix the suite or the test command first.
positive control could not be planted (<reason>) — the harness is not mutating; discard the runThe control's edit could not be made or proven. Usually its old text has drifted.
positive control was NOT CAUGHT — a mutation the suite must catch stayed green, so the harness is broken (not mutating, or the suite cannot see the source); discard the runThe suite passed with the control in place. The control is too weak, the suite does not build the mutated file, or root points at a different tree.
could not provision isolated workspace <i> (<error>) — a parallel sweep cannot share a tree; discard the runWith -j above 1, a worker's copy of the tree could not be made: disk full, unreadable file, or a go.mod rewrite that failed.

Exit codes

StatusMeaningReport on stdout
0Harness healthy. Verdicts are trustworthy. This includes runs with NOT_CAUGHT or COULD_NOT_MUTATE lines.Full report with Totals:.
1Usage, spec or setup error: missing -spec, unreadable or invalid spec, missing test or control, bad -shard, negative -j, temp directory not creatable.None. Message on stderr.
2HARNESS BROKEN: no verdict from this run may be used. Also returned by Go's flag parser for an unknown flag or a malformed flag value such as -j two.HARNESS BROKEN and reason, or nothing for a flag error.
130Interrupted by SIGINT or SIGTERM.None.

Exit 0 is not a pass. It says the instrument worked. Whether the guards held is in the Totals: line.

Exit 2 is never a pass. A broken harness reports nothing about your tests, and reading its silence as "no missing tests" is the failure muhar exists to prevent. The flag parser sharing status 2 is a known collision, tracked as assay#2644; it does not change the rule below.

Gating on the result

The rule: fail on any non-zero exit status, then require a Totals: line with zero NOT CAUGHT and zero could-not-mutate. In bash:

status=0
report=$(muhar -spec mutations.json) || status=$?
printf '%s\n' "$report"
if [ "$status" -ne 0 ]; then
  echo "muhar exited $status: harness broken or usage error, no verdict" >&2
  exit 1
fi
if ! grep -qE '^Totals: [0-9]+ caught, 0 NOT CAUGHT, 0 could-not-mutate\.$' <<<"$report"; then
  echo "a guard has no test, or a mutation did not land" >&2
  exit 1
fi

Against the runs in the worked example, this script passes only the run after the boundary test is added. It fails the NOT_CAUGHT run, the COULD_NOT_MUTATE run and all three broken runs.

Parsing the report

For scripts and agents, every verdict line matches:

^  (CAUGHT|NOT_CAUGHT|COULD_NOT_MUTATE) +(.+)$

The name runs to the end of the line, except on a COULD_NOT_MUTATE line, where the reason follows two spaces and an opening parenthesis: (mutation "<name>": …). The name is free text, so keep names free of the sequence two-spaces-parenthesis to keep the split unambiguous. The report has no machine-readable format other than this text today.