296 lines
20 KiB
Python
296 lines
20 KiB
Python
"""Synthetic checker specimens only. No native/OS execution or acceptance claim.
|
|
|
|
The JSON, Variant stand-ins, executable and lifecycle records here are deliberately
|
|
fabricated unit-test data, never collector output. Semantic corruption tests repin
|
|
their bytes, so they cannot pass merely by detecting a stale artifact checksum.
|
|
"""
|
|
import copy
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import shutil
|
|
import struct
|
|
import zlib
|
|
import subprocess
|
|
|
|
def put(path, data):
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(json.dumps(data, ensure_ascii=False, indent=2)+'\n')
|
|
|
|
def typed(value):
|
|
if isinstance(value, dict):
|
|
return {'type': 'Dictionary', 'entries': [[typed(k), typed(v)] for k, v in value.items()]}
|
|
if isinstance(value, list):
|
|
return {'type': 'Array', 'element_type': 0, 'element_class': '', 'items': [typed(v) for v in value]}
|
|
name = 'bool' if isinstance(value, bool) else 'int' if isinstance(value, int) else 'float' if isinstance(value, float) else 'Nil' if value is None else 'String'
|
|
return {'type': name, 'text': json.dumps(value, ensure_ascii=False)}
|
|
|
|
def owner_proof(folder, pid, checker):
|
|
"""Fabricated weak-reference records, only for the whole-parser control."""
|
|
directory = folder/'teardown'; audio = directory/'owned-audio'
|
|
audio.mkdir(parents=True)
|
|
before = {'owner_ids':[1], 'owner_meta_present':True, 'closing':False,
|
|
'clock_process':True,'clock_physics_process':False,'clock_process_mode':0,
|
|
'root_gui_disable_input':False,'auto_accept_quit':False,'original_auto_accept_quit':True}
|
|
after = dict(before, owner_ids=[], owner_meta_present=False, auto_accept_quit=True)
|
|
control = {'owned_engine_pid':pid,'owner_instance_id':1,'passed':True,
|
|
'maximum_wait_us':500000,'whole_Runtime_field_deletions':0,
|
|
'before':before,'after':after,'expected_remaining_owner_ids':[]}
|
|
for key in ('ordinary_owner_release_verified','clock_process_flags_unchanged',
|
|
'root_gui_input_flag_unchanged','audio_teardown_passed'): control[key] = True
|
|
for key in ('gameplay_expectations_changed','clock_flags_intentionally_modified','application_close_called',
|
|
'SceneTree_quit_overridden','WindowQuit_verified','formal_acceptance'): control[key] = False
|
|
put(directory/'control.json', control)
|
|
targets = [{'kind':kind,'role':role,'instance_id':i*4+j+1,'alive':True}
|
|
for i,kind in enumerate(('stream','packet_sequence')) for j,role in enumerate(('click','success','refusal','notification'))]
|
|
proof = {'owned_engine_pid':pid,'owner_instance_id':1,'passed':True,'maximum_wait_us':500000,
|
|
'waited_actual_us':100,'deadline_reached':False,'initial_targets':targets,
|
|
'final_targets':[dict(t,alive=False) for t in targets], 'full_typed_snapshots':{}}
|
|
for key in ('owner_freed','all_owned_targets_released','whole_runtime_unchanged'): proof[key] = True
|
|
for key in ('bus_deleted','cues_muted_for_test','actual_human_hearing','WindowQuit_verified','formal_acceptance'): proof[key] = False
|
|
for part in ('before','after'):
|
|
path = audio/('owner_1-'+part+'.varbytes')
|
|
path.write_bytes(b'SYNTHETIC typed bytes; not engine proof')
|
|
proof['full_typed_snapshots'][part] = {'path':str(path),'field_deletions':0,'bytes':path.stat().st_size,'sha256':checker.sha(path)}
|
|
put(audio/'owner_1.json', proof)
|
|
owners = checker.module('synthetic_owner_parser', checker.HERE/'regression/ordinary_proof_gate.py')
|
|
return owners.ordinary_gate(directory,pid,folder,['single'])
|
|
|
|
def make(base, source, checker):
|
|
root, out = base/'source', base/'p08-normal-placement-evidence'
|
|
for folder in ('autoload', 'scripts', 'scenes', 'data', 'tests', 'assets', 'tools'):
|
|
(root/folder).mkdir(parents=True, exist_ok=True)
|
|
for name in ('project.godot', 'export_presets.cfg', 'Makefile', 'AGENTS.md', checker.SPEC,
|
|
checker.CONTRACT, checker.TEST, checker.RECORDER, checker.RECORDER+".uid",
|
|
"tools/run_p08_normal_placement.py",
|
|
'docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md',
|
|
'docs/traceability/original/BASELINE.txt', 'data/facilities/reception.tres',
|
|
'data/facilities/standard_room.tres',
|
|
'data/facilities/infrastructure/guest_stairs.tres'):
|
|
target = root/name
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copyfile(source/name, target)
|
|
(root/'tests/fixtures/p08-03').mkdir(parents=True)
|
|
out.mkdir()
|
|
engine = base/'synthetic-engine-not-executable'
|
|
engine.write_text('SYNTHETIC TEST DATA; NEVER EXECUTE\n')
|
|
sha = checker.sha
|
|
source_map = {n: v['sha256'] for n, v in checker.runner.source_refs(root).items()}
|
|
index = {'schema': 'p08-normal-placement-v1', 'commit': subprocess.check_output(['git','-C',str(source),'rev-parse','HEAD'],text=True).strip(), 'source_map': source_map,
|
|
'inputs': checker.input_map(root), 'spec_sha256': checker.SPEC_SHA,
|
|
'marker_contract_sha256': sha(root/checker.CONTRACT), 'conditions': checker.CONDITIONS,
|
|
'collection_error': None, 'acceptance': 'pending', 'regression': None}
|
|
put(out/'runner-input.json', {'selected_source_map': source_map, 'commit': index['commit'],
|
|
'engine': str(engine), 'engine_sha256': sha(engine)})
|
|
put(out/'runner-ended.json', {'error': None, 'cleanup_errors': [], 'synthetic': True})
|
|
|
|
def phase(label, pid):
|
|
prefix = 'runs/'+label+'/'
|
|
command = [str(engine), '--headless', '--path', str(root), '--script', label]
|
|
raw = {'actual_pid': pid, 'command': command, 'live_identity_exact': True,
|
|
'engine_ended': True, 'exit_code': 0, 'synthetic': True}
|
|
for name in ('started.json', 'ended.json'):
|
|
put(out/(prefix+label+'/'+name), raw)
|
|
put(out/(prefix+label+'/outer-owned-finally.json'), {'actual_captured_pids': [pid],
|
|
'all_captured_ended': True, 'outer_cleanup_errors': [], 'foreign_process_or_group_signals': 0})
|
|
(out/(prefix+'stdout.log')).write_text('Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org\nP08 normal placement: 100 checks, 0 failures\n')
|
|
receipt = {'actual_pid': pid, 'command': command, 'phase': label, 'test': checker.TEST,
|
|
'source_sha256': source_map[checker.TEST], 'log': 'stdout.log',
|
|
'exit_code': 0, 'engine_ended': True, 'failed': False,
|
|
'native_process': {'exit_code': 0, 'helper_exit_code': 0, 'timed_out': False, 'lifecycle_error': None},
|
|
'actual_private_profile': {'report': {'fresh_before_parent_initialize': True,
|
|
'profile_writes_before_guard': 0, 'actual_user_data_dir': label, 'expected_user_data_dir': label}}}
|
|
name = prefix+label+'-receipt.json'
|
|
put(out/name, receipt)
|
|
return name
|
|
|
|
pair_phases = [phase('writer', 101), phase('reader', 102)]
|
|
os_phases = []
|
|
index['cases'] = [{'directory': 'pair', 'phases': pair_phases}]
|
|
index['phases'] = pair_phases
|
|
index['os_proof'] = 'os.json'
|
|
put(out/'os.json', {'source_map': source_map, 'inputs': index['inputs'], 'input_method': 'native_os',
|
|
'observer_mutations': [], 'phases': os_phases, 'directory': 'os-pair', 'synthetic': True})
|
|
|
|
def pair(directory, pids, method):
|
|
folder = out/directory
|
|
folder.mkdir()
|
|
runtime = {k: {} for k in sorted(checker.RUNTIME_KEYS)}
|
|
runtime.update(world={'occupancies': [], 'bounds':{'min_x':-10,'max_y':10}}, construction={'facilities': [], 'jobs': []},
|
|
facilities={'instances': []}, next_command_id=1,
|
|
command_queue={'processed': [], 'pending': [], 'in_flight': [], 'accepted': [], 'idempotency': {}})
|
|
model = {'schema_version': 1, 'clock': {'absolute_minute': 360, 'paused': True},
|
|
'game_state': {'resources': {'gold': 5000, 'materials': 50}}, 'systems': {'runtime': runtime}}
|
|
target = [-8, 0, 0]
|
|
cost = {'reception': {'gold': 500, 'materials': 8}, 'guest_stairs': {'gold': 40, 'materials': 0}, 'standard_room':{'gold':350,'materials':5}}
|
|
rooms = 0
|
|
|
|
def snap(name):
|
|
put(folder/(name+'.json'), typed(model))
|
|
(folder/(name+'.var')).write_bytes(json.dumps(model, sort_keys=True).encode())
|
|
return name
|
|
|
|
def position(cell):
|
|
return {'world_cell': cell[:], 'selected_cell': cell[:], 'bounds': {'min_x': -10, 'max_y': 10},
|
|
'map_position': [0, 0], 'cell_dimensions': [10, 10],
|
|
'local': [(cell[0]+10.5)*10, (10.5-cell[1])*10],
|
|
'viewport_transform':[1,0,0,1,0,0], 'screen_transform':[1,0,0,1,0,0],
|
|
'screen':[(cell[0]+10.5)*10, (10.5-cell[1])*10],
|
|
'viewport': [(cell[0]+10.5)*10, (10.5-cell[1])*10], 'zoom': 1.0, 'pan': [0, 0]}
|
|
|
|
def result(code, details=None, message=''):
|
|
row = {'code': code, 'details': details or {}, 'message': message,
|
|
'command_id': runtime['next_command_id'], 'target_id': '', 'is_replay': False, 'resolution_hints': []}
|
|
runtime['next_command_id'] += 1
|
|
runtime['command_queue']['processed'].append(copy.deepcopy(row))
|
|
return row
|
|
|
|
def os_meta(row, pid):
|
|
row['input_method'] = method
|
|
if method != 'native_os': return
|
|
requests = [{'action':'cell', 'world_cell':row['position']['world_cell'],
|
|
'viewport':row['position']['viewport'], 'screen':row['position']['screen']}]
|
|
if row['id'] in ('unsupported','resume_overlap'):
|
|
requests.append({'action':'load_menu'})
|
|
if row['id'] == 'pan_zoom':
|
|
requests.append({'action':'button','node':'/root/Main/ManualSaveButton'})
|
|
requests += [{'action':'wheel','ctrl':False,'move_mode':True}]
|
|
requests += [{'action':'wheel','ctrl':False,'move_mode':False} for _ in range(18)]
|
|
row['requests'] = []
|
|
for sequence, request in enumerate(requests, 1):
|
|
prefix = directory+'/'+row['id']+'-'+str(sequence)+'/'
|
|
request.update(target_pid=pid, sequence=sequence)
|
|
put(out/(prefix+'request.json'), request)
|
|
put(out/(prefix+'observed.json'), {'pid':pid,'sequence':sequence,'events':[{'synthetic':True}]})
|
|
receipt = directory+'/'+row['id']+'-os.json'
|
|
put(out/receipt, {'method':'native_os','target_pid':pid,'timestamp_ns':10000,
|
|
'collector_pid':999,'tool_name':'mock CUA','tool_call_id':'synthetic-only',
|
|
'events':[{'synthetic':True}]})
|
|
put(out/(prefix+'ack.json'), {'target_pid':pid,'sequence':sequence,
|
|
'request_sha256':sha(out/(prefix+'request.json')), 'input_receipt':receipt,
|
|
'screen_before':directory+'/screen.png','screen_after':directory+'/screen.png'})
|
|
row['requests'].append(prefix+'ack.json')
|
|
def chunk(kind, body):
|
|
return struct.pack('>I',len(body))+kind+body+struct.pack('>I',zlib.crc32(kind+body))
|
|
(folder/'screen.png').write_bytes(b'\x89PNG\r\n\x1a\n'+
|
|
chunk(b'IHDR',struct.pack('>IIBBBBB',1,1,8,2,0,0,0))+
|
|
chunk(b'IDAT',zlib.compress(b'\0\0\0\0'))+chunk(b'IEND',b''))
|
|
|
|
actions = []
|
|
for label in checker.WRITER:
|
|
cell = [4, 1, 0] if label in ('lower_stair', 'refused_demolition') else [4, 2, 0] if label == 'upper_stair' else target[:]
|
|
definition = 'guest_stairs' if label in ('lower_stair', 'upper_stair', 'missing_connection') else 'reception'
|
|
if label == 'unsupported': definition = 'standard_room'
|
|
row = {'id': label, 'position': position(cell), 'expected': '', 'results': [], 'status': '',
|
|
'kind': 'build', 'definition': definition, 'before': snap('writer-'+label+'-before')}
|
|
report = {'can_build': True, 'error_codes': [], 'total_cost': cost[definition], 'connection': {'status': 'CONNECTED'}}
|
|
row['report'] = report
|
|
if label in checker.REASONS:
|
|
code, message = checker.REASONS[label]
|
|
report.update(can_build=False, error_codes=[code])
|
|
row.update(expected=code, status=message)
|
|
elif label == 'missing_connection':
|
|
row['expected'] = 'STAIR_LANDING_MISSING'
|
|
row['results'] = [result('VALIDATION_FAILED', {'reason': row['expected']}, 'missing landing')]
|
|
row['status'] = '操作に失敗しました: missing landing'
|
|
elif label == 'cancel_demolition':
|
|
row.update(kind='cancel', status='撤去を取り消しました。')
|
|
elif label in ('demolition', 'refused_demolition'):
|
|
fid = 'f1' if label == 'demolition' else 'f2'
|
|
row.update(kind='demolish', instance_id=fid)
|
|
if label == 'refused_demolition':
|
|
row['expected'] = 'STAIR_LANDING_IN_USE'
|
|
row['results'] = [result('VALIDATION_FAILED', {'reason': row['expected']}, 'dependent stair')]
|
|
else:
|
|
row['results'] = [result('OK', {'refund': {'materials': 2}, 'instance_id': fid})]
|
|
model['game_state']['resources']['materials'] += 2
|
|
runtime['construction']['facilities'] = [v for v in runtime['construction']['facilities'] if v['instance_id'] != fid]
|
|
runtime['construction']['jobs'] = [v for v in runtime['construction']['jobs'] if v.get('facility_instance_id') != fid]
|
|
runtime['facilities']['instances'] = [v for v in runtime['facilities']['instances'] if v['instance_id'] != fid]
|
|
runtime['world']['occupancies'] = [v for v in runtime['world']['occupancies'] if v['entity_id'] != fid]
|
|
r = row['results'][0]
|
|
row['status'] = '%s | %s | %s' % (r['code'], r['details'].get('reason', ''), r['message'])
|
|
elif label == 'pan_zoom':
|
|
row.update(kind='camera', original_local=[1, 2], ctrl_pressed=False,
|
|
pan_before=[0,0], pan_after=[0,10],
|
|
steps=[0.5]*9+[1, 1.5, 2, 2.5, 3, 3.5, 4, 4, 4])
|
|
else:
|
|
rooms += 1
|
|
fid, jid = 'f'+str(rooms), 'j'+str(rooms)
|
|
row['results'] = [result('OK', {'job_id': jid})]
|
|
for k, v in cost[definition].items(): model['game_state']['resources'][k] -= v
|
|
cells = [[cell[0]+dx,cell[1]+dy,cell[2]] for dx in range(4 if definition == 'reception' else 1) for dy in range(2 if definition == 'reception' else 1)]
|
|
job = {'job_id': jid, 'state': 'PLANNED', 'reserved_cells': cells}
|
|
runtime['construction']['jobs'].append(job)
|
|
runtime['world']['occupancies'].append({'entity_id': jid, 'cells': cells})
|
|
row['after'] = snap('writer-'+label+'-after')
|
|
job.update(state='COMPLETED', facility_instance_id=fid)
|
|
facility = {'instance_id': fid, 'definition_id': definition, 'occupied_cells': cells, 'origin': cell[:], 'source_job_id': jid}
|
|
runtime['construction']['facilities'].append(facility)
|
|
runtime['facilities']['instances'].append(copy.deepcopy(facility))
|
|
runtime['world']['occupancies'][-1]['entity_id'] = fid
|
|
row['completed'] = snap('writer-'+label+'-completed')
|
|
if 'after' not in row: row['after'] = snap('writer-'+label+'-after')
|
|
os_meta(row, pids[0])
|
|
actions.append(row)
|
|
budget = {'setup': 'diagnostic', 'costs': [{'definition': d, 'cost': cost[d]} for d in ('reception', 'reception', 'guest_stairs', 'guest_stairs')],
|
|
'needed': {'gold': 1080, 'materials': 16}, 'initial': {'gold': 5000, 'materials': 50}, 'deltas': {}}
|
|
put(folder/'writer-actions.json', {'setup': 'diagnostic', 'actions': actions, 'budget': budget})
|
|
snap('writer-checkpoint')
|
|
snap('reader-checkpoint')
|
|
formal = folder/'formal'
|
|
formal.mkdir()
|
|
for member in checker.MEMBERS: (formal/member).write_text('synthetic '+member+'\n')
|
|
put(folder/'save.json', {'members': {n: sha(formal/n) for n in checker.MEMBERS},
|
|
'pid': pids[0], 'cell': target, 'instance_id': 'f4'})
|
|
row = {'id': 'resume_overlap', 'kind': 'build', 'position': position(target),
|
|
'definition':'reception',
|
|
'before': snap('reader-resume-before'), 'after': snap('reader-resume-after'),
|
|
'results': [], 'report': {'can_build': False, 'error_codes': ['OVERLAP']},
|
|
'status': checker.REASONS['overlap'][1]}
|
|
os_meta(row, pids[1])
|
|
put(folder/'reader-actions.json', {'setup': 'diagnostic', 'actions': [row]})
|
|
if method == 'native_os':
|
|
put(folder/'writer-requests.json', {'pid':pids[0],
|
|
'requests':[name for action in actions for name in action['requests']]})
|
|
put(folder/'reader-requests.json', {'pid':pids[1],'requests':row['requests']})
|
|
for role, pid in zip(('writer', 'reader'), pids):
|
|
put(folder/(role+'-process.json'), {'pid': pid, 'engine': {'hash': 'synthetic', 'string': 'synthetic'}, 'checks': 100, 'failures': 0})
|
|
pair('pair', [101, 102], 'handler')
|
|
pair('os-pair', [201, 202], 'native_os')
|
|
shutil.copytree(out/'pair/formal', out/'pair/initial-formal')
|
|
for role, pid in (('writer',201),('reader',202)):
|
|
prefix = 'os-runs/'+role+'/'
|
|
folder = out/prefix
|
|
folder.mkdir(parents=True)
|
|
shutil.copyfile(source/checker.RECORDER, folder/'passive_os.gd')
|
|
profile = base/('synthetic-profile-'+role)
|
|
command = [str(engine),'--path',str(root),'--script',str(folder/'passive_os.gd')]
|
|
formal = out/('pair/initial-formal' if role == 'writer' else 'os-pair/formal')
|
|
members = {n:{'bytes':(formal/n).stat().st_size,'sha256':sha(formal/n)} for n in checker.MEMBERS}
|
|
record = {'protocol':'p08-placement-native-os-v1','role':role,'commit':index['commit'],
|
|
'source_map':source_map,'stage':str(root),'profile':str(profile),'command':command,
|
|
'engine_sha256':sha(engine),'controller_sha256':source_map['tools/run_p08_normal_placement.py'],
|
|
'recorder_sha256':sha(source/checker.RECORDER),'formal_input':members,
|
|
'actual_pid':pid,'monotonic_ns':1,'exit_code':0,'engine_ended':True,'passed':True,
|
|
'error':None,'guard_errors':[],'cleanup_errors':[],
|
|
'owned_cleanup':[{'pid':pid,'engine_ended':True,'outer_cleanup_errors':[],'foreign_process_or_group_signals':0}],
|
|
'stage_before':{},'stage_after':{},'default_before':{},'default_after':{},
|
|
'source_after':{n:{'sha256':v} for n,v in source_map.items()},
|
|
'profile_before':{'existed':False,'files':{}},'ordinary_owner_proof':owner_proof(folder,pid,checker)}
|
|
for name in ('started.json','process-started.json','ended.json'): put(folder/name, record)
|
|
(folder/'engine-native.log').write_text('P08 passive OS placement: 100 checks, 0 failures\n')
|
|
put(out/('os-pair/'+role+'-profile.json'), {'pid':pid,'user_data_dir':str(profile),'display':'synthetic'})
|
|
os_phases.append(prefix+'ended.json')
|
|
put(out/'os.json', {'source_map':source_map,'inputs':index['inputs'],'input_method':'native_os',
|
|
'observer_mutations':[],'phases':os_phases,'directory':'os-pair','synthetic':True})
|
|
put(out/'index.json', index)
|
|
repin(out)
|
|
return root, out
|
|
|
|
def repin(out):
|
|
index = json.loads((out/'index.json').read_text())
|
|
index['artifacts'] = {p.relative_to(out).as_posix(): {'bytes': p.stat().st_size,
|
|
'sha256': hashlib.sha256(p.read_bytes()).hexdigest()} for p in out.rglob('*') if p.is_file() and p != out/'index.json'}
|
|
put(out/'index.json', index)
|