Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
107 lines
6.7 KiB
Bash
107 lines
6.7 KiB
Bash
#!/usr/bin/env bash
|
||
# Row 143 (#1637): agents review Jason's spec commits, and the assistant summarizes.
|
||
# Each check must fail on a mutant. For each mutant this runs one named test file against the
|
||
# real source (control) and against the source with one exact-once text edit, in the given worktree,
|
||
# one test file at a time, and restores every source file on exit.
|
||
# Usage: mutants.sh <worktree> <outdir> (MUTANT_DRY=1 only proves every edit matches exactly once)
|
||
set -u
|
||
WT=$(cd "$1" && pwd); OUT=$(mkdir -p "$2" && cd "$2" && pwd)
|
||
cd "$WT" || exit 2
|
||
BAK=$(mktemp -d "$OUT/.bak.XXXXXX")
|
||
declare -A SAVED
|
||
save() { [ -n "${SAVED[$1]:-}" ] || { mkdir -p "$BAK/$(dirname "$1")"; cp "$1" "$BAK/$1"; SAVED[$1]=1; }; }
|
||
restore() { for f in "${!SAVED[@]}"; do cp "$BAK/$f" "$f"; done; rm -rf "$BAK"; }
|
||
trap restore EXIT
|
||
edit() { # file old new: exact-once replace
|
||
save "$1"
|
||
node -e '
|
||
const fs = require("fs"); const [f, a, b] = process.argv.slice(1);
|
||
const s = fs.readFileSync(f, "utf8"); const n = s.split(a).length - 1;
|
||
if (n !== 1) { console.error("expected one match, found " + n); process.exit(3); }
|
||
fs.writeFileSync(f, s.replace(a, () => b));
|
||
' "$1" "$2" "$3"
|
||
}
|
||
run() { # name testfile
|
||
if [ -n "${MUTANT_DRY:-}" ]; then echo "$1: edit ok (dry)"; return; fi
|
||
setsid -w timeout -k 10 400 node --test "$2" > "$OUT/$1.out" 2>&1; echo "$?" > "$OUT/$1.rc"
|
||
echo "$1: exit $(cat "$OUT/$1.rc"); $(grep -E '^ℹ (tests|pass|fail)' "$OUT/$1.out" | tr '\n' ' ')"
|
||
grep -E '^✖' "$OUT/$1.out" | sort -u | sed 's/ ([0-9.]*ms)$//' | sed "s/^/ failed: /"
|
||
}
|
||
mutant() { # name testfile file old new (MUTANT_ONLY=<regex> runs just the matching names)
|
||
if [ -n "${MUTANT_ONLY:-}" ] && ! [[ $1 =~ $MUTANT_ONLY ]]; then return; fi
|
||
edit "$3" "$4" "$5" || { echo "$1: edit failed"; return; }
|
||
diff -u "$BAK/$3" "$3" > "$OUT/$1.patch"
|
||
run "$1" "$2"
|
||
cp "$BAK/$3" "$3"
|
||
}
|
||
BB=packages/bus/src/broker.mjs; BT=packages/bus/tests/spec-review.test.mjs
|
||
HT=packages/harness/tests/tools.test.mjs; HS=packages/harness/src/tools.mjs
|
||
CT=packages/business/tests/spec-review-contracts.test.mjs
|
||
if [ -z "${MUTANT_DRY:-}" ] && [ -z "${MUTANT_ONLY:-}" ]; then for t in "$BT" "$HT" "$CT"; do run "control-$(basename "$t" .test.mjs)" "$t"; done; fi
|
||
|
||
# bus: the trigger
|
||
mutant b1-any-path-notifies "$BT" "$BB" "if (saved.path === SPEC_PATH) {" "if (true) {"
|
||
mutant b2-pm-only "$BT" "$BB" "const SPEC_REVIEWERS = ['pm', 'cto'];" "const SPEC_REVIEWERS = ['pm'];"
|
||
mutant b3-chief-also "$BT" "$BB" "const SPEC_REVIEWERS = ['pm', 'cto'];" "const SPEC_REVIEWERS = ['pm', 'cto', 'chief-of-staff'];"
|
||
mutant b4-notice-failure-swallowed "$BT" "$BB" "catch { fail('outcome-unknown'); }
|
||
}
|
||
}
|
||
this.#secretCheck(result);" "catch { }
|
||
}
|
||
}
|
||
this.#secretCheck(result);"
|
||
mutant b5-notice-not-routed "$BT" "$BB" " this.#route(business, nid, to, null);
|
||
}
|
||
}
|
||
// Row 143: a BLOCK answers" " }
|
||
}
|
||
// Row 143: a BLOCK answers"
|
||
mutant b6-body-omits-reply-id "$BT" "$BB" "send_message in_reply_to \${nid}: " "send_message: "
|
||
mutant b7-body-omits-base "$BT" "$BB" "commit \${commit}, from the editor's base \${base}. " "commit \${commit}. "
|
||
|
||
# bus: the BLOCK class and its checks
|
||
mutant c1-no-block-check "$BT" "$BB" "if (a.class === 'BLOCK') this.#checkBlock(s, to, a.in_reply_to);" ""
|
||
mutant c2-any-role-may-block "$BT" "$BB" "|| !SPEC_REVIEWERS.includes(b.roles[s.role]?.definition)) fail('block-sender');" ") fail('block-sender');"
|
||
mutant c3-any-recipient "$BT" "$BB" " if (b.roles[to]?.definition !== SPEC_ANSWER_TO) fail('block-recipient');
|
||
" ""
|
||
mutant c4-no-reply-required "$BT" "$BB" "if (!n || n.from_role !== NOTICE_ROLE || n.to_role !== s.role || !n.body.startsWith(SPEC_NOTICE)) fail('block-reply-required');" ""
|
||
mutant c5-other-roles-notice "$BT" "$BB" "|| n.to_role !== s.role ||" "||"
|
||
mutant c6-forged-notice-accepted "$BT" "$BB" "if (!n || n.from_role !== NOTICE_ROLE || n.to_role" "if (!n || n.to_role"
|
||
mutant c7-any-bus-notice "$BT" "$BB" " || !n.body.startsWith(SPEC_NOTICE)) fail('block-reply-required');" ") fail('block-reply-required');"
|
||
mutant c8-block-class-not-offered "$BT" "$BB" " 'REACTION',
|
||
'BLOCK',
|
||
].includes" " 'REACTION',
|
||
].includes"
|
||
|
||
# bus: the relay's thread
|
||
mutant t1-no-notice-chain "$BT" "$BB" " if (spec) return spec;
|
||
" ""
|
||
mutant t2-forged-notice-opens-thread "$BT" "$BB" "if (m?.from_role === NOTICE_ROLE && m.body.startsWith(SPEC_NOTICE)) {" "if (m.body.startsWith(SPEC_NOTICE)) {"
|
||
mutant t3-any-bus-notice-opens-thread "$BT" "$BB" "if (m?.from_role === NOTICE_ROLE && m.body.startsWith(SPEC_NOTICE)) {" "if (m?.from_role === NOTICE_ROLE) {"
|
||
mutant t4-oldest-thread "$BT" "$BB" "ORDER BY coalesce((SELECT max(o.seq) FROM thread_opens o WHERE o.thread=t.id), 0) DESC, t.seq DESC LIMIT 1" "ORDER BY t.seq ASC LIMIT 1"
|
||
mutant t5-ignores-opens "$BT" "$BB" "ORDER BY coalesce((SELECT max(o.seq) FROM thread_opens o WHERE o.thread=t.id), 0) DESC, t.seq DESC LIMIT 1" "ORDER BY t.seq DESC LIMIT 1"
|
||
mutant t6-any-owner "$BT" "$BB" "AND t.owner=? AND t.instance=? AND p.repo=?" "AND t.instance=? AND p.repo=?"
|
||
mutant t7-any-project "$BT" "$BB" "AND t.owner=? AND t.instance=? AND p.repo=?" "AND t.owner=? AND t.instance=? AND (p.repo=? OR 1)"
|
||
# Dewey's d1, (t.instance=? OR 1), is equivalent: thread.create refuses unless the business has exactly one
|
||
# threaded instance (broker.mjs thread.create), so every thread already belongs to the instance the relay names.
|
||
|
||
# harness: the tool offers the class
|
||
mutant h1-tool-lacks-block "$HT" "$HS" 'DECISION", "REACTION", "BLOCK"];' 'DECISION", "REACTION"];'
|
||
|
||
# contracts
|
||
mutant r1-pm-no-read_spec "$CT" roles/pm.md 'change with `read_spec` and check' 'change and check'
|
||
mutant r2-cto-no-block-class "$CT" roles/cto.md 'with `send_message` class `BLOCK` naming each' 'with `send_message` naming each'
|
||
mutant r3-pm-revert-claim "$CT" roles/pm.md "A BLOCK doesn't revert" "A BLOCK reverts"
|
||
mutant r4-cto-no-accept "$CT" roles/cto.md 'class `INFO` that begins "Accept".' 'class `INFO`.'
|
||
mutant r5-assistant-quotes "$CT" roles/assistant.md "Don't
|
||
repeat the chief of staff's text or quote it back." "Quote the chief of staff's text."
|
||
mutant r6-assistant-no-summary "$CT" roles/assistant.md "summarize it for the user in your own words." "pass it on."
|
||
mutant r7-pm-no-assistant-path "$CT" roles/pm.md "The chief of staff tells the assistant, and the assistant
|
||
tells the user." "The chief of staff tells the user."
|
||
mutant r8-chief-no-reply-link "$CT" roles/chief-of-staff.md '`send_message`
|
||
`in_reply_to` the message that carried it.' '`send_message` the message that carried it.'
|
||
mutant r9-chief-no-refusal-reason "$CT" roles/chief-of-staff.md 'The bus refuses a relay
|
||
without that link. ' ''
|
||
mutant r10-chief-no-block-note "$CT" roles/chief-of-staff.md "A BLOCK doesn't revert the commit." ""
|
||
echo done
|