diff --git a/.project/objectives/DASHBOARD_CATEGORIES.md b/.project/objectives/DASHBOARD_CATEGORIES.md index 78693461..b439d461 100644 --- a/.project/objectives/DASHBOARD_CATEGORIES.md +++ b/.project/objectives/DASHBOARD_CATEGORIES.md @@ -521,6 +521,19 @@ | [p3-13d](p3-13d-anomalous-events.md) | βœ… done | P3 | Anomalous events β€” aurora, fog_bank, thermal_anomaly | [unassigned](../team-leads/unassigned.md) | 🟒 | | [p3-14](p3-14-game-start-script.md) | βœ… done | P3 | Declarative game-start script + runner β€” data-driven, moddable opening sequence | [shipwright](../team-leads/shipwright.md) | 🟒 | | [p3-15](p3-15-hotseat-multiplayer.md) | βœ… done | P3 | Local hotseat multiplayer β€” multiple humans alternating on one device | [shipwright](../team-leads/shipwright.md) | 🟒 | -| [p3-16](p3-16-ai-proactive-war-declaration.md) | 🟑 partial | P3 | AI proactive war-declaration via the courier system | [warcouncil](../team-leads/warcouncil.md) | πŸ”’ p3-17 | -| [p3-17](p3-17.md) | 🟑 partial | P3 | AI exploration / frontier-seeking for idle military + scout units | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-16](p3-16-ai-proactive-war-declaration.md) | βœ… done | P3 | AI proactive war-declaration via the courier system | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-17](p3-17.md) | βœ… done | P3 | AI exploration / frontier-seeking for idle military + scout units | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-18](p3-18-water-crossing-embark-transport.md) | βœ… done | P3 | Water crossing β€” land-unit embarkation + naval transport | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-19](p3-19-player-ecology-feedback.md) | βœ… done | P3 | Player β†’ ecology feedback β€” harvesting & hunting deplete live populations (over-harvest β†’ extinction) | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-20](p3-20-weather-affects-scouting.md) | βœ… done | P3 | Weather affects scouting β€” vision/LoS penalty under storms, blizzards, dust | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-21](p3-21-weather-driven-migration.md) | βœ… done | P3 | Weather/climate-driven fauna & flora migration | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-22](p3-22-ai-builds-scouts.md) | βœ… done | P3 | AI builds dedicated scout units for exploration | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-23](p3-23-trade-richness-gold-strategic.md) | βœ… done | P3 | Trade richness β€” gold & strategic-resource trades with opponents | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-24](p3-24-rail1-economy-turn-logic-port.md) | 🟑 partial | P3 | Rail-1 β€” port per-turn economy/happiness/climate glue logic from GDScript to Rust | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-25](p3-25-rail1-city-model-unify-headless-view-completeness.md) | 🟑 partial | P3 | Rail-1 β€” unify dual city model so view_json carries territory + trades (GDScript = view only) | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-26](p3-26-complete-headless-simulator.md) | 🟑 partial | P3 | Complete the headless simulator β€” close the live-vs-headless system gaps (loop done-criterion) | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-27](p3-27-biosphere-headless.md) | 🟑 partial | P3 | Biosphere in the headless sim β€” ecology population + flora succession + marine ecology | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-28](p3-28-modular-turn-architecture.md) | 🟑 partial | P3 | Modular turn architecture β€” break dep cycle, phase registry, boot-config DRY | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-29](p3-29-rail1-turn-unification.md) | 🟑 partial | P3 | Rail-1 turn unification β€” live game calls the Rust turn, delete GDScript orchestration | [warcouncil](../team-leads/warcouncil.md) | 🟒 | +| [p3-30](p3-30-wild-creature-ai-rust-port.md) | πŸ”΄ stub | P3 | Port wild-creature AI from GDScript to Rust (Rail-1 compliance) | [warcouncil](../team-leads/warcouncil.md) | 🟒 | diff --git a/.project/objectives/DASHBOARD_COMPLETED.md b/.project/objectives/DASHBOARD_COMPLETED.md index 880ce834..e58ace15 100644 --- a/.project/objectives/DASHBOARD_COMPLETED.md +++ b/.project/objectives/DASHBOARD_COMPLETED.md @@ -311,4 +311,12 @@ | [p3-13d](p3-13d-anomalous-events.md) | Anomalous events β€” aurora, fog_bank, thermal_anomaly | β€” | [unassigned](../team-leads/unassigned.md) | 2026-05-07 | | [p3-14](p3-14-game-start-script.md) | Declarative game-start script + runner β€” data-driven, moddable opening sequence | β€” | [shipwright](../team-leads/shipwright.md) | 2026-06-19 | | [p3-15](p3-15-hotseat-multiplayer.md) | Local hotseat multiplayer β€” multiple humans alternating on one device | β€” | [shipwright](../team-leads/shipwright.md) | 2026-06-19 | +| [p3-16](p3-16-ai-proactive-war-declaration.md) | AI proactive war-declaration via the courier system | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-17](p3-17.md) | AI exploration / frontier-seeking for idle military + scout units | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-18](p3-18-water-crossing-embark-transport.md) | Water crossing β€” land-unit embarkation + naval transport | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-19](p3-19-player-ecology-feedback.md) | Player β†’ ecology feedback β€” harvesting & hunting deplete live populations (over-harvest β†’ extinction) | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-20](p3-20-weather-affects-scouting.md) | Weather affects scouting β€” vision/LoS penalty under storms, blizzards, dust | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-21](p3-21-weather-driven-migration.md) | Weather/climate-driven fauna & flora migration | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-22](p3-22-ai-builds-scouts.md) | AI builds dedicated scout units for exploration | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-25 | +| [p3-23](p3-23-trade-richness-gold-strategic.md) | Trade richness β€” gold & strategic-resource trades with opponents | β€” | [warcouncil](../team-leads/warcouncil.md) | 2026-06-26 | diff --git a/.project/objectives/objectives.json b/.project/objectives/objectives.json index 56663b02..44db0076 100644 --- a/.project/objectives/objectives.json +++ b/.project/objectives/objectives.json @@ -1,13 +1,13 @@ { - "generated_at": "2026-06-24T00:56:30Z", + "generated_at": "2026-06-27T07:50:33Z", "totals": { - "done": 290, + "done": 298, "in_progress": 0, - "partial": 2, - "stub": 0, + "partial": 6, + "stub": 1, "missing": 0, "oos": 31, - "total": 323 + "total": 336 }, "objectives": [ { @@ -1161,7 +1161,7 @@ "scope": "game1", "updated_at": "2026-05-05", "blocked_by": [ - "p1-43a (engine + schema + chain-extension proof landed inline in p1-43)" + "p1-43a" ], "summary": "`p1-43a` (closed inline in `p1-43-building-stacking-upgrade.md` on 2026-05-05)\nshipped the engine + schema layer and **5 representative new high-tier\nbuildings** as a chain-extension proof:\n\n| ID | Tier | Chain |\n|---|---|---|\n| `hydroponic_farm` | 5 | food |\n| `bazaar` | 5 | wealth |\n| `grand_chronicle` | 7 | culture |\n| `gravity_press` | 9 | production |\n| `apothecarium` | 5 | medical |\n\nThis objective (`p1-43b`) covers the **remaining ~35 high-tier buildings**\nneeded to extend each short chain to ~8 tiers, per Q1's locked design." }, @@ -3572,25 +3572,166 @@ "id": "p3-16", "title": "AI proactive war-declaration via the courier system", "priority": "p3", - "status": "partial", + "status": "done", "scope": "game1", "owner": "warcouncil", - "updated_at": "2026-06-24", - "blocked_by": [ - "p3-17" - ], + "updated_at": "2026-06-25", + "blocked_by": [], "summary": "The canonical courier-diplomacy model (`COMMUNICATIONS.md` Β§\"War declaration\nsemantics\") assumes a player **dispatches a war-dec envelope** to enter war: the\n**sender** enters `War` immediately on dispatch and its units can attack the same\nturn; the **recipient** flips to `War` on delivery/interception; **defenders\nalways retaliate when struck** regardless of formal `RelationState`. Pairs start\nat **peace** (`mc-player-api/src/projection.rs::project_tactical_relations` defaults\nunset pairs to 0 = peace; `mc-player-api/src/comms_dispatch.rs` flips the shared\n`RelationState` cell to `War` only on delivery).\n\n**The war-declaration decision is now SHIPPED.** A new per-turn diplomacy step\n`decide_diplomacy` (`src/simulator/crates/mc-ai/src/tactical/diplomacy.rs:30`)\nevaluates each *discovered* rival against the clan's `aggression` axis and the\nown-vs-perceived military balance, and emits `Action::DeclareWar { target }`\n(`diplomacy.rs:69`) when conditions warrant. That action is routed through\n`mc_player_api::comms_dispatch::dispatch_war_declaration`\n(`mc-player-api/src/comms_dispatch.rs:59`) β€” the same envelope path the human\nwar-dec uses β€” so the **sender** enters `War` on dispatch and the **recipient**\nflips on delivery, exactly per `COMMUNICATIONS.md` Β§\"War declaration semantics\".\n\nIt is **unit-tested and proven to fire**:\n- 5 `mc-ai` diplomacy cases (`diplomacy.rs:140–185`) cover discovered-weaker\n (declares), undiscovered (holds), already-at-war (holds), cautious-at-parity\n vs warmonger-strikes (axis differentiation), and no-army (holds).\n- The dispatch round-trip is covered by\n `ai_declare_war_maps_to_player_declare_war` (`mc-player-api/src/dispatch.rs:3068`):\n the AI's `DeclareWar` maps to the same `RelationState` mutation the human path\n produces.\n- **Live proof:** in hotseat self-play (seed 42) war-decs dispatch on first\n contact at turns 17/18.\n\n**Why this is still `partial` β€” the war-dec does not yet transform AI-vs-AI\ngames.** The decision-to-declare half is shipped, but full aggressive AI play is\nblocked on a **separate upstream gap: the AI does not scout/explore** (tracked by\n**p3-17**, AI exploration / frontier-seeking). Two consequences:\n1. War-decs fire only on a fleeting enemy-**unit** sighting, which is rare because\n idle military units never push toward unexplored territory.\n2. Even once at war, `collect_enemy_city_positions` (`tactical/movement.rs:402`)\n returns only **visible** enemy cities β€” which the AIs almost never see, because\n idle military units fall to `score_patrol_for_military` (`movement.rs:285`,\n scout-sweep of already-known cities / garrison next to friendly cities) with\n **no frontier-seeking**. So the army declares war but cannot find the enemy\n capital to march on.\n\nThe downstream at-war combat path (`is_at_war` gate, `locked_target` maneuver,\n`aggression`-tuned posture per `mc-ai/src/tactical/thresholds.rs`) already works\nonce a pair is at war and an enemy city is known β€” but discovery starves it.\n**p3-17 must land before personality `aggression` materially differentiates\nAI-vs-AI war outcomes.**" }, { "id": "p3-17", "title": "AI exploration / frontier-seeking for idle military + scout units", "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-25", + "blocked_by": [], + "summary": "The AI never scouts or explores the map, which starves both target-acquisition\nand the war-declaration discovery gate. This objective adds a frontier-seeking\nmove for idle military / scout units so first contact and enemy-city discovery\nhappen reliably in AI-vs-AI play." + }, + { + "id": "p3-18", + "title": "Water crossing β€” land-unit embarkation + naval transport", + "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-25", + "blocked_by": [], + "summary": "Land armies are permanently confined to their starting landmass: `mc-pathfinding`\ngates water purely by `UnitDomain` (`is_passable(\"ocean\", Land)` is hard-`false`),\nwith no tech override and no way to embark or be ferried. On maps where the two\ncapitals sit on separate landmasses (common β€” the start-balancer maximally\nseparates capitals on the 40Γ—24 `duel` map, often ocean-separated), conquest by a\nland army is impossible. This is the Civ \"embarkation\" tech gap.\n\nThe scaffolding is **half-built** (existing tech debt): `mc_combat::siege::\nembarked_defence_penalty` (halves an embarked unit's defence β€” the Civ-V/VI\nvulnerability rule) and a `transport` keyword in `combat.json` (\"carry up to 2\nland units across water\", on `dwarf_fortress_ship`) both exist, but neither is\nwired into movement/pathfinding, so they are dead." + }, + { + "id": "p3-19", + "title": "Player β†’ ecology feedback β€” harvesting & hunting deplete live populations (over-harvest β†’ extinction)", + "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-25", + "blocked_by": [], + "summary": "The living-world ecology sim (mc-ecology / mc-worldsim) ticks per played turn\n(populations grow/collapse, migrate, emerge β€” see g2-08/g2-10, all done), and the\nplayer can harvest flora (chop, `mc-city::harvest`) and kill fauna (combat /\nlair clearing, `mc-combat::loot`). **But the two are decoupled:** harvesting and\nhunting do NOT reduce the ecology `PopulationSlot::population`\n(`mc-ecology/src/population.rs:9`) β€” fauna products are a read-only yield\n(`fauna_product.rs`), and chopping flips terrain + grants a one-shot yield without\ntouching the live population. Only the sim's own tier dynamics cut populations\n(`evolution.rs:1119 ecological_t5_reduces_fauna_populations`).\n\nNet: **you cannot over-harvest or over-hunt a species toward local extinction**,\nand abundance doesn't respond to player pressure β€” which undercuts the\n\"living-world is the Game-1 USP\" promise (the world should react to the player)." + }, + { + "id": "p3-20", + "title": "Weather affects scouting β€” vision/LoS penalty under storms, blizzards, dust", + "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-25", + "blocked_by": [], + "summary": "The runtime weather system (`mc-climate::weather`, six Game-1 types: Storm, Heat\nWave, Blizzard, Drought, Flood, Dust Storm) derives events per turn and applies a\n`movement_penalty` to units, with real unit HP damage wired into the played turn\n(`climate_effects.gd:125`). **But `WeatherEvent` carries no vision/line-of-sight\neffect** β€” weather slows movement and hurts units, but does not reduce scouting\nrange. So storms/blizzards/dust have no effect on exploration, fog reveal, or\nsurprise β€” a missed gameplay lever for the weather system." + }, + { + "id": "p3-21", + "title": "Weather/climate-driven fauna & flora migration", + "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-25", + "blocked_by": [], + "summary": "Fauna/flora migration EXISTS and ticks per played turn\n(`mc-ecology/src/biological.rs:59 MigrationPulse`, `engine.rs` per-turn migration;\ng2-10 done), but it is **population-pressure / carrying-capacity driven only** β€”\nit does not respond to **weather/climate**. Drought should push herds toward\nwater, blizzards/heat-waves should thin or relocate populations, blooms (already\nclimate-linked) should pull flora spread. Today the living world migrates by\ncrowding, not by climate β€” a partial realization of the weather↔ecology coupling." + }, + { + "id": "p3-22", + "title": "AI builds dedicated scout units for exploration", + "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-25", + "blocked_by": [], + "summary": "The AI explores via frontier-seek with idle military units\n(`mc-ai/src/tactical/movement.rs:892`) and gives scout-typed units a special\nenemy-city patrol sweep β€” but it **never builds `dwarf_scout`**: the production\nladder (`mc-ai/src/tactical/production.rs:387`) queues founders, military, and\nbuildings, with workers as fallback, and no scout branch. Early-game discovery /\nfirst-contact therefore relies on diverting combat units, which is slower and\nweaker than a cheap dedicated scout." + }, + { + "id": "p3-23", + "title": "Trade richness β€” gold & strategic-resource trades with opponents", + "priority": "p3", + "status": "done", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-26", + "blocked_by": [], + "summary": "> **DISCOVERY (2026-06-25, verify-first):** the original premise was wrong. The\n> inter-player trade turn-integration is **DISABLED in the played game**, not\n> \"luxury-only\". `turn_manager.gd:287` has `Diplomacy.process_turn()` commented out\n> with a stale \"empty stub module\" note (diplomacy.gd was rebuilt but never\n> re-enabled). The *only* writer of `GameState.trade_ledger_json` is diplomacy.gd:32\n> inside that disabled call, so **no inter-player trades run at all** (luxury, strategic,\n> or gold). Worse, the `diplomacy.gd ↔ GdTrade.process_trades` contract has drifted\n> in 3 places: (1) `_serialize_players` emits `{index, traded_luxuries, personality}`\n> but `process_trades` deserializes `Vec` (`player_index`,\n> `tile_luxuries`, `tile_strategics`, `trade_willingness`); (2) `process_trades`\n> returns `{ledger}` but diplomacy.gd reads `result[\"trade_ledger_json\"]`,\n> `[\"relation_changes\"]`, `[\"new_trades\"]`, `[\"broken_trades\"]`; (3) relations\n> advancement isn't returned. So enabling is NOT a one-line uncomment.\n\nThe **simulation logic is complete + cargo-tested** (luxury/strategic swaps + gold\nsales in `mc-trade`, 66/0) and the gold-flow application is wired (part A) β€” but it\nis all **inert in-game until the diplomacy turn-integration is revived**. The\n`tribute.rs` path stays Game-2 deferred." + }, + { + "id": "p3-24", + "title": "Rail-1 β€” port per-turn economy/happiness/climate glue logic from GDScript to Rust", + "priority": "p3", "status": "partial", "scope": "game1", "owner": "warcouncil", - "updated_at": "2026-06-24", + "updated_at": "2026-06-25", "blocked_by": [], - "summary": "The AI never scouts or explores the map, which starves both target-acquisition\nand the war-declaration discovery gate. This objective adds a frontier-seeking\nmove for idle military / scout units so first contact and enemy-city discovery\nhappen reliably in AI-vs-AI play." + "summary": "The core economy/happiness/event MATH is in Rust (mc-economy, mc-happiness,\nmc-city, mc-climate, mc-trade) β€” good Rail-1 health. **But real per-turn game\nlogic still lives in GDScript**, violating \"GDScript is presentation only\":\n\n- `economy.gd:66-72` computes gold *in GDScript* (building-gold sum, gold-per-pop,\n gold-from-mines) before/around the `GdEconomy` call β€” not a thin wrapper.\n- `happiness.gd` assembles + partially computes the happiness inputs (luxury map,\n building-effect collection) in GDScript.\n- `climate_effects.gd:125` mutates game state in GDScript (`unit.hp -= hp_loss`).\n- `turn_processor.gd` / `turn_manager.gd` own the per-turn ORCHESTRATION (sequence\n the Rust crates, dispatch events, apply results) in GDScript.\n\nThis is the same class of debt as the AI port (p0-26, done) β€” but for the\neconomy/happiness/event/turn surface." + }, + { + "id": "p3-25", + "title": "Rail-1 β€” unify dual city model so view_json carries territory + trades (GDScript = view only)", + "priority": "p3", + "status": "partial", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-26", + "blocked_by": [], + "summary": "> **Owner directive (2026-06-26):** \"gd should only be UI view of simulation\" +\n> \"simulator should provide everything\" + \"no stubs β€” prod code only\". A player-like\n> the headless adapter (or any UI) must get the *full* game state from the simulator's\n> projected view (`GdPlayerApi.view_json` β†’ `PlayerView`), not by GDScript re-deriving\n> simulation facts.\n\n**Root cause (verify-first investigation).** The simulator holds **two parallel city\nmodels** ([api-gdext/src/city_slot.rs:3-6](../../src/simulator/api-gdext/src/city_slot.rs)):\n\n- `GdGameState.presentation_cities: Vec>` β€” the **authoritative**\n rich model: `owned_tiles`, `worked_tiles`, `position`, `culture_stored`, buildings\n ([mc-city/src/city.rs](../../src/simulator/crates/mc-city/src/city.rs)).\n- `GameState.players[pi].cities: Vec` β€” a **bench** model with NO\n territory ([mc-city/src/lib.rs:126](../../src/simulator/crates/mc-city/src/lib.rs)),\n explicitly *\"left untouched\"*. City position lives in the parallel\n `PlayerState.city_positions`.\n\n`project_view` ([mc-player-api/src/projection.rs](../../src/simulator/crates/mc-player-api/src/projection.rs))\nreads the **bench** model, so `view_json` is structurally blind to territory β€” and thus\nto worked tiles and to inter-player trades (which need owned-tile resource sourcing).\n`GdPlayerApi` (the headless harness) holds only `GameState` β€” no `presentation_cities` β€”\nso the fix for the headless path is to give the bench state real territory, not to reach\ninto the rich `City`.\n\nConsequences observed: `CityView.owned_tiles` and `DiplomacyView.{open_borders,\nshared_map,agreements_active}` were hardcoded stubs in the projection; there are no\ntrade-deal fields on `DiplomacyView` at all; `mc-turn::process_trade_phase` sources trade\ninputs from bench proxies (`tile_strategics: Vec::new()`, `tile_luxuries` proxy) and does\nnot persist its computed ledger to `state.trade_ledger`. The live game's working trade\npath (p3-23) is GDScript-orchestrated and parses `trade_ledger_json` itself β€” a\npresentation-layer workaround that this objective supersedes for the headless/sim path.\n\nThe data needed *does* exist in Rust: `GridState.tile(col,row)β†’{biome,quality}` +\n`mc_core::collectibles::tile_collectibles(biome,quality,rng)` resolve a tile's resources\ndeterministically. What's missing is (a) owned-tile territory in the bench state, (b) a\nresource-category catalog (luxury/strategic) in Rust, (c) persistence of swap/sale deals\nto `state.trade_ledger`, (d) projecting it all." + }, + { + "id": "p3-26", + "title": "Complete the headless simulator β€” close the live-vs-headless system gaps (loop done-criterion)", + "priority": "p3", + "status": "partial", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-26", + "blocked_by": [], + "summary": "> **Owner directive (2026-06-26):** the /loop \"continue until Game-1 done\" is **not\n> finished until the SIMULATOR is complete** β€” the headless Rust sim\n> (`mc-turn::TurnProcessor`, driven via `GdPlayerApi`/`magic_civ_*`) must play a full\n> self-play game with ALL systems, not the reduced subset shipped so far. See\n> [[project_loop_done_means_simulator_complete]].\n\nThe headless `step()` ([processor.rs:392+](../../src/simulator/crates/mc-turn/src/processor.rs))\ncurrently runs: trade (p3-25), economy, city_production (single queue), culture+border\nexpansion, tech/science, fauna encounters, combat/siege, diplomacy. Verified live via\n`magic_civ_view` (e.g. border expansion fired turn 0β†’1: `owned_tiles [[1,6]]β†’[[1,6],[0,6]]`).\n\n**Gaps (each verified absent from the headless turn):**" + }, + { + "id": "p3-27", + "title": "Biosphere in the headless sim β€” ecology population + flora succession + marine ecology", + "priority": "p3", + "status": "partial", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-26", + "blocked_by": [], + "summary": "Split from [[p3-26-complete-headless-simulator]]. The biological simulators exist as full\nRust crates β€” `mc-ecology` (`EcologyEngine`: per-tile fauna populations, predator/prey,\nevolution) and `mc-flora` (`FloraEngine`: per-tile vegetation + succession) β€” and the LIVE\ngame ticks them every turn (`EcologyState.tick` + `take_flora_transitions`,\nturn_manager.gd:315). But the **headless `mc-turn` step does NOT tick them** (verified: `0\nhits` for EcologyEngine/FloraEngine/flora in `processor.rs`). Only fauna *encounters*\n(combat) run headless. So the headless sim has no living biosphere for events/economy to\ninteract with." + }, + { + "id": "p3-28", + "title": "Modular turn architecture β€” break dep cycle, phase registry, boot-config DRY", + "priority": "p3", + "status": "partial", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-26", + "blocked_by": [], + "summary": "The per-subsystem sprawl noticed while porting climate/events/happiness/healing/ecology\nrevealed three SOLID/DRY/DIP debts. \"Foundation first\" tackled the layering + phase pieces." + }, + { + "id": "p3-29", + "title": "Rail-1 turn unification β€” live game calls the Rust turn, delete GDScript orchestration", + "priority": "p3", + "status": "partial", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-27", + "blocked_by": [], + "summary": "**The DRY / Rail-1 violation (verified 2026-06-27).** There are TWO turn orchestrations:\n- LIVE: `turn_manager.gd` β†’ `turn_processor.gd::_process_*` (GDScript) + `EcologyState.tick` +\n `WorldsimState` β€” GDScript orchestrating the turn.\n- HEADLESS: `GdPlayerApi` β†’ `mc_turn::TurnProcessor::step` (Rust).\n\nThe system *math* lives once in the Rust crates (DRY). The turn *orchestration* is duplicated β€”\nand the p3-26/p3-27 work this session added happiness/healing/improvements/recipes/equipment/\necology to `mc-turn` while the live game still runs its GDScript copies (e.g. `EcologyState.tick`\nduplicates the new Rust `ecology_phase`). This session BUILT `mc-turn::step` into the complete\nsingle source of truth; this objective is the capstone that makes it actually single.\n\nThe bridge already exists: `GdTurnProcessor::step(GdGameState)` (api-gdext/src/lib.rs:6354) runs\n`mc_turn::TurnProcessor::step` on the LIVE game's state. The live turn just doesn't call it." + }, + { + "id": "p3-30", + "title": "Port wild-creature AI from GDScript to Rust (Rail-1 compliance)", + "priority": "p3", + "status": "stub", + "scope": "game1", + "owner": "warcouncil", + "updated_at": "2026-06-27", + "blocked_by": [], + "summary": "**Rail-1 gap surfaced during the p3-29 logic sweep (2026-06-27).** The live turn runs\nwild-creature AI **decision logic in GDScript**: `turn_processor.gd::_process_wild_creatures`\n(line 459) calls `wild_ai.process_wild_turn(game_map)` β†’\n`src/game/engine/src/modules/ai/wild_creature_ai.gd` (302 LOC β€” a guard / attack / roam state\nmachine over `owner == -1` units).\n\nThis is sim logic, not presentation, so it violates Rail-1 (\"GDScript is presentation only\";\n\"AI decision-making lives in Rust\"). It is **distinct from [[p0-26-ai-tactical-rust-port]]**,\nwhich ported *player* tactical AI (`simple_heuristic_ai.gd` / `ai_tactical.gd` / `ai_military.gd`)\nand explicitly did not touch wild-creature behaviour. It is also distinct from the fauna\n*population/rendering/stats* objectives (`g2-08`, `p3-12`, `p1-49`, `p2-58a`) β€” those model\necology; this is the per-creature **combat behaviour AI**.\n\nThe combat *resolution* for wilds already lives in Rust (`mc-combat::wilds`); only the\n*decision* layer (who to attack, when to roam, leash enforcement) is still GDScript." } ], "blocked": [ @@ -3615,7 +3756,7 @@ { "id": "p1-43b", "blockedBy": [ - "p1-43a (engine + schema + chain-extension proof landed inline in p1-43)" + "p1-43a" ] }, { @@ -3835,18 +3976,12 @@ "blockedBy": [ "p0-36" ] - }, - { - "id": "p3-16", - "blockedBy": [ - "p3-17" - ] } ], "remaining_by_lead": [ { "owner": "warcouncil", - "remaining": 2 + "remaining": 7 } ] } diff --git a/.project/objectives/p3-27-biosphere-headless.md b/.project/objectives/p3-27-biosphere-headless.md index 79bae90b..921389bc 100644 --- a/.project/objectives/p3-27-biosphere-headless.md +++ b/.project/objectives/p3-27-biosphere-headless.md @@ -4,7 +4,7 @@ title: Biosphere in the headless sim β€” ecology population + flora succession + priority: p3 scope: game1 owner: warcouncil -status: open +status: partial updated_at: 2026-06-26 --- diff --git a/.project/objectives/p3-30-wild-creature-ai-rust-port.md b/.project/objectives/p3-30-wild-creature-ai-rust-port.md index be8fce4c..992d5a11 100644 --- a/.project/objectives/p3-30-wild-creature-ai-rust-port.md +++ b/.project/objectives/p3-30-wild-creature-ai-rust-port.md @@ -2,7 +2,7 @@ id: p3-30 title: Port wild-creature AI from GDScript to Rust (Rail-1 compliance) priority: p3 -status: open +status: stub scope: game1 owner: warcouncil updated_at: 2026-06-27