Merges the pre-existing avatar system implementation (catalog, slot registry, loadout, glTF-based loader, customization UI, visualizer -- ~2300 lines across scripts/avatar/) onto current main, which had diverged significantly since this branch was last touched (PC1 UI fixes, PC2's playable level/player/multiplayer work). Fixes found while integrating: - project.godot had wholesale-replaced the [autoload] section again (same recurring pattern as the multiplayer server/client branches), dropping the ApiClient autoload entirely. Restored it additively alongside AvatarSystem. - All other real conflicts (main_menu.tscn/.gd, main.tscn, .godot cache) were pure "this branch re-created a stale duplicate of something main already has" -- resolved by taking main's version, confirmed via `git diff` that this task's own changes never touched those files' actual logic. New: scripts/smoke_test_avatar_system.gd -- confirms AvatarSystem is a real autoload, the committed catalog.json parses, loadout equip/ validate/JSON-round-trip works against real catalog entries, and -- since assets/avatars/*.glb model files don't exist yet -- that AvatarLoader.load_base_body() fails gracefully (null + load_error signal) rather than crashing when given a real catalog entry with no backing file. 10/10 passing. Verified no regressions: all 10 pre-existing Godot smoke suites still pass against a live backend, and all 61 backend pytest tests pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6rUEynmv2QmweocAQYARN
Testing at Package Checkpoints
A Package Checkpoint (PC1, PC2, ...) is a periodic review point — every few
real milestones, the client and server builds get packaged together and
independently reviewed before anyone calls anything actually done. See
project_agp in Claude's memory, or ask, for the full definition; this
doc is just the mechanical "how do I run the tests" part of that review.
Running the suite
python scripts/run_checkpoint_tests.py
Brings up a throwaway Postgres, runs Alembic migrations against it, runs the
backend pytest suite, starts the backend server, and runs every Godot
headless smoke test (scripts/smoke_test_*.gd) against it. Tears the
Postgres container down afterward (--keep-postgres to skip that if you
want to poke at the DB after a failure).
If port 5432 is already taken on the machine, pass --postgres-port with
something else.
Exit code is 0 only if everything that actually ran passed — suites with nothing to run yet (no Godot binary found, no smoke test scripts yet) are reported SKIPPED, not treated as a failure.
What this does and doesn't prove
Passing this script means: migrations apply cleanly to a genuinely empty
database, the backend's unit-level logic is correct, and whatever Godot
smoke tests exist actually round-trip against a live backend. It does
not mean full endpoint/integration coverage exists — see
test_inventory.md for the current, honest list of what's tested and what
isn't. A checkpoint review should still involve reading the actual diffs
for anything this script's current coverage doesn't reach, not just running
green and calling it done.
Growing this over time
As real integration tests get added (endpoint tests hitting the FastAPI app,
more Godot smoke coverage beyond health_check), they should land under
backend/tests/ / scripts/smoke_test_*.gd respectively — this script
picks up new files automatically, nothing to register by hand. Update
test_inventory.md's tables when you do, so the inventory stays a source
of truth instead of quietly going stale.
Eventual goal (not implemented yet): gate merges to main on this script
passing, the same way a real CI pipeline would. For now it's a manual step
run at checkpoint review time.