docs(p2-65): 📝 record Phase-3 cascade verdict + resume note for next session

game_state.rs references 6 mc-turn sibling DATA types in field decls (not
turn-logic calls): RansomQueue, 6 combat_event structs + TurnResult,
CapturePosture, PatrolOrder, CombatBalance (already mc-core). Phase 3 is a
2-step — relocate these to mc-core first (Phase 0c pattern), then move
game_state.rs to mc-state behind a pub-use shim. Save-format round-trip is the
gate. p2-72 gated on full p2-65, 2+ sessions out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
autocommit 2026-06-04 12:16:56 -07:00
parent eaec14406d
commit 3821b297bf

View file

@ -283,6 +283,54 @@ unchanged thanks to the re-export shims).
touches none of the moved types; fails on HEAD; AI-owner decision pending) is
NOT a regression.
## Resume note (next session — start here)
**State:** Phase 0a/0b/0c all done; mc-state crate does NOT exist yet. Workspace
green at the Phase-0c commit. Next chunk = **Phase 1 + Phase 3 as ONE unit**
(Phase 1 skeleton alone is worthless; Phase 2 combat_balance is moot — already
in mc-core).
**Phase-3 cascade verdict (grepped 2026-06-04 — the load-bearing fact):**
`game_state.rs` references **6 mc-turn sibling data types** in its field
declarations (NOT turn-logic calls in method bodies — only one method,
`drain_into`, takes a sibling type by `&mut`). Moving `game_state.rs` to
`mc-state` therefore cascades on these — `mc-state` cannot reference them via
`crate::` and cannot depend on `mc-turn` (that's the cycle, since mc-turn will
dep mc-state):
| referenced type | mc-turn module | resolution |
|---|---|---|
| `CombatBalance` | `crate::combat_balance` | already `mc_core::CombatBalance` — just re-path |
| `RansomQueue` / `RansomOffer` | `crate::ransom` | data-only? audit; relocate to mc-core or mc-state |
| `UnitCapturedEvent`, `UnitRansomOfferedEvent`, `CivilianDestroyedEvent`, `UnitRansomAcceptedEvent`, `UnitRansomExpiredEvent`, `UnitKilledEvent`, `TurnResult` | `crate::combat_event` | data-only events; relocate the data shapes (mc-replay already owns `TurnEvent` — check overlap) |
| `CapturePosture` | `crate::capture` | small enum, likely data-only → mc-core |
| `PatrolOrder` | `crate::patrol` | data-only? audit |
| `is_zero_u32` | `crate::game_state` (self) | local helper, moves with the file |
So Phase 3 is a **2-step**: (3a) audit + relocate these 6 sibling data shapes to
mc-core (same re-export pattern as Phase 0c — each is likely as clean as the
tactical types were), THEN (3b) move `game_state.rs` to mc-state. Do 3a first as
its own green commit(s); it shrinks the game_state move to mechanical.
**Shim strategy (Phase 3b):** after the move, `mc-turn/src/game_state.rs` becomes
`pub use mc_state::game_state::*;` for one cycle so the ~30 consumer sites
(mc-ai, mc-player-api, mc-mod-host, api-gdext, mc-sim, mc-replay) don't move in
the same patch. The `mc-turn/lib.rs:58` re-export of the state types then
re-exports from mc-state transparently.
**Gate for Phase 3b:** save-format round-trip — load a real cycle-N save
byte-identical post-move (serde shapes are invariant, but confirm). Plus
`cargo check --workspace --tests`, `cargo test -p mc-state` (new round-trip
tests), `cargo test -p mc-turn`/`mc-ai`/`mc-player-api` parity.
**Note `game_state.rs` is 1356 lines (>500 limit).** Splitting is OUT OF SCOPE
(spec §Out of scope) — relocate as-is, flag the debt; do not split during the
move.
**Downstream:** p2-72 architecture stack (Path 2) is gated on FULL p2-65 (mc-state
existing + game_state moved + consumer Cargo.toml downgrades). It is 2+ sessions
out; do not start it until p2-65's acceptance bullets are met.
## Phase plan
### Phase 0 — Decide `ScoringWeights` ownership (1-2 hr)