From a0ace92c23b9ba88ab226d44b745ce94ba8728a1 Mon Sep 17 00:00:00 2001 From: Natalie Date: Sat, 27 Jun 2026 06:20:13 -0400 Subject: [PATCH] =?UTF-8?q?docs(@projects/@magic-civilization):=20?= =?UTF-8?q?=E2=9C=85=20p3-29=20=E2=80=94=20T2/T3=20done;=20correct=20T5=20?= =?UTF-8?q?scope=20+=20T6=20keystone=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §A event emission now DONE except ItemProduced (T4, blocked on D1): - T2 UnitHealed (158ef4d1b), T3 GoldenAgeStarted/Ended (a87ea9f4d). Corrected T5: the buffer pattern alone is insufficient — EcologyEngine:: process_step returns only flora transitions; fauna births/deaths + biome changes are unreported by the headless engine (live signals come from fauna.gd). T5 needs a new mc-ecology report surface + an owner ruling on creature-event granularity. Also marked T6 keystone DONE (was pre-landing). Co-Authored-By: Claude Opus 4.8 --- .../p3-29-rail1-turn-unification.md | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/.project/objectives/p3-29-rail1-turn-unification.md b/.project/objectives/p3-29-rail1-turn-unification.md index bc460839..c8708826 100644 --- a/.project/objectives/p3-29-rail1-turn-unification.md +++ b/.project/objectives/p3-29-rail1-turn-unification.md @@ -203,8 +203,8 @@ the objective captures **everything**. UI/input/camera/overlay/selection signals | `unit_created` | `_process_research` | `UnitCreated` | ✅ exists | processor.rs:1984 | | `tech_researched` | `_process_research` | `TechResearched` | ✅ exists | processor.rs:1329 | | `culture_researched` | `_process_culture_research` | **`CultureResearched`** | ✅ DONE (T1, 3e89c411a) — `TurnEvent::CultureResearched` emitted at completion site; dispatch translates to wire (wire.rs:293); `event_to_dict` arm | processor.rs:1284 | -| `golden_age_started` | `_process_growth` | **`GoldenAgeStarted`** (new) | ❌ MISSING — golden-age computed in `happiness_phase` (`process_golden_age`), emits nothing | happiness_phase.rs:35 | -| `unit_healed` | `_process_healing` | **`UnitHealed`** (new) | ❌ MISSING — `healing.rs` emits no event | healing.rs | +| `golden_age_started`/`_ended` | `_process_growth` | **`GoldenAgeStarted`/`GoldenAgeEnded`** | ✅ DONE (T3, 34ab497e1) — both edges buffered in `happiness_phase` (`pending_golden_age_events`), drained in `step()` | happiness_phase.rs | +| `unit_healed` | `_process_healing` | **`UnitHealed`** | ✅ DONE (T2, f98b1fd01) — buffered in `healing.rs` (`pending_heal_events`, clamped applied amount), drained in `step()` | healing.rs | | `item_produced` | `_process_production` | **`ItemProduced`** (new; or fold into building) | ❌ MISSING — designer call: distinct from `CityBuildingCompleted`? | — | | `strategic_gate_rejected` | `_process_production` | `TurnResult.strategic_gate_rejected` field | ⚠️ field EXISTS but NOT in `turn_result_to_dict` (AI advisory; decide surface vs keep-GDScript) | combat_event.rs:28 | @@ -236,7 +236,8 @@ them — flag so it is not a surprise at render-proof: ### Net remaining for "make the Rust turn the single source" (this objective) 1. **New `TurnEvent` variants + emission:** ~~`CultureResearched`~~ ✅ (T1, 3e89c411a), - `GoldenAgeStarted`, `UnitHealed`, `ItemProduced` (§A) — walking §A in order. + ~~`GoldenAgeStarted`/`Ended`~~ ✅ (T3, 34ab497e1), ~~`UnitHealed`~~ ✅ (T2, f98b1fd01), + `ItemProduced` (§A, **blocked on D1**) — §A event emission DONE except ItemProduced. 2. **Flora/ecology surface (§C):** stop discarding `_transitions` (ecology_phase.rs:76); add `flora_transitions` (+ creature/biome) to `TurnResult`. Tied to the registry-events refactor the Step-1 note defers — track it here so it is not lost. @@ -291,15 +292,17 @@ real remaining steps 1-2 (Rust + headless only, live game untouched, no render-p - **T4 — `ItemProduced`** (pending D1). If distinct: {turn, clan, city, item_id, hex}, emit in `process_city_production` alongside `CityBuildingCompleted`. - **T5 — §C creature/biome:** `CreatureBorn` / `CreatureDied` / `BiomeChanged` from the ecology - tick. **Reuse the `GameState.pending_flora_events` buffer pattern** introduced for - `FloraSuccession` (7b6d24bde) — buffer in the phase, drain in `step()` — to dodge the registry - signature cascade. DoD: wiring test sees them in a multi-turn ecology run. -- **T6 — §B KEYSTONE (do this regardless of T1-T5 progress):** add a generic `events: Array` - to `turn_result_to_dict` (api-gdext/src/lib.rs:6562) by looping `result.events_emitted` through - `event_to_dict` (replay.rs — check/raise its visibility to `pub(crate)`/shared). This is what - makes ANY §A event reach the live game; currently none do. Keep the existing typed surfaces - (ambient/captured/ransom) for back-comat. DoD: a GDScript-side read (headless `view`/dict dump) - shows `events` populated with `kind`-tagged entries after a turn that grows a city. + tick. **CORRECTION (verified 2026-06-27):** the buffer pattern alone does NOT suffice — + `EcologyEngine::process_step` (engine.rs:341) returns only `Vec`; it does NOT + report fauna births/deaths or biome-label changes. The live `creature_born`/`creature_died` + signals come from GDScript `fauna.gd:184/209` (a separate path), and biome changes are unreported + by the headless engine. So T5 first needs a new **report surface in `mc-ecology`** (e.g. + `process_step` returns population/biome deltas, or a sibling reporter) — and a **design call** on + granularity (per-tile population delta? species-emergence threshold? new-species-on-tile only?). + Bigger than T1-T3; **needs an owner ruling on creature-event semantics before coding.** +- **T6 — §B KEYSTONE:** ✅ **DONE** (e165b4e6c, lib.rs:6573) — generic `events: Array` in + `turn_result_to_dict` loops `events_emitted` through `event_to_dict`; every §A event reaches the + live game as a kind-tagged dict. (The "do regardless / none reach the game" framing was pre-landing.) ### Swap-phase carve-out to track (steps 3-5, not now)