"""Launch a gate-bound development GUI in a fresh private profile; retain child.""" from pathlib import Path from datetime import datetime, timezone import hashlib import json import os import re import shutil import subprocess import sys BASE = Path(__file__).resolve().parent def now(): return datetime.now(timezone.utc).isoformat() def identity(path): raw = path.read_bytes() return {'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()} manifest_path, manifest_hash, label = sys.argv[1:] manifest_path = Path(manifest_path) assert manifest_path.is_absolute() and identity(manifest_path)['sha256'] == manifest_hash manifest = json.loads(manifest_path.read_text(encoding='utf-8')) assert manifest['nativeReady'] is True and re.fullmatch('trial-text-[0-9]+', label) assert manifest['target'] == 'x86_64-pc-windows-gnullvm' for item in [manifest['binary'], *manifest['evidence']]: path = Path(item['path']) assert path.is_absolute() and identity(path) == {key: item[key] for key in ['bytes', 'sha256']} dll = BASE / 'runtime/libunwind.dll' assert identity(dll)['sha256'] == 'f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4' trial = BASE / label trial.mkdir() for name in ['bin', 'profile/roaming', 'profile/local', 'profile/Desktop', 'tmp', 'cwd', 'screenshots']: (trial / name).mkdir(parents=True, exist_ok=True) executable = trial / 'bin/arcadia-studio.exe' shutil.copyfile(manifest['binary']['path'], executable) shutil.copyfile(dll, trial / 'bin/libunwind.dll') assert identity(executable) == {key: manifest['binary'][key] for key in ['bytes', 'sha256']} assert identity(dll) == identity(trial / 'bin/libunwind.dll') shutil.copyfile(manifest_path, trial / 'launch-manifest.json') def record(name, value): with (trial / name).open('x', encoding='utf-8', newline='\n') as output: json.dump(value, output, indent=2) output.write('\n') inherited = {key.upper(): value for key, value in os.environ.items()} env = {key: inherited[key.upper()] for key in ['SystemRoot', 'SystemDrive', 'ProgramData', 'ALLUSERSPROFILE', 'PUBLIC']} system = env['SystemRoot'] env.update({'WINDIR': system, 'PATH': system + '\\System32;' + system, 'USERPROFILE': str(trial / 'profile'), 'APPDATA': str(trial / 'profile/roaming'), 'LOCALAPPDATA': str(trial / 'profile/local'), 'TEMP': str(trial / 'tmp'), 'TMP': str(trial / 'tmp')}) with (trial / 'stdout.log').open('xb') as out, (trial / 'stderr.log').open('xb') as err: start = now() child = subprocess.Popen([str(executable)], cwd=trial / 'cwd', env=env, stdout=out, stderr=err, creationflags=subprocess.CREATE_NO_WINDOW) receipt_error = None try: receipt = {'started': start, 'pid': child.pid, 'executable': str(executable), 'binary': identity(executable), 'environment': env, 'cwd': str(trial / 'cwd'), 'manifestSha256': manifest_hash, 'helper': identity(Path(__file__)), 'scope': 'Development GUI launch, not packaged release acceptance.'} record('launch.json', receipt) print(json.dumps(receipt), flush=True) except Exception as error: receipt_error = repr(error) finally: code = child.wait() finished = now() closure = {'finished': finished, 'pid': child.pid, 'exitCode': code, 'stdout': identity(trial / 'stdout.log'), 'stderr': identity(trial / 'stderr.log'), 'binaryUnchanged': identity(executable) == {key: manifest['binary'][key] for key in ['bytes', 'sha256']}, 'dllUnchanged': identity(dll) == identity(trial / 'bin/libunwind.dll'), 'launchReceiptError': receipt_error} record('closed.json', closure) print(json.dumps(closure), flush=True) sys.exit(0 if code == 0 and receipt_error is None and closure['binaryUnchanged'] and closure['dllUnchanged'] else 1)