Files
ARCADIA-Studio/harness/experiments/navigation-prerelease-review-20260911/payload/review.py
T

513 lines
37 KiB
Python

"""Independent frozen archive and packaged-server checks; never runs Cargo or GUI."""
from pathlib import Path, PurePosixPath
import hashlib
import json
import os
import re
import socket
import stat
import struct
import subprocess
import sys
import tarfile
import time
import tomllib
import traceback
import urllib.request
import uuid
import zipfile
OUT = Path(__file__).resolve().parent
ROOT = OUT.parents[1]
PREP = ROOT / '.local/nav-repair-retry-20260911'
NAME = 'ArcadiaStudio-0.2.0-preview.navigation.20260911-x86_64-pc-windows-gnullvm'
ZIP = PREP / 'packages' / (NAME + '.zip')
EXTRACT = OUT / 'extracted'
PACKAGE = EXTRACT / NAME
SOURCE = PREP / 'source'
FROZEN = json.loads((OUT / 'frozen-inputs.json').read_text(encoding='utf-8'))
SOURCE_COMMIT = FROZEN['source_commit']
BASE_COMMIT = '33c6d83e9ba9a5b1310b1b627d7c40affcbcf15c'
EXPECTED_ZIP = FROZEN['zip_sha256'].lower()
BINARIES = {
'arcadia-studio.exe': 'b183ef31f16b3986538b3f2aba8435eab45978635c47f99ca01be6e72b168848',
'arcadia-server.exe': 'efeeb89c0d2e0f93df4472cb3e9f48b2b722a37ae1043c90a5a56f2e845fe665',
'libunwind.dll': 'f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4',
}
RESULT = {'checks': [], 'scope': sys.argv[1], 'started_utc': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}
def check(condition, label):
if not condition:
raise AssertionError(label)
RESULT['checks'].append(label)
def sha(data):
return hashlib.sha256(data).hexdigest()
def read_json(path):
return json.loads(path.read_text(encoding='utf-8-sig'))
def write_json(path, value):
with path.open('x', encoding='utf-8', newline='\n') as f:
json.dump(value, f, indent=2, ensure_ascii=False)
f.write('\n')
def file_map(directory):
result = {}
for p in directory.rglob('*'):
check(not p.is_symlink() and not (getattr(p.lstat(), 'st_file_attributes', 0) & 0x400), 'ordinary path: ' + p.relative_to(directory).as_posix())
if p.is_file():
result[p.relative_to(directory).as_posix()] = sha(p.read_bytes())
return result
def safe_name(name):
p = PurePosixPath(name)
return not p.is_absolute() and p.as_posix() == name and '\\' not in name and ':' not in name and all(c not in ('', '.', '..') and not c.endswith(('.', ' ')) and not re.match(r'(?i)^(con|nul|prn|aux|com[1-9]|lpt[1-9])(\.|$)', c) for c in p.parts)
def git_blobs(ref, paths):
raw = subprocess.run(['git', 'cat-file', '--batch'], input=''.join(ref + ':' + p + '\n' for p in paths).encode(), cwd=SOURCE, capture_output=True, check=True).stdout
result, cursor = {}, 0
for p in paths:
end = raw.index(b'\n', cursor)
header = raw[cursor:end].split()
check(len(header) == 3 and header[1] == b'blob', 'Git blob exists: ' + ref[:7] + ':' + p)
size = int(header[2])
result[p] = raw[end + 1:end + 1 + size]
cursor = end + 2 + size
check(cursor == len(raw), 'Git batch framing complete: ' + ref[:7])
return result
def artifact():
for name, h in FROZEN['producer_records'].items():
check(sha((PREP / name).read_bytes()) == h, 'frozen producer record: ' + name)
check(not EXTRACT.exists(), 'clean extraction destination absent')
check(ZIP.stat().st_size == FROZEN['zip_bytes'] and sha(ZIP.read_bytes()) == EXPECTED_ZIP, 'frozen ZIP size and SHA256')
with zipfile.ZipFile(ZIP) as archive:
infos = archive.infolist()
names = [i.filename for i in infos]
check(0 < len(infos) == FROZEN['zip_members'], 'measured ZIP members equal frozen producer inventory')
check(len({n.casefold() for n in names}) == len(names), 'no duplicate or case-colliding ZIP names')
check(all(safe_name(n) and n.startswith(NAME + '/') for n in names), 'one safe ZIP root without traversal or Windows special paths')
check(all(not i.is_dir() and stat.S_IFMT(i.external_attr >> 16) in (0, stat.S_IFREG) for i in infos), 'ordinary file-only ZIP entries')
check(all(i.date_time == (2000, 1, 1, 0, 0, 0) and i.flag_bits & 1 == 0 for i in infos), 'fixed timestamps and no encrypted entries')
check(archive.testzip() is None, 'all ZIP CRCs')
EXTRACT.mkdir()
archive.extractall(EXTRACT)
archive_hashes = {i.filename[len(NAME) + 1:]: sha(archive.read(i)) for i in infos}
actual = file_map(PACKAGE)
producer = read_json(PREP / 'package-readback.json')
check(producer['status'] == 'PASS' and {p: v['sha256'] for p, v in producer['files'].items()} == actual, 'independent extraction equals complete frozen producer readback')
check(actual == archive_hashes, 'complete extracted file set and bytes equal ZIP')
sums = {}
for line in (PACKAGE / 'SHA256SUMS.txt').read_text().splitlines():
match = re.fullmatch(r'([0-9a-f]{64}) (.+)', line)
check(match is not None and safe_name(match[2]) and match[2] not in sums, 'well-formed unique checksum row')
sums[match[2]] = match[1]
check(sums == {p: h for p, h in actual.items() if p != 'SHA256SUMS.txt'}, 'checksum inventory covers every other file exactly')
companion = ZIP.with_suffix('.zip.sha256').read_text(encoding='utf-8').split()
check(companion == [EXPECTED_ZIP, ZIP.name], 'companion checksum binds exact archive')
package = read_json(PACKAGE / 'package.json')
inputs = package['input_sha256']
generated = {'SHA256SUMS.txt', 'START-HERE.txt', 'THIRD-PARTY-NOTICES.txt', 'dependency-notices.json', 'documentation-check.json', 'package.json'}
check(set(actual) - set(inputs) == generated and all(actual[p] == h.lower() for p, h in inputs.items()), 'complete package input hashes plus exactly six generated files')
check(package['version'] == '0.2.0-preview.navigation.20260911' and package['target'] == 'x86_64-pc-windows-gnullvm', 'version and target')
check(all(actual[p] == h for p, h in BINARIES.items()), 'exact GUI, server and runtime hashes')
for p in BINARIES:
data = (PACKAGE / p).read_bytes()
offset = struct.unpack_from('<I', data, 0x3c)[0]
check(data[:2] == b'MZ' and data[offset:offset + 4] == b'PE\0\0' and struct.unpack_from('<H', data, offset + 4)[0] == 0x8664, 'ordinary PE x86_64: ' + p)
check({p for p in actual if '/' not in p} == {'arcadia-server.exe', 'arcadia-studio.exe', 'libunwind.dll', 'LICENSE', 'README.md'} | generated, 'only declared portable top-level files')
check({p.split('/')[0] for p in actual if '/' in p} == {'deployment', 'docs', 'examples', 'licenses'}, 'no harness, private profile, source checkout or credential-directory payload')
for p in actual:
if p.startswith(('docs/', 'examples/', 'deployment/')) or p == 'LICENSE':
check((SOURCE / p).is_file() and sha((SOURCE / p).read_bytes()) == actual[p], 'public source document/example bytes: ' + p)
RESULT['archive'] = {'path': str(ZIP), 'sha256': EXPECTED_ZIP, 'bytes': ZIP.stat().st_size, 'file_count': len(actual), 'files': actual}
RESULT['package_claims'] = {k: package[k] for k in ('version', 'target', 'acceptance', 'build', 'build_evidence')}
check(actual['README.md'] == sha((SOURCE / 'scripts/package-readme.md').read_bytes()), 'packaged README equals its explicit public source input')
provenance()
notices(actual)
check(file_map(PACKAGE) == actual, 'artifact verification leaves extracted package unchanged')
check(sha(ZIP.read_bytes()) == EXPECTED_ZIP, 'artifact verification leaves frozen ZIP unchanged')
def local_source_map(directory):
result = {}
for p in directory.rglob('*'):
rel = p.relative_to(directory)
check(not p.is_symlink() and not (getattr(p.lstat(), 'st_file_attributes', 0) & 0x400), 'ordinary source input: ' + str(p))
if p.is_file() and rel.parts[0] != 'target' and p.name != '.cargo-ok':
result[rel.as_posix()] = sha(p.read_bytes())
return result
def provenance():
gates = ROOT / '.local/text-repair-save-20260911'
input_path = gates / 'inputs1.json'
check(sha(input_path.read_bytes()) == '75a282fd3d4cb2dec6763046ea45d0caa015b998281fbdd6f222d8e3a175b13f', 'original GUI B183 raw input manifest identity')
inputs = read_json(input_path)
expected = {i['path']: i['sha256'] for i in inputs['files']}
sizes = {i['path']: i['bytes'] for i in inputs['files']}
check(len(expected) == len(inputs['files']) == 500 and sum(sizes.values()) == 9482855, 'measured 500 unique original GUI gate inputs and 9482855 bytes')
check(inputs['head'] == 'eeeaa1262748800c4c9aaa1eca79a7de96757358', 'original gate captured head retained separately from accepted source base')
input_zip = gates / 'inputs1.zip'
check(sha(input_zip.read_bytes()) == inputs['archiveSha256'] == '213fdb39ea7c3601b4baac674c3ab3ecc863ac44db1b092d922d3e24f26887b7', 'frozen GUI source ZIP identity')
with zipfile.ZipFile(input_zip) as archive:
names = archive.namelist()
check(len(names) == len(set(names)) == len(expected) and set(names) == set(expected), 'complete captured source ZIP file set')
original = {p: archive.read(p) for p in names}
check(all(sha(original[p]) == h and len(original[p]) == sizes[p] for p, h in expected.items()), 'all 500 original captured input bytes and sizes')
preparation = read_json(PREP / 'preparation.json')
check(preparation['base_commit'] == BASE_COMMIT and preparation['reconstruction_commit'] == SOURCE_COMMIT == '802855f7e6f2f00a107a12196b458b267f586b8d', 'exact release base and independent reconstruction')
check(preparation['gui_inputs'] == expected, 'producer input mapping equals independently pinned gate source mapping')
derived = git_blobs(SOURCE_COMMIT, list(expected))
base = git_blobs(BASE_COMMIT, list(expected))
differences = []
mixed = []
for p, h in expected.items():
current = (SOURCE / p).read_bytes()
check(original[p] == derived[p] == current == (PREP / 'source-roundtrip' / p).read_bytes(), 'captured input equals Git and both reconstructed checkouts: ' + p)
if base[p] != current:
check(base[p].replace(b'\r\n', b'\n') == current.replace(b'\r\n', b'\n'), 'restoration changes only newline bytes: ' + p)
differences.append(p)
crlf = current.count(b'\r\n')
if crlf and current.count(b'\n') > crlf:
mixed.append(p)
wanted = {'docs/api.html', 'docs/api.rst', 'docs/language.html', 'docs/openapi.json', 'harness/fixtures/rest-coverage/coverage-probe.json'} | {
'crates/oa-desktop/src/' + p for p in ('behavior/creation.rs', 'behavior/scenario/workspace.rs', 'behavior/topology/contextual.rs', 'guide.rs', 'semantic_review/artifacts_view.rs', 'semantic_review/attachments_view.rs', 'semantic_review/keyed_rows.rs', 'semantic_review/keyed_tests.rs', 'semantic_review/keyed.rs', 'semantic_review/ordered.rs')}
check(set(differences) == wanted and len(differences) == 15, 'exact fifteen measured newline restorations')
check(set(mixed) == {'crates/oa-desktop/src/behavior/creation.rs', 'crates/oa-desktop/src/guide.rs'}, 'both mixed-newline inputs retained byte-exact')
restored = {i['path']: i for i in preparation['restorations']}
check(len(restored) == len(preparation['restorations']) == 15 and set(restored) == wanted, 'restoration receipt exact path set')
for p, r in restored.items():
check(r['sha256'] == sha(original[p]) and r['base_git_sha256'] == sha(base[p]) and r['bytes'] == len(original[p]) and r['crlf'] == original[p].count(b'\r\n') and r['lf'] == original[p].count(b'\n'), 'independently measured restoration receipt: ' + p)
delta = subprocess.run(['git', 'diff', '--name-only', BASE_COMMIT, SOURCE_COMMIT], cwd=SOURCE, check=True, capture_output=True).stdout.decode().splitlines()
check(set(delta) == wanted | {'.gitattributes'}, 'reconstruction changes only fifteen exact inputs and scoped attributes')
semantic_delta = subprocess.run(['git', 'diff', '--name-only', '--ignore-space-at-eol', BASE_COMMIT, SOURCE_COMMIT], cwd=SOURCE, check=True, capture_output=True).stdout.decode().splitlines()
check(semantic_delta == ['.gitattributes'], 'no non-newline source change in reconstruction')
for p, h in preparation['shared_non_cargo_inputs'].items():
blob = git_blobs(SOURCE_COMMIT, [p])[p]
check(h == sha(blob) == sha((SOURCE / p).read_bytes()) == sha((PREP / 'source-roundtrip' / p).read_bytes()), 'separate shared input exact Git/checkout bytes: ' + p)
roundtrip = read_json(PREP / 'committed-roundtrip.json')
check(roundtrip['checks'] == expected | preparation['shared_non_cargo_inputs'] and roundtrip['clean'] is True, 'complete committed-roundtrip record matches independently checked input union')
check(preparation['root_before'] == preparation['root_after'] and preparation['root_after']['tracked_status'] == '', 'preparation retained root HEAD/index and clean tracked state')
check((SOURCE / '.git/objects').is_dir() and not (SOURCE / '.git/objects/info/alternates').exists(), 'reconstruction has separate Git object store without alternates')
complete = read_json(gates / 'complete.json')
commands = ['desktop-tests', 'desktop-clippy', 'scoped-fmt', 'diff-check', 'gui-build']
check(complete['gates'] == commands and complete['inputsUnchanged'] is True and complete['sourceHead'] == inputs['head'] and complete['archiveSha256'] == inputs['archiveSha256'], 'five terminal gates bind the same captured source')
gate_records = {}
for name in commands:
record = read_json(gates / (name + '-result.json'))
check(record['exitCode'] == 0 and record['inputsUnchanged'] is True, 'successful terminal gate with unchanged input readback: ' + name)
for stream in ('stdout', 'stderr'):
check(sha((gates / (name + '-' + stream + '.log')).read_bytes()) == record[stream + 'Sha256'], 'original gate stream exact hash: ' + name + '/' + stream)
gate_records[name] = record
test_text = (gates / 'desktop-tests-stdout.log').read_text(encoding='utf-8')
summaries = re.findall(r'test result: ok\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;', test_text)
check(summaries == [('755', '0', '1', '0', '0')], 'actual full desktop terminal summary is 755 passed, zero failed, one ignored')
gui = gate_records['gui-build']['binary']
check(gui['sha256'] == BINARIES['arcadia-studio.exe'] and gui['bytes'] == 113206272 and sha((gates / 'gui-repair.exe').read_bytes()) == gui['sha256'], 'original GUI build receipt and preserved binary bind exact shipped B183')
events = [json.loads(line) for line in (gates / 'gui-build-stdout.log').read_text(encoding='utf-8').splitlines() if line.startswith('{')]
artifacts = [e for e in events if e.get('reason') == 'compiler-artifact' and e.get('target', {}).get('name') == 'arcadia-studio' and e.get('executable')]
check(artifacts == [gui['artifact']] and any(e.get('reason') == 'build-finished' and e.get('success') is True for e in events), 'original Cargo stdout contains the exact successful GUI artifact')
check(gui['artifact']['profile']['opt_level'] == '0' and gui['artifact']['profile']['debug_assertions'] is True and gui['artifact']['profile']['test'] is False, 'shipped GUI is a development executable, not a test or release profile')
history = PREP / 'evidence'
historical_pins = {
'server-original-gates.json': 'b7fdfc55ed4c964d276f20f1c57c81c1e924b8da315171089740ab8335ac9f0d',
'server-original-binary-hashes.json': '110a03e323133efb48d50ad065d41414599aa85e0ac420e7d622aa04df4d54f8',
'server-prior-input-comparisons.json': '3c78dea4e93dae186fd24ab826c6680178a2c7849c270a22deae2ff732f1857b',
'prior-dependency-notices.json': '98fab15c1a2bb3aa727c6d52d5c69435b15efa56b6668ed717e7a04cf86f9b52',
'server-source-snapshot.tar.gz': 'cbb371a93a562e1e641d7629fe351e016d63e66fc9112499b3fed6d5cd171f78',
}
for p, h in historical_pins.items():
check(sha((history / p).read_bytes()) == h, 'independent historical server evidence pin: ' + p)
origin_path = ROOT / 'harness/experiments/textual-authoring-20260911-local/provenance.json'
origin = read_json(origin_path)
check(origin['exe_sha256'].lower() == BINARIES['arcadia-server.exe'], 'original independent server record binds unchanged EFEE')
server_expected = {i['path']: i['snapshot_sha256'].lower() for i in origin['source_comparisons']}
check(len(server_expected) == len(origin['source_comparisons']) == 120 and server_expected == preparation['historical_server_inputs'], 'measured 120 unique historical server inputs against their original record')
tar_path = history / 'server-source-snapshot.tar.gz'
tar_manifest = read_json(ROOT / '.local/linux-qa/runtime/source7-20260907T082753190288Z.tar.manifest.json')
with tarfile.open(tar_path) as tar:
regular = [m for m in tar.getmembers() if m.isfile()]
members = {m.name.removeprefix('./'): m for m in regular}
check(len(members) == len(regular), 'historical tar contains no duplicate regular path')
for p, h in server_expected.items():
check(sha(tar.extractfile(members[p]).read()) == h, 'original server tar exact separately recorded source bytes: ' + p)
historical_crate_paths = {p for p in members if p.startswith(('crates/oa-core/', 'crates/oa-server/'))}
check(historical_crate_paths == set(server_expected), 'historical tar complete core/server file set')
shared = [p for p in members if p in ('Cargo.toml', 'Cargo.lock', 'docs/openapi.json') or p.startswith('build/')]
old_shared = {p: tar.extractfile(members[p]).read() for p in shared}
for p, data in old_shared.items():
check(sha(data) == tar_manifest['files'][p].lower(), 'original server shared input matches original tar manifest: ' + p)
if p not in ('Cargo.toml', 'Cargo.lock'):
check(data == (SOURCE / p).read_bytes(), 'unchanged shared server build resource: ' + p)
current_server = {}
for crate in ('oa-core', 'oa-server'):
current_server.update({'crates/' + crate + '/' + p: h for p, h in local_source_map(SOURCE / 'crates' / crate).items()})
changed = sorted(p for p, h in server_expected.items() if current_server.get(p) != h)
added = sorted(set(current_server) - set(server_expected))
check(changed == ['crates/oa-core/src/language.rs'] and added == ['crates/oa-core/src/language_outline_tests.rs'], 'current GUI core differs from historical server only in documented language change/new outline tests')
check(preparation['historical_server_comparison']['changed_current_inputs'] == changed and preparation['historical_server_comparison']['added_current_files'] == added, 'producer states the same independently measured server/source distinction')
old_manifest = tomllib.loads(old_shared['Cargo.toml'].decode())
new_manifest = tomllib.loads((SOURCE / 'Cargo.toml').read_text())
old_members = old_manifest['workspace']['members']
check(new_manifest['workspace']['members'] == old_members + ['crates/oa-cli'], 'only explicit CLI workspace member added since original server build')
new_manifest['workspace']['members'] = old_members
check(new_manifest == old_manifest, 'workspace dependency, resolver and profile semantics remain unchanged')
old_lock = tomllib.loads(old_shared['Cargo.lock'].decode())
new_lock = tomllib.loads((SOURCE / 'Cargo.lock').read_text())
old_packages = {(p['name'], p['version'], p.get('source')): p for p in old_lock.pop('package')}
new_packages = {(p['name'], p['version'], p.get('source')): p for p in new_lock.pop('package')}
cli = new_packages.pop(('oa-cli', '0.2.0', None))
check(cli == {'name': 'oa-cli', 'version': '0.2.0', 'dependencies': ['oa-core', 'serde', 'serde_json']}, 'one explicit local CLI lock entry, no new feature request')
check(old_lock == new_lock and old_packages == new_packages, 'all original lock identities/dependencies/checksums unchanged')
cli_manifest = tomllib.loads((SOURCE / 'crates/oa-cli/Cargo.toml').read_text())
check(cli_manifest['dependencies'] == {'oa-core': {'path': '../oa-core'}, 'serde': {'workspace': True}, 'serde_json': {'workspace': True}}, 'CLI uses existing core/serde requests')
check(not set(cli_manifest).intersection({'features', 'build-dependencies', 'target'}), 'CLI adds no feature/build/target request')
evidence = read_json(PACKAGE / 'package.json')['build_evidence']['evidence']
check(evidence == read_json(PREP / 'build-evidence.json'), 'packaged build evidence equals exact frozen producer evidence semantically')
check(evidence['binary_sha256'] == {k: v for k, v in BINARIES.items() if k.endswith('.exe')}, 'per-binary build evidence binds both exact shipped executables')
check(SOURCE_COMMIT in evidence['source_identity'] and BASE_COMMIT in evidence['source_identity'] and 'not the original build commit' in evidence['source_identity'], 'GUI reconstruction identified without claiming original build commit')
check('No current-source server claim' in evidence['source_identity'] and 'historical development artifact, not rebuilt' in evidence['profile'], 'historical server is explicitly not attributed to the new GUI source')
check('No reproducible build or new server build claimed' in evidence['compiler'] and 'Native/package acceptance remains pending' in evidence['profile'], 'build evidence retains development and native acceptance limitations')
manifest = read_json(PREP / 'evidence-manifest.json')
expected_records = {'evidence/' + p: ROOT / '.local/contextual-prerelease-20260911/evidence' / p for p in historical_pins}
expected_records.update({'evidence/gui-inputs1.json': gates / 'inputs1.json', 'evidence/gui-complete.json': gates / 'complete.json', 'evidence/gui-gate-run.py': gates / 'run.py'})
for name in commands:
for suffix in ('-result.json', '-stdout.log', '-stderr.log'):
expected_records['evidence/gui-' + name + suffix] = gates / (name + suffix)
records = {r['destination']: r for r in manifest}
check(len(records) == len(manifest) == len(expected_records) and set(records) == set(expected_records), 'all 23 independently identified per-binary gate/source records are retained')
for p, source in expected_records.items():
record = records[p]
data = (PREP / p).read_bytes()
check(Path(record['source']).resolve() == source.resolve() and data == source.read_bytes() and sha(data) == record['sha256'] and len(data) == record['bytes'], 'external historical record preserves original exact bytes: ' + p)
per_binary = evidence['per_binary_provenance']
check(set(per_binary) == {'arcadia-studio.exe', 'arcadia-server.exe'}, 'two separate executable provenance records')
check(per_binary['arcadia-studio.exe']['captured_head'] == inputs['head'], 'GUI provenance retains actual precommit captured head')
for binary, references in per_binary.items():
for value in references.values():
if value.startswith('evidence/'):
check(value in expected_records, 'per-binary provenance resolves to verified external record: ' + binary + '/' + value)
check('not files inside the ZIP' in evidence['provenance_reference_base'], 'external provenance references are not advertised as bundled payload')
RESULT['provenance'] = {
'gui_inputs_sha256': sha(input_path.read_bytes()), 'gui_inputs': len(expected), 'gui_input_bytes': sum(sizes.values()),
'captured_build_head': inputs['head'], 'source_commit': SOURCE_COMMIT, 'base_commit': BASE_COMMIT,
'eol_restorations': differences, 'mixed_newline_inputs': mixed, 'gate_counts': [int(n) for n in summaries[0]],
'server_source_files': len(server_expected), 'changed_current_server_inputs': changed, 'added_current_server_inputs': added,
'server_origin_sha256': sha(origin_path.read_bytes()), 'shared_input_files': shared,
'original_lock_packages': len(old_packages), 'additional_local_lock_package': cli,
'original_server_lock_sha256': sha(old_shared['Cargo.lock']), 'current_gui_lock_sha256': sha((SOURCE / 'Cargo.lock').read_bytes()),
'tar_sha256': sha(tar_path.read_bytes()), 'preserved_records': len(records),
'limitations': 'Original build receipts read back; no rebuild, GUI, native acceptance or reproducibility claim by this evaluator.'}
def notices(actual):
notice = read_json(PACKAGE / 'dependency-notices.json')
check(notice['root_packages'] == ['oa-desktop', 'oa-server'], 'exact desktop/server notice roots')
previous_path = PREP / 'evidence/prior-dependency-notices.json'
check(sha(previous_path.read_bytes()) == '98fab15c1a2bb3aa727c6d52d5c69435b15efa56b6668ed717e7a04cf86f9b52', 'previous accepted notice inventory identity')
previous = read_json(previous_path)
key = lambda p: (p['name'], p['version'], p['source'])
old = {key(p): p for p in previous['packages']}
current = {key(p): p for p in notice['packages']}
check(len(current) == len(notice['packages']) and set(current) == set(old), 'measured notice package identities remain the accepted desktop/server graph')
for identity, p in current.items():
if p['source'] is not None:
check(p == old[identity], 'unchanged registry identity/features/source inventory/notices: ' + p['name'])
check(notice['rust'] == previous['rust'] and notice['runtime'] == previous['runtime'], 'unchanged exact Rust/runtime inventory and notice provenance')
check(notice['cargo_lock_sha256'].lower() == sha((SOURCE / 'Cargo.lock').read_bytes()), 'notice lock equals reconstructed current GUI lock, distinct from historical server lock')
shared_names = {'Cargo.toml', 'Cargo.lock', 'LICENSE', 'docs/openapi.json'} | {'build/' + p for p in local_source_map(SOURCE / 'build')}
check(set(notice['workspace_build_inputs_sha256']) == shared_names, 'complete ordinary shared build-input inventory')
for p, h in notice['workspace_build_inputs_sha256'].items():
check(sha((SOURCE / p).read_bytes()) == h, 'notice common build input: ' + p)
lock = tomllib.loads((SOURCE / 'Cargo.lock').read_text())
locked = {(p['name'], p['version'], p.get('source')): p for p in lock['package']}
referenced = set()
def refs(items):
for i in items:
p = i['path']
check(safe_name(p) and p.startswith('licenses/') and actual.get(p) == i['sha256'].lower(), 'bundled exact notice reference: ' + p)
referenced.add(p)
fonts = []
for p in notice['packages']:
key = (p['name'], p['version'], p['source'])
check(key in locked and p['registry_checksum'] == locked[key].get('checksum'), 'notice identity/checksum occurs in verified current lock: ' + p['name'] + '@' + p['version'])
check(len(p['notices']) > 0, 'package has notice text: ' + p['name'])
refs(p['notices'])
for f in p['embedded_fonts']:
check(len(f['notices']) > 0, 'embedded font notice present: ' + p['name'] + '/' + f['path'])
refs(f['notices'])
fonts.append({'package': p['name'], 'path': f['path'], 'sha256': f['sha256'], 'license': f['license']})
if p['source'] is None:
directory = SOURCE / 'crates' / p['name']
files = local_source_map(directory)
check(files == p['local_source_sha256'], 'complete ordinary local-crate inventory: ' + p['name'])
refs(notice['rust']['notices'])
refs(notice['runtime']['notices'])
check(notice['runtime']['sha256'] == BINARIES['libunwind.dll'], 'runtime notice is bound to shipped DLL')
library_dir = ROOT / '.local/toolchain/rustup/toolchains/stable-x86_64-pc-windows-gnullvm/lib/rustlib/x86_64-pc-windows-gnullvm/lib'
check(set(notice['rust']['target_libraries_sha256']) == set(previous['rust']['target_libraries_sha256']), 'measured compiler target-library file set unchanged')
for name, h in notice['rust']['target_libraries_sha256'].items():
check(sha((library_dir / name).read_bytes()) == h, 'retained compiler target-library bytes: ' + name)
RESULT['notices'] = {'packages': len(notice['packages']), 'roots': notice['root_packages'], 'lock_sha256': notice['cargo_lock_sha256'], 'notice_reference_files': len(referenced), 'additional_license_files': sorted({p for p in actual if p.startswith('licenses/')} - referenced), 'embedded_fonts': fonts, 'rust_version': notice['rust']['version'], 'runtime_provenance': notice['runtime']['provenance'], 'scope': notice['scope']}
def server():
prior = read_json(OUT / 'artifact-result.json')
check(prior['status'] == 'PASS' and file_map(PACKAGE) == prior['archive']['files'], 'previously verified extracted package is unchanged')
runtime = OUT / 'server-run'
runtime.mkdir()
data_dir = runtime / 'data'
temp = runtime / 'temp'
temp.mkdir()
windows = Path(os.environ['SystemRoot'])
profile = runtime / 'profile'
for sub in ('Desktop', 'AppData/Roaming', 'AppData/Local'):
(profile / sub).mkdir(parents=True, exist_ok=True)
program_data = runtime / 'ProgramData'
program_data.mkdir()
env = {'SystemDrive': windows.drive, 'SystemRoot': str(windows), 'WINDIR': str(windows),
'PATH': ';'.join(map(str, (PACKAGE, windows / 'System32', windows))),
'TEMP': str(temp), 'TMP': str(temp), 'COMSPEC': str(windows / 'System32/cmd.exe'),
'USERPROFILE': str(profile), 'HOMEDRIVE': profile.drive,
'HOMEPATH': str(profile)[len(profile.drive):], 'APPDATA': str(profile / 'AppData/Roaming'),
'LOCALAPPDATA': str(profile / 'AppData/Local'), 'ProgramData': str(program_data),
'ALLUSERSPROFILE': str(program_data)}
exe = PACKAGE / 'arcadia-server.exe'
RESULT['environment'] = env
RESULT['runtime_package_file_count'] = len(prior['archive']['files'])
RESULT['processes'] = []
for arg in ('--version', '--help'):
output = subprocess.run([str(exe), arg], cwd=PACKAGE, env=env, capture_output=True, timeout=15, creationflags=subprocess.CREATE_NO_WINDOW)
(runtime / (arg[2:] + '.stdout')).write_bytes(output.stdout)
(runtime / (arg[2:] + '.stderr')).write_bytes(output.stderr)
check(output.returncode == 0 and not output.stderr, arg + ' succeeds under clean runtime PATH')
if arg == '--version':
check(output.stdout.decode().strip() == 'arcadia-server 0.2.0', 'server reports underlying application version 0.2.0')
check(not data_dir.exists(), 'help/version do not create explicit test data directory')
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
request_number = 0
def request(port, method, path, payload=None):
nonlocal request_number
request_number += 1
body = None if payload is None else json.dumps(payload, ensure_ascii=False).encode()
req = urllib.request.Request(f'http://127.0.0.1:{port}' + path, data=body, method=method, headers={} if body is None else {'Content-Type': 'application/json'})
with opener.open(req, timeout=10) as response:
raw = response.read()
meta = {'method': method, 'path': path, 'status': response.status, 'headers': dict(response.headers), 'body_sha256': sha(raw)}
prefix = runtime / f'http-{request_number:02d}'
prefix.with_suffix('.body').write_bytes(raw)
write_json(prefix.with_suffix('.json'), meta)
return meta, raw
owned = []
def start(index):
with socket.socket() as s:
s.bind(('127.0.0.1', 0))
port = s.getsockname()[1]
out = (runtime / f'server-{index}.stdout').open('xb')
err = (runtime / f'server-{index}.stderr').open('xb')
args = [str(exe), '--bind', f'127.0.0.1:{port}', '--data-dir', str(data_dir)]
process = subprocess.Popen(args, cwd=PACKAGE, env=env, stdout=out, stderr=err, creationflags=subprocess.CREATE_NO_WINDOW)
owned.append(process)
out.close()
err.close()
RESULT['processes'].append({'pid': process.pid, 'port': port, 'arguments': args})
deadline = time.monotonic() + 15
while True:
if process.poll() is not None:
raise AssertionError('packaged server exited before listening')
try:
with socket.create_connection(('127.0.0.1', port), timeout=.2):
break
except OSError:
if time.monotonic() > deadline:
process.terminate()
process.wait(timeout=5)
raise AssertionError('packaged server did not listen within 15s')
time.sleep(.05)
return process, port
def stop(process):
process.terminate()
code = process.wait(timeout=10)
next(r for r in RESULT['processes'] if r['pid'] == process.pid)['exit_after_explicit_terminate'] = code
process = None
try:
process, port = start(1)
for path in ('/health', '/health/ready'):
meta, raw = request(port, 'GET', path)
check(meta['status'] == 200 and json.loads(raw) == {'status': 'ok'}, path + ' contract')
meta, raw = request(port, 'GET', '/api/v1/openapi.json')
check(meta['status'] == 200 and raw == (PACKAGE / 'docs/openapi.json').read_bytes(), 'served OpenAPI equals complete packaged source bytes')
name = 'Independent navigation package persistence — 救助 20260911'
meta, raw = request(port, 'POST', '/api/v1/projects', {'name': name})
created = json.loads(raw)
check(meta['status'] == 201, 'one create returns 201')
resource = str(uuid.UUID(created['resource_id']))
model_id = str(uuid.UUID(created['model_id']))
expected_summary = {'resource_id': resource, 'revision': 1, 'model_id': model_id, 'schema_version': 7, 'name': name, 'elements': 0, 'relations': 0, 'migration': None}
check(created == expected_summary and resource != model_id, 'complete create summary with distinct fresh resource/model IDs')
etag = f'"p-{resource}-r1"'
headers = {k.lower(): v for k, v in meta['headers'].items()}
path = '/api/v1/projects/' + resource
check(headers.get('etag') == etag and headers.get('location') == path, 'create ETag and resource Location')
meta, raw = request(port, 'GET', path)
stored = json.loads(raw)
model = {'schema_version': 7, 'id': model_id, 'alias': 'mission', 'name': name, 'description': '', 'elements': {}, 'relations': {}, 'diagrams': {}, 'artifact_links': {}, 'traces': {}}
source = f'arcadia 7;\nproject mission {json.dumps(name, ensure_ascii=False)} id "{model_id}" {{\n description "";\n}}\n'
expected = {'resource_id': resource, 'revision': 1, 'model': model, 'source_project': {'entry': 'project.arcadia', 'files': {'project.arcadia': source}}}
check(meta['status'] == 200 and stored == expected, 'GET equals independently predicted complete Project and SourceBundle')
check({k.lower(): v for k, v in meta['headers'].items()}.get('etag') == etag, 'GET ETag equals created revision')
disk = data_dir / (resource + '.json')
disk_bytes = disk.read_bytes()
check(json.loads(disk_bytes) == expected, 'durable disk envelope equals complete expected GET')
check({p.name for p in data_dir.iterdir()} == {'.arcadia.lock', disk.name}, 'private store contains only one project and lock')
stop(process)
process = None
process, port = start(2)
meta, raw = request(port, 'GET', '/health/ready')
check(meta['status'] == 200 and json.loads(raw) == {'status': 'ok'}, 'restarted packaged server ready')
meta, raw = request(port, 'GET', path)
check(meta['status'] == 200 and json.loads(raw) == expected, 'restart retains exact complete Project and SourceBundle')
check({k.lower(): v for k, v in meta['headers'].items()}.get('etag') == etag and disk.read_bytes() == disk_bytes, 'restart retains revision, ETag and every durable envelope byte')
RESULT['persistence'] = {'resource_id': resource, 'model_id': model_id, 'revision': 1, 'etag': etag, 'disk_sha256': sha(disk_bytes), 'expected': expected, 'stop_kind': 'explicit process termination after acknowledged durable create; not a graceful-drain claim'}
finally:
for owned_process in owned:
if owned_process.poll() is None:
stop(owned_process)
check(all(p.poll() is not None for p in owned), 'both owned server processes are terminal')
check(file_map(PACKAGE) == prior['archive']['files'], 'server execution leaves complete extracted package unchanged')
check(sha(ZIP.read_bytes()) == EXPECTED_ZIP, 'frozen ZIP unchanged after independent runtime checks')
if __name__ == '__main__':
result_path = OUT / (sys.argv[1] + '-result.json')
if result_path.exists():
raise SystemExit('Refusing to overwrite prior evidence: ' + str(result_path))
try:
{'artifact': artifact, 'server': server}[sys.argv[1]]()
RESULT['status'] = 'PASS'
except Exception as error:
RESULT['status'] = 'FAIL'
RESULT['error'] = repr(error)
RESULT['traceback'] = traceback.format_exc()
RESULT['finished_utc'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
RESULT['script_sha256'] = sha(Path(__file__).read_bytes())
RESULT['frozen_inputs_sha256'] = sha((OUT / 'frozen-inputs.json').read_bytes())
write_json(result_path, RESULT)
print(json.dumps({k: RESULT[k] for k in ('scope', 'status', 'started_utc', 'finished_utc')}, indent=2))
print('checks:', len(RESULT['checks']))
if RESULT['status'] == 'FAIL':
print(RESULT['traceback'])
sys.exit(1)