R2/B1: after a forbidden or not-found refusal on a child, the tick reads
GET /projects/<id> and drops the child only on 403 or 404; a deleted
kanban view (project read 200) fails the tick as in round 1. Tests 18
and 19, 23/23 mutants killed, gate on ae428a54 green (14 suites).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
49 lines
4.5 KiB
Bash
49 lines
4.5 KiB
Bash
#!/bin/bash
|
||
# Round 3. Same method as mutants-round2.sh: each mutant edits one source file in the build worktree,
|
||
# runs the tests, then restores the file from the worktree index (the round 3 candidate). Rounds 1
|
||
# and 2 run again first, with the round 2 lines retargeted at the new leftTree(). Each runs only the
|
||
# test file that should fail it, since another seat's suite shared the machine; the gate runs every
|
||
# suite on the candidate.
|
||
export TMPDIR=~/darkwing-scratch/r62/tmp
|
||
cd ~/darkwing-scratch/r62/build
|
||
S=packages/tasks/src/sync.mjs; U=packages/tasks/src/startup.mjs; T=packages/tasks/tests/tree.test.mjs
|
||
run() { # name file sed-expr test-file
|
||
sed -i "$3" "$2"
|
||
if git diff --quiet -- "$2"; then echo "$1: MUTATION DID NOT APPLY"; return; fi
|
||
env -u NODE_TEST_CONTEXT node --test --test-timeout=30000 "$4" > ~/darkwing-scratch/r62/tmp/mut3-$1.log 2>&1
|
||
echo "$1: rc=$? $(grep -E '^ℹ (pass|fail) ' ~/darkwing-scratch/r62/tmp/mut3-$1.log | tr '\n' ' ')"
|
||
grep -E '^✖ ' ~/darkwing-scratch/r62/tmp/mut3-$1.log | sed 's/ ([0-9.]*ms)$//; s/^/ /' | sort -u | head -6
|
||
git checkout -q -- "$2"
|
||
}
|
||
# Round 1.
|
||
run no-leave-tree-check $S 's/} else if (!ctx.tree.has(project)) {/} else if (false) {/' $T
|
||
run no-watch-only-bucket $S 's/^const fieldsFor = .*/const fieldsFor = (task, bucket) => taskFields(task, bucket);/' $T
|
||
run placed-by-id $S 's/placed.add(ref(project, id));/placed.add(id);/; s/.filter((r) => !placed.has(r));/.filter((r) => !placed.has(parseRef(r).task));/' $T
|
||
run keep-archived $U 's/if (p.is_archived || p.id === ctx.project) continue;/if (p.id === ctx.project) continue;/' $T
|
||
run config-drops-descendants packages/cli/src/config.mjs 's/ descendants: v\["tracker.descendants"\],/ descendants: false,/' packages/cli/tests/config.test.mjs
|
||
# Round 2: R1, retargeted at the async leftTree().
|
||
run r2-child-refuses $S 's/ if (!(await leftTree(ctx, project, e))) throw e;/ throw e;/' $T
|
||
run r2-skip-keeps-child $S 's/ ctx.tree.delete(project);//' $T
|
||
run r2-root-drops $S 's/ if (project === ctx.project || !(e instanceof BusError)/ if (!(e instanceof BusError)/' $T
|
||
run r2-any-error-drops $S "s/ || (e.code !== 'tracker-forbidden' \&\& e.code !== 'tracker-not-found')) return false;/) return false;/" $T
|
||
run r2-403-only $S "s/(e.code !== 'tracker-forbidden' \&\& e.code !== 'tracker-not-found')/e.code !== 'tracker-forbidden'/" $T
|
||
run r2-404-only $S "s/(e.code !== 'tracker-forbidden' \&\& e.code !== 'tracker-not-found')/e.code !== 'tracker-not-found'/" $T
|
||
# Round 2: Filbert's N1 to N3, under the names Filbert used. Filbert's edits may differ from these.
|
||
run tree-early $U 's/^ const tree = new Map(\[\[ctx.project, ctx.view\]\]);/ const tree = (ctx.tree = new Map([[ctx.project, ctx.view]]));/' $T
|
||
run missing-done-root-bucket $S 's/doneBucket(ctx.tree.get(project))/doneBucket(ctx.view)/' $T
|
||
run leave-tree-no-keep-updated $S '/} else if (!ctx.tree.has(project)) {/{n;s/ updated = c.updated;//}' $T
|
||
# Round 2: Dewey's three test gaps (comment 27280), under Dewey's names. Dewey's edits may differ.
|
||
# tick-done-root-bucket has two lines on the tick path: a closed task the cursor returns that the
|
||
# board no longer shows, and one the board still showed.
|
||
run reconcile-done-root-bucket $S 's/const bucket = t.done ? doneBucket(view) :/const bucket = t.done ? doneBucket(ctx.view) :/' $T
|
||
run tick-done-root-bucket $S "s/bucket: doneBucket(view), via: 'cursor'/bucket: doneBucket(ctx.view), via: 'cursor'/" $T
|
||
run tick-done-root-bucket-board $S 's/const b = use.done ? doneBucket(view) : bucket;/const b = use.done ? doneBucket(ctx.view) : bucket;/' $T
|
||
run tree-check-before-moved $S 's/ if (x.json.project_id !== project) {/ if (x.json.project_id !== project \&\& ctx.tree.has(project)) {/' $T
|
||
# Round 3: R2 (Filbert) and B1 (Dewey), the confirm read. Dewey's name for the 401 one.
|
||
run r3-no-confirm $S "s|^ const r = await ctx.sync('GET', \`/projects/\${project}\`);| const r = { status: 404 };|" $T
|
||
run r3-confirm-403-only $S 's/ return r.status === 403 || r.status === 404;/ return r.status === 403;/' $T
|
||
run r3-confirm-404-only $S 's/ return r.status === 403 || r.status === 404;/ return r.status === 404;/' $T
|
||
run r3-confirm-not-200 $S 's/ return r.status === 403 || r.status === 404;/ return r.status !== 200;/' $T
|
||
run r2-unauthorized-drops $S "s/ \&\& e.code !== 'tracker-not-found')) return false;/ \&\& e.code !== 'tracker-not-found' \&\& e.code !== 'tracker-unauthorized')) return false;/" $T
|
||
git diff --quiet -- $S $U packages/cli/src/config.mjs && echo "restored: sources match the candidate index"
|