"""Archive closed trial 3 / attempt 6; never run GUI, Git, compilers or oracles. Run only after parent acceptance of these helper bytes and normal trial closure. A pre-existing destination is always refused. Failed copies remain for inspection. Historical receipts establish their own scope; this is not a new native evaluator. """ from pathlib import Path, PurePosixPath from datetime import datetime, timezone import hashlib import json import re import shutil import zipfile BASE = Path(__file__).resolve().parent ROOT = Path('C:/ar-text-9e8r6t') TRIAL = BASE / 'trial-text-3' GATE = ROOT / '.local/text-workspace-gates-20260912/attempt-6' DEST = ROOT / 'harness/experiments/text-workspace-native3-20260913' FIXTURES = ROOT / 'harness/experiments/text-workspace-native2-20260913' REVIEWS = BASE.parent / 'text-workspace-design-20260912' GATES = ['escape', 'clippy', 'membership', 'focused', 'selection', 'tests', 'timing', 'gui'] def require(condition, message): if not condition: raise RuntimeError(message) def identity(path): digest = hashlib.sha256() size = 0 with path.open('rb') as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b''): digest.update(chunk) size += len(chunk) return {'bytes': size, 'sha256': digest.hexdigest()} def read(path): return json.loads(path.read_text(encoding='utf-8')) def match(path, expected): measured = identity(path) require(measured['sha256'] == expected['sha256'], f'Hash mismatch: {path}') if 'bytes' in expected: require(measured['bytes'] == expected['bytes'], f'Size mismatch: {path}') return measured def relative(name): path = PurePosixPath(name) require(name and '\\' not in name and not path.is_absolute() and all(part not in ('..', '.', '') and ':' not in part for part in path.parts) and path.as_posix() == name, f'Unsafe relative path: {name!r}') return name def main(): require(not DEST.exists(), f'Fresh destination required; preserve existing attempt: {DEST}') plan = {} names = set() external = [] def add(source, name): name = relative(name) require(name.casefold() not in names, f'Duplicate/case-colliding archive name: {name}') require(source.is_file() and not source.is_symlink(), f'Expected regular file: {source}') names.add(name.casefold()) plan[name] = (source, identity(source)) def pin(path, role): row = {'role': role, 'path': str(path.resolve()), **identity(path)} external.append(row) return row # Closure facts are rechecked against preserved files, not trusted booleans. closed = read(TRIAL / 'closed.json') launch = read(TRIAL / 'launch.json') binding = read(TRIAL / 'launch-manifest.json') require(closed['exitCode'] == 0 and closed['launchReceiptError'] is None, 'Trial must have a recorded normal exit 0 and successful launch receipt') require(closed['binaryUnchanged'] is True and closed['dllUnchanged'] is True, 'Closure reported changed executable or DLL') require(closed['pid'] == launch['pid'], 'Launch/closure process mismatch') match(TRIAL / 'launch-manifest.json', {'sha256': launch['manifestSha256']}) match(BASE / 'attempt-6-launch-manifest.json', {'sha256': launch['manifestSha256']}) require(binding['nativeReady'] is True and binding['target'] == 'x86_64-pc-windows-gnullvm', 'Wrong/unready source gate binding') for stream in ['stdout', 'stderr']: match(TRIAL / (stream + '.log'), closed[stream]) require(Path(launch['executable']).resolve() == (TRIAL / 'bin/arcadia-studio.exe').resolve(), 'Trial executable path mismatch') match(TRIAL / 'bin/arcadia-studio.exe', launch['binary']) match(TRIAL / 'bin/arcadia-studio.exe', binding['binary']) match(BASE / 'launch.py', launch['helper']) match(BASE / 'bind_gates.py', binding['helper']) # Exact archived inputs and all eight successful gate receipts/logs. inputs = read(GATE / 'inputs.json') complete = read(GATE / 'complete.json') require(complete['inputsUnchanged'] is True and complete['gates'] == GATES, 'Attempt 6 must contain all eight completed unchanged-input gates') require(binding['sourceArchiveSha256'] == inputs['archiveSha256'] and binding['baseCommit'] == inputs['baseCommit'] and binding['sourceFiles'] == len(inputs['files']), 'Source binding mismatch') match(GATE / 'inputs.zip', {'sha256': inputs['archiveSha256']}) entries = {relative(row['path']): row for row in inputs['files']} require(len(entries) == len(inputs['files']), 'Duplicate input manifest paths') with zipfile.ZipFile(GATE / 'inputs.zip') as archive: require(len(archive.namelist()) == len(entries) and set(archive.namelist()) == set(entries), 'Input ZIP member inventory mismatch') for name, row in entries.items(): raw = archive.read(name) # Also verifies the stored ZIP CRC. require(len(raw) == row['bytes'] and hashlib.sha256(raw).hexdigest() == row['sha256'], f'Input ZIP member mismatch: {name}') receipts = {} evidence_paths = set() for name in GATES: receipt = read(GATE / (name + '-result.json')) require(receipt['exitCode'] == 0 and receipt['inputsUnchanged'] is True, f'Failed or changed-input gate: {name}') for stream in ['stdout', 'stderr']: match(GATE / (name + '-' + stream + '.log'), {'sha256': receipt[stream + 'Sha256']}) receipts[name] = receipt for row in binding['evidence']: path = Path(row['path']).resolve() require(path.parent == GATE.resolve(), f'Binding evidence outside attempt 6: {path}') require(path.name not in evidence_paths, f'Duplicate binding evidence: {path}') match(path, row) evidence_paths.add(path.name) expected_evidence = {'inputs.json', 'inputs.zip', 'environment.json', 'complete.json'} expected_evidence.update(name + suffix for name in GATES for suffix in ['-result.json', '-stdout.log', '-stderr.log']) require(evidence_paths == expected_evidence, 'Binding does not reference exactly the eight gate receipts/logs') require(binding['membership'] == receipts['membership']['testMembership'], 'Membership binding mismatch') binary = receipts['gui']['binary'] require(Path(binary['preserved']).resolve() == (GATE / 'arcadia-studio.exe').resolve() and Path(binding['binary']['path']).resolve() == (GATE / 'arcadia-studio.exe').resolve(), 'Preserved GUI path mismatch') match(GATE / 'arcadia-studio.exe', binary) match(GATE / 'arcadia-studio.exe', binding['binary']) for path in sorted(GATE.iterdir()): if path.is_file() and path.suffix in {'.json', '.log', '.zip'}: add(path, 'attempt-6/' + path.name) # The authoritative trial-2 archive supplies baseline/expected physical bytes. # Link to it instead of duplicating the four fixture trees in this archive. previous = read(FIXTURES / 'manifest.json') old_files = {relative(row['path']): row for row in previous['files']} require(len(old_files) == len(previous['files']), 'Duplicate prior archive paths') fixture_manifest = read(BASE / 'fixture-manifest.json') match(BASE / 'fixture-manifest.json', old_files['helpers/fixture-manifest.json']) match(FIXTURES / 'helpers/fixture-manifest.json', old_files['helpers/fixture-manifest.json']) for case, row in fixture_manifest['cases'].items(): for variant, key in [('baseline', 'original_files'), ('expected', 'expected_files')]: prefix = 'fixtures/' + case + '/' + variant + '/' archived = {name.removeprefix(prefix): {k: value[k] for k in ['bytes', 'sha256']} for name, value in old_files.items() if name.startswith(prefix)} require(archived == row[key], f'Authoritative archived fixture inventory differs: {case}/{variant}') for name in archived: match(FIXTURES / (prefix + relative(name)), archived[name]) pin(FIXTURES / 'manifest.json', 'authoritative trial-2 archive / fixture inventories') pin(FIXTURES / 'helpers/fixture-manifest.json', 'authoritative fixture manifest') dll_hash = fixture_manifest['dll_sha256'] for path, role in [(TRIAL / 'bin/libunwind.dll', 'trial DLL'), (BASE / 'runtime/libunwind.dll', 'shared runtime DLL')]: match(path, {'sha256': dll_hash}) pin(path, role) pin(TRIAL / 'bin/arcadia-studio.exe', 'closed native executable; intentionally not copied') pin(GATE / 'arcadia-studio.exe', 'gate-preserved executable; intentionally not copied') # Capture every existing verification; require no simple transaction or extra # baseline/expected pair. One representative expected check is sufficient. verifications = [] screenshot_images = set() screenshot_references = set() for path in sorted(TRIAL.iterdir()): if path.is_file(): require(path.suffix in {'.json', '.log', '.md', '.txt'}, f'Unexpected trial root payload: {path}') add(path, 'trial-text-3/' + path.name) elif path.name == 'screenshots': for shot in sorted(path.iterdir()): require(shot.is_file() and shot.suffix in {'.json', '.jpg', '.png'}, f'Unexpected screenshot payload: {shot}') add(shot, 'trial-text-3/screenshots/' + shot.name) if shot.suffix == '.json': for image in read(shot)['screenshots']: image_name = relative(image['file']) require('/' not in image_name, 'Screenshot reference must be a local filename') require((path / image_name).is_file(), f'Missing screenshot reference: {image_name}') screenshot_references.add(image_name) else: screenshot_images.add(shot.name) elif path.name.startswith('verification-'): label = re.fullmatch(r'verification-(simple|representative)-([a-z0-9-]+)', path.name) require(label is not None, f'Unknown verification directory: {path}') case = label.group(1) result = read(path / 'result.json') require(result['passed'] is True and result['exitCode'] == 0 and result['failure'] is None and result['physicalBytesMatch'] is True and result['actualUnchangedByOracle'] is True, f'Verification is not a recorded PASS: {path}') variant = result['expectedVariant'] require(variant in {'baseline', 'expected'}, 'Unknown verification expectation') key = 'original_files' if variant == 'baseline' else 'expected_files' require(result['actualFiles'] == fixture_manifest['cases'][case][key], 'Verification physical inventory differs from its named expectation') require(result['binarySha256'] == launch['binary']['sha256'] and result['oracleSha256'] == fixture_manifest['oracle_sha256'] and result['dllSha256'] == dll_hash, 'Verification binary/oracle/DLL pin mismatch') command = result['command'] require(len(command) == 4 and command[1] == 'same' and Path(command[2]).resolve() == (BASE / case / variant / 'project.arcadia').resolve() and Path(command[3]).resolve() == (BASE / case / 'work/project.arcadia').resolve(), 'Verification command does not name the recorded expectation and work fixture') oracle = Path(command[0]) require(oracle.resolve() == (BASE.parents[1] / '.local/staged-source-oracle-20260911/staged-source-authoring-contract.exe').resolve(), 'Unexpected oracle executable path') match(oracle, {'sha256': result['oracleSha256']}) if not any(row['role'] == 'saved-disk oracle; intentionally not copied' for row in external): pin(oracle, 'saved-disk oracle; intentionally not copied') for stream in ['stdout', 'stderr']: match(path / (stream + '.log'), {'sha256': result[stream + 'Sha256']}) require({p.name for p in path.iterdir()} == {'result.json', 'stdout.log', 'stderr.log'}, 'Unexpected verification payload; review before archiving') for item in sorted(path.iterdir()): add(item, 'trial-text-3/' + path.name + '/' + item.name) verifications.append({'directory': path.name, 'case': case, 'expectedVariant': variant, 'scope': result['scope'], 'resultSha256': identity(path / 'result.json')['sha256']}) else: require(path.name in {'bin', 'profile', 'tmp', 'cwd'}, f'Unclassified trial directory: {path}') require(screenshot_images and screenshot_images == screenshot_references, 'Screenshot payload/reference inventory differs or is empty') require(verifications, 'At least one saved-state verification is required; no transaction sequence is inferred') for name in ['fixture-manifest.json', 'bind_gates.py', 'launch.py', 'verify_saved.py', 'native-recorder.js']: add(BASE / name, 'helpers/' + name) add(GATE.parent / 'gate.py', 'helpers/gate.py') add(Path(__file__).resolve(), 'helpers/archive_trial3.py') for name in ['native2-escape-undo-review.md', 'escape-correction-review.md', 'focus-selection-review.md', 'departure-selection-review.md', 'selection-correction-evidence-review.md', 'integration-review.md']: add(REVIEWS / name, 'reviews/' + name) # A fresh attempt-6 review can be preserved if authored before this helper runs. if (REVIEWS / 'attempt6-evidence-review.md').is_file(): add(REVIEWS / 'attempt6-evidence-review.md', 'reviews/attempt6-evidence-review.md') # Only now create the exclusive destination. No overwrite or cleanup recovery. DEST.mkdir() records = [] for name, (source, expected) in sorted(plan.items()): target = DEST / name target.parent.mkdir(parents=True, exist_ok=True) with source.open('rb') as incoming, target.open('xb') as outgoing: shutil.copyfileobj(incoming, outgoing, 1024 * 1024) match(source, expected) match(target, expected) records.append({'path': name, **expected}) manifest = { 'atUtc': datetime.now(timezone.utc).isoformat(), 'scope': 'Closed development native trial 3 bound to exact attempt-6 inputs and eight successful gates. Saved-disk checks have only their recorded expectations; no unperformed transaction, full UI workflow or packaged-release acceptance is inferred.', 'trial': 'trial-text-3', 'attempt': 'attempt-6', 'closedExitCode': closed['exitCode'], 'sourceArchiveSha256': inputs['archiveSha256'], 'gates': GATES, 'savedVerifications': verifications, 'fixtureArchive': '../text-workspace-native2-20260913/manifest.json', 'externalPins': external, 'helperScope': 'Archived gate.py/verify_saved.py are the current preserved helpers; receipts do not independently bind their historical helper bytes. Launch and bind_gates helper hashes are checked against their receipts.', 'excluded': ['executables', 'DLL payloads', 'profiles', 'temporary directories', 'working fixture copies', 'duplicate authored fixtures', 'build caches'], 'files': records, } with (DEST / 'manifest.json').open('x', encoding='utf-8', newline='\n') as output: json.dump(manifest, output, ensure_ascii=False, indent=2) output.write('\n') print(json.dumps({'directory': str(DEST), 'files': len(records), 'bytes': sum(row['bytes'] for row in records), 'manifestSha256': identity(DEST / 'manifest.json')['sha256']}), flush=True) if __name__ == '__main__': main()