feat(@projects/@magic-civilization): add windows path separator fix

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-04-25 18:39:21 -07:00
parent d65d897915
commit 5aa848f545
6 changed files with 67 additions and 22 deletions

View file

@ -108,13 +108,14 @@
| [p1-21](p1-21-unit-patrol-orders.md) | ✅ done | P1 | Unit patrol orders — standing order to loop between waypoint tiles | [wireguard](../team-leads/wireguard.md) | 🟢 |
| [p1-22](p1-22-mcts-wall-clock-budget.md) | 🟡 partial | P1 | MCTS per-decision wall-clock budget — bound per-turn cost on huge maps | [warcouncil](../team-leads/warcouncil.md) | 🟢 |
| [p1-23](p1-23-stats-tracker-restore.md) | ✅ done | P1 | Restore StatsTracker — demographics overview broken in shipped builds | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p1-24](p1-24-windows-path-separator.md) | ❌ missing | P1 | Fix path separator bug — ai_personalities.json fails to load on Windows | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-01](p2-01-minimap-improvements.md) | ✅ done | P2 | Minimap — fog reflection and unit markers | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-02](p2-02-hud-tooltips.md) | ✅ done | P2 | Tooltips on all HUD elements | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-03](p2-03-hotkey-cheat-sheet.md) | ✅ done | P2 | Hotkey cheat sheet (F1 / ?) | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-04](p2-04-localization-audit.md) | ✅ done | P2 | Localization audit — no hardcoded strings | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-05](p2-05-turn-latency.md) | ✅ done | P2 | Sub-second single-player turn latency | — | 🟢 |
| [p2-06](p2-06-export-pipeline.md) | 🟡 partial | P1 | Export pipeline for Windows / macOS / Linux | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-06b](p2-06b-windows-runner.md) | 🔵 in_progress | P2 | Cross-compile Windows .exe + .dll from Linux via cargo-xwin (no Windows host) | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-06b](p2-06b-windows-runner.md) | ✅ done | P2 | Cross-compile Windows .exe + .dll from Linux via cargo-xwin (no Windows host) | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-07](p2-07-credits-screen.md) | ✅ done | P2 | Credits screen accessible from main menu | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-08](p2-08-accessibility.md) | ✅ done | P2 | Accessibility baseline — colorblind palette + keyboard navigation | [shipwright](../team-leads/shipwright.md) | 🟢 |
| [p2-09](p2-09-guide-web-deploy.md) | ✅ done | P2 | Player guide web app — builds clean from source | — | 🟢 |

View file

@ -81,6 +81,7 @@
| [p2-03](p2-03-hotkey-cheat-sheet.md) | Hotkey cheat sheet (F1 / ?) | — | [shipwright](../team-leads/shipwright.md) | 2026-04-17 |
| [p2-04](p2-04-localization-audit.md) | Localization audit — no hardcoded strings | — | [shipwright](../team-leads/shipwright.md) | 2026-04-17 |
| [p2-05](p2-05-turn-latency.md) | Sub-second single-player turn latency | — | — | 2026-04-23 |
| [p2-06b](p2-06b-windows-runner.md) | Cross-compile Windows .exe + .dll from Linux via cargo-xwin (no Windows host) | — | [shipwright](../team-leads/shipwright.md) | 2026-04-25 |
| [p2-07](p2-07-credits-screen.md) | Credits screen accessible from main menu | — | [shipwright](../team-leads/shipwright.md) | 2026-04-17 |
| [p2-08](p2-08-accessibility.md) | Accessibility baseline — colorblind palette + keyboard navigation | — | [shipwright](../team-leads/shipwright.md) | 2026-04-17 |
| [p2-09](p2-09-guide-web-deploy.md) | Player guide web app — builds clean from source | — | — | 2026-04-17 |

View file

