"""Read-only integrity verification of four isolated policy gates.""" from pathlib import Path import hashlib import json import zipfile root = Path(__file__).resolve().parent def require(condition, message): if not condition: raise SystemExit(message) def digest(data): return {'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()} def read_json(path): return json.loads(path.read_text(encoding='utf-8')) manifest = read_json(root / 'files.json') paths = {p.relative_to(root).as_posix() for p in root.rglob('*') if p.is_file() and p.name != 'files.json' and '__pycache__' not in p.parts} require(paths == set(manifest), 'Archive membership mismatch') for name, expected in manifest.items(): require(digest((root / name).read_bytes()) == expected, f'File mismatch: {name}') captured = {} outcomes = {} for name, count in [('policy-1', 16), ('policy-clippy-1', None), ('policy-2', 18), ('policy-clippy-2', None)]: gate = root / name result = read_json(gate / 'result.json') require(all(result[k] == v for k, v in read_json(gate / 'started.json').items()), f'{name}: start mismatch') require(result['exitCode'] == 0 and result['inputsUnchanged'], f'{name}: failed/changed inputs') for key, filename in [('inputs','inputs.json'),('archive','inputs.zip'),('stdout','stdout.log'),('stderr','stderr.log')]: require(digest((gate / filename).read_bytes()) == result[key], f'{name}: {key} mismatch') require(digest((root / 'gate-policy.py').read_bytes()) == result['helper'], f'{name}: runner mismatch') inputs = read_json(gate / 'inputs.json') captured[name] = inputs require(len(inputs) == result['inputCount'] == 608, f'{name}: input count') require('harness/prototypes/source-defaults-20260913.rs' in inputs, f'{name}: compiled prototype missing') with zipfile.ZipFile(gate / 'inputs.zip') as archive: require(len(archive.namelist()) == len(inputs) and set(archive.namelist()) == set(inputs), f'{name}: ZIP membership') for path, expected in inputs.items(): require(digest(archive.read(path)) == expected, f'{name}: input mismatch {path}') stdout = (gate / 'stdout.log').read_text(encoding='utf-8') if count is not None: require(f'test result: ok. {count} passed; 0 failed; 0 ignored;' in stdout, f'{name}: test summary') tests = [s for s in stdout.splitlines() if s.startswith('test ') and ' ... ' in s] require(len(tests) == count and all(s.endswith(' ... ok') for s in tests), f'{name}: named outcomes') outcomes[name] = {s.split()[1] for s in tests} else: require(result['command'][1] == 'clippy' and result['command'][-3:] == ['--','-D','warnings'], f'{name}: strict command') artifacts = [] finished = False 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) if isinstance(item, dict) and item.get('reason') == 'build-finished': finished = item.get('success') is True require(finished, f'{name}: successful Cargo build record missing') require(artifacts == [a['cargo'] for a in result['artifacts']], f'{name}: artifacts mismatch') require(len(artifacts) == (1 if count else 0), f'{name}: artifact count') for suffix in ['1','2']: require(captured['policy-'+suffix] == captured['policy-clippy-'+suffix], f'Iteration {suffix}: test/lint inputs differ') before, after = captured['policy-1'], captured['policy-2'] changed = {p for p in before.keys() | after.keys() if before.get(p) != after.get(p)} require(changed == {'crates/oa-core/tests/default_omission_policy.rs'}, 'Prototype/production changed between iterations') require(outcomes['policy-2'] - outcomes['policy-1'] == {'nested_future_fields_prevent_whole_default_removal','unknown_and_multikey_constructor_wrappers_are_not_reinterpreted'}, 'Unexpected added tests') require(outcomes['policy-1'] <= outcomes['policy-2'], 'An original test disappeared') print(f'Verified {len(manifest)} pinned files, four 608-input gates, final 18 passing map tests and strict targeted Clippy.') print('This is recorded experimental policy evidence, not public formatter/editor or source8 acceptance.')