40 lines
1.9 KiB
Python
40 lines
1.9 KiB
Python
"""Preserve a whole native trial directory and run its independent oracle."""
|
|
from pathlib import Path
|
|
import hashlib
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
|
|
root = Path(__file__).resolve().parent.parent
|
|
trial = root / '.local/native-qa/canvas-20260911'
|
|
name, source_name, mode = sys.argv[1:4]
|
|
assert name.replace('-', '').isalnum()
|
|
source = (trial / source_name).resolve()
|
|
assert source.is_relative_to(trial) and source.is_dir()
|
|
dest = trial / 'checkpoints' / name
|
|
assert not dest.exists(), 'Never overwrite a verified snapshot'
|
|
shutil.copytree(source, dest)
|
|
files = []
|
|
for p in sorted(source.rglob('*')):
|
|
if p.is_file():
|
|
rel = p.relative_to(source)
|
|
raw = p.read_bytes()
|
|
assert (dest / rel).read_bytes() == raw
|
|
files.append({'path': rel.as_posix(), 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()})
|
|
checker = root / '.local/native-qa/scenario-authoring-contract.exe'
|
|
commands = [[str(checker), 'check', mode, str(dest / 'project.arcadia')]]
|
|
if len(sys.argv) > 4:
|
|
reference = (root / sys.argv[4]).resolve()
|
|
assert reference.is_relative_to(root) and reference.is_file()
|
|
commands.append([str(checker), 'same', str(reference), str(dest / 'project.arcadia')])
|
|
results = []
|
|
for command in commands:
|
|
run = subprocess.run(command, capture_output=True)
|
|
results.append({'argv': command, 'exit_code': run.returncode, 'stdout': run.stdout.decode('utf-8', errors='replace'), 'stderr': run.stderr.decode('utf-8', errors='replace')})
|
|
record = {'utc': datetime.now(timezone.utc).isoformat(), 'name': name, 'source': str(source), 'snapshot': str(dest), 'files': files, 'checker_sha256': hashlib.sha256(checker.read_bytes()).hexdigest(), 'results': results}
|
|
(trial / 'evidence' / (name + '-check.json')).write_text(json.dumps(record, indent=2) + '\n', encoding='utf-8')
|
|
print(json.dumps(record, indent=2))
|
|
sys.exit(0 if all(x['exit_code'] == 0 for x in results) else 1)
|