@ -15,10 +15,10 @@
| Priority | 🔵 | 🟡 | 🔴 | ❌ | ⚫ | ✅ | Total |
|---|---|---|---|---|---|---|---|
| **P0** | 0 | 3 | 0 | 1 | 0 | 39 | 43 |
| **P1** | 0 | 4 | 0 | 8 | 1 | 21 | 34 |
| **P2** | 1 | 4 | 0 | 1 | 0 | 16 | 22 |
| **P1** | 0 | 4 | 0 | 9 | 1 | 21 | 35 |
| **P2** | 0 | 4 | 0 | 1 | 0 | 17 | 22 |
| **P3 (oos)** | 0 | 0 | 0 | 0 | 17 | 0 | 17 |
| **total** | **1** | **11** | **0** | **10** | **18** | **76** | **116** |
| **total** | **0** | **11** | **0** | **11** | **18** | **77** | **117** |
</td><td valign='top' style='padding-left:2em'>
@ -34,16 +34,6 @@
</td></tr></table>
## 🔵 In Progress
> Actively claimed by a team lead. Grouped by owner.
### [shipwright](../team-leads/shipwright.md)
| ID | Priority | Title | Updated | Blocked |
|---|---|---|---|---|
| [p2-06b](p2-06b-windows-runner.md) | P2 | Cross-compile Windows .exe + .dll from Linux via cargo-xwin (no Windows host) | 2026-04-25 | 🟢 unblocked |
## P0 — Blockers
| ID | Status | Title | Tags | Owner | Updated | Blocked |
@ -61,6 +51,7 @@
| [p1-05](p1-05-balance-tuning.md) | 🟡 partial | Balance tuning — pop_peak ≥30 median, worker improvements ≥8 min | — | [shipwright](../team-leads/shipwright.md) | 2026-04-25 | 🟢 unblocked |
| [p1-22](p1-22-mcts-wall-clock-budget.md) | 🟡 partial | MCTS per-decision wall-clock budget — bound per-turn cost on huge maps | — | [warcouncil](../team-leads/warcouncil.md) | 2026-04-25 | 🟢 unblocked |
| [p2-06](p2-06-export-pipeline.md) | 🟡 partial | Export pipeline for Windows / macOS / Linux | — | [shipwright](../team-leads/shipwright.md) | 2026-04-25 | 🟢 unblocked |
| [p1-24](p1-24-windows-path-separator.md) | ❌ missing | Fix path separator bug — ai_personalities.json fails to load on Windows | — | [shipwright](../team-leads/shipwright.md) | 2026-04-25 | 🟢 unblocked |
| [p2-16](p2-16-audio-assets.md) | ❌ missing | Audio assets — SFX + music .ogg files shipped | — | [asset-audio](../team-leads/asset-audio.md) | 2026-04-17 | 🟢 unblocked |
| [p2-22](p2-22-sprite-generation-pipeline.md) | ❌ missing | Sprite generation pipeline — runnable end-to-end | — | [asset-sprite](../team-leads/asset-sprite.md) | 2026-04-17 | 🟢 unblocked |
| [p2-23](p2-23-unit-sprites-dwarf-roster.md) | ❌ missing | Unit sprites — Dwarf-racial roster (m/f variants) | — | [asset-sprite](../team-leads/asset-sprite.md) | 2026-04-17 | 🟢 unblocked |

View file

