Capture current mission, AI, map and administration development

Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
2026-10-13 22:52:53 +02:00
parent a951a96edc
commit 6a667d8deb
8104 changed files with 2124945 additions and 2061 deletions
@@ -0,0 +1,9 @@
# Original BMP accounting proof preparation
The new optional `mounted-ammo --mounted-bmp` Workbench diagnostic closes a qualification gap: the original generic fixture could finish from an armed UAZ and allowed an incomplete but bounded BMP snapshot. The new branch requires the original slot-4 WCS BMP, a complete valid armed snapshot and the exact vehicle’s naturally queued/delivered radio status, preserving original crew/root identities and detached payload checks. It retains the six-root and unarmed cargo-exclusion checks. Mixed mine/swap/courier modes are rejected.
Only this explicit Workbench branch stops unstarted hunters and town admissions before prison unlock. No production population policy, target,135-body cap, stock,180-second proof deadline or actor is replaced/refunded. The default configured convoy count is a maximum;117 committed bodies plus25 crew exceeding135 was a documented admission refusal, not a demonstrated accounting bug. Independent budget and fixture reviews are included.
Ten affected regression programs pass on unchanged inputs. The added actual-method assertions reject the old all-slot observation behavior and a missing-completeness mutation. Their failing controls and one early test-adapter compilation failure are preserved. A host-visible read-only preflight found an existing game with the private prefix idle; no native run was started. No display, input, audio or existing process was modified. Native BMP accounting and radio proof remain pending.
Original533 reference files, five sealed candidates and staged content are unchanged. The crash-start candidate remains the playable development handoff and predates only this diagnostic. This checkpoint does not rerun the complete307-program suite or package an identical ordinary mission. Manual play, physical support reliability, real multiplayer, comparative FPS and clean release remain unqualified. `next-work.json` records the single next native check after the host is free.
@@ -0,0 +1,30 @@
{
"seal.py": "f7559c290bef9bdf9fbc8b584545dea6bba857357ab76eb2449c370b5813be8e",
"next-work.json": "5a1b554391c279531d714d75f36670743290bf2b958e677e7bca2d3d1bafdee6",
"native-preflight.json": "c366735168a088ddfd61e56409fd3b5eff2fc0fde62c12f6a4fdc50e058ab0f8",
"focused-result.json": "6c44589629d989c89e3304541b29455def18e7e20a3f4d58b102d3fb7ea5ae63",
"focused-inputs.json": "b4aa5e04afe3f2b90006a853d8f5923d78907491007796f10477607380f43054",
"focused-setup-refusal.log": "e4107e65e3cb2829322e18f65680176fcadd52e2f3f75fbe8863e479c930d248",
"focused.log": "d482796985be6219ff55cbd1bd09f843c710f6ee8be06c0804fc9d736f5b1f9a",
"run-focused.py": "f3d0db051738a4c2d27e4eb5ede75d0fddda99cedc5b7b7c687c52cbd973953d",
"preservation.json": "3ebf5e70ede199542c91489a77351157e619f53006113eb42e4eb417abdff62a",
"preserve.py": "6b5e9863c86748ce1695435a73d970a34b34242f6053386075683c2f6941b971",
"baseline.json": "bd2679b8cadb508aa70c6c780e975e70408fae35ca920cb0cc9adf943f64b743",
"budget-review.json": "eed255cedb7463f0d7f723d2283bb880b062f23380ae7d056dc7296b571f832c",
"review.json": "59d5a294836894238a8e64539a3d4fa2c37c9c9e516a4d728a0b65766dce3726",
"README.md": "359b1a2a3f2bc89117b4227e06964cb088ed3d9ce7cd030b846da1ada54b2ce6",
"final-source/tools/headless_workbench.py": "b0bbb87597fe5f116e8b4fd1d60d52983935d438d3e82b972c675991fddcc971",
"final-source/tests/test_native_mounted_ammo_probe.py": "87bc8b9952be2e13fd7778af59504078e694b7bd9f0bdfea173feeec58a10f0e",
"final-source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "b7e1857b0678b3a2c71880c0f35b09da9e978f19bacf5b4e7449c893fdbe2b95",
"final-source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "7ddb634444c79ad9291d53a754dc0ed383342e36720ddaa4b7aa4bd4e7ee656d",
"proposals/erri-mounted-bmp-hook/source-manifest.json": "8054b7a04f6ae992fc00f82044738ea04f53fa4e4d334ab183e7638b755ef1e6",
"proposals/erri-mounted-bmp-hook/fix.patch": "792b3670fda0aaadbb09bbf23a7a34981129e93302372cbbea512467fb601c19",
"proposals/erri-mounted-bmp-probe/independent-review.json": "c4a435600d289d7c638b0e0b59732d6a81496e87deeadf23dbeee42a4153e78d",
"proposals/erri-mounted-bmp-probe/finding.json": "85076497ad4d68728df05cf643556dfc7ebfe6c77a84ad41a3ab4f89664bbc3d",
"proposals/erri-mounted-bmp-probe/source-manifest.json": "af0e6e99a3969ea64d3936b01f56f54c829d56754251c2af09c28710468991de",
"proposals/erri-mounted-bmp-probe/fix.patch": "d594eddef2327addad3a3977b247cd971b1fbe8713368151e0e502b8ce9d1fc3",
"proposals/erri-mounted-bmp-probe/mutation-red.log": "a877ec3e21aef3d994d82812f19c54a2120a0a316c5ddb920e079c6137d84193",
"proposals/erri-mounted-bmp-probe/baseline-red.log": "8c2a4a94132827f0b4f6aebd216f93256ccd6af34a5446e5a99921b9a8d2ec0b",
"proposals/erri-mounted-bmp-probe/adapter-compile-failure.log": "0fbdda6e7a15f318622150a45377e3974485eb0fb3dd0e164f6bded65b1d2bde",
"proposals/erri-mounted-bmp-probe/green.log": "608933baa6b1f2798ec075bbc9a66f4b347444c4806d3dde9c930d2aec1be978"
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,35 @@
{
"complete": true,
"verdict": "No demonstrated production accounting defect; intended finite shared admission ceiling.",
"read_only": true,
"tests_run": false,
"native_run": false,
"patch": null,
"facts": [
"Default convoyCount=3 gives body ceiling60+25*3=135; new original convoy needs25. At117 only18 remain, so refusal is correct.",
"CommittedBodies sums living physical noneliminated ledger strength plus outstanding receipt bodies; successful exact BindRecord subtracts outstanding count to avoid double counting.",
"GameMode refreshes physical strengths every2seconds before HQ.Tick; dead groups reduce body load, while released surviving crew correctly remain counted.",
"HQ.Tick runs hunters/objective defence/towns before AutomaticConvoy. The normal configured count is a maximum allowance, not reserved capacity or a guaranteed fleet; other forces can occupy room first.",
"Automatic startup begins after30second grace, retries every5seconds for120passes after existing admission. Capacity can become available during these retries; exhausted automatic passes are terminal by documented policy. Manual finite next-slot command remains available.",
"Current docs and actual-method tests explicitly preserve these boundaries, retry limits, receipt replay and no refunds; no tests or native were run in this audit."
],
"limitations": [
"The exact117 roster provenance belongs to failed fixture logs reviewed by parent; arithmetic alone does not attribute every actor.",
"A stable roster above110 can prevent the first default convoy for the entire retry period. This is documented shared-budget policy, not proof of an unreachable setting under all ordinary gameplay.",
"Changing count semantics, reserving convoy headroom or changing retry policy would require an explicit design change; no cap increase proposed."
],
"source_sha256": {
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "2837755fcb5fc8a174192b4d881e3c623a3bf03a90d55c0d8e4be6ab2f1fd3c3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
"addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "9a0536377f0e93f70972838de6480dfbdb44bfda198f70daaa541616eb046fd6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "47fb9c34d31bffc892b18d6d6c4e7500d10b0a681bfa73e6476a761ed3375f0d",
"addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
"docs/supply-convoys.md": "2193581f4f339879d1409fe90881ad0801e72d98d1b57325d09cd9300f11ef61",
"tests/test_convoy_budget.py": "481364c432715336825466a9ff199edeedaa2d3621daba90c0503addfa6010f7",
"tests/test_supply_budget_admission.py": "3d0e1372f89873470c336038c667df38d2e2e71b3dc2abfddd1215939c448fc5"
}
}
@@ -0,0 +1,343 @@
#ifdef WORKBENCH
// Read-only fixture access to the actual production sender; never initiates a report.
modded class ERR_HQ
{
ERR_HQUnit ERR_MountedFixtureUnit(SCR_AIGroup group)
{
if (!ERR_NativeMountedAmmoProbe.Enabled() || !group) return null;
for (int i = 0; i < m_Units.Count() && i < 256; i++)
if (m_Units[i].Group == group) return m_Units[i];
return null;
}
}
// WORKBENCH-only read access to the exact successful startup callback identity.
modded class ERR_ConvoyMineStock
{
bool ERR_FixtureMine(ERR_SupplyConvoyTask task, ERR_ConvoyVehicle original, IEntity item)
{
if (!m_Closed || task != m_Task || original != m_Original || !original || original.Entity != m_Truck) return false;
if (!m_Truck || !item || !m_Items.Contains(item) || m_Cargo.Count() > 2 || !m_Inventory || m_Inventory.GetOwner() != m_Truck) return false;
if (m_Truck.FindComponent(InventoryStorageManagerComponent) != m_Inventory) return false;
foreach (ERR_ConvoyMineCargo operation : m_Cargo)
if (operation && operation.Finished && operation.Succeeded && operation.Item == item) return true;
return false;
}
}
class ERR_NativeMountedAmmoProbe
{
protected ERR_GameMode m_Mode;
protected float m_Deadline;
protected float m_NextLog;
protected bool m_Failed;
protected bool m_Stopped;
protected bool m_FleetReady;
protected bool m_SwapEligibility;
protected bool m_MineStock;
protected bool m_BMP;
protected ref ERR_ConvoyVehicle m_BMPVehicle;
protected bool m_MountedDiagnosticPrinted;
protected ref ERR_ConvoyMineStock m_MineBatch;
protected ref ERR_ConvoyVehicle m_MineTruck;
protected InventoryStorageManagerComponent m_MineInventory;
protected ref array<IEntity> m_Mines = {};
protected ref array<ref ERR_ConvoyCargoCallback> m_PrimaryCargo = {};
protected ref ERR_NativeMountedSwapProbe m_SwapProbe;
protected ref ERR_SupplyConvoyTask m_ProofTask;
protected ERR_HQUnit m_Unit;
protected IEntity m_Root;
protected ref ERR_HQStatusReport m_Queued;
protected ref ERR_HQMountedAmmoSnapshot m_Payload;
protected ref ERR_HQRoute m_Route;
protected string m_RoutePayload;
static bool Enabled()
{
string enabled, outcome;
return Replication.IsServer() && System.GetCLIParam("errSmoke", enabled) && enabled == "1"
&& System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "mounted-ammo";
}
void ERR_NativeMountedAmmoProbe(ERR_GameMode mode, float now)
{
m_Mode = mode; m_Deadline = now + 180000;
string swap, mines, courier, bmp;
m_BMP = System.GetCLIParam("errMountedBMP", bmp) && bmp == "1";
m_MineStock = System.GetCLIParam("errMineStock", mines) && mines == "1";
m_SwapEligibility = System.GetCLIParam("errMountedSwapEligibility", swap) && swap == "1";
if (m_MineStock && (m_SwapEligibility || (System.GetCLIParam("errMountedCourier", courier) && courier == "1")))
Check(false, "mine-stock proof requires the normal mounted radio path, without swap or courier flags");
if (m_BMP && (m_MineStock || m_SwapEligibility || (System.GetCLIParam("errMountedCourier", courier) && courier == "1")))
Check(false, "BMP proof requires the normal mounted radio path, without mine, swap or courier flags");
if (m_SwapEligibility) m_SwapProbe = new ERR_NativeMountedSwapProbe();
}
bool SwapEligibility() { return m_SwapEligibility; }
static string CompletionText(bool swapEligibility)
{
if (swapEligibility) return "ERR SMOKE COMPLETE: native mounted swap eligibility only; no transfer or radio proof; explicit fixture reset";
return "ERR SMOKE COMPLETE: production fleet mounted ammunition, cargo exclusion and actual radio delivery; explicit fixture reset";
}
protected bool Check(bool condition, string detail)
{
if (condition) { Print("ERR SMOKE PASS: mounted ammo " + detail); return true; }
m_Failed = true; Print("ERR SMOKE FAIL: mounted ammo " + detail, LogLevel.ERROR); return false;
}
protected bool Same(ERR_HQMountedAmmoSnapshot a, ERR_HQMountedAmmoSnapshot b)
{
return a && b && a.Complete == b.Complete && a.Weapons == b.Weapons && a.Muzzles == b.Muzzles
&& a.Magazines == b.Magazines && a.Rounds == b.Rounds && a.Capacity == b.Capacity
&& a.Chambers == b.Chambers && a.LowMagazines == b.LowMagazines;
}
protected bool Original(ERR_ConvoyVehicle vehicle, ERR_HQUnit unit)
{
if (!vehicle || !unit || !vehicle.Registered || vehicle.Released || !vehicle.Entity || !vehicle.Group
|| vehicle.Members.Count() > 32 || unit.Group != vehicle.Group || !unit.StatusSampler || !unit.StatusSampler.OwnsRoster(vehicle.Group)) return false;
ERR_ForceRecord record = m_Mode.Forces().FindGroup(vehicle.Group);
if (!record || record.Kind != ERR_ForceKind.CONVOY || !record.Physical || record.Eliminated
|| record.SourceId != unit.StatusSampler.InitialSourceId() || record.InitialStrength != vehicle.Members.Count()
|| unit.StatusSampler.InitialStrength() != vehicle.Members.Count()) return false;
foreach (IEntity member : vehicle.Members)
{
bool original;
for (int slot = 0; slot < unit.StatusSampler.InitialStrength(); slot++)
if (unit.StatusSampler.InitialMember(slot) == member) original = true;
if (!original || !ERR_Actors.Alive(member) || ERR_Actors.Group(member) != vehicle.Group
|| !ERR_ConvoyRules.PartOf(CompartmentAccessComponent.GetVehicleIn(member), vehicle.Entity)) return false;
}
return !vehicle.Members.IsEmpty();
}
protected bool BMPReady(ERR_ConvoyVehicle vehicle, ERR_HQMountedAmmoSnapshot sample)
{
return vehicle && vehicle.Entity && vehicle.Entity.GetPrefabData()
&& vehicle.Entity.GetPrefabData().GetPrefabName() == ERR_ConvoyResources.VehiclePrefab(4)
&& sample && sample.Valid() && sample.Complete && sample.Weapons > 0 && sample.Magazines > 0
&& sample.Rounds + sample.Chambers > 0;
}
protected void Capture(ERR_HQ hq, ERR_ConvoyVehicle vehicle, float now)
{
if (m_Queued || !vehicle || !vehicle.Registered) return;
ERR_HQUnit unit = hq.ERR_MountedFixtureUnit(vehicle.Group);
if (!Original(vehicle, unit) || !unit.PendingStatus || !unit.Uplink) return;
ERR_HQStatusReport report = unit.PendingStatus;
if (!report.MountedAmmo || report.MountedAmmo.Weapons < 1 || report.MountedAmmo.Magazines < 1) return;
if (m_BMP && !BMPReady(vehicle, report.MountedAmmo)) return;
ERR_HQWatchEntry before = hq.Watch().Find(report.SourceId);
if (before && before.MessageId >= report.MessageId) return;
if (!Check(ERR_HQWatchRules.Valid(report, now) && report.SourceId == unit.StatusSampler.InitialSourceId()
&& unit.Uplink.MessageId == report.MessageId && unit.Uplink.Cursor < unit.Uplink.Nodes.Count(), "original mounted payload observed before real radio delivery")) return;
if (m_BMP) m_BMPVehicle = vehicle;
m_Unit = unit; m_Root = vehicle.Entity; m_Queued = report;
m_Payload = report.MountedAmmo.Snapshot(); m_Route = unit.Uplink; m_RoutePayload = m_Route.Payload;
Check(m_Payload != report.MountedAmmo && Same(m_Payload, report.MountedAmmo)
&& m_RoutePayload.Contains("mounted ammunition="), "queued counts copied without mutating sender or radio payload");
}
protected ERR_SupplyConvoyTask Candidate(ERR_HQ hq)
{
for (int i = 0; i < hq.Convoys().Count() && i < 3; i++)
{
ERR_SupplyConvoyTask task = ERR_SupplyConvoyTask.Cast(hq.Convoys().At(i));
if (m_MineStock && m_ProofTask && task != m_ProofTask) continue;
if (!task || task.Stopped || !task.Ready || !task.MagazinesIssued || !task.Receipt || task.Vehicles.Count() != 6 || task.Cargo.Count() > 128) continue;
bool finished = true;
foreach (ERR_ConvoyCargoCallback pending : task.Cargo) if (!pending || !pending.Finished) finished = false;
if (!finished) continue;
// If an initial report was already observed, prove that same convoy's roots.
if (m_Queued)
{
bool ownsRoot;
foreach (ERR_ConvoyVehicle vehicle : task.Vehicles) if (vehicle && vehicle.Entity == m_Root) ownsRoot = true;
if (!ownsRoot) continue;
}
if (m_MineStock)
{
// Pin the first ordinary eligible convoy; absent optional cargo must not
// select a different fleet or change the original fixed proof deadline.
if (!m_ProofTask) m_ProofTask = task;
if (!m_MineBatch) m_MineBatch = task.MineStock;
if (m_MineBatch && task.MineStock != m_MineBatch)
{ Check(false, "original pending optional mine batch replaced"); return null; }
if (!m_MineBatch || !m_MineBatch.Complete()) return null;
}
return task;
}
return null;
}
protected bool MineCustody(IEntity item, IEntity truck, array<IEntity> items)
{
if (!ERR_InfantryMineTransfer.ReadyMine(item) || !items.Contains(item)) return false;
if (!item.FindComponent(DamageManagerComponent)) return false;
InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
if (!carried) return false;
InventoryStorageSlot slot = carried.GetParentSlot();
if (!slot || slot.GetAttachedEntity() != item || !slot.GetStorage()) return false;
if (slot.GetStorage().GetSlot(slot.GetID()) != slot) return false;
return ERR_InfantryAmmoTransfer.StoredUnder(item, truck);
}
protected bool Mines(ERR_SupplyConvoyTask task, bool capture)
{
if (!m_MineStock) return true;
if (!Check(task && !task.Stopped && task.Ready && task.MagazinesIssued && task.Vehicles.Count() == 6,
"mine proof retains ready original production convoy")) return false;
ERR_ConvoyVehicle truck = task.Vehicles[1];
ERR_ConvoyMineStock batch = task.MineStock;
if (!Check(truck && truck.Entity && truck.Registered && !truck.Released && batch && batch.Complete(),
"original truck optional mine batch closed")) return false;
int count = batch.Count();
if (!Check(count >= 1 && count <= 2, "one or two exact initial PMN4 identities available; no stock fabricated")) return false;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(truck.Entity.FindComponent(InventoryStorageManagerComponent));
if (!Check(inventory && inventory.GetOwner() == truck.Entity && task.Cargo.Count() <= 128,
"original mine truck inventory and primary callback bounds")) return false;
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
if (!Check(items.Count() <= 128, "mine physical inventory enumeration bounded")) return false;
if (capture)
{
if (!Check(!m_MineBatch || m_MineBatch == batch, "same original mine batch at capture")) return false;
m_MineBatch = batch; m_MineTruck = truck; m_MineInventory = inventory;
for (int primary = 0; primary < task.Cargo.Count(); primary++) m_PrimaryCargo.Insert(task.Cargo[primary]);
}
else if (!Check(batch == m_MineBatch && truck == m_MineTruck && inventory == m_MineInventory
&& count == m_Mines.Count() && task.Cargo.Count() == m_PrimaryCargo.Count(), "original mine batch, truck, count and primary callbacks unchanged through radio delivery")) return false;
for (int cargo = 0; cargo < task.Cargo.Count(); cargo++)
if (!Check(task.Cargo[cargo] && task.Cargo[cargo].Finished && task.Cargo[cargo] == m_PrimaryCargo[cargo],
"higher-priority primary cargo remains settled and unchanged")) return false;
array<IEntity> unique = {};
for (int index = 0; index < count; index++)
{
IEntity item = batch.At(index);
if (!Check(item && !unique.Contains(item) && batch.ERR_FixtureMine(task, truck, item)
&& MineCustody(item, truck.Entity, items), "unique original callback-proved inactive PMN4 retains reciprocal truck storage custody")) return false;
unique.Insert(item);
if (capture) m_Mines.Insert(item);
else if (!Check(m_Mines[index] == item, "exact initial PMN4 snapshot identity unchanged")) return false;
}
PrintFormat("ERR MINE STOCK PROOF: capture=%1 originals=%2 primary=%3; read-only, no transfer proof", capture, count, task.Cargo.Count());
return true;
}
protected bool Fleet(ERR_HQ hq)
{
ERR_SupplyConvoyTask task = Candidate(hq);
if (!task) return false;
if (!Check(task.Vehicles.Count() == 6, "six original production roots in selected convoy")) return false;
bool armed;
for (int slot = 0; slot < 6; slot++)
{
ERR_ConvoyVehicle vehicle = task.Vehicles[slot];
if (!Check(vehicle && Original(vehicle, hq.ERR_MountedFixtureUnit(vehicle.Group)), "root retains original admitted seated crew and ledger")) return false;
bool diagnose = ((m_MineStock && slot == 1) || (m_BMP && slot == 4)) && !m_MountedDiagnosticPrinted;
if (diagnose) ERR_HQMountedAmmoSampler.BeginDiagnostic();
ERR_HQMountedAmmoSnapshot sample = ERR_HQMountedAmmoSampler.Inspect(vehicle.Entity);
if (diagnose)
{
ref ERR_HQMountedAmmoDiagnostic diagnostic = ERR_HQMountedAmmoSampler.EndDiagnostic();
m_MountedDiagnosticPrinted = true;
if (sample && !sample.Complete && diagnostic)
{
PrintFormat("ERR MOUNTED COLLECT: reasons=%1 nodes=%2 allowed=%3 managers=%4 detail=%5", diagnostic.Reasons, diagnostic.Nodes, diagnostic.Allowed, diagnostic.Managers, diagnostic.Detail);
PrintFormat("ERR MOUNTED BUDGET: structural=%1 cargo=%2", diagnostic.Structural, diagnostic.Cargo);
PrintFormat("ERR MOUNTED FIRST REJECT: prefab=%1 storage-purpose=%2", diagnostic.FirstPrefab, diagnostic.FirstPurpose);
}
}
if (!Check(sample && sample.Valid(), "native root returns bounded valid snapshot")) return false;
PrintFormat("ERR MOUNTED SAMPLE: source=%1 slot=%2 complete=%3 weapons=%4 muzzles=%5 magazines=%6", task.Receipt.SourceId, slot, sample.Complete, sample.Weapons, sample.Muzzles, sample.Magazines);
PrintFormat("ERR MOUNTED COUNTS: slot=%1 rounds=%2 capacity=%3 chambers=%4 low=%5", slot, sample.Rounds, sample.Capacity, sample.Chambers, sample.LowMagazines);
if (m_BMP && slot == 4 && !Check(BMPReady(vehicle, sample), "original slot4 BMP has complete valid armed mounted counts")) return false;
if (sample.Weapons > 0 && sample.Magazines > 0) armed = true;
if (slot == 1)
{
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(vehicle.Entity.FindComponent(InventoryStorageManagerComponent));
if (!Check(inventory != null, "original ammo truck storage present")) return false;
array<IEntity> cargo = {}; inventory.GetItems(cargo, EStoragePurpose.PURPOSE_DEPOSIT);
if (!Check(cargo.Count() <= 128, "cargo proof inspection is bounded")) return false;
int cargoWeapons;
foreach (IEntity item : cargo)
if (item && BaseWeaponComponent.Cast(item.FindComponent(BaseWeaponComponent))) cargoWeapons++;
if (!Check(cargoWeapons >= 8 && sample.Complete && sample.Weapons == 0 && sample.Magazines == 0
&& sample.Rounds == 0 && sample.Capacity == 0 && sample.Chambers == 0, "eight physical cargo weapons excluded from unarmed truck snapshot")) return false;
}
}
if (!Check(armed, "actual installed weapon magazines sampled in production convoy")) return false;
if (!Mines(task, true)) return false;
m_ProofTask = task;
PrintFormat("ERR MOUNTED SCOPE: checked=1 original convoy, deployed=%1 configured=%2; remaining fleet reliability not qualified", hq.Convoys().Count(), hq.SupplyConvoys().Target());
return true;
}
int Tick(ERR_HQ hq, float now)
{
if (m_Stopped || m_Failed) return -1;
if (!m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active()) return -1;
if (now > m_Deadline)
{
if (m_MineStock) Check(false, "fixed 180-second mine-stock and radio proof deadline; original stock or delivery unavailable");
else Check(false, "fixed 180-second proof deadline");
return -1;
}
if (!hq || !hq.Convoys() || !hq.SupplyConvoys()) return 0;
if (!CheckTarget(hq)) return -1;
if (m_ProofTask && m_ProofTask.Stopped) { Check(false, "selected original convoy retained through proof"); return -1; }
if (now >= m_NextLog)
{
PrintFormat("ERR MOUNTED WAIT: fleet=%1 ready=%2 queued=%3 remaining=%4", hq.Convoys().Count(), m_FleetReady, m_Queued != null, m_Deadline - now);
PrintFormat("ERR MOUNTED PRODUCTION: %1", hq.SupplyConvoys().Status());
m_NextLog = now + 10000;
}
if (m_SwapEligibility)
{
if (!m_ProofTask) m_ProofTask = Candidate(hq);
if (!m_ProofTask) return 0;
int eligibility = m_SwapProbe.Tick(m_Mode, hq, m_ProofTask);
if (eligibility < 0) { Check(false, "swap eligibility unavailable or native refusal; no radio-delivery qualification"); return -1; }
return eligibility;
}
// Observe queues during fleet preparation too, so fast initial deliveries are not missed.
for (int convoy = 0; convoy < hq.Convoys().Count() && convoy < 3; convoy++)
{
ERR_ConvoyTask task = hq.Convoys().At(convoy);
if (!task || (m_ProofTask && task != m_ProofTask)) continue;
for (int slot = 0; slot < task.Vehicles.Count() && slot < 6; slot++)
{
if (m_BMP && slot != 4) continue;
Capture(hq, task.Vehicles[slot], now);
}
}
if (!m_FleetReady) m_FleetReady = Fleet(hq);
if (m_Failed) return -1;
if (!m_FleetReady || !m_Queued) return 0;
ERR_HQWatchEntry delivered = hq.Watch().Find(m_Queued.SourceId);
if (!delivered || delivered.MessageId < m_Queued.MessageId)
{
if (m_Unit.PendingStatus != m_Queued && m_Unit.Uplink != m_Route)
{
Check(true, "interrupted observed transmission created no matching HQ knowledge; wait for another natural report");
Forget();
}
return 0;
}
if (!Check(delivered.MessageId == m_Queued.MessageId && delivered.MountedAmmo
&& delivered.MountedAmmo != m_Queued.MountedAmmo && delivered.MountedAmmo != m_Payload
&& Same(delivered.MountedAmmo, m_Payload) && Same(m_Queued.MountedAmmo, m_Payload), "actual HQ Watch holds separate copy of the exact queued counts")) return -1;
if (!Check(delivered.ObservedAt == m_Queued.ObservedAt && delivered.LastDeliveredAt >= delivered.ObservedAt
&& delivered.LastDeliveredAt <= now && delivered.LastDeliveredAt - delivered.ObservedAt <= 120000
&& delivered.Strength == m_Queued.Strength && delivered.Count == m_Queued.Count
&& delivered.Fit == m_Queued.Fit && m_Route.MessageId == m_Queued.MessageId
&& m_Route.Payload == m_RoutePayload, "delivered observation age, roster counts and radio payload preserved")) return -1;
if (!Check(hq.ERR_MountedFixtureUnit(m_Unit.Group) == m_Unit && ERR_Actors.Alive(m_Root), "original source and root retained through delivery")) return -1;
if (m_BMP && !Check(m_ProofTask && m_ProofTask.Vehicles.Count() == 6
&& m_BMPVehicle && m_ProofTask.Vehicles[4] == m_BMPVehicle && m_BMPVehicle.Entity == m_Root
&& Original(m_BMPVehicle, m_Unit) && BMPReady(m_BMPVehicle, m_Payload),
"same original slot4 BMP and complete armed queued snapshot retained through actual radio delivery")) return -1;
if (!Mines(m_ProofTask, false)) return -1;
return 1;
}
protected bool CheckTarget(ERR_HQ hq)
{
if (hq.SupplyConvoys().Target() == 3 && hq.Convoys().Count() <= 3) return true;
return Check(false, "unchanged default three-convoy production target");
}
protected void Forget() { m_BMPVehicle = null; m_Unit = null; m_Root = null; m_Queued = null; m_Payload = null; m_Route = null; m_RoutePayload = string.Empty; }
void Stop()
{
m_Stopped = true; if (m_SwapProbe) m_SwapProbe.Stop();
m_ProofTask = null; m_MineBatch = null; m_MineTruck = null; m_MineInventory = null;
m_Mines.Clear(); m_PrimaryCargo.Clear(); Forget();
}
}
#endif
@@ -0,0 +1,245 @@
"""Execute native mounted probe proof/termination methods; inspect read-only setup boundaries."""
import re, ast, os
from pathlib import Path
from policy_harness import ROOT, body, run
ROOT=Path(os.environ.get('ERR_NATIVE_SWAP_ROOT',ROOT))
p=Path(os.environ.get('ERR_NATIVE_MOUNTED_AMMO_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c'))
s=p.read_text();smoke=Path(os.environ.get('ERR_NATIVE_SMOKE_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')).read_text()
runner=Path(os.environ.get('ERR_NATIVE_MOUNTED_RUNNER',ROOT/'tools/headless_workbench.py')).read_text()
assert s.startswith('#ifdef WORKBENCH') and s.rstrip().endswith('#endif')
for forbidden in ('Spawn(', 'SpawnEntity', 'TrySpawn', '.Ingest(', '.Advance(', '.Dispatch(', '.BindVehicle(', '.Sample(',
'.SetOrigin(', '.SetAmmoCount(', '.Kill(', '.SetHealth(', 'NextStatus =', 'PendingStatus =', 'Uplink =', 'new ERR_HQStatusReport'):
assert forbidden not in s,forbidden
assert 'checked=1 original convoy, deployed=%1 configured=%2' in s
assert 'if (!task || (m_ProofTask && task != m_ProofTask)) continue' in s
assert 'now + 180000' in s and 'now > m_Deadline' in s
assert s.index('Capture(hq, task.Vehicles[slot], now)') < s.index('if (!m_FleetReady) m_FleetReady = Fleet(hq)')
for evidence in ('cargoWeapons >= 8 && sample.Complete && sample.Weapons == 0', 'sample.Magazines == 0', 'sample.Capacity == 0',
'cargo.Count() <= 128', 'sample.Weapons > 0 && sample.Magazines > 0', 'Original(vehicle,',
'record.SourceId != unit.StatusSampler.InitialSourceId()', 'unit.StatusSampler.InitialMember(slot)',
'vehicle.Members.Count() > 32', 'm_Units.Count() && i < 256'):
assert evidence in s,evidence
start=smoke.split('if (m_ERRTestMountedAmmo)\n\t\t\t{',1)[1].split('\n\t\t\tif (m_ERRTestConvoy)',1)[0]
assert start.index('if (!ERR_Check(UnlockPrison(') < start.index('new ERR_NativeMountedAmmoProbe(this, now)')
assert start.index('mountedObserverDamage.EnableDamageHandling(false)') < start.index('UnlockPrison(')
assert 'm_ERRSmokeStep = 3000' in start and 'm_ERRMountedAmmo.Stop()' in smoke
assert 'm_ERRSmokeStep == 3001' in smoke and 'm_ERRMountedAmmo.Tick(ERR_HQ.Cast(Command()), now)' in smoke
# Execute only the selector condition AST, never the process-launching runner.
node=next(n for n in ast.parse(runner).body if isinstance(n,ast.If) and "mounted-ammo" in ast.unparse(n.test) and "mounted_swap_eligibility" not in ast.unparse(n.test) and "mounted_courier" not in ast.unparse(n.test))
condition=compile(ast.Expression(node.test),'<selector>','eval')
from types import SimpleNamespace
for project,rounds,timeout,bad in [('chat',1,360,False),('chat',1,359,True),('core',1,360,True),('chat',2,360,True)]:
assert eval(condition,{'a':SimpleNamespace(smoke='mounted-ammo',project=project,rounds=rounds,timeout=timeout)})==bad
code='\n'.join(body(p,x) for x in ('protected bool Same(', 'int Tick(', 'protected bool CheckTarget(', 'protected void Forget(', 'void Stop('))
code=code.replace('string.Empty','string{}').replace('protected ','').replace('null','nullptr').replace('ERR_GameMode.Get()', 'ERR_GameMode::Get()').replace('ERR_Actors.Alive(', 'ERR_Actors::Alive(')
for t in ('ERR_HQMountedAmmoSnapshot','ERR_HQ','ERR_ConvoyTask','ERR_HQWatchEntry'):
code=re.sub(r'\b'+t+r' (?=\w)',t+'* ',code)
for var in ('a','b','hq','m_Mode','task','m_Queued','delivered','m_Unit','m_Route','m_ProofTask','m_SwapProbe','m_BMPVehicle'):
code=re.sub(r'\b'+var+r'\.',var+'->',code)
for call in ('Convoys()','SupplyConvoys()','Watch()'):code=code.replace(call+'.',call+'->')
run(r'''
#include <cassert>
#include <string>
#include <vector>
using string=std::string;
struct ERR_HQMountedAmmoSnapshot{bool Complete=true;int Weapons=1,Muzzles=1,Magazines=1,Rounds=80,Capacity=100,Chambers=1,LowMagazines=0;};
struct Report{string SourceId="source";int MessageId=7,Strength=3,Count=3,Fit=3;float ObservedAt=1000;ERR_HQMountedAmmoSnapshot* MountedAmmo=nullptr;};
struct ERR_HQWatchEntry:Report{float LastDeliveredAt=2000;};
struct Root{bool alive=true;};struct ERR_Actors{static bool Alive(Root* r){return r&&r->alive;}};
struct Route{int MessageId=7;string Payload="original";};struct Unit{int Group=1;Report* PendingStatus=nullptr;Route* Uplink=nullptr;};
struct ERR_GameMode{bool active=true;static inline ERR_GameMode* current=nullptr;static ERR_GameMode* Get(){return current;}bool Active(){return active;}};
template<class T>struct Arr:std::vector<T>{int Count(){return this->size();}void Clear(){this->clear();}};
struct Escort{Root* Entity=nullptr;};struct ERR_ConvoyTask{bool Stopped=false;Arr<Escort*> Vehicles;};struct Pool{ERR_ConvoyTask* task=nullptr;int count=3;int Count(){return count;}ERR_ConvoyTask* At(int){return task;}};
struct Supply{int target=3;int Target(){return target;}string Status(){return "fixture production status";}};struct Watch{ERR_HQWatchEntry* entry=nullptr;ERR_HQWatchEntry* Find(string){return entry;}};
struct ERR_HQ{Pool pool;Supply supply;struct Watch watch;Unit* unit=nullptr;
Pool* Convoys(){return &pool;}Supply* SupplyConvoys(){return &supply;}struct Watch* Watch(){return &watch;}Unit* ERR_MountedFixtureUnit(int){return unit;}};
template<class... T>void PrintFormat(T...){}
struct SwapProbe{int result=1,calls=0,stops=0;int Tick(ERR_GameMode*,ERR_HQ*,ERR_ConvoyTask*){calls++;return result;}void Stop(){stops++;}};
struct Probe{bool m_BMP=false,original=true;Escort*m_BMPVehicle=nullptr;bool Original(Escort*,Unit*){return original;}bool BMPReady(Escort*,ERR_HQMountedAmmoSnapshot*s){return s&&s->Complete&&s->Weapons>0&&s->Magazines>0&&s->Rounds+s->Chambers>0;}bool m_MineStock=false,mineProof=true;int mineChecks=0;void*m_MineBatch=nullptr,*m_MineTruck=nullptr,*m_MineInventory=nullptr;Arr<int>m_Mines,m_PrimaryCargo;bool Mines(ERR_ConvoyTask*,bool){mineChecks++;return !m_MineStock||mineProof;}bool m_SwapEligibility=false;SwapProbe* m_SwapProbe=nullptr;ERR_ConvoyTask* candidate=nullptr;ERR_ConvoyTask* Candidate(ERR_HQ*){return candidate;}bool m_Stopped=false,m_Failed=false,m_FleetReady=false,fleet=true;float m_Deadline=180000,m_NextLog=0;
ERR_ConvoyTask* m_ProofTask=nullptr;ERR_GameMode* m_Mode=nullptr;Report* m_Queued=nullptr;ERR_HQMountedAmmoSnapshot* m_Payload=nullptr;Route* m_Route=nullptr;
int captures=0;string m_RoutePayload="original";Unit* m_Unit=nullptr;Root* m_Root=nullptr;
bool Check(bool b,string){if(!b)m_Failed=true;return b;}bool Fleet(ERR_HQ*){return fleet;}void Capture(ERR_HQ*,Escort*,float){captures++;}
'''+code+r'''
};
struct Setup{ERR_GameMode mode;ERR_HQ hq;Probe p;Root root;Unit unit;Route route;Report queued;ERR_HQWatchEntry delivered;
ERR_HQMountedAmmoSnapshot payload,original,received;
Setup(){ERR_GameMode::current=&mode;p.m_Mode=&mode;p.m_Queued=&queued;p.m_Payload=&payload;p.m_Route=&route;p.m_Unit=&unit;p.m_Root=&root;
unit.PendingStatus=&queued;unit.Uplink=&route;queued.MountedAmmo=&original;delivered.MountedAmmo=&received;hq.watch.entry=&delivered;hq.unit=&unit;}
};
int main(){
// BMP delivery cannot succeed through a different slot/root, lost ownership or incomplete payload.
for(int fault=0;fault<6;fault++){Setup s;ERR_ConvoyTask task;Escort bmp,other;Root replacement;
task.Vehicles.resize(6);bmp.Entity=&s.root;task.Vehicles[4]=&bmp;s.p.m_BMP=true;s.p.m_BMPVehicle=&bmp;s.p.m_ProofTask=&task;s.hq.pool.task=&task;
if(fault==1)task.Vehicles[4]=&other;if(fault==2)bmp.Entity=&replacement;if(fault==3)s.p.original=false;
if(fault==4){s.payload.Complete=false;s.original.Complete=false;s.received.Complete=false;}
if(fault==5){s.payload.Rounds=0;s.payload.Chambers=0;s.original=s.payload;s.received=s.payload;}
assert(s.p.Tick(&s.hq,3000)==(fault==0?1:-1));assert(s.p.captures==3); // exactly slot4 per observed task, never other slots
}
{Setup s;s.p.m_MineStock=true;s.p.mineProof=false;assert(s.p.Tick(&s.hq,3000)==-1&&s.p.mineChecks==1);}
{Setup s;s.p.m_MineStock=true;s.p.m_Mines.push_back(1);s.p.m_PrimaryCargo.push_back(2);s.p.m_MineBatch=&s;s.p.Stop();assert(s.p.m_Mines.empty()&&s.p.m_PrimaryCargo.empty()&&!s.p.m_MineBatch);}
{Setup s;SwapProbe dry;ERR_ConvoyTask task;s.p.m_SwapEligibility=true;s.p.m_SwapProbe=&dry;s.p.candidate=&task;
s.hq.watch.entry=nullptr;s.p.m_Queued=nullptr;assert(s.p.Tick(&s.hq,3000)==1&&dry.calls==1&&s.p.captures==0);
assert(!s.p.m_FleetReady&&s.p.m_ProofTask==&task);s.p.Stop();assert(dry.stops==1);}
{Setup s;SwapProbe dry;s.p.m_SwapEligibility=true;s.p.m_SwapProbe=&dry;
assert(s.p.Tick(&s.hq,3000)==0&&dry.calls==0&&s.p.captures==0);assert(s.p.Tick(&s.hq,180001)==-1&&dry.calls==0);}
{Setup s;assert(s.p.Tick(&s.hq,3000)==1&&!s.p.m_Failed);}
for(int field=0;field<8;field++){Setup s;if(field==0)s.received.Complete=false;if(field==1)s.received.Weapons++;
if(field==2)s.received.Muzzles++;if(field==3)s.received.Magazines++;if(field==4)s.received.Rounds++;
if(field==5)s.received.Capacity++;if(field==6)s.received.Chambers++;if(field==7)s.received.LowMagazines++;
assert(s.p.Tick(&s.hq,3000)==-1&&s.p.m_Failed);}
for(int fault=0;fault<12;fault++){Setup s;
if(fault==0)s.delivered.MountedAmmo=&s.original;if(fault==1)s.delivered.MountedAmmo=&s.payload;
if(fault==2)s.delivered.ObservedAt=999;if(fault==3)s.delivered.LastDeliveredAt=999;
if(fault==4)s.delivered.LastDeliveredAt=3001;if(fault==5)s.delivered.LastDeliveredAt=122000;
if(fault==6)s.delivered.Count--;if(fault==7)s.delivered.Fit--;if(fault==8)s.route.Payload="changed";
if(fault==9)s.route.MessageId++;if(fault==10)s.root.alive=false;if(fault==11)s.hq.unit=nullptr;
assert(s.p.Tick(&s.hq,3000)==-1);}
{Setup s;s.delivered.MessageId=6;assert(s.p.Tick(&s.hq,3000)==0);s.delivered.MessageId=8;assert(s.p.Tick(&s.hq,3000)==-1);}
{Setup s;s.p.fleet=false;assert(s.p.Tick(&s.hq,3000)==0);assert(s.p.Tick(&s.hq,180001)==-1);assert(s.p.m_Deadline==180000);}
{Setup s;s.hq.watch.entry=nullptr;s.unit.PendingStatus=nullptr;s.unit.Uplink=nullptr;assert(s.p.Tick(&s.hq,3000)==0);
assert(!s.p.m_Queued&&!s.p.m_Stopped&&s.p.m_Deadline==180000);}
{Setup s;s.p.m_Queued=nullptr;assert(s.p.Tick(&s.hq,3000)==0);}
{Setup s;s.hq.supply.target=2;assert(s.p.Tick(&s.hq,3000)==-1);}
{Setup s;s.hq.pool.count=4;assert(s.p.Tick(&s.hq,3000)==-1);}
{Setup s;s.mode.active=false;assert(s.p.Tick(&s.hq,3000)==-1);}
{Setup s;s.p.Stop();s.p.Stop();assert(!s.p.m_Queued&&!s.p.m_Payload&&!s.p.m_Route&&!s.p.m_Root&&!s.p.m_Unit);assert(s.p.Tick(&s.hq,3000)==-1);}
}
'''.replace(';if(', ';\n if('))
print('PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector')
candidate=body(p,'protected ERR_SupplyConvoyTask Candidate(').replace('protected ','').replace('null','nullptr')
candidate=candidate.replace('ERR_SupplyConvoyTask.Cast(hq.Convoys().At(i))','hq->Convoys()->At(i)')
candidate=candidate.replace('ERR_HQ hq','ERR_HQ* hq').replace('ERR_SupplyConvoyTask ', 'ERR_SupplyConvoyTask* ')
candidate=candidate.replace('foreach (','for (').replace('hq.Convoys().','hq->Convoys()->')
for var in ('task','pending','vehicle'):candidate=candidate.replace(var+'.',var+'->')
candidate=candidate.replace('bool ownsRoot;', 'bool ownsRoot=false;').replace('m_MineBatch.','m_MineBatch->')
run(r'''
#include <cassert>
#include <vector>
template<class T>struct Arr:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}void Clear(){this->clear();}};
struct Vehicle{int Entity=0;};using ERR_ConvoyVehicle=Vehicle*;
struct Cargo{bool Finished=true;};using ERR_ConvoyCargoCallback=Cargo*;
struct MineBatch{bool Complete(){return true;}};
struct ERR_SupplyConvoyTask{MineBatch*MineStock=nullptr;bool Stopped=false,Ready=true,MagazinesIssued=true,Receipt=true;Arr<Vehicle*> Vehicles;Arr<struct Cargo*> Cargo;
ERR_SupplyConvoyTask(){Vehicles.resize(6);}};
struct Pool{Arr<ERR_SupplyConvoyTask*> tasks;int reads=0;int Count(){return tasks.Count();}ERR_SupplyConvoyTask* At(int i){reads++;return tasks[i];}};
struct ERR_HQ{Pool pool;Pool* Convoys(){return &pool;}};
struct Probe{bool m_MineStock=false;ERR_SupplyConvoyTask*m_ProofTask=nullptr;MineBatch*m_MineBatch=nullptr;bool Check(bool yes,const char*){return yes;}bool m_Queued=false;int m_Root=42;
'''+candidate+r'''
};
int main(){
ERR_HQ hq;Probe p;ERR_SupplyConvoyTask first,second,third,fourth;Vehicle owned;owned.Entity=42;
assert(p.Candidate(&hq)==nullptr);
hq.pool.tasks={&first};assert(p.Candidate(&hq)==&first); // one actual convoy sufficient
hq.pool.tasks={&first,&second};first.Ready=false;assert(p.Candidate(&hq)==&second);
first.Ready=true;p.m_Queued=true;second.Vehicles[3]=&owned;assert(p.Candidate(&hq)==&second); // exact captured sender's task
second.Vehicles[3]=nullptr;assert(p.Candidate(&hq)==nullptr);
p.m_Queued=false;hq.pool.tasks={&first};
for(int failure=0;failure<7;failure++){
ERR_SupplyConvoyTask t;Cargo pending;hq.pool.tasks={&t};
if(failure==0)t.Stopped=true;
if(failure==1)t.MagazinesIssued=false;
if(failure==2)t.Receipt=false;
if(failure==3)t.Vehicles.resize(5);
if(failure==4){pending.Finished=false;t.Cargo={&pending};}
if(failure==5)t.Cargo={nullptr};
if(failure==6)t.Cargo.resize(129,&pending);
assert(p.Candidate(&hq)==nullptr);
}
first.Ready=false;second.Ready=false;third.Ready=false;hq.pool.tasks={&first,&second,&third,&fourth};hq.pool.reads=0;
assert(p.Candidate(&hq)==nullptr&&hq.pool.reads==3); // no fourth candidate traversal
}
''')
print('PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound')
# Execute the exact Capture and BMPReady methods; native identity/roster/watch
# boundaries are explicit doubles, while the snapshot validator has its own full suite.
selected=[]
if 'protected bool BMPReady(' in s: selected.append(body(p,'protected bool BMPReady('))
selected.append(body(p,'protected void Capture('))
capture='\n'.join(selected).replace('protected ','').replace('null','nullptr')
for ns in ('ERR_ConvoyResources','ERR_HQWatchRules'):
capture=capture.replace(ns+'.',ns+'::')
for t in ('ERR_ConvoyVehicle','ERR_HQMountedAmmoSnapshot','ERR_HQ','ERR_HQUnit','ERR_HQStatusReport','ERR_HQWatchEntry'):
capture=re.sub(r'\b'+t+r' (?=\w)',t+'* ',capture)
for v in ('vehicle','sample','hq','unit','report','before','m_Route','m_Payload'):
capture=re.sub(r'\b'+v+r'\.',v+'->',capture)
for x in ('Entity','MountedAmmo','StatusSampler','Uplink'):
capture=capture.replace('.'+x+'.','.'+x+'->').replace('->'+x+'.','->'+x+'->')
for x in ('GetPrefabData()','Watch()'):
capture=capture.replace(x+'.',x+'->')
capture=capture.replace('unit->Uplink->Nodes.Count()', 'int(unit->Uplink->Nodes.size())')
run(r'''
#include <cassert>
#include <string>
#include <vector>
struct string:std::string{using std::string::string;string(const std::string&s):std::string(s){}bool Contains(const char*s){return find(s)!=npos;}};
struct Prefab{string name="bmp";string GetPrefabName(){return name;}};
struct Entity{Prefab prefab;Prefab*GetPrefabData(){return &prefab;}};
struct ERR_ConvoyResources{static string VehiclePrefab(int slot){assert(slot==4);return "bmp";}};
struct ERR_HQMountedAmmoSnapshot{bool Complete=true,valid=true;int Weapons=3,Magazines=3,Rounds=80,Chambers=1;
bool Valid(){return valid;}ERR_HQMountedAmmoSnapshot*Snapshot(){return new ERR_HQMountedAmmoSnapshot(*this);}};
struct ERR_ConvoyVehicle{struct Entity*Entity=nullptr;bool Registered=true;int Group=1;};
struct ERR_HQStatusReport{ERR_HQMountedAmmoSnapshot*MountedAmmo=nullptr;int MessageId=7;string SourceId="source";};
struct ERR_HQWatchEntry{int MessageId=6;};
struct Sampler{string InitialSourceId(){return "source";}};
struct Route{int MessageId=7,Cursor=0;std::vector<int>Nodes={1,2};string Payload="mounted ammunition=original";};
struct ERR_HQUnit{ERR_HQStatusReport*PendingStatus=nullptr;Route*Uplink=nullptr;Sampler*StatusSampler=nullptr;};
struct Watch{ERR_HQWatchEntry*entry=nullptr;ERR_HQWatchEntry*Find(string){return entry;}};
struct ERR_HQ{ERR_HQUnit*unit=nullptr;struct Watch watch;ERR_HQUnit*ERR_MountedFixtureUnit(int){return unit;}struct Watch*Watch(){return &watch;}};
struct ERR_HQWatchRules{static bool Valid(ERR_HQStatusReport*,float){return true;}};
struct Probe{bool m_BMP=true,original=true,failed=false;ERR_ConvoyVehicle*m_BMPVehicle=nullptr;ERR_HQStatusReport*m_Queued=nullptr;ERR_HQUnit*m_Unit=nullptr;Entity*m_Root=nullptr;ERR_HQMountedAmmoSnapshot*m_Payload=nullptr;Route*m_Route=nullptr;string m_RoutePayload;
bool Original(ERR_ConvoyVehicle*,ERR_HQUnit*){return original;}bool Check(bool x,const char*){if(!x)failed=true;return x;}
bool Same(ERR_HQMountedAmmoSnapshot*a,ERR_HQMountedAmmoSnapshot*b){return a->Complete==b->Complete&&a->Weapons==b->Weapons&&a->Magazines==b->Magazines&&a->Rounds==b->Rounds&&a->Chambers==b->Chambers;}
'''+capture+r'''
};
struct Setup{Probe p;Entity root;ERR_ConvoyVehicle vehicle;ERR_HQ hq;ERR_HQUnit unit;Sampler sampler;Route route;ERR_HQStatusReport report;ERR_HQMountedAmmoSnapshot sample;
Setup(){vehicle.Entity=&root;hq.unit=&unit;unit.PendingStatus=&report;unit.Uplink=&route;unit.StatusSampler=&sampler;report.MountedAmmo=&sample;}};
int main(){
{Setup s;s.root.prefab.name="uaz";s.p.Capture(&s.hq,&s.vehicle,1000);assert(!s.p.m_Queued&&!s.p.m_Payload);}
for(int bad=0;bad<6;bad++){Setup s;if(bad==0)s.sample.Complete=false;if(bad==1)s.sample.valid=false;
if(bad==2)s.sample.Weapons=0;if(bad==3)s.sample.Magazines=0;if(bad==4){s.sample.Rounds=0;s.sample.Chambers=0;}if(bad==5)s.p.original=false;
s.p.Capture(&s.hq,&s.vehicle,1000);assert(!s.p.m_Queued&&!s.p.m_BMPVehicle);}
{Setup s;s.p.Capture(&s.hq,&s.vehicle,1000);assert(s.p.m_Queued==&s.report&&s.p.m_BMPVehicle==&s.vehicle&&s.p.m_Root==&s.root);
assert(s.p.m_Payload!=&s.sample&&s.p.m_Payload->Complete&&s.p.m_Route==&s.route&&!s.p.failed);
s.sample.Rounds=0;assert(s.p.m_Payload->Rounds==80);}
{Setup s;s.p.m_BMP=false;s.root.prefab.name="uaz";s.sample.Complete=false;s.p.Capture(&s.hq,&s.vehicle,1000);assert(s.p.m_Queued==&s.report&&!s.p.m_BMPVehicle);}
}
'''.replace(';if(', ';\n if('))
node=next(n for n in ast.parse(runner).body if isinstance(n,ast.If) and ast.unparse(n.test).startswith('a.mounted_bmp and'))
condition=compile(ast.Expression(node.test),'<bmp-selector>','eval')
for field in [None,'smoke','project','rounds','timeout','mine_stock','mounted_courier','mounted_swap_eligibility']:
values=dict(mounted_bmp=True,smoke='mounted-ammo',project='chat',rounds=1,timeout=360,mine_stock=False,mounted_courier=False,mounted_swap_eligibility=False)
if field:values[field]={'smoke':'convoy','project':'core','rounds':2,'timeout':359}.get(field,True)
assert eval(condition,{'a':SimpleNamespace(**values)})==(field is not None)
assert "if a.mounted_bmp: command += ['-errMountedBMP', '1']" in runner
print('PASS: actual BMP capture requires complete armed exact original resource; pinned delivery/slot checks and isolated CLI flag')
# WORKBENCH isolation changes only unrelated services before the real unlock.
assert start.index('!mixedBMP && StartMode() == 0 && Phase() == ERR_Phase.PRISON') < start.index('bmpHQ.ERR_IsolateMountedBMP()') < start.index('UnlockPrison(')
assert all(x in start for x in ('errMineStock','errMountedSwapEligibility','errMountedCourier'))
hook_path=Path(os.environ.get('ERR_NATIVE_SMOKE_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c'))
hook=body(hook_path,'bool ERR_IsolateMountedBMP(').replace('ERR_NativeMountedAmmoProbe.','ERR_NativeMountedAmmoProbe::').replace('System.','System::').replace('ERR_GameMode.','ERR_GameMode::').replace('ERR_Phase.','ERR_Phase::')
for v in ('m_Mode','m_Hunters','m_Towns'):hook=hook.replace(v+'.',v+'->')
run(r'''
#include <cassert>
#include <string>
using string=std::string;
struct ERR_NativeMountedAmmoProbe{static inline bool enabled=true;static bool Enabled(){return enabled;}};
struct System{static inline string flag="1";static bool GetCLIParam(string key,string&out){assert(key=="errMountedBMP");out=flag;return !flag.empty();}};
struct ERR_Phase{static constexpr int PRISON=1;};
struct ERR_GameMode{int start=0,phase=1;static inline ERR_GameMode*current=nullptr;static ERR_GameMode*Get(){return current;}int StartMode(){return start;}int Phase(){return phase;}};
struct Service{int deployed=0,stops=0;int Deployed(){return deployed;}void Stop(){stops++;}};
struct HQ{ERR_GameMode*m_Mode=nullptr;Service*m_Hunters=nullptr,*m_Towns=nullptr;
'''+hook+r'''
};
int main(){for(int fault=0;fault<10;fault++){
ERR_GameMode mode,other;ERR_GameMode::current=&mode;Service hunters,towns;HQ h;h.m_Mode=&mode;h.m_Hunters=&hunters;h.m_Towns=&towns;
ERR_NativeMountedAmmoProbe::enabled=true;System::flag="1";
if(fault==1)ERR_NativeMountedAmmoProbe::enabled=false;if(fault==2)System::flag="";if(fault==3)System::flag="0";
if(fault==4)ERR_GameMode::current=&other;if(fault==5)mode.start=1;if(fault==6)mode.phase=2;
if(fault==7)hunters.deployed=1;if(fault==8)h.m_Hunters=nullptr;if(fault==9)h.m_Towns=nullptr;
assert(h.ERR_IsolateMountedBMP()==(fault==0));assert(hunters.stops==(fault==0?1:0)&&towns.stops==(fault==0?1:0));
}}
'''.replace(';if(', ';\n if('))
print('PASS: actual opt-in pre-unlock isolation refuses wrong mode/phase/flag and existing hunters; no baseline service changes')
@@ -0,0 +1,256 @@
#!/usr/bin/env python3
"""Run bounded native Workbench smoke tests inside a windowless Gamescope display.
Requires Linux, gamescope, Proton, and a disposable COPY of a working Tools compat prefix.
No desktop rules or existing Wine processes are changed. This is not a dedicated server.
"""
import argparse, fcntl, json, os, shutil, signal, subprocess, time
from pathlib import Path
from native_provenance import snapshot, persist, bindings, seal_run
from headless_game import assert_prefix_idle, cleanup_owned_run
from external_addons import policy as external_policy, prepare_profile, verify_profile
ROOT = Path(__file__).resolve().parents[1]
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--steam', type=Path, default=Path.home()/'.local/share/Steam')
p.add_argument('--external-addons', type=Path, help='Installed RHS/WCS/BMP source root; expose only audited closure in a separate Chat profile')
p.add_argument('--compat', type=Path, required=True, help='Disposable cloned Proton compatdata directory outside Steam')
p.add_argument('--profile', type=Path, required=True, help='Separate disposable successor Workbench profile')
p.add_argument('--smoke', choices=['crash-start', 'crash-geometry', 'normal-escape-route', 'escape-route', 'optional-site-skip', 'infantry-combat', 'medical-combat', 'hunter-faction', 'unconscious-camera', 'objective-map', 'town-garrisons', 'site-garrisons', 'radio-interaction', 'enemy-loadout', 'aggression', 'air-logistics', 'air-assault', 'air-recon', 'airfield-markers', 'opening-tools', 'mortar-station', 'generated-sites', 'hq-local-handoff', 'infantry-transfer', 'hq-body', 'convoy', 'supply-convoys', 'supply-travel', 'mounted-ammo', 'alarm-hearing', 'hq-memory', 'hq-awareness', 'aircraft-field', 'aircraft-route', 'native-end-active', 'native-end-preparing', 'aircraft-control', 'aircraft-cancel', 'aircraft-translate', 'map-ownership', 'mortar-refresh', 'mortar-salvo', 'mortar-courier', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'mortar-expiry', 'mortar-transfer', 'mortar-fire', 'patrol-hq', 'victory', 'lost-helicopter', 'player-death', 'radio-network', 'hq-response', 'mortar-inventory', 'startup-failure', 'site-survey', 'cache-loss', 'extraction-capacity', 'early-helicopter-loss', 'extraction-startup-failure', 'extraction-boundary-failure', 'transport-loss', 'transport-survey', 'lifecycle', 'objective-ui', 'recovery', 'prisoner-kit', 'medical', 'casualty-load', 'casualty-direct', 'casualty-bench', 'casualty-remove', 'environment', 'environment-restart', 'patrols', 'radio-document-loss', 'radio-document-loss-partial', 'guard-cancel', 'casualty-service'], default='victory')
p.add_argument('--trace-random-radius', action='store_true', help='Workbench-only read-only zero-radius caller traces; one normal Chat round, capped at sixteen records')
p.add_argument('--maintenance-refuel', action='store_true', help='Opt-in normal-route check: original held Southern fuel can transfers finite fuel through its native UAZ action; one arranged tank depletion, no stock creation')
p.add_argument('--mounted-swap-eligibility', action='store_true', help='Read-only mounted-ammo variant: one exact finite cargo/mounted magazine CanSwap call; no transfer or radio proof')
p.add_argument('--mounted-bmp', action='store_true', help='Read-only original BMP slot4 complete mounted counts and its natural HQ radio delivery; isolates unrelated opening hunters before unlock')
p.add_argument('--mine-stock', action='store_true', help='Read-only mounted-ammo check of exact callback-proved finite PMN4 cargo before and after natural radio delivery')
p.add_argument('--mounted-courier', action='store_true', help='Mounted-ammo variant: intentionally deplete one original installed magazine, then require natural HQ radio, finite pickup, native exchange and original-seat return')
p.add_argument('--mounted-intercept', action='store_true', help='After convoy driving, two synthetic witness samples exercise real HQ radio/planning and original escort detour/hold/expiry/resume')
p.add_argument('--convoy-cover', action='store_true', help='After convoy driving, arrange the existing prisoner to verify native sighting/radio HOLD and RESUME')
p.add_argument('--field-terrain-audit', action='store_true', help='After a fixed aircraft-field survey refusal, log one read-only 1681-node coarse terrain grid; never selects or qualifies a corridor')
p.add_argument('--field-service-cancel', action='store_true', help='Explicit aircraft-field variant: Stop the original retained service during measured cruise; requires physical cancellation landing')
p.add_argument('--route-service-cancel', action='store_true', help='Explicit aircraft-route variant: stop the retained service after actual airborne translation and require controlled cancellation landing')
p.add_argument('--station-teardown-diagnostics', action='store_true', help='Opt-in bounded native deletion diagnostics; preserves all validation errors')
p.add_argument('--flight-autohover', action='store_true', help='Opt-in owned native helicopter autohover experiment; requires Core powered-flight and actor-local action inputs')
p.add_argument('--flight-action-inputs', action='store_true', help='Experimental exact-AI ActionManager inputs; Core powered-flight fixture only')
p.add_argument('--flight-input-diagnostics', action='store_true', help='Opt-in read-only powered-flight input/application and native rotor signal observations')
p.add_argument('--recon-takeover-only', action='store_true', help='Air-recon fixture: only native faction handover/release and explicit aircraft deletion')
p.add_argument('--body-recovery-only', action='store_true', help='Air-logistics fixture: only physical corpse inspection and returned document intelligence')
p.add_argument('--rounds', type=int, default=2)
p.add_argument('--timeout', type=int, default=360)
p.add_argument('--project', choices=['core', 'chat'], default='chat', help='Diagnostic fixture family (both load the combined mod)')
a = p.parse_args()
if a.smoke == 'crash-start' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 240): p.error('crash-start requires Chat, one round and timeout at least 240 seconds')
if a.smoke == 'crash-geometry' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 180): p.error('crash-geometry requires Chat, one round and timeout at least180 seconds')
if a.trace_random_radius and (a.smoke != 'normal-escape-route' or a.project != 'chat' or a.rounds != 1 or a.timeout < 420): p.error('--trace-random-radius requires Chat normal-escape-route, one round and timeout at least 420 seconds')
if a.smoke == 'objective-map' and (a.project != 'core' or a.rounds != 1): p.error('objective-map requires --project core --rounds 1')
if a.smoke == 'unconscious-camera' and a.project != 'core': p.error('unconscious-camera requires --project core to keep the general smoke fixture inactive')
if a.mine_stock:
if a.smoke != 'mounted-ammo' or a.project != 'chat' or a.rounds != 1 or a.timeout < 360:
p.error('--mine-stock requires --smoke mounted-ammo --project chat --rounds 1 and timeout at least 360 seconds')
if a.mounted_courier or a.mounted_swap_eligibility:
p.error('--mine-stock cannot combine with --mounted-courier or --mounted-swap-eligibility')
if a.maintenance_refuel and (a.smoke != 'normal-escape-route' or a.project != 'chat' or a.rounds != 1 or a.timeout < 420): p.error('--maintenance-refuel requires Chat normal-escape-route, one round and timeout at least 420 seconds')
if a.body_recovery_only and (a.smoke != 'air-logistics' or a.project != 'core' or a.rounds != 1): p.error('--body-recovery-only requires Core air-logistics and one round')
if a.recon_takeover_only and (a.smoke != 'air-recon' or a.project != 'core' or a.rounds != 1): p.error('--recon-takeover-only requires Core air-recon and one round')
steam, compat, profile = a.steam.resolve(), a.compat.resolve(), a.profile.resolve()
if not 1 <= a.rounds <= 10 or not 60 <= a.timeout <= 1800:
p.error('Use 1..10 rounds and a 60..1800 second timeout')
if a.field_terrain_audit and a.smoke != 'aircraft-field': p.error('--field-terrain-audit requires --smoke aircraft-field')
if a.field_terrain_audit and a.field_service_cancel: p.error('--field-terrain-audit and --field-service-cancel are mutually exclusive')
if a.field_service_cancel and a.smoke != 'aircraft-field': p.error('--field-service-cancel requires --smoke aircraft-field')
if a.route_service_cancel and a.smoke != 'aircraft-route': p.error('--route-service-cancel requires --smoke aircraft-route')
if a.smoke == 'mortar-courier' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 500):
p.error('mortar-courier requires --project chat --rounds 1 --timeout at least 500')
if a.smoke in {'mortar-refresh', 'mortar-salvo', 'mortar-expiry', 'mortar-transfer', 'mortar-fire'} and (a.project != 'chat' or a.rounds != 1 or a.timeout < 400):
p.error('mortar-refresh/mortar-salvo/mortar-expiry/mortar-transfer/mortar-fire requires --project chat --rounds 1 --timeout at least 400')
if a.smoke in {'aircraft-field', 'aircraft-route', 'aircraft-control', 'aircraft-cancel', 'aircraft-translate'} and (a.project != 'chat' or a.rounds != 1 or a.timeout < 420): p.error('aircraft-field/aircraft-route/aircraft-control/aircraft-cancel/aircraft-translate requires Chat, one round, and at least 420 seconds')
if a.mounted_swap_eligibility and a.smoke != 'mounted-ammo': p.error('--mounted-swap-eligibility requires --smoke mounted-ammo')
if a.mounted_courier and (a.smoke != 'mounted-ammo' or a.project != 'chat' or a.rounds != 1 or a.timeout < 780): p.error('--mounted-courier requires --smoke mounted-ammo --project chat --rounds 1 and timeout at least780 seconds')
if a.mounted_courier and a.mounted_swap_eligibility: p.error('--mounted-courier and --mounted-swap-eligibility are mutually exclusive')
if a.mounted_intercept and (a.smoke != 'convoy' or a.project != 'chat' or a.rounds != 1 or a.timeout < 900): p.error('--mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds')
if a.mounted_intercept and a.convoy_cover: p.error('--mounted-intercept and --convoy-cover are mutually exclusive')
if a.convoy_cover and a.smoke != 'convoy': p.error('--convoy-cover requires --smoke convoy')
if a.convoy_cover and a.timeout < 900: p.error('--convoy-cover requires timeout at least900 seconds')
if a.smoke == 'supply-travel' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 480): p.error('supply-travel requires Chat, one round, and at least480 seconds')
if a.smoke == 'supply-convoys' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 900): p.error('supply-convoys requires Chat, one round, and at least900 seconds')
if a.smoke == 'alarm-hearing' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('alarm-hearing requires Chat, exactly one round, and timeout at least360 seconds')
if a.smoke == 'mounted-ammo' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('mounted-ammo requires Chat, exactly one round, and timeout at least360 seconds')
if a.mounted_bmp and (a.smoke != 'mounted-ammo' or a.project != 'chat' or a.rounds != 1 or a.timeout < 360 or a.mine_stock or a.mounted_courier or a.mounted_swap_eligibility): p.error('--mounted-bmp requires Chat mounted-ammo, one round, timeout at least360 seconds, without mine/courier/swap flags')
if a.smoke == 'convoy' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 600): p.error('convoy requires Chat, exactly one round, and timeout at least600 seconds')
if a.smoke == 'infantry-transfer' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('infantry-transfer requires Chat, one round and timeout at least360 seconds')
if a.smoke == 'hq-local-handoff' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('hq-local-handoff requires Chat, one round and timeout at least360 seconds')
if a.smoke in {'hq-memory', 'hq-awareness', 'hq-body'} and (a.project != 'chat' or a.rounds != 1): p.error('hq-memory/hq-awareness/hq-body requires Chat and exactly one round')
if a.smoke == 'map-ownership' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 180): p.error('map-ownership requires Chat, one round, and at least 180 seconds')
if a.smoke == 'powered-translate' and (a.project != 'core' or not a.flight_action_inputs or not a.flight_autohover): p.error('powered-translate requires Core with flight-action-inputs and flight-autohover')
if a.flight_autohover and (a.project != 'core' or a.smoke not in {'powered-flight', 'powered-translate'} or not a.flight_action_inputs): p.error('flight-autohover requires Core powered-flight with flight-action-inputs')
if a.flight_action_inputs and (a.project != 'core' or a.smoke not in {'powered-flight', 'powered-translate'}): p.error('flight-action-inputs requires the Core powered-flight fixture')
if a.smoke in {'powered-flight', 'powered-translate'} and (a.project != 'core' or a.rounds != 1 or a.timeout < 420): p.error('powered-flight requires Core, one round, and at least 420 seconds')
if a.smoke == 'station-teardown' and (a.project != 'core' or a.rounds != 1): p.error('station-teardown requires --project core --rounds 1')
if a.smoke in {'native-end-active', 'native-end-preparing'}:
if a.project != 'core' or a.rounds != 2 or a.timeout < 120: p.error('native-end fixtures require Core, exactly two rounds and at least 120 seconds')
fixture_names = ['erri-native-end-round.json', 'erri-native-end-round.json.tmp', 'erri-native-end-round.json.bak']
if any((profile/name).exists() or (profile/name).is_symlink() for name in fixture_names): p.error('native-end fixture paths must not preexist; preserve prior evidence before retrying')
if a.smoke == 'environment-restart':
if a.project != 'core' or a.rounds != 2: p.error('environment-restart requires --project core --rounds 2')
fixture_names = ['erri-environment-restart.json', 'erri-environment-restart.json.bak', 'erri-environment-restart.json.tmp', 'erri-environment-restart-round.json']
if any((profile/name).exists() or (profile/name).is_symlink() for name in fixture_names): p.error('environment-restart fixture paths must not preexist; preserve or move prior evidence before retrying')
if compat.is_relative_to(steam) or not (compat/'pfx/system.reg').is_file():
p.error('--compat must be a disposable cloned prefix outside the Steam installation')
if a.external_addons and profile == Path('/tmp/erri-workbench-profile'): p.error('Use a separate external-dependency profile; preserve the vanilla test profile')
if not a.external_addons: p.error('The combined mod requires --external-addons pointing to installed authorized RHS/WCS/BMP dependencies')
prefix_lock = (compat/'.erri-workbench.lock').open('a')
try: fcntl.flock(prefix_lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
except BlockingIOError: p.error('Another test runner owns this disposable Wine prefix')
# The lock must be held before the preflight; never repair a busy prefix here.
try: assert_prefix_idle(compat)
except (OSError,ValueError) as error: p.error(str(error))
if profile.is_relative_to(ROOT) or profile.is_relative_to(steam):
p.error('--profile must be outside source and Steam directories')
if not shutil.which('gamescope') or not shutil.which('pactl'): p.error('gamescope and pactl are required')
wb = steam/'steamapps/common/Arma Reforger Tools/Workbench'
proton = steam/'steamapps/common/Proton - Experimental/proton'
vanilla = steam/'steamapps/common/Arma Reforger/addons/data'
if not proton.is_file() or not (wb/'ArmaReforgerWorkbenchSteamDiag.exe').is_file():
p.error('Stable Reforger Tools and Proton Experimental must already be installed')
profile.mkdir(parents=True, exist_ok=True)
addons = profile/'addons'
addons.mkdir(exist_ok=True)
link = addons/'ArmaReforger'
if not link.exists(): link.symlink_to(vanilla, target_is_directory=True)
external_inputs = None
external_cache = profile/'external-source-cache.json'
allowed_profile_addons = {'ArmaReforger', 'saves'}
if a.external_addons:
try:
external_rules = external_policy(ROOT)
external_inputs = prepare_profile(addons, a.external_addons, external_rules, external_cache)
allowed_profile_addons.update('ERRI_'+guid for guid in external_inputs)
except (OSError, ValueError) as error: p.error(str(error))
if link.resolve() != vanilla.resolve() or any(x.name not in allowed_profile_addons for x in addons.iterdir()) or any((addons/'saves').rglob('*.gproj')):
p.error('Test profile addons must contain only vanilla and the explicit audited external closure')
profile_arg = 'Z:'+str(profile)
# Refuse concurrency instead of terminating anybody else's editor.
for proc in Path('/proc').iterdir():
if not proc.name.isdigit(): continue
try:
args = (proc/'cmdline').read_bytes().split(b'\0')
if profile_arg.encode() in args and any(x.endswith(b'ArmaReforgerWorkbenchSteamDiag.exe') for x in args):
p.error('Another Workbench already uses this test profile')
except (FileNotFoundError, PermissionError, ProcessLookupError): pass
command = ['gamescope', '--backend', 'headless', '-W', '1280', '-H', '720', '-w', '1280', '-h', '720', '-r', '30', '--', str(proton), 'run', str(wb/'ArmaReforgerWorkbenchSteamDiag.exe'), '-gproj', 'Z:'+str(ROOT/'addons/core/addon.gproj'), '-addonsDir', 'Z:'+str(ROOT/'addons'), '-profile', profile_arg, '-logconsole', '-wbModule=WorldEditor', '-load', 'Worlds/ERR_Everon.ent', '-plugin=ERR_ValidateWorldPlugin', '-errPlay', '1', '-errSmoke', '1', '-errSmokeOutcome', a.smoke, '-noThrow', '-disableCrashReporter']
if a.convoy_cover: command += ['-errConvoyCover', '1']
if a.mounted_intercept: command += ['-errMountedIntercept', '1']
if a.mounted_swap_eligibility: command += ['-errMountedSwapEligibility', '1']
if a.mounted_courier: command += ['-errMountedCourier', '1']
if a.mounted_bmp: command += ['-errMountedBMP', '1']
if a.mine_stock: command += ['-errMineStock', '1']
if a.maintenance_refuel: command += ['-errMaintenanceRefuel', '1']
if a.trace_random_radius: command += ['-errTraceRandomRadius', '1']
if a.field_service_cancel: command += ['-errSmokeFieldServiceCancel', '1']
if a.field_terrain_audit: command += ['-errSmokeFieldTerrainAudit', '1']
if a.route_service_cancel: command += ['-errSmokeRouteServiceCancel', '1']
if a.station_teardown_diagnostics: command += ['-errStationTeardownDiag', '1']
if a.flight_input_diagnostics: command += ['-errFlightInputDiag', '1']
if a.flight_action_inputs: command += ['-errFlightActionInputs', '1']
if a.flight_autohover: command += ['-errFlightAutohover', '1']
if a.recon_takeover_only: command += ['-errReconTakeoverOnly', '1']
if a.body_recovery_only: command += ['-errBodyRecoveryOnly', '1']
if a.project == 'core':
if a.smoke not in {'optional-site-skip', 'infantry-combat', 'medical-combat', 'hunter-faction', 'unconscious-camera', 'objective-map', 'town-garrisons', 'site-garrisons', 'radio-interaction', 'enemy-loadout', 'aggression', 'air-logistics', 'air-assault', 'air-recon', 'airfield-markers', 'opening-tools', 'mortar-station', 'generated-sites', 'native-end-active', 'native-end-preparing', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'victory', 'startup-failure', 'site-survey', 'cache-loss', 'extraction-capacity', 'early-helicopter-loss', 'extraction-startup-failure', 'extraction-boundary-failure', 'transport-loss', 'transport-survey', 'lifecycle', 'objective-ui', 'recovery', 'prisoner-kit', 'medical', 'casualty-load', 'casualty-direct', 'casualty-bench', 'casualty-remove', 'environment', 'environment-restart', 'patrols', 'radio-document-loss', 'radio-document-loss-partial', 'guard-cancel', 'casualty-service'}: p.error('Unsupported Core-only fixture')
command[command.index('-plugin=ERR_ValidateWorldPlugin')] = '-plugin=ERR_ValidateBaseWorldPlugin'
command[command.index('-errSmoke')] = '-errBaseSmoke'
if a.smoke in {'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'cache-loss', 'extraction-capacity', 'early-helicopter-loss', 'extraction-startup-failure', 'extraction-boundary-failure', 'transport-loss', 'transport-survey', 'lifecycle', 'objective-ui', 'recovery', 'prisoner-kit', 'medical', 'casualty-load', 'casualty-direct', 'casualty-bench', 'casualty-remove', 'environment', 'environment-restart', 'patrols', 'radio-document-loss', 'radio-document-loss-partial', 'guard-cancel', 'casualty-service'} and a.project != 'core': p.error('This fixture requires --project core')
if a.smoke in {'startup-failure', 'site-survey', 'transport-survey', 'extraction-startup-failure', 'extraction-boundary-failure'} and (a.project != 'core' or a.rounds != 1): p.error('This diagnostic requires --project core --rounds 1')
env = os.environ.copy()
env.update(STEAM_COMPAT_DATA_PATH=str(compat), STEAM_COMPAT_CLIENT_INSTALL_PATH=str(steam), WINEPREFIX=str(compat/'pfx'))
# A test-only sink prevents startup sounds; a stream check also catches a saved
# explicit Wine device selection. Never change the user's default sink.
silent_sink = 'erri_tests_silent'
sinks = json.loads(subprocess.check_output(['pactl', '-f', 'json', 'list', 'short', 'sinks'], text=True))
if not any(sink['name'] == silent_sink for sink in sinks):
subprocess.run(['pactl', 'load-module', 'module-null-sink', 'sink_name='+silent_sink, 'sink_properties=device.description=ERRI_Silent_Tests'], check=True, stdout=subprocess.DEVNULL)
subprocess.run(['pactl', 'set-sink-mute', silent_sink, '1'], check=True)
subprocess.run(['pactl', 'set-sink-volume', silent_sink, '0%'], check=True)
sinks = json.loads(subprocess.check_output(['pactl', '-f', 'json', 'list', 'short', 'sinks'], text=True))
silent_index = next(sink['index'] for sink in sinks if sink['name'] == silent_sink)
env.update(PULSE_SINK=silent_sink, PULSE_PROP='application.id=org.escapistsrereintroduced.tests')
muted_streams = set()
def silence_test_streams():
streams = json.loads(subprocess.check_output(['pactl', '-f', 'json', 'list', 'sink-inputs'], text=True))
for stream in streams:
props = stream.get('properties', {})
owned = props.get('application.id') == 'org.escapistsrereintroduced.tests'
pid = props.get('application.process.id', '')
if not owned and pid.isdigit():
try:
target = str(compat/'pfx').encode()
values = (Path('/proc')/pid/'environ').read_bytes().split(b'\0')
owned = any(value.startswith(b'WINEPREFIX=') and value[len(b'WINEPREFIX='):].rstrip(b'/') == target for value in values)
except (FileNotFoundError, PermissionError, ProcessLookupError): pass
if not owned: continue
index = str(stream['index'])
if stream.get('sink') != silent_index:
subprocess.run(['pactl', 'move-sink-input', index, silent_sink], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if not stream.get('mute'):
subprocess.run(['pactl', 'set-sink-input-mute', index, '1'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if index not in muted_streams:
muted_streams.add(index)
print('Test audio routed to silent output and muted (stream '+index+')', flush=True)
# Snapshot addon bytes before launching any engine process.
captured_sources = snapshot(ROOT, command)
recorded_sessions = set()
started = time.time()
log_root = profile/'logs'
previous = set(log_root.glob('logs_*')) if log_root.exists() else set()
result, session, complete_at = 'timeout', None, None
runner_error = None
cleanup_ok = True
cleanup_report = None
child = None
with (profile/'headless-launch.log').open('w') as output:
try:
child = subprocess.Popen(command, cwd=wb, env=env, stdout=output, stderr=subprocess.STDOUT, start_new_session=True)
while time.time()-started < a.timeout:
silence_test_streams()
candidates = [x for x in log_root.glob('logs_*') if x not in previous]
if candidates:
session = max(candidates, key=lambda x:x.stat().st_mtime)
if session not in recorded_sessions:
persist(session, captured_sources)
if external_inputs:
(session/'external-addons-inputs.json').write_text(json.dumps(external_inputs, indent=2)+'\n')
recorded_sessions.add(session)
console = session/'console.log'
content = console.read_text(errors='replace') if console.exists() else ''
if ('Reintroduced: scenario preparation failed' in content and a.smoke not in {'startup-failure', 'extraction-startup-failure', 'extraction-boundary-failure'}) or 'ERR SMOKE FAIL:' in content or 'Virtual Machine Exception' in content or 'Can\'t compile "Game"' in content:
result = 'test-failed'; break
if content.count('ERR SMOKE COMPLETE:') >= a.rounds:
if complete_at is None: complete_at = time.time()
if time.time()-complete_at >= 6: result = 'smoke-completed'; break
if child.poll() is not None: result = 'process-exited'; break
time.sleep(1)
except KeyboardInterrupt:
result = 'interrupted'
except (OSError,ValueError,subprocess.SubprocessError) as error:
result = 'runner-failed'; runner_error = str(error)
finally:
result_before_cleanup = result
if child is not None:
cleanup_report = cleanup_owned_run(child,proton,env,compat)
cleanup_ok = cleanup_report['cleanup_confirmed']
if not cleanup_ok:
result = 'cleanup-failed'
cleanup_error = '; '.join(cleanup_report['errors'])
runner_error = (runner_error + '; ' if runner_error else '') + cleanup_error
external_unchanged = True
if external_inputs:
try: external_unchanged = verify_profile(external_inputs, a.external_addons, external_rules, external_cache, addons)
except (OSError, ValueError): external_unchanged = False
if not external_unchanged: result = 'external-inputs-changed'
stopped_evidence = seal_run(ROOT, session, captured_sources) if cleanup_ok and session else {}
if stopped_evidence and not stopped_evidence['source_unchanged_after_run']: result = 'source-changed'
summary = {**stopped_evidence, **bindings(captured_sources), 'external_addons_unchanged_after_run':external_unchanged, 'external_addon_count':len(external_inputs or {}), 'external_addon_inputs':'external-addons-inputs.json' if external_inputs else None, 'started_unix':started, 'result':result, 'result_before_cleanup':result_before_cleanup, 'cleanup_confirmed':cleanup_ok, 'cleanup_report':cleanup_report, 'runner_error':runner_error, 'session':str(session) if session else None, 'rounds_required':a.rounds, 'project':a.project, 'display':'headless Gamescope 1280x720/30Hz', 'dedicated_server':False, 'audio':'silent sink and per-test-stream mute'}
if session:
(session/'runner.json').write_text(json.dumps(summary, indent=2)+'\n')
shutil.copyfile(profile/'headless-launch.log', session/'headless-launch.log')
print(json.dumps(summary, indent=2), flush=True)
if result != 'smoke-completed': raise SystemExit(1)
# All native errors still fail the report even when the scripted sequence completed.
raise SystemExit(subprocess.call(['python3', str(ROOT/'tools/native_report.py'), str(session/'console.log'), '--require-completions', str(a.rounds)]))
@@ -0,0 +1,802 @@
{
"addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
"addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
"addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
"addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
"addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
"addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
"addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
"addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
"addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
"addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
"addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
"addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
"addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
"addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
"addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
"addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
"addons/core/Configs/ERR/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
"addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
"addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
"addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
"addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
"addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
"addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
"addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
"addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
"addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
"addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
"addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
"addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
"addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
"addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
"addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
"addons/core/Prefabs/ERR/CrashSite.et": "8d06afe6e2db8986f06a7c5d6649e52df009f9eead7345bf2b477f50a0725b3c",
"addons/core/Prefabs/ERR/CrashSite.et.meta": "0f54fe80ed96394374c1922e1d0b05f7e0200ce5b979ff58325b033f51641f69",
"addons/core/Prefabs/ERR/CrashWreck.et": "f5de4785c0e3cdf02f1d5372e9b01171bd5a37acb9c36aa2a94bae3f429b2272",
"addons/core/Prefabs/ERR/CrashWreck.et.meta": "bde3299bdbbddb91d2ef471b61035b6cced29899cff4cd90c080fe584ce63f26",
"addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
"addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
"addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
"addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
"addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
"addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
"addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
"addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
"addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
"addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
"addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
"addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
"addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
"addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
"addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
"addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
"addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
"addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
"addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
"addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
"addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
"addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
"addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
"addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
"addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
"addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
"addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
"addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
"addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
"addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
"addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
"addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
"addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
"addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
"addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
"addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
"addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
"addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
"addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
"addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
"addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
"addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
"addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
"addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
"addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
"addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
"addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
"addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
"addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
"addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
"addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
"addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
"addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
"addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
"addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
"addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
"addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
"addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
"addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
"addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
"addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
"addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "8e8233a1c9000901e3a48141d59a55584099fc3b319f87c1589461b975ac9221",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "e8f778bfe56a91a1c761968261dcd7a5f5daa7f4983752d818a5443385fac049",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "3dfc424b1fc83dbc094054ea2e969a4aa584c724b77f23623e2fec9cba83ec52",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "3e2734dfb935a4e93d79b66ca4a7c883723a1fc348e3595432dbf2bfca643923",
"addons/core/Scripts/Game/ERR/00_Core/ERR_CrashSiteResources.c": "832aebf6e754dba54ba28b8f480180d32ced968a2d2f192424c4007a862c2b43",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
"addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "04b8bd8a042cf743ab8a87ec3711f9758e7b0112995a9d363e81a63df4eabe5e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "9a0536377f0e93f70972838de6480dfbdb44bfda198f70daaa541616eb046fd6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "addd7850e58a2f5c4a0ca6672033f2b42f5879e9a1a6a7ab86aa730419cef97b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "690a39a28a84ffe7ccbd27d4af50679925a870b53accf18d6573fe94e71d35ba",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
"addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
"addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "17d1f48878b02a457eebbe5ff87c4267488d68d2a9b3121dda77a8bc8e69c8c6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "60aa767d9455f2f4958a6a47bd68bbd8ab0466adc8f1dd9ae433c40ae96c68ff",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "2e2a880e68c9384698f9df21334d27e1aceaf3b59166d00eaabb802f19f61a13",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "67f8b444824634fc37fc253c60fd24b56d06d971f48e56a8d53095c97aaf0070",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "ed180448cb516bc4ec521aedd366810a47787628c7f5ee9c9afdbd185d980751",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c": "bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "d7c953fc8617c21e03f7d501c4a4c00a034b6375060072fd03c751fc2970feeb",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SelectionStyle.c": "f8a545dc9c21ebe397a5f790f6dd85d3c8ab18e444ac3b486b386f7d0df15008",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "d3385219f4f28e95b32cfae27092168ed09ace6baab4fe8c755963bdb8a795a6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "0ac154f77852b959244716e2494f632b6a2d8cd08171a4681af0365fcd5e7436",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "47fb9c34d31bffc892b18d6d6c4e7500d10b0a681bfa73e6476a761ed3375f0d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
"addons/core/Scripts/Game/ERR/00_Core/ERR_StartRules.c": "ab7c21ef700343cbe769d8d51d91f167db37285b466d6af9873e121b3adf4ade",
"addons/core/Scripts/Game/ERR/00_Core/ERR_StartSetup.c": "58a6b617b22910d0ce9255f82091dc11cd1284417a66adf1cdaa7b661c1ed01c",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "93fc55f2c33e95adbcf2bead3430aa14bdb55154315760bcc9647f89dc8286ff",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "e4585f70f193878169a3f0566d03610143ecb94682d78c9a91cfd816c64be6fd",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "64cbad8fada3630132d3fc6ee5ad63d698e6ef204c3ca7199a9c51d870ac4a19",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
"addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
"addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
"addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_WelcomeVoice.c": "a01d4163d3ab5b480ffbd2ceeff7384d8df6b7dd64036d580cd0c462b0135d25",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
"addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "2c3135a1457677028d91abee41b68c40a3a2d64a7588ced3ace47cc8e2cfd950",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "aac2a2c508aebcd9eed0a0cd310c2f3774357bb9b1fc383f305182b41d29caf3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "cc8dc67129457623505d959a097df765a1364ba4616313954ed6bf4ff0eb3542",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "69382b9f3a7cc50798ec5d7ae646145f9e7b80ce89370e9d7fb184e1272d569a",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMinePosts.c": "bcddb72845189b52e5ed71c687d7dd4b0b40b91b7306c3f6edf84a631002fc5b",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "d838f5693d4fa5d252d529e59777f560674c02532f1041a5598e938b3a850839",
"addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "2837755fcb5fc8a174192b4d881e3c623a3bf03a90d55c0d8e4be6ab2f1fd3c3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "2f0db77ba999586e4290e440d112f1002da17ab5fd20bb4f5b7ff6df99f58a81",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "f62f8bb8fde222f3f47d89df1439083deb6f5b14633402a2afb7c6a97803582f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "5f45545c11de5e183969203cdf07e29089697ddc89752a9c5aea0fa2a1a33a97",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "5a364f0349fa59e9a76aaa6bea42fff9b6592e36462fce9fd67d7962a3cdca6f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "f87727aa1c722a180c7b71fa2d896601b6250978a21bd2d1e973501fee81373b",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "16ed213344c00ec80080fb6866136333c11115e99f402d455033b686ecec8dfe",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
"addons/core/Scripts/Game/ERR/10_AI/ERR_InterceptVehicleFootprint.c": "5dea67d14ebab67231c485e14bc92f34c005a5f1bf6d9c0943db28e9857e958a",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "9784b551cbb91f017004fb728ce08b5c36bead0ffc83aa7149c2c46a7c4dc495",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "b7665e1ee678347b1e74b91830d3d4ca5e5a7c0432ee82c57d76f58ba6b90ac0",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
"addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
"addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
"addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
"addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
"addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
"addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeCrashGeometryProbe.c": "7867ce1794aa0d1bbab72c32f60f5bd0c2bad4f5ff6224978c215e7828840178",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeCrashStartProbe.c": "957f40e36bfc025b8bc752b1f41dc177c8d0844c69ee5994321a47cf3ddea1ad",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "7ddb634444c79ad9291d53a754dc0ed383342e36720ddaa4b7aa4bd4e7ee656d",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRandomRadiusTrace.c": "7e946406067092e30b6b75cc6ef0c56db7f866249e02bd13648156933ee578d9",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "b7e1857b0678b3a2c71880c0f35b09da9e978f19bacf5b4e7449c893fdbe2b95",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c": "32e6074e912491f2643a24cb44311b9fe5b069c76e4e94a45e7409ac82d36507",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
"addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
"addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
"addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
"addons/core/UI/layouts/ERR/AdminMenu.layout": "5583b018cabbebd7b4398b36bdca26c75c3437bcefed482dae9ed2a619bb7cf4",
"addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
"addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
"addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
"addons/core/UI/layouts/ERR/ContentRow.layout": "942e33bf2e08550446b40bcac31fb4504b7d8c717a42c196f54bf4025c72706c",
"addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
"addons/core/UI/layouts/ERR/ItemRow.layout": "6d364ce48158b90abd2185ca87ee27b095d0f7a5c8d59a0c65940e4be5488ac3",
"addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
"addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
"addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
"addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
"addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
"addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
"addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
"addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
"addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
"addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
"addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
"addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
"addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
"tools/native_command.py": "883c5955018e43c9451e3e6cb56e9cc8491c77920be3264478612a82c248cbbe",
"tools/release_check.py": "65df1bff33638a583905ba5f6c583a095b9f7e38186b6f29d70b72a61525589e",
"tools/reference_guard.py": "545b67111927d73bf2020f291528ea6f2f687a994b3e37bf567f239c32c8cd78",
"tools/native_report.py": "bb75ef5fe551f45776d441f15a49ccad4daf19abca505187f9b2d30102538658",
"tools/archive_native.py": "445736e18e645f1d6fac0aaf837627e94179d295c21a6a67a8e84b5b468758f9",
"tools/compare_performance.py": "568acfee2525b8924f3e7a39784e8641f76d63bb3703dcce8251ab9ac9bb1854",
"tools/source_manifest.py": "c1a985348bad16f3b5b69ef7e545b6341eca298d8ae08111b8340b31535cc199",
"tools/native_provenance.py": "d4777f1f6ffed6993f7009ee2af41b100e8e0138d60ebfdcc5404ff2128f8e2a",
"tools/dedicated_preflight.py": "ee56e05a15ada3bda80fecd74a024d141dcc3df00416821ac2c1a29ff308123f",
"tools/dedicated_native.py": "35e0c1402be1d54f1b4345de8ac4fa7fc73f8cdfd09c7cc6f832a39dfb33e621",
"tools/source_bundle.py": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
"tools/native_package.py": "32195bf9b43024028e9931a99885d0a131b28ba1b77b32e9d6ed70b914625559",
"tools/pak_inventory.py": "95b0b64ab1f89a2142385ca596016fa131b49d933e31aef42d9bf18e2ec01383",
"tools/archive_packed.py": "99cec180db72dc93c1ea8256bc316d42c23ab02843d5331a9d228b1a06a71d57",
"tools/parse_native_stats.py": "32aa0935d63e59ace29fcdb1a02eaa850898b21ee4cce011a21d364e3dd69c75",
"tools/headless_display_probe.py": "4ec3851835474eb4d8b84fc74c20d08567d92906ce832643d911f1d062abf0bd",
"tools/private_prefix_cleanup.py": "336889ddfbfe8032eef584d8e9e222d85e33a039441f8fe9c4904e1db8ee10e9",
"tools/headless_input_proof.py": "1952fb2ba577b80420133b9698b6d718d25211c86f853de8d22e0acb15f9f9c3",
"tools/headless_inventory_control.py": "194121b64ee39c31cc25935afea8ee9dddbce04cbf26aaf058e25d02ee9828fe",
"tools/ordinary_look_evidence.py": "3b6a0415352295e15e988ff78659e81981001e1ee03430a5b4c2df1518dd9a31",
"tools/ordinary_gate_evidence.py": "5f02596c92b945b28081d861e466f01897875489e673bf0feafa6e4ebdae1708",
"tools/prison_approach_proof.py": "fcd2936fa5a67ba6a970c56e8e4d04cc76bff6ffc6087ac95085716fb5fa673f",
"tools/prison_approach_evidence.py": "12f1618b16f845d987ba928c8d95f2d448bc6a600fb76f8870b2ae8fd4a660cb",
"tools/prison_alignment_proof.py": "37bd011642ca96dd0279e90cce785fc689002011b3977055f15c0dfad4161bed",
"tools/prison_alignment_evidence.py": "67d5675c13b2de75110c53b99d1bd88e0eb0c36673488312711b03fec32e4235",
"tools/ordinary_gate_choices.py": "59a0055d44f2f5b27c530406e5cbd46847357285d2d260d08e5c34cc53b7a795",
"tools/prison_action_selection_proof.py": "00d397bf9b13405a2612678ec866f09d452acb4079f2072eb97c79a7fdf650da",
"tools/prison_action_selection_evidence.py": "668b1d6ff86903ddeb702fd0c49d8d8110cd58559062d6d650f2962e4e321ab6",
"tools/prison_held_action_proof.py": "450f03c6dbb4960d9f15a0f9c43ae5a18ab00594181e23321a2eea9b59ed47fd",
"tools/prison_held_action_evidence.py": "971a630d663291d50c407dbadf6005e17ea035db88b5358e5ec1f6b24e6824fb",
"tools/project_schema.py": "cc1527c5f68fb75711208f293f4751c206fedc725934d9db7d4b7fe539f60cec",
"tools/external_addons.py": "c389b76c4d5f0f763420cd7d564d3ff5ebb7350cac10d2a26164c17f59b72dde",
"tools/headless_game.py": "e7cab472ee51497343174cb460022b3e4591f148d4acbc6e6f881fc68c0fda1b",
"tools/packed_external.py": "46203c078a82e825ec2e82c2495e6e165aa7ddc92368d2fe7786d87b957d3096",
"tools/prefab_identity.py": "26088826275e84dcac2dbac771faf0552545791d30e9110df1ce88ee0d5a81ad",
"tools/terrain_adapter.py": "d5ca50a5dc3ab4ba8b7d8cf2c72a9c3579b6567efbad5572acab991267116417",
"tools/welcome_voice.py": "dc61bb965861b71b00e19bb0bb19bc00995d35da2d8ed5fbcea52eabb4503201",
"tools/welcome_voice_requirements.txt": "7a454d3dc4efc97999407c3d4e73585f72bdba7acce42be59662296e432d90e8",
"tools/resource_references.py": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
"tools/import_settings.py": "a35ec5adf2c177f4daf2e3be5f97131b83a9920e765ee3e2c845b0d54c00af37",
"tools/check.py": "2965f354c39b6dd44f9f8a0c8d923fc65056fb1464d0227adf75ad98ab707d36",
"tools/headless_workbench.py": "b0bbb87597fe5f116e8b4fd1d60d52983935d438d3e82b972c675991fddcc971",
"tools/desktop/kwin-right-monitor.js": "ff2b6f7b9d1b1eb9f92b61b39df18f1ddc44be5540e18b1fc1829eb2fc1fb1a2",
"tests/helicopter_availability_regression.py": "3f256b7f5db246723b75caa2cc247249881cba95bde71ea1c90733404fe19f35",
"tests/mortar_salvo_regression.py": "0f5d5f5d33f64ff43f5a2b954fe4eec032a00697f51f09efa10284537a3682db",
"tests/test_mission_rules.py": "f534ae447fe1db6ae939430c3b14568d2bf1b84956dca295cce04211411d9ee7",
"tests/policy_harness.py": "e861c30037b3e456f0c8ef1c02e9fe1417b601ffb15d2037974715008865e4be",
"tests/test_time_policy.py": "45ae5768f6e87009b4074937cbc2e384c59341e905a3f250672bd2a110b2e6c5",
"tests/test_radio_defence_policy.py": "48c9c01dc6135a3f6d2187b0974645758040f041c3c2c2c26b14222fc572dfe1",
"tests/test_performance_comparison.py": "5f932de9e9898acdd379f26c777a35c884269522dbf8c41991a7a25bf61c369a",
"tests/test_release_check.py": "8b6e755ed922ad129ba01c228989610a31f3a79841dc7cdddd4ddbd0e510971b",
"tests/test_player_admission_policy.py": "745ec0a9e491ffcf5bec53ebf67ecee8333f4dcfa5d19bafbde31cbd1cad7f8b",
"tests/test_recovery_policy.py": "adc4966ab92f0849d08636d93da5bd02b9162d1ad7369b325a1a357903abaa55",
"tests/test_admin_setting_policy.py": "69af6f74e262ee4981ac428ac1ab85561f8b365aed5879e20d315ededca9ee22",
"tests/test_prison_placement_policy.py": "34539744426f0b30e41883203484ed60606df8ca319324014f07e833bcbf854b",
"tests/test_environment_policy.py": "66b86e66f47c4ce397c6093a50a724bbe8dedbf3db53e0dd7d53ff33243a0b52",
"tests/test_faction_catalog_scope.py": "c8fab92575f2621f47ed8685243338aa9ea717bb809c2ef9e8e0884af9df263b",
"tests/test_environment_restart_runner.py": "05bc09bc45db70ba4a635b65b0a96aa38437ba50c98640b47ed8d0683c3a5f71",
"tests/test_inventory_enumeration_policy.py": "95cbfd7c4351cb9a8e1cd6783524be79f77255e5996299919a61dcfce8b0f21a",
"tests/test_site_discovery_policy.py": "40fda37b86d469a1cf8fcb7a1fb18abcaab0df44ad09f50018744d42f8f4f649",
"tests/test_headless_game_runner.py": "0d84160076ec9961e7315ccd50d6ce45ff971328c298649505fbba6305c22f31",
"tests/test_initial_guard_policy.py": "0c80e744db1ce0a0d0746c43d867f5d2f47d9b92bc48d6561ceeb28a204d8743",
"tests/test_casualty_loading_policy.py": "cdf2c0abe4b794502f18228b173db47c4093ea062378ec9e3971e0c4f9e3bf1f",
"tests/test_casualty_reservation_death.py": "fd68dce04ea48ee2a22fac499c32a5c53847a25e3f14eaba3f50437d2c040f25",
"tests/test_casualty_ground_policy.py": "6543c594293d7122242ec68d506a92dc81464d110cdb7496a225555cee338c83",
"tests/test_guard_cancellation_policy.py": "f8f134b6d525a3c775677b2a95c562b12aa84ba287318c08c833d684ad0bd9d8",
"tests/test_radio_feedback_policy.py": "6b576472f81a35bd4df4dae3f19925b046eedbba262ad67f9bfe1ce9d220a487",
"tests/test_extraction_placement_policy.py": "d924f163d98c78989938ca01eca5935891fb454266810f4817cbe49651b84ae2",
"tests/test_casualty_remove_probe.py": "e3b8ac386bb8e4a9832215cbbe1cacf7a5bd1314467bd4b07ed4a57b2db75458",
"tests/test_casualty_incapacitation.py": "55b5cfb7b3eae496a8cc18888872d11331ecc01afb7326fbee3b8d65047dbe93",
"tests/test_diagnostic_no_splash.py": "d99539a8b3277c2f1ac3e3bfa4c897876fe21e704c9ae33c542eed79fc2e9e65",
"tests/test_native_mortar_probe.py": "217801a6eddd48f76e99363a72a9812c0f48766ebd2faf8e188f4466ed1e4088",
"tests/test_local_admission.py": "0bde82f6d5c31c4187ed0aa1935940b8b9e634868b3a4820eca073580ad136b4",
"tests/test_dedicated_preflight.py": "0d654375db6b8eb91d0b92663b50e32776aaa7ecafbfdb83c00f04826df5236e",
"tests/test_mortar_aim_renewal.py": "cf228b7f83d247d93277ec4c8644eb1090a20336a7e9ee2b90086c78199a70ca",
"tests/test_native_mortar_transfer.py": "3b2a201a73c9ff2509276428988e4a98023c6aa94f8eeb42bc06c6cc604473d2",
"tests/test_dedicated_native.py": "f0323b20743221bd1ad46d6462246c2a0e2be84b395e40faa39007ef330aaa3c",
"tests/test_mortar_report_ledger.py": "fd2346e06c37a9e7621e1861e0f472b72ac14786fd2bcfbd785b62700d55ffde",
"tests/test_native_local_admission_probe.py": "16864bc359ab607dae3919442bd18f191320721411a8156e23be999f24e4454f",
"tests/test_powered_flight_policy.py": "86bfd5851be6fe3a187e1fe7fd2b7b0965c891cf29b2260b0df292255c5c547a",
"tests/test_prison_escape_policy.py": "d5d54588116eb730a8fda046f25fc4edc89a5345f85774cbc0f0a9b3adb85b98",
"tests/test_powered_flight_pad.py": "690c1c6e05f3520a6d4d6c45a0fc5d9184e30a12b24356b3126bdb35c4171b82",
"tests/test_item_station_teardown.py": "4e0f508dea6172862be82d6c7f295ede2bfb2412c390a0937a75ab176655f4b6",
"tests/test_source_bundle.py": "074ad87ee7ab0b41ab94a7cb28efca66a975c24b8e2574122a13a52a4d491d0a",
"tests/test_native_flight_footprint.py": "96923c018608f0c4d24294a9f8e769e2037be1fac8f1d51f4d73463706e134ad",
"tests/test_native_flight_input_diagnostics.py": "355e2e45b86b9a46c68efb0563d16bef7a032cd7758169704b4b26ea92bee2bc",
"tests/test_mortar_logistics.py": "98cdf38e43eb564163d8b409dfc95c4ae23e775c423651f05698acd52a7ef5a2",
"tests/test_mortar_courier_storage.py": "0eb75fbcdcd712ff1c2220dcdd87cff6f3ed1e6e8f1c889916daa6b84a4359f5",
"tests/test_progression_identity.py": "2fb3725aa735e00b20ba7a4ac45f8e087d4346c58a176bee091bab0a9755c1df",
"tests/test_discovery_map_position.py": "0644aea60d4c546e819ef417771563ab7598e84d5e13db2fa63416ae1fe6ddb0",
"tests/test_vanilla_game_control.py": "8ab3777a5bd0f8213efae08bd6db70a05790af992c2abfda8e5e5aa079beebbb",
"tests/test_archive_game_control.py": "8126e2be91f9ee8c09fceb82d03bb0d9c51247909189a424c3e24dd2b1ed22ce",
"tests/test_flight_action_runner.py": "aa14ebe85fce7c0435f48aceec1d4463b33fe8a5792b4e935b543dff94f4ad02",
"tests/test_native_package.py": "0776a1eedede7185aa36c7fe816ea6231e6f475c0f6d210a2c732b23dc6d765e",
"tests/test_spectator_guidance.py": "26c02deb1a707f51dcf577a9ccb789bf33f432b41d9404d36a7b1b3c8802298f",
"tests/test_native_mortar_salvo.py": "f45625eb92d16adc8b3eb57bc72b77c8829d46c2c7e5bef40d302fc90252ba72",
"tests/test_pak_inventory.py": "8f0b55bb295117c226900bd641d25175db1021a365866a5ce6482a78d08c7f41",
"tests/test_packed_core_game.py": "ddac4281f74999b1e60c2052bbdee36c97699192cfd5174a88b6f01ee740111e",
"tests/test_mortar_refresh.py": "0ac74cff8aa10fb06ecb75d17eb7ca3a6b80bf5194522bffec583a44fc01a419",
"tests/test_archive_packed.py": "37712810b7c6fd11a2df35665df81546f8b98682dc74b317ad1f9ad6ad274d86",
"tests/test_native_mortar_refresh.py": "60f3c4fcb063506e9bd85e4abd3cd2fc802304bc71933f3e31d88f5b896aaa7b",
"tests/test_mortar_activity_completion.py": "a0db3b63962bc95de42ec12ef17c53730464ac7421a4475020957121513586ec",
"tests/test_packed_chat_game.py": "d23c099d17a0dda09e5ee28931a4850f9bf6df5a7874581342eacbd16860565e",
"tests/test_shared_map_ownership.py": "486eb3a8a04a47878b87ec3952c613542871077af1de27ea7299fa3d72caff1d",
"tests/test_native_shared_map_ownership.py": "672d248550339dc6350e548034c50b3440d44b91668457f3efb2d91c8445c3dc",
"tests/test_participant_selection.py": "e153f69ffa60d186dc3b1a238df1d48f2a0623b2dd8331d2cbbbdd57cce5529e",
"tests/test_ordinary_screenshot.py": "eadd4f8ae2a8057d0ac7bca5e8f4abc260faa10cddfca31b8552d7b49669ab33",
"tests/test_aircraft_flight_policy.py": "147a27fb57c0b01cded35eae26af4394d7f41eeeb68856f564972e1c89c629c9",
"tests/test_aircraft_flight_envelope.py": "6499ec174ed68dbfc07bd49275eaff8a7e60865615bbaefee354de7233a6ff13",
"tests/test_native_aircraft_control.py": "3ffed5429896254d96b67ff3fdd01f65689f526e6a1766cc6874e2e63f2e26f3",
"tests/test_aircraft_translation.py": "983fcff4800e777cd1c42126431ca94e7c03bc06b5fb34a243704b8ca55dc36d",
"tests/test_action_feedback.py": "1fec11a218b6da69c8c40ce232523582f0ad390f8357e74f24daccf5d46d3814",
"tests/test_spawn_retry_budget.py": "c182acfcfd52cd74a94dc3336d7603d14668850a684b758cc7545a98a5d14beb",
"tests/test_native_stats.py": "a9ce90c74f0ae7e5c40e451f6b1d60dadde831c3d858710a70929390d5c70f7c",
"tests/test_native_end_lifecycle.py": "8b187723c9039e68e3e590c812c91dcffe1e5917d4e450ed798dc177888fda7a",
"tests/test_native_end_runner.py": "aed94be9b370a412937303cc5b66f0151c2cd64c3e1358f983f9ea53eb0d1057",
"tests/test_escape_result_wording.py": "7b3613cccd4f24d3ef4665dfc1854cfc958a69018a59f9b8090617f0185a82a8",
"tests/test_preparation_status.py": "e43cb7ce81232a31d00219004574dc2d1806760e0b6f0c49693725ffcb1b4e9e",
"tests/test_headless_display_probe.py": "d4d6c9907d7419ca888d5d9ba7448cbe6f5d2e53810f74c85660dfbdfc9f7e2d",
"tests/test_headless_display_runner.py": "f03a908e813c9ca4dc2ff13b3ade08549931e39490b8636742390a304c73974f",
"tests/test_aircraft_route_envelope.py": "08b16d4e7f97db96e3f88af0cfccd9b6bc083f6f25ec33cffd7ec36b18798729",
"tests/test_aircraft_route_policy.py": "b717734a07a59ada837f05c36172110bd7d0b5a5a277e8fae55a11dcab3e2aa2",
"tests/test_aircraft_route_probe.py": "bd8cb998fef33db8f26342eec0198c54b7715662d333530e2bede572c81f162f",
"tests/test_ordinary_input_observer.py": "09cf661ae47f53cb429a7ab17c2b752ae30a04368a260468227b0678148b2434",
"tests/test_ordinary_input_runner.py": "1ed373818673a438647fc7074c4c689f5bac0a91e8d55edf29d466b96f6703f8",
"tests/test_private_prefix_cleanup.py": "bc6d3fcf6a5ee5b5266bfc4516642d2f73e71dfc870c527d67cb5a47964dede0",
"tests/test_runner_private_cleanup.py": "4380874af7553391ea7e1e234c8a3f8e61922e0f16b1bf9bd4821cc479e5edf4",
"tests/test_headless_input_proof.py": "55c84de6dac3a9c44bd1ab4113d306544025a405c613f6e7d26550328e84f6c1",
"tests/test_headless_input_exercise_runner.py": "0b812647718a3d7145905a3ed17fef97b025d57b1372773d2c1069a3473a9b1f",
"tests/test_inventory_control_runner.py": "f325fe1975f7a56fbbb1a6357206d2ac0c9e7c32c396473fdfaf1cb80ad39b11",
"tests/test_inventory_layout.py": "8e176f8a87c300b8062a37ee34b22a105978c7d9c6147b506757135f4f48a1ff",
"tests/test_relative_look_runner.py": "131d829c60a7bbfe3e047af8e38d255e5ecb9d84b7d2188d14422dde724fa05e",
"tests/test_ordinary_look_observer.py": "cd5842e54c9ccab16766637bf2ab4e4e0b98f4d597b5927b0c2ec3f720fa3668",
"tests/test_ordinary_look_evidence.py": "1b98be4b69a5e5bacf46791f1e009fa3c73cdaff875c012837c9888443a61633",
"tests/test_ordinary_gate_observer.py": "78ff734604724a525809567ecda88f4d5fcd67816a6ba4960b72d0685f1a8b00",
"tests/test_ordinary_gate_evidence.py": "2bb3cff082b3fe45f668933a5039fd06a8d31562049cdd41c4f32181136ea5df",
"tests/test_prison_approach_proof.py": "ca71ba6c8cc20dad52d2966984676a111004333c24bc408f1ec84312e4208039",
"tests/test_prison_approach_evidence.py": "660e03b6f9932947c1aafc4c043c2a2c5bca776433c2146df18e8bb90c606a9a",
"tests/test_aircraft_route_demand.py": "96d9a21c49605cb671525f977928a21c57f1d0b441460a2624892006e7057efb",
"tests/test_prison_alignment_proof.py": "04c96825ea03b95c3966e3a53ce2c15990d63388386d84f2bff3e6b6838b18c0",
"tests/test_prison_alignment_evidence.py": "214af04ff9b0e8ebf0bc97f528233f5d55fccc7623392a65c6dd286ed415e724",
"tests/test_aircraft_control_bridge.py": "bae6f1711dcc5f55f7a813af251fc210ed017c58a8067c03d91e936824542ef0",
"tests/test_ordinary_gate_choices.py": "0e21f2933a4862eb5fd2f04b3b32dc7de6b2ca72d920aaa332d179edadb932cf",
"tests/test_prison_action_selection_proof.py": "1f09fb84b73ea916bb39ef985c58aa6886223e60cd425f929b3a020eef74ebae",
"tests/test_prison_action_selection_evidence.py": "1fee0421669721618dc2f9a3039f945d470b83b186661d3b1f00291ff8b78e9f",
"tests/test_aircraft_service.py": "9c19a09354ccfe8b41961204d80c3621d11e6704909b7266fa00e6c197bfd20b",
"tests/test_aircraft_service_cancel_runner.py": "1220e7c45c50590d12c9a5192eb4482e7e6942d7c00f36d9a79b5ca70bd1429d",
"tests/test_command_maintenance.py": "be2c942aa11a5f874448e94f06925f2f1de2210a14881fb7e486842119cb673c",
"tests/test_aircraft_field_rules.py": "dbed3a499eeddf2513e3582667ea2bd90fff6ed26057891c7df6e196c3d00e84",
"tests/test_aircraft_field_envelope.py": "67e60717a92580e3c4caa4974994cd92a96c98562be805b31319b3585f296639",
"tests/test_aircraft_field_runner.py": "822717f77702c335667b226f025aa6525415689b492f9ed42dd256d4c893429d",
"tests/test_prison_coarse_facing.py": "fe0ceebb74dba77005d6a7e31baa1a50156cc66f79a1d90eba4db9b27b099acb",
"tests/test_prison_held_action_proof.py": "349ee99d36f18fb7c70382ce95f1e9d84d819575a45b6f5429394d1702f1f227",
"tests/test_prison_held_action_evidence.py": "bbb032736774bc5db5fab7758faeaf038eeaae9eb49ba706a52f1e9bfe09fd01",
"tests/test_prison_held_input_adapter.py": "56fa60ae69bf280e1c2e90e7882fa213914623980b6800a4312c6f1017b8f632",
"tests/test_prison_held_runner.py": "d50905e899c2d0d92ca2f4c51dccbf2166ee21b8c6d2d4b218da459b724c5a4c",
"tests/test_aircraft_field_flight.py": "ae5e18f0e2efe5ad01523cb1cf9bc64139094aeaac7477a900a9abd8e6ae8f18",
"tests/test_aircraft_field_probe.py": "fe4e5b58bbdca0f366fe4c614f7506f2a05fa29fabcde345e322cdb3d62db897",
"tests/test_initial_admission_exhaustion.py": "14d6959a1185f154389be1405c49e2f7c1c9a3f27295e26074ac4ec74380057d",
"tests/test_casualty_feedback.py": "2d8bada9a3fd7583af4fd4f07033dd9eac28ca3bdf34a4557c8985b7a1714dbc",
"tests/test_intel_admin.py": "f2704740a380de8e93c7ceace414744f938442cffc6bca77a3439b4ae36aade6",
"tests/test_intel_reroll.py": "d102cff7467323440273eb457b5dfed6610d27f32c52c6fb7801ce93348ef5ae",
"tests/test_admin_player_tools.py": "7520c768b760ef3a03dd2f17376077fc17695360a89f91df88af924899a74517",
"tests/test_admin_session.py": "6e1850c625e18460a5d64ccbadac992b663a46bd612fcc16b6006f19b3014896",
"tests/test_project_schema.py": "0e25ade3ee0083618c1b2837aaaef36ce33663d78f35d862e1dbec256f4d6e40",
"tests/test_admin_tick_delivery.py": "8f61a6aaf07b0c41df2f415a1956d8f09fe61a7d4f256775ca62511030937a5d",
"tests/test_hq_doctrine.py": "5c18ee72454cf92132dedfb4bf581d174d67fc2e423158347ebe52ca74e8a416",
"tests/test_force_ledger.py": "3dc268db304b9465d53056edfcd8cedcc15591b411c55ae8f9bd43e163ff9c49",
"tests/test_hq_body_observer.py": "6cae50ef0a2b2fe35845f42e90998c517c061fc417cadfac375bacc89bbe603a",
"tests/test_convoy_budget.py": "481364c432715336825466a9ff199edeedaa2d3621daba90c0503addfa6010f7",
"tests/test_convoy_dispatch.py": "47e77f544ec6f3f34346dc6b5082f9df0a2d869897e094ca993a92c7315468c0",
"tests/test_convoy_admission.py": "0ace42a7e1afee7413e45a3909e7ea5c29dbb8c0e692acc3dc9a35ea7ffd4adf",
"tests/test_native_package_external.py": "8eb3eaee401640521c67a51607104a28de89ea9c32b3b6dffd05d9d3026fca3d",
"tests/test_convoy_road_plan.py": "62bb655a84f90e934bb894f8e472a8a06905d72e1c0b05bd641e46eb8f4873b4",
"tests/test_convoy_placement.py": "895feb51b971cf99e39c3a7d01806b360ff46dfc90f8de2a36910cc49251ba7b",
"tests/test_actor_group.py": "0d808be40d13866bf8bd983d62ea3a8e7772e9c49a41109fffb02c5352153a4d",
"tests/test_external_addons.py": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
"tests/test_external_profile_review.py": "a35e9670a8f5eb47d28b4d6afe498e5a58b2ab2dbdc59912a206010ac8dc5240",
"tests/test_hq_delivered_casualties.py": "c22ad9e395b36b41e8292b034f170e14b5d13a6a02b2a81dc619dd37110ad905",
"tests/test_hq_ammo_dispatch.py": "6c7a4cbaa41ca3bee01082ffab376fc2db5b08757aac88c5e8caf99b39677d0a",
"tests/test_convoy_combat.py": "140d5e8c8c978f97f7f15238bf2aa4efc6ca4d9b6370ef5a0c68bf469cec0b9a",
"tests/test_native_hq_body_probe.py": "f2b761fadf013d55d4e9c2ae11c5349fc054e767cf950aa632a43b8f4fe1d758",
"tests/test_enemy_optics.py": "06361eccef16d60a6f5072f9b126814a8f686c478049760047bb2ae8d19b5c52",
"tests/test_native_convoy_cover_probe.py": "68681753a1ab89a8e8e07ba7f701190bf860d07762e5a06e87da7ba606fc0de6",
"tests/test_vehicle_security.py": "f08a1cffb0860ac7ad93e94f4cb8b7cc37b8c49b3dee72b1d310fc72d9f95422",
"tests/test_vehicle_security_native_probe.py": "977384c5ec07588bc77aa9aeae45b008c02d55d31169e46984a1947e987545c3",
"tests/test_vehicle_entry_diagnostics.py": "49e8b4cd8274e08de628e89f4471ddb47823af38d98b464336e8c98a4308dbda",
"tests/test_hq_radio_node.py": "2297ae23b7a5fece845c13f16432dece6e2dde55ecc097a5be6311f470dd5242",
"tests/test_native_maintenance_stock.py": "7acbb488f7075428c08a10cf0e975ca0d508f3bb6416eddcc2991da93a5fad91",
"tests/test_packed_external_game.py": "c5581fa3225bbc5b160fafc26c65783eb7d551489ab101b17f7a6acc1d8d9e63",
"tests/test_intel_registration.py": "41cd929a29ea5e6b37d856cfc873c33fa2a8130e3aad30146f522ce217875488",
"tests/test_convoy_startup.py": "2c9106023ecb6dcfb5c96c2edc98b51695c325c685b2ced37b999b6cd4504c65",
"tests/test_failure_result_refresh.py": "076444d2c740609ea4290de1525cd5d7fbd99beef3c48c134afb581422a3dcfe",
"tests/test_convoy_auto_settings.py": "69fa7c957d3e19cbe6f954c26a08c6f0902473ed20ca289c9378c9338c2e7e3d",
"tests/test_native_memory_deadlines.py": "66cf766ff2477518610eaab231572633ae7c2920cb183909bef346f9835ba889",
"tests/test_enemy_gunner_skill.py": "67172901ed950517977e535c1237e8eaab10d22d52452bbe05fe16bfbb4089fe",
"tests/test_native_infantry_fixture_lifecycle.py": "c20ed9dd152489a8242ec0b97135b0691c9c104783bb843b0715cdd8d7c2e156",
"tests/test_infantry_ammo_access.py": "bd80e4405c3f2029553b5e932ec49c6370b8366cd4e9ed03be89393f86c07dbf",
"tests/test_infantry_placement_settle.py": "1490a797e016b99a222280f57875cc83096980022d1784495a80b8a406d400f7",
"tests/test_infantry_resupply_waypoints.py": "df3596515e0bb6a4cbf1e6f07d56755344415ad1deeffb8a70f71e8ed73a139e",
"tests/hq_network_regression.py": "63c7525b26ae6b6e2369307250e89223a77e7e28321daf4309ab76f21ca1bc50",
"tests/test_hq_report_selection.py": "4bd4c4800c217584ad9e1b4a37968350eb9a160e0151fc8b0375781736726cc0",
"tests/test_hq_local_handoff.py": "0fdbcac1958b0d12296753e7c9d92700079ea6c5c8e33d0e21e8318f997b79e7",
"tests/test_hq_local_handoff_intake.py": "c51f0ca082456331eb5856bf6dad864c3852adc20beba9b6829bdef978b11d88",
"tests/test_native_local_handoff_probe.py": "5a0904863ea00fd7ad262fcf91d8c1e55036b2041f16b043104f333c37d8c7ba",
"tests/test_hq_road_intercept.py": "0e83cb7c63131141ab50a38e7da1dfb41b631a6cb5768dff1066a0ad385ba7fd",
"tests/test_prefab_identity.py": "2a1c6e4cb1ead0c7b36b8fffb2ba0c59dc7e025dafaf8344a8158d38fe17582d",
"tests/test_spawn_scene_inventory.py": "f29bee9c629072f51caf66b680013b18f608bbfc5135a1f020e1a2904e89cdd5",
"tests/test_spawn_scene_lease.py": "adaf38b259cc36af526884d3d2312ccec0cbe6eca18d7aed2c1a066be8ea0da6",
"tests/test_content_policy.py": "260eedd838802647af59f33a15510d2c721aa80a7540d54e47f22734041cb49e",
"tests/test_random_settings.py": "75fbcba53ff2331811fb91051bbae1b2c28108fa9477d98372e0eb057655f225",
"tests/test_hq_convoy_combat.py": "07a4cd8e3bcf50ced71de05d0713a7944849a38b3f33cdea27f145bd53b9708e",
"tests/test_faction_selection.py": "77e4789499b3560e729a115197c5b02d032c291ae1bd44b1cac5a2c2c476e450",
"tests/test_generated_sites.py": "111095f40133b025ab67380b6cdcbc25ce0ecbc03379d1a015db6fdb0e5f2b25",
"tests/test_debug_ai.py": "7f4b847ba11e8da937eba7be3c4c0ab898b44567f6f553ff842da54c1e7a85c2",
"tests/test_mortar_station.py": "6570f18f787b7366ec5341da68dd99acf541cbbc31c6db7a9a3ae967506456ec",
"tests/test_scouts.py": "25c6bb1bcc9cb171d12cb1e59b5b278e256a7a4b257b5ce3a1d76d60d459bb59",
"tests/test_air_recon.py": "ed8938ac85c2e539bc5cddff339809624bdaecfff63ff4b2ab728d006548dc46",
"tests/test_air_support_policy.py": "bedd5437ba0667c371c390cb8c4fb5a3096e8ef6a71c8bac2091264b8d2eebf7",
"tests/test_intel_body_inspection.py": "04dd19efafc796f349976d29df77cb71b95615e527ad9add4fceda1f6105fc94",
"tests/test_air_logistics_orders.py": "adf7181998f522f8825b71ef10955c9311aba9086e5bb601cfd47599baa46d8a",
"tests/test_enemy_awareness.py": "881289417a1e4af219546b113d018e9bc6a402a16cf4bfa7e983ab240f41c2aa",
"tests/test_faction_menu.py": "9e6381a4786487962358362b75a2287532a688ab27df756e84801e2bb6dc2e55",
"tests/test_hunter_opening.py": "8d791372f465b6242a386d81b8e2136865390cbea5dfdcbfc6bb8b4f717c041d",
"tests/test_journal_readability.py": "47764126522e7d7a90100cd9beff741bf49e4d8390111f977919d3e323a5c7df",
"tests/test_player_medical.py": "e4b3140a3afc0161db53f261e5480e51f1ca09f85657e25b0efb7dbba3336e3f",
"tests/test_gameplay_session_regressions.py": "d9968b06627ce10412e5b1165987de662385d5dcb29090c5626b90fb59df52f2",
"tests/test_field_sites.py": "fddb0e44e72fdfe32bb94347a14da64efbd2208e4f252754e80c620fbecda56c",
"tests/test_town_garrisons.py": "3674f713d7adc62ec9098f7923991c9f6b1d0edfc1431ccfd82fc8031ddae17f",
"tests/test_unconscious_controls.py": "74d4008a5c02ad0087b55030c177c8320b7099c11b97a14d93acf0ad14941356",
"tests/test_hq_local_awareness.py": "00c8023f85e88ffc1113353836962c31e8e541a32c9b2f1f66b91eaff5b923af",
"tests/test_hunter_combat.py": "240472940515795b205d5caf530392ce416e3e0d2b97e473bb935930f29287d6",
"tests/test_enemy_medicine.py": "d13ab1d4ebe81614e00a9a579c6bcc6bd5b2c608187458f414e47f47686d7ad0",
"tests/test_infantry_combat.py": "03bc85811c52bd894ab8545794135227fc33b911a51f4e70d89fbeb2673de8ee",
"tests/test_hunter_profiles.py": "bdc7898666a7e1078ece35b5dc9bf903d2218843abb24addcea9353fe6b3f7f3",
"tests/test_gameplay_review_fixes.py": "5f988d63ea4b2a8a364b181982ddd462baa628ab66e3a35d0fb5ea6f20c50b0b",
"tests/test_convoy_column.py": "8c5de7616d4f8c3ed15bcc29bbb57f04dcaaca0626683b81547e2170fc5f9a62",
"tests/test_spectator_recovery.py": "8bb59c51df003e24532ad9476af4c8ff3b7f4276dca25e8162b91eb77c7b67c2",
"tests/test_server_log_regressions.py": "733084d7d2e33eb96740768c48d9e25bd7f3ffa9081949e38d0776c6822f5748",
"tests/test_mortar_load_ack.py": "6eceee33969ec268d904f062bd1ac12ec4269cf87acd235469052b193b048774",
"tests/test_body_recovery_lifecycle.py": "242e185d2934dbe756c5d90c45211d3c1bcdd5d8cf829c867c9e9f9a110f2cfb",
"tests/test_native_infantry_cargo.py": "0d27423c6834503840813327d0d3ba0d675206ca759260ff79cb775adf83e314",
"tests/test_native_infantry_setup.py": "8d935cd24ae49ca8a11f9a52fbd73146e567b8f36e0a7acc6565eb3e7d55f1fd",
"tests/test_view_distance.py": "ddc6cbeb41485f14a4f2ce23a7a86f1708e7e335bbeecee6309be49fd72e00e7",
"tests/test_optional_transport.py": "16c72845dd07f4ade7de361136c04bd264ff75634152e83a19d19a2fdf59bd0e",
"tests/test_terrain_adapter.py": "bcc6f469a12399f833651c591b3e1ca9a8e7f49d8b98e223a271fddc245bc4c4",
"tests/test_terrain_sites.py": "03ffa5812ae4fa282174f29b5fb3738fdeb261ea26ddbc44b9cd3b3d61c008c1",
"tests/test_terrain_airfields.py": "3a6e7151902657a38d8bf0510fb5c1a8049408d4f84d51ca260a0b5d651431e4",
"tests/test_vehicle_alarm.py": "1b58d6b35f080003ecab03b23c8da68e0ba2a6a82db4edce89e6031d83f26c82",
"tests/test_hq_mounted_binding.py": "40b6af209178cab30b2d6b4420acabf2086532fe0d3f836caaba60e369bdb905",
"tests/test_vehicle_alarm_perception.py": "6c8854088c28e2a7b4ee8d38a1f10f66eddfcf9d67afdd460b395d19877b7191",
"tests/test_hq_vehicle_seats.py": "8f35fcbd30e51b5576349245a102105926c7df738f3f77abb6ffcd780c6cb62e",
"tests/test_native_alarm_hearing.py": "7842886a177aa9fbb6b943b72703c4dafd18d162f26581ce30ce04289e7e9ab5",
"tests/test_finite_magazine_reservation.py": "dce435b1dd2d9b1e0ae1f54b5f911ca4207227c4c23586b4f4701c6a6995fc8b",
"tests/test_hq_memory.py": "839c7adc63dfab023fafe1547e29caf0ccef52882c5d2fad7b342691b562a41d",
"tests/test_supply_budget_admission.py": "3d0e1372f89873470c336038c667df38d2e2e71b3dc2abfddd1215939c448fc5",
"tests/test_native_mounted_swap_probe.py": "08674b3c0121756fe94762bd0acd5b6880ba5b234691557851eca5558718e2ea",
"tests/test_mounted_initial_stock.py": "cf7d101d8bd31cbdaaa0e7d66f0d8b39aff9b3b70acf51641902c6d0de5be096",
"tests/test_spawn_scene.py": "d89ef752906c1cf27c4cc7292997a4d793ddb3b56a6dfbdeff837978350167be",
"tests/test_spawn_preload_timeout.py": "db3a3aa42c20f047da90cac6755cb283d15cb3de6a22a57a6e1f352e9b4511dc",
"tests/test_hq_uplink_fairness.py": "fc4808a2045522ac6038eef9c37c75ef133bd8af7ffa02c6c1d105b3bfd6c555",
"tests/test_hq_pursuit.py": "caf00e5a3a4f0efaf1bd8159c3290eca3d0cec60bfa1368844410d65f3a20ea3",
"tests/test_supply_convoys.py": "be4fc6376a77296c6721ce966ea33fd256fe9d76af8705a056a88b32c4f16710",
"tests/test_native_mounted_courier_probe.py": "4dadd3157f7da193ce8996b5b08e802f891295ad82a4236366f3018c778c07e7",
"tests/test_vehicle_maintenance_stock.py": "e09a6e98f314eef1cf487cbaf8b2185bda950c12329939214ed1ba95713a097a",
"tests/test_hq_coverage.py": "d790ae0e5b533f702284e6deeb2c84f7ede5c89bb2b6a68847400e915d50c146",
"tests/test_engineer_mine_hq.py": "40cb6cb73a00311e9e3d2dfd2cbc10f7f2ea61d3e7281a69f227584a773d8684",
"tests/test_intel_discovery_feedback.py": "49b2fedd8704ec67af60a6bb3dd156ddca28eb334d18b20692ab1e4659f439c5",
"tests/test_mine_intel_discovery_integration.py": "bac2c8ec269d6e51a46fc17893de4114a5613f37899a1e044a9132d97d44cc5a",
"tests/test_hq_delivered_task.py": "21bf539814121af7eb98505cdfd7f48984b983de529ce0c2b6b1077a82f0a70f",
"tests/test_hq_assignment_lifecycle.py": "4cfd15d1655b7cfadcbc08104bd01cdfc9960dc88a95ebc5a9958f6f71ce4aea",
"tests/test_hq_task_reservations.py": "aa6c5a38618d4bb469c84f18fb7d1748501b4608bd1929cf7e0a6600d248c0f8",
"tests/test_terrain_takeover.py": "12365036f81e0874910f100626d2e26b4b2a83042327a927727fda87f05e80db",
"tests/test_ai_stinger_admin.py": "d645813857f85854aeca60c9010689662d7cc43f298256d73ae37b05d74e94c1",
"tests/test_native_maintenance_refuel.py": "15eb8c0ee75778fce2a1caace045940b63cd253f81d16a081f669643b9fefcae",
"tests/test_mounted_ammo_pickup.py": "cc4f70870b10beb2595ac4fb030952cc25be1fe1d9506f54dc3901fd1baecda4",
"tests/test_mounted_ammo_transfer.py": "cb354bfc71560f430101aae9421f04d601bc2cb0788500771d66ac750df8ae72",
"tests/test_mounted_resupply.py": "c17525ffeca6791b4542ea0c7641e4b220b03bce506fc2fda924aac09e8b24ce",
"tests/test_hq_mine_sampler.py": "67186d8f6609c3544a9c60f57af876b046618f9b586b2a56520d3a5c8a0e6e22",
"tests/test_hq_status_sampler.py": "b8582fb71b7ac77a23158ccd6230e8124ef0432831204e4b8992dee3a9c10062",
"tests/test_convoy_mine_stock.py": "e0073271428f00edf86251c9af5530f39094261b05474058df6b794bd958091f",
"tests/test_infantry_supply_pool.py": "6fc0053337bbb889021c6eba608796ef946ff4d30a1b01cf678927293218d9d2",
"tests/test_automatic_equipment.py": "f8cb478df7979ab9e35c2bcb084e75b2571d41e21e68c8ab28249e01f5708c92",
"tests/test_admin_providers.py": "4869c86d2cb8c17a383680d594131f4053a051eb4af369657523e20f68311de6",
"tests/test_native_mine_stock_runner.py": "51b30d4d7d7543b1674285448d382dcbca55272a0403ea977d2cf08db6a5290c",
"tests/test_native_convoy_mine_stock.py": "f069900030cb644ba9e04adb01a6d847a1afa6248a6c458f547aa4fcbd4b5a40",
"tests/test_hq_mounted_ammo_sampler.py": "a4d098adcd3d1f1156d00cf0753268f286cd63640bdae5aed81828f74a8b4633",
"tests/test_native_player_death_fixture.py": "0d0825ebb948a68ff8b8f5cbdcc7e27bdf940e5af1e277ba1780d03e12f2ba33",
"tests/test_enemy_loadout.py": "0cdfd28ce4d9c89223a7f439eaec1cad762cfc6c9e1cc4c3213d4600a3501b37",
"tests/test_enemy_equipment.py": "bbc753525bdfe05ea9ee7fcf45f3158307ed56428518b08845e097fbcdf299c0",
"tests/test_infantry_mine_transfer.py": "55caf2735f2d86aa4cc474ef2d3998f847935e0a0b0d881d5390b2039a055704",
"tests/test_infantry_mine_coordinator.py": "2fdb2138685a329cef11557973450bd5189d3d7d657dac5cc51b3df2530fab6b",
"tests/test_enemy_radio.py": "698c3ea5e1a3680d5b0438c50a341e53dd09f08d2f1f935e59667bc72ae83765",
"tests/test_hq_planner_budget.py": "53578da6fb82f4cc4210169332b1f54ac349fab05cce5513be7328218edd264a",
"tests/test_ground_depot_lifecycle.py": "927a6f15560e177c838322e18ef555ce7db3acde0651d1a43353a2c6e805f3a8",
"tests/test_ground_depot_loading.py": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755",
"tests/test_ground_depot_transfer.py": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36",
"tests/test_ground_depot_provenance.py": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85",
"tests/test_native_observer_selector.py": "bafdca52e25cc45d94f2fc306c078e5e59d48f2e2540248acc3822b42668e937",
"tests/test_chat_client_ownership.py": "c559dbda1af996455038da9eeb5ffcfc6332da9b93082da8ad3071f5d72b8bdf",
"tests/test_mine_intel.py": "db64129001c0010ad11389ff764356893ac7c4fbf45e7c82aa56bbe4c75f4929",
"tests/test_objective_map_element.py": "b02e59f977aa81462649282f99e70b0b6320b31ba0ea46f586e9ac0c5d15b884",
"tests/test_objective_map_presentation.py": "2418f4c0f370bd436b316e56d5ead97ff4b6aa7cdfb3777c9d2af22486148268",
"tests/test_native_objective_map_probe.py": "ef0663aa7d620e06fda63fef578abb397a9dcd8fe5336af5445056e32e19aa28",
"tests/test_hint_delivery.py": "6066e2b00e54553ac298a3f9b37060a23851f5ca5d4f98eb25e502b2c44240a6",
"tests/test_observer_ownership.py": "8e485c3d2e6ae90df82cbc7829996138db8e9a5a4a42a5e2bcaa3bffa61368de",
"tests/test_hq_ammo_reporting.py": "bdd4a30440501a2861aca80c951098c48cf999023eaaabd9a2eef82174f8173d",
"tests/test_hq_ammo_sampler.py": "e9c2d147eb1547be471df7459f1be815cdc9ef0a64c9a4ae4ef58936424dbc55",
"tests/test_hq_multiconvoy_supply.py": "e58d1d6eba48b2c5c6073d54c76302b2a7250ad22176fa94c386e1bc2ce65588",
"tests/test_hq_watch.py": "51d5a728b0be83ff957c0df61289d14f90aba109b49365e457c9b200d5ede36a",
"tests/test_infantry_ammo_transfer.py": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29",
"tests/test_infantry_resupply_coordinator.py": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
"tests/test_infantry_resupply_planning.py": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
"tests/test_mounted_supply_integration.py": "f52acf7a16c9d5273894eb5a4afe7657a7c97de2ed72ba06671d25e163eea5d7",
"tests/test_hq_mounted_intercept.py": "dc28ee9625d961cdbecdd6061879cd42a882f183f70a3a04670f225e61d52776",
"tests/test_hq_mounted_dispatch.py": "36c1d3dfc69d98b5b25d7c8f86a94a9d9df0745eddfef44cda378533181b7a97",
"tests/test_terrain_presentation.py": "05f070c5730a9f7f0aae9487a313342785a42682c9beebc3b10cac270b514f18",
"tests/test_terrain_selection.py": "3f43ed1d003415c7c942fe09009f386866da5ed99bb20a8ad96417d69a8423fe",
"tests/test_native_mounted_intercept.py": "24810c0a22b221604e1fd8e6596f2d409e558699c5070fef7aae1f74a4fc2f5d",
"tests/test_server_item_catalog.py": "c5aae32a55552095e49d9e7884ef88e1cdb4bdb257f850af67d387793c327e74",
"tests/test_mortar_transactions.py": "5db4ec737355a7ae995240dc93f1dce146e07c0110c2da2c23451f180b134d26",
"tests/test_native_convoy_probe.py": "c81046b5b3f7734f2f53dead61b01a3d81c96e841b7f9a4478c05702b29bde07",
"tests/test_convoy_lifecycle.py": "67e385ab8c843df1cb138ae9fc4c276bf30fda42eea63ee1303174cef2387415",
"tests/test_hunter_lifecycle.py": "4d228ec10c3d5f02ecf0eb755ca2773e3496a2c25a1e1c355e6ec79ee2ef53b6",
"tests/test_convoy_survivors.py": "415cf9f5d23cce363e483d4bfd0292b58ab1fb3d9e727f9581271aa65c1c3109",
"tests/test_hunter_capture.py": "d88b3a830c350e27a08fe5977cf85247dff140b3dc9135062eb5e7774b400790",
"tests/test_hq_mounted_intercept_pair.py": "1136c04270a7d63acbf00b8d2ce81d152e00c2110a280463fe547d6c18103d0d",
"tests/test_convoy_intercept_pair.py": "3a587a043be3482a6cc5b4d0d152a22113126b637565cc627694aceae9d66eb5",
"tests/test_native_supply_travel.py": "045c055e96ba5a19bb79406fa1ae29ca2afac6ed0770801b5623d692087e01de",
"tests/test_native_supply_travel_runner.py": "4c7e1eb4de6bec932f7462a68f4597908c4c53a279521499ff28e64ed8053e3a",
"tests/test_native_supply_travel_hook.py": "d92f80c44d5a3095ac16d539569d99d951e5bd865e904c65e91d5d6682bc0af9",
"tests/test_engineer_mine_site.py": "b174162dc0621c46835b050d7df1ab9540e2f8f3b1ee805aeba8bb6d4f956a90",
"tests/test_native_random_radius_trace.py": "a87f553de26a32b5f242c2cc8ea31564eb54d29f1d0cab7018c1c408888b8101",
"tests/test_native_random_radius_runner.py": "aa75c700906d55b098731715503ce52725a944d47b7195fcd47d222756345c75",
"tests/test_engineer_mine.py": "eb906e07963284dea3fc4510a0036df53b49c62af5ee815ec41abe5f6e1deb2d",
"tests/test_engineer_mine_posts.py": "6185b5ab6576948fd8b47bb945fbe40107ec6944eafde2d04dd60ff49d5ec89c",
"tests/test_ground_depot_mine_claim.py": "dfe117f58cdf420974fc0d821b1a4153c9fd4da7585fb3e6b872a418d22d2083",
"tests/test_welcome_voice.py": "5acad80fc7fecb08409899a5ccf81dec0d310184aafe02b70f46c58bc515e1d8",
"tests/test_item_preferences.py": "d7717f4ecb4e83556aed16cc4318fb05662f3482a1de38451f0c479a6095d4de",
"tests/test_profile_config.py": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435",
"tests/test_bmp_intercept_geometry.py": "5b3322e7f7f29dfe47e2ffc52ab71c08c16db3548b1e880d47d4bc49a5188a90",
"tests/test_intercept_vehicle_footprint.py": "5acfa2d3c16c924a5c88ae734814242dae96b168997a1bc4617476a7a48afb42",
"tests/test_recon_search.py": "75f017eb29b03389cfd1f5d03be7e70cd15e726d6777d3cd48ca19237b665192",
"tests/test_body_recovery_selection.py": "72715eedddbc443538426f4fe52cda09af60c8d132d2dbd62df6dc7286b376c9",
"tests/test_admin_menu.py": "789f88da25bbd57bb7923065fc718f70c8a18c50681dd90079931a18993b9729",
"tests/test_settings_migration.py": "eee1f5c598f5875816d89a4bc46a9e6cc0f770557abde3d264c09dc2ded27523",
"tests/test_rough_intel_feedback.py": "a7c5a956d65a1a4d4f4aca6ddb47ba07fe70d07e2f0f99030058ba67e9246422",
"tests/test_radio_waiting_text.py": "2acd7ebf18766c8436b998b57f06fcf07ec9e42a28b686e0bd95ede570a9a5d9",
"tests/test_start_settings.py": "8b4dcc9e786c5fc00a1e88f1c364fd8e9a1bf8f6fa73f1d5aebbaeb5da444cd7",
"tests/test_crash_start.py": "b65da31d60b5cdaacc8e729155b05eb1388284c9a6241549eaac49d59e1f4552",
"tests/test_hq_convoy_dispatch.py": "eab5cbc72fa6efcf4702acc4f2d2165c99b37da97c648d3c3b489234f375ecd4",
"tests/test_prison_ai.py": "9c0db6205bde7df7710acfc6bb20231f9e893b0f3913b7a2c4cfcf45e219a70d",
"tests/test_terrain_editor.py": "1736098a5ae588d7d575a9c07b024fe473a0d1e2d0183fa55a8c63e42def422a",
"tests/test_native_mounted_ammo_probe.py": "87bc8b9952be2e13fd7778af59504078e694b7bd9f0bdfea173feeec58a10f0e",
"tests/native/inventory_control/README.md": "29f7086ee223b1cfe657932c7f236a1640876503f69f6f401451c72a5452695d",
"tests/native/inventory_control/addon.gproj": "18dd7db85574119fac5057091c4d9991b247855f67f06bb86cf440f429b5911f",
"tests/native/inventory_control/Prefabs/ERRIC_InventoryMode.et.meta": "6b4f66f296d15e7e5f82928cf1bdfa58f085421ae9b6f24afc5ac922d2a8781e",
"tests/native/inventory_control/Prefabs/ERRIC_InventoryMode.et": "98408ab80347058f5b79b1103b849b19beaeb97a9ff81662b59fe6100ddd6bf8",
"tests/native/inventory_control/Worlds/ERRIC_Inventory.ent.meta": "ca0420504016fa2aa7220712d13b7bf7748832d8d58b085afc4373f4abeb1339",
"tests/native/inventory_control/Worlds/ERRIC_Inventory.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
"tests/native/inventory_control/Scripts/Game/ERRIC/ERRIC_InventoryControl.c": "8707f35ecf48813bc4e72c599fe2527c44807493496218d18e89aa8739eb59f9",
"tests/native/inventory_control/Scripts/WorkbenchGame/ERRIC/ERRIC_InventoryControlPlugin.c": "000d8fa3aa6412a5adb1561333f840f27185dc42fa61569c311b0607df0f2420",
"tests/native/inventory_control/Worlds/ERRIC_Inventory_Layers/default.layer": "80a5f0b6c1bc8761469ea69978967dffc070ba9f98c5125430a78a506684c39e"
}
@@ -0,0 +1,47 @@
{
"exit": 0,
"inputs_unchanged": true,
"programs": [
{
"path": "tests/test_native_mounted_ammo_probe.py",
"exit": 0
},
{
"path": "tests/test_native_mounted_swap_probe.py",
"exit": 0
},
{
"path": "tests/test_native_mounted_courier_probe.py",
"exit": 0
},
{
"path": "tests/test_native_convoy_mine_stock.py",
"exit": 0
},
{
"path": "tests/test_native_mine_stock_runner.py",
"exit": 0
},
{
"path": "tests/test_native_memory_deadlines.py",
"exit": 0
},
{
"path": "tests/test_convoy_budget.py",
"exit": 0
},
{
"path": "tests/test_supply_convoys.py",
"exit": 0
},
{
"path": "tests/test_hq_mounted_ammo_sampler.py",
"exit": 0
},
{
"path": "tests/test_hq_watch.py",
"exit": 0
}
],
"fresh_full_suite_claimed": false
}
@@ -0,0 +1,5 @@
Traceback (most recent call last):
File "/tmp/erri-bmp-native-2103/run-focused.py", line 5, in <module>
assert all((R/'tests'/n).is_file() for n in names),names
~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: ['test_native_mounted_ammo_probe.py', 'test_native_mounted_swap_probe.py', 'test_native_mounted_courier_probe.py', 'test_native_convoy_mine_stock.py', 'test_native_mine_stock_runner.py', 'test_native_memory_deadlines.py', 'test_convoy_budget.py', 'test_supply_convoys.py', 'test_hq_mounted_ammo_sampler.py', 'test_hq_watchdog.py']
@@ -0,0 +1,25 @@
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
PASS: actual BMP capture requires complete armed exact original resource; pinned delivery/slot checks and isolated CLI flag
PASS: actual opt-in pre-unlock isolation refuses wrong mode/phase/flag and existing hunters; no baseline service changes
PASS: actual once-only native dry query, exact before/after slots, native refusal, shutdown; shared bounded discovery and distinct opt-in verdict
PASS: actual completion selector and pre-cleanup variant capture preserve separate radio and eligibility verdicts
PASS: actual cargo diagnostic stages separate absent/foreign magazines, used/empty/invalid rounds, well mismatch and exact truck storage/attachment without mutation
PASS: actual native courier witness rejects missing radio/custody/swap/reboard evidence; CLI opt-in bounded; native success remains unqualified
PASS: actual courier constructor/Tick waits for preparation, returns before physical checks, preserves fixed deadline and sticky stop/failure; Enfusion startup awaits native verification
PASS: actual optional candidate barrier, exact callback/custody proof and unchanged mine/primary snapshots; no native transfer claim
Native finite mine-stock runner: parser, scope, exclusions and command pass
PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines
PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths
PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged
PASS: actual patrol fixture leaves prison before responder HQ proof, followed by separate permanent-patrol observation
PASS: exact patrol-hq finite responder preparation and native search-radius receipt verification
PASS: actual convoy receipt identity/one-use, shared60-body and128-formation caps, outstanding/native-ledger accounting, exact19-body composition, source reuse, mode/client guards and no consumed receipt refunds
PASS: actual supply route cycling/arrival/stops, finite startup bounds, contact freshness, dismount hold, quiet interval, interrupted boarding, timeout and lost-truck release
PASS: moving-convoy perception boundaries and scoped individual/group abandonment priorities
PASS: actual supply startup reasons expose unchanged body budget/requirement, journal only failure changes, preserve retry cadence/caps and report the true final refusal
PASS: actual combat start releases only exact intercept claims before owning route/orders; foreign claim defers combat takeover
PASS: actual mounted hierarchy sampling, ownership exclusion, deduplication, completeness/caps, quarter threshold and detached validation; no runtime policy or ammunition mutation
PASS: WORKBENCH opt-in diagnostics distinguish cycles/cap/storage/manager/mount failures without repeated native traversal
PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence, detached/validated mounted payload replacement 256-record cap and detached carried-mine radio delivery/chronology
Focused result 0 10 programs inputs unchanged True
@@ -0,0 +1,8 @@
{
"read_only": true,
"host_visible": true,
"game_process_check": "An Arma Reforger game process already exists (PID 3363484); leave it untouched",
"prefix_process_check": "clear",
"native_run_attempted": false,
"existing_game_left_untouched": true
}
@@ -0,0 +1,9 @@
{
"priority": "When the host has no existing game and the private prefix is idle, run the already implemented and reviewed mounted-ammo --mounted-bmp fixture once, with project chat, one round, timeout420 and a fresh prison0 profile. Keep its180-second proof deadline and all production limits unchanged.",
"native_command_arguments": ["--project", "chat", "--smoke", "mounted-ammo", "--mounted-bmp", "--rounds", "1", "--timeout", "420"],
"scope": "Opening hunters and new town admissions are explicitly stopped only for this opt-in Workbench accounting fixture before prison exit. Original site troops and ordinary automatic convoy target3/shared cap135/finite stock remain intact. Proof must identify original slot4 BMP with complete armed counts and its own real radio-delivered snapshot; a UAZ cannot satisfy it.",
"not_a_production_fix": "The prior117+25>135 refusal obeyed the documented shared body admission ceiling. No bug was demonstrated in that accounting; no cap, target, scheduling deadline or production admission behavior changed.",
"existing_candidate": ".build/playtest-2026-10-03-crash-start remains the current development handoff; it predates only this new diagnostic, not a new ordinary-gameplay feature.",
"avoid": ["No repeated identical package rebuild", "No production cap increases to satisfy a fixture", "No prison input automation", "No experimental AI flight", "No touching an existing game or physical display/audio defaults"],
"remaining_acceptance": "Physical support reliability, manual escape, real multiplayer/JIP/reconnect/partial escape, comparative FPS and clean release remain unqualified."
}
@@ -0,0 +1,48 @@
{
"complete": true,
"original": {
"missing": [],
"changed": [],
"count": 533,
"unexpected": [],
"manifest_sha256": "661c5ddf080c4ba8d4463aa4907f739d4d96acaa8694ac8d6f3d85bb94231226"
},
"candidates": {
"crash-start": {
"missing": [],
"changed": [],
"count": 446,
"unexpected": [],
"manifest_sha256": "8a594a8e340694efaf9874834c05713a40a6d223bbc08491fb42ae84bcce625f"
},
"depot-mines": {
"missing": [],
"changed": [],
"count": 432,
"unexpected": [],
"manifest_sha256": "c91acda173e2914fea59fd3e264a451158ee21d85918fe1ec5c8312dd46f7074"
},
"ground-supply": {
"missing": [],
"changed": [],
"count": 432,
"unexpected": [],
"manifest_sha256": "0b58fde4127486894917db58ce92b684f984233b341317418e336b1740cac107"
},
"mine-safety": {
"missing": [],
"changed": [],
"count": 431,
"unexpected": [],
"manifest_sha256": "202fa0854cf60a6c08ace1f22b276d826abcb538c79b6e052b48e5e51f458a87"
},
"mounted-pair": {
"missing": [],
"changed": [],
"count": 429,
"unexpected": [],
"manifest_sha256": "9fee715f8c9c324c465387ba1f88744c9c3748cb49668ce65e9c9500a38b14d7"
}
},
"staged_diff_sha256": "670073db5d7531aca4466cc9d2827d10a46bfcfbd35f27ac97724de9d2fd3725"
}
@@ -0,0 +1,24 @@
from pathlib import Path
import json,hashlib,subprocess
R=Path('/home/jakub/devel/escapistsrereintroduced');B=Path('/tmp/erri-bmp-native-2103')
def sha(p):
h=hashlib.sha256()
with p.open('rb') as f:
while chunk:=f.read(1024*1024):h.update(chunk)
return h.hexdigest()
def verify(root,manifest,exact=False):
data=json.loads(manifest.read_text()); missing=[];changed=[]
for n,h in data.items():
p=root/n
if not p.is_file():missing.append(n)
elif sha(p)!=h:changed.append(n)
actual={str(p.relative_to(root)) for p in root.rglob('*') if p.is_file()} if exact else set(data)
return {'missing':missing,'changed':changed,'count':len(data),'unexpected':sorted(actual-set(data)),'manifest_sha256':sha(manifest)}
original=verify(Path('/home/jakub/devel/escapists'),Path('/tmp/erri-heartbeat-20260930-1542-reference.json'))
candidates={n:verify(R/'.build'/('playtest-2026-10-03-'+n),R/'docs/evidence'/('playtest-refresh-2026-10-03-'+n)/'candidate-sha256.json',True) for n in ['crash-start','depot-mines','ground-supply','mine-safety','mounted-pair']}
staged=hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=R)).hexdigest()
baseline=json.loads((B/'baseline.json').read_text())
assert staged==baseline['staged_diff_sha256']
for result in [original,*candidates.values()]:assert not result['missing'] and not result['changed'] and not result['unexpected'],result
(B/'preservation.json').write_text(json.dumps({'complete':True,'original':original,'candidates':candidates,'staged_diff_sha256':staged},indent=2)+'\n')
print('Original533, five sealed candidates and staged diff unchanged')
@@ -0,0 +1,45 @@
--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
@@ -1,5 +1,21 @@
// Explicit, local Workbench diagnostic only. Never compiled into game/server builds.
#ifdef WORKBENCH
+modded class ERR_HQ
+{
+ bool ERR_IsolateMountedBMP()
+ {
+ string bmp;
+ if (!ERR_NativeMountedAmmoProbe.Enabled() || !System.GetCLIParam("errMountedBMP", bmp) || bmp != "1"
+ || !m_Mode || m_Mode != ERR_GameMode.Get() || m_Mode.StartMode() != 0 || m_Mode.Phase() != ERR_Phase.PRISON
+ || !m_Hunters || m_Hunters.Deployed() != 0 || !m_Towns) return false;
+ // Neither service ticks in PRISON. Town creation is synchronous; there are
+ // no queued town soldiers to cancel or existing populations to refund here.
+ m_Hunters.Stop();
+ m_Towns.Stop();
+ return true;
+ }
+}
+
modded class ERR_GameMode
{
// Read-only normal-route stock witness; no courier, movement or arming action.
@@ -838,6 +854,20 @@
}
if (m_ERRTestMountedAmmo)
{
+ string mountedBMP;
+ if (System.GetCLIParam("errMountedBMP", mountedBMP) && mountedBMP == "1")
+ {
+ string bmpMines, bmpSwap, bmpCourier;
+ bool mixedBMP = (System.GetCLIParam("errMineStock", bmpMines) && bmpMines == "1")
+ || (System.GetCLIParam("errMountedSwapEligibility", bmpSwap) && bmpSwap == "1")
+ || (System.GetCLIParam("errMountedCourier", bmpCourier) && bmpCourier == "1");
+ if (!ERR_Check(!mixedBMP && StartMode() == 0 && Phase() == ERR_Phase.PRISON,
+ "BMP accounting isolation requires prison start and no mine/swap/courier variants")) return;
+ ERR_HQ bmpHQ = ERR_HQ.Get();
+ if (!ERR_Check(bmpHQ && bmpHQ.ERR_IsolateMountedBMP(),
+ "BMP accounting isolation precedes opening hunter and town admissions")) return;
+ Print("ERR BMP FIXTURE: opening hunters and new town admissions stopped before prison escape; original site troops, automatic convoy target, body cap, stock and proof deadline unchanged");
+ }
// Protect only this diagnostic observer while normal enemy forces continue.
DamageManagerComponent mountedObserverDamage = DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent));
if (!ERR_Check(mountedObserverDamage != null, "mounted observer has native damage component")) return;
@@ -0,0 +1,10 @@
{
"files": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": {
"baseline_sha256": "e2a32dbe372edc2f5cd03a55dcb3dd11689ad8b60940a7a318b0c829d464d3e2",
"proposal_sha256": "b7e1857b0678b3a2c71880c0f35b09da9e978f19bacf5b4e7449c893fdbe2b95"
}
},
"patch_sha256": "792b3670fda0aaadbb09bbf23a7a34981129e93302372cbbea512467fb601c19",
"scope": "WORKBENCH mounted-ammo+errMountedBMP fixture only. Before initial prison exit, stop unstarted hunters/town admissions. No actors deleted/refunded, settings/caps/targets/deadlines unchanged. No tests/compiler/native run."
}
@@ -0,0 +1,34 @@
/tmp/err-policy-iqjo2mvy/check.cpp:11:33: error: declaration of ‘Entity* ERR_ConvoyVehicle::Entity’ changes meaning of ‘Entity’ [-Wchanges-meaning]
11 | struct ERR_ConvoyVehicle{Entity*Entity=nullptr;bool Registered=true;int Group=1;};
| ^~~~~~
/tmp/err-policy-iqjo2mvy/check.cpp:11:26: note: used here to mean ‘struct Entity’
11 | struct ERR_ConvoyVehicle{Entity*Entity=nullptr;bool Registered=true;int Group=1;};
| ^~~~~~
/tmp/err-policy-iqjo2mvy/check.cpp:7:8: note: declared here
7 | struct Entity{Prefab prefab;Prefab*GetPrefabData(){return &prefab;}};
| ^~~~~~
/tmp/err-policy-iqjo2mvy/check.cpp: In member function ‘void Probe::Capture(ERR_HQ*, ERR_ConvoyVehicle*, float)’:
/tmp/err-policy-iqjo2mvy/check.cpp:41:76: error: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<int>::size_type’ {aka ‘long unsigned int’} [-Werror=sign-compare]
41 | && unit->Uplink->MessageId == report->MessageId && unit->Uplink->Cursor < unit->Uplink->Nodes.size(), "original mounted payload observed before real radio delivery")) return;
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
Traceback (most recent call last):
File "/tmp/erri-mounted-bmp-probe/tests/test_native_mounted_ammo_probe.py", line 172, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<33 lines>...
}
^
'''.replace(';if(', ';\n if('))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 13, in run
subprocess.run(['g++','-std=c++17','-Wall','-Werror',str(p/'check.cpp'),'-o',str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['g++', '-std=c++17', '-Wall', '-Werror', '/tmp/err-policy-iqjo2mvy/check.cpp', '-o', '/tmp/err-policy-iqjo2mvy/check']' returned non-zero exit status 1.
@@ -0,0 +1,19 @@
check: /tmp/err-policy-oooz7m9i/check.cpp:115: int main(): Assertion `s.p.captures==3' failed.
Traceback (most recent call last):
File "/tmp/erri-mounted-bmp-probe/tests/test_native_mounted_ammo_probe.py", line 40, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<64 lines>...
}
^
'''.replace(';if(', ';\n if('))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
subprocess.run([str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/tmp/err-policy-oooz7m9i/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,8 @@
{
"finding": "Existing mounted witness allowed BMP Complete=false if Valid and could prove natural radio delivery from a UAZ. Thus it did not qualify the exact WCS BMP controls exclusion. No production defect demonstrated.",
"fix": "Opt-in --mounted-bmp restricted to Chat mounted-ammo one round at least360s without mine/swap/courier. Capture only task slot4, exact BMP prefab plus Complete/Valid/nonzero armed snapshot. Fleet retains all6 roots and existing cargo proof, requires same BMP completeness; final delivered detached-copy proof retains exact slot4 vehicle/root/crew and queued snapshot. Interrupted reports may retry naturally on same proof task without deadline reset.",
"unchanged": "Default target3, body budget/admission,180s fixed proof deadline, cargo/roster/freshness/copy checks, default mounted/swap/courier/mine behavior, production sampler/report/order logic. Hegel separate hook explicitly isolates unrelated hunter/town admissions before canonical prison unlock.",
"test_boundaries": "Actual Capture/BMPReady/Tick/Candidate/Forget/Stop and hook isolation methods executed. Native inventory, reporter/roster identity and snapshot Valid are explicit doubles; actual sampler has existing separate tests. Fleet source condition preserved/reviewed, not full native Fleet execution in this harness. Baseline compiles then fails first slot-only capture assertion. Removing Complete guard compiles then fails actual Capture incomplete rejection.",
"native_qualification": "Pending parent native run. No firing, consumption, reload, stock transfer, autonomous interception or physical travel proof claimed.",
"compilers_finished": true
}
@@ -0,0 +1,283 @@
--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c
@@ -35,6 +35,8 @@
protected bool m_FleetReady;
protected bool m_SwapEligibility;
protected bool m_MineStock;
+ protected bool m_BMP;
+ protected ref ERR_ConvoyVehicle m_BMPVehicle;
protected bool m_MountedDiagnosticPrinted;
protected ref ERR_ConvoyMineStock m_MineBatch;
protected ref ERR_ConvoyVehicle m_MineTruck;
@@ -58,11 +60,14 @@
void ERR_NativeMountedAmmoProbe(ERR_GameMode mode, float now)
{
m_Mode = mode; m_Deadline = now + 180000;
- string swap, mines, courier;
+ string swap, mines, courier, bmp;
+ m_BMP = System.GetCLIParam("errMountedBMP", bmp) && bmp == "1";
m_MineStock = System.GetCLIParam("errMineStock", mines) && mines == "1";
m_SwapEligibility = System.GetCLIParam("errMountedSwapEligibility", swap) && swap == "1";
if (m_MineStock && (m_SwapEligibility || (System.GetCLIParam("errMountedCourier", courier) && courier == "1")))
Check(false, "mine-stock proof requires the normal mounted radio path, without swap or courier flags");
+ if (m_BMP && (m_MineStock || m_SwapEligibility || (System.GetCLIParam("errMountedCourier", courier) && courier == "1")))
+ Check(false, "BMP proof requires the normal mounted radio path, without mine, swap or courier flags");
if (m_SwapEligibility) m_SwapProbe = new ERR_NativeMountedSwapProbe();
}
bool SwapEligibility() { return m_SwapEligibility; }
@@ -100,6 +105,13 @@
}
return !vehicle.Members.IsEmpty();
}
+ protected bool BMPReady(ERR_ConvoyVehicle vehicle, ERR_HQMountedAmmoSnapshot sample)
+ {
+ return vehicle && vehicle.Entity && vehicle.Entity.GetPrefabData()
+ && vehicle.Entity.GetPrefabData().GetPrefabName() == ERR_ConvoyResources.VehiclePrefab(4)
+ && sample && sample.Valid() && sample.Complete && sample.Weapons > 0 && sample.Magazines > 0
+ && sample.Rounds + sample.Chambers > 0;
+ }
protected void Capture(ERR_HQ hq, ERR_ConvoyVehicle vehicle, float now)
{
if (m_Queued || !vehicle || !vehicle.Registered) return;
@@ -107,10 +119,12 @@
if (!Original(vehicle, unit) || !unit.PendingStatus || !unit.Uplink) return;
ERR_HQStatusReport report = unit.PendingStatus;
if (!report.MountedAmmo || report.MountedAmmo.Weapons < 1 || report.MountedAmmo.Magazines < 1) return;
+ if (m_BMP && !BMPReady(vehicle, report.MountedAmmo)) return;
ERR_HQWatchEntry before = hq.Watch().Find(report.SourceId);
if (before && before.MessageId >= report.MessageId) return;
if (!Check(ERR_HQWatchRules.Valid(report, now) && report.SourceId == unit.StatusSampler.InitialSourceId()
&& unit.Uplink.MessageId == report.MessageId && unit.Uplink.Cursor < unit.Uplink.Nodes.Count(), "original mounted payload observed before real radio delivery")) return;
+ if (m_BMP) m_BMPVehicle = vehicle;
m_Unit = unit; m_Root = vehicle.Entity; m_Queued = report;
m_Payload = report.MountedAmmo.Snapshot(); m_Route = unit.Uplink; m_RoutePayload = m_Route.Payload;
Check(m_Payload != report.MountedAmmo && Same(m_Payload, report.MountedAmmo)
@@ -208,7 +222,7 @@
{
ERR_ConvoyVehicle vehicle = task.Vehicles[slot];
if (!Check(vehicle && Original(vehicle, hq.ERR_MountedFixtureUnit(vehicle.Group)), "root retains original admitted seated crew and ledger")) return false;
- bool diagnose = m_MineStock && slot == 1 && !m_MountedDiagnosticPrinted;
+ bool diagnose = ((m_MineStock && slot == 1) || (m_BMP && slot == 4)) && !m_MountedDiagnosticPrinted;
if (diagnose) ERR_HQMountedAmmoSampler.BeginDiagnostic();
ERR_HQMountedAmmoSnapshot sample = ERR_HQMountedAmmoSampler.Inspect(vehicle.Entity);
if (diagnose)
@@ -225,6 +239,7 @@
if (!Check(sample && sample.Valid(), "native root returns bounded valid snapshot")) return false;
PrintFormat("ERR MOUNTED SAMPLE: source=%1 slot=%2 complete=%3 weapons=%4 muzzles=%5 magazines=%6", task.Receipt.SourceId, slot, sample.Complete, sample.Weapons, sample.Muzzles, sample.Magazines);
PrintFormat("ERR MOUNTED COUNTS: slot=%1 rounds=%2 capacity=%3 chambers=%4 low=%5", slot, sample.Rounds, sample.Capacity, sample.Chambers, sample.LowMagazines);
+ if (m_BMP && slot == 4 && !Check(BMPReady(vehicle, sample), "original slot4 BMP has complete valid armed mounted counts")) return false;
if (sample.Weapons > 0 && sample.Magazines > 0) armed = true;
if (slot == 1)
{
@@ -277,7 +292,11 @@
{
ERR_ConvoyTask task = hq.Convoys().At(convoy);
if (!task || (m_ProofTask && task != m_ProofTask)) continue;
- for (int slot = 0; slot < task.Vehicles.Count() && slot < 6; slot++) Capture(hq, task.Vehicles[slot], now);
+ for (int slot = 0; slot < task.Vehicles.Count() && slot < 6; slot++)
+ {
+ if (m_BMP && slot != 4) continue;
+ Capture(hq, task.Vehicles[slot], now);
+ }
}
if (!m_FleetReady) m_FleetReady = Fleet(hq);
if (m_Failed) return -1;
@@ -301,6 +320,10 @@
&& delivered.Fit == m_Queued.Fit && m_Route.MessageId == m_Queued.MessageId
&& m_Route.Payload == m_RoutePayload, "delivered observation age, roster counts and radio payload preserved")) return -1;
if (!Check(hq.ERR_MountedFixtureUnit(m_Unit.Group) == m_Unit && ERR_Actors.Alive(m_Root), "original source and root retained through delivery")) return -1;
+ if (m_BMP && !Check(m_ProofTask && m_ProofTask.Vehicles.Count() == 6
+ && m_BMPVehicle && m_ProofTask.Vehicles[4] == m_BMPVehicle && m_BMPVehicle.Entity == m_Root
+ && Original(m_BMPVehicle, m_Unit) && BMPReady(m_BMPVehicle, m_Payload),
+ "same original slot4 BMP and complete armed queued snapshot retained through actual radio delivery")) return -1;
if (!Mines(m_ProofTask, false)) return -1;
return 1;
}
@@ -309,7 +332,7 @@
if (hq.SupplyConvoys().Target() == 3 && hq.Convoys().Count() <= 3) return true;
return Check(false, "unchanged default three-convoy production target");
}
- protected void Forget() { m_Unit = null; m_Root = null; m_Queued = null; m_Payload = null; m_Route = null; m_RoutePayload = string.Empty; }
+ protected void Forget() { m_BMPVehicle = null; m_Unit = null; m_Root = null; m_Queued = null; m_Payload = null; m_Route = null; m_RoutePayload = string.Empty; }
void Stop()
{
m_Stopped = true; if (m_SwapProbe) m_SwapProbe.Stop();
--- a/tools/headless_workbench.py
+++ b/tools/headless_workbench.py
@@ -18,6 +18,7 @@
p.add_argument('--trace-random-radius', action='store_true', help='Workbench-only read-only zero-radius caller traces; one normal Chat round, capped at sixteen records')
p.add_argument('--maintenance-refuel', action='store_true', help='Opt-in normal-route check: original held Southern fuel can transfers finite fuel through its native UAZ action; one arranged tank depletion, no stock creation')
p.add_argument('--mounted-swap-eligibility', action='store_true', help='Read-only mounted-ammo variant: one exact finite cargo/mounted magazine CanSwap call; no transfer or radio proof')
+p.add_argument('--mounted-bmp', action='store_true', help='Read-only original BMP slot4 complete mounted counts and its natural HQ radio delivery; isolates unrelated opening hunters before unlock')
p.add_argument('--mine-stock', action='store_true', help='Read-only mounted-ammo check of exact callback-proved finite PMN4 cargo before and after natural radio delivery')
p.add_argument('--mounted-courier', action='store_true', help='Mounted-ammo variant: intentionally deplete one original installed magazine, then require natural HQ radio, finite pickup, native exchange and original-seat return')
p.add_argument('--mounted-intercept', action='store_true', help='After convoy driving, two synthetic witness samples exercise real HQ radio/planning and original escort detour/hold/expiry/resume')
@@ -71,6 +72,7 @@
if a.smoke == 'supply-convoys' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 900): p.error('supply-convoys requires Chat, one round, and at least900 seconds')
if a.smoke == 'alarm-hearing' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('alarm-hearing requires Chat, exactly one round, and timeout at least360 seconds')
if a.smoke == 'mounted-ammo' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('mounted-ammo requires Chat, exactly one round, and timeout at least360 seconds')
+if a.mounted_bmp and (a.smoke != 'mounted-ammo' or a.project != 'chat' or a.rounds != 1 or a.timeout < 360 or a.mine_stock or a.mounted_courier or a.mounted_swap_eligibility): p.error('--mounted-bmp requires Chat mounted-ammo, one round, timeout at least360 seconds, without mine/courier/swap flags')
if a.smoke == 'convoy' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 600): p.error('convoy requires Chat, exactly one round, and timeout at least600 seconds')
if a.smoke == 'infantry-transfer' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('infantry-transfer requires Chat, one round and timeout at least360 seconds')
if a.smoke == 'hq-local-handoff' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('hq-local-handoff requires Chat, one round and timeout at least360 seconds')
@@ -137,6 +139,7 @@
if a.mounted_intercept: command += ['-errMountedIntercept', '1']
if a.mounted_swap_eligibility: command += ['-errMountedSwapEligibility', '1']
if a.mounted_courier: command += ['-errMountedCourier', '1']
+if a.mounted_bmp: command += ['-errMountedBMP', '1']
if a.mine_stock: command += ['-errMineStock', '1']
if a.maintenance_refuel: command += ['-errMaintenanceRefuel', '1']
if a.trace_random_radius: command += ['-errTraceRandomRadius', '1']
--- a/tests/test_native_mounted_ammo_probe.py
+++ b/tests/test_native_mounted_ammo_probe.py
@@ -4,8 +4,8 @@
from policy_harness import ROOT, body, run
ROOT=Path(os.environ.get('ERR_NATIVE_SWAP_ROOT',ROOT))
p=Path(os.environ.get('ERR_NATIVE_MOUNTED_AMMO_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c'))
-s=p.read_text();smoke=(ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c').read_text()
-runner=(ROOT/'tools/headless_workbench.py').read_text()
+s=p.read_text();smoke=Path(os.environ.get('ERR_NATIVE_SMOKE_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')).read_text()
+runner=Path(os.environ.get('ERR_NATIVE_MOUNTED_RUNNER',ROOT/'tools/headless_workbench.py')).read_text()
assert s.startswith('#ifdef WORKBENCH') and s.rstrip().endswith('#endif')
for forbidden in ('Spawn(', 'SpawnEntity', 'TrySpawn', '.Ingest(', '.Advance(', '.Dispatch(', '.BindVehicle(', '.Sample(',
'.SetOrigin(', '.SetAmmoCount(', '.Kill(', '.SetHealth(', 'NextStatus =', 'PendingStatus =', 'Uplink =', 'new ERR_HQStatusReport'):
@@ -34,7 +34,7 @@
code=code.replace('string.Empty','string{}').replace('protected ','').replace('null','nullptr').replace('ERR_GameMode.Get()', 'ERR_GameMode::Get()').replace('ERR_Actors.Alive(', 'ERR_Actors::Alive(')
for t in ('ERR_HQMountedAmmoSnapshot','ERR_HQ','ERR_ConvoyTask','ERR_HQWatchEntry'):
code=re.sub(r'\b'+t+r' (?=\w)',t+'* ',code)
-for var in ('a','b','hq','m_Mode','task','m_Queued','delivered','m_Unit','m_Route','m_ProofTask','m_SwapProbe'):
+for var in ('a','b','hq','m_Mode','task','m_Queued','delivered','m_Unit','m_Route','m_ProofTask','m_SwapProbe','m_BMPVehicle'):
code=re.sub(r'\b'+var+r'\.',var+'->',code)
for call in ('Convoys()','SupplyConvoys()','Watch()'):code=code.replace(call+'.',call+'->')
run(r'''
@@ -49,16 +49,16 @@
struct Route{int MessageId=7;string Payload="original";};struct Unit{int Group=1;Report* PendingStatus=nullptr;Route* Uplink=nullptr;};
struct ERR_GameMode{bool active=true;static inline ERR_GameMode* current=nullptr;static ERR_GameMode* Get(){return current;}bool Active(){return active;}};
template<class T>struct Arr:std::vector<T>{int Count(){return this->size();}void Clear(){this->clear();}};
-struct ERR_ConvoyTask{bool Stopped=false;Arr<int> Vehicles;};struct Pool{int count=3;int Count(){return count;}ERR_ConvoyTask* At(int){return nullptr;}};
+struct Escort{Root* Entity=nullptr;};struct ERR_ConvoyTask{bool Stopped=false;Arr<Escort*> Vehicles;};struct Pool{ERR_ConvoyTask* task=nullptr;int count=3;int Count(){return count;}ERR_ConvoyTask* At(int){return task;}};
struct Supply{int target=3;int Target(){return target;}string Status(){return "fixture production status";}};struct Watch{ERR_HQWatchEntry* entry=nullptr;ERR_HQWatchEntry* Find(string){return entry;}};
struct ERR_HQ{Pool pool;Supply supply;struct Watch watch;Unit* unit=nullptr;
Pool* Convoys(){return &pool;}Supply* SupplyConvoys(){return &supply;}struct Watch* Watch(){return &watch;}Unit* ERR_MountedFixtureUnit(int){return unit;}};
template<class... T>void PrintFormat(T...){}
struct SwapProbe{int result=1,calls=0,stops=0;int Tick(ERR_GameMode*,ERR_HQ*,ERR_ConvoyTask*){calls++;return result;}void Stop(){stops++;}};
-struct Probe{bool m_MineStock=false,mineProof=true;int mineChecks=0;void*m_MineBatch=nullptr,*m_MineTruck=nullptr,*m_MineInventory=nullptr;Arr<int>m_Mines,m_PrimaryCargo;bool Mines(ERR_ConvoyTask*,bool){mineChecks++;return !m_MineStock||mineProof;}bool m_SwapEligibility=false;SwapProbe* m_SwapProbe=nullptr;ERR_ConvoyTask* candidate=nullptr;ERR_ConvoyTask* Candidate(ERR_HQ*){return candidate;}bool m_Stopped=false,m_Failed=false,m_FleetReady=false,fleet=true;float m_Deadline=180000,m_NextLog=0;
+struct Probe{bool m_BMP=false,original=true;Escort*m_BMPVehicle=nullptr;bool Original(Escort*,Unit*){return original;}bool BMPReady(Escort*,ERR_HQMountedAmmoSnapshot*s){return s&&s->Complete&&s->Weapons>0&&s->Magazines>0&&s->Rounds+s->Chambers>0;}bool m_MineStock=false,mineProof=true;int mineChecks=0;void*m_MineBatch=nullptr,*m_MineTruck=nullptr,*m_MineInventory=nullptr;Arr<int>m_Mines,m_PrimaryCargo;bool Mines(ERR_ConvoyTask*,bool){mineChecks++;return !m_MineStock||mineProof;}bool m_SwapEligibility=false;SwapProbe* m_SwapProbe=nullptr;ERR_ConvoyTask* candidate=nullptr;ERR_ConvoyTask* Candidate(ERR_HQ*){return candidate;}bool m_Stopped=false,m_Failed=false,m_FleetReady=false,fleet=true;float m_Deadline=180000,m_NextLog=0;
ERR_ConvoyTask* m_ProofTask=nullptr;ERR_GameMode* m_Mode=nullptr;Report* m_Queued=nullptr;ERR_HQMountedAmmoSnapshot* m_Payload=nullptr;Route* m_Route=nullptr;
int captures=0;string m_RoutePayload="original";Unit* m_Unit=nullptr;Root* m_Root=nullptr;
- bool Check(bool b,string){if(!b)m_Failed=true;return b;}bool Fleet(ERR_HQ*){return fleet;}void Capture(ERR_HQ*,int,float){captures++;}
+ bool Check(bool b,string){if(!b)m_Failed=true;return b;}bool Fleet(ERR_HQ*){return fleet;}void Capture(ERR_HQ*,Escort*,float){captures++;}
'''+code+r'''
};
struct Setup{ERR_GameMode mode;ERR_HQ hq;Probe p;Root root;Unit unit;Route route;Report queued;ERR_HQWatchEntry delivered;
@@ -67,6 +67,14 @@
unit.PendingStatus=&queued;unit.Uplink=&route;queued.MountedAmmo=&original;delivered.MountedAmmo=&received;hq.watch.entry=&delivered;hq.unit=&unit;}
};
int main(){
+ // BMP delivery cannot succeed through a different slot/root, lost ownership or incomplete payload.
+ for(int fault=0;fault<6;fault++){Setup s;ERR_ConvoyTask task;Escort bmp,other;Root replacement;
+ task.Vehicles.resize(6);bmp.Entity=&s.root;task.Vehicles[4]=&bmp;s.p.m_BMP=true;s.p.m_BMPVehicle=&bmp;s.p.m_ProofTask=&task;s.hq.pool.task=&task;
+ if(fault==1)task.Vehicles[4]=&other;if(fault==2)bmp.Entity=&replacement;if(fault==3)s.p.original=false;
+ if(fault==4){s.payload.Complete=false;s.original.Complete=false;s.received.Complete=false;}
+ if(fault==5){s.payload.Rounds=0;s.payload.Chambers=0;s.original=s.payload;s.received=s.payload;}
+ assert(s.p.Tick(&s.hq,3000)==(fault==0?1:-1));assert(s.p.captures==3); // exactly slot4 per observed task, never other slots
+ }
{Setup s;s.p.m_MineStock=true;s.p.mineProof=false;assert(s.p.Tick(&s.hq,3000)==-1&&s.p.mineChecks==1);}
{Setup s;s.p.m_MineStock=true;s.p.m_Mines.push_back(1);s.p.m_PrimaryCargo.push_back(2);s.p.m_MineBatch=&s;s.p.Stop();assert(s.p.m_Mines.empty()&&s.p.m_PrimaryCargo.empty()&&!s.p.m_MineBatch);}
{Setup s;SwapProbe dry;ERR_ConvoyTask task;s.p.m_SwapEligibility=true;s.p.m_SwapProbe=&dry;s.p.candidate=&task;
@@ -143,3 +151,95 @@
}
''')
print('PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound')
+
+# Execute the exact Capture and BMPReady methods; native identity/roster/watch
+# boundaries are explicit doubles, while the snapshot validator has its own full suite.
+selected=[]
+if 'protected bool BMPReady(' in s: selected.append(body(p,'protected bool BMPReady('))
+selected.append(body(p,'protected void Capture('))
+capture='\n'.join(selected).replace('protected ','').replace('null','nullptr')
+for ns in ('ERR_ConvoyResources','ERR_HQWatchRules'):
+ capture=capture.replace(ns+'.',ns+'::')
+for t in ('ERR_ConvoyVehicle','ERR_HQMountedAmmoSnapshot','ERR_HQ','ERR_HQUnit','ERR_HQStatusReport','ERR_HQWatchEntry'):
+ capture=re.sub(r'\b'+t+r' (?=\w)',t+'* ',capture)
+for v in ('vehicle','sample','hq','unit','report','before','m_Route','m_Payload'):
+ capture=re.sub(r'\b'+v+r'\.',v+'->',capture)
+for x in ('Entity','MountedAmmo','StatusSampler','Uplink'):
+ capture=capture.replace('.'+x+'.','.'+x+'->').replace('->'+x+'.','->'+x+'->')
+for x in ('GetPrefabData()','Watch()'):
+ capture=capture.replace(x+'.',x+'->')
+capture=capture.replace('unit->Uplink->Nodes.Count()', 'int(unit->Uplink->Nodes.size())')
+run(r'''
+#include <cassert>
+#include <string>
+#include <vector>
+struct string:std::string{using std::string::string;string(const std::string&s):std::string(s){}bool Contains(const char*s){return find(s)!=npos;}};
+struct Prefab{string name="bmp";string GetPrefabName(){return name;}};
+struct Entity{Prefab prefab;Prefab*GetPrefabData(){return &prefab;}};
+struct ERR_ConvoyResources{static string VehiclePrefab(int slot){assert(slot==4);return "bmp";}};
+struct ERR_HQMountedAmmoSnapshot{bool Complete=true,valid=true;int Weapons=3,Magazines=3,Rounds=80,Chambers=1;
+ bool Valid(){return valid;}ERR_HQMountedAmmoSnapshot*Snapshot(){return new ERR_HQMountedAmmoSnapshot(*this);}};
+struct ERR_ConvoyVehicle{struct Entity*Entity=nullptr;bool Registered=true;int Group=1;};
+struct ERR_HQStatusReport{ERR_HQMountedAmmoSnapshot*MountedAmmo=nullptr;int MessageId=7;string SourceId="source";};
+struct ERR_HQWatchEntry{int MessageId=6;};
+struct Sampler{string InitialSourceId(){return "source";}};
+struct Route{int MessageId=7,Cursor=0;std::vector<int>Nodes={1,2};string Payload="mounted ammunition=original";};
+struct ERR_HQUnit{ERR_HQStatusReport*PendingStatus=nullptr;Route*Uplink=nullptr;Sampler*StatusSampler=nullptr;};
+struct Watch{ERR_HQWatchEntry*entry=nullptr;ERR_HQWatchEntry*Find(string){return entry;}};
+struct ERR_HQ{ERR_HQUnit*unit=nullptr;struct Watch watch;ERR_HQUnit*ERR_MountedFixtureUnit(int){return unit;}struct Watch*Watch(){return &watch;}};
+struct ERR_HQWatchRules{static bool Valid(ERR_HQStatusReport*,float){return true;}};
+struct Probe{bool m_BMP=true,original=true,failed=false;ERR_ConvoyVehicle*m_BMPVehicle=nullptr;ERR_HQStatusReport*m_Queued=nullptr;ERR_HQUnit*m_Unit=nullptr;Entity*m_Root=nullptr;ERR_HQMountedAmmoSnapshot*m_Payload=nullptr;Route*m_Route=nullptr;string m_RoutePayload;
+ bool Original(ERR_ConvoyVehicle*,ERR_HQUnit*){return original;}bool Check(bool x,const char*){if(!x)failed=true;return x;}
+ bool Same(ERR_HQMountedAmmoSnapshot*a,ERR_HQMountedAmmoSnapshot*b){return a->Complete==b->Complete&&a->Weapons==b->Weapons&&a->Magazines==b->Magazines&&a->Rounds==b->Rounds&&a->Chambers==b->Chambers;}
+'''+capture+r'''
+};
+struct Setup{Probe p;Entity root;ERR_ConvoyVehicle vehicle;ERR_HQ hq;ERR_HQUnit unit;Sampler sampler;Route route;ERR_HQStatusReport report;ERR_HQMountedAmmoSnapshot sample;
+ Setup(){vehicle.Entity=&root;hq.unit=&unit;unit.PendingStatus=&report;unit.Uplink=&route;unit.StatusSampler=&sampler;report.MountedAmmo=&sample;}};
+int main(){
+ {Setup s;s.root.prefab.name="uaz";s.p.Capture(&s.hq,&s.vehicle,1000);assert(!s.p.m_Queued&&!s.p.m_Payload);}
+ for(int bad=0;bad<6;bad++){Setup s;if(bad==0)s.sample.Complete=false;if(bad==1)s.sample.valid=false;
+ if(bad==2)s.sample.Weapons=0;if(bad==3)s.sample.Magazines=0;if(bad==4){s.sample.Rounds=0;s.sample.Chambers=0;}if(bad==5)s.p.original=false;
+ s.p.Capture(&s.hq,&s.vehicle,1000);assert(!s.p.m_Queued&&!s.p.m_BMPVehicle);}
+ {Setup s;s.p.Capture(&s.hq,&s.vehicle,1000);assert(s.p.m_Queued==&s.report&&s.p.m_BMPVehicle==&s.vehicle&&s.p.m_Root==&s.root);
+ assert(s.p.m_Payload!=&s.sample&&s.p.m_Payload->Complete&&s.p.m_Route==&s.route&&!s.p.failed);
+ s.sample.Rounds=0;assert(s.p.m_Payload->Rounds==80);}
+ {Setup s;s.p.m_BMP=false;s.root.prefab.name="uaz";s.sample.Complete=false;s.p.Capture(&s.hq,&s.vehicle,1000);assert(s.p.m_Queued==&s.report&&!s.p.m_BMPVehicle);}
+}
+'''.replace(';if(', ';\n if('))
+node=next(n for n in ast.parse(runner).body if isinstance(n,ast.If) and ast.unparse(n.test).startswith('a.mounted_bmp and'))
+condition=compile(ast.Expression(node.test),'<bmp-selector>','eval')
+for field in [None,'smoke','project','rounds','timeout','mine_stock','mounted_courier','mounted_swap_eligibility']:
+ values=dict(mounted_bmp=True,smoke='mounted-ammo',project='chat',rounds=1,timeout=360,mine_stock=False,mounted_courier=False,mounted_swap_eligibility=False)
+ if field:values[field]={'smoke':'convoy','project':'core','rounds':2,'timeout':359}.get(field,True)
+ assert eval(condition,{'a':SimpleNamespace(**values)})==(field is not None)
+assert "if a.mounted_bmp: command += ['-errMountedBMP', '1']" in runner
+print('PASS: actual BMP capture requires complete armed exact original resource; pinned delivery/slot checks and isolated CLI flag')
+
+# WORKBENCH isolation changes only unrelated services before the real unlock.
+assert start.index('!mixedBMP && StartMode() == 0 && Phase() == ERR_Phase.PRISON') < start.index('bmpHQ.ERR_IsolateMountedBMP()') < start.index('UnlockPrison(')
+assert all(x in start for x in ('errMineStock','errMountedSwapEligibility','errMountedCourier'))
+hook_path=Path(os.environ.get('ERR_NATIVE_SMOKE_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c'))
+hook=body(hook_path,'bool ERR_IsolateMountedBMP(').replace('ERR_NativeMountedAmmoProbe.','ERR_NativeMountedAmmoProbe::').replace('System.','System::').replace('ERR_GameMode.','ERR_GameMode::').replace('ERR_Phase.','ERR_Phase::')
+for v in ('m_Mode','m_Hunters','m_Towns'):hook=hook.replace(v+'.',v+'->')
+run(r'''
+#include <cassert>
+#include <string>
+using string=std::string;
+struct ERR_NativeMountedAmmoProbe{static inline bool enabled=true;static bool Enabled(){return enabled;}};
+struct System{static inline string flag="1";static bool GetCLIParam(string key,string&out){assert(key=="errMountedBMP");out=flag;return !flag.empty();}};
+struct ERR_Phase{static constexpr int PRISON=1;};
+struct ERR_GameMode{int start=0,phase=1;static inline ERR_GameMode*current=nullptr;static ERR_GameMode*Get(){return current;}int StartMode(){return start;}int Phase(){return phase;}};
+struct Service{int deployed=0,stops=0;int Deployed(){return deployed;}void Stop(){stops++;}};
+struct HQ{ERR_GameMode*m_Mode=nullptr;Service*m_Hunters=nullptr,*m_Towns=nullptr;
+'''+hook+r'''
+};
+int main(){for(int fault=0;fault<10;fault++){
+ ERR_GameMode mode,other;ERR_GameMode::current=&mode;Service hunters,towns;HQ h;h.m_Mode=&mode;h.m_Hunters=&hunters;h.m_Towns=&towns;
+ ERR_NativeMountedAmmoProbe::enabled=true;System::flag="1";
+ if(fault==1)ERR_NativeMountedAmmoProbe::enabled=false;if(fault==2)System::flag="";if(fault==3)System::flag="0";
+ if(fault==4)ERR_GameMode::current=&other;if(fault==5)mode.start=1;if(fault==6)mode.phase=2;
+ if(fault==7)hunters.deployed=1;if(fault==8)h.m_Hunters=nullptr;if(fault==9)h.m_Towns=nullptr;
+ assert(h.ERR_IsolateMountedBMP()==(fault==0));assert(hunters.stops==(fault==0?1:0)&&towns.stops==(fault==0?1:0));
+}}
+'''.replace(';if(', ';\n if('))
+print('PASS: actual opt-in pre-unlock isolation refuses wrong mode/phase/flag and existing hunters; no baseline service changes')
@@ -0,0 +1,4 @@
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
PASS: actual BMP capture requires complete armed exact original resource; pinned delivery/slot checks and isolated CLI flag
PASS: actual opt-in pre-unlock isolation refuses wrong mode/phase/flag and existing hunters; no baseline service changes
@@ -0,0 +1,50 @@
{
"complete": true,
"approved": true,
"blockers": [],
"review": "Independent read-only inspection of both exact frozen proposals, existing production service guards, actual-method harness source and recorded logs. No tests/compiler/native rerun.",
"bindings": {
"/tmp/erri-mounted-bmp-probe": {
"manifest_sha256": "af0e6e99a3969ea64d3936b01f56f54c829d56754251c2af09c28710468991de",
"patch_sha256": "d594eddef2327addad3a3977b247cd971b1fbe8713368151e0e502b8ce9d1fc3",
"files": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": {
"baseline_sha256": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
"proposed_sha256": "7ddb634444c79ad9291d53a754dc0ed383342e36720ddaa4b7aa4bd4e7ee656d"
},
"tools/headless_workbench.py": {
"baseline_sha256": "af11b29cc9f22f12e019978164fe808c9c903ea977b15a722846501a8377727f",
"proposed_sha256": "b0bbb87597fe5f116e8b4fd1d60d52983935d438d3e82b972c675991fddcc971"
},
"tests/test_native_mounted_ammo_probe.py": {
"baseline_sha256": "dd7169d8127fef52a4815fb4ad8227307df557170da6a22723c765bcd74ba340",
"proposed_sha256": "87bc8b9952be2e13fd7778af59504078e694b7bd9f0bdfea173feeec58a10f0e"
}
}
},
"/tmp/erri-mounted-bmp-hook": {
"manifest_sha256": "8054b7a04f6ae992fc00f82044738ea04f53fa4e4d334ab183e7638b755ef1e6",
"patch_sha256": "792b3670fda0aaadbb09bbf23a7a34981129e93302372cbbea512467fb601c19",
"files": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": {
"baseline_sha256": "e2a32dbe372edc2f5cd03a55dcb3dd11689ad8b60940a7a318b0c829d464d3e2",
"proposal_sha256": "b7e1857b0678b3a2c71880c0f35b09da9e978f19bacf5b4e7449c893fdbe2b95"
}
}
}
},
"checks": [
"Isolation helper remains inside WORKBENCH and requires actual mounted-ammo enabled/server path, errMountedBMP=1, current mode, prison start and PRISON phase, no previously deployed hunters, and both service identities. Calls Stop before canonical UnlockPrison. Town Tick refuses PRISON and creation is synchronous; no existing town population or new body refunds required.",
"Runner rejects wrong fixture/project/rounds/deadline and mixed mine/courier/swap flags before launch. Raw fixture repeats mutual-exclusion guards before isolation. Default flag-disabled branch unchanged.",
"Automatic target remains3, pool/cap/reservations and startup clock unchanged. Existing180000ms probe deadline and six-root physical roster/cargo-exclusion checks retained.",
"BMP capture selects slot4 only and checks exact original BMP resource, valid Complete nonempty armed counts. Pins exact convoy vehicle/root, original roster, sender source, queued message and route payload; copies snapshot independently.",
"Final proof requires same selected task slot4/original vehicle/root and original roster, exact Watch MessageId, separate delivered and queued snapshots equal to detached captured scalars, observation/delivery bounds and unchanged route payload. No direct radio Advance/Ingest/dispatch or stock edits.",
"Harness logs show final green, baseline compiled runtime-red at absent slot4-only selection, Complete-removal mutation compiled runtime-red at admission assertion. Native APIs/physics are doubled; no engine proof inferred."
],
"limitations": [
"This is a deliberately isolated protected-observer diagnostic; ordinary default-population convoy availability is not qualified.",
"Success would qualify original BMP mounted accounting and natural radio delivery for one original convoy only, not physical interception, full fleet reliability, manual play, multiplayer or FPS.",
"Existing baseline fixture failure and shared117/135 refusal remain valid evidence; cap policy unchanged.",
"No native completion is asserted by this source review."
]
}
@@ -0,0 +1,21 @@
check: /tmp/err-policy-yqj9w2m8/check.cpp:59: int main(): Assertion `!s.p.m_Queued&&!s.p.m_BMPVehicle' failed.
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
Traceback (most recent call last):
File "/tmp/erri-mounted-bmp-probe/tests/test_native_mounted_ammo_probe.py", line 172, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<33 lines>...
}
^
'''.replace(';if(', ';\n if('))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
subprocess.run([str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/tmp/err-policy-yqj9w2m8/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,31 @@
{
"files": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": {
"baseline_sha256": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
"proposed_sha256": "7ddb634444c79ad9291d53a754dc0ed383342e36720ddaa4b7aa4bd4e7ee656d"
},
"tools/headless_workbench.py": {
"baseline_sha256": "af11b29cc9f22f12e019978164fe808c9c903ea977b15a722846501a8377727f",
"proposed_sha256": "b0bbb87597fe5f116e8b4fd1d60d52983935d438d3e82b972c675991fddcc971"
},
"tests/test_native_mounted_ammo_probe.py": {
"baseline_sha256": "dd7169d8127fef52a4815fb4ad8227307df557170da6a22723c765bcd74ba340",
"proposed_sha256": "87bc8b9952be2e13fd7778af59504078e694b7bd9f0bdfea173feeec58a10f0e"
}
},
"patch_sha256": "d594eddef2327addad3a3977b247cd971b1fbe8713368151e0e502b8ce9d1fc3",
"hook_source_sha256": "b7e1857b0678b3a2c71880c0f35b09da9e978f19bacf5b4e7449c893fdbe2b95",
"tests": {
"green_exit": 0,
"baseline_exit": 1,
"baseline_compiled_runtime_red": true,
"mutation_exit": 1,
"mutation_compiled_runtime_red": true,
"logs": {
"green.log": "608933baa6b1f2798ec075bbc9a66f4b347444c4806d3dde9c930d2aec1be978",
"baseline-red.log": "8c2a4a94132827f0b4f6aebd216f93256ccd6af34a5446e5a99921b9a8d2ec0b",
"mutation-red.log": "a877ec3e21aef3d994d82812f19c54a2120a0a316c5ddb920e079c6137d84193",
"adapter-compile-failure.log": "0fbdda6e7a15f318622150a45377e3974485eb0fb3dd0e164f6bded65b1d2bde"
}
}
}
@@ -0,0 +1,29 @@
{
"complete": true,
"ordinary_gameplay_changed": false,
"source_changes": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "b7e1857b0678b3a2c71880c0f35b09da9e978f19bacf5b4e7449c893fdbe2b95",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "7ddb634444c79ad9291d53a754dc0ed383342e36720ddaa4b7aa4bd4e7ee656d",
"tools/headless_workbench.py": "b0bbb87597fe5f116e8b4fd1d60d52983935d438d3e82b972c675991fddcc971",
"tests/test_native_mounted_ammo_probe.py": "87bc8b9952be2e13fd7778af59504078e694b7bd9f0bdfea173feeec58a10f0e"
},
"focused_regression_programs": 10,
"full_suite_repeated": false,
"native_run_attempted": false,
"native_qualification": false,
"documented_body_budget_preserved": true,
"documentation_changes": {
"docs/current-status.md": {
"before": "04a5e417225f85ca387e0ff1d9c9eed5164c17bc6249e6f52904a4a270d86e23",
"after": "570ead864b4f36e620493fe206880863e5a810a23c3d6c36f0f802709660ca2c"
},
"docs/runtime-testing.md": {
"before": "50ffdfb91b127412ffe3ea2dc915d18e3ccf853502adff1c561fdc8c0244b5e6",
"after": "a23e32f0893669c0303d3c2bb10cc710c0aeb72b6d72e31987ea5b079fc349dc"
}
},
"prior_candidates_preserved": 5,
"original_reference_files_preserved": 533,
"staged_diff_sha256": "670073db5d7531aca4466cc9d2827d10a46bfcfbd35f27ac97724de9d2fd3725",
"release_qualified": false
}
@@ -0,0 +1,18 @@
from pathlib import Path
import sys,os,json,hashlib,subprocess,time
R=Path('/home/jakub/devel/escapistsrereintroduced');B=Path('/tmp/erri-bmp-native-2103');sys.path.insert(0,str(R/'tools'));from source_manifest import addon_manifest
names=['test_native_mounted_ammo_probe.py','test_native_mounted_swap_probe.py','test_native_mounted_courier_probe.py','test_native_convoy_mine_stock.py','test_native_mine_stock_runner.py','test_native_memory_deadlines.py','test_convoy_budget.py','test_supply_convoys.py','test_hq_mounted_ammo_sampler.py','test_hq_watch.py']
assert all((R/'tests'/n).is_file() for n in names),names
inputs=addon_manifest(R)
for folder in ['tools','tests']:
for p in (R/folder).rglob('*'):
if p.is_file() and '__pycache__' not in p.parts and p.suffix!='.pyc':inputs[str(p.relative_to(R))]=hashlib.sha256(p.read_bytes()).hexdigest()
(B/'focused-inputs.json').write_text(json.dumps(inputs,indent=2)+'\n')
env={k:v for k,v in os.environ.items() if not k.startswith('ERR_')};env['PYTHONDONTWRITEBYTECODE']='1';env['ERR_REPO']=str(R)
results=[]
for name in names:
process=subprocess.run([sys.executable,'-B',str(R/'tests'/name)],env=env,cwd=R)
results.append({'path':'tests/'+name,'exit':process.returncode})
if process.returncode:break
unchanged=all(hashlib.sha256((R/n).read_bytes()).hexdigest()==h for n,h in inputs.items());code=0 if unchanged and len(results)==len(names) and all(r['exit']==0 for r in results) else 1
(B/'focused-result.json').write_text(json.dumps({'exit':code,'inputs_unchanged':unchanged,'programs':results,'fresh_full_suite_claimed':False},indent=2)+'\n');print('Focused result',code,len(results),'programs', 'inputs unchanged',unchanged);raise SystemExit(code)
@@ -0,0 +1,56 @@
from pathlib import Path
import json,hashlib,shutil,subprocess
R=Path('/home/jakub/devel/escapistsrereintroduced');B=Path('/tmp/erri-bmp-native-2103');E=R/'docs/evidence/bmp-native-proof-preparation-2026-10-03'
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest();load=lambda p:json.loads(p.read_text());write=lambda p,v:p.write_text(json.dumps(v,indent=2)+'\n')
base=load(B/'baseline.json');focused=load(B/'focused-result.json');assert focused['exit']==0 and focused['inputs_unchanged'] and len(focused['programs'])==10 and all(p['exit']==0 for p in focused['programs'])
assert load(B/'preservation.json')['complete'] and not load(B/'native-preflight.json')['native_run_attempted']
assert hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=R)).hexdigest()==base['staged_diff_sha256']
for n,h in load(B/'focused-inputs.json').items():assert sha(R/n)==h,n
proposals=[Path('/tmp/erri-mounted-bmp-hook'),Path('/tmp/erri-mounted-bmp-probe')];expected={}
for p in proposals:
m=load(p/'source-manifest.json');assert sha(p/'fix.patch')==m['patch_sha256']
for n,v in m['files'].items():assert base['files'][n]==v['baseline_sha256'];expected[n]=v.get('proposal_sha256',v.get('proposed_sha256'));assert sha(R/n)==expected[n]
changed={n for n,h in base['files'].items() if sha(R/n)!=h};assert changed==set(expected),changed
review=load(Path('/tmp/erri-mounted-bmp-probe/independent-review.json'));assert review.get('complete',False) or review.get('approved',False),review
updates={}
n='docs/current-status.md';old=(R/n).read_text();first,rest=old.split('\n',1);updates[n]=first+'\n\n'+'''**3 October 2026 — BMP accounting verification strengthened; native run pending:** an opt-in Workbench check now requires complete armed counts from the original slot-4 BMP and that same vehicle’s actual queued and radio-delivered HQ status. The old generic check could be satisfied by a UAZ. The isolated check stops opening hunters and new town admissions before prison exit, while retaining original site troops, automatic convoy target, body cap, finite stock and the fixed proof deadline. Ordinary mission behavior is unchanged.
All **10 affected regression programs pass** on unchanged inputs; baseline and missing-completeness controls fail as expected. A read-only host preflight found an existing game, so no native run was started and the game was left untouched. The earlier 117/135 refusal correctly enforced the documented shared cap and was not a demonstrated accounting defect. The current crash-start playtest package is unchanged; it predates this diagnostic only. Native BMP accounting/radio proof, physical support reliability, manual play, multiplayer and FPS remain unqualified. [Prepared check and exact evidence](evidence/bmp-native-proof-preparation-2026-10-03/README.md).
'''+rest.lstrip('\n')
n='docs/runtime-testing.md';old=(R/n).read_text();updates[n]=old.rstrip()+'''
## Original BMP mounted-accounting diagnostic
Use the existing hidden/muted private Workbench runner with `--project chat --smoke mounted-ammo --mounted-bmp --rounds 1 --timeout 420`, audited external addons and a fresh Prison-start profile. Perform the host-visible game/prefix preflight first and defer while any game exists. The original 180-second proof deadline is unchanged; the runner allowance includes preparation and cleanup.
This opt-in Workbench-only variant stops unstarted opening hunters and new town admissions before prison exit. It retains the initial site population, normal automatic convoy target of three, shared body cap and finite original stock. It checks all six original vehicle roots and cargo exclusion, then requires complete valid armed counts from original slot 4’s WCS BMP and that BMP’s own detached status snapshot delivered through the actual radio path. An armed UAZ cannot satisfy the BMP proof. Mine-stock, swap and courier variants are incompatible. No replacement BMP, direct report injection, ammunition refill, body refund or raised cap is used.
The source and ten focused regressions are recorded in [the preparation checkpoint](evidence/bmp-native-proof-preparation-2026-10-03/README.md). Native confirmation is pending because a host game was running at preparation time. Even a pass would qualify only this isolated accounting/radio scene, not default three-convoy admission, physical interception, multiplayer or performance.
'''
doc_changes={}
for n,t in updates.items():assert sha(R/n)==base['files'][n];doc_changes[n]={'before':sha(R/n),'after':hashlib.sha256(t.encode()).hexdigest()};(R/n).write_text(t)
assert not E.exists();E.mkdir()
for p in B.iterdir():
if p.is_file():shutil.copyfile(p,E/p.name)
for folder in proposals:
for p in folder.rglob('*'):
if p.is_file() and p.suffix in {'.patch','.json','.log'} and not any(k in p.parts for k in ['isolated','baseline','proposed']):
q=E/'proposals'/folder.name/p.relative_to(folder);q.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(p,q)
shutil.copyfile('/tmp/erri-convoy-budget-review-20261003/review.json',E/'budget-review.json')
for n,h in expected.items():
q=E/'final-source'/n;q.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(R/n,q);assert sha(q)==h
write(E/'review.json',{'complete':True,'ordinary_gameplay_changed':False,'source_changes':expected,'focused_regression_programs':10,'full_suite_repeated':False,'native_run_attempted':False,'native_qualification':False,'documented_body_budget_preserved':True,'documentation_changes':doc_changes,'prior_candidates_preserved':5,'original_reference_files_preserved':533,'staged_diff_sha256':base['staged_diff_sha256'],'release_qualified':False})
(E/'README.md').write_text('''# Original BMP accounting proof preparation
The new optional `mounted-ammo --mounted-bmp` Workbench diagnostic closes a qualification gap: the original generic fixture could finish from an armed UAZ and allowed an incomplete but bounded BMP snapshot. The new branch requires the original slot-4 WCS BMP, a complete valid armed snapshot and the exact vehicle’s naturally queued/delivered radio status, preserving original crew/root identities and detached payload checks. It retains the six-root and unarmed cargo-exclusion checks. Mixed mine/swap/courier modes are rejected.
Only this explicit Workbench branch stops unstarted hunters and town admissions before prison unlock. No production population policy, target,135-body cap, stock,180-second proof deadline or actor is replaced/refunded. The default configured convoy count is a maximum;117 committed bodies plus25 crew exceeding135 was a documented admission refusal, not a demonstrated accounting bug. Independent budget and fixture reviews are included.
Ten affected regression programs pass on unchanged inputs. The added actual-method assertions reject the old all-slot observation behavior and a missing-completeness mutation. Their failing controls and one early test-adapter compilation failure are preserved. A host-visible read-only preflight found an existing game with the private prefix idle; no native run was started. No display, input, audio or existing process was modified. Native BMP accounting and radio proof remain pending.
Original533 reference files, five sealed candidates and staged content are unchanged. The crash-start candidate remains the playable development handoff and predates only this diagnostic. This checkpoint does not rerun the complete307-program suite or package an identical ordinary mission. Manual play, physical support reliability, real multiplayer, comparative FPS and clean release remain unqualified. `next-work.json` records the single next native check after the host is free.
''')
write(E/'artifact-sha256.json',{str(p.relative_to(E)):sha(p) for p in E.rglob('*') if p.is_file()})
for n,h in base['files'].items():assert sha(R/n)==doc_changes.get(n,{}).get('after',expected.get(n,h)),n
print(json.dumps({'source_files':len(expected),'focused_programs':10,'native_run_attempted':False,'original_and_candidates_preserved':True}))