gizmoduck: row 270 (264c, #1775) round 1 for review (sage-3024): mutants.py M1-M12 with anchors at 7d199f033, each matching once, kills read from the tests; run plan with broker.mjs reruns; launcher and runtime wiring named as untested; not run
This commit is contained in:
1 parent
7d199f0331
commit
8a5eb3c8ba
2 files changed
+105
No files matched your search
@@ -154,3 +154,43 @@ Each must turn a new test red:
|
||||
- M10 removed stream ignored: drop the missing-cursor loop. Kill: remove subtest.
|
||||
- M11 broker legacy flag: `op === 'legacy-3l'` → `false`. Kill: bus legacy test.
|
||||
- M12 broker default 0: no reader → `{count: 0, known: true, ...}`. Kill: bus no-reader test.
|
||||
|
||||
## Round 1 for review (sage-3024)
|
||||
|
||||
270's code reached the 271 branch in 09b20784f and 48c34539c and has no verdict and no mutant run.
|
||||
This round submits it on its own: the manifest is the paths 270's commits change, hashed at
|
||||
7d199f033 (the 271 r3 tip). queue-271/BUILD.md, which 8365e4e5b also touched, stays with 271.
|
||||
broker.mjs, runtime.mjs and launcher.mjs carry 271's changes too, so their blobs match the 271 round.
|
||||
|
||||
Mutants: `mutants.py` beside this file, anchors at 7d199f033, each matching once (`check`, python
|
||||
only). Each kill below is read from the test, not run yet.
|
||||
|
||||
| Mutant | Edit | Kill: first failing assertion |
|
||||
| --- | --- | --- |
|
||||
| M1 | collect key `keyOf(f.stream + f.entry, ...)` | seat compactions.test.mjs:64, ledger lines gain `[c1,b.jsonl]` (counts hold, readLedger dedupes) |
|
||||
| M2 | `keyOf` drops the timestamp | :81, count 1 not 2 |
|
||||
| M3 | count `compactionSummary` messages | :40, m2 counts 1 |
|
||||
| M4 | tail digest check `true` | :170 in `rewrite`, known true |
|
||||
| M5 | `bad = torn = true` to `torn = true` | :131, the torn line is popped unparsed, count reads known 0 |
|
||||
| M6 | no newline after a torn line | :133, c1 joins the torn line, count null not 1 |
|
||||
| M7 | drop `if (ledger.incomplete)` | :174 in `shrink` (`remove` stays incomplete by its missing cursor) |
|
||||
| M8 | drop `if (ledger.unsupported)` | :201, Pi run reads known |
|
||||
| M9 | `count \|\| null` to `count` | :131, count 0 not null |
|
||||
| M10 | drop the missing-cursor loop | :170 in `remove` |
|
||||
| M11 | broker `op === 'legacy-3l'` to `false` | bus session-compactions.test.mjs:76 |
|
||||
| M12 | broker no reader gives `{count: 0, known: true}` | bus session-compactions.test.mjs:81 |
|
||||
|
||||
Run plan, on a CLEAR only: each mutant runs its test file whole under `timeout -k 10 120` (M1-M10
|
||||
seat compactions.test.mjs, M11-M12 bus session-compactions.test.mjs), TMPDIR from
|
||||
`mktemp -d /mnt/storage/scratch/tmp/gXXX`, restore with `git checkout` and a clean-tree check after
|
||||
each. A kill is an AssertionError at the named line. M11 and M12 edit broker.mjs, which 271 also
|
||||
changed, so after their restore bus session-clear.test.mjs and sessions.test.mjs run whole, each
|
||||
under `timeout -k 10 300`. compactions.mjs has no 271 change.
|
||||
|
||||
Not covered: launcher.mjs's two `compactions(store, ...)` calls (run start, run end) and runtime.mjs's
|
||||
reader closure have no test in either file, and no test elsewhere names compactions. A mutant
|
||||
dropping either launcher call or making the closure answer a constant would survive. This is the
|
||||
T3 Pi half as built; the Tests section above never claimed the wiring. Adding a cli and a runtime
|
||||
test is a scope call for Sage.
|
||||
|
||||
Prior coverage: none. 271's M1-M14 edit no 270 line, and no past verdict names 270.
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
# Row 270 mutants M1-M12 (BUILD.md "Mutants", anchors at 7d199f033). `apply <id>` edits the
|
||||
# worktree and prints the touched path; each edit asserts its anchor appears exactly once.
|
||||
# K names the test and the first assertion each mutant should fail (checked by reading, not run).
|
||||
import sys
|
||||
WT = "/mnt/storage/scratch/gizmo-270/"
|
||||
C = "packages/seat/src/compactions.mjs"
|
||||
B = "packages/bus/src/broker.mjs"
|
||||
ST = "packages/seat/tests/compactions.test.mjs"
|
||||
BT = "packages/bus/tests/session-compactions.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 })"),
|
||||
"M10": (C, ' for (const stream of Object.keys(cursors)) if (!names.includes(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 };"),
|
||||
}
|
||||
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"),
|
||||
}
|
||||
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)
|
||||
Reference in new issue
Block a user