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,22 @@
check: /tmp/err-policy-phq1o06u/check.cpp:23: ERR_NativePatrolProbe::ERR_NativePatrolProbe(Fixture*): Assertion `owner->phase==2&&owner->active&&owner->unlocks==1' failed.
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
Traceback (most recent call last):
File "/tmp/erri-patrol-start-1659/tests/test_native_memory_deadlines.py", line 133, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<20 lines>...
}
^
'''.replace('BRANCH',patrol_branch))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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-phq1o06u/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,120 @@
"""Actual native-fixture startup/deadline gate, engine boundaries doubled."""
import os,sys,re
from pathlib import Path
REPO=Path(os.environ.get('ERR_REPO', Path(__file__).resolve().parents[1]))
sys.path.insert(0,str(REPO/'tests'))
from policy_harness import body,run
p=Path(os.environ.get('ERR_MEMORY_PROBE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c'))
s=body(p,'int Tick(ERR_HQ hq, float now)')
# Execute the unchanged deadline/startup prefix; payload/native radio assertions
# after this gate remain the full fixture's responsibility.
s=s[:s.index(' if (!m_ValueChecked)')]+ ' }\n return 1;\n }'
s=s.replace('ERR_HQ hq','ERR_HQ* hq').replace('hq.','hq->')
run(r'''
#include <cassert>
#include <string>
using string = std::string;
struct CLI {string outcome="hq-memory"; void GetCLIParam(string,string& value){value=outcome;}} System;
struct ERR_HQ{bool ready=true;bool ERR_ProbeSquadsReady(){return ready;}};
struct Probe{bool enabled=true,m_Mode=true,m_Failed=false,m_AutoChecked=false;int m_Step=0,automatic=0,checks=0;float m_Deadline=0;bool Enabled(){return enabled;}void Check(bool,std::string){checks++;m_Failed=true;}int AutomaticConvoy(ERR_HQ*){if(automatic==1)m_AutoChecked=true;return automatic;}
METHOD
};
int main(){ERR_HQ hq;
Probe p;assert(p.Tick(&hq,1000)==0&&p.m_Deadline==151000);assert(p.Tick(&hq,130000)==0&&p.m_Deadline==151000);p.automatic=1;assert(p.Tick(&hq,145000)==1&&p.m_Deadline==265000);assert(p.Tick(&hq,200000)==1&&p.m_Deadline==265000);assert(p.Tick(&hq,265000)==1);assert(p.Tick(&hq,265001)==-1&&p.checks==1);
Probe missing;assert(missing.Tick(&hq,0)==0);assert(missing.Tick(&hq,150001)==-1&&missing.checks==1);
Probe refused;refused.Tick(&hq,0);refused.automatic=-1;assert(refused.Tick(&hq,40000)==-1&&refused.m_Deadline==150000&&!refused.m_AutoChecked);
Probe unavailable;hq.ready=false;assert(unavailable.Tick(&hq,0)==0);assert(unavailable.Tick(&hq,150001)==-1);hq.ready=true;
System.outcome="hq-awareness"; hq.ready=false; Probe awareness; assert(awareness.Tick(&hq,1000)==1 && !awareness.m_AutoChecked && awareness.m_Deadline==151000); assert(awareness.Tick(&hq,151001)==-1);
Probe invalid;invalid.enabled=false;assert(invalid.Tick(&hq,0)==-1&&invalid.m_Deadline==0);
}
'''.replace('METHOD',s))
smoke=Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')).read_text()
assert 'if (m_ERRTestHQMemory) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 360000;' in smoke
assert 'if (m_ERRTestHQBody) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000;' in smoke
# Execute the actual startup selector, so enlarged full-route budgets cannot
# accidentally extend a death/radio test or shorten an existing specialized run.
start=smoke.index('m_ERRTestLostHelicopter = System.GetCLIParam(')
end=smoke.index('OnStop().Insert(ERR_StopHQPatrol);',start)
selector=smoke[start:end].replace('System.GetCLIParam("errSmokeOutcome", outcome) && ', '')
selector=selector.replace('GetWorld().GetWorldTime()', 'now').replace('ERR_NativeConvoyCoverProbe.Enabled()', 'cover').replace('ERR_NativeMountedCourierProbe.Enabled()', 'courier').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance').replace('ERR_NativeMountedInterceptProbe.Enabled()', 'intercept')
flags=sorted(set(re.findall(r'\bm_ERRTest\w+',selector)))
run(r'''
#include <cassert>
#include <string>
using string = std::string;
float deadline(string outcome,float now,bool cover=false,bool courier=false,bool maintenance=false,bool intercept=false){
[[maybe_unused]] bool DECLARATIONS;
float m_ERRSmokeDeadline=0;
SELECTOR
return m_ERRSmokeDeadline;
}
int main(){
for(float now : {0.0f, 42000.0f}) {
for(string outcome : {"", "victory", "lost-helicopter"}) assert(deadline(outcome,now)==now+300000);
for(string outcome : {"escape-route", "normal-escape-route", "player-death", "radio-network", "hq-response", "map-ownership"}) assert(deadline(outcome,now)==now+150000);
assert(deadline("hq-memory",now)==now+360000);
assert(deadline("hq-body",now)==now+240000);
assert(deadline("convoy",now)==now+540000);
assert(deadline("convoy",now,false,false,false,true)==now+840000);
assert(deadline("supply-convoys",now)==now+840000);
assert(deadline("convoy",now,true)==now+840000);
assert(deadline("mounted-ammo",now)==now+330000);
assert(deadline("mounted-ammo",now,false,true)==now+750000);
assert(deadline("normal-escape-route",now,false,false,true)==now+330000);
}
}
'''.replace('DECLARATIONS', ','.join(flag+'=false' for flag in flags)).replace('SELECTOR',selector))
print('PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines')
# The new route diagnostic must leave the original administrator/reroll stress
# intact and may skip only those extras, never clue or radio progression gates.
route=body(Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')), 'bool ERR_CheckRouteExtras(float now)').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance')
run(r'''
#include <cassert>
#include <string>
struct Probe {
bool m_ERRTestEscapeRoute=false,rerollReady=false,maintenance=false,maintenanceReady=false;
int maintenanceCalls=0; bool ERR_RunMaintenance(float){maintenanceCalls++;return maintenanceReady;}
int adminResult=0,adminCalls=0,rerollCalls=0,failures=0;
int ERR_ProbeAdminMenu(float){adminCalls++;return adminResult;}
bool ERR_Check(bool result,std::string){if(!result)failures++;return result;}
bool ERR_CheckIntelReroll(float){rerollCalls++;return rerollReady;}
METHOD
};
int main(){
Probe route;route.m_ERRTestEscapeRoute=true;assert(route.ERR_CheckRouteExtras(100));
assert(route.adminCalls==0&&route.rerollCalls==0&&route.failures==0);
route.maintenance=true;assert(!route.ERR_CheckRouteExtras(101)&&route.maintenanceCalls==1);
route.maintenanceReady=true;assert(route.ERR_CheckRouteExtras(102)&&route.maintenanceCalls==2&&route.adminCalls==0&&route.rerollCalls==0);
Probe full;assert(!full.ERR_CheckRouteExtras(100)&&full.adminCalls==1&&full.rerollCalls==0);
full.adminResult=-1;assert(!full.ERR_CheckRouteExtras(200)&&full.failures==1&&full.rerollCalls==0);
full.adminResult=1;assert(!full.ERR_CheckRouteExtras(300)&&full.rerollCalls==1);
full.rerollReady=true;assert(full.ERR_CheckRouteExtras(400)&&full.rerollCalls==2);
}
'''.replace('METHOD',route))
assert 'if (!ERR_CheckRouteExtras(now)) return;' in smoke
assert 'if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2,' in smoke
assert 'if (!ERR_Check(Phase() == ERR_Phase.EXTRACTION,' in smoke
print('PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths')
# Execute the actual scenario-selection expressions: normal route must retain
# the ordinary catalog AND random placement, while historical probes stay fixed.
scenario=(REPO/'addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c').read_text()
conditions=[]
for variable in ('historicalFixture','fixture'):
line=next(line.strip() for line in scenario.splitlines() if line.strip().startswith('if (') and 'System.GetCLIParam("errSmokeOutcome", '+variable+')' in line)
expression=line[4:-1].replace('System.GetCLIParam("errSmokeOutcome", '+variable+')','supplied').replace(variable,'outcome')
conditions.append(expression)
run(r'''
#include <cassert>
#include <string>
using string=std::string;
bool legacy(bool supplied,string outcome,bool m_TerrainIndependent=false){return LEGACY;}
bool fixed(bool supplied,string outcome,bool m_TerrainIndependent=false){return FIXED;}
int main(){
for(string route : {"normal-escape-route","generated-sites","optional-site-skip"}) {assert(!legacy(true,route));assert(!fixed(true,route));}
for(string route : {"escape-route","victory","transport-survey"}) {assert(legacy(true,route));assert(fixed(true,route));}
assert(!legacy(false,"escape-route")&&!fixed(false,"escape-route"));
}
'''.replace('LEGACY',conditions[0]).replace('FIXED',conditions[1]))
print('PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged')
@@ -0,0 +1,18 @@
{
"conclusion": "Fixture starts patrol movement observation during intentional production prison freeze. Correct fixture through actual canonical UnlockPrison before creating movement probe. Not a demonstrated site-patrol movement or search-radius production defect.",
"evidence": [
"console has phase 0->1 and no RADIO_SEARCH entry before timeout",
"ERR_PrisonAI.ERR_HoldForPrison disables mission enemies through PRISON; callback releases on RADIO_SEARCH",
"original patrol-hq step0 branch creates ERR_NativePatrolProbe before unlock"
],
"change": "One WORKBENCH branch adds successful UnlockPrison(m_ERRSmokePlayer) and resulting RADIO_SEARCH check before allocation; failure returns without movement probe.",
"unchanged": [
"production prison AI/gameplay/mission rules",
"180000ms movement deadline",
"five ordered completions and >=8m displacement",
"native queue/route",
"existing observer damage protection",
"420000ms overall fixture deadline"
],
"scope": "New test executes exact branch; native unlock/damage/constructor boundaries doubled. Existing actual prison hold/release and canonical progression tests pass. Current native outcome remains unproven until root rerun. Earlier September passes are historical, not evidence against current opening policy."
}
@@ -0,0 +1,60 @@
--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
@@ -698,6 +698,7 @@
if (m_ERRTestPatrolHQ)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
+ if (!ERR_Check(UnlockPrison(m_ERRSmokePlayer) && Phase() == ERR_Phase.RADIO_SEARCH, "patrol HQ fixture leaves prison through canonical admission before observing movement")) return;
m_ERRHQPatrolMovement = new ERR_NativePatrolProbe(this);
m_ERRSmokeStep = 130;
return;
--- a/tests/test_native_memory_deadlines.py
+++ b/tests/test_native_memory_deadlines.py
@@ -52,6 +52,7 @@
for(float now : {0.0f, 42000.0f}) {
for(string outcome : {"", "victory", "lost-helicopter"}) assert(deadline(outcome,now)==now+300000);
for(string outcome : {"escape-route", "normal-escape-route", "player-death", "radio-network", "hq-response", "map-ownership"}) assert(deadline(outcome,now)==now+150000);
+ assert(deadline("patrol-hq",now)==now+420000);
assert(deadline("hq-memory",now)==now+360000);
assert(deadline("hq-body",now)==now+240000);
assert(deadline("convoy",now)==now+540000);
@@ -118,3 +119,39 @@
}
'''.replace('LEGACY',conditions[0]).replace('FIXED',conditions[1]))
print('PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged')
+
+# Execute the actual patrol-hq admission branch. The existing production
+# prison-AI/progression tests cover canonical UnlockPrison and phase callbacks;
+# here native damage, allocation and unlock boundaries are explicit doubles.
+smoke_path=Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c'))
+smoke_tick=body(smoke_path,'protected void ERR_SmokeTick(')
+a=smoke_tick.index('if (m_ERRTestPatrolHQ)'); b=smoke_tick.index('{',a); i=b+1; depth=1
+while depth:
+ depth+=(smoke_tick[i]=='{')-(smoke_tick[i]=='}');i+=1
+patrol_branch=smoke_tick[a:i]
+patrol_branch=patrol_branch.replace('DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);','ProtectOriginal(m_ERRSmokePlayer);').replace('ERR_Phase.RADIO_SEARCH','2')
+run(r'''
+#include <cassert>
+#include <string>
+struct Fixture;
+struct ERR_NativePatrolProbe {explicit ERR_NativePatrolProbe(Fixture* owner);};
+struct Fixture {
+ bool m_ERRTestPatrolHQ=true,allowed=true,wrongPhase=false,active=false;
+ int m_ERRSmokePlayer=7,phase=1,unlocks=0,failures=0,allocations=0,protections=0,m_ERRSmokeStep=0;
+ ERR_NativePatrolProbe* m_ERRHQPatrolMovement=nullptr;
+ ~Fixture(){delete m_ERRHQPatrolMovement;}
+ void ProtectOriginal(int actor){assert(actor==7);protections++;}
+ bool UnlockPrison(int actor){assert(actor==7);unlocks++;if(!allowed)return false;if(!wrongPhase){phase=2;active=true;}return true;}
+ int Phase(){return phase;}
+ bool ERR_Check(bool ok,std::string){if(!ok)failures++;return ok;}
+ void Start(){BRANCH}
+};
+ERR_NativePatrolProbe::ERR_NativePatrolProbe(Fixture* owner){assert(owner->phase==2&&owner->active&&owner->unlocks==1);owner->allocations++;}
+int main(){
+ Fixture healthy;healthy.Start();assert(healthy.m_ERRSmokeStep==130&&healthy.allocations==1&&healthy.failures==0&&healthy.protections==1);
+ Fixture refused;refused.allowed=false;refused.Start();assert(refused.unlocks==1&&refused.failures==1&&refused.allocations==0&&refused.m_ERRSmokeStep==0&&!refused.active);
+ Fixture wrong;wrong.wrongPhase=true;wrong.Start();assert(wrong.unlocks==1&&wrong.failures==1&&wrong.allocations==0&&wrong.m_ERRSmokeStep==0);
+ Fixture other;other.m_ERRTestPatrolHQ=false;other.Start();assert(other.unlocks==0&&other.allocations==0&&other.protections==0&&other.m_ERRSmokeStep==0);
+}
+'''.replace('BRANCH',patrol_branch))
+print('PASS: actual patrol fixture leaves prison before movement observation and refuses failed transition')
@@ -0,0 +1,4 @@
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 movement observation and refuses failed transition
@@ -0,0 +1,44 @@
{
"approved": true,
"blockers": [],
"review_mode": "Read-only independent exact source/test/log inspection; no compiler or native rerun.",
"patch_sha256": "448bee9abebcb2c0a592715abb0b37a6da2ffe5ff5ffa3bb81d9571aa3503540",
"source_manifest_sha256": "1c29e6ea4382196591f3a4a3a6854554b870d30b2bf191d43e455f89f45c0105",
"files": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": {
"baseline_sha256": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
"proposed_sha256": "7d8dcb96efeeeb44f46f604f96bae337d3200fd15347a8019259d21a94f67d81"
},
"tests/test_native_memory_deadlines.py": {
"baseline_sha256": "f2d3f0feda862318ab936031487743218a8c8241d192b34e2b1ab63a5aa2cc48",
"proposed_sha256": "597d4f430a4fb9bd684958c60d44d98703410b9bab629290e21f857c001c7112"
}
},
"checks": [
"Only one WORKBENCH patrol-hq admission line changes: canonical original admitted observer unlock and resulting RADIO_SEARCH guard before probe allocation. Existing damage protection remains before transition.",
"Actual UnlockPrison validates server/current canonical fit player/faction/proximity and transitions only from PRISON. Nonterminal phase callback does not trigger smoke completion. Production prisoner AI policy releases only on RADIO_SEARCH and stays unchanged.",
"Actual extracted branch test covers successful transition before constructor, refused unlock, wrong resulting phase, and unselected fixture with no work. Baseline compiled then fails premature constructor phase assertion; corrected author program green.",
"Existing prison-AI and progression identity tests author logs pass. Exact180000ms native movement bound, five ordered completions,>=8m displacement,420000ms fixture lifetime and same original actors/route/probe remain unchanged.",
"Failed native evidence has only phase0->1 before180s route traversal failure; current fixture bypassed required unlock. This is fixture setup correction, not demonstrated production movement failure."
],
"limitations": [
"No native validation of corrected fixture yet; native actor movement and final patrol HQ preemption/resumption remain pending.",
"Native unlock/damage/allocation behavior is doubled in focused branch test; separate unchanged production method tests and source establish policy linkage."
],
"evidence_sha256": {
"green.log": "f0f1259c73095bf4ce66107a82bf3363d1d30a1bae1d14000c4ad2cd0629e3fb",
"baseline-red.log": "13065e36fc08d14024660a7e962250d5a73222d7be2136e50a0b3c96404b088d",
"prison-ai-green.log": "63ef1dee605d5ea050f379a0fdfd398c5593126bc0db3d7cb48e12e1151c1523",
"progression-green.log": "9e3c909c4acd90a8094c5bebf05b411775b0f676616f5bb2e5e8015b42c68a4e",
"finding.json": "3536550b06d42b21525e866889f9f810f64eecb61e836cd8d3eab64ac38f49bf"
},
"unchanged_production": {
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c"
},
"native_failed_evidence": {
"report.json": "d8fc5e1cd3f946636f91ffd46226ca4d0217b47a11c3a38d55ff438d8076cd8b",
"console.log.txt": "d08c221dee2bff342e5c512a0284fef6ef6dbbc0ae9c978b19945438827a5080"
}
}
@@ -0,0 +1 @@
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
@@ -0,0 +1,2 @@
PASS: actual gate and pre-inventory document guards reject noncanonical/faction/life/disconnect/server mismatches; canonical reconnect and unconscious carried intel preserved
PASS: WB-only native fault injection restores both body mutations before checks/returns and requires eligible held-document negative/positive proof; runtime pending
@@ -0,0 +1,39 @@
{
"files": {
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": {
"baseline_sha256": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
"proposed_sha256": "7d8dcb96efeeeb44f46f604f96bae337d3200fd15347a8019259d21a94f67d81"
},
"tests/test_native_memory_deadlines.py": {
"baseline_sha256": "f2d3f0feda862318ab936031487743218a8c8241d192b34e2b1ab63a5aa2cc48",
"proposed_sha256": "597d4f430a4fb9bd684958c60d44d98703410b9bab629290e21f857c001c7112"
}
},
"patch_sha256": "448bee9abebcb2c0a592715abb0b37a6da2ffe5ff5ffa3bb81d9571aa3503540",
"tests": {
"proposed_existing_program_exit": 0,
"baseline_existing_program_exit": 1,
"baseline_failure": "compiled then SIGABRT at movement constructor assertion: phase==RADIO_SEARCH && active && unlocks==1",
"prison_ai_exit": 0,
"progression_identity_exit": 0
},
"evidence": {
"green.log": "f0f1259c73095bf4ce66107a82bf3363d1d30a1bae1d14000c4ad2cd0629e3fb",
"baseline-red.log": "13065e36fc08d14024660a7e962250d5a73222d7be2136e50a0b3c96404b088d",
"prison-ai-green.log": "63ef1dee605d5ea050f379a0fdfd398c5593126bc0db3d7cb48e12e1151c1523",
"progression-green.log": "9e3c909c4acd90a8094c5bebf05b411775b0f676616f5bb2e5e8015b42c68a4e",
"finding.json": "3536550b06d42b21525e866889f9f810f64eecb61e836cd8d3eab64ac38f49bf"
},
"unchanged_production": {
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c"
},
"native_failed_evidence": {
"report.json": "d8fc5e1cd3f946636f91ffd46226ca4d0217b47a11c3a38d55ff438d8076cd8b",
"console.log.txt": "d08c221dee2bff342e5c512a0284fef6ef6dbbc0ae9c978b19945438827a5080"
},
"native_runs": 0,
"live_edits": false,
"compiler_work_complete": true
}
@@ -0,0 +1,157 @@
"""Actual native-fixture startup/deadline gate, engine boundaries doubled."""
import os,sys,re
from pathlib import Path
REPO=Path(os.environ.get('ERR_REPO', Path(__file__).resolve().parents[1]))
sys.path.insert(0,str(REPO/'tests'))
from policy_harness import body,run
p=Path(os.environ.get('ERR_MEMORY_PROBE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c'))
s=body(p,'int Tick(ERR_HQ hq, float now)')
# Execute the unchanged deadline/startup prefix; payload/native radio assertions
# after this gate remain the full fixture's responsibility.
s=s[:s.index(' if (!m_ValueChecked)')]+ ' }\n return 1;\n }'
s=s.replace('ERR_HQ hq','ERR_HQ* hq').replace('hq.','hq->')
run(r'''
#include <cassert>
#include <string>
using string = std::string;
struct CLI {string outcome="hq-memory"; void GetCLIParam(string,string& value){value=outcome;}} System;
struct ERR_HQ{bool ready=true;bool ERR_ProbeSquadsReady(){return ready;}};
struct Probe{bool enabled=true,m_Mode=true,m_Failed=false,m_AutoChecked=false;int m_Step=0,automatic=0,checks=0;float m_Deadline=0;bool Enabled(){return enabled;}void Check(bool,std::string){checks++;m_Failed=true;}int AutomaticConvoy(ERR_HQ*){if(automatic==1)m_AutoChecked=true;return automatic;}
METHOD
};
int main(){ERR_HQ hq;
Probe p;assert(p.Tick(&hq,1000)==0&&p.m_Deadline==151000);assert(p.Tick(&hq,130000)==0&&p.m_Deadline==151000);p.automatic=1;assert(p.Tick(&hq,145000)==1&&p.m_Deadline==265000);assert(p.Tick(&hq,200000)==1&&p.m_Deadline==265000);assert(p.Tick(&hq,265000)==1);assert(p.Tick(&hq,265001)==-1&&p.checks==1);
Probe missing;assert(missing.Tick(&hq,0)==0);assert(missing.Tick(&hq,150001)==-1&&missing.checks==1);
Probe refused;refused.Tick(&hq,0);refused.automatic=-1;assert(refused.Tick(&hq,40000)==-1&&refused.m_Deadline==150000&&!refused.m_AutoChecked);
Probe unavailable;hq.ready=false;assert(unavailable.Tick(&hq,0)==0);assert(unavailable.Tick(&hq,150001)==-1);hq.ready=true;
System.outcome="hq-awareness"; hq.ready=false; Probe awareness; assert(awareness.Tick(&hq,1000)==1 && !awareness.m_AutoChecked && awareness.m_Deadline==151000); assert(awareness.Tick(&hq,151001)==-1);
Probe invalid;invalid.enabled=false;assert(invalid.Tick(&hq,0)==-1&&invalid.m_Deadline==0);
}
'''.replace('METHOD',s))
smoke=Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')).read_text()
assert 'if (m_ERRTestHQMemory) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 360000;' in smoke
assert 'if (m_ERRTestHQBody) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000;' in smoke
# Execute the actual startup selector, so enlarged full-route budgets cannot
# accidentally extend a death/radio test or shorten an existing specialized run.
start=smoke.index('m_ERRTestLostHelicopter = System.GetCLIParam(')
end=smoke.index('OnStop().Insert(ERR_StopHQPatrol);',start)
selector=smoke[start:end].replace('System.GetCLIParam("errSmokeOutcome", outcome) && ', '')
selector=selector.replace('GetWorld().GetWorldTime()', 'now').replace('ERR_NativeConvoyCoverProbe.Enabled()', 'cover').replace('ERR_NativeMountedCourierProbe.Enabled()', 'courier').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance').replace('ERR_NativeMountedInterceptProbe.Enabled()', 'intercept')
flags=sorted(set(re.findall(r'\bm_ERRTest\w+',selector)))
run(r'''
#include <cassert>
#include <string>
using string = std::string;
float deadline(string outcome,float now,bool cover=false,bool courier=false,bool maintenance=false,bool intercept=false){
[[maybe_unused]] bool DECLARATIONS;
float m_ERRSmokeDeadline=0;
SELECTOR
return m_ERRSmokeDeadline;
}
int main(){
for(float now : {0.0f, 42000.0f}) {
for(string outcome : {"", "victory", "lost-helicopter"}) assert(deadline(outcome,now)==now+300000);
for(string outcome : {"escape-route", "normal-escape-route", "player-death", "radio-network", "hq-response", "map-ownership"}) assert(deadline(outcome,now)==now+150000);
assert(deadline("patrol-hq",now)==now+420000);
assert(deadline("hq-memory",now)==now+360000);
assert(deadline("hq-body",now)==now+240000);
assert(deadline("convoy",now)==now+540000);
assert(deadline("convoy",now,false,false,false,true)==now+840000);
assert(deadline("supply-convoys",now)==now+840000);
assert(deadline("convoy",now,true)==now+840000);
assert(deadline("mounted-ammo",now)==now+330000);
assert(deadline("mounted-ammo",now,false,true)==now+750000);
assert(deadline("normal-escape-route",now,false,false,true)==now+330000);
}
}
'''.replace('DECLARATIONS', ','.join(flag+'=false' for flag in flags)).replace('SELECTOR',selector))
print('PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines')
# The new route diagnostic must leave the original administrator/reroll stress
# intact and may skip only those extras, never clue or radio progression gates.
route=body(Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')), 'bool ERR_CheckRouteExtras(float now)').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance')
run(r'''
#include <cassert>
#include <string>
struct Probe {
bool m_ERRTestEscapeRoute=false,rerollReady=false,maintenance=false,maintenanceReady=false;
int maintenanceCalls=0; bool ERR_RunMaintenance(float){maintenanceCalls++;return maintenanceReady;}
int adminResult=0,adminCalls=0,rerollCalls=0,failures=0;
int ERR_ProbeAdminMenu(float){adminCalls++;return adminResult;}
bool ERR_Check(bool result,std::string){if(!result)failures++;return result;}
bool ERR_CheckIntelReroll(float){rerollCalls++;return rerollReady;}
METHOD
};
int main(){
Probe route;route.m_ERRTestEscapeRoute=true;assert(route.ERR_CheckRouteExtras(100));
assert(route.adminCalls==0&&route.rerollCalls==0&&route.failures==0);
route.maintenance=true;assert(!route.ERR_CheckRouteExtras(101)&&route.maintenanceCalls==1);
route.maintenanceReady=true;assert(route.ERR_CheckRouteExtras(102)&&route.maintenanceCalls==2&&route.adminCalls==0&&route.rerollCalls==0);
Probe full;assert(!full.ERR_CheckRouteExtras(100)&&full.adminCalls==1&&full.rerollCalls==0);
full.adminResult=-1;assert(!full.ERR_CheckRouteExtras(200)&&full.failures==1&&full.rerollCalls==0);
full.adminResult=1;assert(!full.ERR_CheckRouteExtras(300)&&full.rerollCalls==1);
full.rerollReady=true;assert(full.ERR_CheckRouteExtras(400)&&full.rerollCalls==2);
}
'''.replace('METHOD',route))
assert 'if (!ERR_CheckRouteExtras(now)) return;' in smoke
assert 'if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2,' in smoke
assert 'if (!ERR_Check(Phase() == ERR_Phase.EXTRACTION,' in smoke
print('PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths')
# Execute the actual scenario-selection expressions: normal route must retain
# the ordinary catalog AND random placement, while historical probes stay fixed.
scenario=(REPO/'addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c').read_text()
conditions=[]
for variable in ('historicalFixture','fixture'):
line=next(line.strip() for line in scenario.splitlines() if line.strip().startswith('if (') and 'System.GetCLIParam("errSmokeOutcome", '+variable+')' in line)
expression=line[4:-1].replace('System.GetCLIParam("errSmokeOutcome", '+variable+')','supplied').replace(variable,'outcome')
conditions.append(expression)
run(r'''
#include <cassert>
#include <string>
using string=std::string;
bool legacy(bool supplied,string outcome,bool m_TerrainIndependent=false){return LEGACY;}
bool fixed(bool supplied,string outcome,bool m_TerrainIndependent=false){return FIXED;}
int main(){
for(string route : {"normal-escape-route","generated-sites","optional-site-skip"}) {assert(!legacy(true,route));assert(!fixed(true,route));}
for(string route : {"escape-route","victory","transport-survey"}) {assert(legacy(true,route));assert(fixed(true,route));}
assert(!legacy(false,"escape-route")&&!fixed(false,"escape-route"));
}
'''.replace('LEGACY',conditions[0]).replace('FIXED',conditions[1]))
print('PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged')
# Execute the actual patrol-hq admission branch. The existing production
# prison-AI/progression tests cover canonical UnlockPrison and phase callbacks;
# here native damage, allocation and unlock boundaries are explicit doubles.
smoke_path=Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c'))
smoke_tick=body(smoke_path,'protected void ERR_SmokeTick(')
a=smoke_tick.index('if (m_ERRTestPatrolHQ)'); b=smoke_tick.index('{',a); i=b+1; depth=1
while depth:
depth+=(smoke_tick[i]=='{')-(smoke_tick[i]=='}');i+=1
patrol_branch=smoke_tick[a:i]
patrol_branch=patrol_branch.replace('DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);','ProtectOriginal(m_ERRSmokePlayer);').replace('ERR_Phase.RADIO_SEARCH','2')
run(r'''
#include <cassert>
#include <string>
struct Fixture;
struct ERR_NativePatrolProbe {explicit ERR_NativePatrolProbe(Fixture* owner);};
struct Fixture {
bool m_ERRTestPatrolHQ=true,allowed=true,wrongPhase=false,active=false;
int m_ERRSmokePlayer=7,phase=1,unlocks=0,failures=0,allocations=0,protections=0,m_ERRSmokeStep=0;
ERR_NativePatrolProbe* m_ERRHQPatrolMovement=nullptr;
~Fixture(){delete m_ERRHQPatrolMovement;}
void ProtectOriginal(int actor){assert(actor==7);protections++;}
bool UnlockPrison(int actor){assert(actor==7);unlocks++;if(!allowed)return false;if(!wrongPhase){phase=2;active=true;}return true;}
int Phase(){return phase;}
bool ERR_Check(bool ok,std::string){if(!ok)failures++;return ok;}
void Start(){BRANCH}
};
ERR_NativePatrolProbe::ERR_NativePatrolProbe(Fixture* owner){assert(owner->phase==2&&owner->active&&owner->unlocks==1);owner->allocations++;}
int main(){
Fixture healthy;healthy.Start();assert(healthy.m_ERRSmokeStep==130&&healthy.allocations==1&&healthy.failures==0&&healthy.protections==1);
Fixture refused;refused.allowed=false;refused.Start();assert(refused.unlocks==1&&refused.failures==1&&refused.allocations==0&&refused.m_ERRSmokeStep==0&&!refused.active);
Fixture wrong;wrong.wrongPhase=true;wrong.Start();assert(wrong.unlocks==1&&wrong.failures==1&&wrong.allocations==0&&wrong.m_ERRSmokeStep==0);
Fixture other;other.m_ERRTestPatrolHQ=false;other.Start();assert(other.unlocks==0&&other.allocations==0&&other.protections==0&&other.m_ERRSmokeStep==0);
}
'''.replace('BRANCH',patrol_branch))
print('PASS: actual patrol fixture leaves prison before movement observation and refuses failed transition')