"""Read-only rehash of the saved Phase4AR shutdown inventory and registered sources.""" import argparse from datetime import datetime, timezone import hashlib import json from pathlib import Path import subprocess import time INVENTORY = Path('/home/qishizhe/phase4ar-user-shutdown-20260930T203113Z/saved-files.sha256.jsonl') INVENTORY_SHA = 'd7b675b0d0d4647d8fe2fcf9616b9a599e5bc3c15565e604e0d66a046afb835a' REG = Path('/data/digital-drosophila/experiments/phase4ar-normal-conditioning/protocol/preregistered.json') REG_SHA = 'b63e6281b6505ca3b60acb467dd0b3fae274cf513dcbfd653649ba52e9ba9740' def sha(path): h = hashlib.sha256() with Path(path).open('rb') as f: for chunk in iter(lambda: f.read(8 << 20), b''): h.update(chunk) return h.hexdigest() p = argparse.ArgumentParser() p.add_argument('--output', type=Path, required=True) a = p.parse_args() assert not a.output.exists() and a.output.parent.is_dir() start = time.perf_counter() assert sha(INVENTORY) == INVENTORY_SHA and sha(REG) == REG_SHA records = [json.loads(line) for line in INVENTORY.read_text().splitlines()] differences = [] for row in records: path = Path(row['path']) if not path.is_file() or path.stat().st_size != row['bytes'] or sha(path) != row['sha256']: differences.append(str(path)) reg = json.loads(REG.read_text()) source_mismatches = [path for path, expected in reg['source_sha256'].items() if sha(path) != expected] head = subprocess.check_output(['git', '-C', '/data/digital-drosophila', 'rev-parse', 'HEAD'], text=True).strip() status = subprocess.check_output(['git', '-C', '/data/digital-drosophila', 'status', '--porcelain'], text=True) summary = dict(status='PASS' if not differences and not source_mismatches and status == '' else 'FAIL', created_utc=datetime.now(timezone.utc).isoformat(), files_checked=len(records), bytes_checked=sum(r['bytes'] for r in records), inventory_sha256=INVENTORY_SHA, registration_sha256=REG_SHA, registered_science_commit=reg['source_code_commit'], sources_checked=len(reg['source_sha256']), file_mismatches=differences, source_mismatches=source_mismatches, original_git_head=head, original_git_status=status, wall_seconds=time.perf_counter()-start, scope='Saved Phase4AR experiment/control files and registered source files; NOT a new Phase1-4AQ numerical regression', training_epochs_cpu_verified_unchanged=1033, probes_completed_unchanged=138, original_experiment_resumed=False) with a.output.open('x') as f: json.dump(summary, f, indent=2) print(json.dumps(summary), flush=True) raise SystemExit(0 if summary['status'] == 'PASS' else 1)