"""Archive only the closed, identified canvas native trial; never stage/commit.""" from pathlib import Path from datetime import datetime, timezone import hashlib import json root = Path(__file__).resolve().parent.parent trial = root / '.local/native-qa/canvas-followup-20260912-01' stage = root / '.local/native-qa/studio-83f53c7' prefix = 'harness/experiments/canvas-native-83f53c7-20260912' destination = root / prefix source = '83f53c7c6e277e250f06d2ae6bfa6a7988bd2e4b' result_path = root / '.local/canvas-native-83f53c7-archive-result.json' assert not destination.exists() and not result_path.exists(), 'Never overwrite an archive/run' assert destination.resolve().is_relative_to(root / 'harness/experiments') def digest(path): raw = path.read_bytes() return {'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()} def read(path): return json.loads(path.read_bytes()) def verify(path, record): actual = digest(path) assert actual['sha256'] == record['sha256'], str(path) if 'bytes' in record: assert actual['bytes'] == record['bytes'], str(path) def write_new(path, record): with path.open('x', encoding='utf-8', newline='\n') as stream: stream.write(json.dumps(record, indent=2) + '\n') launch = read(trial / 'launch.json') closure = read(trial / 'closure.json') prepared = read(trial / 'preparation.json') staged = read(stage / 'manifest.json') assert launch['source'] == staged['source'] == staged['full_test_source'] == source assert closure['pid'] == launch['pid'] and closure['exit'] == 0 assert prepared['utc'] < launch['utc'] < closure['utc'] assert Path(launch['binary']).resolve() == (stage / 'arcadia-studio.exe').resolve() assert launch['sha256'] == staged['artifacts']['arcadia-studio.exe']['sha256'] for name in ['arcadia-studio.exe', 'libunwind.dll']: verify(stage / name, staged['artifacts'][name]) for name in ['full', 'clippy', 'gui']: gate = staged['results'][name] assert gate['source'] == source and gate['exit'] == 0 and not gate['changed_inputs'] baseline_names = ['compact-baseline', 'bound-baseline'] baseline_records = [row for row in prepared['files'] if Path(row['path']).parts[0] in baseline_names] for row in baseline_records: verify(trial / row['path'], row) # Original baseline sources are independently retained elsewhere too. verify(root / row['source'], row) assert {row['path'] for row in baseline_records} == { path.relative_to(trial).as_posix() for name in baseline_names for path in (trial / name).rglob('*') if path.is_file()} checkpoint_records = [] checkpoint_files = set() oracle_identities = {} for path in sorted((trial / 'evidence').glob('*.json')): record = read(path) assert set(['snapshot', 'command', 'checker_sha256', 'exit', 'files']) <= record.keys(), str(path) assert record['exit'] == 0 snapshot = Path(record['snapshot']).resolve() assert snapshot == (trial / 'checkpoints' / path.stem).resolve() assert record['utc'] <= closure['utc'] actual = {p.resolve() for p in snapshot.rglob('*') if p.is_file()} declared = {(snapshot / row['path']).resolve() for row in record['files']} assert actual == declared for row in record['files']: item = (snapshot / row['path']).resolve() assert item.is_relative_to(snapshot) verify(item, row) checker = Path(record['command'][0]) verify(checker, {'sha256': record['checker_sha256']}) oracle_identities[str(checker.relative_to(root))] = digest(checker) assert (trial / 'evidence' / (path.stem + '.log')).is_file() checkpoint_files.update(actual) checkpoint_records.append(path.relative_to(trial).as_posix()) assert checkpoint_files == {p.resolve() for p in (trial / 'checkpoints').rglob('*') if p.is_file()} payloads = [] for name in ['preparation.json', 'launch.json', 'closure.json', 'stdout.log', 'stderr.log']: payloads.append((trial / name, Path(name))) for name in ['evidence', 'checkpoints', *baseline_names]: for path in sorted((trial / name).rglob('*')): if path.is_file(): assert path.resolve().is_relative_to(trial) and not path.is_symlink() if name == 'evidence': assert path.suffix.lower() in ['.png', '.json', '.log'], path payloads.append((path, path.relative_to(trial))) for name in ['canvas-native-session.py', 'canvas-native-checkpoint.py', Path(__file__).name]: payloads.append((root / '.local' / name, Path('tools') / name)) payloads.append((stage / 'manifest.json', Path('stage/manifest.json'))) assert len({relative.as_posix() for _, relative in payloads}) == len(payloads) assert not any(relative.parts[0] in ['profile', 'temp', 'compact-work', 'bound-work', 'draft-work', 'process-work'] for _, relative in payloads) before = {str(path): digest(path) for path, _ in payloads} destination.mkdir() rows = [] for path, relative in payloads: target = destination / relative target.parent.mkdir(parents=True, exist_ok=True) raw = path.read_bytes() with target.open('xb') as stream: stream.write(raw) verify(target, before[str(path)]) rows.append({'path': relative.as_posix(), 'source_path': path.relative_to(root).as_posix(), **before[str(path)]}) for path, _ in payloads: verify(path, before[str(path)]) # Only append a scoped rule; never rewrite or normalize existing attributes. attributes = root / '.gitattributes' attribute_before = digest(attributes) rule = prefix + '/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol' current = attributes.read_bytes() added = rule.encode() not in current.splitlines() if added: assert (prefix + '/').encode() not in current, 'Review an existing prefix rule instead of replacing it' with attributes.open('ab') as stream: if current and not current.endswith(b'\n'): stream.write(b'\n') stream.write(rule.encode() + b'\n') manifest = {'archived_utc': datetime.now(timezone.utc).isoformat(), 'source': source, 'native_trial': trial.relative_to(root).as_posix(), 'native_pid': launch['pid'], 'native_exit': closure['exit'], 'payload_count': len(rows), 'payload_bytes': sum(row['bytes'] for row in rows), 'verified_checkpoint_records': checkpoint_records, 'verified_baseline_files': len(baseline_records), 'oracle_binary_identities_not_native_app_source': oracle_identities, 'exclusions': ['profile', 'temp', 'compact-work', 'bound-work', 'draft-work', 'process-work'], 'byte_policy': 'Copied source bytes exactly, including CRLF; originals unmodified. Source paths are provenance, not portable execution paths.', 'attributes': {'rule': rule, 'appended': added, 'before': attribute_before, 'after': digest(attributes)}, 'files': rows} write_new(destination / 'manifest.json', manifest) assert {p.relative_to(destination).as_posix() for p in destination.rglob('*') if p.is_file()} == { row['path'] for row in rows} | {'manifest.json'} result = {'archive': prefix, 'source': source, 'native_exit': closure['exit'], 'payload_count': len(rows), 'archive_file_count_including_manifest': len(rows) + 1, 'screenshots': sum(row['path'].endswith('.png') for row in rows), 'checkpoint_count': len(checkpoint_records), 'payload_bytes': manifest['payload_bytes'], 'all_payload_source_and_destination_hashes_equal': True, 'manifest': digest(destination / 'manifest.json'), 'helper': digest(Path(__file__)), 'attributes_rule_appended': added, 'git_staging_or_commit_performed': False} write_new(result_path, result) print(json.dumps(result, indent=2))