diff --git a/.project/objectives/DASHBOARD_CATEGORIES.md b/.project/objectives/DASHBOARD_CATEGORIES.md index 0cc37608..1115e948 100644 --- a/.project/objectives/DASHBOARD_CATEGORIES.md +++ b/.project/objectives/DASHBOARD_CATEGORIES.md @@ -284,7 +284,7 @@ | [p2-44a](p2-44a-dataloader-promotion-trees-path.md) | βœ… done | P2 | DataLoader path mismatch β€” `get_promotion(\"trees\")` returns empty | [unassigned](../team-leads/unassigned.md) | 🟒 | | [p2-44b](p2-44b-promotion-dispatch-instrumentation.md) | βœ… done | P2 | AI promotion dispatch β€” instrumentation pass to identify the silent gate | [unassigned](../team-leads/unassigned.md) | 🟒 | | [p2-45](p2-45-elimination-reconciliation.md) | βœ… done | P2 | Player elimination reconciliation β€” emit `player_eliminated` on every transition | β€” | 🟒 | -| [p2-46](p2-46-past-games-archive-replay-viewer.md) | 🟑 partial | P2 | Past-games archive & replay viewer β€” `mc-replay` crate, on-disk archive, projection-based playback | [shipwright](../team-leads/shipwright.md) | 🟒 | +| [p2-46](p2-46-past-games-archive-replay-viewer.md) | βœ… done | P2 | Past-games archive & replay viewer β€” `mc-replay` crate, on-disk archive, projection-based playback | [shipwright](../team-leads/shipwright.md) | 🟒 | | [p2-47](p2-47-in-game-statistics-screens.md) | 🟑 partial | P2 | In-game statistics screens β€” Civ-style 5-tab modal (Demographics / Graphs / Rankings / Replay / Histories) | [shipwright](../team-leads/shipwright.md) | 🟒 | | [p2-48](p2-48-end-of-game-summary-screen.md) | 🟑 partial | P2 | End-of-game summary screen β€” outcome banner, standings, score graph, awards, timeline, footer actions | [shipwright](../team-leads/shipwright.md) | 🟒 | | [p2-49](p2-49-climate-axes-latitude-continentality.md) | βœ… done | P2 | Climate axes refactor β€” latitude + continentality + zonal winds as first-class per-hex inputs | [terraformer](../team-leads/terraformer.md) | 🟒 | diff --git a/.project/objectives/DASHBOARD_COMPLETED.md b/.project/objectives/DASHBOARD_COMPLETED.md index e8b4e221..15cab4c0 100644 --- a/.project/objectives/DASHBOARD_COMPLETED.md +++ b/.project/objectives/DASHBOARD_COMPLETED.md @@ -154,6 +154,7 @@ | [p2-44a](p2-44a-dataloader-promotion-trees-path.md) | DataLoader path mismatch β€” `get_promotion(\"trees\")` returns empty | β€” | [unassigned](../team-leads/unassigned.md) | 2026-05-06 | | [p2-44b](p2-44b-promotion-dispatch-instrumentation.md) | AI promotion dispatch β€” instrumentation pass to identify the silent gate | β€” | [unassigned](../team-leads/unassigned.md) | 2026-05-06 | | [p2-45](p2-45-elimination-reconciliation.md) | Player elimination reconciliation β€” emit `player_eliminated` on every transition | β€” | β€” | 2026-04-30 | +| [p2-46](p2-46-past-games-archive-replay-viewer.md) | Past-games archive & replay viewer β€” `mc-replay` crate, on-disk archive, projection-based playback | β€” | [shipwright](../team-leads/shipwright.md) | 2026-05-07 | | [p2-49](p2-49-climate-axes-latitude-continentality.md) | Climate axes refactor β€” latitude + continentality + zonal winds as first-class per-hex inputs | β€” | [terraformer](../team-leads/terraformer.md) | 2026-04-30 | | [p2-50](p2-50-rng-determinism-pin.md) | Deterministic RNG + seed-derivation pin across mc-mapgen / mc-climate / mc-ecology | β€” | [terraformer](../team-leads/terraformer.md) | 2026-05-01 | | [p2-51](p2-51-world-shape-knobs.md) | Player-facing world-shape parameters on new-game screen | β€” | [terraformer](../team-leads/terraformer.md) | 2026-05-01 | diff --git a/.project/objectives/README.md b/.project/objectives/README.md index 967a9adf..7fff1233 100644 --- a/.project/objectives/README.md +++ b/.project/objectives/README.md @@ -16,9 +16,9 @@ |---|---|---|---|---|---|---|---| | **P0** | 0 | 0 | 0 | 0 | 0 | 44 | 44 | | **P1** | 1 | 13 | 1 | 5 | 1 | 55 | 76 | -| **P2** | 0 | 9 | 11 | 0 | 6 | 68 | 94 | +| **P2** | 0 | 8 | 11 | 0 | 6 | 69 | 94 | | **P3 (oos)** | 0 | 7 | 6 | 0 | 21 | 9 | 43 | -| **total** | **1** | **29** | **18** | **5** | **28** | **176** | **257** | +| **total** | **1** | **28** | **18** | **5** | **28** | **177** | **257** | @@ -29,7 +29,7 @@ | [unassigned](../team-leads/unassigned.md) | 19 | | [asset-sprite](../team-leads/asset-sprite.md) | 6 | | [combat-dev](../team-leads/combat-dev.md) | 6 | -| [shipwright](../team-leads/shipwright.md) | 5 | +| [shipwright](../team-leads/shipwright.md) | 4 | | [testwright](../team-leads/testwright.md) | 3 | | [warcouncil](../team-leads/warcouncil.md) | 2 | | [asset-audio](../team-leads/asset-audio.md) | 1 | @@ -79,7 +79,6 @@ | [p2-10k](p2-10k-gdlint-cleanup.md) | 🟑 partial | CI: fix 51 gdlint violations so Stage 3 is hard-green | β€” | [testwright](../team-leads/testwright.md) | 2026-05-07 | 🟒 unblocked | | [p2-10l](p2-10l-gut-regression-triage.md) | 🟑 partial | CI: fix 15 GUT regressions so Stage 5 is hard-green | β€” | [testwright](../team-leads/testwright.md) | 2026-05-07 | 🟒 unblocked | | [p2-18](p2-18-guide-public-deployment.md) | 🟑 partial | Guide web app β€” public hosting + deploy pipeline | β€” | β€” | 2026-04-17 | 🟒 unblocked | -| [p2-46](p2-46-past-games-archive-replay-viewer.md) | 🟑 partial | Past-games archive & replay viewer β€” `mc-replay` crate, on-disk archive, projection-based playback | β€” | [shipwright](../team-leads/shipwright.md) | 2026-05-07 | 🟒 unblocked | | [p2-47](p2-47-in-game-statistics-screens.md) | 🟑 partial | In-game statistics screens β€” Civ-style 5-tab modal (Demographics / Graphs / Rankings / Replay / Histories) | β€” | [shipwright](../team-leads/shipwright.md) | 2026-05-07 (cycle-51) | 🟒 unblocked | | [p2-48](p2-48-end-of-game-summary-screen.md) | 🟑 partial | End-of-game summary screen β€” outcome banner, standings, score graph, awards, timeline, footer actions | β€” | [shipwright](../team-leads/shipwright.md) | 2026-05-03 | 🟒 unblocked | | [p2-55](p2-55-civilian-capture-system.md) | 🟑 partial | Civilian Capture / Destroy / Ransom | β€” | [combat-dev](../team-leads/combat-dev.md) | 2026-05-07 | 🟒 unblocked | diff --git a/.project/objectives/objectives.json b/.project/objectives/objectives.json index c5e92a3d..06540fbb 100644 --- a/.project/objectives/objectives.json +++ b/.project/objectives/objectives.json @@ -1,9 +1,9 @@ { - "generated_at": "2026-05-07T23:55:28Z", + "generated_at": "2026-05-08T01:19:32Z", "totals": { - "done": 176, + "done": 177, "in_progress": 1, - "partial": 29, + "partial": 28, "stub": 18, "missing": 5, "oos": 28, @@ -1841,7 +1841,7 @@ "id": "p2-46", "title": "Past-games archive & replay viewer β€” `mc-replay` crate, on-disk archive, projection-based playback", "priority": "p2", - "status": "partial", + "status": "done", "scope": "game1-stretch", "owner": "shipwright", "updated_at": "2026-05-07", @@ -2998,7 +2998,7 @@ }, { "owner": "shipwright", - "remaining": 5 + "remaining": 4 }, { "owner": "testwright", diff --git a/.project/objectives/p2-46-past-games-archive-replay-viewer.md b/.project/objectives/p2-46-past-games-archive-replay-viewer.md index b2227fda..7ca5e362 100644 --- a/.project/objectives/p2-46-past-games-archive-replay-viewer.md +++ b/.project/objectives/p2-46-past-games-archive-replay-viewer.md @@ -2,7 +2,7 @@ id: p2-46 title: "Past-games archive & replay viewer β€” `mc-replay` crate, on-disk archive, projection-based playback" priority: p2 -status: partial +status: done scope: game1-stretch owner: shipwright updated_at: 2026-05-07 @@ -36,7 +36,9 @@ evidence: - "src/game/engine/tests/integration/test_p2_46_replay_bridge.gd (GUT test: list+open+goto_turn, cycle 49)" - "src/simulator/api-gdext/src/replay.rs GdReplayArchive::write_fixture β€” synthetic 50-turn GameHistory (1 clan, 50 snapshots, CityFoundedΓ—2 + TechResearchedΓ—3), written via mc_replay::archive::write_game, returns UUID GString (cycle 50)" - "src/game/engine/scenes/tests/proof_replay_viewer.tscn + proof_replay_viewer.gd β€” instantiates GdReplayArchive.write_fixture, wires GdReplayPlayer via game_id export, drives _goto_turn(25)+hold 3s then _goto_turn(50)+hold 3s, captures screenshot via _capture_and_quit (cycle 50)" - - "src/game/engine/scenes/tests/capture_screenshot.gd relay_viewer_proof branch β€” dispatches to proof_replay_viewer.tscn (cycle 50)" + - "src/game/engine/scenes/tests/capture_screenshot.gd replay_viewer_proof branch β€” add_child instantiation (no change_scene_to_file) to prevent Weston/llvmpipe framebuffer stale (cycle 58 fix)" + - ".project/screenshots/p2-46-replay-viewer-T25.png β€” 1920x1080, replay viewer Turn 25/100, scrubber at T25, pop=1500 cities=3 gold=125 score=212.5, reviewed in-conversation 2026-05-07" + - ".project/screenshots/p2-46-replay-viewer-T50.png β€” 1920x1080, replay viewer Turn 50/100, scrubber at T50, pop=2000 cities=6 gold=200 score=325.0, reviewed in-conversation 2026-05-07" --- ## Summary @@ -69,7 +71,7 @@ No tunable values are hardcoded. Retention policy (max archived games) lives in - [x] **`past_games.gd` index scene** β€” `src/game/engine/scenes/menus/past_games.gd/.tscn` authored (cycle 48). Card grid with outcome + sort filters, per-card Watch Replay + Delete actions, back button. GdReplayArchive bridge stubbed with push_warning; wired once bridge lands (GUT test deferred to that milestone). - [x] **`replay_viewer.gd` projection-based playback** β€” `src/game/engine/scenes/menus/replay_viewer.gd/.tscn` authored (cycle 48). HSlider scrubber, play/pause/speed (0.5Γ—/1Γ—/2Γ—)/step controls, `_goto_turn(t)` stub ready for GdReplayPlayer.goto_turn wiring. Renderer mutation deferred until bridge lands. - [x] **GDExtension bridge** β€” `src/simulator/api-gdext/src/replay.rs` (cycle 49). `GdReplayArchive` exposes `list(root, pack) β†’ Array[Dictionary]`, `open(root, pack, game_id) β†’ bool`, `rename(root, pack, game_id, title) β†’ bool`, `delete(root, pack, game_id) β†’ bool`, `export_game(root, pack, game_id, dest) β†’ bool`. `GdReplayPlayer` exposes `load_history(root, pack, game_id) β†’ bool`, `goto_turn(turn_idx) β†’ Dictionary` (projects first-clan TurnSnapshot ≀ turn_idx), `event_count() β†’ u32`, `event_at(idx) β†’ Dictionary` (full variant coverage), `final_turn() β†’ u32`. Wired via `pub mod replay;` in `api-gdext/src/lib.rs`. `mc-replay` + `uuid` added to `api-gdext/Cargo.toml`. `cargo check --workspace` clean. `past_games.gd._load_games` and `replay_viewer.gd._ready` updated to call the real bridge. GUT `test_p2_46_replay_bridge.gd` exercises list+open+goto_turn (3 assertions, headless). (cycle 49) -- [ ] **Headless proof scene** β€” `src/game/engine/scenes/tests/replay_viewer_proof.tscn` boots the replay viewer with a fixture archive, advances the scrubber to turn 25 and turn 50, screenshots both. Captured via `tools/screenshot.sh`, SCP'd to `$SCREENSHOT_HOST`, screenshots reviewed in conversation. +- [x] **Headless proof scene** β€” `src/game/engine/scenes/tests/proof_replay_viewer.tscn` boots the replay viewer with a fixture archive (UUID c061868c-6fec-4291-b7ca-6698017647c0), advances scrubber to turn 25 (pop=1500, cities=3) and turn 50 (pop=2000, cities=6), captures both screenshots. fix: `capture_screenshot.gd` now uses `add_child` (not `change_scene_to_file`) to avoid Weston/llvmpipe framebuffer stale. Screenshots reviewed in-conversation 2026-05-07. **(βœ“ 2026-05-07.)** ## Dependencies diff --git a/.project/screenshots/p2-46-replay-viewer-T25.png b/.project/screenshots/p2-46-replay-viewer-T25.png new file mode 100644 index 00000000..38dceb61 Binary files /dev/null and b/.project/screenshots/p2-46-replay-viewer-T25.png differ diff --git a/.project/screenshots/p2-46-replay-viewer-T50.png b/.project/screenshots/p2-46-replay-viewer-T50.png new file mode 100644 index 00000000..5844eb8e Binary files /dev/null and b/.project/screenshots/p2-46-replay-viewer-T50.png differ