Files
ARCADIA-Studio/harness/experiments/canvas-native-d61f1f3-20260912/tools/canvas-native-paint-session.py
T

69 lines
4.4 KiB
Python

"""Prepare a new disposable canvas trial; retain the real GUI process exit code."""
from pathlib import Path
from datetime import datetime, timezone
import hashlib
import json
import os
import shutil
import subprocess
import sys
root = Path(__file__).resolve().parent.parent
trial = root / '.local/native-qa/canvas-paint-d61f1f3-20260912-01'
mode = sys.argv[1]
if mode == 'prepare':
assert not trial.exists(), 'Never overwrite a native trial'
sources = {
'compact-baseline': root / '.local/native-qa/delete-20260912/compact-baseline-v2',
'compact-work': root / '.local/native-qa/delete-20260912/compact-baseline-v2',
'bound-baseline': root / 'harness/experiments/canvas-editing-followup-20260912/bound-nested-fixture-r1-20260912',
'bound-work': root / 'harness/experiments/canvas-editing-followup-20260912/bound-nested-fixture-r1-20260912',
'draft-work': root / 'harness/experiments/canvas-editing-followup-20260912/nested-call-fixture-20260912',
'process-work': root / 'harness/fixtures/source7-native/base',
}
assert all(path.is_dir() for path in sources.values())
trial.mkdir()
rows = []
for label, source in sources.items():
shutil.copytree(source, trial / label)
for path in sorted(source.rglob('*')):
if path.is_file():
relative = path.relative_to(source)
raw = path.read_bytes()
assert (trial / label / relative).read_bytes() == raw
rows.append({'path': f'{label}/{relative.as_posix()}', 'source': str(path.relative_to(root)), 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()})
for label in ['profile/Desktop', 'profile/Documents', 'profile/AppData/Local', 'profile/AppData/Roaming', 'temp', 'evidence']:
(trial / label).mkdir(parents=True, exist_ok=True)
(trial / 'preparation.json').write_text(json.dumps({'utc': datetime.now(timezone.utc).isoformat(), 'files': rows}, indent=2) + '\n', encoding='utf-8', newline='\n')
print(json.dumps({'trial': str(trial), 'identical_fixture_files': len(rows)}))
elif mode == 'launch':
assert (trial / 'preparation.json').is_file()
assert not (trial / 'launch.json').exists()
stage = Path(sys.argv[2]).resolve()
assert stage.is_relative_to(root / '.local/native-qa')
record = json.loads((stage / 'manifest.json').read_bytes())
for gate in ['full', 'clippy', 'gui']:
result = record['results'][gate]
assert result['exit'] == 0 and not result['changed_inputs']
assert result['source'] == record['source'], 'Require same-source gates for this production correction'
for name in ['arcadia-studio.exe', 'libunwind.dll']:
raw = (stage / name).read_bytes()
assert len(raw) == record['artifacts'][name]['bytes']
assert hashlib.sha256(raw).hexdigest() == record['artifacts'][name]['sha256']
env = {key: os.environ[key] for key in ['SystemRoot', 'WINDIR', 'SystemDrive', 'ProgramData', 'ALLUSERSPROFILE', 'PUBLIC', 'COMSPEC', 'PATHEXT', 'NUMBER_OF_PROCESSORS', 'PROCESSOR_ARCHITECTURE', 'OS'] if key in os.environ}
profile = trial / 'profile'
windows = Path(env['SystemRoot'])
env.update({'PATH': os.pathsep.join(map(str, [stage, windows / 'System32', windows])), 'USERPROFILE': str(profile), 'LOCALAPPDATA': str(profile / 'AppData/Local'), 'APPDATA': str(profile / 'AppData/Roaming'), 'TEMP': str(trial / 'temp'), 'TMP': str(trial / 'temp')})
with (trial / 'stdout.log').open('xb') as out, (trial / 'stderr.log').open('xb') as err:
process = subprocess.Popen([str(stage / 'arcadia-studio.exe')], cwd=trial, env=env, stdin=subprocess.DEVNULL, stdout=out, stderr=err, creationflags=subprocess.CREATE_NO_WINDOW)
launch = {'utc': datetime.now(timezone.utc).isoformat(), 'pid': process.pid, 'source': record['source'], 'binary': str(stage / 'arcadia-studio.exe'), 'sha256': record['artifacts']['arcadia-studio.exe']['sha256'], 'private_profile': str(profile)}
(trial / 'launch.json').write_text(json.dumps(launch, indent=2) + '\n', encoding='utf-8', newline='\n')
print(json.dumps(launch), flush=True)
code = process.wait()
closure = {'utc': datetime.now(timezone.utc).isoformat(), 'pid': process.pid, 'exit': code}
(trial / 'closure.json').write_text(json.dumps(closure, indent=2) + '\n', encoding='utf-8', newline='\n')
print(json.dumps(closure), flush=True)
sys.exit(code)
else:
raise SystemExit('Expected prepare or launch STAGED_DIRECTORY')