2026-04-15 07:45 iter 4 status: CODE DEPLOYED but 0 improvements built (1 worker created at t133, no start/completed events). Debugging. Queued iter 5: HUNTING_GROUNDS improvement type (fauna-tier, forest/tundra tile with adjacent fauna).
2026-04-15 07:30 iter 4 COMPLETE: TILE IMPROVEMENTS, 0→2 improvement events (seed 1 smoke), files=1 (auto_play.gd, +15/-5). Root cause: _command_unit defined but never called; _play_turn had inline loops that skipped workers. Fix: added explicit worker-command loop + workers excluded from ATTACK/garrison branches. Bonus: seed 1 hit victory at t=379 (2nd-consecutive victory signal after iter 3's seed 1 t=132).
2026-04-15 17:47 iter 5 (fresh binary): GROWTH confirmed (median p0_pop_peak 5), 0 invariants. VICTORY at 0/3 within 150-turn cap — structural since smoke-seed-1 took 379 turns. Regression caught: mac→apricot rsync had clobbered apricot's .so with Apr-12 stale binary; rebuilt on apricot at 17:36, added gitignore rule + CLAUDE.md warning. Team dispatched to speed up victories.
2026-04-16 01:13 iter 5 COMPLETE: VICTORY gap (attack conversion). Shipped 14-factor state-based scoring in _next_building() + loosened ATTACK trigger (advantage≥1.1 OR enemy_city_within_6 OR mil-vs-zero) + 10-turn phase hysteresis. Seed 1 smoke: 172 combats (up from 19 baseline), 2.4:1 KDR (48:20 kills), strategy emerges (≥6 distinct items chosen). Still no capture: seed 1 is structurally mountain-locked (1 production-crippled city vs enemy's 3 cities). Running 3-seed batch at 400-turn cap next to see seeds 2/3 fare. Files=1 (auto_play.gd, +153/-90 net). DEBT: attack decision still uses prescriptive thresholds; iter 6 should promote to scoring (objective-based commitment) per approved plan.
2026-04-16 01:34 iter 6 COMPLETE: CITY SITING. Wired _score_site() into settler decisions via new _decide_settler(). 3-seed smoke (250-300t): p0 pop_peak 6/9/8 (iter 5: 2), first_pop_4 at 77/25/43, 0 invariants. Seed 1 no longer mountain-locked (founds at (25,-1) not (24,-3)). Found + fixed real root cause: _try_found_city() was the greedy founder, not _command_unit() settler branch (different call site). Also fixed 4 bugs in _score_site() (deep_ocean typo, wrong food-zero biomes incl. missing boreal_forest/volcano/snow, dead river branch, impassable not rejected). Files=1 (auto_play.gd, +80/-22). Terrain-auditor agent provided exact biome constants.
2026-04-13 (task #10) TECH GATE VERIFICATION: JSON has tech_required on cavalry/spearmen/pikeman/wyvern_riders and 0 buildings (all null). Rust QueueError::TechLocked only guards item queue (enqueue_item), NOT building/unit queue. GDScript gap: city_buildable_helper populate_* called city.can_build() which did not exist → UI filter silently skipped via has_method guard. ProductionFilter defined but had zero callers (dead code). Auto_play _next_building has its own hardcoded tech_req map covering 4 buildings; candidate unit list is warrior/founder/worker only (none tech-gated), so no smoke-observable violation today but gate was hypothetical. FIX (city.gd +~16 lines, inlined _instantiate_gd_city & _parse_json_dict to stay ≤500): added City.can_build() delegating to ProductionFilter.is_unit_buildable/is_building_buildable; City.add_to_queue() now rejects gated items (returns bool). This wires the existing UI filter and closes the GDScript-path gap mirroring rust-resource-dev's pattern. DEBT: building/unit completion still GDScript-side; Rust-side enforcement symmetry with item queue (QueueError::TechLocked) remains future work.
2026-04-16 03:55 iter 8 COMPLETE (5 waves of agents, 10 tasks): VICTORY RATE IMPROVED (seed 1 dom victory t=94 from military-dev), plus 9 other gaps addressed. Tasks: #1 siege math (Rust mc-combat wall penalties + bug: city.city_hp→city.hp), #2 strategic resource filter (GDScript UI), #3 luxury tracking in player_stats, #5 RNG state serialization (RandomNumberGenerator.state), #6 parse errors (TechWeb stubs, null school_affinity, PackedFloat32Array), #7 Rust resource enforcement (mc-city production, 27 tests), #8 military sustain (auto_play stack+hysteresis), #9 happiness buildings verified + 2 new (ale_hall, bathhouse), #10 tech gate activation (ProductionFilter had zero callers — now wired), #4 fauna loot drops (with 7 subfixes including JSON float→u32). Test scaffold from #4 gated behind AUTO_PLAY_TEST_LOOT_SCAFFOLD env var to not bias normal batches.
2026-04-16 04:05 iter 8 FINAL BATCH: 2/3 victories (66%, hits stop criterion numerically) BUT median turn=68.5 indicates OVERSHOT — siege buff made capture trivial, and p1 AI collapses in 2/3 seeds (0 cities, 0 mil in seed 2; 1 city lost turn 68 in seed 1; only seed 3 has functional p1). Victory rate is synthetic, not from "real 4X game". Need iter 9 to: (a) rebalance siege (wall penalty 0.85→0.80 midpoint), (b) fix enemy AI production loss (likely caused by add_to_queue bool-reject swallowing failed tech-gated attempts). Game is NOT 100% complete despite numerical metrics.
2026-04-16 04:45 iter 9: siege rebalance (walls penalty 0.85→0.80, castle 0.75→0.65, siege bonus 2.0→1.7) + simple_heuristic_ai production fix (can_build pre-filter, fallback military, emergency Priority 0 garrison, fixed MILITARY_COMBAT_TYPES never-matched bug where AoD uses unit_type:military not combat_type:melee). Seed 3 acceptance met (p1 3 cities 5 mil). Seeds 1-2 still end t68-69 because p0 uses auto_play's aggressive 14-factor scoring while p1 uses simple_heuristic_ai — AI asymmetry makes p0 dominate. iter 10: fix AI matchup so both players play same AI OR equalize auto_play aggression to simple_heuristic_ai pacing.
2026-04-16 06:15 task #4 STRATEGIC RESOURCES (resources-verify-dev): VERIFICATION task. Iter 8 #7 already shipped Rust QueueError::MissingResource + full wiring through api-gdext → city.gd.enqueue_item(available_resources) → auto_play/city_buildable_helper player_owns_resource gate. Only test coverage gap. Added GUT test `test_enqueue_rejects_when_strategic_resource_missing` in test_city_bridge.gd mirroring the Rust test via GdCity bridge (+45 lines, gdlint clean). `cargo test -p mc-city` 27/27 green. Smoke seed 1/150 victory t118; resource-gated units (cavalry, spearmen) not in AI candidate list so no runtime rejection logs but gate is wired. DEBT: ProductionFilter._unit_allowed() doesn't check requires_resource — theoretical bypass only; external callers filter first.
2026-04-16 06:25 task #6 LUXURY + FAUNA (resources-verify-dev): VERIFICATION task (two 4X checklist items bundled). Target A (luxury→happiness) FULLY WIRED: 25 luxury deposit JSONs at public/resources/deposits/ with category=luxury; mc-happiness pool.rs LUXURY_HAPPINESS=4; happiness.gd counts unique luxuries across player.cities[*].owned_tiles vs 22-id LUXURY_DEPOSITS const; smoke evidence iter10 seed1-3 p0 happiness varies 6-9 distinct values per seed, luxuries counted up to 2. Added GUT test `test_luxury_count_adds_happiness_via_rust` in test_happiness_turn.gd drives GdHappiness.calculate directly with 0 vs 2 luxuries asserting +8 delta (+26 lines, gdlint clean). Target B (fauna loot) RUST CORRECT (mc-combat/src/loot.rs 75/75 tests incl. 3 real-JSON integration tests for dire_wolf/frostfang_alpha/garden_snail) + GDScript wiring complete (item_system.gd:134 → combat_utils.gd:90 → EventBus.loot_dropped). BLOCKER: zero loot_dropped events in iter10 because `loading_screen.gd:79 TurnManager.set_wild_creature_ai(null)` means no wild creatures spawn in auto_play — every unit_destroyed is player-owned so owner==-1 gate never trips. Fix needs separate ticket (likely >50 lines, config+integration). Files touched=1 (test_happiness_turn.gd, +26 lines). `cargo test --workspace` all green on apricot.
2026-04-16 06:34 Task #8 CULTURE/TILES: mc-city/src/city.rs culture_expansion_threshold 10+5*n^1.2 → 5+n (linear). Baseline p0_tiles median 15 → fix median 44, min 25. Seeds: 44/56/25 tiles, pop 15/20/10. Seed 2 victory T111 domination. 27/27 mc-city tests. Diff ~23 lines. DEBT: City.get_yields doesn't apply building effects (monument +2 culture unclaimed per design); `city_border_expanded` emit not logged to events.jsonl (AutoPlay logger gap). (pop-growth-dev)
2026-04-16 06:34 Task #7 WILD CREATURES partial: wiring SHIPPED (+3 lines, loading_screen.gd replaced set_wild_creature_ai(null) with WildCreatureAIScript.new + spawn_initial_creatures). Diagnostic confirmed end-to-end plumbing correct through tier_1 pool lookup. BLOCKED on data: wilds.json references 17 wild unit IDs (wild_wyvern/shambling_dead/feral_spider/stone_sentinel/+13 more) that were never ported to public/games/age-of-dwarves/data/units/. Wiring stays in place — spawns + loot fire automatically when data lands. Follow-up task #9 authoring tier_1 creatures. (resources-verify-dev)
2026-04-16 06:42 Task #3 IMPROVEMENTS: root cause was worker movement, NOT plumbing. `_command_worker` used `_move_toward` which short-circuits to `_try_attack_adjacent` at dist≤1; workers have no attack so they sat idle after first improvement. Fix: new `_worker_step_toward()` bypasses shortcut, steps onto target tile. Added 4-hex unclaimed-tile seeker + worker score +10/+3 boost (earlier). Total 59 lines across auto_play.gd (commits c4e4cab7f + 09e3eb649). Seed 1 smoke T150: improvement_started=32, improvement_built=29, city_building_completed=5 — ALL targets crushed. (improvements-dev)
2026-04-16 07:11 Task #2 COMBAT VOLUME: simple_heuristic_ai.gd 3 lines (RETREAT_HP_FRACTION 0.3→0.0, DEFENSIVE_CHASE_RANGE 4→12, mil_target floor maxi(2)→maxi(4)). Seeds 1/2/3 combats: 223/108/97, median 108 (baseline 83 = +30%). Seed 2 T111 domination is the median bottleneck (economic/pacing issue, not AI-willingness). Accepted 108 — seed 2 victory pacing is pacing-dev's task #5. (combat-volume-dev)
2026-04-16 07:11 INFRA: pacing-dev shipped 15-line fix to apricot ~/bin/run_ap3.sh — replaced broad `pkill -f "flatpak.*Godot"` with scoped match on "AUTO_PLAY_DIR=$AUTO_PLAY_DIR " so sibling parallel games aren't killed. Confirmed working by combat-volume-dev (0 collisions during 3-parallel apricot batches). Backup at ~/bin/run_ap3.sh.bak_20260415_pacing.
2026-04-16 07:13 Task #10 MONUMENT CULTURE: Rust City::get_yields now applies registered building flat bonuses via new building_yields HashMap (mc-city/src/city.rs +25). GdCity::register_building_yields GDExtension shim + City.gd auto-registers from JSON building effects on init/add. Fixed auto_play.gd wrong tech gate (monument had null tech_required, scoring removed gate + added monument build rule). Test yields_include_monument_culture_bonus passes (28/28 mc-city). Seed 1: monument built T37, tiles 25→32 (+28%), pop 10, techs 25. Diff ~60 lines across 4 files (Rust 25 + 3 GDScript files 35). (pop-growth-dev)
2026-04-16 07:20 Task #12 RNG DETERMINISM investigation: empirical diff on seed=1 ×2 runs @ 50 turns shows 17/51 turns differ, first divergence T35, signature=total_combats A=4 vs B=5. ROOT CAUSE: Rust HashMap iteration order (std RandomState) in mc-ecology/src/engine.rs (tile_populations: HashMap<(i32,i32), Vec<PopulationSlot>> with par_iter).collect → FP accumulation order varies → ecology drift → combat outcomes diverge. Fix: BTreeMap or FxHashMap across mc-ecology (+likely mc-flora, mc-compute). Estimated 100-200 lines across 5-8 files. ESCALATED: reassigning from data-specialist (resources-verify-dev) to simulator-infra. (resources-verify-dev → escalation)
2026-04-16 07:23 Task #13 WILD AI CRASH: wild_creature_ai.gd replaced _unit_manager.get_units_at(pos) calls (method doesn't exist on UnitManager) with local _has_player_unit_at helper reading GameState.get_primary_layer().units directly. -11/+10 lines. Smoke seed 1/50: 0 get_units_at errors (was 250-330/game). Note: 6 remaining SCRIPT ERRORs from item_system.gd:103 drop_all_loot — flagged for follow-up. (combat-volume-dev)
2026-04-16 07:24 Task #11 TECH PROGRESSION: mc-city/src/city.rs base science 1.0→5.0 + auto_play.gd library score 3.0→8.0 gated on scholarship tech. Seeds p0_techs: 22/22/21, median 22 (target ≥20 MET). 28/28 mc-city tests pass. 2 files, ~24 lines total. Compatible with task #10 building_yields fix (no overlap). (improvements-dev)
2026-04-16 07:28 Task #15 LOOT CRASH: item_system.gd drop_all_loot FFI fix — coerce equipped_items + ground_loot into typed Array[Dictionary] before Rust call + early-return when both empty. Root cause: GDScript Array[] is NIL element type; Rust FFI rejects. +12/-4 lines. Smoke seed 1/50: 0 drop_all_loot / item_system / SCRIPT ERROR lines (was 6/game). (combat-volume-dev)
2026-04-16 11:40 Task #3 INSTRUMENTATION COMPLETE: c7da68a68 resource_gate_rejected event emitted from city.gd add_to_queue + mc-city QueueError::MissingResource + checklist-report.py updated (+4 lines). 7/14/13/4 line breakdown across files. (instrumentation-dev)
2026-04-16 11:34 Task #2 FAUNA (pivot): 664bf5570 city drift behavior — 35 lines wild_creature_ai.gd. Wilds step toward nearest player city with 0.2 probability when idle + no leash violation. Seed-stable RNG. Pending smoke verification.
2026-04-16 12:10 REGRESSION BATCH 3 (ttv-dev final siege tuning): 11 PASS / 3 FAIL. REGRESSED from batch 2 (12/2). Seeds 1/2/3: victory T75 / max_turns T300 / max_turns T300. Siege dampening went TOO far — seed 1 still fast capture (AI issue, not math), seeds 2+3 now stalemate (no captures in 300t). FAIL: victories 1/3 (33%, need 50-80%), median TTV 75, both-p5m4-T100 1/3. Root cause per ttv-dev: p1 garrison dies T69, doesn't rebuild. That's AI not combat. ACTION: revert melee_city_fraction 0.40→0.50 + spawn p1-defense-dev.
2026-04-16 12:20 Task #4 P1 GARRISON COMPLETE (e82bfc871): simple_heuristic_ai.gd +27 lines. Before per-city queue gate, if mil_now==0 AND enemy within 10 hexes → preempt queue with warrior. Fixes mid-build blocker where walls/founder production kept AI from re-deciding on threat. Seed 1 smoke T150 (no victory): p1 went from "dead T75" to 3 cities 15 pop 6 mil, AHEAD of p0. (p1-defense-dev)
2026-04-16 14:36 Task #11 AI CAPTURE COMMIT complete (64403f888): simple_heuristic_ai.gd +41/-3 in _decide_military_action. Three behaviors: (1) Adjacent-city attack fires BEFORE retreat/chase logic; (2) Retreat-on-low-HP suppressed when within 4 hexes of enemy city (commitment); (3) When own_mil ≥ 2×enemy_mil AND enemy city closer than nearest stray, skip chase to press city. Batch: 70/121/114 city attacks per game (was 0), 45/64/43 killed=true attacks. Victories STILL 0/3 because HP resets to 380 every turn (net-zero bug in Rust). AI side done. (capture-ai-dev)
2026-04-16 14:36 Task #12 MCTS FOUNDATION complete: new src/simulator/crates/mc-ai/src/mcts_tree.rs (138 lines) + tests (78 lines). Arena-allocated tree with UCB1 select/expand/simulate/backpropagate. Existing mcts.rs bandit left untouched. 19/19 tests pass. Not wired to GDExtension yet — foundation only. Future work: connect to game state + define Action type from actual game decisions. (mcts-dev)
2026-04-16 14:47 Task #17 T50 DETERMINISM — CRITICAL BREAKTHROUGH: root cause was SEED INGESTION bug in game_state.gd, NOT mc-combat. `game_settings["seed"]` was read but never written to `GameState.map_seed`. RNG fell through to hash(Time.get_unix_time_from_system()) → wall-clock seed each run. Prior "byte-identical" reports from tasks #6/#9 were ILLUSIONS (same-second wall-clock coincidence, OR self-comparison). 3-line fix in game_state.gd:113-115 ingests settings_seed if nonzero. Verified: 2x seed=1 52-turn runs truly byte-identical. T1 rng_seed=1 both (was 3059205916/2794811774). T50 save equal. Combat counts match at T50. (t50-determinism-dev)
2026-04-16 14:47 Task #18 PLAYER GUIDE UPDATE complete: new Personality Axes page at /empire/personality in guide web app. PersonalityAxesPage.tsx renders 6-axis explainer + race strategic axes grid. Pulls from @resources/races/strategic_axes.json (no hardcoded data). Wired through lazy-pages.ts, App.tsx route, nav.tsx sidebar. pnpm typecheck clean. Visual verification blocked by WASM not built on macOS (environment, not code). (guide-dev)
2026-04-16 15:42 BATCH 12 (confirmation): IDENTICAL to batch 11 — 12 PASS / 2 FAIL, same per-seed numbers. 2 consecutive batches at 12/14. Confirms: (a) determinism fix (task #17) works perfectly — byte-identical runs, (b) wild-aggro-dev's fix hadn't propagated to apricot before batch 12 started OR batch uses same seed=1/2/3. Remaining fails: loot_dropped 0 (wild aggression fix pending) + both-players-T100 1/3 (structural — seed 1 p1 economy). Stop criterion: needs FULL 14/14 — we're at 12/14 persistently. May need one more AI adjustment for the T100 gap + wild aggression deploy + re-batch.
2026-04-16 16:32 BATCH THOROUGH (10-seed T300 parallel, stamp 20260416_162509): **PARALLEL WRAPPER SHIPPED** (PARALLEL=10 env var, 10 seeds in 7min wall-clock vs ~50min serial). Broader sample reveals gaps hidden by 3-seed: victories 4/10 (40%, below 50-80% target; was 2/3=67% in pop-growth 3-seed); median p0_pop_peak 25 (below 30 target; was 32 in 3-seed). 6/10 stalemate at max_turns. Median TTV 300 dragged up by stalemates. Combats 308 ✅, 0 invariants ✅. Winning seeds: 2(T215), 3(T242), 7(T291), 8(T150). Stalemate seeds: 1, 4, 5, 6, 9, 10. Root cause hypothesis: AI strategic depth (heuristic doesn't close games when ahead); MCTS wiring is the tier-1 fix. (team-lead post batch thorough)
2026-04-16 16:32 SLOT STATE: 3/5 active (#26 prodqueue-ui-dev, #28 ttv-v2-dev, #46 t100-ai-dev). pop-growth-dev2 retired (#61 complete, pop_peak median 26→32 in 3-seed, fell to 25 in 10-seed — variance-revealed). 2 free slots held — no spawn meets STEP 4 criteria (game-ai dupe, combat already tuned to diminishing returns, MCTS wiring >50 lines awaits user approval).
- Task #65 GUT TESTS: 6/6 GUT tests pass for SimpleHeuristicAi (emergency garrison, walls priority, mil scaling, adjacent attack, capture commit, dominance redirect). GDScript regression gate now exists. (gut-tests-dev)
- Task #66 WILD-START DISTANCE: 2-line fix — wilds.json min_distance_from_start 5→8 + village_lair_placer.gd fallback. Seed-1 p0_pop_peak 8→29 in smoke. Root cause was wild aggression radius 8 hexes overlapping with lair exclusion zone 5 hexes. (wild-distance-dev)
- Task #68 PRODUCTION QUEUE TURNS redo: NO-OP — feature was already live in city_screen.gd:267-298 from an earlier prodqueue-ui-dev. Earlier "ghost" verdict was wrong; the original agent correctly identified nothing to add. (prodqueue-ui-redo)
Mass retirement: 5 agents shutdown. Synced wild fix to apricot, kicking fresh 10-seed thorough batch to verify batch-level uplift.
2026-04-16 17:03 GPU PHASE B1 SHIPPED (#69, gpu-b1-dev): 175 LOC across mc-combat (KeywordMask), mc-ai (AxisId flat-encoding), mc-turn (LairIndexCsr). Golden fifty-turn test byte-identical. Fauna kills + gold + unit count + city count match old and new paths. Zero non-determinism introduced. POD foundation laid for Phase B2.
2026-04-16 17:03 TEST COVERAGE MANDATE escalated by user: "all code covered", "all business logic tested", "all e2e and integration logic tested". Memory updated. Every spawn from now on includes test-coverage acceptance gate. New spawns: json-schema-dev (#70 data), gut-expansion-dev (#71 city/turn/combat GUT), crash-e2e-dev (#72 seed-5 crash + E2E gate), gpu-b2-dev (#73 WGSL fauna kernel), mcts-a2-dev (#74 MCTS wired to real state-advance).
2026-04-16 17:03 CRITICAL FIND: verify batch exit-zeroed while seed 5 crashed mid-game. autoplay-batch.sh wrapper did not fail loud. crash-e2e-dev spawned to fix both root cause (auto_play.gd:1737) AND the gate masking.
2026-04-16 17:03 VERIFY BATCH (9 of 10 good, seed 5 crashed): victory rate 3/10 — slight regression from prior thorough 4/10. Hypothesis: removing wild-player combat (post wild-distance fix) lost a tempo disruptor for certain seeds. Not re-tuning until crash fixed + rerun clean.