"""Execute dry native eligibility/slot proof; never launch the runner or inventory operation.""" import ast,os,re from pathlib import Path from types import SimpleNamespace from policy_harness import ROOT,body,run R=Path(os.environ.get('ERR_NATIVE_SWAP_ROOT',ROOT)) p=Path(os.environ.get('ERR_NATIVE_SWAP_SOURCE',R/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c')) s=p.read_text();fixture=(R/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c').read_text() smoke=(R/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c').read_text() runner=(R/'tools/headless_workbench.py').read_text() assert s.startswith('#ifdef WORKBENCH') and s.rstrip().endswith('#endif') for forbidden in ('TrySwap','TryMove','TrySpawn','Spawn(', 'SetAmmoCount','SetOrigin','DeleteEntity','.Reserve(','.Commit(','.BindVehicle(','.Sample(','.Advance(','.Ingest(','.AddWaypoint(','.RemoveWaypoint('): assert forbidden not in s,forbidden assert s.count('.CanSwapItemStorages(')==1 assert 'Collect(vehicle.Entity, shape, allowed, weapons)' in s assert 'GetChildren(' not in s and 'GetSibling(' not in s # exact shared production collector, no parallel traversal for guard in ('index < 6','weapons.Count() > 32','muzzles.Count() > 8','seen.Count() >= 128','cargo.Count() > 128','stores.Count() > 64','InitialStrength() > 32','CanAttribute(slot, worker, false)','ValidateBoundVehicle(vehicle.Entity)','cargo.Contains(outgoing)','ExactGun()'): assert guard in s,guard assert 'now + 180000' in fixture and 'now > m_Deadline' in fixture assert fixture.index('if (m_SwapEligibility)\n {') < fixture.index('Capture(hq, task.Vehicles[slot], now)') assert 'if (!m_ProofTask) m_ProofTask = Candidate(hq)' in fixture assert 'native mounted swap eligibility only; no transfer or radio proof' in smoke assert "['-errMountedSwapEligibility', '1']" in runner node=next(n for n in ast.parse(runner).body if isinstance(n,ast.If) and 'a.mounted_swap_eligibility' in ast.unparse(n.test)) condition=compile(ast.Expression(node.test),'','eval') for flag,outcome,bad in [(True,'mounted-ammo',False),(False,'convoy',False),(True,'convoy',True)]: assert eval(condition,{'a':SimpleNamespace(mounted_swap_eligibility=flag,smoke=outcome)})==bad # Check exact dry call/body with controlled native result and original inventory slots. code='\n'.join(body(p,x) for x in ('protected static bool Attached(', 'protected int DryRun(', 'void Stop(')) code=code.replace('protected ','').replace('InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent))','item->inventory') for t in ('IEntity','InventoryStorageSlot','InventoryStorageManagerComponent','BaseMuzzleComponent','InventoryItemComponent'): code=re.sub(r'\b'+t+r' (?=\w)',t+'* ',code) for var in ('slot','inventoryItem','source','muzzle'):code=code.replace(var+'.',var+'->') code=code.replace('GetMagazine().','GetMagazine()->') run(r''' #include #include struct IEntity;struct InventoryStorageSlot; struct InventoryItemComponent{InventoryStorageSlot* slot=nullptr;InventoryStorageSlot* GetParentSlot(){return slot;}}; struct IEntity{InventoryItemComponent* inventory=nullptr;}; struct InventoryStorageSlot{IEntity* attached=nullptr;IEntity* GetAttachedEntity(){return attached;}}; struct Magazine{IEntity* owner=nullptr;IEntity* GetOwner(){return owner;}}; struct BaseMuzzleComponent{Magazine* loaded=nullptr;Magazine* GetMagazine(){return loaded;}}; struct InventoryStorageManagerComponent{int calls=0;bool result=true;std::function effect; bool CanSwapItemStorages(IEntity* incoming,IEntity* outgoing){assert(incoming&&outgoing);calls++;if(effect)effect();return result;}}; templatevoid PrintFormat(T...){} struct Probe{bool m_Stopped=false,m_Called=false;int m_Result=0; '''+code+r''' }; struct Fixture{IEntity incoming,outgoing,foreign;InventoryItemComponent a,b;InventoryStorageSlot from,to,other; Magazine magazine;BaseMuzzleComponent muzzle;InventoryStorageManagerComponent source;Probe p; Fixture(){incoming.inventory=&a;outgoing.inventory=&b;a.slot=&from;b.slot=&to;from.attached=&incoming;to.attached=&outgoing;magazine.owner=&outgoing;muzzle.loaded=&magazine;} int Run(){return p.DryRun(&source,&incoming,&outgoing,&from,&to,&muzzle);} }; int main(){ {Fixture f;assert(f.Run()==1&&f.source.calls==1&&f.p.m_Called);assert(f.Run()==1&&f.source.calls==1); assert(f.from.attached==&f.incoming&&f.to.attached==&f.outgoing&&f.muzzle.loaded==&f.magazine);} {Fixture f;f.source.result=false;assert(f.Run()==-1&&f.source.calls==1);f.source.result=true;assert(f.Run()==-1&&f.source.calls==1);} for(int bad=0;bad<6;bad++){ Fixture f;if(bad==0){f.incoming.inventory=nullptr;} if(bad==1){f.a.slot=&f.other;} if(bad==2){f.from.attached=&f.foreign;} if(bad==3){f.to.attached=&f.foreign;} if(bad==4){f.muzzle.loaded=nullptr;} if(bad==5){f.magazine.owner=&f.foreign;} assert(f.Run()==-1&&f.source.calls==0&&!f.p.m_Called);} // Even a positive native query cannot pass if exact ownership changes during it. for(int changed=0;changed<3;changed++){ Fixture f;f.source.effect=[&](){if(changed==0)f.from.attached=&f.foreign;if(changed==1)f.b.slot=&f.other;if(changed==2)f.muzzle.loaded=nullptr;}; assert(f.Run()==-1&&f.source.calls==1&&f.p.m_Called);assert(f.Run()==-1&&f.source.calls==1);} {Fixture f;f.p.Stop();assert(f.Run()==-1&&f.source.calls==0);} {Fixture f;assert(f.Run()==1);f.p.Stop();assert(f.Run()==-1&&f.source.calls==1);} {Fixture f;assert(f.p.DryRun(nullptr,&f.incoming,&f.outgoing,&f.from,&f.to,&f.muzzle)==-1&&f.source.calls==0);} } ''') print('PASS: actual once-only native dry query, exact before/after slots, native refusal, shutdown; shared bounded discovery and distinct opt-in verdict') # Execute the actual final-completion selector; the step verdict alone does not # prevent the round-end branch from wrongly claiming radio delivery. completion=body(ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c','static string CompletionText(') run('#include \n#include \nusing string=std::string;\n'+completion+r''' int main(){ auto ordinary=CompletionText(false),swap=CompletionText(true); assert(ordinary.find("actual radio delivery")!=string::npos); assert(swap.find("eligibility only")!=string::npos); assert(swap.find("no transfer or radio proof")!=string::npos); assert(swap.find("actual radio delivery")==string::npos); assert(swap!=ordinary); } ''') terminal=smoke.split('if (m_ERRTestMountedAmmo)\n\t\t{',1)[1].split('if (m_ERRTestConvoy)',1)[0] assert terminal.index('CompletionText(m_ERRMountedAmmo && m_ERRMountedAmmo.SwapEligibility())') < terminal.index('ERR_StopHQPatrol()') < terminal.index('Print(mountedCompletion)') assert 'actual radio delivery' not in terminal print('PASS: actual completion selector and pre-cleanup variant capture preserve separate radio and eligibility verdicts') # Exercise the production single-pass candidate classifier, not only its log text. stage='\n'.join(body(p,x) for x in ('protected static bool Attached(', 'protected int CargoStage(')) stage=stage.replace('protected ','').replace('null','nullptr') stage=stage.replace('BaseMagazineComponent.Cast(candidate.FindComponent(BaseMagazineComponent))','candidate->magazine') stage=stage.replace('InventoryItemComponent.Cast(candidate.FindComponent(InventoryItemComponent))','candidate->inventory') stage=stage.replace('InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent))','item->inventory') stage=stage.replace('array stores','Array& stores') for typ in ('BaseMagazineComponent','InventoryStorageSlot','BaseInventoryStorageComponent'): stage=stage.replace('out '+typ+' ',typ+'*& ') for typ in ('IEntity','InventoryItemComponent','InventoryStorageSlot','BaseInventoryStorageComponent'): stage=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',stage) for name in ('candidate','magazine','item','from','storage','slot','inventoryItem','m_Muzzle'): stage=stage.replace(name+'.',name+'->') stage=stage.replace('GetMagazineWell().','GetMagazineWell()->').replace('ERR_InfantryAmmoTransfer.','ERR_InfantryAmmoTransfer::') run(r''' #include #include #include struct IEntity;struct InventoryStorageSlot;struct BaseMagazineComponent;struct InventoryItemComponent; templatestruct Array:std::vector{using std::vector::vector;bool Contains(T value){return std::find(this->begin(),this->end(),value)!=this->end();}}; struct Well{int kind=1;int Type(){return kind;}bool IsInherited(int type){return kind==type;}}; struct IEntity{BaseMagazineComponent* magazine=nullptr;InventoryItemComponent* inventory=nullptr;IEntity* truck=nullptr;}; struct BaseMagazineComponent{IEntity* owner=nullptr;Well* well=nullptr;bool used=false;int rounds=100,capacity=100; IEntity* GetOwner(){return owner;}bool IsUsed(){return used;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}Well* GetMagazineWell(){return well;}}; struct BaseInventoryStorageComponent{IEntity* owner=nullptr;IEntity* GetOwner(){return owner;}}; struct InventoryStorageSlot{IEntity* attached=nullptr;BaseInventoryStorageComponent* storage=nullptr;IEntity* GetAttachedEntity(){return attached;}BaseInventoryStorageComponent* GetStorage(){return storage;}}; struct InventoryItemComponent{InventoryStorageSlot* slot=nullptr;InventoryStorageSlot* GetParentSlot(){return slot;}}; struct Muzzle{Well* well=nullptr;Well* GetMagazineWell(){return well;}}; namespace ERR_InfantryAmmoTransfer{int checks=0;bool StoredUnder(IEntity* owner,IEntity* truck){checks++;return owner&&owner->truck==truck;}} struct Probe{Muzzle* m_Muzzle=nullptr; '''+stage+r''' }; struct Fixture{IEntity candidate,truck,storageOwner,foreign;Well well,wrong;BaseMagazineComponent magazine; BaseInventoryStorageComponent storage;InventoryStorageSlot slot,other;InventoryItemComponent item;Muzzle muzzle;Probe probe; Array stores;BaseMagazineComponent* selected=nullptr;InventoryStorageSlot* from=nullptr;BaseInventoryStorageComponent* selectedStorage=nullptr; Fixture(){wrong.kind=2;candidate.magazine=&magazine;candidate.inventory=&item;magazine.owner=&candidate;magazine.well=&well; storageOwner.truck=&truck;storage.owner=&storageOwner;slot.attached=&candidate;slot.storage=&storage;item.slot=&slot;stores={&storage};muzzle.well=&well;probe.m_Muzzle=&muzzle;} int Run(){return probe.CargoStage(&candidate,&truck,stores,selected,from,selectedStorage);} }; int main(){ {Fixture f;assert(f.Run()==4&&f.selected==&f.magazine&&f.from==&f.slot&&f.selectedStorage==&f.storage);} for(int bad=0;bad<2;bad++){Fixture f;if(bad==0){f.candidate.magazine=nullptr;}else f.magazine.owner=&f.foreign; assert(f.Run()==0&&f.from==nullptr&&f.selectedStorage==nullptr);} for(int bad=0;bad<5;bad++){Fixture f;if(bad==0){f.magazine.used=true;}if(bad==1){f.magazine.rounds=0;} if(bad==2){f.magazine.capacity=0;}if(bad==3){f.magazine.capacity=100001;}if(bad==4){f.magazine.rounds=101;} ERR_InfantryAmmoTransfer::checks=0;assert(f.Run()==1&&f.from==nullptr&&ERR_InfantryAmmoTransfer::checks==0);} for(int bad=0;bad<3;bad++){Fixture f;if(bad==0){f.magazine.well=nullptr;}if(bad==1){f.muzzle.well=nullptr;}if(bad==2){f.magazine.well=&f.wrong;} ERR_InfantryAmmoTransfer::checks=0;assert(f.Run()==2&&f.from==nullptr&&ERR_InfantryAmmoTransfer::checks==0);} for(int bad=0;bad<6;bad++){Fixture f;if(bad==0){f.candidate.inventory=nullptr;}if(bad==1){f.item.slot=nullptr;} if(bad==2){f.slot.storage=nullptr;}if(bad==3){f.stores.clear();}if(bad==4){f.storageOwner.truck=&f.foreign;}if(bad==5){f.slot.attached=&f.foreign;} assert(f.Run()==3);} // Exact counters are cumulative stages; classification neither transfers nor consumes. Fixture valid;assert(valid.Run()==4&&!valid.magazine.used&&valid.magazine.rounds==100&&valid.slot.attached==&valid.candidate); // Reusing output arguments cannot accidentally retain a prior eligible slot/storage. valid.candidate.magazine=nullptr;assert(valid.Run()==0&&valid.from==nullptr&&valid.selectedStorage==nullptr); } ''') print('PASS: actual cargo diagnostic stages separate absent/foreign magazines, used/empty/invalid rounds, well mismatch and exact truck storage/attachment without mutation')