Spaces:
Paused
Paused
Commit History
-
T-004: rebrand to SpaceCitiesβ
Unverified signatureRenames the product's user-visible identity β page title, npm package name, the in-game splash/version banners, the dev-server console banner, and the README's own title β from "Stellar Frontier: RTS" to "SpaceCities". version.js/version.json needed no change: both already matched package.json at 1.1.0. Deliberately narrow, per ADR-0002: only the displayed product name moves. In-universe lore references to "Stellar Frontier" β the sibling turn-based game this RTS shares a universe with β are left exactly as written, since renaming those would misrepresent the fiction, not the brand. Historical/dated docs (CHANGELOG.md, docs/code-review-2026-08.md) and the in-game field manual (docs/player-handbook.html) are left for a separate pass; nothing in this commit depends on them. tools/smoke.js's title assertion moves in the same commit as index.html's <title> β CONTRIBUTING.md's own rule about updating a test's assertion rather than letting it silently diverge. Verified against real Chromiuβ¦b99addb
-
Fix the smoke job: npx --package does not do what I assumedβ
Claude +1: Claude Opus 4.8Unverified signatureThe smoke job failed on main with `sh: 1: playwright: not found` (exit 127). Two mistakes, and I merged before CI confirmed either β which is precisely the discipline the review said was the root problem. Owning that: the fix is here, and this one waits for a green run before it merges. MISTAKE 1: playwright-core ships no CLI. Only the full `playwright` package carries the binary that downloads browsers. The install step could never have worked. MISTAKE 2, the more interesting one: `npx --yes --package X -- node script.js` does not make X importable by the script. npx puts the package's BIN on PATH; it does not put its module on a child node process's resolution path, so the `require` inside tools/smoke.js fails with MODULE_NOT_FOUND regardless of which package was named. I had verified the script by setting NODE_PATH by hand and never exercised the mechanism the CI command actually used, so my local run proved the test worked and proved nothing about the plumbing around it. Both veβ¦d3f8729 -
Boot the game in a real browser in CI β the one thing 2502 tests cannot seeβ
Claude +1: Claude Opus 4.8Unverified signatureThere is no build step, so the files in the repo are the files the browser loads. The suite is headless and dependency-free, which is the point of it, and it means nothing in it can catch a page that parses, imports cleanly, and then throws on load. static-integrity.test.js catches STATIC breakage β a syntax error, an import pointing at a moved file, a getElementById for an id that does not exist β and stops exactly there. The failure it cannot reach is a blank white screen, and the way that has been found here before is a human clicking. Measured rather than asserted. Adding a bad draw call to renderUnits.js β one line, valid syntax, imports fine β leaves all 2502 tests passing and takes the game down on its first frame. tools/smoke.js catches it and exits 1 with the stack. A second mutation (a runtime throw in boot.js) is caught by BOTH this and the existing "imports cleanly under Node" guard, which is why the render one is the honest demonstration of what is new here. tools/smoke.β¦778e159 -
Cut 1.1.0, un-deprecate the CI actions, and run the browser smoke testβ
Claude +1: Claude Opus 4.8Unverified signatureFinding 9 of docs/code-review-2026-08.md, and the release checklist step that had never gated any of this work. CONTRIBUTING's release checklist is thorough and was going unused: the app sat at 1.0.0 while [Unreleased] accumulated Observer Mode, patrol orders, the counter-triangle work, doctrine research timing, Odyssey world selection, the endgame clock, a fourth archetype, competitions with Elo, genome evolution and an in-app AI editor. Bumped version.js, package.json and version.json in lockstep (release-manifest.test.js gates that), and dated the changelog section. Save formats are deliberately NOT bumped β nothing changed shape this cycle, so 1.0.0 saves load as-is, and version.json now says so. Deliberately NOT done: `git tag v1.1.0` and any deploy. Those are outward-facing and yours to make; everything they need is prepared. actions/checkout and actions/setup-node bumped v4 -> v5. Both were being force-run on Node 24 with a deprecation warning on every job. Ran the browser sβ¦dd41939
-
Tier 1, step 1: make the static guards actually guardβ
Claude +1: Claude Opus 5Unverified signatureSix findings from docs/code-improvement-tiers.md (C1-C4, C12, C13). Each was verified red before the fix and, where the guard is new, re-verified by reproducing the bug it exists to catch. C1 β determinism.test.js fingerprinted with its own hand-rolled snapshot that had drifted into a WEAKER one than test/_helpers.js's shared entitySnapshot: it recorded only order.type, and no cargo, tier, charge, constructing flag or state.time. So a float-accumulation drift moving a hauler's cargo or a move order's destination replayed "identically". It now imports the shared fingerprint, and a new sensitivity test mutates each sim-owned field in turn and requires the fingerprint to move (red against the old snapshot on all seven). C2 β the all-worlds roster sweep ran 400 ticks, which measurably produced ZERO combat orders on all eleven worlds: an opening-only replay that could not see a divergence in combat, veterancy, wreckage or separation under pressure. Running longer doesn't fix it (the playeβ¦9af10ec
-
Add JSDoc typedefs + // @ts-check for the core sim shapes (no build step)β
Claude +1: Claude Opus 4.8Unverified signatureAddress the top architectural-review finding β an untyped mutable `state` bag threaded through ~360 functions, where a mistyped or renamed field reads undefined silently and the same-seed determinism test can't see it. Now that class of bug is a check-time error. Zero runtime cost and no build step: the shipped code stays plain ES modules. - engine/types.js: JSDoc @typedefs for the core shapes (State, Unit, Building, Player, AiState, Resources, Cargo, Order, ResourceNode, GameMap, Fog, Market, Diplomacy, Galaxy, β¦). No runtime code, never imported β global typedefs the checker and any editor's TS language service resolve project-wide. - jsconfig.json + `npm run typecheck` (tsc, noEmit): checking is OPT-IN per file via a `// @ts-check` pragma, so coverage grows file-by-file. Editors check the annotated files live with no install; the script needs a tsc available. - Enabled + annotated on the core data + hot path: state.js (the factories bind the types to the real objects), β¦e3658fa -
Tier 5: release hygiene β docs, license, dev server, npm startβ
Claude +1: Claude Opus 4.8Unverified signatureTurn the repo into something a stranger can clone, run, and contribute to. - README: rewritten to lead with how to run it (npm start), fix the stale "no tech tree" claim (there's a Refinery doctrine system, a Foundry gate and Datacenter research), and document the whole Odyssey open-world layer, the two save channels, and the versioning scheme β none of which were mentioned. - tools/serve.js + `npm start`: a zero-dependency static server so the ES-module game runs with nothing but Node (no npx, no Python), serving .js as application/javascript (or the modules won't load) with a path-traversal guard. - LICENSE: MIT. - CONTRIBUTING.md: the load-bearing invariants (engine purity, determinism, no build step, versioned saves) with the guarding test for each, plus a release checklist. - CHANGELOG.md: the 1.0.0 entry. Full suite green (560 tests). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AEQUVetLk31Jj7niDQAsXLd0e9298 -
Tier 1 review fixes: save-load hardening, engine guards, UX bugsβ
Claude +1: Claude Opus 4.8Unverified signatureAddresses the Tier-1 (correctness & safety) findings from the codebase review. Save/load safety (engine/persist.js, saveload.js): - Validate values on load, not just JSON shape: drop entities of unknown type (an undefined def threw on the first tick, freezing the game AFTER load's try/catch returned), coerce numeric fields to finite/in-range (a string "time" concatenated; a NaN coord poisoned the spatial hash), and recompute the entity-id counter past every loaded id so a low/missing nextEntityId can't mint a colliding id. All identity for a valid save, so determinism is untouched. - Persist aiWaveCount β omitting it reset the AI economy-raid cadence on every reload, breaking continue-identically for Tactical games. - deserializeGalaxy now throws on structural nonsense (no worlds/planets, or an activeId with no planet) BEFORE the caller tears down the live game, and filters the world roster to real world ids. - autoSave returns success; "Save & Exit" falls back to a β¦a4bbde9
-
First playable slice: 1v1 skirmish vs scripted AI on Ferros Primeβ
Claude +1: Claude Sonnet 5Unverified signatureGather ore/crystals/radioactives with Workers, build a Barracks, produce Skiffs, fight, win by destroying the enemy Command Center. engine/ holds the sim: a fixed-timestep loop decoupled from render rate, movement, the gather/deposit loop, combat with auto-acquire, building construction + unit production queues, a scripted AI opponent, and the win condition. render.js/input.js are the canvas view and mouse controls (drag-select, right-click context orders, build placement); main.js wires it to a DOM HUD. Converted data.js's top-level tables to ES module exports so the engine can import them directly. Covered by 23 node:test cases including a full simulated skirmish that plays to a winner, and manually playtested end-to-end in a real browser (gather -> build -> produce -> victory/defeat UI) via Playwright. One real bug caught in that process: constructed buildings never got a `radius` copied onto the instance, which went on to poison unit spawn points and building hit-testing with Naβ¦17641e3 -
Seed repo: shared universe data + real-time loop bootstrapβ
Claude +1: Claude Sonnet 5Unverified signatureCarries over data.js verbatim from the original Stellar Frontier repo (pure static data: factions, commodities, recipes, the 20 charted worlds) plus the style.css color palette, so this reads as the same universe. Everything else is new β index.html/main.js is a minimal canvas + requestAnimationFrame loop proving out the real-time tick, with no game state or mechanics yet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BDmJ8vc9jxc6TUegK9F2YJ7a2b109