#!/usr/bin/env python3 """Emit reviewed handoff commands/helpers into this scratch directory; never execute them.""" import argparse,json,shlex,hashlib from pathlib import Path HERE=Path(__file__).resolve().parent ROOT=Path('/home/jakub/devel/escapistsrereintroduced') OLD=Path('/tmp/erri-playtest-menu-fix-1349') def sha(p): return hashlib.sha256(p.read_bytes()).hexdigest() def main(): p=argparse.ArgumentParser(description=__doc__) p.add_argument('--compat',type=Path,required=True,help='Existing idle disposable Tools prefix under /tmp; inspection only is separately emitted') p.add_argument('--external-addons',type=Path,required=True) p.add_argument('--suite-directory',type=Path,default=Path('/tmp/erri-playtest-1631')) a=p.parse_args() compat=a.compat.absolute();external=a.external_addons.resolve() assert str(compat).startswith('/tmp/') and compat.exists(),'Need explicit existing disposable /tmp prefix' assert external.is_dir(),'Installed external-addon directory must exist' cfg={'root':str(ROOT),'frozen_root':str(ROOT/'.build/playtest-source-2026-10-02-gameplay-fixes'), 'build':str(ROOT/'.build/playtest-2026-10-02-gameplay-fixes'), 'package_session':'/tmp/erri-package-20261002-gameplay-fixes-final', 'package_log':'/tmp/erri-package-20261002-gameplay-fixes-final.log', 'source_zip':'/tmp/erri-playtest-source-20261002-gameplay-fixes.zip', 'packed_session':'/tmp/erri-packed-chat-20261002-gameplay-fixes-final', 'packed_log':'/tmp/erri-packed-chat-20261002-gameplay-fixes-final.log', 'package_evidence':str(ROOT/'docs/evidence/package-2026-10-02-gameplay-fixes'), 'normal_evidence':str(ROOT/'docs/evidence/native-2026-10-02-gameplay-fixes-normal'), 'packed_evidence':str(ROOT/'docs/evidence/packed-2026-10-02-gameplay-fixes'), 'suite_directory':str(a.suite_directory.absolute()),'compat':str(compat),'external_addons':str(external), 'qualification':'UNQUALIFIED DEVELOPMENT CANDIDATE; entire frozen snapshot, not necessarily later live source'} (HERE/'config.json').write_text(json.dumps(cfg,indent=2)+'\n') oldf='/home/jakub/devel/escapistsrereintroduced/.build/playtest-memory-menu-fix-native-1349' replacements={oldf:cfg['frozen_root'],'/tmp/erri-playtest-menu-fix-1349/frozen-suite':cfg['suite_directory'], '.build/playtest-memory-menu-fix-native-1349':'.build/playtest-source-2026-10-02-gameplay-fixes','20261002-hq-memory-menu-fix-final':'20261002-gameplay-fixes-final','2026-10-02-hq-memory-menu-fix':'2026-10-02-gameplay-fixes'} for name in ['assemble.py','verify.py']: s=(OLD/name).read_text() for old,new in replacements.items(): s=s.replace(old,new) s=s.replace('/tmp/erri-playtest-source-20261002-gameplay-fixes-final.zip',cfg['source_zip']) s=s.replace("'frozen_snapshot_excludes_later_concurrent_terrain_presentation':True", "'qualification_source_root':str(f),'qualification_source_is_frozen_snapshot':True,'live_source_match_not_claimed':True") if name=='assemble.py': anchor="authored=json.loads((package/'authored-before.json').read_text())" s=s.replace(anchor,anchor+"\nsuite_dir=Path("+repr(cfg['suite_directory'])+")\nsuite_result=json.loads((suite_dir/'suite-result.json').read_text())\nsuite_inputs=json.loads((suite_dir/'suite-inputs.json').read_text())\nassert suite_result['exit']==0 and suite_result['inputs_unchanged']\nassert all(p['exit']==0 for p in suite_result['programs'])\nassert all(suite_inputs.get(n)==h for n,h in authored.items())\nassert all(digest(f/n)==h for n,h in suite_inputs.items())") if name=='verify.py': s=s.replace("assert suite_result['exit']==0 and suite_result['inputs_unchanged']", "assert suite_result['exit']==0 and suite_result['inputs_unchanged']\nassert not suite_result.get('resumed'), 'This handoff helper requires the parent fresh full frozen suite; explicitly adapt evidence binding if split verification is intended'") s=s.replace("repository_check_reused_for_identical_source=True", "repository_check_reused_for_identical_source=True,qualification_source_root=str(f),qualification_source_is_frozen_snapshot=True,live_source_match_not_claimed=True") if name=='verify.py': start=s.index('se.mkdir(exist_ok=False)');end=s.index('assert json.loads((r/',start) writes=s[start:end];s=s[:start]+s[end:] s=s.replace("(pe/'repository-check.log.txt').read_text()", "Path("+repr(cfg['suite_directory']+'/regressions.log')+").read_text()") insert=s.index("for name in ['suite-inputs.json','suite-result.json']:") s=s[:insert]+writes+s[insert:] assert not any(old in s for old in ['1349','hq-memory','409 authored','285 registered']), 'Stale handoff identifier in emitted helper' (HERE/name).write_text(s) f=Path(cfg['frozen_root']); python='python3'; base=['--compat',str(compat),'--external-addons',str(external)] commands=[ ('READ-ONLY: first verify frozen suite and normal evidence; refuses pending or mismatched input', [python,str(HERE/'preflight.py')]), ('READ-ONLY: inspect processes; do not bypass a running game or runner', [python,str(f/'tools/headless_game.py'),'--compat',str(compat),'--inspect-processes']), ('NATIVE: one bounded hidden/muted single-project pack; retain nonzero exit and raw report', [python,str(f/'tools/native_package.py'),'--project','core','--session',cfg['package_session'],*base,'--timeout','300']), ('FILES: new development editable source ZIP from same frozen root', [python,str(f/'tools/source_bundle.py'),'--mode','development','--output',cfg['source_zip']]), ('FILES: exact authored/PAK/ZIP/normal-source checks, then create NEW candidate only', [python,str(HERE/'assemble.py')]), ('READ-ONLY: inspect again before packed startup', [python,str(f/'tools/headless_game.py'),'--compat',str(compat),'--inspect-processes']), ('NATIVE: one ordinary packed startup, hidden/muted, schema4, no smoke/input/flight flags', [python,str(f/'tools/headless_game.py'),'--project','chat','--packed-addons',cfg['build']+'/packages','--packed-session',cfg['packed_session'],*base,'--timeout','180','--failure-grace','120']), ('FILES: recompute raw packed evidence, match all runtime bytes and update NEW candidate only', [python,str(HERE/'verify.py')])] entries=[] for n,v in commands: if str(f/'tools/source_bundle.py') in v and Path(cfg['source_zip']).exists(): entries.append({'purpose':'Existing source ZIP is preserved; preflight/assembly verify its exact bytes. Do not recreate.', 'existing_path':cfg['source_zip']});continue entry={'purpose':n,'argv':v} if str(f/'tools/native_package.py') in v:entry['stdout_stderr_log']=cfg['package_log'] if '--packed-session' in v:entry['stdout_stderr_log']=cfg['packed_log'] entries.append(entry) (HERE/'commands.json').write_text(json.dumps(entries,indent=2)+'\n') (HERE/'commands.txt').write_text('\n\n'.join('# '+e['purpose']+'\n'+(shlex.join(e['argv'])+(' > '+shlex.quote(e['stdout_stderr_log'])+' 2>&1' if 'stdout_stderr_log' in e else '') if 'argv' in e else '# '+e['existing_path']) for e in entries)+'\n') (HERE/'template-provenance.json').write_text(json.dumps({'templates':{str(OLD/n):sha(OLD/n) for n in ['assemble.py','verify.py']},'generated':{n:sha(HERE/n) for n in ['assemble.py','verify.py','commands.json','config.json']},'executed_native':False,'target_writes':False},indent=2)+'\n') print('Emitted scratch commands and helpers only; no launch, build or target write.') if __name__=='__main__':main()