Files
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

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))