Import verified AzerothAI snapshot from GitHub
Core tests / core (push) Successful in 9m57s
Full verification / application (push) Failing after 5m16s
Full verification / local-brain (push) Failing after 6m15s
Realm simulation / simulated-live-world (push) Failing after 5m32s
WoW integration lab / real-worldserver (push) Canceled after 17m23s
Core tests / core (push) Successful in 9m57s
Full verification / application (push) Failing after 5m16s
Full verification / local-brain (push) Failing after 6m15s
Realm simulation / simulated-live-world (push) Failing after 5m32s
WoW integration lab / real-worldserver (push) Canceled after 17m23s
Source branch: feature/ai-brain-router Source commit: c2a09e0460465201a58aaab56c71424e9a96405e
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
const base=(process.env.AZEROTHAI_URL||'http://127.0.0.1:8787').replace(/\/$/,'');
|
||||
const token=process.env.ALE_BRIDGE_TOKEN||'simulation-bridge-token';
|
||||
const autonomyToken=process.env.AUTONOMY_TOKEN||'simulation-autonomy-token';
|
||||
|
||||
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
|
||||
const assert=(condition,message)=>{if(!condition)throw new Error(message);};
|
||||
|
||||
async function json(path,options={}){
|
||||
const r=await fetch(base+path,options);
|
||||
const text=await r.text();
|
||||
let body;
|
||||
try{body=text?JSON.parse(text):null;}catch{body={raw:text};}
|
||||
if(!r.ok)throw new Error(`${options.method||'GET'} ${path} -> ${r.status}: ${text.slice(0,1000)}`);
|
||||
return body;
|
||||
}
|
||||
|
||||
async function ale(kind,payload={}){
|
||||
return json('/api/bridge/ale/event',{
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json',Authorization:`Bearer ${token}`},
|
||||
body:JSON.stringify({kind,payload})
|
||||
});
|
||||
}
|
||||
|
||||
async function state(){return json('/api/state');}
|
||||
|
||||
console.log('Booting simulated live-world event sequence...');
|
||||
const initial=await state();
|
||||
assert(initial.bots.some(b=>b.id==='hero-zaku'),'Seeded Zaku is missing');
|
||||
assert(!initial.population?.lastPlan,'Population plan should be empty before authoritative human movement');
|
||||
|
||||
await ale('bridge.ready',{pollMs:750,protectedCharacter:'Zaku'});
|
||||
await ale('server.startup',{players:1});
|
||||
|
||||
await ale('player.login',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:85,areaId:159,isBot:true,zoneName:'Brill'
|
||||
});
|
||||
await ale('player.zone',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest'
|
||||
});
|
||||
|
||||
let afterBotMove=await state();
|
||||
assert(!afterBotMove.population?.lastPlan,'AI resident movement incorrectly triggered the Population Director');
|
||||
|
||||
await ale('player.combat.enter',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest',enemy:'Moonrage Glutton'
|
||||
});
|
||||
await ale('player.close-call',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest',healthBefore:23,incomingDamage:61
|
||||
});
|
||||
await ale('player.combat.leave',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest'
|
||||
});
|
||||
await ale('player.quest.accept',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest',quest:'The Dead Fields'
|
||||
});
|
||||
await ale('player.snapshot',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest'
|
||||
});
|
||||
|
||||
await ale('player.login',{
|
||||
name:'Durnak',characterGuid:9002,accountId:502,level:22,mapId:0,zoneId:40,areaId:40,isBot:true,zoneName:'Westfall'
|
||||
});
|
||||
await ale('player.zone',{
|
||||
name:'Durnak',characterGuid:9002,accountId:502,level:22,mapId:0,zoneId:40,areaId:40,isBot:true,zoneName:'Westfall'
|
||||
});
|
||||
await ale('player.combat.enter',{
|
||||
name:'Durnak',characterGuid:9002,accountId:502,level:22,mapId:0,zoneId:40,areaId:40,isBot:true,zoneName:'Westfall',enemy:'Defias Pillager'
|
||||
});
|
||||
await ale('player.killed-by-creature',{
|
||||
name:'Durnak',characterGuid:9002,accountId:502,level:22,mapId:0,zoneId:40,areaId:40,isBot:true,zoneName:'Westfall',killer:'Defias Pillager'
|
||||
});
|
||||
await ale('player.resurrect',{
|
||||
name:'Durnak',characterGuid:9002,accountId:502,level:22,mapId:0,zoneId:40,areaId:40,isBot:true,zoneName:'Westfall'
|
||||
});
|
||||
|
||||
await ale('player.killed-by-creature',{
|
||||
name:'Zaku',characterGuid:9001,accountId:501,level:14,mapId:0,zoneId:130,areaId:130,isBot:true,zoneName:'Silverpine Forest',killer:'Moonrage Glutton'
|
||||
});
|
||||
|
||||
await ale('player.login',{
|
||||
name:'Player',level:12,mapId:0,zoneId:10,areaId:10,isBot:false,zoneName:'Duskwood'
|
||||
});
|
||||
await ale('player.zone',{
|
||||
name:'Player',level:12,mapId:0,zoneId:10,areaId:10,isBot:false,zoneName:'Duskwood'
|
||||
});
|
||||
|
||||
await sleep(250);
|
||||
|
||||
const autonomy=await json('/api/autonomy/tick',{
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json',Authorization:`Bearer ${autonomyToken}`},
|
||||
body:'{}'
|
||||
});
|
||||
assert(autonomy.ran===true,'Autonomy heartbeat did not select a live managed Playerbot');
|
||||
assert(autonomy.name==='Zaku',`Expected Zaku to receive autonomous intent, got ${autonomy.name}`);
|
||||
|
||||
const polled=await fetch(base+'/api/bridge/ale/poll',{
|
||||
headers:{Authorization:`Bearer ${token}`}
|
||||
});
|
||||
assert(polled.status===200,`ALE bridge did not receive queued autonomous command: HTTP ${polled.status}`);
|
||||
const commandId=polled.headers.get('x-azerothai-command');
|
||||
const lua=await polled.text();
|
||||
assert(commandId,'Autonomous ALE command had no command id');
|
||||
assert(lua.includes('GetPlayerByName("Zaku")'),'Autonomous ALE command did not target Zaku');
|
||||
assert(lua.includes(':GetBotAI()'),'Autonomous ALE command did not route through PlayerBotAI');
|
||||
await json('/api/bridge/ale/result',{
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json',Authorization:`Bearer ${token}`},
|
||||
body:JSON.stringify({id:commandId,ok:true,result:'simulated PlayerBotAI intent accepted'})
|
||||
});
|
||||
|
||||
const finalState=await state();
|
||||
const monitor=await json('/api/world-monitor');
|
||||
|
||||
const zaku=finalState.bots.find(b=>b.id==='hero-zaku');
|
||||
const durnak=finalState.bots.find(b=>b.id==='bot-2');
|
||||
|
||||
assert(zaku,'Zaku disappeared');
|
||||
assert(durnak,'Durnak disappeared');
|
||||
assert(zaku.status!=='dead','Zaku entered the death state');
|
||||
assert(zaku.zone==='Silverpine Forest',`Zaku authoritative zone did not sync: ${zaku.zone}`);
|
||||
assert(zaku.level===14,`Zaku authoritative level did not sync: ${zaku.level}`);
|
||||
assert(zaku.autonomy?.managed===true,'Zaku was not adopted as a managed live resident');
|
||||
assert(zaku.autonomy?.characterGuid===9001,`Zaku character GUID binding was not persisted: ${zaku.autonomy?.characterGuid}`);
|
||||
assert(zaku.autonomy?.accountId===501,`Zaku account binding was not persisted: ${zaku.autonomy?.accountId}`);
|
||||
assert(zaku.decisions>=1,'Autonomous heartbeat did not persist a Zaku decision');
|
||||
assert(zaku.memories.some(m=>m.source==='observation'&&/barely survived/i.test(m.text)),'Zaku did not retain a close-call memory');
|
||||
assert(zaku.memories.some(m=>/accepted The Dead Fields/i.test(m.text)),'Zaku did not retain an authoritative quest memory');
|
||||
assert(durnak.status==='dead',`Durnak should be permanently dead, got ${durnak.status}`);
|
||||
assert(durnak.death?.verified===true,'Durnak death was not verified');
|
||||
assert(durnak.death?.source==='azerothcore',`Durnak death source should be azerothcore, got ${durnak.death?.source}`);
|
||||
assert(durnak.death?.killer==='Defias Pillager','Durnak killer was not preserved');
|
||||
assert(zaku.memories.some(m=>/Durnak died permanently/i.test(m.text)),'Zaku did not receive memorial memory for a known realm death');
|
||||
assert(finalState.population?.lastPlan?.trigger?.zone==='Duskwood','Human movement did not drive the Population Director');
|
||||
assert(finalState.population?.lastPlan?.trigger?.playerName==='Player','Human player name was not preserved in population trigger');
|
||||
assert(monitor.ale?.bridgeReady===true,'World Monitor did not see bridge.ready');
|
||||
assert(monitor.ale?.activeRecently===true,'World Monitor did not mark recent ALE activity live');
|
||||
assert((monitor.playerbots?.observedBots??0)>=2,'World Monitor did not observe both live Playerbot identities');
|
||||
assert(monitor.events.some(e=>e.kind==='player.close-call'&&e.name==='Zaku'),'World Monitor missed Zaku close-call ALE event');
|
||||
assert(monitor.events.some(e=>e.kind==='player.killed-by-creature'&&e.name==='Durnak'),'World Monitor missed authoritative death ALE event');
|
||||
assert(finalState.events.some(e=>e.kind==='error'&&/Plot armor breach/.test(e.message)&&e.botId==='hero-zaku'),'Zaku kill report did not produce a plot-armor breach alert');
|
||||
assert(finalState.events.some(e=>e.kind==='error'&&/permanently dead resident Durnak/.test(e.message)),'Hardcore resurrection attempt was not rejected in state');
|
||||
|
||||
const report={
|
||||
result:'PASS',
|
||||
zaku:{
|
||||
status:zaku.status,
|
||||
level:zaku.level,
|
||||
zone:zaku.zone,
|
||||
closeCallRemembered:zaku.memories.some(m=>/barely survived/i.test(m.text)),
|
||||
rememberedDurnakDeath:zaku.memories.some(m=>/Durnak died permanently/i.test(m.text)),
|
||||
plotArmorBreachAlerted:finalState.events.some(e=>e.kind==='error'&&/Plot armor breach/.test(e.message)&&e.botId==='hero-zaku'),
|
||||
characterGuid:zaku.autonomy?.characterGuid,
|
||||
autonomousDecisions:zaku.decisions,
|
||||
lastDecision:zaku.lastDecision?.action
|
||||
},
|
||||
durnak:{
|
||||
status:durnak.status,
|
||||
verifiedDeath:durnak.death?.verified,
|
||||
deathSource:durnak.death?.source,
|
||||
killer:durnak.death?.killer,
|
||||
resurrectionRejected:finalState.events.some(e=>e.kind==='error'&&/permanently dead resident Durnak/.test(e.message))
|
||||
},
|
||||
population:{
|
||||
trigger:finalState.population?.lastPlan?.trigger?.kind,
|
||||
zone:finalState.population?.lastPlan?.trigger?.zone,
|
||||
playerName:finalState.population?.lastPlan?.trigger?.playerName,
|
||||
selected:finalState.population?.lastPlan?.selectedBotIds?.length??0
|
||||
},
|
||||
worldMonitor:{
|
||||
bridgeReady:monitor.ale?.bridgeReady,
|
||||
activeRecently:monitor.ale?.activeRecently,
|
||||
observedBotEvents:monitor.playerbots?.observedBots,
|
||||
visibleAleEvents:monitor.events.length
|
||||
},
|
||||
checks:[
|
||||
'AI movement does not trigger human-centered population activation',
|
||||
'authoritative bot zone and level sync back into AzerothAI',
|
||||
'Zaku close call becomes a diegetic memory',
|
||||
'ordinary Hardcore death is permanent and verified',
|
||||
'dead resident resurrection is rejected by AzerothAI state',
|
||||
'Zaku cannot enter the death state even when a bad authoritative kill event arrives',
|
||||
'human movement drives the Population Director',
|
||||
'World Monitor receives live-style ALE telemetry',
|
||||
'live resident identity is bound to authoritative character GUID/account',
|
||||
'autonomy heartbeat queues a real PlayerBotAI command through ALE'
|
||||
]
|
||||
};
|
||||
|
||||
console.log('\n=== AZEROTHAI LIVE-WORLD SIMULATION ===');
|
||||
console.log(JSON.stringify(report,null,2));
|
||||
Reference in New Issue
Block a user