diff --git a/src/simulator/api-gdext/src/ai.rs b/src/simulator/api-gdext/src/ai.rs index 71169988..b77f0fd3 100644 --- a/src/simulator/api-gdext/src/ai.rs +++ b/src/simulator/api-gdext/src/ai.rs @@ -270,7 +270,13 @@ fn decide_strategic_kind(state: &GameState, player_index: usize, seed: u64) -> & // sets current_player from the GameState's turn-order, not from the caller's // explicit slot, so align it here. tactical.current_player = player_slot; - let actions = run_ai_turn(&tactical, player_slot, &weights, seed); + // p1-29h — this FFI probe derives a one-shot strategic-directive string for + // GDScript production priming; it is NOT the persistent live-decision path + // (that is the pure-Rust `mc_player_api::dispatch::drive_ai_slot`, which + // p1-29d measures and which threads the slot's persisted memory). A + // transient per-call memory is correct here. + let mut memory = mc_ai::tactical::TacticalMemory::default(); + let actions = run_ai_turn(&tactical, player_slot, &weights, seed, &mut memory); derive_strategic_kind(&actions) } @@ -905,7 +911,13 @@ pub fn run_tactical( seed: u64, ) -> Vec { let mut rng = XorShift64::new(seed); - let actions: Vec = decide_tactical_actions(state, weights, &mut rng, None); + // p1-29h — `run_tactical` is the stateless GdAiController FFI shim: it owns + // no GameState and no persistent slot state, so the army-level memory is a + // documented transient here. The persistent army-lock lives on the + // pure-Rust dispatch path (`drive_ai_slot`), the surface p1-29d measures. + let mut memory = mc_ai::tactical::TacticalMemory::default(); + let actions: Vec = + decide_tactical_actions(state, weights, &mut rng, None, &mut memory); actions .into_iter() .filter_map(|a| match serde_json::to_string(&a) {