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:
+22
@@ -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>.
|
||||
+1164
File diff suppressed because it is too large
Load Diff
+120
@@ -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
|
||||
+44
@@ -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"
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
|
||||
+2
@@ -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
|
||||
+39
@@ -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
|
||||
}
|
||||
+1165
File diff suppressed because it is too large
Load Diff
+157
@@ -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')
|
||||
Reference in New Issue
Block a user