Files

137 lines
5.6 KiB
Bash

#!/usr/bin/env bash
# CHECK-q148 -- the baseline re-take tool, and the re-take it performed.
#
# Q148 (2026-11-01): `check_entry_baseline.tsv` fails in the direction nobody
# automates -- a row whose entry point has since been repaired reads IMPROVED in
# the sweep, and the row is re-taken by hand (Q145, Q146, Q147 each did it once).
# `wizard-work/volt/q143-check-sweep/retake.py` measures named rows with the
# sweep's own `run_entry`/`classify`, reports the codes that moved, and rewrites
# only those rows behind `--write`, with a provenance comment.
#
# leg 1 the tool's 12-cell selftest
# leg 2 two rows the sweep recorded green still read green from the tool
# leg 3 a copy of the baseline with one row's code moved is named, written
# back, and reads clean on a second take (the tool's own contract)
# leg 4 the baseline on disk carries this tick's provenance block and still
# parses under the sweep's own reader
# leg 5 no row in the baseline names evidence the tree does not have
# (the MISSING direction; the NEW direction is another lane's row)
#
# rc 0 all legs pass, rc 1 a leg faulted, rc 2 could not grade.
set -u
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || { echo "CANNOT GRADE: no directory"; exit 2; }
ROOT="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null)" || { echo "CANNOT GRADE: not a git repository"; exit 2; }
SWEEP="$ROOT/wizard-work/volt/q143-check-sweep"
TOOL="$SWEEP/retake.py"
BASE="$SWEEP/check_entry_baseline.tsv"
for f in "$TOOL" "$BASE" "$SWEEP/check_sweep.py"; do
[ -f "$f" ] || { echo "CANNOT GRADE: missing $f"; exit 2; }
done
PY="${PYTHON:-python3}"
WORK="$(mktemp -d "${TMPDIR:-/tmp}/q148.XXXXXX")" || exit 2
trap 'rm -rf "$WORK"' EXIT
# The baseline is a shared file: other ticks re-take rows in it, and a re-take is
# an atomic whole-file replace. Leg 3 grades the TOOL by mutating a copy and
# asking it to name the move, so it compares against a snapshot taken here, not
# against $BASE at compare time -- otherwise a lane that re-took a row between
# the copy and the compare reads as this tool writing the wrong row (measured:
# 2026-11-01 11:57Z and 12:14Z, FAIL beside a green tool selftest).
SNAP="$WORK/base.orig.tsv"
cp "$BASE" "$SNAP" 2>/dev/null && [ -s "$SNAP" ] \
|| { echo "CANNOT GRADE: cannot snapshot $BASE"; exit 2; }
faults=0
pass() { echo "PASS $1"; }
fail() { echo "FAIL $1"; faults=$((faults+1)); }
# leg 1
if out="$("$PY" "$TOOL" --selftest 2>&1)"; then
pass "selftest $(printf '%s' "$out" | tail -1 | sed 's/selftest: //')"
else
fail "selftest"; printf '%s\n' "$out" | tail -4
fi
# leg 2 -- two green rows, measured again
if out="$("$PY" "$TOOL" --repo "$ROOT" --path CHECK-q147 --path CHECK-q146 2>&1)"; then
pass "green-rows $(printf '%s' "$out" | tail -1 | sed 's/retake: //')"
else
fail "green-rows rc=$?"; printf '%s\n' "$out" | grep '^MOVED' | head -3
fi
# leg 3 -- the mutation: one row's code moved, named, written, re-read clean.
# The mutation is applied to the snapshot, so what is compared at the end is
# "the tool's rewrite vs the file it was handed".
"$PY" - "$SNAP" "$WORK/base.tsv" <<'PY'
import sys
src, dst = sys.argv[1], sys.argv[2]
lines = open(src, encoding="utf-8").read().split("\n")
out = []
for line in lines:
parts = line.split("\t")
if parts[0] == "CHECK-q147" and len(parts) > 2:
parts[1] = "1"
line = "\t".join(parts)
out.append(line)
open(dst, "w", encoding="utf-8", newline="\n").write("\n".join(out))
PY
out="$("$PY" "$TOOL" --baseline "$WORK/base.tsv" --repo "$ROOT" --path CHECK-q147 2>&1)"; rc=$?
if [ "$rc" -eq 1 ] && printf '%s' "$out" | grep -q '^MOVED CHECK-q147 1 -> 0'; then
wout="$("$PY" "$TOOL" --baseline "$WORK/base.tsv" --repo "$ROOT" --path CHECK-q147 --write 2>&1)"; wrc=$?
if [ "$wrc" -eq 0 ] && "$PY" "$TOOL" --baseline "$WORK/base.tsv" --repo "$ROOT" --path CHECK-q147 >/dev/null 2>&1; then
if "$PY" - "$SNAP" "$WORK/base.tsv" <<'PY'
import sys
def rows(p):
out = {}
for line in open(p, encoding="utf-8"):
if line.startswith("#") or not line.strip():
continue
parts = line.rstrip("\n").split("\t")
out[parts[0]] = (parts[1], parts[2] if len(parts) > 2 else "")
return out
a, b = rows(sys.argv[1]), rows(sys.argv[2])
bad = ["%s %s!=%s" % (k, a[k], b[k]) for k in a if a.get(k) != b.get(k)]
print("data rows: %d compared, %d differ" % (len(a), len(bad)))
sys.exit(1 if bad else 0)
PY
then
pass "mutation named, written, re-read clean, other rows identical"
else
fail "mutation reintroduced a difference in another row"
fi
else
fail "mutation write rc=$wrc or second take still moved"
fi
else
fail "mutation not named (rc=$rc)"; printf '%s\n' "$out" | tail -2
fi
# leg 4 -- the on-disk baseline carries this tick's provenance and still parses
if grep -q '^# row-level re-take (q148 via retake.py' "$BASE" \
&& "$PY" - "$BASE" <<'PY'
import sys
sys.path.insert(0, sys.argv[1].rsplit("/", 1)[0])
import check_sweep
rev, rows = check_sweep.read_baseline(sys.argv[1])
print("baseline parses: %d row(s), rev %s" % (len(rows), rev))
sys.exit(0 if rows and rev else 1)
PY
then
pass "provenance block present, baseline parses"
else
fail "provenance block missing or baseline does not parse"
fi
# leg 5 -- no MISSING row (evidence the baseline names and the tree lacks)
out="$("$PY" "$SWEEP/check_sweep.py" --repo "$ROOT" --paths 2>&1)"
if printf '%s' "$out" | grep -q '^FAIL: MISSING'; then
fail "baseline names a path the tree lacks"
printf '%s\n' "$out" | grep '^FAIL: MISSING' | head -3
else
pass "no MISSING row ($(printf '%s' "$out" | tail -1 | sed 's/paths: //'))"
fi
echo "q148: $((5-faults)) of 5 leg(s) passed"
[ "$faults" -eq 0 ] || exit 1
exit 0