Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
80 lines
6.4 KiB
Python
80 lines
6.4 KiB
Python
from pathlib import Path
|
|
import hashlib,json,shutil,sys,zipfile
|
|
r=Path('/home/jakub/devel/escapistsrereintroduced');f=Path('/home/jakub/devel/escapistsrereintroduced/.build/playtest-source-2026-10-03-depot-mines');sys.path.insert(0,str(f/'tools'))
|
|
from source_bundle import canonical,inventory as source_inventory
|
|
from packed_external import inventory as runtime_inventory
|
|
from pak_inventory import inventory as pak_inventory
|
|
|
|
def digest(p): return hashlib.sha256(p.read_bytes()).hexdigest()
|
|
def write(p,v): p.write_text(json.dumps(v,indent=2)+'\n')
|
|
package=Path('/tmp/erri-package-depot-mines-1305')
|
|
build=r/'.build/playtest-2026-10-03-depot-mines'
|
|
e=r/'docs/evidence/package-2026-10-03-depot-mines'
|
|
route=r/'docs/evidence/native-2026-10-03-depot-mines'
|
|
authored=json.loads((package/'authored-before.json').read_text())
|
|
suite_dir=Path('/tmp/erri-depot-mines-root-1116')
|
|
suite_result=json.loads((suite_dir/'suite-result.json').read_text())
|
|
suite_inputs=json.loads((suite_dir/'suite-inputs.json').read_text())
|
|
assert suite_result['exit']==0 and suite_result['inputs_unchanged']
|
|
assert all(p['exit']==0 for p in suite_result['programs'])
|
|
assert all(suite_inputs.get(n)==h for n,h in authored.items())
|
|
from suite_binding import verify_suite_binding
|
|
suite_binding=verify_suite_binding(f, suite_dir, authored)
|
|
assert authored==source_inventory(f)==json.loads((route/'source-sha256.json').read_text())
|
|
report=json.loads((package/'package-report.json').read_text())
|
|
assert report['project_order']==['core'] and len(report['projects'])==1 and report['source_repository_unchanged']
|
|
attempt=report['projects'][0]
|
|
assert attempt['project']=='core' and attempt['copied_authored_unchanged'] and attempt['profile_addons_unchanged']
|
|
assert attempt['cleanup_confirmed'] and attempt['external_addons_unchanged_after_run'] and report['external_addons_unchanged_after_run']
|
|
assert attempt['native_exit_code']==0
|
|
payload=pak_inventory(package/'packages/core/data.pak')
|
|
actual={x['path']:x['sha256'] for x in payload['entries']}
|
|
assert len(actual)==len(payload['entries'])
|
|
expected={name.removeprefix('addons/core/'):sha for name,sha in authored.items() if not name.endswith('.meta') and not name.endswith('/addon.gproj')}
|
|
assert actual==expected
|
|
assert len(authored)==423 and len(actual)==364
|
|
runtime=runtime_inventory(package/'packages')
|
|
assert len(runtime)==3
|
|
assert runtime['core/addon.gproj']['sha256']==authored['addons/core/addon.gproj']
|
|
zip_path=Path('/tmp/erri-source-depot-mines-1210.zip')
|
|
with zipfile.ZipFile(zip_path) as z:
|
|
manifest=json.loads(z.read('BUNDLE-MANIFEST.json'))
|
|
names=z.namelist()
|
|
assert len(names)==len(set(names))==len({n.casefold() for n in names})
|
|
assert set(names)==set(manifest['files'])|{'BUNDLE-MANIFEST.json'}
|
|
assert {n:h for n,h in manifest['files'].items() if n.startswith('addons/')}==authored
|
|
contents={}
|
|
for n in names:
|
|
canonical(n);contents[n]=z.read(n)
|
|
if n in manifest['files']:assert hashlib.sha256(contents[n]).hexdigest()==manifest['files'][n]
|
|
route_report=json.loads((route/'report.json').read_text())
|
|
assert route_report['smoke_completions']==1 and not route_report['script_or_runtime_failures']
|
|
route_runner=json.loads((route/'runner.json.txt').read_text())
|
|
assert route_runner['cleanup_confirmed'] and route_runner['source_unchanged_after_run']
|
|
assert digest(route/'console.log.txt')==route_runner['console_sha256']
|
|
assert route_report['assertions_passed']==64
|
|
assert 'ERR DEPOT MINE STOCK: original camps=5 inert stored identities=10; no physical courier claim' in (route/'console.log.txt').read_text()
|
|
for p in (build,e):p.mkdir(exist_ok=False)
|
|
shutil.copytree(package/'packages',build/'packages')
|
|
shutil.copyfile(zip_path,build/'source.zip')
|
|
assert digest(zip_path)==digest(build/'source.zip')
|
|
for n,content in contents.items():
|
|
p=build/'source'/n;p.parent.mkdir(parents=True,exist_ok=True);p.write_bytes(content)
|
|
assert {str(p.relative_to(build/'source')) for p in (build/'source').rglob('*') if p.is_file()}==set(contents)
|
|
for n,content in contents.items(): assert (build/'source'/n).read_bytes()==content
|
|
assert runtime_inventory(build/'packages')==runtime
|
|
for p in package.iterdir():
|
|
if p.is_file() and p.suffix=='.json':shutil.copyfile(p,e/p.name)
|
|
shutil.copytree(package/'evidence',e/'native')
|
|
shutil.copyfile('/tmp/erri-gameplay-root-1305/package.log',e/'runner-output.log.txt')
|
|
write(e/'bundle-summary.json',{'archive_sha256':digest(zip_path),'archive_bytes':zip_path.stat().st_size,'payload_files':len(manifest['files']),'projects':manifest['projects']})
|
|
shutil.copyfile(__file__,e/'assemble-handoff.py')
|
|
shutil.copyfile(Path(__file__).with_name('suite_binding.py'),e/'suite_binding.py')
|
|
shutil.copyfile(Path(__file__).with_name('excluded-live-additions.json'),e/'excluded-live-additions.json')
|
|
shutil.copyfile('/tmp/erri-playtest-review-1210/preflight.json',e/'suite-reuse-review.json')
|
|
write(e/'pak-inventory.json',payload)
|
|
review={'kind':'UNQUALIFIED DEVELOPMENT CANDIDATE','authored_files':len(authored),'pak_payload_files':len(actual),'runtime_files':runtime,'source_zip_sha256':digest(zip_path),'source_manifest_sha256':route_runner['launch_source_sha256'],'route_package_source_match':True,'normal_route_reused_without_source_changes':True,'qualification_source_root':str(f),'qualification_source_is_frozen_snapshot':True,'live_source_match_not_claimed':True,'suite_reuse_binding':suite_binding,'normal_route_console_sha256':digest(route/'console.log.txt'),'package_candidate_created':attempt['candidate_created'],'package_result':attempt['result'],'package_stopped_reason':report['stopped_reason'],'original_packaging_failure_retained':not attempt['candidate_created'],'normal_mission_ready':False,'local_participant_verified':False,'strict_packed_consumption_verified':False,'release_qualified':False,'published':False,'source_zip_exact_membership_and_hashes_verified':True,'extracted_source_and_runtime_reverified':True,'evidence':{'route':str(route.relative_to(r)),'package':str(e.relative_to(r)),'startup':'docs/evidence/packed-2026-10-03-depot-mines'}}
|
|
for p in [build/'handoff.json',e/'handoff.json']:write(p,review)
|
|
(build/'README.md').write_text('# Development candidate preparation\n\nMatching source and package hashes are verified in handoff.json. Ordinary packed startup is still pending. This is not a release or Workshop publication.\n')
|
|
print(json.dumps({'build':str(build),'authored_files':len(authored),'pak_payload_files':len(actual),'runtime_files':len(runtime),'source_zip_sha256':review['source_zip_sha256']},indent=2))
|