magicciv/.project/FINISH_GAME1_PLAN.md
autocommit 180c521977 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>
2026-06-04 19:20:40 -07:00

8.6 KiB
Raw Permalink Blame History

Finish Game 1 — Plan of Record

Generated: 2026-06-04, from the true-state gap analysis appended to all 28 open objectives. Definition of done (operator, 2026-06-04): every open objective reaches done EXCEPT the two accepted-open items:

  1. Audio sign-off (p2-16) — functionally complete & plays in-game; needs a human ear.
  2. Artist-paid final sprites (p2-23…p2-27) — placeholder coverage ships the build (commercial-safe game-icons baseline + Wesnoth demo layer); final art is a paid-artist commission.

Out of scope for "Game 1 complete": the web guide (p2-18) is a companion app on its own track, not the game.

Index snapshot: done 241 · partial 19 · stub 8 · missing 1 · in_progress 1 (of 303; rest oos/superseded). The base 4X game is functionally ROADMAP-complete and playable today (131 UI scenes, MCTS AI, full turn loop). The work below is completion polish + one hard AI problem + an architecture refactor.


The one real risk: AI convergence (not a checkbox)

p1-29h Phase 1 built the decisiveness capability (army target-lock + commitment hysteresis + press-on-capture, 278 tests green). Phase 2 built the fair measurement surface and measured: 20 captures → 0 eliminations → 38 refounds over 160 turns. The army takes cities; the loser always refounds and recovers. Diagnosis is precise (refound-suppression), but the fix is unsolved and likely needs balance-design iteration (suppress refounding hard enough to converge without breaking 4X feel). This is the only item I cannot promise lands clean — budget several iterations. Everything else is mechanical.


Waves (dependency-ordered)

Wave A — wiring & quick wins (SM · highest value/effort)

Built logic that's dead-ended on a missing thin wrapper, plus cheap unblocks.

Task Objective Detail
statistics.tscn wrapper p2-47 709-line statistics.gd + mc-score exist; world_map.gd:1001 & ingame_menu.gd:80 push a missing .tscn → F9/info-button/Stats menu dead-end. Author the one-node wrapper. (bug fix)
end_game_summary.tscn wrapper + game-over wiring + GUT p2-48a (+ p2-48) end_game_summary.gd orphaned (no .tscn, nothing instantiates). Logic/tests largely done; author wrapper, wire all 4 GameOverReason, GUT + apricot proof.
processor live-loop hookup p2-57b + p2-57c Wire tick_and_stamp/apply_quality into mc-turn::processor::process_city_production (zero quality calls today). One M task closes both — unit quality is inert in-game until it lands. Rephrase p2-57b bullet-4 (global default covers all units; per-unit optional).
_pick_research regression batch p0-26b Run 10-seed T300 on apricot vs main; flip done if tier_peak ≥ baseline.
3 missing unit JSONs (data) dwarf_master_engineer, master_surgeon, saga_writer referenced by buildings but absent.

Wave B — lairs (M)

Task Objective Detail
GdLair::assault bridge + Assault/Siege/Raid picker UI p3-10a Resolver + loot all done (4/5); only the GDExt bridge + picker remain.
Wire SiegeState into dispatch + turn loop p3-10b tick_siege/SiegeState landed but dead code (LairCombatMode::SiegeNotImplemented). Add dispatch branch, per-turn integration, siege_resistance JSON, tests, bridge.

Wave C — AI convergence (L · AT RISK — see risk box)

Task Objective Detail
Refound-suppression lever (new objective p1-29i) p1-29h, p1-29d Suppress/delay enemy refound after city loss (or make captures sticky). Re-measure ≥1 elimination on the existing gridded harness.
Re-score convergence + trained-vs-scripted p1-29d, p1-29g Once eliminations occur, re-run the gridded surface; p1-29g (unblocked, p1-29f done) drives trained vs scripted.
Production-posture short-circuit p1-29e Smaller lever; re-evaluate after refound-suppression.
Upstream prereqs (NOT in the 28) p0-08, ecology p0-08 luxury-tempo must land in main → unblocks p1-05-fu. Flip ecology_yields.json off static_terrain → unblocks p1-38-fu. Then run both balance batches.

Wave D — architecture stack (L · the heavy refactor, multi-session)

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 🟡 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).
5 p2-72a-save-format-migration GDScript SaveManager rewrite (Rust backend SaveEnvelope done; fix CURRENT_VERSION doc drift 2 vs 1).
6 p2-72 GdPlayerApi → GdGameState render bridge — ~1hr tail once the stack lands.

Wave E — CI hygiene (S)

Task Objective Detail
Choose + apply max-file-lines policy p2-10k-followup 11 files >500 lines; game_state.gd now 718 (split into subdirs per the <500 rule — naturally folds into Wave D's game_state.gd refactor).

Critical path & sequencing

  • Wave A and B are independent, parallel-safe in concept but all touch Rust/GDScript source → one serialized source lane (single shared workspace, no worktrees). Asset/run/doc work parallelizes; source does not.
  • Wave D is the long pole by wall-clock (the p2-72a render-source milestone, 58 days). It can run as its own multi-session lane in parallel with A/B/C only if file-disjoint — in practice it churns game_state.gd + api-gdext, so it largely serializes with A's processor hookup and B's bridges. Recommend: A → (B ∥ start of D) → C in the background → finish D.
  • Wave C is research-paced; start the refound-suppression lever early and iterate while A/B/D mechanical work proceeds.

Accepted-open at "Game 1 complete"

  • p2-16 audio — human listen-test only.
  • p2-23…p2-27 — paid final art (placeholders ship).
  • p2-18 web guide — separate track (needs WASM build + operator publish-approval).

Integration / commits

All work lands as atomic commits on the worktree-bridge-cse_* submodule branch; the live commits.service + claire-agent daemons propagate to main automatically (do NOT manually merge — it races the daemons). Proof screenshots capture on apricot (plum down).


Wave F — Design-system fidelity (NEW 2026-06-04 · L · the "Godot UI ≠ design guides" gap)

Gap (quantified): the design system (design-tokens.json + UI_DESIGN_SYSTEM.md + HTML sketches + React gallery) drives the web guide (fantasy-theme.ts) but not the Godot game. ui_theme.tres exists yet is never applied as the root theme, and 45 scene scripts hardcode 973 raw Color() + 307 add_theme_*_override calls, hand-rolling visuals that diverge from the spec. The scenes are GUT-green but visually plain — a real "missing UI side" beyond wiring.

Task Objective Detail
Token→theme pipeline + global apply + ThemeAssets.color() accessor p2-73 Generate ui_theme.tres from design-tokens.json (tokens = SoT); apply it as the root Control theme; add a semantic token-color accessor. Foundation — in progress.
De-hardcode 45 scene scripts p2-74 (blocked_by p2-73) Route 973 inline Color() + 307 overrides onto the theme / ThemeAssets.color() tokens, per-screen-cluster, always-green. The bulk of the visual-fidelity work — L, multi-session.

Why it matters / honest framing: the web feels "easier" because tokens flow straight to CSS; Godot's Control/Theme/StyleBox + programmatic tree-building threw that away. The fix is the missing tokens → .tres plumbing + a de-hardcode pass — not shipping HTML (Godot is the Steam target). Polish-tier, not demo-blocking, but required if "Game 1 complete" means fidelity to the design guides.