Packet for #1536 comment 27055: suites, 13 mutants, review notes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
42 lines
2.9 KiB
Python
42 lines
2.9 KiB
Python
# mutate.py <id>: apply one named mutant (each edit exact text, must match once). Run from the tree root.
|
|
import sys
|
|
C = "packages/conversation/"
|
|
CT = C + "src/controller.mjs"
|
|
CO = C + "src/cohort.mjs"
|
|
RELSTOP = (CT, " await this.#releaseScope(\"force-stop\", proven);\n", "")
|
|
RELCLOSE = (CT, " if (this.b?.state === \"stopped\" && this.#stopped(this.stops.get(this.b.stop))) await this.#releaseScope(\"close\");\n", "")
|
|
GUARD = " if (!rec || rec.state !== \"stopped\" || rec.proof?.kind !== \"cohortProof\" || !rec.shim) return null;\n"
|
|
M = {
|
|
"norelstop": [RELSTOP],
|
|
"norelclose": [RELCLOSE],
|
|
"norel": [RELSTOP, RELCLOSE],
|
|
# releaseCohort reports the unit absent without looking.
|
|
"nowait": [(CO, " const end = Date.now() + waitMs;\n", " return { outcome: \"released\", unit: \"absent\" };\n const end = Date.now() + waitMs;\n")],
|
|
# releaseCohort doesn't wait for systemd at all, and says so.
|
|
"wait0": [(CO, "shimSocket, waitMs = 3000 })", "shimSocket, waitMs = 0 })")],
|
|
# #releaseScope keeps only the shim check; callers unchanged.
|
|
"noguard": [(CT, GUARD, " if (!rec || !rec.shim) return null;\n")],
|
|
# close releases whenever the binding reads stopped, with no #stopped check.
|
|
"closenoproof": [(CT, " if (this.b?.state === \"stopped\" && this.#stopped(this.stops.get(this.b.stop))) await", " if (this.b?.state === \"stopped\") await")],
|
|
# The release result isn't pushed to observers.
|
|
"nopush": [(CT, " this.#push({ kind: \"evidence\", evidence: entry });\n", "")],
|
|
# The release result isn't recorded in evidence.releases.
|
|
"noevid": [(CT, " this.evidence.releases.push(entry);\n", "")],
|
|
# releaseCohort drops the null-ID check.
|
|
"invnull": [(CO, "if (!invocationId || hello.invocationId !== invocationId)", "if (hello.invocationId !== invocationId)")],
|
|
# releaseCohort sends release with no hello and no ID check.
|
|
"nohello": [(CO, " const hello = await shimRequest(shimSocket, \"hello\");\n if (!hello.ok) return { outcome: \"unavailable\", reason: hello.unavailable };\n if (!invocationId || hello.invocationId !== invocationId) return { outcome: \"unavailable\", reason: \"the shim does not answer for the recorded scope; nothing released\" };\n", "")],
|
|
# The force stop releases before the claim records stopped (guard intact).
|
|
"early": [RELSTOP, (CT, " let session = null;\n try {\n session = this.#readSession();", " await this.#releaseScope(\"force-stop\", this.claim);\n let session = null;\n try {\n session = this.#readSession();")],
|
|
# N2: killShims signals any unit.
|
|
"n2": [(C + "tests/harness.mjs", " if (!/^mosaic-chat-/.test(s.unit ?? \"\")) {\n", " if (false) {\n")],
|
|
}
|
|
if "--files" in sys.argv:
|
|
print(" ".join(sorted({f for f, _, _ in M[sys.argv[1]]}))); sys.exit(0)
|
|
for f, old, new in M[sys.argv[1]]:
|
|
s = open(f).read()
|
|
n = s.count(old)
|
|
if n != 1: sys.exit(f"{sys.argv[1]}: {n} matches in {f}")
|
|
open(f, "w").write(s.replace(old, new))
|
|
print(f)
|