"""Execute production spent-folder cleanup against explicit native API doubles.""" import re from policy_harness import ROOT, body, run p = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c' callback = body(p, 'class ERR_IntelDeleteCallback') callback = callback.replace('class ERR_IntelDeleteCallback : ScriptedInventoryOperationCallback', 'struct ERR_IntelDeleteCallback') callback = callback.replace('protected ', '').replace('override ', '').replace('bool Finished;', 'bool Finished=false;').replace('bool Succeeded;', 'bool Succeeded=false;') code = '\n'.join(body(p, s) for s in ('protected void QueueCleanup(', 'protected bool ProcessCleanup(', 'void Tick(float now)', 'void Stop()')) code = code.replace('protected ', '').replace('foreach (', 'for (').replace('null', 'nullptr').replace('array', 'Array') for typ in ('ERR_SpentIntelCleanup', 'InventoryStorageManagerComponent'): code = re.sub(r'\b' + typ + r' (\w+)', typ + r'* \1', code) for ns in ('ERR_GameMode', 'Replication', 'ERR_Actors', 'SCR_FactionManager', 'ERR_InfantryAmmoTransfer', 'InventoryStorageManagerComponent', 'Math', 'LogLevel'): code = code.replace(ns + '.', ns + '::') for obj in ('request', 'player', 'folder', 'inventory', 'm_Mode'): code = re.sub(r'\b' + obj + r'\.', obj + '->', code) code = code.replace('Folder.', 'Folder->').replace('Operation.', 'Operation->').replace('Players().', 'Players()->') code = re.sub(r'FindComponent\((\w+)\)', r'FindComponent("\1")', code) run(r''' #include #include #include #include templatestruct Array:std::vector{using std::vector::vector;void Insert(T v){this->push_back(v);}int Count(){return this->size();}void Clear(){this->clear();}void Remove(int i){this->erase(this->begin()+i);}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}}; ''' + callback + r'''; struct Entity;using IEntity=Entity*; struct InventoryStorageManagerComponent{ Arrayitems;bool accept=true;int calls=0,immediate=0;ERR_IntelDeleteCallback*last=nullptr; static InventoryStorageManagerComponent*Cast(void*p){return (InventoryStorageManagerComponent*)p;} bool Contains(IEntity item){return items.Contains(item);} bool TryDeleteItem(IEntity item,ERR_IntelDeleteCallback*cb){assert(Contains(item));assert(!last||last->Finished);calls++;if(!accept)return false;last=cb;if(immediate==1)cb->OnComplete();if(immediate==2)cb->OnFailed();return true;} }; struct Entity{bool alive=true,canonical=true,objective=false;int faction=1;IEntity holder=nullptr;InventoryStorageManagerComponent*inventory=nullptr;void*FindComponent(std::string type){if(type=="ERR_DocumentComponent")return objective?this:nullptr;return inventory;}}; struct Roster{IEntity CurrentActor(IEntity p){return p&&p->canonical?p:nullptr;}}; struct ERR_GameMode{inline static ERR_GameMode*current=nullptr;Roster roster;bool active=true;int faction=1;static ERR_GameMode*Get(){return current;}bool Active(){return active;}Roster*Players(){return &roster;}int PlayerFaction(){return faction;}}; namespace Replication{bool server=true;bool IsServer(){return server;}} namespace ERR_Actors{Arrayplayers;void Players(Array&out){out=players;}bool Alive(IEntity p){return p&&p->alive;}} namespace SCR_FactionManager{int SGetFaction(IEntity p){return p->faction;}} namespace ERR_InfantryAmmoTransfer{bool StoredUnder(IEntity item,IEntity player){return item->holder==player;}} namespace Math{int Min(int a,int b){return std::min(a,b);}} namespace LogLevel{int WARNING=1;}int warnings=0;void Print(std::string,int){warnings++;} struct ERR_SpentIntelCleanup{IEntity Folder=nullptr;ERR_IntelDeleteCallback*Operation=nullptr;int Attempts=0;float NextAttempt=0,Deadline=0;bool TimeoutReported=false;}; struct Service{ERR_GameMode*m_Mode=nullptr;Arraym_Cleanup;Arraym_Spent;int m_CleanupCursor=0,recovers=0;float m_CleanupNow=0;bool m_Stopped=false;void Recover(IEntity){recovers++;} ''' + code + r''' }; struct Fixture{ERR_GameMode mode;Service service;Entity player,folder;InventoryStorageManagerComponent inventory; Fixture(){Replication::server=true;ERR_GameMode::current=&mode;service.m_Mode=&mode;player.inventory=&inventory;folder.holder=&player;inventory.items.Insert(&folder);ERR_Actors::players={&player};service.QueueCleanup(&folder,1000);} ERR_SpentIntelCleanup*job(){return service.m_Cleanup[0];} }; int main(){ // Callback terminal state cannot be changed by duplicate/late notifications. ERR_IntelDeleteCallback cb;cb.OnComplete();cb.OnAllFailed();assert(cb.Finished&&cb.Succeeded); ERR_IntelDeleteCallback failed;failed.OnFailed();failed.OnAllComplete();assert(failed.Finished&&!failed.Succeeded); {Fixture f;f.service.Tick(1000);auto cb=f.inventory.last;assert(f.inventory.calls==1&&f.job()->Attempts==1); f.service.Tick(6000);assert(f.inventory.calls==1); // one outstanding native operation cb->OnComplete();f.service.Tick(7000);assert(f.service.m_Cleanup.empty()&&f.inventory.calls==1);} // Rejection is retried slowly and stops after three requests; no force deletion. {Fixture f;f.inventory.accept=false;f.service.Tick(1000);f.service.Tick(5999);assert(f.inventory.calls==1); f.service.Tick(6000);assert(f.inventory.calls==2);f.service.Tick(11000);assert(f.inventory.calls==3); f.service.Tick(11001);assert(f.service.m_Cleanup.empty());} // An accepted request can fail later; only a definitive callback permits retry. {Fixture f;f.service.Tick(1000);f.inventory.last->OnFailed();f.service.Tick(2000); f.service.Tick(6999);assert(f.inventory.calls==1);f.service.Tick(7000);assert(f.inventory.calls==2); f.inventory.last->OnComplete();f.service.Tick(8000);assert(f.service.m_Cleanup.empty());} // A missing callback stays quarantined after deadline and logs only once. {Fixture f;f.service.Tick(1000);int before=warnings;f.service.Tick(61000);f.service.Tick(100000); assert(f.inventory.calls==1&&warnings==before+1&&!f.service.m_Cleanup.empty()); f.inventory.last->OnFailed();f.service.Tick(101000);assert(f.service.m_Cleanup.empty()&&f.inventory.calls==1);} // Deleted native entity completes without dereferencing a stale item. {Fixture f;f.job()->Folder=nullptr;f.service.Tick(1000);assert(f.service.m_Cleanup.empty()&&f.inventory.calls==0);} // Moving a folder never authorizes removal from a corpse, NPC, or ground. for(int fault=0;fault<6;fault++){Fixture f; if(fault==0)f.folder.holder=nullptr; if(fault==1)f.player.alive=false; if(fault==2)f.player.canonical=false; if(fault==3)f.player.faction=2; if(fault==4)f.inventory.items.Clear(); if(fault==5)f.player.inventory=nullptr; f.service.Tick(1000);assert(f.inventory.calls==0);f.service.Tick(61000);assert(f.service.m_Cleanup.empty());} {Fixture f;Entity next;InventoryStorageManagerComponent other;next.inventory=&other;other.items.Insert(&f.folder); f.folder.holder=&next;f.inventory.items.Clear();ERR_Actors::players.Insert(&next);f.service.Tick(1000); assert(f.inventory.calls==0&&other.calls==1);} // Objective documents never enter the queue, even if a caller asks directly. {Fixture f;Entity objective;objective.objective=true;f.service.QueueCleanup(&objective,1000);assert(f.service.m_Cleanup.size()==1); f.folder.objective=true;f.service.Tick(1000);assert(f.inventory.calls==0&&f.service.m_Cleanup.empty());} // Mode replacement, client side, shutdown and inactive rounds cannot mutate inventory. for(int fault=0;fault<4;fault++){Fixture f; if(fault==0)Replication::server=false; if(fault==1)ERR_GameMode::current=nullptr; if(fault==2)f.mode.active=false; if(fault==3)f.service.Stop(); f.service.Tick(1000);assert(f.inventory.calls==0&&f.service.recovers==0);} {Fixture f;f.service.Tick(1000);auto late=f.inventory.last;f.service.Stop();late->OnComplete();f.service.Tick(61000); assert(f.inventory.calls==1&&f.service.m_Cleanup.empty());} // Synchronous completion is accepted; the next tick retires the request. {Fixture f;f.inventory.immediate=1;f.service.Tick(1000);f.service.Tick(2000);assert(f.service.m_Cleanup.empty()&&f.inventory.calls==1);} // Round-robin tick budget stays bounded and does not starve later requests. {Fixture f;Entity folders[9];for(auto& item:folders){item.holder=&f.player;f.inventory.items.Insert(&item);f.service.QueueCleanup(&item,1000);} f.inventory.accept=false;f.service.Tick(1000);assert(f.inventory.calls==8);f.service.Tick(1001);assert(f.inventory.calls==10);} } ''') source = p.read_text() assert 'Evidence().Retire(' not in source and 'DeleteEntityAndChildren' not in source assert 'TryDeleteItem(request.Folder, request.Operation)' in source print('PASS: native-callback cleanup, bounded retries and budget, pending quarantine, objective/ownership/lifecycle protection, no evidence retirement or forced entity deletion')