feat(@projects/@magic-civilization): add u8 field parsing fixes for player state

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-04-18 07:51:01 -07:00
parent 2f48101a01
commit 5858a0180b

View file

@ -144,6 +144,38 @@ Same CLASS of bug as Round 2 (WeatherEvent i32 fields) but for u8 fields in mc-t
**Predicted outcome**: E2E gate passes. Games run full length with both players active. Other u8 fields (PlayerSnap.wealth/expansion_axis/production_axis, McSnapshot.victory_city_count, combat_event structs) may still need annotation — but `choose_action_with_stats` only parses `GameState` directly, so the PlayerState fix should be sufficient for that specific call path.
**RESULT (batch bdncm5x7y, in-flight mid-batch snapshot)**:
| Seed | Outcome | Turn | p1 cities |
|---|---|---|---|
| 1 | victory | 98 | 0 |
| 2 | in_progress | 125 | 3 |
| 3 | in_progress | 211 | 2 |
| 4 | victory | 73 | 1 |
| 5 | victory | 223 | 1 |
| 6 | victory | 160 | 0 |
| 7 | in_progress | 121 | 1 |
| 8 | victory | 39 | 3 |
| 9 | in_progress | 140 | 3 |
| 10 | victory | 189 | 1 |
**8/10 games with p1 holding ≥1 city.** Turn range T39T223+. Mixed victory/in_progress. Matches pre-port baseline shape. The P1-inert regression is RESOLVED.
---
## Summary — what fixed the regression
Two bugs in the same class (data-driven founder-recognition), in two files:
1. **`settle.rs::is_settler`** (Round 3): only matched `"settler" | "founder"` kind-strings. Fixed by adding `can_found_city: bool` to `TacticalUnit` and checking that flag first.
2. **`movement.rs::unit_role`** (Round 6): same kind-string match issue, routed `dwarf_tribe` settlers through Military branch → conflicting MoveUnit + FoundCity dispatches. Fixed by the same `can_found_city` short-circuit.
Plus an adjacent serde issue that blocked strategic-layer MCTS parsing:
3. **mc-core gd_compat for u8 / BTreeMap<String, u8>** (Round 7): GDScript's JSON.stringify emits all numbers as floats, serde rejected them for `PlayerState::player_index: u8` and `PlayerState::strategic_axes: BTreeMap<String, u8>`. Fixed by shared `mc_core::gd_compat` helpers on those fields.
**Meta-learning**: the "inert" symptom category was key — once I stopped treating it as a decision-logic bug and instrumented to see the actual action trace, the conflict between movement/settle modules was obvious in ~4 minutes of instrumented run.
---
## Key meta-lessons from this debug