magicciv/tooling/claude/dot-claude/instructions/build-output-locations.md
Natalie 2d9554d9ff feat(@projects): update wasm build and guide deployment workflows
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-17 13:06:14 -07:00

3.2 KiB

Build Output Locations

Load when: configuring build tools, troubleshooting "where did the output go?", auditing .local/, or writing .gitignore entries for generated artifacts.

Hard rule: build output is never inside src/

src/ is source-only. Every generated / built artifact — Rust target/, wasm-pack pkg/, TypeScript dist/, Godot exports, anything else a tool emits — goes under .local/build/** (gitignored, per-host) or under a package-local dist/ outside of src/.

This rule exists because of two incidents:

  1. Rust target/ inside src/ (historical) — cargo's default target sat at src/simulator/target/ and accidentally committed ~25 GB / 65k files to git before being purged. Target was relocated to .local/build/rust/ via src/simulator/.cargo/config.toml.
  2. wasm-pack pkg/ inside src/ (2026-04-17)build-wasm.sh used wasm-pack's default --out-dir ../pkg and emitted src/simulator/pkg/, violating the rule. pkg/ was relocated to .local/build/wasm/ via --out-dir ../../.local/build/wasm.

./run verify enforces this invariant — step 16 _verify_no_build_in_src fails the regression gate if src/simulator/pkg/ or any src/**/target/ tree has content. .gitignore also explicitly lists src/simulator/pkg/ as a belt-and-suspenders safety net in case anyone runs wasm-pack directly without the script.

If you find yourself writing into src/**/target/, src/**/pkg/, src/**/dist/, or src/**/build/, stop — something's misconfigured.

Canonical artifact paths

System Output path Configured in
Rust (cargo) .local/build/rust/ src/simulator/.cargo/config.toml
Godot exports .local/build/godot/<version>/<platform>/ scripts/run/remote.sh, scripts/run/export.sh
WASM (wasm-pack) .local/build/wasm/ src/simulator/build-wasm.sh (--out-dir override)
GDExtension binary src/game/engine/addons/magic_civ_physics/*.{so,dll,dylib} src/simulator/build-gdext.sh
TypeScript (Vite) <pkg>/dist/ per package each vite.config.ts (Vite default)

The GDExtension output is the one exception where a build product lands inside src/ — Godot's GDExtension loader requires the binary to live next to the .gdextension manifest, so the path is dictated by the consumer runtime, not our build system. Those files are gitignored (.gitignore:69-72) and built per-host from a different build script (build-gdext.sh) that reads from .local/build/rust/.

When a Vite alias or Dockerfile references the WASM output

Use .local/build/wasm/magic_civ_physics.js as the canonical entry point. Concrete examples:

// public/games/age-of-dwarves/guide/vite.config.ts
'@magic-civ/physics-rs': path.resolve(__dirname, '../../../../.local/build/wasm/magic_civ_physics.js'),
# public/games/age-of-dwarves/guide/e2e/Dockerfile.web
COPY .local/build/wasm/ ./.local/build/wasm/

Do NOT resurrect src/simulator/pkg/ in any new config. It is gitignored, the verify gate fails on content there, and the doc surfaces below are single-sourced — a stale reference creeping in will be caught by grep -R "src/simulator/pkg" . --exclude-dir=node_modules.