#!/usr/bin/env bash # Row 72 (#1566): rerun the six mutants the row 68 reviewers named against a # tree with the candidate tests. Usage: mutants.sh . Each mutant edits # one line of bus-service.sh or adapter.sh, runs the pin tests, and restores # the file from git. Prints "killed" or "SURVIVED" per mutant; exit 1 if any # mutant survives, a sed doesn't change its file, or the unmutated run fails. set -euo pipefail TREE="$(cd "${1:?usage: mutants.sh }" && pwd)" cd "$TREE" BS=scripts/bus-service.sh AD=adapters/claude/adapter.sh PATTERN='directory pin|symlink default|pin with a space|pins the claude|MOSAIC_CLAUDE_BIN wins' TESTS=(packages/cli/tests/host.test.mjs packages/harness/tests/claude-session.test.mjs) run_tests() { node --test --test-name-pattern="$PATTERN" "${TESTS[@]}" >"$1" 2>&1; } # name | file | sed expression MUTANTS=( 'bs-no-f|'"$BS"'|s/\[ -f "\$bin" \] \&\& \[ -x "\$bin" \]/[ -e "$bin" ] \&\& [ -x "$bin" ]/' 'bs-x-only|'"$BS"'|s/\[ -f "\$bin" \] \&\& \[ -x "\$bin" \]/[ -x "$bin" ]/' 'ad-no-f|'"$AD"'|s/\[ -f "\$MOSAIC_CLAUDE_BIN" \] \&\& \[ -x "\$MOSAIC_CLAUDE_BIN" \]/[ -e "$MOSAIC_CLAUDE_BIN" ] \&\& [ -x "$MOSAIC_CLAUDE_BIN" ]/' 'ad-x-only|'"$AD"'|s/\[ -f "\$MOSAIC_CLAUDE_BIN" \] \&\& \[ -x "\$MOSAIC_CLAUDE_BIN" \]/[ -x "$MOSAIC_CLAUDE_BIN" ]/' 'bs-resolve-default|'"$BS"'|s/^ bin="\$(command -v claude || true)"$/ bin="$(command -v claude || true)"; [ -z "$bin" ] || bin="$(readlink -f "$bin")"/' 'ad-unquoted-run|'"$AD"'|s/^"\$CLAUDE" -p /$CLAUDE -p /' ) OUT="${OUT:-$TREE/.mutants}" mkdir -p "$OUT" git diff --quiet -- "$BS" "$AD" || { echo "refusing: $BS or $AD already modified" >&2; exit 1; } run_tests "$OUT/baseline.log" || { echo "baseline run failed: $OUT/baseline.log" >&2; exit 1; } echo "baseline: pass" status=0 for m in "${MUTANTS[@]}"; do IFS='|' read -r name file expr <<<"$m" sed -i -e "$expr" "$file" if git diff --quiet -- "$file"; then echo "$name: NOT APPLIED (sed matched nothing)"; status=1; continue fi git diff -- "$file" >"$OUT/$name.diff" if run_tests "$OUT/$name.log"; then echo "$name: SURVIVED"; status=1 else echo "$name: killed ($(grep -E '^✖' "$OUT/$name.log" | sed 's/ ([0-9.]*ms)$//' | sort -u | tr '\n' ';' ))" fi git checkout -q -- "$file" done git diff --quiet -- "$BS" "$AD" || { echo "restore failed" >&2; exit 1; } exit "$status"