docs(p2-65): 📊 Phases 1/3a/3b landed — status stub→partial, Phase-4 resume note

mc-state crate created + GameState moved into it (green @ 0ed21945c). Records the
3 green-between commits (0bace0e6c / 45e9adea9 / 0ed21945c), the save-format +
parity evidence, the honest ~5/9 acceptance recount (bullet 6 still 20+ shim
leaks → status stays partial, NOT done), and the precise Phase-4 path: sweep
all mc_turn::game_state/GameState sites (external + mc-turn internals + the
lib.rs:62 re-export) to mc_state::, delete both shims, with the dev-dep rule for
mc-core/derived_stats (the one upstream-of-mc-state consumer). FINISH_GAME1_PLAN
Wave-D row 1 updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
autocommit 2026-06-04 19:20:40 -07:00
parent f05231b825
commit 180c521977
2 changed files with 66 additions and 2 deletions

View file

@ -47,7 +47,7 @@ Built logic that's dead-ended on a missing thin wrapper, plus cheap unblocks.
Rail-1 hygiene: make the existing UI read game state from Rust. **Game renders fine via GDScript today — this is post-demo correctness, but required for "complete."** Chain order:
| Order | Objective | Detail |
|---|---|---|
| 1 | p2-65 | Extract `GameState`+pending-queue → `mc-state` crate (Phase 0c groundwork done; Phase 1+3 per its resume note — relocate 6 mc-turn data types, then move game_state.rs behind a `pub use` shim; save round-trip is the gate). |
| 1 | p2-65 | 🟡 **partial (~5/9, green @ `6de3c67a8`)**`mc-state` crate created + `GameState` moved into it behind `pub use` shims (Phases 1/3a/3b landed 2026-06-04; save-format round-trip byte-identical + parity trio green). **Remaining:** Phase 4 (sweep 20+ `mc_turn::game_state` consumer sites + mc-turn internals + the `lib.rs:62` re-export to `mc_state::`, delete shims — bullet 6 must hit zero hits), Phase 5 (Cargo downgrades), Phase 7 (p2-55f `SimConfig`). See p2-65 resume note. |
| 2 | p2-72a-building-entity-port | Rust surface done (5/11); remove the parallel `npc_buildings` array + spatial index from `game_state.gd`, route 6 readers through `GdGameState`. |
| 3 | **p2-72a** (canonical render source) | The **58 day milestone**: convert PlayerScript/UnitScript/GameMap fat classes → thin views over `GdGameState`. |
| 4 | p2-72b — **Path 2** | `Vec<Vec<mc_city::City>>` on `GdGameState` (operator-chosen; blocker cleared). |

View file

