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:
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"conclusion": "IsAIActivated does not identify prison hold. SDK explicitly says agents are disabled at maxLOD. The failed all-active assertion does not prove a prison-release defect. Individual failed agent LOD/cause was not logged, so distance dormancy remains a source-supported explanation, not established attribution.",
|
||||
"sdk": {
|
||||
"path": "/tmp/erri-vanilla-stock/scripts/Game/generated/AI/AIAgent.c",
|
||||
"sha256": "83d066ddd047136cc045228ce41e6a5f50f2b603c33fc7a0b4140061844f2a98",
|
||||
"lines": "20-37 GetLOD/SetPermanentLOD/PreventMaxLOD/AllowMaxLOD and native maxLOD disable semantics"
|
||||
},
|
||||
"phase_history": "Smoke EOnInit subscribes before scheduled StartScenario (1500ms); crash flag assigned before subscription. ERR_SmokePhase records any entered PRISON. Initial route requires RADIO_SEARCH. Existing source ERR_PrisonPhaseChanged unsubscribes and releases on current==RADIO_SEARCH without depending on previous; test now explicitly covers0->2 and1->2.",
|
||||
"limits": [
|
||||
"Probe enumerates currently retained force-ledger group agents; no claim of a historical roster snapshot or replacement detection.",
|
||||
"Active/dormant counts are diagnostic only and do not attribute dormancy to one engine subsystem.",
|
||||
"No native rerun by reviewer; no proof of crash full route yet."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c
|
||||
@@ -4,6 +4,10 @@
|
||||
modded class SCR_ChimeraAIAgent
|
||||
{
|
||||
protected ERR_GameMode m_ERRPrisonMode;
|
||||
+#ifdef WORKBENCH
|
||||
+ // Observe only this mission hold; native distance LOD may independently deactivate AI.
|
||||
+ bool ERR_PrisonHeldForTest() { return m_ERRPrisonMode != null; }
|
||||
+#endif
|
||||
|
||||
void ERR_HoldForPrison()
|
||||
{
|
||||
--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
|
||||
@@ -541,6 +541,29 @@
|
||||
PrintFormat("ERR PRISON AI: checked=%1 active=%2", checked, active);
|
||||
return checked > 0;
|
||||
}
|
||||
+ protected bool ERR_CrashPrisonHoldReleased()
|
||||
+ {
|
||||
+ if (!Forces() || Forces().Count() > 256) return false;
|
||||
+ int checked, held, active, dormant;
|
||||
+ for (int i = 0; i < Forces().Count(); i++)
|
||||
+ {
|
||||
+ ERR_ForceRecord record = Forces().At(i);
|
||||
+ if (!record || !record.Group) continue;
|
||||
+ array<AIAgent> agents = {};
|
||||
+ record.Group.GetAgents(agents);
|
||||
+ if (agents.Count() > 128) return false;
|
||||
+ foreach (AIAgent original : agents)
|
||||
+ {
|
||||
+ SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(original);
|
||||
+ if (!agent || !agent.GetControlledEntity()) return false;
|
||||
+ checked++;
|
||||
+ if (agent.ERR_PrisonHeldForTest()) held++;
|
||||
+ if (agent.IsAIActivated()) active++; else dormant++;
|
||||
+ }
|
||||
+ }
|
||||
+ PrintFormat("ERR CRASH PRISON HOLD: checked=%1 held=%2 active=%3 dormant=%4; native activation is independent", checked, held, active, dormant);
|
||||
+ return checked > 0 && held == 0;
|
||||
+ }
|
||||
protected void ERR_EndScreenshot() { System.MakeScreenshot("$logs:err-result"); }
|
||||
protected void ERR_BeginProtectedDeathProbe(float now)
|
||||
{
|
||||
@@ -906,7 +929,7 @@
|
||||
}
|
||||
if (m_ERRTestCrashStart)
|
||||
{
|
||||
- if (!ERR_Check(!m_ERRCrashEnteredPrison && ERR_PrisonAIState(true), "crash start never enters prison and existing enemies are active")) return;
|
||||
+ if (!ERR_Check(!m_ERRCrashEnteredPrison && ERR_CrashPrisonHoldReleased(), "crash start never enters prison and existing enemies have no prison hold")) return;
|
||||
if (!ERR_NativeCrashStartProbe.Run(this, m_ERRSmokePlayer)) { m_ERRSmokeDone = true; GetGame().GetCallqueue().Remove(ERR_SmokeTick); return; }
|
||||
}
|
||||
else
|
||||
--- a/tests/test_prison_ai.py
|
||||
+++ b/tests/test_prison_ai.py
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Run the production prison hold/release callbacks with engine boundaries stubbed."""
|
||||
from policy_harness import ROOT, body, run
|
||||
-source = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c'
|
||||
+from pathlib import Path
|
||||
+import os
|
||||
+source = Path(os.environ.get('ERR_PRISON_AI_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c'))
|
||||
def cpp(signature):
|
||||
s=body(source,signature).replace('protected ','')
|
||||
for ns in ('Replication','SCR_Global','ERR_GameMode','ERR_Phase','ERR_Actors','SCR_FactionManager'):
|
||||
@@ -32,16 +34,17 @@
|
||||
struct Agent {ERR_GameMode* m_ERRPrisonMode=nullptr;Actor* actor=nullptr;bool pending=false,active=true;int starts=0;
|
||||
Actor* GetControlledEntity(){return actor;}bool IsPlayerPending_S(){return pending;}
|
||||
void DeactivateAI(){active=false;}void ActivateAI(){active=true;starts++;}
|
||||
-'''+cpp('void ERR_HoldForPrison(')+cpp('protected void ERR_PrisonUnsubscribe(')+cpp('protected void ERR_PrisonPhaseChanged(')+cpp('protected void ERR_PrisonStopped(')+r'''
|
||||
+'''+cpp('bool ERR_PrisonHeldForTest(')+cpp('void ERR_HoldForPrison(')+cpp('protected void ERR_PrisonUnsubscribe(')+cpp('protected void ERR_PrisonPhaseChanged(')+cpp('protected void ERR_PrisonStopped(')+r'''
|
||||
};
|
||||
int main(){
|
||||
for(int phase=0;phase<=1;phase++){
|
||||
ERR_GameMode mode;mode.phase=phase;ERR_GameMode::current=&mode;Actor actor;Agent a;a.actor=&actor;
|
||||
- a.ERR_HoldForPrison();assert(!a.active&&mode.phases.callbacks.size()==1&&mode.stops.callbacks.size()==1);
|
||||
+ a.ERR_HoldForPrison();assert(a.ERR_PrisonHeldForTest());assert(!a.active&&mode.phases.callbacks.size()==1&&mode.stops.callbacks.size()==1);
|
||||
a.active=true;a.ERR_HoldForPrison();assert(!a.active&&mode.phases.inserted==1);
|
||||
a.ERR_PrisonPhaseChanged(0,1);assert(!a.active&&a.m_ERRPrisonMode==&mode);
|
||||
- mode.phase=2;a.ERR_PrisonPhaseChanged(1,2);assert(a.active&&a.starts==1&&!a.m_ERRPrisonMode&&mode.phases.callbacks.empty()&&mode.stops.callbacks.empty());
|
||||
+ mode.phase=2;a.ERR_PrisonPhaseChanged(phase,2);assert(a.active&&a.starts==1&&!a.m_ERRPrisonMode&&mode.phases.callbacks.empty()&&mode.stops.callbacks.empty());
|
||||
a.ERR_HoldForPrison();assert(a.active&&mode.phases.inserted==1);
|
||||
+ assert(!a.ERR_PrisonHeldForTest());a.DeactivateAI();assert(!a.active&&!a.ERR_PrisonHeldForTest());
|
||||
}
|
||||
for(int fault=0;fault<8;fault++){
|
||||
ERR_GameMode mode;ERR_GameMode::current=&mode;Actor actor;Agent a;a.actor=&actor;
|
||||
@@ -0,0 +1 @@
|
||||
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"scope": "Read-only proposed nearby activation witness; current parent native run not modified.",
|
||||
"source_sha256": "c8767f6eb946655df3c0cfcdc471e3b51b5d13cd2859c39591b12c3f5906deb9",
|
||||
"sdk_sha256": "83d066ddd047136cc045228ce41e6a5f50f2b603c33fc7a0b4140061844f2a98",
|
||||
"recommendation": "Crash-only observation at existing step3 before radio movement, after two existing2500ms waits at everon-supply-1 cache. Require at least one living nonplayer guard from exact pinned original cache roster within100m of canonical player with IsAIActivated true. Preserve original group/member identity; never spawn/activate/changeLOD. Log checked/living/nearby/nearbyActive with current GetLOD/GetPermanentLOD and prison hold flags for nearby members.",
|
||||
"identity_limit": "SiteRuntime.InitialGuardCount is a count, not retained member identities; pin initial group and agents at step0 if the assertion says original. Current GetAgents alone supports only current guard claim.",
|
||||
"sdk_limit": "Generated AIAgent documents maxLOD disabled state and native GetLOD/IsAIActivated. It does not promise reactivation within5000ms. A failed observation is retained qualification evidence, not proof of a particular production defect.",
|
||||
"changes": [],
|
||||
"compiler_or_native_runs": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": {
|
||||
"baseline_sha256": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"proposed_sha256": "67f8b444824634fc37fc253c60fd24b56d06d971f48e56a8d53095c97aaf0070"
|
||||
},
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": {
|
||||
"baseline_sha256": "ce55c8be0047406e17ec4dced1912332ab4347bfa1f204921302392099a9e67b",
|
||||
"proposed_sha256": "c8767f6eb946655df3c0cfcdc471e3b51b5d13cd2859c39591b12c3f5906deb9"
|
||||
},
|
||||
"tests/test_prison_ai.py": {
|
||||
"baseline_sha256": "557015a4a3191aede258dcd7dee4ec4f555c3efde02331687185ed124cebb4fc",
|
||||
"proposed_sha256": "9c0db6205bde7df7710acfc6bb20231f9e893b0f3913b7a2c4cfcf45e219a70d"
|
||||
}
|
||||
},
|
||||
"patch_sha256": "341f2a50aef996328b866830125f613ede1c94abd8f3342be210fe7d9e6d5f49",
|
||||
"test": {
|
||||
"exit_code": 0,
|
||||
"green_sha256": "63ef1dee605d5ea050f379a0fdfd398c5593126bc0db3d7cb48e12e1151c1523",
|
||||
"actual_methods": "ERR_HoldForPrison, ERR_PrisonPhaseChanged, ERR_PrisonUnsubscribe, ERR_PrisonStopped and WB getter",
|
||||
"controls": "Original assertions retained, both PREPARING and PRISON previous phases directly tested; native deactivation after release remains distinct from hold."
|
||||
},
|
||||
"scope": "WORKBENCH diagnostic only; production hold, phase callbacks, activation and stop behavior unchanged."
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"ERR_TerrainTakeover.c": "/tmp/erri-optional-identity-1509/test-root/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c",
|
||||
"ERR_TerrainTakeoverManagers.c": "/tmp/erri-optional-identity-1509/test-root/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c"
|
||||
}
|
||||
Reference in New Issue
Block a user