#!/usr/bin/env python3 # Row 270 mutants. M1-M12 are round 1's (anchors at 7d199f033); M13-M21 are round 2's # (duckworth-0223 B1-B3, sage-3030, sage-3031, mos-1352); M22-M24 are round 3's (duckworth-0226 # B4, sage-3038). Round 3's kill lines are at round 3's tests. `apply ` edits the worktree and # prints the touched path; each edit asserts its anchor appears exactly once. `check` prints each # anchor's count and kill. K names the test and the first assertion each mutant should fail # (checked by reading, not run). The base blob of every touched file is in BUILD.md; a restore is # `git checkout -- `, then sha256 against it (sage-3030 item 3). import sys WT = "/mnt/storage/scratch/gizmo-270/" C = "packages/seat/src/compactions.mjs" B = "packages/bus/src/broker.mjs" L = "packages/cli/src/launcher.mjs" R = "packages/bus/src/runtime.mjs" ST = "packages/seat/tests/compactions.test.mjs" SB = "packages/seat/tests/compactions-budget.test.mjs" BT = "packages/bus/tests/session-compactions.test.mjs" CT = "packages/cli/tests/compactions-launch.test.mjs" M = { "M1": (C, " const key = keyOf(f.entry, f.completedAt);\n if (ledger.events.has(key)) continue;", " const key = keyOf(f.stream + f.entry, f.completedAt);\n if (ledger.events.has(key)) continue;"), "M2": (C, "const keyOf = (entry, completedAt) => JSON.stringify([entry, completedAt]);", "const keyOf = (entry, completedAt) => JSON.stringify([entry, null]);"), "M3": (C, 'if (e.type === "compaction" && typeof e.id === "string" && e.id) {', 'if ((e.type === "compaction" || e.message?.role === "compactionSummary") && typeof e.id === "string" && e.id) {'), "M4": (C, "digest(tail) === c.tail) from = c.bytes;", "true) from = c.bytes;"), "M5": (C, 'if (lines.pop() !== "") bad = torn = true;', 'if (lines.pop() !== "") torn = true;'), "M6": (C, '(ledger.torn ? "\\n" : "") + out.map', 'out.map'), "M7": (C, ' if (ledger.incomplete) return unknown("store-incomplete", count, at);\n', ""), "M8": (C, ' if (ledger.unsupported) return unknown("harness-unsupported", count, at);\n', ""), "M9": (C, "({ count: count || null, known: false, reason, at })", "({ count, known: false, reason, at })"), # Round 3 moved M10's anchor to the Set (duckworth-0226 B4); the mutant is the same. "M10": (C, ' for (const stream of Object.keys(cursors)) if (!present.has(stream)) problems.add("store-incomplete");\n', ""), "M11": (B, "op === 'legacy-3l')", "false)"), "M12": (B, "if (!this.#compactions) return unknown('not-collected');", "if (!this.#compactions) return { count: 0, known: true, reason: null, at: null };"), # B2: the launcher's two collections and the runtime's reader. "M13": (L, " if (store) compactions(store, model.harness, { instance, thread, session, run });\n const toolSocket", " const toolSocket"), "M14": (L, " if (store) compactions(store, model.harness, { instance, thread, session, run });\n try { lock?.release(); }", " try { lock?.release(); }"), "M15": (R, " return dir ? compactionCount(dir) : { count: null, known: false, reason: 'store-unreadable', at: null };", " return null;"), # B1: the budget, its setting and the carry across reads. "M16": (C, " const stop = Math.min(size, from + left);", " const stop = size;"), "M17": (C, " return Number.isSafeInteger(value) && value >= READ_MIN && value <= READ_MAX ? value : READ_BYTES;", " return value ?? READ_BYTES;"), "M18": (L, " const budget = readBudget(system?.compactionReadBytes);", " const budget = READ_BYTES;"), "M19": (C, " take(carry.length ? Buffer.concat([...carry, view.subarray(i, nl)]) : view.subarray(i, nl));", " take(view.subarray(i, nl));"), # B3: Claude history from before the ledger, and its stickiness. "M20": (C, ' if (harness === "pi" && !prior && claudeHistory(store)) {', ' if (harness === "pi" && !prior && false) {'), "M21": (C, 'if (r.harness !== "pi" || r.reason === "harness-unsupported") unsupported = true;', 'if (r.harness !== "pi") unsupported = true;'), # B4: the stream cap and its setting. "M22": (C, ' if (visit.length > streams) problems.add("not-collected");\n for (const name of visit.slice(0, streams)) {', ' for (const name of visit) {'), "M23": (C, " return Number.isSafeInteger(value) && value >= STREAMS_MIN && value <= STREAMS_MAX ? value : STREAMS;", " return value ?? STREAMS;"), "M24": (L, " const streams = readStreams(system?.compactionStreams);", " const streams = STREAMS;"), } K = { "M1": (ST, "a compaction copied into a branched stream counts once, under the stream it was first seen in", 64, "c1 is written again under b.jsonl: [[c1,a],[c1,b],[c2,b]]; the count holds at 1 and 2 because readLedger dedupes"), "M2": (ST, "the same entry id at another time in another stream is another compaction", 81, "count 1, not 2"), "M3": (ST, "an empty store, a store with no compaction and a failed start count 0, known", 40, "the compactionSummary message m2 counts: count 1, not 0"), "M4": (ST, "a stream that shrank, changed under its cursor or went away is store-incomplete for good > rewrite", 170, "same length, other bytes, read from the old cursor: known true"), "M5": (ST, "a torn last ledger line makes the count unknown, a lower bound, and stays so", 131, "the torn line is popped unparsed, so nothing sets bad: {count 0, known true}"), "M6": (ST, "a torn last ledger line makes the count unknown, a lower bound, and stays so", 133, "the c1 record joins the torn line and is lost: count null, not 1"), "M7": (ST, "a stream that shrank, changed under its cursor or went away is store-incomplete for good > shrink", 174, "the later clean collection reads known; remove would pass, its cursor stays missing"), "M8": (ST, "a Claude run is harness-unsupported, and stays so after a Pi run", 201, "the Pi run reads known true"), "M9": (ST, "a torn last ledger line makes the count unknown, a lower bound, and stays so", 131, "count 0, not null; the symlinked-stream test's :184 fails the same way"), "M10": (ST, "a stream that shrank, changed under its cursor or went away is store-incomplete for good > remove", 170, "a removed stream raises no problem: known true"), "M11": (BT, "a legacy session is asked for with legacy true", 76, "asked with legacy false"), "M12": (BT, "without a reader the count is unknown, never 0; a reader that throws is store-unreadable", 81, "{count 0, known true} for no reader"), "M13": (CT, "a run collects compactions at its start and its end, and the count holds across a resume and a host restart", 188, "no start collection: run 1 logs only [D,2,true,null]; settle returns after 5 s with one event"), "M14": (CT, "a run collects compactions at its start and its end, and the count holds across a resume and a host restart", 188, "no end collection: run 1 logs only [D,1,true,null]"), "M15": (CT, "a run collects compactions at its start and its end, and the count holds across a resume and a host restart", 203, "session.list's compactions is null: {at: 'undefined'} and no count; the clear test's :328 and the legacy :348 fail the same way"), "M16": (SB, "a stream past the default budget is not-collected with a lower bound, and a later collection catches up", 50, "the whole 66 MiB is read: {count 1, known true, reason null}"), "M17": (SB, "the budget is the setting's whole number of bytes from 1 MiB to 1 GiB, and the default for anything else", 39, "readBudget(null) is the default, but readBudget('8388608') is the string"), "M18": (CT, "the read budget is the system config's compactionReadBytes, and a bad value takes the default", 254, "the 1 MiB setting is ignored, the 2 MiB hole is read whole: [D,1,true,null] twice"), "M19": (SB, "a line split across reads counts once", 81, "c1's two halves parse alone and fail: {count null, known false, reason store-incomplete}"), "M20": (SB, "Claude history from before the ledger makes the first Pi collection harness-unsupported, for good", 90, "the first collection counts c1: {count 1, known true}"), "M21": (SB, "Claude history from before the ledger makes the first Pi collection harness-unsupported, for good", 91, "a Pi collected record isn't sticky: the second reads {count 1, known true}"), "M22": (SB, "more streams than the cap is not-collected, with cursors only for the streams opened, and a larger cap catches up", 129, "all four streams are opened: {count 4, known true, reason null}; the default-cap test's :143 fails the same way (1025 cursors)"), "M23": (SB, "the stream cap is the setting's whole number from 32 to 65536, and the default for anything else", 120, "readStreams(null) is the default, but readStreams('2048') is the string"), "M24": (CT, "the stream cap is the system config's compactionStreams, and a bad value takes the default", 290, "the cap of 32 is ignored, all 34 streams are opened: [D,1,true,null] twice"), } cmd = sys.argv[1] if cmd == "list": print(" ".join(M)); sys.exit(0) if cmd == "check": for k, (f, a, b) in M.items(): n = open(WT + f).read().count(a) tf, name, line, why = K[k] print(k, f, n, "kill", f"{tf}:{line}", name) sys.exit(0) f, a, b = M[sys.argv[2]] s = open(WT + f).read() assert s.count(a) == 1, (sys.argv[2], s.count(a)) open(WT + f, "w").write(s.replace(a, b)) print(f)