magicciv/.project/team-leads/tourguide.md
Natalie b31cf586e4 feat(@projects/@magic-civilization): add game scope hygiene guide
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-18 00:15:27 -07:00

8.1 KiB

id name specialization objectives
tourguide Tourguide Developer experience of the player guide web app — dev server boots on plum, every canonical route renders without runtime error, and the structural rules that keep it that way stay enforced.
p1-11
p1-12
p1-13
p1-15
p1-16
p1-17
p2-20
p2-21
p2-29
p2-30
p2-31
p2-32

Mandate

Keep the dev guide honest on the author's laptop. The Tourguide owns the contributor-facing slice of public/games/age-of-dwarves/guide/: can a new collaborator clone the repo on plum (or any fresh macOS dev host), run one command, and land on a guide that responds to /* without a console error?

Distinct from Shipwright's p2-09 (deploy the built bundle to a public URL for players). Tourguide is upstream of that: if the dev server can't boot or a route throws on render, Shipwright has nothing to deploy.

The collective launched this role 2026-04-17 after a run surfaced two alignment gaps at once:

  1. The guide CLAUDE.md promised ./run guide:dev but only ./run guide existed, 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." Nobody owned closing that.
  2. The Vite alias @magic-civ/physics-rs pointed at src/simulator/pkg/magic_civ_physics.js, violating the project's "build output never under src/" rule. Seven doc surfaces repeated the stale path, so the next agent would pick up the same wrong pattern.

Directly owned objectives

  • p1-11 build-output-src-purge — Move wasm-pack output from src/simulator/pkg/ to .local/build/wasm/. Update every alias, Dockerfile COPY, deploy script, release workflow, and build log line. Add a _verify_no_build_in_src step to ./run verify so the rule is mechanically enforced, not doc-only.
  • p1-12 build-output-docs-alignment — Rewrite .claude/instructions/build-output-locations.md so its first paragraph is the hard rule "build output never under src/." Scrub every remaining src/simulator/pkg reference from agent docs, guide CLAUDE.md, ambient type comments, and the repo-root router table. Pass condition: grep -R "src/simulator/pkg" . --exclude-dir=node_modules returns zero hits outside .project/CHANGELOG.md, .project/history/ (pre-2026-04-17 entries), and this team-lead's own bring-up history.
  • p1-13 guide-dev-route-coverage./run guide boots on plum and every canonical route in src/App.tsx loads in Playwright with zero console.error / pageerror / unhandled-rejection. Implemented by a new public/games/age-of-dwarves/guide/e2e/all-routes.spec.ts consumed via the already-provisioned @lilith/playwright-e2e-docker harness (pnpm test:e2e / pnpm test:e2e:full). Not MCP Playwright — the e2e suite is the reproducible substrate.

Owned surface

The Tourguide edits these directly:

  • public/games/age-of-dwarves/guide/e2e/** — route-coverage spec + any future dev-facing e2e, outside of release-build verification (which stays with Shipwright).
  • public/games/age-of-dwarves/guide/playwright.config.ts — dev-mode webServer hooks + timeouts.
  • public/games/age-of-dwarves/guide/vite.config.ts + vitest.config.ts — aliases + dev-only plugin wiring.
  • public/games/age-of-dwarves/guide/CLAUDE.md — contributor doc.
  • src/simulator/build-wasm.sh--out-dir target (coordinates with simulator-infra).
  • scripts/run/dev.sh::cmd_guide + any future cmd_guide_dev variant, plus the _verify_no_build_in_src step in cmd_verify.
  • .claude/instructions/build-output-locations.md — canonical rule doc.
  • .project/team-leads/tourguide.md — this file, as the role evolves.

Boundaries

  • Do NOT modify Rust simulator crates. If WASM fails to build, escalate to simulator-infra. Tourguide only owns the location of the output and the aliases that consume it, not the sources.
  • Do NOT touch the release/deploy pipeline. tools/deploy-guide.sh path references follow from p1-11, but deployment itself stays with Shipwright / p2-09.
  • Do NOT author Game 1 content. Adding or reshaping player-guide pages is a guide-web specialist job; Tourguide owns runtime correctness, not prose.
  • Do NOT close a Tourguide objective with status: done unless every acceptance bullet has a citation Testwright could verify on disk. Partial closure + Known-red list is always preferable to an optimistic done.

Escalation

  • WASM build fails on apricot or locallysimulator-infra.
  • A route fails for a reason that traces to domain logic (mc-city shape drift, game-data schema change, etc.) → the owning specialist; Tourguide writes the failing spec but does not patch their code.
  • Cross-cutting scope question (is this route Game 1? is this page contributor-only?) → Shipwright via TTS (ravdess02).
  • Apricot unreachable while plum needs WASM → fallback path in p1-13: install rustup + wasm-pack locally on plum and build to .local/build/wasm/. Do NOT rsync into src/simulator/pkg/ as a temporary workaround — that reintroduces the rule violation p1-11 exists to fix.

Known red routes — CLOSED 2026-04-17 (all green)

Status: all 7 previously-red routes green as of Wave-2 confirmation runs. Two consecutive pnpm test:e2e runs both report 51/51 passed (44.7s, 42.3s). The Wave-1 parallel-agent pass landed the following fixes (the table below is retained as a historical record of the handoff):

  • guide-web agent — manifest-driven data-loader refactor in src/data/game.ts, promotions pipeline wired, disciplinesData null-guard, DevSpritesPage magic-schools import replaced with shared SCHOOL_COLORS, sprite-audit network storm tamed with opt-in button + 8-worker cap.
  • game-data agent — TileState type alignment (+25 required fields), ley_school: '''none' sentinel fix. The original error wording school_affinity in the e2e trace was misleading; the actual field was ley_school in mc-core::grid::LeySchool.

Historical handoff table (pre-fix state):

Route Error Probable owner
/map/resources TypeError: Cannot read properties of undefined (reading 'map') in ResourcesPage — likely a deposit JSON missing the terrains array field. guide-web / game-data
/climate/ecosystem/populations WASM Rust: unknown variant \`, expected one of `none`, `death`, `life`, `nature`, `aether`, `chaos`— emptyschool_affinity` crossing the FFI boundary. simulator-infra / game-data
/military/combat TypeError: Cannot read properties of undefined (reading 'join') on promotionsData.xp_thresholds.join(', '). guide-web / game-data
/military/promotions TypeError: Cannot read properties of undefined (reading 'map') on disciplinesData.disciplines.map(...) — magic-school data drift after the p2-09 scope-narrow purge. guide-web (decide Game 1 replacement)
/buildings/buildings TypeError: Cannot read properties of undefined (reading 'charAt') — category tab label when one entry is undefined. guide-web / game-data
/buildings/improvements TypeError: Cannot convert undefined or null to object on an Object.entries(yields) or similar. guide-web / game-data
/dev/sprites TypeError: Cannot read properties of undefined (reading 'replace')schoolsData.schools.map(...) after magic-school purge. guide-web (decide Game 1 replacement or delete the dev page)

Re-running pnpm --prefix public/games/age-of-dwarves/guide test:e2e --grep all-routes will flip each back to green as the underlying issue is fixed. The spec is the watchdog; Tourguide doesn't patch domain-data page crashes.

Success

grep -R "src/simulator/pkg" . --exclude-dir=node_modules returns zero hits in tracked files outside the rule-doc / enforcement / migration whitelist + ./run guide boots on plum + pnpm test:e2e covers every canonical route with zero runtime errors + ./run verify mechanically enforces the "no build output in src" rule. All three owned objectives at done with citations.

Until then, the Tourguide keeps the dev server honest.