<?php
set_exception_handler(static function(Throwable $e){$r=['class'=>get_class($e),'message'=>$e->getMessage(),'line'=>$e->getLine(),'observer'=>$GLOBALS['FOOD_OBSERVER']??[]];$f=__DIR__.'/private/read8-tool-failure-'.str_replace('.','-',sprintf('%.6f',microtime(true))).'.json';file_put_contents($f,json_encode($r,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_PRESERVE_ZERO_FRACTION));chmod($f,0600);fwrite(STDERR,'Read8 setup stopped; private diagnostic saved'.PHP_EOL);exit(1);});
$GLOBALS['FOOD_READ_BATCH_ACTIVE']=true;require __DIR__.'/common.php';require __DIR__.'/read-source.php';$mode=$argv[1]??'';
if($lane==='B')$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,false);
if($mode==='preflight'){
 $tables=FoodGate::READ_TABLES;$in=implode(',',array_fill(0,count($tables),'?'));$cols=$lane==='B'?$q('store','SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('.$in.') ORDER BY TABLE_NAME,ORDINAL_POSITION',$tables):$q('store','SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME IN ('.$in.') ORDER BY TABLE_NAME,COLUMN_ID',array_map('strtoupper',$tables));$schema=[];foreach($cols as $r)$schema[strtolower($r['table_name'])][]=$r;$snapshot=$readSnapshot($schema);$actor=json_decode(file_get_contents(__DIR__.'/private/baseline.json'),true)['actor'][0];
 $role=isset($schema['ydy_role'])?$q('store','SELECT uuid FROM ydy_role ORDER BY id DESC LIMIT 1'):[];$staff=isset($schema['ydy_staff'])?$q('store','SELECT uuid FROM ydy_staff WHERE is_show=? ORDER BY id LIMIT 1',[1]):[];$annex=isset($schema['ydy_annex'])?$q('store','SELECT staff_uuid FROM ydy_annex WHERE type=? ORDER BY id DESC LIMIT 1',[1]):[];$employment=isset($schema['ydy_employment_state'])?$q('store','SELECT staff_uuid FROM ydy_employment_state ORDER BY id DESC LIMIT 1'):[];$enginery=isset($schema['ydy_enginery_iochemistry'])?$q('store','SELECT uuid,staff_uuid FROM ydy_enginery_iochemistry ORDER BY id DESC LIMIT 1'):[];$none='00000000-0000-4000-8000-000000000000';$staffUuid=$staff[0]['uuid']??$none;
 $cases=[['role','/p/role/getData',[]],['role-checked','/p/role/getDataCheked',['role_uuid'=>$role[0]['uuid']??$none]],['role-checked','/p/role/getDataCheked',[]],['user','/p/user/dataPermissionInfo',['uuid'=>$actor['uuid']]],['user','/p/user/dataPermissionInfo',[]],['ai-task','/p/cater/aiImportTaskList',['page'=>1,'page_size'=>2]],['ai-task','/p/cater/aiImportTaskList',['page'=>0,'page_size'=>0]],['annex','/p/materialAnnex/lists',['staff_uuid'=>$annex[0]['staff_uuid']??$staffUuid,'page'=>1]],['employment','/p/employmentState/info',['staff_uuid'=>$employment[0]['staff_uuid']??$staffUuid]],['enginery-list','/p/engineryIochemistry/lists',['staff_uuid'=>$enginery[0]['staff_uuid']??$staffUuid,'page'=>1]],['enginery-info','/p/engineryIochemistry/info',['uuid'=>$enginery[0]['uuid']??$none]],['enginery-info','/p/engineryIochemistry/info',[]]];$out=[];foreach($cases as $i=>$c)$out[]=['label'=>sprintf('R%02d',$i+1),'kind'=>$c[0],'path'=>$c[1],'params'=>$c[2],'readonly'=>true,'stage'=>0];$save('read8-preflight.json',['schema'=>$schema,'snapshot'=>$snapshot,'cases'=>$out,'selection_counts'=>['role'=>count($role),'staff'=>count($staff),'annex'=>count($annex),'employment'=>count($employment),'enginery'=>count($enginery)],'observer'=>$GLOBALS['FOOD_OBSERVER']]);echo json_encode(['lane'=>$lane,'read8_preflight'=>true,'schema_tables'=>count($schema),'selection_nonempty'=>['role'=>count($role),'staff'=>count($staff),'annex'=>count($annex),'employment'=>count($employment),'enginery'=>count($enginery)]]),"\n";exit;
}
$pre=json_decode(file_get_contents(__DIR__.'/private/read8-preflight.json'),true);if($mode==='finish'){$snap=$readSnapshot($pre['schema']);if($snap!==$pre['snapshot'])throw new RuntimeException('Read batch related table drift');$save('read8-final.json',['snapshot'=>$snap,'observer'=>$GLOBALS['FOOD_OBSERVER'],'strict_equal'=>true]);echo json_encode(['lane'=>$lane,'read8_final_equal'=>true]),"\n";exit;}
// Remaining B requests may need longer than the first preserved 45s timeout.
// This changes only the local client wait, never the original server memory/source.
if($mode==='step' && $lane==='B'){
 $n=(int)($argv[2]??0);if($n<2||$n>12)throw new RuntimeException('R01 never replayed');
 $case=$pre['cases'][$n-1];$label=$case['label'];if(is_file(__DIR__.'/private/sent-'.$label.'.json'))throw new RuntimeException('No read replay');
 file_put_contents(__DIR__.'/private/current.json',json_encode($case,JSON_UNESCAPED_UNICODE));chmod(__DIR__.'/private/current.json',0600);$budget('read8-HTTP',$n===12?14:13);$save('sent-'.$label.'.json',['case'=>$case,'started'=>microtime(true)]);$auth=json_decode(file_get_contents(__DIR__.'/private/auth.json'),true);$headers=[];$c=curl_init('http://127.0.0.1:18995'.$case['path']);curl_setopt_array($c,[CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>json_encode($case['params'],JSON_UNESCAPED_UNICODE),CURLOPT_RETURNTRANSFER=>true,CURLOPT_HTTPHEADER=>['Content-Type: application/json','token: '.$auth['token'],'X-CDX-CASE: '.$label],CURLOPT_CONNECTTIMEOUT=>5,CURLOPT_TIMEOUT=>($n===2?300:45),CURLOPT_HEADERFUNCTION=>static function($c,$v)use(&$headers){$headers[]=$v;return strlen($v);}]);$body=curl_exec($c);$info=curl_getinfo($c);$error=curl_error($c);curl_close($c);$save('client-'.$label.'.json',['status'=>$info['http_code'],'body'=>$body,'headers'=>$headers,'error'=>$error,'duration'=>$info['total_time']]);unset($body);usleep(200000);$hasWire=is_file(__DIR__.'/private/wire-'.$label.'.json');$hasExecution=is_file(__DIR__.'/private/execution-'.$label.'.json');echo json_encode(['lane'=>$lane,'case'=>$label,'HTTP'=>$info['http_code'],'wire_saved'=>$hasWire,'execution_saved'=>$hasExecution,'error'=>$error]),"\n";if(!$hasWire&&!$hasExecution)throw new RuntimeException('Complete original wire missing');exit;
}
if($mode!=='step')throw new RuntimeException('Readonly mode');$n=(int)($argv[2]??0);if($n<1||$n>12)throw new RuntimeException('Read case range');$case=$pre['cases'][$n-1];if($lane==='B'&&$n===1)$case['label']='R01-fixed';$label=$case['label'];if(is_file(__DIR__.'/private/sent-'.$label.'.json'))throw new RuntimeException('No read replay');file_put_contents(__DIR__.'/private/current.json',json_encode($case,JSON_UNESCAPED_UNICODE));chmod(__DIR__.'/private/current.json',0600);$budget('read8-HTTP',$lane==='B'?13:12);$save('sent-'.$label.'.json',['case'=>$case,'started'=>microtime(true)]);$auth=json_decode(file_get_contents(__DIR__.'/private/auth.json'),true);$headers=[];$c=curl_init('http://127.0.0.1:'.($lane==='B'?18995:18996).$case['path']);curl_setopt_array($c,[CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>json_encode($case['params'],JSON_UNESCAPED_UNICODE),CURLOPT_RETURNTRANSFER=>true,CURLOPT_HTTPHEADER=>['Content-Type: application/json','token: '.$auth['token'],'X-CDX-CASE: '.$label],CURLOPT_CONNECTTIMEOUT=>5,CURLOPT_TIMEOUT=>45,CURLOPT_HEADERFUNCTION=>static function($c,$v)use(&$headers){$headers[]=$v;return strlen($v);}]);$body=curl_exec($c);$info=curl_getinfo($c);$error=curl_error($c);curl_close($c);$save('client-'.$label.'.json',['status'=>$info['http_code'],'body'=>$body,'headers'=>$headers,'error'=>$error,'duration'=>$info['total_time']]);usleep(200000);$wire=json_decode((string)file_get_contents(__DIR__.'/private/wire-'.$label.'.json'),true);if(!$wire)throw new RuntimeException('Complete original wire missing');if($wire['DML_attempts']!==0||$wire['transport_spy']!==[]||$wire['notification_spy']!==[])throw new RuntimeException('Unexpected readonly effect');$decoded=json_decode((string)$body,true);echo json_encode(['lane'=>$lane,'case'=>$label,'HTTP'=>$info['http_code'],'code'=>$decoded['code']??null,'source_error'=>$wire['source_error']??null,'native_statements'=>count($wire['native'])],JSON_UNESCAPED_UNICODE),"\n";
