docs(@projects/@magic-civilization): p3-29 — T2/T3 done; correct T5 scope + T6 keystone status

§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 <noreply@anthropic.com>
This commit is contained in:
Natalie 2026-06-27 06:20:13 -04:00
parent a87ea9f4d4
commit a0ace92c23

View file

@ -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<FloraTransition>`; 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)