<?php
declare(strict_types=1);require __DIR__.'/contract.php';
$runtime=getenv('SM7_RUNTIME');$lane=getenv('SM7_LANE');$port=$lane==='B'?18411:18412;
if(!preg_match('#^/tmp/cdx-device-catalog-[BC]-[A-Za-z0-9]+$#D',__DIR__)||realpath($runtime)!==__DIR__.'/private-runtime'||is_link($runtime)){throw new RuntimeException('Private cleanup root guard');}
if(is_file(__DIR__.'/worker_state.json')){throw new RuntimeException('Stop this worker first');}
if($s=@fsockopen('127.0.0.1',$port,$n,$e,1)){fclose($s);throw new RuntimeException('Owned port still listening');}
catActor(smPdo());$removed=[];
foreach(['collection-private.json','card-collection-private.json','green-collection-private.json','native-report/catalog-original.json','native-report/card.json','native-report/catalog-green.json'] as $file){$path=$runtime.'/'.$file;if(!is_file($path)){continue;}if(is_link($path)){throw new RuntimeException('Token artifact symlink');}$removed[]=['file'=>$file,'bytes'=>filesize($path),'sha256'=>hash_file('sha256',$path)];unlink($path);}
$counts=[];foreach(['cache','runtime','safe-log'] as $folder){$path=$runtime.'/'.$folder;$count=0;if(is_dir($path)){if(is_link($path)||realpath($path)!==$runtime.'/'.$folder){throw new RuntimeException('Private transient boundary');}$it=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path,FilesystemIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST);foreach($it as $file){if($file->isLink()||$file->isFile()){unlink($file->getPathname());$count++;}elseif($file->isDir()){rmdir($file->getPathname());}}}$counts[$folder]=$count;}
$remaining=0;foreach(['collection-private.json','card-collection-private.json','green-collection-private.json','native-report/catalog-original.json','native-report/card.json','native-report/catalog-green.json'] as $file){$remaining+=(int)is_file($runtime.'/'.$file);}
$cacheRemaining=0;if(is_dir($runtime.'/cache')){foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($runtime.'/cache',FilesystemIterator::SKIP_DOTS)) as $file){if($file->isFile()||$file->isLink()){$cacheRemaining++;}}}
$source=__DIR__.'/source';if(is_link($source)||realpath($source)!==$source){throw new RuntimeException('Owned source cleanup guard');}$sourceRemoved=0;
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source,FilesystemIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST) as $file){if($file->isLink()||$file->isFile()){unlink($file->getPathname());$sourceRemoved++;}elseif($file->isDir()){rmdir($file->getPathname());}}rmdir($source);
$result=['lane'=>$lane,'port'=>$port,'port_listening'=>false,'worker_state_exists'=>false,'private_cache_files_removed'=>$counts['cache'],'private_cache_files_remaining'=>0,'private_transient_files_removed'=>$counts,'token_artifacts_removed'=>$removed,'token_artifacts_remaining'=>$remaining,'new_pdo_owned_actor_verified'=>true,'new_fixture_dml'=>0,'ddl'=>0,'business_rows_deleted'=>0,'natural_global_unchanged_claimed'=>false,'consumed_source_window_checks'=>'per-stage before/after evidence','credential_free_raw_wire_retained'=>true,'shared_cli_cache_preserved'=>'/tmp/cdx-apifox-cli-2.2.8-cache/package'];
$result['private_cache_files_remaining']=$cacheRemaining;$result['credential_bearing_private_source_files_removed']=$sourceRemoved;$result['credential_bearing_private_source_remaining']=(int)is_dir($source);
if($remaining!==0||$cacheRemaining!==0||is_dir($source)){throw new RuntimeException('Private cleanup incomplete');}
smSave('cleanup-private.json',$result);echo json_encode($result),PHP_EOL;
