Files
ARCADIA-Studio/harness/experiments/ordinary-text-integration-20260913/verify.py
T

90 lines
5.4 KiB
Python

"""Read-only, Python-standard-library verification. Never executes archived code."""
from pathlib import Path, PurePosixPath
from datetime import datetime
import hashlib
import io
import json
import re
import zipfile
ROOT = Path(__file__).resolve().parent
def require(ok, message):
if not ok:
raise ValueError(message)
def digest(data):
return {'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()}
def members(z, expected):
names = z.namelist()
require(len(names) == len(set(names)), 'duplicate ZIP members')
require(set(names) == set(expected), 'archive membership mismatch')
require(all(not PurePosixPath(n).is_absolute() and '..' not in PurePosixPath(n).parts
and '\\' not in n and ':' not in n for n in names), 'unsafe member')
def main():
inventory = json.loads((ROOT / 'files.json').read_text())
for name, expected in inventory.items():
require(digest((ROOT / name).read_bytes()) == expected, 'external file hash: ' + name)
manifest = json.loads((ROOT / 'manifest.json').read_text())
with zipfile.ZipFile(ROOT / 'evidence.zip') as z:
members(z, manifest['members'])
for name, expected in manifest['members'].items():
require(digest(z.read(name)) == expected, 'member hash: ' + name)
def raw(name): return z.read(name)
def obj(name): return json.loads(raw(name))
checked = set()
for run, spec in manifest['runs'].items():
if spec['kind'] != 'cargo':
continue
prefix = 'runs/' + run + '/'
start, result, process = (obj(prefix + n + '.json') for n in ('started', 'result', 'process'))
require(all(result[k] == v for k, v in start.items()), run + ': start/result relationship')
require(result['command'] == spec['command'] == process['command'], run + ': command')
require(result['head'] == spec['head'], run + ': HEAD')
require(result['exitCode'] == spec['exitCode'] and result['inputsUnchanged'] is True, run + ': outcome')
require(datetime.fromisoformat(result['finish']) >= datetime.fromisoformat(start['start']), run + ': times')
require(result['seconds'] >= 0, run + ': duration')
require(result['helper'] == digest(raw('helpers/gate-union.py')), run + ': helper')
for field, file in [('inputs', spec['inputs']), ('archive', spec['archive']), ('stdout', prefix+'stdout.log'), ('stderr', prefix+'stderr.log')]:
require(result[field] == digest(raw(file)), run + ': receipt ' + field)
inputs = obj(spec['inputs'])
require(len(inputs) == result['inputCount'] == spec['inputCount'], run + ': input count')
require(sum(p.startswith('crates/vendor/iced_widget/') for p in inputs) == 71, run + ': vendor count')
pair = (spec['inputs'], spec['archive'])
if pair not in checked:
with zipfile.ZipFile(io.BytesIO(raw(spec['archive']))) as source:
members(source, inputs)
for name, expected in inputs.items():
require(digest(source.read(name)) == expected, run + ': source hash ' + name)
checked.add(pair)
stdout = raw(prefix+'stdout.log').decode('utf-8', errors='replace')
rows = [[int(x) for x in row] for row in re.findall(r'test result: (?:ok|FAILED)\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;', stdout)]
require(rows == spec['testRows'], run + ': exact test summaries')
require([sum(row[i] for row in rows) for i in range(5)] == spec['testTotals'], run + ': test totals')
artifacts = []
for line in stdout.splitlines():
try: item = json.loads(line)
except json.JSONDecodeError: continue
if isinstance(item, dict) and item.get('reason') == 'compiler-artifact' and item.get('executable'):
artifacts.append(item)
require(artifacts == [a['cargo'] for a in result['artifacts']], run + ': artifact receipt relationship')
print(run, 'exit', result['exitCode'], 'test totals', spec['testTotals'])
composition = obj('helpers/composition.json')
require(composition['patch'] == digest(raw('helpers/ordinary.patch')), 'composition patch')
doc = obj('runs/language-doc-2/result.json')
require(doc['strict'] is True and doc['docutils'] == '0.23', 'render settings')
for field, path in [('source','render/language.rst'), ('html','render/language.html'), ('warnings','runs/language-doc-2/warnings.log')]:
require(doc[field] == digest(raw(path)), 'render receipt ' + field)
require(raw('runs/language-doc-2/warnings.log') == b'', 'successful render warnings')
require(bool(raw('runs/language-doc-1/warnings.log')), 'failed render warning missing')
for path in manifest['generatedFiles']:
require(path.startswith('generated-release1/') and path in manifest['members'], 'generated mapping')
require(len(manifest['generatedFiles']) == manifest['generatedCount'], 'generated count')
print('PASS:', len(manifest['runs']), 'closed captures;', len(manifest['members']), 'members;', len(checked), 'input manifest/archive pairs')
print('Integrity and receipt consistency only; no rerun, signature, binary verification, or GUI claim.')
if __name__ == '__main__':
main()