Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
86 lines
8.5 KiB
Python
86 lines
8.5 KiB
Python
from pathlib import Path
|
|
import hashlib,json,shutil,subprocess,sys
|
|
r=Path('/home/jakub/devel/escapistsrereintroduced');b=Path('/tmp/erri-playtest-menu-fix-1349');p=Path('/tmp/erri-playtest-menu-fix-docs-1349');build=r/'.build/playtest-2026-10-02-hq-memory-menu-fix';e=r/'docs/evidence/playtest-refresh-2026-10-02-hq-memory-menu-fix'
|
|
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
|
read=lambda p:json.loads(p.read_text())
|
|
write=lambda p,v:p.write_text(json.dumps(v,indent=2)+'\n')
|
|
sys.path.insert(0,str(r/'tools'));from source_manifest import addon_manifest
|
|
baseline=read(b/'baseline.json');proposal=read(p/'proposal.json');assert proposal['mode']=='verified-final-proposal'
|
|
bindings=read(p/'validation-bindings.json');source=Path(bindings['source_root']);testroot=Path(bindings['suite_root']);live=read(Path(bindings['live_preservation']))
|
|
assert addon_manifest(source)==baseline['source']
|
|
assert addon_manifest(r)==live['source']
|
|
assert all(sha(r/n)==h for n,h in live['working_modified'].items())
|
|
assert hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=r)).hexdigest()==baseline['index_diff_sha256']
|
|
original=read(Path('/tmp/erri-heartbeat-20260930-1542-reference.json'))
|
|
prior=read(r/'docs/evidence/playtest-refresh-2026-10-02-objective-map/candidate-sha256.json')
|
|
assert all(sha(Path('/home/jakub/devel/escapists')/n)==h for n,h in original.items())
|
|
assert {str(x.relative_to(r/'.build/playtest-2026-10-02-objective-map')):sha(x) for x in (r/'.build/playtest-2026-10-02-objective-map').rglob('*') if x.is_file()}==prior
|
|
failedroot=r/'.build/playtest-2026-10-02-hq-memory'
|
|
failedmanifest=read(p/'failed-candidate-sha256.json')
|
|
assert len(failedmanifest)==418 and {str(x.relative_to(failedroot)):sha(x) for x in failedroot.rglob('*') if x.is_file()}==failedmanifest
|
|
oldbaseline=read(Path('/tmp/erri-playtest-1349/baseline.json'))
|
|
fixpaths={'addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c','tests/test_terrain_takeover.py'}
|
|
assert {n for n,h in oldbaseline['source'].items() if baseline['source'][n]!=h}=={'addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c'}
|
|
assert all(h==baseline['working_modified'][n] for n,h in oldbaseline['working_modified'].items() if n not in fixpaths)
|
|
assert len(baseline['working_modified'])==97
|
|
h=read(build/'handoff.json');assert h['authored_files']==409 and h['pak_payload_files']==351 and len(h['runtime_files'])==3
|
|
assert h['normal_mission_ready'] and h['local_participant_verified'] and h['repository_regression_programs']==285 and not h['release_qualified'] and not h['strict_packed_consumption_verified']
|
|
for n,v in proposal['documentation_baselines'].items():assert sha(r/n)==v
|
|
assert len(proposal['proposed_destinations'])==5
|
|
assert h['packed_script_failures']==0 and h['packed_resource_errors']==17
|
|
freshsuite=read(Path(bindings['suite_result']));assert freshsuite['exit']==0 and freshsuite['regression_programs']==285 and freshsuite['inputs_unchanged']
|
|
assert all(sha(testroot/n)==v for n,v in read(Path(bindings['suite_inputs'])).items())
|
|
assert addon_manifest(testroot)==baseline['source']
|
|
route=r/'docs/evidence/native-2026-10-02-hq-memory-menu-fix-normal'
|
|
rr=read(route/'report.json');assert rr['assertions_passed']==63 and rr['smoke_completions']==1 and not rr['script_or_runtime_failures'] and len(rr['engine_errors'])==13
|
|
assert read(route/'source-sha256.json')==baseline['source']
|
|
assert Path('/tmp/erri-playtest-menu-fix-review-1349/review.json').exists(), 'Independent final package review pending'
|
|
live_result=read(b/'suite-result.json');assert live_result['exit']==1 and not live_result['inputs_unchanged'] and live_result['regression_programs']==285 and all(row['exit']==0 for row in live_result['programs'])
|
|
e.mkdir(exist_ok=False)
|
|
concurrent=e/'concurrent-live-suite';concurrent.mkdir()
|
|
for name in ['suite-result.json','suite-inputs.json','regressions.log']:
|
|
shutil.copyfile(b/name,concurrent/name)
|
|
shutil.copyfile(p/'failed-candidate-sha256.json',e/'failed-candidate-sha256.json')
|
|
failed=e/'initial-failed-candidate';failed.mkdir()
|
|
shutil.copyfile('/tmp/erri-playtest-review-1349/review.json',failed/'independent-review.json')
|
|
oldrun=Path('/tmp/erri-packed-chat-20261002-hq-memory-final')
|
|
for name in ['packed-startup-report.json','packed-runner.json','packed-input-provenance.json']:
|
|
shutil.copyfile(oldrun/name,failed/name)
|
|
oldreport=read(oldrun/'packed-startup-report.json');assert len(oldreport['script_or_runtime_failures'])==1 and len(oldreport['engine_errors'])==18
|
|
oldlogs=Path(read(oldrun/'packed-runner.json')['session'])
|
|
for name in ['console.log','script.log','error.log']:
|
|
if (oldlogs/name).exists():shutil.copyfile(oldlogs/name,failed/(name+'.txt'))
|
|
fix=e/'menu-guard-fix';fix.mkdir()
|
|
for name in ['fix.patch','baseline.json','review.json','red.log','green.log']:
|
|
shutil.copyfile(Path('/tmp/erri-takeover-menu-fix-1349')/name,fix/name)
|
|
for name in ['takeover-guard-review.json','takeover-red.log','takeover-green.log']:
|
|
shutil.copyfile(Path('/tmp/erri-playtest-review-1349')/name,fix/('independent-'+name))
|
|
shutil.copyfile(b/'baseline.json',e/'baseline.json')
|
|
shutil.copyfile(Path(bindings['suite_result']),e/'suite-result.json')
|
|
shutil.copyfile(Path(bindings['suite_inputs']),e/'suite-inputs.json')
|
|
shutil.copyfile(Path(bindings['live_preservation']),e/'concurrent-live-preservation.json')
|
|
shutil.copyfile(p/'validation-bindings.json',e/'validation-bindings.json')
|
|
shutil.copyfile('/tmp/erri-package-20261002-hq-memory.log',e/'initial-package-concurrency-refusal.log.txt')
|
|
shutil.copyfile(b/'packed-concurrency-refusal.log',e/'packed-concurrency-refusal.log.txt')
|
|
shutil.copyfile('/tmp/erri-playtest-1349/concurrent-work.json',e/'concurrent-work.json')
|
|
shutil.copyfile('/tmp/erri-playtest-menu-fix-review-1349/review.json',e/'independent-package-review.json')
|
|
shutil.copyfile(p/'prepare.py',e/'prepare-documentation.py');shutil.copyfile(p/'proposal.json',e/'documentation-proposal.json')
|
|
for n,v in proposal['documentation_baselines'].items():
|
|
shutil.copyfile(r/n,e/(Path(n).name+'.before'))
|
|
for n in proposal['proposed_destinations']:
|
|
assert n in ['.build/playtest-2026-10-02-hq-memory-menu-fix/README.md',*proposal['documentation_baselines']]
|
|
shutil.copyfile(p/'proposed'/n,r/n)
|
|
summary={'artifact':str(build.relative_to(r)),'authored_files':409,'pak_payload_files':351,'runtime_files':3,'regression_programs':285,'fresh_suite_and_normal_route_match_packaged_source':True,'source_scope':'Sealed409 snapshot; newer concurrent live terrain-name/presentation work preserved but not packaged','included_changes':['Observer recovery/defeat guidance','Finite supported-launcher resupply','Radio-directed motorized interception from delivered travel history','Concurrent automatic terrain takeover work preserved, with mode-less menu preflight guard'],'native_normal_route':{'assertions':63,'rounds':1,'script_failures':0,'retained_engine_errors':13},'packed_ordinary_startup':{'normal_mission_ready':True,'local_prisoner_verified':True,'script_failures':0,'retained_engine_errors':17,'strict_failure_retained':True},'native_packaging':'Child exit0 and exact authored/payload identity; strict completion/prefix-active failure retained. Unqualified development candidate.','preserved':{'working_modified_paths_before_doc_updates':len(baseline['working_modified']),'captured_concurrent_working_paths':len(live['working_modified']),'original_reference_files':len(original),'previous_candidate_files':len(prior),'retained_failed_diagnostic_candidate_files':len(failedmanifest),'index_unchanged':True},'remaining':'Physical interception/holding/rejoin, physical launcher transfer, human escape, held-map rendering, real multiplayer/JIP/reconnect/twelve players, comparative FPS and clean release.','initial_failed_candidate':{'script_failures':1,'engine_errors':18,'bytes_preserved':True},'committed':False,'published':False,'release_qualified':False}
|
|
write(e/'review.json',summary)
|
|
write(e/'documentation-after.json',{n:sha(r/n) for n in proposal['proposed_destinations']})
|
|
write(e/'candidate-sha256.json',{str(x.relative_to(build)):sha(x) for x in sorted(build.rglob('*')) if x.is_file()})
|
|
shutil.copyfile(__file__,e/'finalize.py')
|
|
for n,v in live['working_modified'].items():
|
|
if n not in proposal['documentation_baselines']:assert sha(r/n)==v,n
|
|
assert {str(x.relative_to(failedroot)):sha(x) for x in failedroot.rglob('*') if x.is_file()}==failedmanifest
|
|
assert addon_manifest(source)==baseline['source']
|
|
assert addon_manifest(r)==live['source']
|
|
assert hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=r)).hexdigest()==baseline['index_diff_sha256']
|
|
subprocess.run(['git','diff','--check'],cwd=r,check=True)
|
|
print(json.dumps(summary,indent=2))
|