Reported directly by the user after seeding a test world through the browse-worlds screen: "screen is blank now". Two compounding layout bugs, both real: 1. world_list.tscn's root VBoxContainer had no anchors at all, only size_flags -- but its parent (the scene's root node) is a plain Control, not a Container, so size_flags on a Control's direct child are meaningless there. Without anchors it never actually filled the screen, so it (and everything under it) collapsed toward zero size. 2. size_flags_horizontal/vertical used the raw integer 4 everywhere expand-fill was clearly intended (ScrollContainer, its WorldList child, HeaderHBox, TitleLabel) -- but 4 is Control.SIZE_SHRINK_CENTER in Godot 4, not SIZE_EXPAND_FILL (which is 3). ScrollContainer with SHRINK_CENTER takes only its own minimum size instead of expanding, cascading a ~1px width down through every card and every label. Confirmed the actual enum values by asking Godot directly rather than assuming. Both are exactly the kind of bug a headless smoke test checking only "did cards get added to the tree" can't catch -- child_count was correctly non-zero, nothing crashed, the content was just rendered invisibly thin. Verified the fix is real by deliberately reintroducing bug #2 and confirming the test now correctly fails (card width 25px, below the 200px sanity threshold) before restoring it. Also replaced the card background: it was a ColorRect manually moved to child index 0 of a VBoxContainer, which doesn't work as an overlay -- a VBoxContainer lays out ALL its children in sequence, so the "moved to front" ColorRect rendered as an empty dark bar ABOVE the text, not behind it. Now a proper PanelContainer with a StyleBoxFlat background, the idiomatic way to get a colored panel behind auto-laid-out content in Godot. smoke_test_world_list.gd strengthened to actually catch this class of bug going forward: seeds a real world via POST /api/worlds/ first (the checkpoint runner's fresh DB meant the populated-card path never ran in CI at all before this, only empty-list did), and asserts each card's real computed width, not just that cards exist. Full checkpoint suite re-verified clean on this branch: migrations, 68/68 pytest, all 6 Godot smoke tests, both platform exports. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.