Four child-path tests in verbs.test.mjs for Dewey's and Filbert's round 1 survivors; the task.create README paragraph rewrapped. Code unchanged. Row 89 (ce104b27) edited tools.mjs and tools.test.mjs after round 1's base, so this round is built oncca5f23e. Mutants 25 of 25 killed; gate 15 of 15 green. Co-Authored-By: Claude Opus 5.5 <[email protected]>
54 lines
4.6 KiB
Bash
54 lines
4.6 KiB
Bash
#!/usr/bin/env bash
|
||
# Row 63 (#1556) round 2 mutants: round 1's 18, then 7 more. Run from the candidate worktree's root:
|
||
# bash mutants.sh /path/to/mut.mjs > mutants.txt
|
||
# Each mutant edits one site with mut.mjs (exactly one match, else exit 3),
|
||
# runs the named test files and restores the file. "killed" means the run
|
||
# failed; "survived" means it passed.
|
||
set -u
|
||
MUT=$1
|
||
run() {
|
||
local name=$1 file=$2 from=$3 to=$4; shift 4
|
||
cp -- "$file" "$file.orig"
|
||
if ! node "$MUT" "$file" "$from" "$to"; then
|
||
echo "$name: NO MATCH"; mv -- "$file.orig" "$file"; return
|
||
fi
|
||
if node --test "$@" > "${LOG:-.}/mut-$name.log" 2>&1; then
|
||
echo "$name: survived"
|
||
else
|
||
echo "$name: killed ($(grep -m1 -o 'ℹ fail [0-9]*' "${LOG:-.}/mut-$name.log"), $(grep -m1 -o "code: '[a-z-]*'" "${LOG:-.}/mut-$name.log" || echo 'assertion'))"
|
||
fi
|
||
mv -- "$file.orig" "$file"
|
||
}
|
||
V=packages/tasks/src/verbs.mjs
|
||
T=(packages/tasks/tests/verbs.test.mjs packages/tasks/tests/tree.test.mjs)
|
||
H=packages/harness/src/tools.mjs
|
||
HT=(packages/harness/tests/tools.test.mjs)
|
||
run watch-only-writable $V $' if (!view) fail(\'project-not-installed\');\n' '' "${T[@]}"
|
||
run create-root-only $V 'plan.at = { project, view: ctx.tree.get(project) };' 'plan.at = { project: ctx.project, view: ctx.view };' "${T[@]}"
|
||
run create-watch-only-ok $V "if (!ctx.tree.get(project)) fail('project-not-installed');" "if (!ctx.tree.has(project)) fail('project-not-installed');" "${T[@]}"
|
||
run create-project-any $V "if (!Number.isSafeInteger(project) || project < 1) fail('invalid-request');" '' "${T[@]}"
|
||
run move-root-view $V 'const to = args.state === undefined ? fields.bucket : view.ids[args.state];' 'const to = args.state === undefined ? fields.bucket : ctx.view.ids[args.state];' "${T[@]}"
|
||
run move-path-root-view $V '`/projects/${project}/views/${view.id}/buckets/${to}/tasks`' '`/projects/${project}/views/${ctx.view.id}/buckets/${to}/tasks`' "${T[@]}"
|
||
run close-root-done $V '`/projects/${project}/views/${view.id}/buckets/${view.done}/tasks`' '`/projects/${project}/views/${view.id}/buckets/${ctx.view.done}/tasks`' "${T[@]}"
|
||
run read-root-board $V 'bucket = (await board(ctx, at.project, at.view)).get(id)?.bucket;' 'bucket = (await board(ctx)).get(id)?.bucket;' "${T[@]}"
|
||
run read-no-project $V "if (x.json.project_id !== at.project) fail('task-moved');" '' "${T[@]}"
|
||
run relation-any-project $V $' installed(other.project);\n' '' "${T[@]}"
|
||
run handle-no-located $V $' await located(plan.others ?? []);\n' '' "${T[@]}"
|
||
run create-no-located $V $' await located(plan.others);\n' '' "${T[@]}"
|
||
run located-no-project $V "if (x.json.project_id !== r.project) fail('task-moved');" '' "${T[@]}"
|
||
run schedule-add-only $V 'plan.others = [...relations.add, ...relations.remove];' 'plan.others = [...relations.add];' "${T[@]}"
|
||
run located-after-authorize $V $' await located(plan.others ?? []);\n ctx.broker.authorize(cap, verb, { decision: plan.decision, target: args.task_ref });\n' $' ctx.broker.authorize(cap, verb, { decision: plan.decision, target: args.task_ref });\n await located(plan.others ?? []);\n' "${T[@]}"
|
||
run tool-project-string $H 'project: { type: "integer", minimum: 1,' 'project: { type: "string", minimum: 1,' "${HT[@]}"
|
||
run tool-project-zero $H 'project: { type: "integer", minimum: 1,' 'project: { type: "integer", minimum: 0,' "${HT[@]}"
|
||
run tool-project-required $H '}, ["title", "request", "requirement"]],' '}, ["title", "request", "requirement", "project"]],' "${HT[@]}"
|
||
# Round 2: the survivors of Dewey's and Filbert's round 1 mutants, each a child path sent back to
|
||
# the root's project or view, or the relation read cut to the first relation.
|
||
R='{ ...at, project: ctx.project, view: ctx.view }'
|
||
run located-first-only $V 'for (const r of list) {' 'for (const r of list.slice(0, 1)) {' "${T[@]}"
|
||
run step-reread-root $V $'after = await read(at);\n } catch {\n // the re-read failed too' $'after = await read('"$R"$');\n } catch {\n // the re-read failed too' "${T[@]}"
|
||
run handle-final-root $V $'after = await read(at);\n } catch {\n // handled below: a failed' $'after = await read('"$R"$');\n } catch {\n // handled below: a failed' "${T[@]}"
|
||
run create-final-root $V $'after = await read(at);\n } catch {\n // handled below, as in handle()' $'after = await read('"$R"$');\n } catch {\n // handled below, as in handle()' "${T[@]}"
|
||
run create-fallback-root-todo $V 'taskFields(r.json, at.view.ids.todo)' 'taskFields(r.json, ctx.view.ids.todo)' "${T[@]}"
|
||
run read-done-root $V 'let bucket = at.view.done;' 'let bucket = ctx.view.done;' "${T[@]}"
|
||
run close-done-root $V '(a) => a.task.done && a.bucket === view.done,' '(a) => a.task.done && a.bucket === ctx.view.done,' "${T[@]}"
|