← All decisions

Extract the three reference games into a new glemy-games repository

architecturerepository-topologypackagingdeployment

Context

docs/technical-architecture.md §2.3 already stated the extraction trigger explicitly: shared engine modules stay in one repo only until a second, genre-distinct game begins active development, at which point they're extracted into an independently versioned package. That trigger was met by Breakout (decision 0052) and exceeded by Platformer (decision 0061) -- three real, structurally different games existed, each fully wired to real rendering, real input, and confirmed live end to end. Per an explicit user request ("detaching the games from the engine project and moving them to an independent glemy-games repository, cleaning up the engine's refinements, and releasing fully functional APIs as a properly documented library"), extraction was carried out for real rather than continuing to defer it.

Options considered

Continue deferring extraction indefinitely, treating the trigger as evidence to note rather than an action to take — rejected
The trigger's own stated precondition (a second, genre-distinct game) was met two games ago and exceeded by a third; deferring further stopped being 'waiting for evidence' and became inertia. The user's explicit request made this an ordinary implementation task, not a fresh design question.
A Gleam workspace/monorepo tool keeping games and engine in one repository but as separate packages — rejected
Gleam has no first-class multi-package-workspace convention comparable to Cargo workspaces or npm workspaces; every comparable engine surveyed for the original trigger (Bevy, Godot, Phaser) ships the engine as a package or binary consumed by independent game projects, not a monorepo. A separate repository, consumed via a normal dependency, matches that precedent directly.
Have glemy-games depend on glemy via a Hex package from the start — rejected
glemy isn't published to Hex yet (that's a separate, later stage of the same request). A git dependency pinned to a commit SHA (Gleam's own documented preference over a branch/tag, for the same integrity reasoning this project already applies elsewhere) is the correct bridge until a real Hex release exists to depend on instead.

Decision

Created recregt/glemy-games (public). Moved games/tiers.gleam(+/rules.gleam), games/breakout.gleam(+brick/paddle.gleam), games/platformer.gleam, all three game_<name>.gleam/_ffi.mjs runners, the shared game_ffi.mjs, all three HTML entry points, every mirroring test file, and the browser-check tooling (browser_check*.ts + browser_check_shared.ts) into it, under src/glemy_games/ (module path glemy_games/... for game-specific code; imports of glemy/physics, glemy/render, glemy/io, etc. stay unchanged, resolving through the new git dependency). glemy-games' gleam.toml depends on glemy via `{ git = "https://github.com/recregt/glemy", ref = "<pinned commit sha>" }`. glemy-games got its own CI (mirroring glemy's lavapipe/WebGPU setup), ARCHITECTURE.md, CLAUDE.md, and a fresh docs/decisions.jsonl (glemy's own log stays canonical for everything before the split). glemy-website's deploy.yml was reworked: it now checks out and builds glemy-games (edge and stable) instead of glemy directly -- building glemy-games alone transitively builds glemy via its git dependency, so the separate glemy checkout/build steps it used to need are gone; glemy is still checked out once, only for decisions.jsonl/development-plan.jsonl content. STABLE_GLEMY_REF was renamed to STABLE_GLEMY_GAMES_REF and promote-stable.yml now polls glemy-games' own CI instead of glemy's. The moved files were then deleted from glemy itself, and ARCHITECTURE.md/CLAUDE.md/docs/technical-architecture.md were updated to describe glemy as engine-only, pointing to glemy-games' own ARCHITECTURE.md for game-specific conventions.

Verification

glemy-games: gleam build/gleam test --target javascript both green (118 Erlang / 125 JavaScript tests), deno task check-warnings PASS against a fresh baseline, all three browser-checks (Tiers/Breakout/Platformer) passed for real against a live dev server, and its own GitHub Actions CI ran green end-to-end (a fresh checkout with no local build cache, proving the git dependency resolves and builds cleanly on its own). glemy-website: the full deploy.yml rework was verified with a real local simulation of all three checkouts + build + demo-copy + site build before ever touching the live pipeline; the real push then ran green in CI, and the live site was smoke-checked directly afterward (curl against the live /play page and one demo's compiled output confirmed both glemy/glemy/render.mjs and glemy_games/glemy_games/game_tiers.mjs resolve correctly, HTTP 200). glemy itself: after deleting the moved files, gleam build/gleam test both targets stayed green with exactly the expected reduced counts (170 Erlang, 190 JavaScript -- precisely the prior full-repo counts minus glemy-games' own 118/125), and deno task check-warnings passed after updating the baseline to drop only warnings tied to the now-deleted files (confirmed each dropped warning traced to a deleted file, not a real regression, before updating).

Consequences

glemy is now engine-only: physics/physics/*, render, io, and the small Core utilities, with no game-specific code at all. Adding a fourth game means working in glemy-games, not glemy; a change to glemy's own Core API now needs a real, deliberate dependency-ref bump in glemy-games' gleam.toml to reach the games, rather than being immediately visible via a same-repo relative import -- slower to propagate, but a real, auditable boundary rather than an implicit one, matching every comparable engine's own topology. glemy-website's deploy pipeline gained a third checkout but lost two build steps (glemy no longer builds directly there), a net simplification. STABLE_GLEMY_GAMES_REF's promotion signal is now one hop removed from glemy's own CI (via glemy-games' CI, which itself depends on glemy building), a real but small increase in promotion latency, not a correctness gap. This sets up the next stage of the same request (cleaning up glemy's own public API, now that a real external consumer exists to test it against) and the stage after that (publishing glemy to Hex, at which point glemy-games' git dependency can become a real Hex dependency) -- both still open, tracked in the plan this decision executes the first stage of.

References