Files
jason.woltjeandClaude Sonnet 5.5 d10a1a4677 researcher: row 140 packet, the pm asks the chief of staff for staff and the chief launches within limits (#1634)
Candidate on dda7e31b0: staff.request verb (pm only, STAFF-REQUEST class no other writer can produce),
request_staff pm tool and prompt line, pm and chief-of-staff contract text, 7 bus tests, tools and bundle
tests, one launcher end-to-end test. 21/21 mutants killed; node suites and all ten scripts/test-*.sh green.
Packet only; the candidate itself is row140.patch and is not applied to the tree. Nothing pushed.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-15 18:05:45 -05:00

97 lines
6.2 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Row 140 (#1634): pm asks chief for staff, and chief hires and launches.
# 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
edit "$3" "$4" "$5" || { echo "$1: edit failed"; return; }
diff -u "$BAK/$3" "$3" > "$OUT/$1.patch"
run "$1" "$2"
cp "$BAK/$3" "$3"
}
B=packages/bus/src/broker.mjs; BT=packages/bus/tests/staff-request.test.mjs
T=packages/harness/src/tools.mjs; TT=packages/harness/tests/tools.test.mjs
U=packages/harness/src/bundle.mjs; UT=packages/harness/tests/bundle.test.mjs
for t in "$BT" "$TT" "$UT"; do run "control-$(basename "$t" .test.mjs)" "$t"; done
# m1: any role can send a staff request, not only the pm
mutant m1-sender-any-role "$BT" "$B" "if (b.roles[s.role]?.definition !== STAFF_FROM) fail('staff-request-refused');" ''
# m2: the request goes to the launcher whatever it is, not only a chief of staff
mutant m2-launcher-any-role "$BT" "$B" "if (!chief || b.roles[chief]?.definition !== STAFF_TO) fail('no-chief-of-staff');" "if (!chief) fail('no-chief-of-staff');"
# m3: no launcher at all still sends (to a null recipient is the broker's problem, not this verb's)
mutant m3-no-launcher-passes "$BT" "$B" "if (!chief || b.roles[chief]?.definition !== STAFF_TO) fail('no-chief-of-staff');" "if (chief && b.roles[chief]?.definition !== STAFF_TO) fail('no-chief-of-staff');"
# m4: the role definitions' messaging lists no longer apply to a staff request
mutant m4-messaging-lists "$BT" "$B" " this.#checkMessaging(s.business, this.#sender(s), chief);
const mid = randomUUID();
const list" " const mid = randomUUID();
const list"
# m5: message.send writes the STAFF-REQUEST class, so any role can forge one
mutant m5-message-send-class "$BT" "$B" " 'REACTION',
].includes(a.class)" " 'REACTION',
'STAFF-REQUEST',
].includes(a.class)"
# m6: thread.send writes the STAFF-REQUEST class
mutant m6-thread-send-class "$BT" "$B" "['REQUEST', 'INFO', 'REACTION'].includes(a.class)) fail('invalid-class');" "['REQUEST', 'INFO', 'REACTION', 'STAFF-REQUEST'].includes(a.class)) fail('invalid-class');"
# m7: the count has no upper bound
mutant m7-count-max "$BT" "$B" "|| r.count < 1 || r.count > STAFF_COUNT) fail" "|| r.count < 1) fail"
# m8: a count of zero is accepted
mutant m8-count-min "$BT" "$B" "|| r.count < 1 || r.count > STAFF_COUNT) fail" "|| r.count > STAFF_COUNT) fail"
# m9: a count may be a fraction or a string
mutant m9-count-integer "$BT" "$B" "if (!Number.isInteger(r.count) || r.count < 1" "if (r.count < 1"
# m10: the role list has no upper bound
mutant m10-roles-max "$BT" "$B" " || a.roles.length > STAFF_ROLES)" ")"
# m11: an empty role list is accepted
mutant m11-roles-min "$BT" "$B" "|| a.roles.length < 1 || a.roles.length > STAFF_ROLES)" "|| a.roles.length > STAFF_ROLES)"
# m12: the same role may be named twice, so counts could be split past the bound
mutant m12-duplicate-role "$BT" "$B" " if (new Set(a.roles.map((r) => r.role)).size !== a.roles.length) fail('invalid-request');
" ''
# m13: the task reference is not checked
mutant m13-task-ref "$BT" "$B" "if (!taskRef(a.task_ref) || !Array.isArray(a.roles)" "if (!Array.isArray(a.roles)"
# m14: a role entry may carry keys beyond role and count
mutant m14-role-entry-keys "$BT" "$B" "keys(r, ['role', 'count'], ['role', 'count']);" "keys(r, ['role', 'count', 'model', 'harness'], ['role']);"
# m15: the request goes to the sender itself, not the launcher
mutant m15-recipient "$BT" "$B" " to: chief,
cls: 'STAFF-REQUEST'," " to: s.role,
cls: 'STAFF-REQUEST',"
# m16: the log no longer names the task the request is for
mutant m16-log-task "$BT" "$B" "staff_for: a.task_ref," "staff_for: null,"
# m17: a pm without message.send is no longer refused: the action is not the one pm holds
mutant m17-action-spent "$BT" "$B" " 'message.send',
{ decision: withinRole ? null : (a.decision ?? null), target: chief ?? null }," " 'task.assign',
{ decision: withinRole ? null : (a.decision ?? null), target: chief ?? null },"
# m18: every role with message.send is offered request_staff
mutant m18-tool-any-role "$TT" "$T" 'if (resolved.definition === "pm")
add("request_staff"' 'if (true)
add("request_staff"'
# m19: the tool's count has no upper bound in its schema
mutant m19-tool-count-max "$TT" "$T" 'count: { type: "integer", minimum: 1, maximum: 20, description: "How many" },' 'count: { type: "integer", minimum: 1, description: "How many" },'
# m20: the tool sends the wrong broker verb
mutant m20-tool-verb "$TT" "$T" 'add("request_staff", "staff.request", "message.send",' 'add("request_staff", "message.send", "message.send",'
# m21: the prompt's staff line goes to every role that can send a message
mutant m21-prompt-any-role "$UT" "$U" 'if (named.has("request_staff"))' 'if (named.has("send_message"))'
echo "mutants finished"