The complement to the per-function compare harness. Instead of "did this function's declared outputs match", it asks "is the entire simulation state still identical" -- so no region-declaration mistake can hide from it. Coverage is PROVED, not declared: the digest tree is re-serialised and compared byte-for-byte against the inflated save on every run. When that reconstruction reproduces the stream, the whole file is a function of the digest's inputs. A run that cannot account for the file says so and exits non-zero. This is the direct answer to B4's three hooks that printed "0 diverged" over an empty region set. It localises. The root is the fold of a per-subsystem / per-object tree with named objects, so the known load->re-save delta reports as exactly five leaves -- /Summary/Checksum and four /Sim/players/Player[...]/Status 4->0 -- naming the two Singularity players by id where the raw byte diff could only say "1st of two". One real End Turn reports as 108 fully attributed differences. Float-parity policy is explicit and strict by default (STATE_CHECKSUM.md 3): raw IEEE-754 bits; a `canonical` policy for signed zero and NaN payloads only; and deliberately NO tolerant hashing mode, because quantisation moves the cliff rather than removing it and destroys the roll-up. Tolerance lives in the differ as --ulps, applied after localisation. Corpus census: 0 NaN, 0 -0.0, 0 subnormals across 4,474 float leaves, so the strict default costs nothing today and a test fails the day that changes. Validated on the real saves (verify/results/state-checksum/): 10 files, 4 distinct contents, all STABLE + COVERED; chain record/verify works on the real turn1-3 saves. The VM-driven replay loop is designed (section 5) but UNRUN. Section 3.5 names the one question the host side cannot settle -- whether the turn pipeline depends on x87 intermediate precision -- and the experiment that would: force fpu_cw to 0x027f / 0x127f / 0x137f across End Turn and checksum the three autosaves. Also recorded: Summary.Checksum is NOT a byte sum over the inflated stream nor a sum over the int leaves (both ruled out), so nobody repeats those two. 38 tests; sots-engine untouched, clean_room_check.sh OK.
114 lines
3.8 KiB
Bash
Executable file
114 lines
3.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Regenerate verify/results/state-checksum/ from the saves on this host.
|
|
#
|
|
# Saves are read from $SOTS_SAVES_DIR when set, plus the in-repo
|
|
# verify/results/saves/. No .sav is copied anywhere. Skips cleanly with a
|
|
# message when there is nothing to read.
|
|
#
|
|
# verify/state-checksum/run_validation.sh
|
|
#
|
|
# Each gate is run separately and its exit status reported; nothing is chained
|
|
# with && so that a failure cannot skip a later step.
|
|
set -u
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VERIFY="$(dirname "$HERE")"
|
|
OUT="$VERIFY/results/state-checksum"
|
|
SC="uv run python3 $HERE/state_checksum.py"
|
|
|
|
mkdir -p "$OUT"
|
|
|
|
REPO_SAVES="$VERIFY/results/saves"
|
|
EXTRA="${SOTS_SAVES_DIR:-}"
|
|
if [ -n "$EXTRA" ] && [ ! -d "$EXTRA" ]; then
|
|
echo "note: \$SOTS_SAVES_DIR=$EXTRA is not a directory; ignoring"
|
|
EXTRA=""
|
|
fi
|
|
if [ -z "$EXTRA" ]; then
|
|
echo "note: \$SOTS_SAVES_DIR unset; using in-repo saves only"
|
|
fi
|
|
|
|
shopt -s nullglob
|
|
ALL=("$REPO_SAVES"/*.sav)
|
|
[ -n "$EXTRA" ] && ALL+=("$EXTRA"/*.sav)
|
|
if [ ${#ALL[@]} -eq 0 ]; then
|
|
echo "no saves available; nothing to validate"
|
|
exit 0
|
|
fi
|
|
|
|
rc=0
|
|
note() { echo "== $1 -> exit $2"; [ "$2" -eq 0 ] || rc=1; }
|
|
|
|
# 1. one root + subsystem digest set per distinct save content
|
|
{
|
|
echo "# state_checksum roots -- $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
echo
|
|
seen=""
|
|
for f in "${ALL[@]}"; do
|
|
h=$(sha256sum "$f" | cut -c1-16)
|
|
case " $seen " in *" $h "*) continue;; esac
|
|
seen="$seen $h"
|
|
echo "--- sha256:$h $(basename "$f")"
|
|
$SC "$f"
|
|
echo
|
|
done
|
|
} > "$OUT/roots.txt" 2>&1
|
|
note "roots" $?
|
|
|
|
# 2. identical bytes must give identical roots, and every save must be covered
|
|
uv run python3 "$HERE/stability_check.py" "${ALL[@]}" > "$OUT/identical-roots.txt" 2>&1
|
|
note "identical-roots" $?
|
|
|
|
# 3. the known load->re-save delta must LOCALISE, not read as a whole-state miss
|
|
A="$REPO_SAVES/turn2-state.sav"
|
|
B=""
|
|
for f in "${ALL[@]}"; do
|
|
[ "$(sha256sum "$f" | cut -c1-8)" = "bb4fd9ac" ] && B="$f" && break
|
|
done
|
|
if [ -n "$B" ] && [ -f "$A" ]; then
|
|
{
|
|
echo "# determinism-oracle.md: loading a post-turn autosave and re-saving it"
|
|
echo "# changes Player.Status (4->0) on the four turn-participating players"
|
|
echo "# plus the derived Summary.Checksum. Nothing else."
|
|
echo
|
|
echo "\$ state_checksum.py turn2-state.sav $(basename "$B")"
|
|
$SC "$A" "$B"
|
|
echo
|
|
echo "\$ state_checksum.py turn2-state.sav $(basename "$B") --mask resave"
|
|
$SC "$A" "$B" --mask resave
|
|
} > "$OUT/resave-localisation.txt" 2>&1
|
|
note "resave-localisation" 0
|
|
else
|
|
echo "== resave-localisation -> SKIPPED (the bb4fd9ac re-save form is not on this host)"
|
|
fi
|
|
|
|
# 4. a real turn transition, fully attributed
|
|
if [ -f "$REPO_SAVES/turn2-state.sav" ] && [ -f "$REPO_SAVES/turn3-state.sav" ]; then
|
|
{
|
|
echo "# one real End Turn (turn 2 -> turn 3), every difference named"
|
|
echo
|
|
$SC "$REPO_SAVES/turn2-state.sav" "$REPO_SAVES/turn3-state.sav" --ulps 2 --limit 500
|
|
} > "$OUT/turn2-to-turn3.txt" 2>&1
|
|
note "turn-transition" 0
|
|
fi
|
|
|
|
# 5. the recorded chain (host side of the replay loop; the VM side is unrun)
|
|
CH=("$REPO_SAVES/turn1-state.sav" "$REPO_SAVES/turn2-state.sav" "$REPO_SAVES/turn3-state.sav")
|
|
have=1
|
|
for f in "${CH[@]}"; do [ -f "$f" ] || have=0; done
|
|
if [ "$have" = 1 ]; then
|
|
$SC "${CH[@]}" --record-chain "$OUT/chain-turn1-3.json" > "$OUT/chain.txt" 2>&1
|
|
note "record-chain" $?
|
|
echo >> "$OUT/chain.txt"
|
|
echo "\$ state_checksum.py --chain chain-turn1-3.json turn1 turn2 turn3" >> "$OUT/chain.txt"
|
|
$SC --chain "$OUT/chain-turn1-3.json" "${CH[@]}" >> "$OUT/chain.txt" 2>&1
|
|
note "verify-chain" $?
|
|
fi
|
|
|
|
# 6. float census -- the evidence behind the float-parity policy
|
|
uv run python3 "$HERE/float_census.py" "${ALL[@]}" > "$OUT/float-census.txt" 2>&1
|
|
note "float-census" $?
|
|
|
|
echo
|
|
echo "wrote $OUT"
|
|
exit $rc
|