Files
jason.woltje 4ff4f44c98 lead: commit researcher's untracked evidence (1406 files: queue-101 queue-105 queue-128 queue-134 queue-143 queue-148 queue-183 queue-228)
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.
2026-11-02 15:05:14 -06:00

115 lines
8.7 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 148 (#1642): a Console editor for the project's spec and docs.
# 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"
}
PI=packages/project/src/index.mjs; PP=packages/project/src/paths.mjs; PT=packages/project/tests/human-file.test.mjs
BB=packages/bus/src/broker.mjs; BT=packages/bus/tests/project-files.test.mjs
WS=packages/webui/src/serve.mjs; WT_=packages/webui/tests/project-file.test.mjs
MD=packages/webui/src/public/markdown-preview.js; MT=packages/webui/tests/markdown-preview.test.mjs
BJ=packages/webui/src/public/bus.js; DT=packages/webui/tests/docs-browser.test.mjs
if [ -z "${MUTANT_DRY:-}" ]; then for t in "$PT" "$BT" "$WT_" "$MT" "$DT"; do run "control-$(basename "$t" .test.mjs)" "$t"; done; fi
# project: the human writer
mutant p1-no-stale-guard "$PT" "$PI" "'HEAD', '--', path]) !== base)" "'HEAD', '--', path]) !== base && false)"
mutant p2-any-path "$PT" "$PP" "(path === 'spec/north-star.md' || /^docs" "(true || path === 'spec/north-star.md' || /^docs"
mutant p3-author-not-the-human "$PT" "$PI" "const name = checkedId(context.business.human);" "const name = 'someone';"
mutant p4-creates-missing-file "$PT" "$PI" "if (before === null) throw new ProjectError('project-read-missing'" "if (false) throw new ProjectError('project-read-missing'"
mutant p5-no-content-check "$PT" "$PI" "if (typeof content !== 'string' || !content.length ||" "if (typeof content !== 'string' ||"
# bus: the human-only verbs
mutant b1-agent-may-save "$BT" "$BB" " this.#human(s);
if (!this.#project?.listFiles) fail('project-not-configured');" " if (!this.#project?.listFiles) fail('project-not-configured');"
mutant b2-save-keys-not-strict "$BT" "$BB" "keys(args, ['project', 'path', 'base', 'content'], ['project', 'path', 'base', 'content']);" "keys(args, ['project', 'path', 'base', 'content'], ['project', 'path']);"
# webui server: the save route
mutant w1-no-origin-check "$WT_" "$WS" " if (one(req, 'origin') !== \`https://\${preview.host}\`) return refuse(403, 'cross-origin request refused', 'a save needs the Console\\'s own Origin');
" ""
mutant w2-no-fetch-metadata "$WT_" "$WS" " if (one(req, 'sec-fetch-site') !== 'same-origin') return refuse(403, 'cross-site request refused', 'a save needs same-origin Fetch Metadata');
" ""
mutant w3-extra-keys-allowed "$WT_" "$WS" "if (Object.keys(value).length !== FILE_SAVE_KEYS.length || !FILE_SAVE_KEYS.every" "if (!FILE_SAVE_KEYS.every"
mutant w4-stale-looks-unknown "$WT_" "$WS" "return sent === false
? refuse(busStatus(code), code, code === 'stale-base'" "return false
? refuse(busStatus(code), code, code === 'stale-base'"
mutant w5-answer-path-unchecked "$WT_" "$WS" "|| result.path !== value.path) return refuse(503, 'outcome-unknown'" ") return refuse(503, 'outcome-unknown'"
# preview: no script, no sink, no unsafe link
mutant v1-sink-in-preview "$MT" "$MD" "window.MosaicMarkdown = Object.freeze({ render, linkTarget });" "window.MosaicMarkdown = Object.freeze({ render, linkTarget }); void 0 && document.body.innerHTML;"
mutant v2-any-scheme-links "$MT" "$MD" "return /^https?:\\/\\/[^/?#]/i.test(target) ? target : null;" "return target;"
mutant v3-protocol-relative-links "$MT" "$MD" "return target.startsWith('//') ? null : target;" "return target;"
mutant v4-no-rel "$MT" "$MD" "a.setAttribute('rel', 'noopener noreferrer');" ""
mutant v5-evasion-class-skipped "$MT" "$MD" "if (!target || target.length > SPAN ||" "if (!target || target.length > SPAN || false &&"
mutant v6-scheme-links-in-browser "$DT" "$MD" "return /^https?:\\/\\/[^/?#]/i.test(target) ? target : null;" "return target;"
mutant v7-unbounded-scan "$MT" "$MD" "const found = text.slice(from, last + 1).indexOf(ch);" "const found = text.slice(from).indexOf(ch);"
mutant v8-no-budget-check "$MT" "$MD" " if (work >= budget) return null;
const miss" " const miss"
mutant v9-budget-never-spent "$MT" "$MD" "const miss = reached => { work += reached - at + 1; return null; };" "const miss = reached => { return null; };"
mutant v10-budget-multiplier "$MT" "$MD" "BUDGET_PER_CHAR = 32, BUDGET_FLOOR = 1 << 20;" "BUDGET_PER_CHAR = 32000, BUDGET_FLOOR = 1 << 20;"
mutant v11-code-span-scan-uncharged "$MT" "$MD" " work += j - from;
return -1;" " return -1;"
mutant v12-closer-scan-uncharged "$MT" "$MD" " work += j - from;
return null;" " return null;"
mutant v13-closer-unbudgeted "$MT" "$MD" " function closerOf(text, from, ch, use) {
if (work >= budget) return null;" " function closerOf(text, from, ch, use) {"
mutant v14-paragraph-trim-by-regex "$MT" "$MD" "para.map(trimBlanksEnd).join" "para.map(l => l.replace(/[ \\t]+\$/, '')).join"
mutant v15-closing-hashes-by-regex "$MT" "$MD" "inline(stripClosingHashes((atx[2] ?? '').trim()).trim()," "inline((atx[2] ?? '').trim().replace(/(^|[ \\t]+)#+\$/, '').trim(),"
# round 3 (B1): the `s` flag on the three block regexes that end in (.*)$; each is removed in turn
mutant v16-fence-without-s-flag "$MT" "$MD" '(`{3,}|~{3,})(.*)$/s;' '(`{3,}|~{3,})(.*)$/;'
mutant v17-atx-without-s-flag "$MT" "$MD" '(?:[ \t]+(.*))?$/s;' '(?:[ \t]+(.*))?$/;'
mutant v18-item-without-s-flag "$MT" "$MD" '([ \t]+|$)(.*)$/s;' '([ \t]+|$)(.*)$/;'
# round 3 (sage-0621): the thematic-break scan that replaced the HR regex; one rule of it is broken in turn
mutant v19-rule-needs-one-mark "$MT" "$MD" 'return marks >= 3;' 'return marks >= 1;'
mutant v20-rule-needs-two-marks "$MT" "$MD" 'return marks >= 3;' 'return marks >= 2;'
mutant v21-rule-allows-four-spaces "$MT" "$MD" "while (i < 3 && line[i] === ' ') i++;" "while (i < 4 && line[i] === ' ') i++;"
mutant v22-rule-ignores-other-chars "$MT" "$MD" 'else if (!blank(line[i])) return false;' 'else if (false) return false;'
mutant v23-rule-mixes-marks "$MT" "$MD" "if (line[i] === mark) marks++;" "if (line[i] === '-' || line[i] === '*' || line[i] === '_') marks++;"
mutant v24-rule-refuses-tabs "$MT" "$MD" 'else if (!blank(line[i])) return false;' "else if (line[i] !== ' ') return false;"
mutant v25-rule-back-to-regex "$MT" "$MD" 'const isRule = line => {' 'const isRule = line => /^ {0,3}([-*_])(?:[ \t]*\1){2,}[ \t]*$/.test(line);
const isRuleScan = line => {'
# editor view
mutant e1-preview-by-markup "$DT" "$BJ" "box.replaceChildren(window.MosaicMarkdown.render(s.text));" "box.innerHTML = s.text;"
mutant e2-wrong-base "$DT" "$BJ" "base: s.commit, content: s.text }" "base: '0'.repeat(40), content: s.text }"
mutant e3-base-does-not-move "$DT" "$BJ" "s.commit = body.commit; s.original = sent.content;" "s.original = sent.content;"
mutant e4-unchanged-is-savable "$DT" "$BJ" "&& s.text !== s.original && !s.raw.includes" "&& !s.raw.includes"
mutant e5-refusal-drops-draft "$DT" "$BJ" "} else if (body?.sent === false) s.status = \`\${typeof body.message === 'string' && body.message ? body.message : 'Not saved.'} Draft kept.\`;" "} else if (body?.sent === false) { s.status = 'Not saved.'; s.text = s.original; }"
# round 4 (sage-0624): a throw in the preview or a paint must not wedge the editor
mutant e6-preview-throw-uncaught "$DT" "$BJ" "} catch { box.textContent = 'The preview failed. The source is unchanged.'; }" "} finally { }"
mutant e7-saving-not-reset-on-throw "$DT" "$BJ" "} finally { s.saving = false; } // a throw above must not leave Save off and Reload refused" "} finally { } s.saving = false;"
echo "mutants finished"