# CLAUDE.md — U R M03 Godot 4 game project. Science-fiction rogue-lite: strategy-forward mech auto-battler with a light action layer and a nurturing base-builder meta. ## Persistent memory `persistent-memory.md` at the repo root captures durable intent and supporting evidence (goals, decisions, foot-gun warnings, in-flight state) across context resets. Read it at session start; treat it as one input alongside this CLAUDE.md and the auto-memory system, not as the single source of truth. It is a lean **index**: the dated log sections keep each over-threshold entry's full body in `persistent-memory.d/.md`. Pull a detail file only when its index line is relevant to your work — never bulk-read `persistent-memory.d/`. When you commit, include any pending `persistent-memory.md` and `persistent-memory.d/` updates in the same commit (stage them alongside whatever else is being committed). Never leave them as a floating uncommitted change while shipping other work — durable memory that lags the code defeats its own purpose. ## Design canon (read before designing anything) The design documents are canonical and live in the advisor repo, NOT here: | Document | Canonical for | |---|---| | `~/development/advisors/game-design/concept/mechatronics/CONCEPT.md` | All systems: loop stack, run skeleton, tag grammar, chemistry table, encounter grammar, base, economy, campaign | | `~/development/advisors/game-design/concept/mechatronics/MOE.md` | M03 ("Moe") — character bible, design law, scenes | Where they conflict: MOE.md wins for Moe, CONCEPT.md for systems. Design decisions are made in those documents first, then implemented here. Do not fork design decisions in this repo; propose changes against the advisor repo's docs. Non-negotiable canon highlights (full rationale in CONCEPT.md): - **ONE BOT** — the cast is M03, Khoe, and rescued humans. No other friendly mech, ever. Build variety rides in RIGS. - **No immunities, no healing enemies, ever** (the invincibility laws). Susceptibilities only; damage dealt is progress banked. - **Two-solutions rule** — every encounter answerable by brute force AND by the read; cleverness pays only in speed, safety, spectacle. - **Combos produce verbs, not multipliers.** Every chemistry row is a visible event, learnable by seeing it once. - **No tutorial, ever.** The base's growth order is the curriculum. - **Siege/base-defense mode: permanently rejected.** Do not build, do not re-propose. ## Design questions — where answers live, in order 1. **CONCEPT.md / MOE.md** (paths above) — most questions are already settled there; check the decisions log and § Open questions before re-deriving anything. 2. **The advisor repo's persistent memory** — `~/development/advisors/game-design/persistent-memory.md` — for context, foot-guns, and tried-and-abandoned ideas. 3. **The book, via the KB.** Load-bearing design-theory claims ground in Jesse Schell, *The Art of Game Design* (3rd ed.), retrievable live: ```bash cd ~/development/advisors/game-design source env.sh # gitignored credentials; if missing, see env.sh.template there uv run --with httpx python kb_query.py "your query" --title "Art of Game Design" ``` Always pass `--title "Art of Game Design"` (mixed corpus). Use distinctive tokens (lens names, Schell's coined terms), not broad words. Confidence buckets: high ≥ 0.030, medium ≥ 0.016. **Honesty discipline (hard floor): quote what the KB returns; if it doesn't surface the claim, say so — never confabulate "Schell says."** An empty result means retrieval missed, not that the book lacks it. Full retrieval guidance: the advisor repo's CLAUDE.md. Foot-gun: env.sh carries a borrowed Worldtree key (ratatoskr's); HTTP 401 means it rotated — fix documented in env.sh's header. ## Engine - **Godot 4.7.1-stable, pinned.** Both dev machines run `4.7.1.stable.official.a13da4feb` (Mac editor: `/Applications/ Godot.app` + `godot` shim; nh3-dev headless: `~/bin/godot`). Do not upgrade unilaterally — version skew rewrites scene files. An upgrade is an operator decision applied to both machines at once. - Headless verification: `godot --headless` works on nh3-dev for scripts, tests, and imports. Smoke gate: `~/bin/godot --headless --path . res://tests/smoke.tscn` (exit 0 pass / 1 fail; run 3x to catch flakes). After adding scenes/assets, import first: `~/bin/godot --headless --import --path .` - **Generated sidecars ship with their sources.** Run the headless import BEFORE committing new scripts/assets so `.uid` / `.import` sidecars land in the same commit — otherwise the other machine's editor mints untracked copies and its next `git pull` refuses to merge. Enforced on nh3-dev by a local `.git/hooks/pre-commit` (not versioned — recreate on fresh clones: refuse staged-new `.gd` without a tracked `.uid`). - **Aseprite headless on nh3-dev**: `~/bin/aseprite` (1.3.18.2, operator-licensed source build; tree at `~/src/aseprite`, skia m124 at `~/deps/skia`). Sprite pipeline: `aseprite -b --script tools/aseprite/gen_sprites.lua` from the repo root; the Pillow previewer `tools/aseprite/preview.py` renders pixel-identical PNGs from the same maps (verified 2026-08-14). - **Two-machine hygiene (Mac editor side):** pull BEFORE opening the editor after new commits land. If a pull ever refuses over generated sidecars anyway, they're safe to delete wholesale: `git clean -f '*.uid'` (add `'*.import'` if named) — then pull. **If a pulled scene runs black / actors invisible / no input** (stale local import cache): quit the editor, `rm -rf .godot`, pull, reopen, and let the reimport bar finish BEFORE pressing Play. The `.godot/` cache is gitignored and fully regenerable. - **Code-created sprites/resources use runtime `load()`, never `preload()`.** `preload` is a compile-time dependency: if the cross-machine import cache is stale, it fails at parse time and kills the whole script (movement + logic gone, not just the texture). `load()` degrades a missing resource to a null texture and keeps the script alive. (Lesson paid 2026-08-14, commit `62e86f9`.) - GDScript for design iteration; C# reserved for hot paths (none yet). - 2D, pixel-first: integer scaling, nearest-neighbor filtering (set in project.godot). Hi-bit mixed-res effects layer comes later. Actors now use `_ph` placeholder sprites (hand-authored pixel maps in `tools/aseprite/maps/`, rendered to `assets/sprites_ph/`); arena floor/walls, HUD, and FX stay primitives. Real art (watercolor scenery + pixel sprites, CONCEPT.md § Tech & art direction) comes at the art pass — placeholders only, no polish, until then. ## Current phase: GREYBOX (v1 per ROADMAP.md) The falsifier slice, specced in CONCEPT.md § Encounter grammar: one arena · one auto-fire KINETIC weapon · two cards (HEAT + KINETIC) · the KINETIC+HEAT chemistry row (knock a heated enemy into others → heat spreads on impact) · two enemy types (untagged grunt swarm + self-heating burster). It exists to falsify three bets: positioning ↔ build interaction, card-freeze rhythm, chemistry delight. Greybox art: `_ph` placeholder pixel sprites for actors, primitives for arena/HUD/FX — no polish; the real art pass comes later.