#!/usr/bin/env bash # P8-REVIEW axis 3, REFUTER mutations. Reversible. Point PLATFORM at a COPY, never at the repo. # PLATFORM=/path/to/copy/platform ./mutations-refuter.sh R1|R2|R3|R4|restore set -euo pipefail PLATFORM="${PLATFORM:?set PLATFORM to a copy of platform/}" R="$PLATFORM/internal/runs/reconcile.go" S="$PLATFORM/internal/pgstore/sink.go" M="$PLATFORM/internal/readmodel/readmodel.go" B="$PLATFORM/internal/books/parse.go" back() { for f in "$R" "$S" "$M" "$B"; do [ -f "$f.p8bak" ] || cp "$f" "$f.p8bak"; done; } case "${1:?R1|R2|R3|R4|restore}" in R1) # "CLEARED BY EVIDENCE, never by the absence of it": drop the guard, so a pass that asked the # engine nothing clears the failure count of a wedged run (the 1,0,1,0 oscillation). back python3 - "$R" <<'PY' import sys p=sys.argv[1]; s=open(p).read() old=""" if !established { """ new=""" if !established && false { """ assert s.count(old)==1, s.count(old) open(p,'w').write(s.replace(old,new)) PY ;; R2) # UnsettledRuns keyed on the RUN being over instead of the ATTEMPT being over — the exact # regression its own doc comment names ("the hold stayed reserved for the life of the account"). back python3 - "$S" <<'PY' import sys p=sys.argv[1]; s=open(p).read() old="join run_attempts a on a.run_id = r.id and a.ended_at is not null" new="join run_attempts a on a.run_id = r.id and r.finished_at is not null" assert s.count(old)==1, s.count(old) open(p,'w').write(s.replace(old,new)) PY ;; R3) # readmodel.Drain loses the between-books budget gate — the mechanism PD-293 is marked fixed by. back python3 - "$M" <<'PY' import sys p=sys.argv[1]; s=open(p).read() old=""" if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < MaterializeBudget {""" new=""" if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < 0 && deadline.IsZero() {""" assert s.count(old)==1, s.count(old) open(p,'w').write(s.replace(old,new)) PY ;; R4) # books.Sweep loses the "do not start a book we cannot give a whole parse" gate. back python3 - "$B" <<'PY' import sys p=sys.argv[1]; s=open(p).read() old=""" if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < jobs.JobTimeout {""" new=""" if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < 0 && deadline.IsZero() {""" assert s.count(old)==1, s.count(old) open(p,'w').write(s.replace(old,new)) PY ;; restore) for f in "$R" "$S" "$M" "$B"; do [ -f "$f.p8bak" ] && mv "$f.p8bak" "$f"; done; echo restored ;; esac