Files

182 lines
16 KiB
Python

# coding: utf-8
"""Compile only r285-r02 integer Array codec bridge against authenticated unchanged r133 SDK archive; no Godot execution."""
from pathlib import Path
import importlib.util, json, os, platform, shutil, subprocess, sys, time, signal, shlex
sys.dont_write_bytecode=True
R=Path(__file__).resolve().parents[2];A=R/'artifacts/original-completion-2026-10-02'
C=A/'p23-02-native-integer-window-codec-candidate-r285-r02';O=A/'p23-02-native-integer-window-codec-build-r286'
BASE=A/'p23-02-native-bridge-build-r76';BASE_SDK=BASE/'sdk';SDK_C=A/'p23-02-native-sdk-lifetime-candidate-r131';SDK=SDK_C/'sdk';HOST=A/'p23-02-native-sdk-lifetime-build-r133'
FLOOR=512*1048576;GROWTH=16*1048576
def mod(name,path):
spec=importlib.util.spec_from_file_location(name,path);m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m);return m
def main():
r=mod('buffer_build_runner',R/'tools/run_all_tests.py');outer=mod('buffer_build_owned',r.SUPPORT/'owned_outer.py')
build_helper_path=A/'p23-02-native-bridge-build-r76.py'
build_helper=mod('retained_build_ownership',build_helper_path)
def pin(p):return dict(path=str(p),bytes=p.stat().st_size,sha256=r.sha(p))
D=R/'docs/plans/original-completion-2026-10-02';names=['IMPLEMENTATION_PLAN.md','PROGRESS_INTEGRATION.md','work_packages.json','progress_snapshot.json']
preexecution_review=A/'p23-02-native-integer-window-codec-build-preexecution-independent-review-r286.json'
preexecution=r.read(preexecution_review)
assert preexecution['execution_allowed'] and not preexecution['blockers']
for group in ['evidence_sha256','canonical_doc4_context_pins']:
values=preexecution[group]
for q in values.values() if isinstance(values,dict) else values:
p=Path(q['path']);assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256']
pre_root=r.read(A/'p23-02-native-integer-window-codec-build-preexecution-root-verification-r286.json');assert pre_root['passed'] and pre_root['review_sha256']==r.sha(preexecution_review)
source=r.source_refs(R);player=r.default_player(R);docs={n:r.sha(D/n) for n in names}
assert {n:v['sha256'] for n,v in source.items()}==r.read(A/'p23-02-final-candidate-r32-source-adoption-r03/source-after.json')
assert platform.machine()=='arm64' and not O.exists() and not outer.native.helper['live_engines']()
assert shutil.disk_usage(A).free>=FLOOR+GROWTH
review=A/'p23-02-native-bridge-build-validation-independent-review-r77.json'
assert r.sha(review)=='75d3bbff767fb88af266c4b1b9da37d96294ab72b9e07fcac9a3e7e567a29d49'
auth=r.read(review)['evidence_sha256']
base_input=BASE/'input.json';archive=BASE_SDK/'bin/libgodot-cpp.macos.template_debug.arm64.a'
accepted_receipt=A/'p23-02-native-bridge-build-validation-r77/execution.json'
for p in [base_input,archive,accepted_receipt]:
v=auth[str(p)];assert p.stat().st_size==v['bytes'] and r.sha(p)==v['sha256']
old=r.read(base_input);compiler=Path(old['compiler_pins']['clang++']['path'])
assert pin(compiler)==old['compiler_pins']['clang++']
for p in old['macos_sdk']['pins']:assert pin(Path(p['path']))==p
sdk_path=old['macos_sdk']['path']
assert str(Path(subprocess.run(['/usr/bin/xcrun','--sdk','macosx','--show-sdk-path'],capture_output=True,text=True,check=True,timeout=10).stdout.strip()).resolve())==sdk_path
candidate_input=C/'input.json';candidate_review=A/'p23-02-native-integer-window-codec-static-independent-review-r285-r02.json'
candidate_root=r.read(A/'p23-02-native-integer-window-codec-static-root-verification-r285-r02.json')
assert candidate_root['passed'] and candidate_root['review_sha256']==r.sha(candidate_review)
v=r.read(candidate_input);support=r.read(candidate_review)
assert support['implementation_supported'] and not support['blockers']
# Authenticate candidate evidence; current canonical184 context pins must still match at preexecution.
for path,q in support['evidence_sha256'].items():
p=Path(q.get('path',path));assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256']
canonical_context=support['canonical_doc4_context_pins']
for q in canonical_context.values() if isinstance(canonical_context,dict) else canonical_context:
p=Path(q['path']);assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256']
host_review=A/'p23-02-native-sdk-lifetime-build-actual-independent-review-r133.json'
assert r.sha(host_review)=='c3cbeb45c1353dfea5f8181d10cc60f8a9b81db55d766ac5db902ac28c159a61'
host_support=r.read(host_review);assert host_support['host_build_accepted'] and not host_support['blockers']
host_input=HOST/'input.json';new_archive=HOST/'libgodot-cpp.macos.template_debug.arm64.a'
for p in [host_input,new_archive]:
q=host_support['evidence_sha256'][str(p)];assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256']
host=r.read(host_input);sdk_inventory=host['SDK_inventory'];assert r.inventory(SDK)==sdk_inventory
sdk_candidate_inventory=host['candidate_inventory'];assert r.inventory(SDK_C)==sdk_candidate_inventory
accepted_inventory=r.read(accepted_receipt)['original_r76_inventory']
parent_sdk_inventory={key[len('sdk/'):]:value for key,value in accepted_inventory.items() if key.startswith('sdk/')}
assert parent_sdk_inventory and r.inventory(BASE_SDK)==parent_sdk_inventory
source_inventory=r.inventory(C/'source')
assert pin(C/'source/tree_numeric_core.cpp')==v['candidate_cpp'] and pin(C/'source/tree_core.hpp')==v['candidate_header']
candidate_inventory=r.inventory(C);base_source_inventory=r.inventory(BASE/'source')
compile_db=BASE/'compile_commands.json'
authenticated_compile_db=auth[str(compile_db)]
assert compile_db.stat().st_size==authenticated_compile_db['bytes'] and r.sha(compile_db)==authenticated_compile_db['sha256']
commands=r.read(compile_db);assert len(commands)==63
fixed=[review,base_input,archive,accepted_receipt,compiler,candidate_input,candidate_review,C/'source/tree_numeric_core.cpp',C/'source/tree_core.hpp',compile_db,host_review,host_input,new_archive,build_helper_path,Path(__file__)]
fixed += [A/'p23-02-native-integer-window-codec-static-root-verification-r285-r02.json']
fixed += [preexecution_review]
fixed += [Path(p['path']) for p in old['macos_sdk']['pins']]
pins={str(p):pin(p) for p in fixed}
O.mkdir();(O/'objects').mkdir();library=O/'libtree_numeric_core.macos.template_debug.dylib'
compile_plan=[];sdk_objects=[];bridge_object=None
for i,row in enumerate(commands):
if row['file'].startswith('sdk/'):continue
argv=shlex.split(row['command']);assert argv[0]=='clang++' and '-c' in argv
argv[0]=str(compiler);out_index=argv.index('-o')+1;assert argv[out_index]==row['output']
obj=O/'objects'/('%03d-'%i+Path(row['output']).name);argv[out_index]=str(obj)
for j,t in enumerate(argv):
if t.startswith('sdk/'):argv[j]=str(SDK_C/t)
elif t.startswith('source/'):argv[j]=str(C/t)
elif t.startswith('-Isdk/'):argv[j]='-I'+str(SDK_C/t[2:])
elif t=='-Isource':argv[j]='-I'+str(C/t[2:])
source_file=C/row['file'];assert source_file.is_file();pins[str(source_file)]=pin(source_file)
compile_plan.append(('compile-%03d'%i,argv))
if row['file'].startswith('sdk/'):sdk_objects.append(obj)
else:assert row['file']=='source/tree_numeric_core.cpp' and bridge_object is None;bridge_object=obj
assert len(sdk_objects)==0 and len(compile_plan)==1 and bridge_object is not None
link_argv=[str(compiler),'-o',str(library),'-arch','arm64','-isysroot',sdk_path,'-fvisibility=hidden','-Wl,-S','-Wl,-x','-Wl,-dead_strip','-shared',str(bridge_object),str(new_archive)]
plan=compile_plan+[('link',link_argv)]
assert json.loads(json.dumps(plan))==r.read(A/'p23-02-native-integer-window-codec-build-preview-r286.json')['plan']
r.write(O/'input.json',dict(source_before=source,default_player_before=player,doc4_before=docs,pins=pins,SDK_path=str(SDK),SDK_inventory=sdk_inventory,parent_SDK_inventory=parent_sdk_inventory,SDK_identity_source=pin(accepted_receipt),candidate_inventory=candidate_inventory,base_source_inventory=base_source_inventory,plan=plan,capacity_floor_bytes=FLOOR,maximum_growth_bytes=GROWTH,expected_duration_seconds=[2,30],watchdog_seconds_each=90,serial=True,authenticated_compile_database=authenticated_compile_db,full_input_inventory_before_and_after_each_phase=True,planned_bridge_compilations=1,planned_SDK_compilations=0,SDK_archive_reused=pin(new_archive),old_bridge_object_reused=False,Godot_loaded=False,unit_accepted=False))
env=r.fresh_environment(os.environ)
for key in list(env):
if key.startswith('CCACHE_') or key in ['CFLAGS','CXXFLAGS','CCFLAGS','LDFLAGS','CPATH','CPLUS_INCLUDE_PATH','LIBRARY_PATH','SDKROOT','MACOSX_DEPLOYMENT_TARGET']:
env.pop(key)
phases=[];error=None;cleanup=[];cleanup_errors=[];binary_checks={};spawned=[]
def verify_protected_inputs():
assert r.inventory(C)==candidate_inventory
assert r.inventory(SDK)==sdk_inventory and r.inventory(SDK_C)==sdk_candidate_inventory
assert r.inventory(BASE/'source')==base_source_inventory
assert r.inventory(BASE_SDK)==parent_sdk_inventory
for path,q in pins.items():assert pin(Path(path))==q
def run_build_phase(name,argv):
# Compiler diagnostics have no Godot banner. Use retained build ownership,
# not the engine-specific diagnostic parser or a synthesized banner.
folder=O/name;folder.mkdir();process=None;phase_error=None;phase_cleanup=[];errors=[];remaining=None
started=time.monotonic();timed_out=False;exit_code=None
try:
with (folder/'stdout.log').open('wb') as stdout,(folder/'stderr.log').open('wb') as stderr:
process=subprocess.Popen(argv,cwd=folder,env=env,stdout=stdout,stderr=stderr,start_new_session=True)
spawned.append(dict(phase=name,pid=process.pid,argv=argv))
initial=build_helper.group_members(process.pid)
if process.poll() is None:
assert os.getpgid(process.pid)==process.pid and os.getsid(process.pid)==process.pid
assert any(q['pid']==process.pid and q['ppid']==os.getpid() for q in initial)
r.write(folder/'started.json',dict(pid=process.pid,owner_pid=os.getpid(),pgid=process.pid,argv=argv,started_utc=r.now(),initial_members=initial,owned_new_session=True))
print(json.dumps(dict(build_phase=name,pid=process.pid)),flush=True)
while process.poll() is None:
if time.monotonic()-started>90:
timed_out=True;raise TimeoutError('owned compiler watchdog90s')
assert shutil.disk_usage(A).free>=FLOOR
assert sum(p.stat().st_size for p in O.rglob('*') if p.is_file())<=GROWTH
time.sleep(0.1)
exit_code=process.wait(timeout=5)
except BaseException as caught:phase_error=type(caught).__name__+': '+str(caught)
finally:
if process is not None:
try:
phase_cleanup,remaining=build_helper.cleanup_owned_parent(process,process.pid,errors)
except BaseException as caught:
errors.append('retained cleanup exception: '+repr(caught))
# An unexpected helper exception never skips exact-Popen cleanup.
# No group is discovered or signalled by this fallback.
for sig in [signal.SIGTERM,signal.SIGKILL]:
try:
if process.poll() is None:process.send_signal(sig)
except BaseException as failure:errors.append('tracked signal: '+repr(failure))
try:process.wait(timeout=3)
except BaseException as failure:errors.append('tracked wait: '+repr(failure))
try:exit_code=process.wait(timeout=5)
except BaseException as caught:errors.append('final tracked wait: '+repr(caught))
r.write(folder/'ended.json',dict(pid=process.pid,argv=argv,pgid=process.pid,ended_utc=r.now(),exit_code=exit_code,duration_seconds=time.monotonic()-started,cleanup=phase_cleanup,remaining=remaining,cleanup_errors=errors,foreign_process_or_group_signals=0))
result=dict(pid=process.pid if process else None,exit_code=exit_code,timed_out=timed_out,error_lines=[phase_error] if phase_error else [],duration_seconds=time.monotonic()-started)
capture=dict(passed=process is not None and phase_error is None and not errors and remaining==[],cleanup=phase_cleanup,cleanup_errors=errors,all_captured_ended=process is not None and process.poll() is not None,foreign_process_or_group_signals=0)
return result,capture
try:
for name,argv in plan:
assert shutil.disk_usage(A).free>=FLOOR+GROWTH and not outer.native.helper['live_engines']()
# Authenticate every header/source and retained parent before and after each owned phase.
verify_protected_inputs()
result,capture=run_build_phase(name,argv)
post_input_error=None
try:verify_protected_inputs()
except BaseException as caught:post_input_error=type(caught).__name__+': '+str(caught)
row=dict(name=name,result=result,capture=capture,full_input_inventory_before_verified=True,full_input_inventory_after_verified=post_input_error is None,post_input_error=post_input_error);phases.append(row);r.write(O/(name+'-phase.json'),row)
assert post_input_error is None, post_input_error
assert result is not None and result['exit_code']==0 and not result['error_lines'] and not result['timed_out'] and capture['passed']
assert (O/name/'stderr.log').read_bytes()==b'' and (O/name/'stdout.log').read_bytes()==b''
assert sum(p.stat().st_size for p in O.rglob('*') if p.is_file())<=GROWTH
assert library.is_file() and bridge_object.is_file() and new_archive.is_file()
for name,argv in [('file',['/usr/bin/file',str(library)]),('arch',['/usr/bin/lipo','-archs',str(library)]),('dependencies',['/usr/bin/otool','-L',str(library)]),('exports',['/usr/bin/nm','-gU',str(library)])]:
q=subprocess.run(argv,capture_output=True,text=True,check=True,timeout=10)
assert not q.stderr;binary_checks[name]=q.stdout
assert binary_checks['arch'].strip()=='arm64' and '_tree_numeric_core_init' in binary_checks['exports'] and 'dynamically linked shared library' in binary_checks['file']
except BaseException as caught:error=type(caught).__name__+': '+str(caught)
finally:
cleanup=[row['capture']['cleanup'] for row in phases]
cleanup_errors=[message for row in phases for message in row['capture']['cleanup_errors']]
preserved=r.source_refs(R)==source and r.default_player(R)==player and {n:r.sha(D/n) for n in names}==docs and r.inventory(C)==candidate_inventory and r.inventory(SDK)==sdk_inventory and r.inventory(SDK_C)==sdk_candidate_inventory and r.inventory(BASE/'source')==base_source_inventory and r.inventory(BASE_SDK)==parent_sdk_inventory
for name_pin,q in pins.items():preserved=preserved and pin(Path(name_pin))==q
assert preserved
passed=error is None and len(phases)==2 and not cleanup_errors
r.write(O/'execution.json',dict(passed=passed,error=error,phases=phases,cleanup=cleanup,cleanup_errors=cleanup_errors,binary_checks=binary_checks,object=pin(bridge_object) if bridge_object.exists() else None,library=pin(library) if library.exists() else None,original_inputs_preserved=preserved,bridge_compilations=sum(q['phase']=='compile-062' for q in spawned),link_attempts=sum(q['phase']=='link' for q in spawned),spawned_children=spawned,SDK_compilations=sum(q['phase'].startswith('compile-') and q['phase']!='compile-062' for q in spawned),SDK_archive_reused=pin(new_archive),SDK_archive_rebuilt=False,old_bridge_object_reused=False,Godot_loaded=False,selected=False,unit_accepted=False,performance_accepted=False,limits=['Exact modified r285-r02 integer Array codec bridge one-object compile and link to authenticated unchanged r133 SDK archive only; no SDK recompilation, Godot load, protocol, performance or unit acceptance.']))
print(json.dumps(dict(passed=passed,error=error)),flush=True);return 0 if passed else 1
if __name__=='__main__':raise SystemExit(main())