magicciv/.project/objectives/p1-13-guide-dev-route-coverage.md
Natalie d7df3db0a8 feat(@projects): add team-lead tourguide and guide development docs
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-17 14:33:54 -07:00

8.5 KiB

id title priority status scope owner updated_at evidence
p1-13 Guide dev server boots on plum with zero-error route coverage p1 done game1 tourguide 2026-04-17
public/games/age-of-dwarves/guide/e2e/all-routes.spec.ts
public/games/age-of-dwarves/guide/playwright.config.ts
public/games/age-of-dwarves/guide/src/App.tsx
public/games/age-of-dwarves/guide/src/app/lazy-pages.ts
scripts/run/dev.sh
.project/history/20260417_tourguide_dev_bringup.md

Status — 2026-04-17 (tourguide, closed)

All 6 acceptance bullets verifiable in repo:

  • ./run guide boots on plum. Dev server starts via Vite on port 5800 (per scripts/run/dev.sh::cmd_guide). The e2e run uses playwright.config.ts's webServer hook to start pnpm dev --port 5802; the server reaches "ready" and serves all 51 routes end-to-end.
  • public/games/age-of-dwarves/guide/e2e/all-routes.spec.ts exists with 49 canonical fast/slow routes + 1 fallback-redirect negative check (51 tests total), encoded as readonly RouteSpec[] with as const satisfies so adding a route is a single-line append.
  • ✓ Each test captures page.on('console') error-level messages + page.on('pageerror'), ignoring a small IGNORED_ERROR_PATTERNS list (React DevTools notice), and asserts both accumulator arrays are empty with the full message set inlined as the expect failure label.
  • pnpm test:e2e full green: 51/51 passed (44.7s) on run 1 and 51/51 passed (42.3s) on run 2 after Wave 1 landed (guide-web agent's page/data fixes + game-data agent's ley_school + TileState field-drift fix).
  • ✓ Two consecutive full-green runs confirmed — no flakes.
  • scripts/run/dev.sh::cmd_guide pre-check emits two yellow warnings when appropriate: (a) if src/simulator/pkg/ has content, and (b) if .local/build/wasm/magic_civ_physics.js is missing. Both include concrete remediation commands (local build, apricot rsync).

Wave-2 domain fixes consumed by this closure

The 7 routes that were red at the initial 2026-04-17 bring-up are all green. Parallel Wave-1 agents landed the underlying fixes:

  • guide-web — manifest-driven data-loader overhaul in public/games/age-of-dwarves/guide/src/data/game.ts (wrapper JSON files no longer polluted allResources / allImprovements / allBuildings), promotions pipeline wired from @resources/promotions/promotions.json with a Raw→Canonical adapter, null-guards on disciplinesData.disciplines in PromotionsPage, magic-schools import removed from DevSpritesPage in favor of the shared SCHOOL_COLORS export, sprite-audit network storm gated behind opt-in button + 8-worker concurrency cap.
  • game-datasrc/packages/engine-ts/src/types.ts TileState widened to match the Rust struct in mc-core/src/grid/mod.rs (25 missing required fields added: maturity, deadwood, soil_depth, lair-state fields, aerosol_mitigation, etc.); ley_school: '' sentinels replaced with 'none' to match Rust's LeySchool enum snake_case serialization; simulation + ecology/event-system test helpers aligned. The original Tourguide report mis-labeled the field as school_affinity — the actual culprit was ley_school in PopulationDashboardPage's simulation initializer.

Evidence

  • .project/history/20260417_tourguide_dev_bringup.md — original bring-up record.
  • Wave-2 confirmation runs: two consecutive 51 passed outputs preserved in the Tourguide closure entry (.project/CHANGELOG.md, 2026-04-17).
  • Known-red list in .project/team-leads/tourguide.md retained for historical reference with a closure note.
  • MCP Playwright visual verify (2026-04-17) — independent real-chromium walkthrough of 5 representative routes (home, /map/resources, /military/promotions, /climate/ecosystem/populations, /dev/sprites) beyond the headless e2e. All 5 render with zero console errors; /climate/ecosystem/populations in particular runs the full 120-turn WASM ecology sim end-to-end through the Rust ↔ TS FFI — empirical proof the ley_school + TileState drift fix holds at runtime. Screenshots under .playwright-mcp/mcp_{home,resources,promotions,populations,dev_sprites}.png.

