"""Prepare isolated exact sources/binaries only after recorded GUI/full gates. Do not execute without root's preparation authorization. Never invokes Cargo, launches applications, publishes, or writes the main repository's index/refs. """ from datetime import datetime, timezone import hashlib import json from pathlib import Path, PurePosixPath import re import shutil import subprocess import tarfile import traceback import sys import tomllib import zipfile BASE = Path(__file__).resolve().parent ROOT = BASE.parents[1] SOURCE = BASE / 'source' COMMIT = '33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c' BRANCH = 'codex/navigation-repair-prerelease-source-20260911' VERSION = '0.2.0-preview.navigation.20260911' TARGET = 'x86_64-pc-windows-gnullvm' GATES = ROOT / '.local/text-repair-save-20260911' HISTORY = ROOT / '.local/contextual-prerelease-20260911/evidence' INPUT_SHA = '75a282fd3d4cb2dec6763046ea45d0caa015b998281fbdd6f222d8e3a175b13f' ZIP_SHA = '213fdb39ea7c3601b4baac674c3ab3ecc863ac44db1b092d922d3e24f26887b7' SERVER_SHA = 'efeeb89c0d2e0f93df4472cb3e9f48b2b722a37ae1043c90a5a56f2e845fe665' DLL_SHA = 'f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4' HISTORICAL = { 'server-original-gates.json': 'b7fdfc55ed4c964d276f20f1c57c81c1e924b8da315171089740ab8335ac9f0d', 'server-original-binary-hashes.json': '110a03e323133efb48d50ad065d41414599aa85e0ac420e7d622aa04df4d54f8', 'server-prior-input-comparisons.json': '3c78dea4e93dae186fd24ab826c6680178a2c7849c270a22deae2ff732f1857b', 'prior-dependency-notices.json': '98fab15c1a2bb3aa727c6d52d5c69435b15efa56b6668ed717e7a04cf86f9b52', 'server-source-snapshot.tar.gz': 'cbb371a93a562e1e641d7629fe351e016d63e66fc9112499b3fed6d5cd171f78', } SCRIPT_HASHES = { 'scripts/package-windows.ps1': '28997ff78565619ed9c9b185f66dc922808f1f0be17f522b430c6c415448663d', 'scripts/package-common.ps1': 'd859453a8230b4f305d822c8742b371a71e35df698109a5d55c948f6dfaf0640', 'scripts/windows-notices.ps1': 'a5328c05579e1b9ca09142ee99e87c12994d12764f7c69448e392883d718ef01', } COMMANDS = { 'desktop-tests': ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', '--', '--test-threads=1'], 'desktop-clippy': ['cargo', 'clippy', '--locked', '--offline', '-p', 'oa-desktop', '--all-targets', '--', '-D', 'warnings'], 'scoped-fmt': ['rustfmt', '--check', '--edition', '2024', '--config', 'skip_children=true', 'crates/oa-desktop/src/app.rs', 'crates/oa-desktop/src/document.rs', 'crates/oa-desktop/src/app/repair_save_state_tests.rs'], 'diff-check': ['git', 'diff', '--check'], 'gui-build': ['cargo', 'build', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', '--message-format=json-render-diagnostics'], } def now(): return datetime.now(timezone.utc).isoformat() def ordinary(path): path = Path(path).absolute() for part in (path, *path.parents): if part.exists(): assert not part.is_symlink() and not (getattr(part.lstat(), 'st_file_attributes', 0) & 0x400), str(part) return path def sha(path): with ordinary(path).open('rb') as stream: return hashlib.file_digest(stream, 'sha256').hexdigest() def load(path): return json.loads(ordinary(path).read_text(encoding='utf-8-sig')) def record(path, value): ordinary(path) with Path(path).open('x', encoding='utf-8', newline='\n') as stream: json.dump(value, stream, ensure_ascii=False, indent=2) stream.write('\n') def git(cwd, *args): return subprocess.run(['git', *args], cwd=cwd, check=True, capture_output=True).stdout def relative(name): p = PurePosixPath(name) assert name == p.as_posix() and not p.is_absolute() and p.parts and all(x not in ('..', '.') for x in p.parts) assert '\\' not in name and ':' not in name and '\n' not in name and '\r' not in name return name def blobs(cwd, revision, paths): paths = list(paths) raw = subprocess.run(['git', 'cat-file', '--batch'], cwd=cwd, check=True, capture_output=True, input=''.join(f'{revision}:{p}\n' for p in paths).encode()).stdout cursor, out = 0, {} for path in paths: end = raw.index(b'\n', cursor) header = raw[cursor:end].split() assert len(header) == 3 and header[1] == b'blob', path size = int(header[2]) out[path] = raw[end + 1:end + 1 + size] cursor = end + size + 2 assert cursor == len(raw) return out def root_identity(): index = Path(git(ROOT, 'rev-parse', '--git-path', 'index').decode().strip()) if not index.is_absolute(): index = ROOT / index return {'head': git(ROOT, 'rev-parse', 'HEAD').decode().strip(), 'index_sha256': sha(index), 'tracked_status': git(ROOT, 'status', '--porcelain', '-uno').decode()} def historical_inputs(): for name, checksum in HISTORICAL.items(): assert sha(HISTORY / name) == checksum, name inventory = load(HISTORY / 'server-prior-input-comparisons.json') entries = inventory['server_source_file_comparisons'] expected = {relative(e['path']): e['recorded_sha256'] for e in entries} assert len(expected) == len(entries) and expected found = {} with tarfile.open(HISTORY / 'server-source-snapshot.tar.gz', 'r:gz') as archive: for member in archive.getmembers(): name = member.name.removeprefix('./') if name in expected: assert member.isfile() and name not in found, name with archive.extractfile(member) as stream: found[name] = hashlib.file_digest(stream, 'sha256').hexdigest() assert found == expected assert any(e['Hash'].lower() == SERVER_SHA and Path(e['Path']).name == 'arcadia-server.exe' for e in load(HISTORY / 'server-original-binary-hashes.json')) return expected def admission(): assert sha(GATES / 'inputs1.json') == INPUT_SHA assert sha(GATES / 'inputs1.zip') == ZIP_SHA manifest = load(GATES / 'inputs1.json') assert manifest['archiveSha256'] == ZIP_SHA expected = {relative(e['path']): e for e in manifest['files']} assert len(expected) == len(manifest['files']) and expected assert len({p.casefold() for p in expected}) == len(expected) with zipfile.ZipFile(GATES / 'inputs1.zip') as archive: assert len(archive.namelist()) == len(expected) and set(archive.namelist()) == set(expected) frozen = {name: archive.read(name) for name in expected} for name, raw in frozen.items(): assert len(raw) == expected[name]['bytes'] and hashlib.sha256(raw).hexdigest() == expected[name]['sha256'], name assert len(expected) == 500 complete = load(GATES / 'complete.json') assert complete['archiveSha256'] == ZIP_SHA and complete['inputsUnchanged'] is True assert complete['gates'] == list(COMMANDS) and complete['sourceHead'] == manifest['head'] # The gates captured eeeaa126 plus the repair delta; COMMIT commits those # exact raw inputs. Never relabel the captured sourceHead as a clean build. assert manifest['head'] == 'eeeaa1262748800c4c9aaa1eca79a7de96757358' for name, command in COMMANDS.items(): receipt = load(GATES / (name + '-result.json')) assert receipt['exitCode'] == 0 and receipt['inputsUnchanged'] is True and receipt['command'] == command assert sha(GATES / (name + '-stdout.log')) == receipt['stdoutSha256'] assert sha(GATES / (name + '-stderr.log')) == receipt['stderrSha256'] build = load(GATES / 'gui-build-result.json')['binary'] artifact = build['artifact'] assert artifact['target']['name'] == 'arcadia-studio' and artifact['profile']['test'] is False assert artifact['profile']['opt_level'] == '0' and artifact['profile']['debug_assertions'] is True assert Path(artifact['executable']).resolve() == Path(build['path']).resolve() assert Path(build['path']).resolve().is_relative_to(ROOT / '.local/target-gnullvm') gui = GATES / 'gui-repair.exe' assert sha(gui) == build['sha256'] == 'b183ef31f16b3986538b3f2aba8435eab45978635c47f99ca01be6e72b168848' assert gui.stat().st_size == build['bytes'] == 113206272 summaries = re.findall(r'test result: ok\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;', (GATES / 'desktop-tests-stdout.log').read_text(encoding='utf-8')) assert summaries == [('755', '0', '1', '0', '0')] counts = dict(zip(('passed', 'failed', 'ignored', 'measured', 'filtered'), map(int, summaries[0]))) server = ROOT / '.local/contextual-prerelease-20260911/bin/arcadia-server.exe' dll = ROOT / '.local/contextual-prerelease-20260911/bin/libunwind.dll' assert sha(server) == SERVER_SHA and sha(dll) == DLL_SHA old = historical_inputs() return manifest, frozen, build, gui, counts, server, dll, old def main(): ordinary(BASE) for name in ('source', 'source-roundtrip', 'bin', 'evidence', 'preparation.json', 'committed-roundtrip.json', 'build-evidence.json', 'evidence-manifest.json'): assert not (BASE / name).exists(), f'Refusing existing output: {name}' before = root_identity() assert not before['tracked_status'], 'Root tracked edits must be frozen before preparation.' assert git(ROOT, 'rev-parse', COMMIT).decode().strip() == COMMIT # Later root commits may record evidence only. Do not silently package later # production/docs/dependency or instruction changes under the tested source. git(ROOT, 'merge-base', '--is-ancestor', COMMIT, before['head']) later = git(ROOT, 'diff', '--name-only', '-z', COMMIT, before['head']).decode().split('\0')[:-1] assert all(p.startswith('harness/') and not p.startswith('harness/fixtures/') for p in later), later manifest, frozen, build, gui, counts, server, dll, old = admission() for path, raw in frozen.items(): assert ordinary(ROOT / path).read_bytes() == raw, f'Current frozen input changed: {path}' selectors = ['crates', '.cargo', 'Cargo.toml', 'Cargo.lock', 'docs', 'examples', 'harness/fixtures'] current_paths = git(ROOT, 'ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', *selectors).decode().split('\0')[:-1] assert sorted(current_paths) == sorted(frozen), 'Current input file set differs from the successful freeze.' committed_paths = git(ROOT, 'ls-tree', '-r', '--name-only', '-z', COMMIT, '--', *selectors).decode().split('\0')[:-1] assert sorted(committed_paths) == sorted(frozen), 'Committed input file set differs from the successful gate freeze.' assert shutil.disk_usage(BASE).free >= 2 * 1024 ** 3 original = blobs(ROOT, COMMIT, frozen) for path, raw in frozen.items(): assert original[path].replace(b'\r\n', b'\n') == raw.replace(b'\r\n', b'\n'), f'Non-newline source mismatch: {path}' notice = load(HISTORY / 'prior-dependency-notices.json') shared = {p: h for p, h in notice['workspace_build_inputs_sha256'].items() if p not in ('Cargo.toml', 'Cargo.lock')} for p, raw in blobs(ROOT, COMMIT, shared).items(): assert hashlib.sha256(raw).hexdigest() == shared[p] or raw.replace(b'\r\n', b'\n') == (ROOT / p).read_bytes().replace(b'\r\n', b'\n') assert sha(ROOT / p) == shared[p], p if p in frozen: assert frozen[p] == (ROOT / p).read_bytes(), p frozen[p] = (ROOT / p).read_bytes() registry = {(x['name'], x['version'], x['source']): x['registry_checksum'] for x in notice['packages'] if x['source']} locked = {(x['name'], x['version'], x.get('source')): x.get('checksum') for x in tomllib.loads(frozen['Cargo.lock'].decode())['package']} assert registry and all(locked.get(k) == v for k, v in registry.items()), 'Historical registry coverage differs.' # Local clone has its own index/refs and does not create a worktree in ROOT. git(ROOT, 'clone', '--no-hardlinks', '--no-checkout', str(ROOT), str(SOURCE)) git(SOURCE, 'checkout', '-b', BRANCH, COMMIT) checks = {p: hashlib.sha256(raw).hexdigest() for p, raw in frozen.items()} original = blobs(SOURCE, COMMIT, checks) restores = [] for p, raw in frozen.items(): assert original[p].replace(b'\r\n', b'\n') == raw.replace(b'\r\n', b'\n'), p if hashlib.sha256(original[p]).hexdigest() != checks[p] or sha(SOURCE / p) != checks[p]: assert re.fullmatch(r'[A-Za-z0-9_./-]+', p), 'Attribute path needs explicit quoting review.' ordinary(SOURCE / p).write_bytes(raw) restores.append({'path': p, 'sha256': checks[p], 'base_git_sha256': hashlib.sha256(original[p]).hexdigest(), 'bytes': len(raw), 'crlf': raw.count(b'\r\n'), 'lf': raw.count(b'\n')}) if restores: with (SOURCE / '.gitattributes').open('ab') as out: out.write(b'\n# Exact frozen navigation GUI input bytes; historical server source is separate.\n') for item in restores: out.write((item['path'] + ' -text\n').encode()) git(SOURCE, 'add', '--renormalize', '--', '.gitattributes', *[x['path'] for x in restores]) git(SOURCE, '-c', 'user.name=Codex-9e8r6t', '-c', 'user.email=codex-9e8r6t@local.invalid', 'commit', '-m', 'Preserve exact navigation prerelease GUI inputs') reconstruction = git(SOURCE, 'rev-parse', 'HEAD').decode().strip() committed = blobs(SOURCE, 'HEAD', checks) fresh = BASE / 'source-roundtrip' fresh.mkdir() git(SOURCE, 'checkout-index', '--all', '--prefix=' + fresh.as_posix() + '/') for p, checksum in checks.items(): assert hashlib.sha256(committed[p]).hexdigest() == sha(SOURCE / p) == sha(fresh / p) == checksum, p for p, checksum in SCRIPT_HASHES.items(): assert sha(SOURCE / p) == checksum, p assert not git(SOURCE, 'status', '--porcelain').strip() comparison = {'historical_file_count': len(old), 'changed_current_inputs': [p for p, h in old.items() if sha(SOURCE / p) != h], 'added_current_files': sorted(p.relative_to(SOURCE).as_posix() for crate in ('oa-core', 'oa-server') for p in (SOURCE / 'crates' / crate).rglob('*') if p.is_file() and p.relative_to(SOURCE).as_posix() not in old), 'scope': 'Historical server inputs verified against their own preserved tar, not required to equal the new GUI source.'} assert comparison['changed_current_inputs'] == ['crates/oa-core/src/language.rs'] assert comparison['added_current_files'] == ['crates/oa-core/src/language_outline_tests.rs'] (BASE / 'bin').mkdir() artifacts = [] for source, name, checksum in ((gui, 'arcadia-studio.exe', build['sha256']), (server, 'arcadia-server.exe', SERVER_SHA), (dll, 'libunwind.dll', DLL_SHA)): assert sha(source) == checksum target = BASE / 'bin' / name with source.open('rb') as src, target.open('xb') as dst: shutil.copyfileobj(src, dst) assert sha(source) == sha(target) == checksum artifacts.append({'source': str(source), 'destination': 'bin/' + name, 'sha256': checksum, 'bytes': target.stat().st_size}) provenance = {name: HISTORY / name for name in HISTORICAL} provenance.update({'gui-inputs1.json': GATES / 'inputs1.json', 'gui-complete.json': GATES / 'complete.json', 'gui-gate-run.py': GATES / 'run.py'}) for name in COMMANDS: for suffix in ('-result.json', '-stdout.log', '-stderr.log'): provenance['gui-' + name + suffix] = GATES / (name + suffix) (BASE / 'evidence').mkdir() evidence = [] for name, source in provenance.items(): checksum = sha(source) destination = BASE / 'evidence' / name with source.open('rb') as src, destination.open('xb') as dst: shutil.copyfileobj(src, dst) assert sha(source) == sha(destination) == checksum evidence.append({'source': str(source), 'destination': 'evidence/' + name, 'sha256': checksum, 'bytes': destination.stat().st_size}) record(BASE / 'evidence-manifest.json', evidence) record(BASE / 'committed-roundtrip.json', {'base_commit': COMMIT, 'reconstruction_commit': reconstruction, 'checks': checks, 'clean': True}) record(BASE / 'build-evidence.json', { 'source_identity': f'GUI exact-byte reconstruction {reconstruction} from {COMMIT}; {len(manifest["files"])} frozen GUI gate inputs plus separately verified shared build resources. This is not the original build commit. EFEE server retains its separate September 7 source snapshot; its old language.rs differs from current GUI core. No current-source server claim.', 'profile': f'Prebuilt Windows development GUI, actual full desktop result {counts}. Retained EFEE server is the historical development artifact, not rebuilt. Native/package acceptance remains pending.', 'compiler': 'Original GUI Cargo artifact/profile and server build records retained separately; package collector records current compiler/sysroot facts. No reproducible build or new server build claimed.', 'target': TARGET, 'binary_sha256': {'arcadia-studio.exe': build['sha256'], 'arcadia-server.exe': SERVER_SHA}, 'provenance_reference_base': 'evidence/ references are external preparation records, not files inside the ZIP.', 'per_binary_provenance': { 'arcadia-studio.exe': {'build': 'evidence/gui-gui-build-result.json', 'inputs': 'evidence/gui-inputs1.json', 'full_gate': 'evidence/gui-desktop-tests-result.json', 'complete': 'evidence/gui-complete.json', 'captured_head': manifest['head'], 'scope': 'Built from captured eeeaa126 plus exact repair input delta; those bytes are committed at base_commit, then reconstructed without changing code.'}, 'arcadia-server.exe': {'build': 'evidence/server-original-gates.json', 'hashes': 'evidence/server-original-binary-hashes.json', 'source_tar': 'evidence/server-source-snapshot.tar.gz', 'source_inventory': 'evidence/server-prior-input-comparisons.json', 'notices': 'evidence/prior-dependency-notices.json', 'scope': 'Unchanged historical EFEE; separate source, not rebuilt from navigation source.'}}}) after = root_identity() assert after == before, 'Root HEAD/index/tracked state changed during preparation; inspect before proceeding.' record(BASE / 'preparation.json', {'version': VERSION, 'target': TARGET, 'base_commit': COMMIT, 'reconstruction_commit': reconstruction, 'branch': BRANCH, 'record_only_root_paths_after_base': later, 'historical_registry_count': len(registry), 'source_repository': str(SOURCE), 'restorations': restores, 'gui_inputs': {e['path']: e['sha256'] for e in manifest['files']}, 'shared_non_cargo_inputs': shared, 'historical_server_inputs': old, 'historical_server_comparison': comparison, 'artifacts': artifacts, 'full_test_counts': counts, 'root_before': before, 'root_after': after, 'prepared': now(), 'scope': 'Isolated preparation only; package integrity and native acceptance pending.'}) print(json.dumps({'success': True, 'reconstruction': reconstruction, 'gui_inputs': len(manifest['files']), 'restorations': len(restores), 'historical_server_inputs': len(old)})) if __name__ == '__main__': sys.stdout.reconfigure(encoding='utf-8') sys.stderr.reconfigure(encoding='utf-8') assert not (BASE / 'prepare-result.json').exists() status = {'started': now(), 'scope': 'Preparation only; no application/Cargo/package execution.'} try: main() status['success'] = True except BaseException as error: status.update(success=False, error=repr(error)) traceback.print_exc() raise finally: status['finished'] = now() record(BASE / 'prepare-result.json', status)