179 lines
16 KiB
Python
179 lines
16 KiB
Python
"""Adapt the prior independent reviewer, preserving its artifact/server contracts."""
|
|
from pathlib import Path
|
|
import ast
|
|
import hashlib
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
ROOT = HERE.parent.parent
|
|
original_path = ROOT / '.local/authoring-prerelease-review-20260911/review.py'
|
|
original = original_path.read_bytes()
|
|
assert hashlib.sha256(original).hexdigest() == 'af9eb20946dfcec78bf8959f1d5dc175e82ebb9fabba9f94cefe590fea516b92'
|
|
source = original.decode('utf-8').replace('\r\n', '\n')
|
|
|
|
|
|
def replace(old, new):
|
|
global source
|
|
assert source.count(old) == 1, old[:100]
|
|
source = source.replace(old, new, 1)
|
|
|
|
|
|
replace("PREP = ROOT / '.local/authoring-prerelease-20260911'", "PREP = ROOT / '.local/contextual-prerelease-20260911'")
|
|
replace("NAME = 'ArcadiaStudio-0.2.0-preview.authoring.20260911-x86_64-pc-windows-gnullvm'", "NAME = 'ArcadiaStudio-0.2.0-preview.contextual.20260911-x86_64-pc-windows-gnullvm'")
|
|
replace("SOURCE_COMMIT = '234e01e27d6935d213097b345d91d369f808af82'\nBASE_COMMIT = '2ec72d4241fa8971fa6fe9f626937de9dfd7c7eb'\nEXPECTED_ZIP = '664f30b6217689aca1492eb263b3d15777067d732fa890eeb028f435209dadfa'",
|
|
"FROZEN = json.loads((OUT / 'frozen-inputs.json').read_text(encoding='utf-8'))\nSOURCE_COMMIT = FROZEN['source_commit']\nBASE_COMMIT = 'b2c3e54001fc19a05423bcd5808ceea78d13ff59'\nEXPECTED_ZIP = FROZEN['zip_sha256'].lower()")
|
|
replace("'arcadia-studio.exe': 'd4d9c2bd937e301ff1009d7cb93a34ee5aa6dfc837ff7e87d468c85371b20c31'", "'arcadia-studio.exe': '5657bab5c841939b66f901efe6c0ffb2d7cbbe8cc5f111a0ca3de8073d3846ce'")
|
|
replace("check(ZIP.stat().st_size == 32618262 and sha(ZIP.read_bytes()) == EXPECTED_ZIP, 'frozen ZIP size and SHA256')", "check(ZIP.stat().st_size == FROZEN['zip_bytes'] and sha(ZIP.read_bytes()) == EXPECTED_ZIP, 'frozen ZIP size and SHA256')")
|
|
replace("check(len(infos) == 559, '559 ZIP members')", "check(0 < len(infos) == FROZEN['zip_members'], 'measured ZIP members equal frozen producer inventory')")
|
|
replace("'553 package input hashes plus exactly six generated files'", "'complete package input hashes plus exactly six generated files'")
|
|
replace("package['version'] == '0.2.0-preview.authoring.20260911'", "package['version'] == '0.2.0-preview.contextual.20260911'")
|
|
replace(" provenance()\n notices(actual)", " check(actual['README.md'] == sha((SOURCE / 'scripts/package-readme.md').read_bytes()), 'packaged README equals its explicit public source input')\n provenance()\n notices(actual)\n check(file_map(PACKAGE) == actual, 'artifact verification leaves extracted package unchanged')\n check(sha(ZIP.read_bytes()) == EXPECTED_ZIP, 'artifact verification leaves frozen ZIP unchanged')")
|
|
|
|
start = source.index('def provenance():')
|
|
end = source.index('\ndef notices(actual):', start)
|
|
source = source[:start] + r'''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():
|
|
gui_path = ROOT / '.local/contextual-source-layout-20260911/gui-verified/manifest.json'
|
|
input_path = gui_path.parent / '../inputs4.json'
|
|
check(sha(gui_path.read_bytes()) == '4beb64b955aecf5ae3bfb606316ec1fc9d17d288ed85023515148bb1890f034f', 'original GUI5657 manifest identity')
|
|
check(sha(input_path.read_bytes()) == '669724858967d83ab7da5f78bfafb6065e2bcab3bad0e68d0a74feb86c7195e7', 'original GUI5657 raw input manifest identity')
|
|
gui = read_json(gui_path)
|
|
inputs = read_json(input_path)
|
|
expected = {i['path'].replace('\\', '/'): i['sha256'].lower() for i in inputs['inputs']}
|
|
check(len(expected) == len(inputs['inputs']) == 238, 'measured 238 unique original GUI inputs')
|
|
check({i['file']: i['sha256'].lower() for i in gui['artifacts']} == {k: BINARIES[k] for k in ('arcadia-studio.exe', 'libunwind.dll')}, 'GUI record binds shipped GUI and runtime')
|
|
derived = git_blobs(SOURCE_COMMIT, list(expected))
|
|
base = git_blobs(BASE_COMMIT, list(expected))
|
|
differences = []
|
|
mixed = 'crates/oa-desktop/src/behavior/creation.rs'
|
|
wanted = {'docs/openapi.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')
|
|
}
|
|
for p, h in expected.items():
|
|
current = (SOURCE / p).read_bytes()
|
|
check(sha(derived[p]) == h == sha(current), 'original GUI input equals reconstructed Git blob and checkout: ' + p)
|
|
if sha(base[p]) != h:
|
|
check(base[p].replace(b'\r\n', b'\n') == current.replace(b'\r\n', b'\n'), 'restoration changes only newline bytes: ' + p)
|
|
uniform = base[p].replace(b'\r\n', b'\n').replace(b'\n', b'\r\n')
|
|
if p == mixed:
|
|
crlf = current.count(b'\r\n')
|
|
bare_lf = current.count(b'\n') - crlf
|
|
check(crlf > 0 and bare_lf > 0 and sha(uniform) != h, 'creation.rs retains exact mixed newlines; uniform conversion is insufficient')
|
|
else:
|
|
check(sha(uniform) == h, 'exact uniform CRLF restoration: ' + p)
|
|
differences.append(p)
|
|
check(set(differences) == wanted and len(differences) == 11, 'exact eleven documented newline restorations')
|
|
delta = subprocess.run(['git', 'diff', '--name-only', BASE_COMMIT, SOURCE_COMMIT], cwd=ROOT, check=True, capture_output=True).stdout.decode().splitlines()
|
|
check(set(delta) == wanted | {'.gitattributes'}, 'reconstruction changes only eleven exact inputs and preservation attributes')
|
|
semantic_delta = subprocess.run(['git', 'diff', '--name-only', '--ignore-space-at-eol', BASE_COMMIT, SOURCE_COMMIT], cwd=ROOT, check=True, capture_output=True).stdout.decode().splitlines()
|
|
check(semantic_delta == ['.gitattributes'], 'no non-newline source change in reconstruction')
|
|
|
|
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')
|
|
tar_path = ROOT / '.local/linux-qa/runtime/source7-20260907T082753190288Z.tar.gz'
|
|
check(sha(tar_path.read_bytes()) == 'cbb371a93a562e1e641d7629fe351e016d63e66fc9112499b3fed6d5cd171f78', 'original server source tar identity')
|
|
server_expected = {i['path']: i['snapshot_sha256'].lower() for i in origin['source_comparisons']}
|
|
check(len(server_expected) == len(origin['source_comparisons']) == 120, 'measured 120 unique originally recorded server source files')
|
|
server_base = git_blobs(BASE_COMMIT, list(server_expected))
|
|
tar_manifest = read_json(tar_path.with_suffix('').with_suffix('.tar.manifest.json'))
|
|
with tarfile.open(tar_path) as tar:
|
|
members = {m.name.removeprefix('./'): m for m in tar.getmembers() if m.isfile()}
|
|
for p, h in server_expected.items():
|
|
check(sha(tar.extractfile(members[p]).read()) == h == sha(server_base[p]) == sha((SOURCE / p).read_bytes()), 'original server tar equals base Git and reconstructed input: ' + p)
|
|
for crate in ('oa-core', 'oa-server'):
|
|
prefix = 'crates/' + crate + '/'
|
|
expected_crate = {p[len(prefix):]: h for p, h in server_expected.items() if p.startswith(prefix)}
|
|
check(local_source_map(SOURCE / 'crates' / crate) == expected_crate, 'complete unchanged server input closure: ' + crate)
|
|
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, raw in old_shared.items():
|
|
check(sha(raw) == tar_manifest['files'][p].lower(), 'original server shared input matches original tar manifest: ' + p)
|
|
if p not in ('Cargo.toml', 'Cargo.lock'):
|
|
check(raw == (SOURCE / p).read_bytes(), 'unchanged actual shared server build bytes: ' + p)
|
|
|
|
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 the producer frozen evidence bytes semantically')
|
|
check(evidence['binary_sha256'] == {k: v for k, v in BINARIES.items() if k.endswith('.exe')}, 'build evidence binds both exact shipped executables')
|
|
check(SOURCE_COMMIT in evidence['source_identity'] and BASE_COMMIT in evidence['source_identity'], 'evidence distinguishes reconstruction from release base')
|
|
check('not' in evidence['source_identity'].lower() and 'original build commit' in evidence['source_identity'].lower(), 'reconstruction is not claimed as original build commit')
|
|
check('server' in evidence['profile'].lower() and 'september 7' in evidence['profile'].lower(), 'server retains its separate historical build provenance')
|
|
check('neither a new server build nor release-profile/reproducible-build acceptance is claimed' in evidence['profile'].lower(), 'development/reproducibility limitation retained')
|
|
preserved_originals = {
|
|
'evidence/gui-build-status.json': '.local/contextual-source-layout-20260911/gui1-status.json',
|
|
'evidence/gui-stage-manifest.json': '.local/contextual-source-layout-20260911/gui-verified/manifest.json',
|
|
'evidence/gui-inputs4.json': '.local/contextual-source-layout-20260911/inputs4.json',
|
|
'evidence/gui-full679-result.json': 'harness/experiments/contextual-source-layout-full-20260911/full-result.json',
|
|
'evidence/server-original-gates.json': '.local/source7-post-routing-gates-status.json',
|
|
'evidence/server-original-binary-hashes.json': '.local/native-qa/source7-post-routing-binary-hashes.json',
|
|
'evidence/server-prior-input-comparisons.json': '.local/authoring-prerelease-20260911/inventory.json',
|
|
}
|
|
referred = set()
|
|
for binary, references in evidence['per_binary_provenance'].items():
|
|
check(binary in BINARIES and binary.endswith('.exe'), 'per-binary history names a shipped executable')
|
|
for value in references.values():
|
|
if value.startswith('evidence/'):
|
|
check(value in preserved_originals, 'known independently identified historical evidence path: ' + value)
|
|
check((PREP / value).read_bytes() == (ROOT / preserved_originals[value]).read_bytes(), 'preserved per-binary evidence equals original bytes: ' + value)
|
|
referred.add(value)
|
|
check(referred == set(preserved_originals), 'both original binary histories remain complete and separate')
|
|
check('not files inside the distributable ZIP' in evidence['provenance_reference_base'], 'external provenance paths are not advertised as bundled files')
|
|
RESULT['provenance'] = {
|
|
'gui_manifest_sha256': sha(gui_path.read_bytes()), 'gui_inputs_sha256': sha(input_path.read_bytes()),
|
|
'gui_inputs': len(expected), 'historical_gui_input_record': {k: v for k, v in inputs.items() if k != 'inputs'},
|
|
'source_commit': SOURCE_COMMIT, 'base_commit': BASE_COMMIT, 'eol_restorations': differences,
|
|
'mixed_newline_input': mixed, 'server_source_files': len(server_expected),
|
|
'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())
|
|
}
|
|
|
|
''' + source[end:]
|
|
|
|
replace("check(notice['root_packages'] == ['oa-desktop', 'oa-server'] and len(notice['packages']) == 266, '266 notice packages and exact desktop/server roots')",
|
|
"check(notice['root_packages'] == ['oa-desktop', 'oa-server'], 'exact desktop/server notice roots')\n previous_path = ROOT / '.local/authoring-prerelease-review-20260911/extracted/ArcadiaStudio-0.2.0-preview.authoring.20260911-x86_64-pc-windows-gnullvm/dependency-notices.json'\n check(sha(previous_path.read_bytes()) == '98fab15c1a2bb3aa727c6d52d5c69435b15efa56b6668ed717e7a04cf86f9b52', 'previous accepted notice inventory identity')\n previous = read_json(previous_path)\n key = lambda p: (p['name'], p['version'], p['source'])\n old = {key(p): p for p in previous['packages']}\n current = {key(p): p for p in notice['packages']}\n check(len(current) == len(notice['packages']) and set(current) == set(old), 'measured notice package identities remain the accepted desktop/server graph')\n for identity, p in current.items():\n if p['source'] is not None:\n check(p == old[identity], 'unchanged registry identity/features/source inventory/notices: ' + p['name'])\n check(notice['rust'] == previous['rust'] and notice['runtime'] == previous['runtime'], 'unchanged exact Rust/runtime inventory and notice provenance')")
|
|
replace("'notice lock equals exact historical source lock'", "'notice lock equals reconstructed current GUI lock, distinct from historical server lock'")
|
|
replace("files = {f.relative_to(directory).as_posix(): sha(f.read_bytes()) for f in directory.rglob('*') if f.is_file() and 'target' not in f.relative_to(directory).parts and f.name != '.cargo-ok'}", "files = local_source_map(directory)")
|
|
replace("check(len(notice['rust']['target_libraries_sha256']) == 58, '58 compiler target libraries recorded')", "check(set(notice['rust']['target_libraries_sha256']) == set(previous['rust']['target_libraries_sha256']), 'measured compiler target-library file set unchanged')")
|
|
replace("'Independent package persistence — 救助 20260911'", "'Independent contextual package persistence — 救助 20260911'")
|
|
replace("RESULT['environment'] = env", "RESULT['environment'] = env\n RESULT['runtime_package_file_count'] = len(prior['archive']['files'])")
|
|
replace(" RESULT['script_sha256'] = sha(Path(__file__).read_bytes())", " RESULT['script_sha256'] = sha(Path(__file__).read_bytes())\n RESULT['frozen_inputs_sha256'] = sha((OUT / 'frozen-inputs.json').read_bytes())")
|
|
|
|
ast.parse(source)
|
|
output = HERE / 'review.py'
|
|
assert not output.exists(), 'Refuse to replace prepared reviewer'
|
|
output.write_text(source, encoding='utf-8', newline='\n')
|
|
print('Prepared review.py:', output.stat().st_size, 'bytes SHA256', hashlib.sha256(output.read_bytes()).hexdigest())
|
|
print('Python source syntax parsed; artifact/server execution: none.')
|