@ -2,7 +2,7 @@
id: p2-65
title: "Extract `GameState` and pending-queue data types into a dedicated `mc-state` crate"
priority: p2
status: stub
status: partial
scope: game1
category: architecture
owner: simulator-infra
@ -469,3 +469,67 @@ with `GameState` in mc-turn; nothing user-visible changes. Zero demo dependency.
**Effort:** L — 2+ focused sessions (Phase 3a is the long pole: 6 sibling-type
relocations, each with audit + green commit, then the mechanical game_state move +
30-site consumer sweep).
## 2026-06-04 Wave-D session — Phases 1 / 3a / 3b LANDED (status stub → partial, K≈5/9)
**Green SHA to resume from: `6de3c67a8`** (workspace `--no-run` clean; save-format gate +
parity trio all green — evidence below). The `mc-state` crate now EXISTS and `GameState` lives
in it. Acceptance recount: ~5/9 met — crate exists (✓), data-only modules moved (✓ ransom,
capture, combat_event, patrol, game_state), ScoringWeights cycle resolved (✓ via Phase-0c
`mc_core::tactical_types` + `mc_core::ScoringWeights`), save-format round-trip byte-identical
(✓ proven). **NOT yet done (status stays `partial`, NOT `done`):** bullet 6 (`grep
"mc_turn::game_state\|mc_turn::GameState"` must return ZERO — currently 20+ external hits + the
mc-turn internals + the `lib.rs:62` re-export), bullet 5 (consumer Cargo.toml downgrades),
bullet 4 (mc-turn becomes logic-only — still carries `mc-ai` dep + the shims), bullet 9 (p2-55f
`SimConfig` wiring). The shims are deliberate and green; mid-sweep is the WORST resume point, so
this session banked the clean fully-shimmed boundary.
### What landed (commits, in order — each green-between)
| Phase | Commit | What |
|---|---|---|
| 1 + 3a-ransom | `380619f89` | New `mc-state` crate (workspace member; data-shape deps only, NO mc-ai/mc-turn/rayon/GPU — verified no cycle: mc-state deliberately omits mc-vision, which deps mc-turn). `RansomOffer`/`RansomQueue` (+mechanics) → `mc_state::ransom`; mc-turn `ransom.rs` = `pub use` shim. |
| 3a-rest | `9745f59e3` | `CapturePosture`+`Default`+`TryFrom<_> for PostureResolution`+`PromptUnresolved``mc_state::capture` (the `TryFrom` MUST move with the enum — orphan-rule). 6 capture/PvP event structs → `mc_state::combat_event`. `PatrolOrder`+`PatrolMode`+pure self-methods → `mc_state::patrol`. mc-turn keeps `resolve_posture`, `issue/cancel/edit/PatrolError/validate_waypoints/advance_on_turn` (now FREE FNS — 3 call sites in action_handlers/mod.rs updated `PatrolOrder::``patrol::`), `TurnResult`+Fauna/Pvp/Siege events. |
| 3b | `6de3c67a8` | `git mv game_state.rs → mc-state`; mc-turn `game_state.rs` = `pub use mc_state::game_state::*;` shim. Re-paths: `crate::combat_balance::CombatBalance``mc_core::CombatBalance` (only non-sibling code ref); broken `[crate::…]` doc-links demoted. `PendingCaptureEvents::drain_into` peeled into mc-turn-local `DrainCaptureEvents` trait (`capture_drain.rs`) — it embeds `mc_replay::TurnEvent`+`TurnResult`, un-movable without a cycle; 4 call sites add the trait `use`. |
### Evidence (apricot, this box = the RUN host; `cargo` runs directly in CWD)
- `cargo test --workspace --no-run` exit 0 at `6de3c67a8`.
- **Save-format gate (byte-identical proof):** `mc-turn` `serde_roundtrip` 6/6, `full_turn_golden` 3/3.
- **Parity trio:** `mc-turn` lib 234/234 (1 ignored, pre-existing `five_players_overflow`; was 238
pre-move — the 4 game_state unit tests moved WITH the file); `mc-ai` 268/268; `mc-player-api` 126/126.
- `mc-state` lib 12/12 (ransom 2 + capture 2 + combat_event 1 + patrol 3 + the 4 moved game_state tests).
### Phase 4 path (the next session — start here; the load-bearing rule)
**Phase 4 (bullet 6) — retarget ALL `mc_turn::game_state`/`mc_turn::GameState` sites to `mc_state::`,
then DELETE both shims.** This is bigger than the 20-file external grep — completeness requires THREE
surfaces, all driven to zero:
1. **External consumers (20+ files):** mc-player-api (src+tests), mc-sim, api-gdext, mc-core/derived_stats,
mc-save, mc-vision, tests/integration. Sweep `use mc_turn::game_state``use mc_state::game_state`
and `mc_turn::{GameState,…}``mc_state::game_state::{…}`.
2. **mc-turn internals:** `crate::game_state::…` across processor.rs / action_handlers/ — keep as
`crate::game_state` ONLY if the shim stays; to delete the shim, retarget these to `mc_state::game_state`.
3. **The `mc-turn/lib.rs:62` re-export** `pub use game_state::{GameState,…}` — this is what PRODUCES
`mc_turn::GameState` (bullet 6 also drives THAT to zero). Delete it (or re-point consumers).
Then delete `mc-turn/src/game_state.rs` (shim).
**THE DEV-DEP RULE (advisor-pinned, prevents the only cycle trap):** any crate that mc-state
*depends on* (mc-core, mc-units, mc-city, mc-combat, mc-trade, mc-tech, mc-culture, mc-civics,
mc-comms, mc-replay, mc-observation) CANNOT take a normal mc-state dep. From the 20, only
`mc-core/src/derived_stats.rs` is in that set, and its `mc_turn::game_state` use is **test-only**
(a normal mc-core→mc-turn dep is already impossible — Cargo rejects it — so it's a dev-dep today).
In Phase 4 it becomes a `[dev-dependencies] mc-state` entry (dev-dep cycles are legal). Everything
DOWNSTREAM of mc-state (incl. mc-vision — mc-state does NOT dep it) gets a normal dep.
**Phase 5 (bullet 5):** `cargo tree -p <crate>` each consumer; where its only `mc-turn` use was state
shape, drop `mc-turn` from its Cargo.toml. **Phase 4-bonus (bullet 4):** once internals are off
`crate::game_state`, check whether mc-turn still needs its `mc-ai` dep (Phase-0c left it; may now be
removable). **Phase 7 (bullet 9):** `mc_state::SimConfig` carrying `combat_balance`, wired once at
api-gdext registration → `GdGameState::init` populates `self.inner.combat_balance` (closes p2-55f bullet 2).
**Gate each phase:** `cargo test --workspace --no-run` + `serde_roundtrip` + `full_turn_golden` +
the mc-turn/mc-ai/mc-player-api parity trio. Do NOT split `game_state.rs` (>500 lines) — out of scope,
flagged debt. Pre-existing unrelated failure `mc-turn::abstract_projection::
five_players_overflow_truncates_to_max_players` (MAX_PLAYERS 4→12 staleness) fails on HEAD, touches
none of the moved types — NOT a regression.