Preserve raw include diagnostic provenance and derive bands from the existing shaped editor. Retain deferred tooltip paragraphs through rendering. Include source, regression, failure and native-trial evidence; corrected native acceptance remains pending.
90 lines
4.6 KiB
Python
90 lines
4.6 KiB
Python
"""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-diagnostic-[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'
|
|
preserved_executable = Path(manifest['binary']['path'])
|
|
# The preserved artifact is immutable and separate from Cargo's mutable output.
|
|
# Share its bytes through a fresh same-volume name, with no silent copy fallback.
|
|
os.link(preserved_executable, executable)
|
|
same_file_before_launch = os.path.samefile(preserved_executable, executable)
|
|
assert same_file_before_launch
|
|
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'),
|
|
'binaryStorage': 'Hard link to separately preserved immutable artifact',
|
|
'preservedExecutable': str(preserved_executable),
|
|
'sameFileBeforeLaunch': same_file_before_launch,
|
|
'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']},
|
|
'preservedBinaryUnchanged': identity(preserved_executable) == {key: manifest['binary'][key] for key in ['bytes', 'sha256']},
|
|
'sameFileAfterExit': os.path.samefile(preserved_executable, executable),
|
|
'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['preservedBinaryUnchanged'] and closure['sameFileAfterExit'] and closure['dllUnchanged'] else 1)
|