<?php
require __DIR__.'/runner.php';$p=json_decode(file_get_contents(__DIR__.'/plan.json'),true);$dir=$argv[1]??__DIR__.'/private';$checks=[];
function yes($label,$fn){global $checks;$fn();$checks[]=['name'=>$label,'positive'=>true];}
function no($label,$fn){global $checks;$bad=false;try{$fn();}catch(Throwable $e){$bad=true;}fd2_need($bad,'Mutation accepted '.$label);$checks[]=['name'=>$label,'rejected'=>true];}
yes('literal46read2DDL',static function()use($p){fd2_gate($p);});
$bad=$p;$bad['steps'][0]['SQL']='DELETE FROM ydy_staff';no('unknown SQL',static function()use($bad){fd2_gate($bad);});
$bad=$p;$bad['steps'][2]['PDO_types']=[1];no('bind type',static function()use($bad){fd2_gate($bad);});
$bad=$p;$bad['steps'][31]['SQL'].=' DROP TABLE X';no('third effect',static function()use($bad){fd2_gate($bad);});
$b=fd2_baseline($dir,$p);$checks[]=['name'=>'all2338 complete62/other60/map ID types streamed','positive'=>true];
$stage=[];foreach($p['steps']as $s){if($s['phase']!=='pre'||$s['kind']!=='read')continue;$label=$s['label'];if(isset($b['metadata'][$label]))$stage[$label]=fd2_materialize($b['metadata'][$label]);}
$stage['identity']=fd2_materialize([['db'=>'ZHCT_APP']]);
function offline_summary($dir,$calibrated){$h=fopen($dir.'/date-before62.jsonl','r');$m=fopen($dir.'/date-map0.jsonl','r');$all=hash_init('sha256');$other=hash_init('sha256');$types=hash_init('sha256');$n=0;while(($base=fd2_original($h))!==null){$map=fd2_original($m);$actual=$base;if($calibrated)foreach(['create_time','update_time']as $k)$actual['row'][$k]=substr($map['map'][$k.'_zero'],0,19);fd2_row($actual,$base,$map,$calibrated);$o=$actual['row'];unset($o['create_time'],$o['update_time']);hash_update($all,serialize($actual['row']));hash_update($other,hash('sha256',serialize($o)));hash_update($types,serialize($actual['native_types']));$n++;}fclose($h);fclose($m);return ['rows'=>$n,'whole_typed_sha256'=>hash_final($all),'other60_typed_sha256'=>hash_final($other),'types_sha256'=>hash_final($types)];}
$stage['rows_before']=$stage['rows_after']=offline_summary($dir,false);$stage['map0']=['rows'=>2338];
yes('real metadata/pre full rows phase',static function()use($stage,$b,$p){fd2_phase($stage,$b,$p,'pre');});
$reordered=$stage;foreach($reordered['indexes']['rows']as &$r)$r=array_reverse($r,true);unset($r);yes('dictionary key order not a false type gate',static function()use($reordered,$b,$p){fd2_phase($reordered,$b,$p,'pre');});
$after=$stage;$after['columns']=fd2_materialize(fd2_expected_columns($b['metadata']['columns'],true));$after['table_ddl']=fd2_materialize([['ddl'=>fd2_expected_ddl($b['metadata']['table_ddl'][0]['ddl'],true)]]);$after['rows_before']=$after['rows_after']=offline_summary($dir,true);
yes('synthetic postDDL candidate only/full2338 mapped0',static function()use($after,$b,$p){fd2_phase($after,$b,$p,'after_alter');});
yes('actual metadata DATA_SCALE/default_length double preserved',static function()use($after){foreach($after['columns']['rows']as $c)if(in_array($c['column_name'],['CREATE_TIME','UPDATE_TIME'],true))fd2_need(is_float($c['data_scale'])&&$c['data_scale']===0.0&&is_float($c['default_length'])&&$c['default_length']===20.0,'Original double type');});
$final=$after;$final['triggers']=fd2_materialize([['trigger_name'=>$p['trigger'],'table_name'=>'YDY_FOODS_COMPOSITION','table_owner'=>'ZHCT_APP','status'=>'Y','triggering_type'=>'BEFORE ROW','triggering_event'=>'UPDATE','trigger_body'=>$p['steps'][31]['SQL']]]);$final['objects']=fd2_materialize([['object_name'=>$p['trigger'],'object_type'=>'TRIGGER','status'=>'VALID'],['object_name'=>'YDY_FOODS_COMPOSITION','object_type'=>'TABLE','status'=>'VALID']]);$final['dependencies']=fd2_materialize($p['baseline']['expected_owned_dependencies']);
yes('synthetic own trigger semantic/dependency phase',static function()use($final,$b,$p){fd2_phase($final,$b,$p,'after_trigger');});
yes('same-build CREATE OR REPLACE header accepted only',static function()use($p){fd2_trigger(str_replace('CREATE TRIGGER','CREATE OR REPLACE TRIGGER',$p['steps'][31]['SQL']),$p['steps'][31]['SQL']);});
$bad=$after;foreach($bad['columns']['rows']as &$c)if($c['column_name']==='UPDATE_TIME')$c['data_scale']=0;unset($c);no('float metadata coerced int',static function()use($bad,$b,$p){fd2_phase($bad,$b,$p,'after_alter');});
$bad=$after;$bad['indexes']['rows'][0]['status']='INVALID';no('index status drift',static function()use($bad,$b,$p){fd2_phase($bad,$b,$p,'after_alter');});
$bad=$after;$bad['constraints']['rows'][0]['index_owner']='OTHER';no('PK indexowner drift',static function()use($bad,$b,$p){fd2_phase($bad,$b,$p,'after_alter');});
$bad=$final;$bad['objects']['rows'][]=['object_name'=>'NATURAL','object_type'=>'TRIGGER','status'=>'VALID'];no('extra object',static function()use($bad,$b,$p){fd2_phase($bad,$b,$p,'after_trigger');});
foreach(['CONDIMENT_STATE','NAME','CREATE_TIME']as $field){$bad=str_replace(':NEW.'.$field,':NEW.WRONG_FIELD',$p['steps'][31]['SQL']);no('complete trigger field '.$field,static function()use($bad,$p){fd2_trigger($bad,$p['steps'][31]['SQL']);});}
$bad=str_replace("UPDATING('UPDATE_TIME')","UPDATING('CREATE_TIME')",$p['steps'][31]['SQL']);no('wrong explicit UPDATE_TIME guard',static function()use($bad,$p){fd2_trigger($bad,$p['steps'][31]['SQL']);});
$bad=str_replace(':NEW.UPDATE_TIME :=',':NEW.CREATE_TIME :=',$p['steps'][31]['SQL']);no('natural field assignment',static function()use($bad,$p){fd2_trigger($bad,$p['steps'][31]['SQL']);});
$h=fopen($dir.'/date-before62.jsonl','r');$old=fd2_original($h);fclose($h);$h=fopen($dir.'/date-map0.jsonl','r');$map=fd2_original($h);fclose($h);
foreach(['price'=>'other60','id'=>'PK','date'=>'date mapping','type'=>'native type','missing'=>'62 arity']as $kind=>$name){$bad=$old;if($kind==='price')$bad['row']['energy']+=1;if($kind==='id')$bad['row']['id']+=1;if($kind==='date')$bad['row']['create_time']='2099-01-01 00:00:00.000000';if($kind==='type')$bad['native_types']['energy']='string';if($kind==='missing')unset($bad['row']['condiment_state']);no('raw row '.$name,static function()use($bad,$old,$map){fd2_row($bad,$old,$map,false);});}
no('worker lacks Root execute release before PDO',static function()use($p){fd2_execute($p,[]);});
$result=fd2_json(['status'=>'PURE_FOOD_ROOT_RUNNER_TEST_GREEN','checks'=>count($checks),'details'=>$checks,'synthetic_postDDL_is_not_execution_evidence'=>true,'rows_streamed_per_phase'=>2338,'DB_connections'=>0,'SQL'=>0,'DDL'=>0,'DML'=>0,'HTTP'=>0])."\n";
if(isset($argv[2])){fd2_need(in_array($argv[2],['pure-php73.json','pure-php74.json'],true),'Exact new pure result filename');$h=fopen(__DIR__.'/private/'.$argv[2],'x');fd2_need(is_resource($h),'No pure result overwrite');fd2_need(fwrite($h,$result)===strlen($result),'Raw pure stdout saved');fclose($h);chmod(__DIR__.'/private/'.$argv[2],0600);}echo $result;
