Files
SpaceWanderer/CHANGELOG.md
T
kamilkrzywda dcaeb4dded
CI / build + unit + e2e (pull_request) Successful in 3m2s
release v0.6.0
2026-09-28 23:47:37 +00:00

12 KiB
Raw Blame History

Changelog

v0.6.0 — 2026-09-28 23:46

  • SHIP SYSTEMS tab — expand / upgrade / build ship systems + save backfill plumbing (issue #8): the first spend-side game loop on top of issue #7's crew, plus a root-cause fix for saves created by older code lacking data newer code seeds. Single-player, no auth, by design.
  • Backfill plumbing: schema_version INTEGER added to saves (NULL = v1). ensureSave now runs ordered IDEMPOTENT backfill steps for anything below current — v2: every system without planets gets its generated bodies (same (seed, systemId) derivation as fresh generation), v3: starting crew if no rows. New games get the current version directly. lib/db/client.ts open() carries an idempotent ALTER TABLE ... ADD COLUMN guard for files created before the column existed — old saves open fine and backfill on first read, so DB wipes are no longer needed when deploying new versions.
  • New table (lib/db/schema.ts + DDL): ship_systems (id/save_id/type/level/capacity, UNIQUE(save_id,type)). built is derived, not stored — level > 0 means built; unbuilt rows sit at level/capacity 0. Starting ship seeded on new game AND as backfill step v4: core types (HULL, REACTOR, LIFE SUPPORT, NAV COMPUTER, COMMS ARRAY) built at base values, WEAPONS unbuilt until a build action.
  • Cost model (lib/game/ship-costs.ts, pure — imported by both the API and the UI so affordability can't drift): UPGRADE costs level units of any resource (capped at MAX_LEVEL 5), EXPAND costs capacity units of any resource (capped at MAX_CAPACITY 10), BUILD costs a flat 3 parts. Consumption takes from the oldest cargo row of the required kind first, deleting rows that hit zero; an unaffordable action mutates nothing.
  • Ship actions (lib/game/ship.ts): upgradeSystem / expandSystem / buildSystem — validate (404 unknown id/type, 409 not built / already built / at cap, 422 insufficient inventory), spend the cost, bump level/capacity or build at base values, cost one turn and write an event each.
  • New endpoints: GET /api/ship → {systems:[{id,type,level,capacity,built}],inventory,turn}; POST /api/ship/upgrade {systemId}, POST /api/ship/expand {systemId}, POST /api/ship/build {type} — each returns the fresh ship state. OpenAPI spec in code updated (10 paths).
  • SHIP SYSTEMS tab now renders REAL data: cards show type + level/capacity with UPGRADE / EXPAND buttons per built card and BUILD NEW for unbuilt types, disabled when unaffordable or capped; each action's response is applied directly (no polling). Left column mirrors live state too — the SHIP SYSTEMS panel lists every system with its status/level/capacity + an N ONLINE badge, and VESSEL METRICS bars are driven by real values (hull/reactor from system levels, crew roster vs a cap of 6). Placeholder constants for both removed; other tabs keep theirs until their issues land.
  • Tests: unit — backfill upgrades a hand-built v1 save in place (deterministic vs fresh generation, idempotent), starting ship seeding, cost validation with no mutation on failure, exact oldest-first inventory deduction, level/capacity caps, build-once, turn + event per action; e2e — SHIP SYSTEMS tab performs one affordable UPGRADE/BUILD via the UI after a bounded scan loop until something is affordable (asserting card + left column reflect it), and ship state survives the mid-run container restart.

v0.5.0 — 2026-09-28 22:51

  • CREW tab — crew roster with good/bad traits (issue #7): the ship's people on top of issue #6's exploration loop. Single-player, no auth, by design. Display + arrival only — no dismiss/assign actions yet.
  • New table (lib/db/schema.ts + DDL in lib/db/client.ts): crew (id/save_id/name/role/trait_good/trait_bad/origin). Origin is 'STARTING CREW' for the seeded crew or ', ' for members found while exploring.
  • Pure seeded crew generation (lib/game/crew.ts, same pattern as world.ts): name pools (16 first × 22 last, unique per roster), role pool of 8, good/bad trait pools of 10 each. generateStartingCrew gives a new game 2–3 members with unique names and roles; rollCrewMember finds a joining member on ~18% of scans (CREW_CHANCE = 0.18).
  • Starting crew is seeded in ensureSave from the save seed via startingCrewRng(seed) — same per-save derivation pattern as bodies/exploration, so a given seed always starts with the same crew.
  • Exploration extended: the crew roll draws from the SAME per-planet rng stream as the resource/part haul (called after it in explorePlanet), so outcomes stay deterministic per save+planet and existing hauls are unchanged. Found members join the roster with origin = ', '; each body can only be scanned once, so no duplicate joins.
  • New endpoint: GET /api/crew → [{id,name,role,trait_good,trait_bad,origin}] in join order (auto-initializes like the others). POST /api/explore responses now also carry crewFound (the joining member or null). OpenAPI spec in code (lib/openapi.ts) updated for both.
  • CREW tab now renders REAL data: fetches /api/crew on mount (Radix unmounts inactive tabs, so opening the tab always refetches — no polling), cards show name + role, the good (+) and bad (−) traits and an ORIGIN line. Placeholder crew constants removed for this tab only — other tabs keep theirs until their issues land.

v0.4.0 — 2026-09-28 22:17

  • LOCAL SYSTEM tab — planet list + exploration to find things (issue #6): the first in-system game loop on top of issue #5's save/world foundation. Single-player, no auth, by design.
  • New tables (lib/db/schema.ts + DDL in lib/db/client.ts): planets (id/system_id/parent_id/name/type/hazard/explored — planets have parent_id NULL, moons point at their planet) and inventory_items (id/save_id/kind[name]/qty — the dumb-simple cargo hold SHIP SYSTEMS (#8) will spend from later).
  • Planet generation hooks into world gen (lib/game/world.ts, pure + seeded): each system gets 2–5 planets, some with 1–3 moons, generated when the system is inserted via bodyRng(seed, systemId) — so a given system always has the same bodies regardless of order. Bodies are stored in display order (a moon follows its parent row).
  • Exploration (lib/game/save.ts): explorePlanet rolls a deterministic haul from explorationRng(seed, planetId) — a resource and/or a part (qty), or nothing (~21% of scans) — marks the body explored (each once), costs a turn, accumulates finds into inventory (same kind+name bumps qty) and writes an explore event.
  • New endpoints: GET /api/system → { systemId, systemName, planets[{id,name,type,hazard,explored,parent}], inventory, turn }; POST /api/explore {planetId} → fresh system state + outcome (400 malformed body, 404 unknown planet, 409 already explored). OpenAPI spec in code (lib/openapi.ts) updated for both.
  • LOCAL SYSTEM tab now renders REAL data: fetches /api/system on mount, draws the staggered body list (planets base level, moons indented + dimmed with their parent's name), badges reflect real state (UNEXPLORED / SCANNED / HAZARD) and an EXPLORE button per unexplored row; explore responses apply directly (no polling). A CARGO HOLD panel shows the live inventory. Placeholder constants removed for this tab only — other tabs keep theirs until their issues land.

v0.3.0 — 2026-09-28 21:35

  • World generation + jump between solar systems (issue #5): the game save, DB schema, turn counter and event writing that all later tabs build on. Single-player by design — one save row, no auth/accounts.
  • New tables (lib/db/schema.ts + DDL in lib/db/client.ts): saves (id/seed/turn/created_at), solar_systems (name, x/y chart position, discovered, is_current), jump_routes (directed pairs, both directions stored for single-row adjacency lookups), events (append-only log: new-game + jump events so far).
  • Seeded world generation (lib/game/world.ts, pure functions): a save's seed deterministically generates the starting system plus a ring of six undiscovered neighbours with jump routes; jumping into an undiscovered system grows the chart with four more neighbours around it, so there is always somewhere to jump and a route back.
  • Save lifecycle (lib/game/save.ts): auto-initializes on first API hit when no save exists, exposes world state, validates jumps (adjacency required — non-adjacent/unknown rejected), sets current, increments the turn counter, writes events, persists durably.
  • New endpoints: GET /api/world → { systems, edges, turn }; POST /api/jump { systemId } → fresh world state (400 malformed body, 404 unknown system, 409 not adjacent). OpenAPI spec in code (lib/openapi.ts) updated for both.
  • WORLD MAP tab now renders REAL data: fetches /api/world on mount, draws the live NodeGraph (current = ACTIVE/CURRENT, discovered = NEUTRAL/DISCOVERED, unknown = OFFLINE/UNKNOWN) with a jump button per adjacent system; placeholder map constants removed for this tab only — other tabs keep their placeholders until their own issues land.

v0.2.2 — 2026-09-28 21:02

  • LOCAL SYSTEM tab: explorable-worlds list now staggers moons under their parent planet (indented rows) — ASHFALL attached under BRIMSTONE, new PALEMOON moon under AURELLE; badges unchanged.

v0.2.1 — 2026-09-28 20:22

  • LOCAL SYSTEM tab: removed the system node graph (star/planets/moons) — the tab now shows only the explorable-worlds list at full panel width. WORLD MAP keeps its node graph; components/ui/node-graph.tsx unchanged and still in use there.

v0.2.0 — 2026-09-28 19:19

  • Game interface template (visual only, zero game logic): the operations panel in components/mission-control.tsx is now seven tabs — WORLD MAP (NodeGraph of 10 placeholder solar systems linked by jump routes), LOCAL SYSTEM (NodeGraph of star + planets/moons plus an explorable-worlds list), CREW (crew cards with name/role and good/bad trait placeholders), SHIP SYSTEMS (system cards with inert EXPAND / UPGRADE / BUILD NEW affordances), SKILL TREE (tech cards unlocking new system builds/upgrades), MISSIONS (previous NEXT MISSION content), EVENT LOG (ship log terminal). All data is local placeholder constants.
  • Left column: VESSEL METRICS progress rings replaced with scificn Progress bracket bars; SHIP SYSTEMS status panel, header stat cards and right column unchanged.
  • New scificn-ui components copied into components/ui/: NodeGraph, Progress (+ @radix-ui/react-progress dependency).

v0.1.0 — 2026-09-28 15:47

  • Initial scaffold (stack proof): base stack copied/adapted from Flight-Ops (../flight) — Next.js 16 App Router + React 19 + TypeScript strict, bun package manager, Node 22 in CI/Docker.
  • Single-player only by design: NO auth/accounts/multiplayer anywhere (Flight-Ops's users/sessions/admin/leaderboard patterns deliberately not copied).
  • Frontend component layer: scificn-ui v0.1.0 integrated copy-paste (Radix + Tailwind v4, SCI-FI theme) — Button, Panel, Badge, Card, Alert in components/ui/; theme tokens in app/globals.css with a brightened --text-muted override (#4A4A40 → #6B6B5C).
  • Interface base: the scificn-ui Mission Control showcase (https://www.scificn.dev/showcase/mission-control) rebuilt as the app's main UI — app/page.tsx renders components/mission-control.tsx (client dashboard: sticky header, stat-card row, 3-column grid of Panel/Tabs/StatusGrid/ProgressRing/BarChart/LineChart/Terminal panels, sticky footer), placeholder ship content only, no game logic; additional upstream components copied into components/ui/ (Tabs, StatCard, Terminal, StatusGrid, ProgressRing, BarChart, LineChart) + @radix-ui/react-tabs dependency.
  • DB plumbing: SQLite via Drizzle ORM + sql.js (WASM) at db/space-wanderer.db, volume-mounted; empty schema placeholder — game tables land with the first game systems.
  • API pattern established: /api/version + OpenAPI 3.x spec generated in code (lib/openapi.ts) served at /api/openapi.
  • CI/e2e/docker pipeline: single "build + unit + e2e" job on the dind runner, isolated stack space-wanderer-ci with static IP 172.39.0.10 (fresh DB volume per run), Playwright e2e (smoke.spec.ts, state.spec.ts) CI-only against that stack; prod compose behind Traefik at https://space-wanderer.dev.kkhost.pl (not deployed yet).