Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
76 lines
7.2 KiB
Python
76 lines
7.2 KiB
Python
#!/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()
|