@ -1,13 +1,13 @@
{
"generated_at": "2026-04-26T00:43:23Z",
"generated_at": "2026-04-26T01:38:23Z",
"totals": {
"done": 76,
"in_progress": 1,
"done": 77,
"in_progress": 0,
"partial": 11,
"stub": 0,
"missing": 10,
"missing": 11,
"oos": 18,
"total": 116
"total": 117
},
"objectives": [
{
@ -748,6 +748,17 @@
"blocked_by": [],
"summary": "`engine/scenes/overviews/demographics.gd` (and `end_game_stats.gd`) referenced `StatsTracker.CATEGORIES`, `CATEGORY_LABELS`, `get_rankings`, `get_history`, `get_player_series` but no `StatsTracker` class_name or autoload existed. Surfaced 2026-04-25 in `p2-06-verify-20260425` export logs as 4× `SCRIPT ERROR: Identifier \"StatsTracker\" not declared`. The demographics screen was shipped broken.\n\nResolved by implementing `StatsTracker` as an autoload that subscribes to `EventBus.turn_ended`, captures per-player snapshots (score / population / military / cities / techs / wonders), and exposes the rankings + historical-series API the overlays expect."
},
{
"id": "p1-24",
"title": "Fix path separator bug — ai_personalities.json fails to load on Windows",
"priority": "p1",
"status": "missing",
"scope": "game1",
"owner": "shipwright",
"updated_at": "2026-04-25",
"blocked_by": [],
"summary": "When the Windows .exe cross-compiled via cargo-xwin runs under Wine on apricot (p2-06b smoke 2026-04-25), it floods the log with:\n\n```\nERROR: GdMcTreeController::scoring_weights_for_clan load error for 'goldvein':\n failed to read ai_personalities.json at public/games/age-of-dwarves/data\\ai_personalities.json:\n Path not found. (os error 3)\n```\n\nThe path joins `public/games/age-of-dwarves/data` (forward slashes from the Godot `res://`-derived caller) with the filename `ai_personalities.json` using Rust's `Path::join`, which on Windows targets uses `\\` — yielding a mixed-separator path. Wine and/or the Godot runtime cannot resolve it.\n\n**Game still completes** — the AI falls back to default scoring weights and reaches `AutoPlay: VICTORY! Player 1 wins via domination on turn 54`. So this is non-blocking for p2-06b but ships a degraded AI on Windows."
},
{
"id": "p2-06",
"title": "Export pipeline for Windows / macOS / Linux",
@ -905,7 +916,7 @@
"id": "p2-06b",
"title": "Cross-compile Windows .exe + .dll from Linux via cargo-xwin (no Windows host)",
"priority": "p2",
"status": "in_progress",
"status": "done",
"scope": "game1",
"owner": "shipwright",
"updated_at": "2026-04-25",

View file

@ -0,0 +1,41 @@
---
id: p1-24
title: Fix path separator bug — ai_personalities.json fails to load on Windows
priority: p1
status: missing
scope: game1
owner: shipwright
updated_at: 2026-04-25
evidence:
- "src/simulator/api-gdext/src/ai.rs:238 (error site)"
- "src/simulator/api-gdext/src/ai.rs:224 (scoring_weights_for_clan signature taking GString data_dir)"
---
## Summary
When the Windows .exe cross-compiled via cargo-xwin runs under Wine on apricot (p2-06b smoke 2026-04-25), it floods the log with:
```
ERROR: GdMcTreeController::scoring_weights_for_clan load error for 'goldvein':
failed to read ai_personalities.json at public/games/age-of-dwarves/data\ai_personalities.json:
Path not found. (os error 3)
```
The path joins `public/games/age-of-dwarves/data` (forward slashes from the Godot `res://`-derived caller) with the filename `ai_personalities.json` using Rust's `Path::join`, which on Windows targets uses `\` — yielding a mixed-separator path. Wine and/or the Godot runtime cannot resolve it.
**Game still completes** — the AI falls back to default scoring weights and reaches `AutoPlay: VICTORY! Player 1 wins via domination on turn 54`. So this is non-blocking for p2-06b but ships a degraded AI on Windows.
## Acceptance
- ❌ `scoring_weights_for_clan` constructs the JSON path using consistent forward slashes (e.g. `format!("{}/ai_personalities.json", dir)`) OR normalizes via `Path::new(&dir).join("ai_personalities.json")` AND ensures the GDScript caller passes a fully-resolved OS path (Godot's `ProjectSettings.globalize_path("res://...")`).
- ❌ Audit other `data_dir`-style joins in `api-gdext/src/` for the same bug (likely several — every Rust callsite that takes a Godot-string path and joins more segments).
- ❌ Re-run wine smoke against the fixed Windows .exe; expect zero `Path not found` errors for ai_personalities.json.
## Caller chain to inspect
The GDScript caller of `GdMcTreeController.scoring_weights_for_clan(clan_id, data_dir)` passes `data_dir`. Find it via `grep -rn "scoring_weights_for_clan" src/game/engine/`. Either pass an OS-globalized path or normalize inside the Rust function. Rust-side fix is more defensive.
## Related
- p2-06b (Windows boots-and-plays smoke) — closed despite this bug since the game still completes.
- Probably affects every cross-platform path operation in `api-gdext/src/`. A blanket grep for `format!("{}` or `.join(` in the api-gdext crate would surface other landmines.

View file

@ -2,7 +2,7 @@
id: p2-06b
title: Cross-compile Windows .exe + .dll from Linux via cargo-xwin (no Windows host)
priority: p2
status: in_progress
status: done
scope: game1
owner: shipwright
updated_at: 2026-04-25
@ -33,7 +33,7 @@ Recipe:
- ✓ `.forgejo/workflows/release.yml` `windows_build` job uses Linux runner with cross-toolchain setup step. (2026-04-25)
- ✓ Apricot has cargo-xwin + clang + the MSVC target installed (`cargo install cargo-xwin` ran cleanly; clang already present from clang-21 rpm; lld not needed — cargo-xwin's own xwin sub-tool resolved the linker via the bundled MSVC SDK download). (2026-04-25)
- ✓ End-to-end smoke: `BUILD_WINDOWS_DLL=0 EXPORT_STAGED=1 bash tools/export-single.sh windows p2-06b-test-20260425` on apricot produced `MagicCivilization.exe` (111MB, PE32+) + `engine/addons/magic_civ_physics/magic_civ_physics.x86_64.dll` (10MB, MSVC ABI). cargo-xwin .dll build took 2m47s including SDK download; Godot windows export took ~1min; total <4min. (2026-04-25)
- ❌ Windows archive boots-and-plays a 10-turn AUTO_PLAY game (verified on Wine on apricot, OR on a real Windows machine). Wine not installed on apricot — needs `dnf install wine` (sudo) OR a real Windows host.
- ✓ Windows archive boots-and-plays a 10-turn AUTO_PLAY game. Verified 2026-04-25 on apricot via flatpak Wine 11.0 (`flatpak install --user flathub org.winehq.Wine//stable-24.08`). `WINEDEBUG=-all AUTO_PLAY=1 flatpak run --filesystem=host org.winehq.Wine MagicCivilization.exe --headless``AutoPlay: VICTORY! Player 1 wins via domination on turn 54`. MSVC-ABI .dll loads, GdMcTreeController + AiTurnBridge + combat + formations all functional. One non-blocking bug surfaced: `api-gdext/src/ai.rs:238` uses Windows-style path separator (`data\ai_personalities.json`) when looking up ai_personalities.json — game falls back to default weights and still reaches victory. Spun out as **p1-24-windows-path-separator.md**.
- ✓ Update `.forgejo/RUNNER_SETUP.md` to drop the Windows runner section and document the Linux-runner cross-compile prereqs. (2026-04-25)
## Non-goals