Known caveat (surfaced by MCP verify, tracked separately)

/climate/simulation with noGui=true&totalTurns=50&buffer=0 params stalls at 0% in "pre-computed simulation from server" mode — simCachePlugin's tsx-spawned pre-warm worker can't resolve @magic-civ/physics-rs through the pnpm symlink now that src/simulator/package.json has no main/types (the ../../ escape out of the package root that would have pointed at .local/build/wasm/ doesn't traverse cleanly through node's resolver). This is a dev-only server optimization; the client-WASM fallback path is what all-routes.spec.ts measured and passed (44.7 s / 42.3 s). Tracked as a Tourguide follow-up in p2-20 guide-sim-cache-pnpm-resolve; not a user-facing bug, not blocking this objective's closure.

Summary

./run guide on plum (natalie@plum.local, macOS) today fails before first paint because @magic-civ/physics-rs resolves to the missing src/simulator/pkg/magic_civ_physics.js — p1-11 + p1-12 close that structural half. What remains is the contributor-side proof: starting the dev server on a fresh clone, loading every canonical route in Playwright, and asserting zero runtime errors. Nobody currently owns that proof, and the last guide-dev CHANGELOG entry (2026-04-16 14:47 task #18) explicitly marked "visual verification blocked by WASM not built on macOS." The gap closes when a spec exists, runs green on plum, and catches new routes automatically on every pnpm test:e2e.

The e2e substrate is already wired — @lilith/playwright-e2e-docker is a committed dependency, e2e/Dockerfile.web pre-bakes a production build, playwright.config.ts switches its webServer between pnpm dev --port 5802 (local) and pnpm preview --port 5802 (CI), and two specs (diag.spec.ts, simulator.spec.ts) already exercise the climate simulator. This objective extends that harness with one route-coverage spec; no new infrastructure.

Acceptance

  • ./run guide launches Vite on plum, reports "VITE ready in …ms", and lsof -iTCP:5800 shows the listening port.
  • New spec public/games/age-of-dwarves/guide/e2e/all-routes.spec.ts enumerates the 49 canonical routes from src/App.tsx (+ one negative /does-not-exist redirect check) as a strongly-typed const ROUTES = [...] as const satisfies readonly string[] so adding a route is a single-line append.
  • Each route test: captures page.on('console', ...) + page.on('pageerror', ...), navigates with ?skip=welcome to bypass onboarding, waits for network-idle (bounded: 30s climate / 10s static), asserts both accumulator arrays are empty with the messages inlined as the expect failure label.
  • pnpm --prefix public/games/age-of-dwarves/guide test:e2e reports "N passed" where N matches the enumerated routes + the existing climate-sim suite; two consecutive runs both green (no flakes).
  • scripts/run/dev.sh::cmd_guide pre-check: if src/simulator/pkg/ exists, prints a one-line warning pointing at bash src/simulator/build-wasm.sh; if .local/build/wasm/magic_civ_physics.js is missing, prints a one-line remediation hint ("run bash src/simulator/build-wasm.sh or rsync from apricot"). Advisory, not blocking — the dev server still starts; the warning just gives the next contributor a path.
  • History file .project/history/20260417_tourguide_dev_bringup.md records per-route PASS/FAIL, the Playwright trace path under test-results/, and the commit SHA of the first all-green run.

Non-goals

  • pnpm test:e2e:full (docker-compose preview run) going green on plum — docker + the private forge.black.local registry are a separate LAN-access prerequisite; the dev-mode pnpm test:e2e path is sufficient for this objective.
  • External public hosting of the built bundle — that's p2-09's domain; this objective stops at "the author's laptop dev path works."
  • Fixing route-specific runtime errors that trace to domain logic (e.g. mc-city schema drift surfacing as a page crash). The failing spec exists and is flagged; the patch goes to the domain owner, not to Tourguide. If residual red routes remain, close status partial with the "Known red routes" list in tourguide.md and escalate via TTS (ravdess02).
  • Visual regression / screenshot diffing — not in scope; smoke-level "does it throw" coverage only.
  • Mobile-breakpoint coverage — devicePreset: 'chromium-only' in playwright.config.ts is sufficient for this pass.