Closes#8. Real ship systems that spend the cargo hold, plus versioned idempotent save backfill so old saves survive future features without DB wipes.
Backfill plumbing (root-cause fix)
schema_version on saves (NULL = v1) + ALTER TABLE guard for pre-existing files; ordered idempotent steps in ensureSave: v2 bodies for systems lacking them, v3 starting crew if none, v4 starting ship if none — all deterministic from the save seed, so a backfilled save is identical to a fresh one
Ship systems
ship_systems (type/level/capacity, UNIQUE per type; built = level > 0); starting ship: HULL, REACTOR, LIFE SUPPORT, NAV COMPUTER, COMMS ARRAY at LV1/CAP2, WEAPONS unbuilt
Actions (each +1 turn + event): UPGRADE level×resource → MAX_LEVEL 5 · EXPAND capacity×resource → MAX_CAPACITY 10 · BUILD flat 3 parts, once per type; costs in pure lib/game/ship-costs.ts shared by API and UI; 404/409/422 validation with no mutation on failure
API: GET /api/ship + POST /api/ship/{upgrade,expand,build}; OpenAPI updated (10 paths)
UI: SHIP SYSTEMS tab on live data — real cards, buttons disabled when unaffordable/capped; left column StatusGrid + VESSEL METRICS bars now driven by real values (placeholder constants removed for both)
Tests: unit 38→50 (backfill idempotency/determinism vs fresh gen, exact oldest-first deduction, caps, build-once, no-mutation failures), e2e 11→12 (bounded scan loop → affordable action via UI button → card + left column reflect it; full ship state deep-equal across the mid-run container restart)
Local verification: tsc ✓, vitest 50/50 ✓, playwright --list ✓, next build clean (7 tab triggers present).
Closes #8. Real ship systems that spend the cargo hold, plus versioned idempotent save backfill so old saves survive future features without DB wipes.
**Backfill plumbing (root-cause fix)**
- `schema_version` on `saves` (NULL = v1) + ALTER TABLE guard for pre-existing files; ordered idempotent steps in ensureSave: v2 bodies for systems lacking them, v3 starting crew if none, v4 starting ship if none — all deterministic from the save seed, so a backfilled save is identical to a fresh one
**Ship systems**
- `ship_systems` (type/level/capacity, UNIQUE per type; built = level > 0); starting ship: HULL, REACTOR, LIFE SUPPORT, NAV COMPUTER, COMMS ARRAY at LV1/CAP2, WEAPONS unbuilt
- Actions (each +1 turn + event): UPGRADE `level`×resource → MAX_LEVEL 5 · EXPAND `capacity`×resource → MAX_CAPACITY 10 · BUILD flat 3 parts, once per type; costs in pure lib/game/ship-costs.ts shared by API and UI; 404/409/422 validation with no mutation on failure
- **API:** GET /api/ship + POST /api/ship/{upgrade,expand,build}; OpenAPI updated (10 paths)
- **UI:** SHIP SYSTEMS tab on live data — real cards, buttons disabled when unaffordable/capped; left column StatusGrid + VESSEL METRICS bars now driven by real values (placeholder constants removed for both)
- **Tests:** unit 38→50 (backfill idempotency/determinism vs fresh gen, exact oldest-first deduction, caps, build-once, no-mutation failures), e2e 11→12 (bounded scan loop → affordable action via UI button → card + left column reflect it; full ship state deep-equal across the mid-run container restart)
Local verification: tsc ✓, vitest 50/50 ✓, playwright --list ✓, next build clean (7 tab triggers present).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #8. Real ship systems that spend the cargo hold, plus versioned idempotent save backfill so old saves survive future features without DB wipes.
Backfill plumbing (root-cause fix)
schema_versiononsaves(NULL = v1) + ALTER TABLE guard for pre-existing files; ordered idempotent steps in ensureSave: v2 bodies for systems lacking them, v3 starting crew if none, v4 starting ship if none — all deterministic from the save seed, so a backfilled save is identical to a fresh oneShip systems
ship_systems(type/level/capacity, UNIQUE per type; built = level > 0); starting ship: HULL, REACTOR, LIFE SUPPORT, NAV COMPUTER, COMMS ARRAY at LV1/CAP2, WEAPONS unbuiltlevel×resource → MAX_LEVEL 5 · EXPANDcapacity×resource → MAX_CAPACITY 10 · BUILD flat 3 parts, once per type; costs in pure lib/game/ship-costs.ts shared by API and UI; 404/409/422 validation with no mutation on failureLocal verification: tsc ✓, vitest 50/50 ✓, playwright --list ✓, next build clean (7 tab triggers present).