7.0 KiB
Enterprise migration: @suaveplan/game-server (core slice)
Package: @suaveplan/game-server
Status: PROPOSED
Type: new-package
Why
@suaveplan/game-server on the reference branch
claude/review-game-engine-arch-Kaykr (main repo
packages/universal/game-server/) is a 192-file framework with session
lifecycle, plugin chain, networking, state-sync, matchmaking, and an
"enhanced" variant (anti-cheat / lag-compensation / interest management /
replay / tournament / persistence / leaderboard / state-sync / timing).
The branch's last commit (2fb25cdb35) made the engine generic by
removing all game-specific adapters (bingo / tic-tac-toe / gem-crush).
Genesis needs that engine, but porting all 192 files in one slice would
either skip the genesis quality gates (100% test coverage, sibling .md
per .ts, kebab-case + 5-file layout, typed errors, Zod boundaries,
OTel) or land partially-built code. Six required workspace dependencies
(controller, keys, network-webrtc, network-websockets,
storage-browser, workflow) do not yet exist on genesis, blocking the
network/, plugins/, and parts of state/.
This change ships the dependency-light foundation that every later
slice depends on, behind the @suaveplan/game-server name at 0.1.0,
and documents the remaining scope as explicitly deferred follow-on
changes. The package is fully usable today by downstream code that wants
typed errors, Zod-validated boundary types, or the DI container.
What changes
- ADDED:
@suaveplan/game-serverpackage atpackages/gaming/games/game-server/(universal tier,sideEffects: false, version0.1.0). - ADDED:
GameServerError+GAME_SERVER_CODESregistry viadefineCodes— four initial codes:SERVICE_NOT_REGISTERED,INVALID_GAME_CONFIG,INVALID_SESSION_METADATA,INVALID_PLAYER_INFO. - ADDED:
GameConfig,SessionMetadata,PlayerInfo,MoveValidationResult,GameResult,SessionType,DeepReadonlywith Zod schemas (GameConfigSchema,SessionMetadataSchema,PlayerInfoSchema,MoveValidationResultSchema,GameResultSchema,SessionTypeSchema) and validators (parseGameConfig,parseSessionMetadata,parsePlayerInfo,tryParseMoveValidationResult,tryParseGameResult). - ADDED:
DIContainerwith singleton/transient lifecycles, typed error on miss, and re-register-invalidates-cache semantics (genesis improvement over upstream). - ADDED: Subpath exports
./errors,./types,./engine/di-containerfor tree-shaking.
Out of scope (deferred)
| Surface area | Why deferred | Follow-up change |
|---|---|---|
core/{AbstractGameLogic, interfaces/*, events/*} |
Each contract file needs its own 5-file layout + tests + docs; bundling all of them in one slice would force this PR over 30 files. | enterprise-game-server-core-contracts |
engine/{GameEngine 487, GameLoop 355, PlayerManager 345, PluginManager 340, SessionLifecycle 295, SessionNode 173, SessionStore 128, SessionTree 429} |
Six of eight files exceed the 300-line genesis hard limit and require splitting. Each needs Zod boundary schemas, OTel instruments, typed GAME_SERVER.* codes, 100% coverage, ≥200-word sibling .md. |
enterprise-game-server-engine |
state/{DeltaCompressor 221, StateDiffer 280, StateManager 316, StateSync 375} |
StateManager and StateSync exceed the 300-line limit; StateSync also reaches into networking which is blocked. | enterprise-game-server-state |
matchmaking/{MatchmakingEngine 152, QueueManager 169, SpectatorManager 122, skill-matcher 40, winner-stays-on 56} |
Dependency-clean but still requires the engine/state slices to be useful end-to-end. | enterprise-game-server-matchmaking |
performance/{NetworkTierAdapter, ObjectPool, SessionPool} → telemetry/ |
Folds into engine slice (SessionPool consumes Session from engine). |
enterprise-game-server-engine |
network/{NetworkAdapter, ReconnectionManager, WebRTCTransport, WebSocketTransport} |
BLOCKED on missing genesis deps @suaveplan/network-webrtc and @suaveplan/network-websockets. |
After transport packages land. |
plugins/{ABTest, Analytics, BasePlugin, FeatureFlag, Logging, Persistence, Rules, Workflow} |
BLOCKED on missing genesis deps @suaveplan/workflow and @suaveplan/keys. |
After workflow/keys packages land. |
enhanced/ (73 files: anti-cheat, components, interest-management, lag-compensation, leaderboard, persistence, replay, service-discovery, state-sync, timing, tournament) |
Priority 2 per migration brief; the enhanced variant sits above a stable engine. Several enhanced features have transitive deps on the blocked packages. | enterprise-game-server-enhanced |
integrations/components/game-lobby/* |
Priority 3 — React-coupled UI that belongs in a react-game-lobby package, not a universal-tier engine. |
enterprise-react-game-lobby |
integrations/enhanced-server/* |
Bundles every enhanced feature; depends on enterprise-game-server-enhanced. |
enterprise-game-server-enhanced |
stories/*, e2e/*, benchmarks/* |
Storybook/Playwright/bench tooling lands with the surfaces they exercise. | per-slice. |
Source mapping
This change derives from ../suaveplan/enterprise/game-server.md (not
present in the worktree's parent repo — the reference is the branch
claude/review-game-engine-arch-Kaykr itself, since the package was
under active redesign).
| Requirement | Source lines | Notes |
|---|---|---|
Typed error registry GAME_SERVER.* |
src/engine/DIContainer.ts:30 (only throw site in the migrated slice; upstream used plain Error) |
reworded — typed error replaces plain throw. |
GameConfig/SessionMetadata/PlayerInfo/MoveValidationResult/GameResult types |
src/core/types/index.ts:1-47 |
extended — added Zod schemas + validators (no source line). |
DIContainer singleton/transient resolver |
src/engine/DIContainer.ts:1-61 |
extended — re-register-invalidates-cache is new in genesis. |
Requirements with no source line
| Requirement | Justification |
|---|---|
| Zod schemas for every boundary type | Genesis rule: every public boundary is Zod-validated. |
Typed GameServerError instead of plain Error |
Genesis rule: every package throws via its own defineCodes registry. |
readonly modifiers on every interface field |
Genesis lint profile rejects Record<string, any> and prefers immutable shapes. |
Re-register-invalidates-cache on DIContainer |
Bug-class fix: upstream silently kept stale singletons after re-register. |
Verification approach
src/errors/game-server-error.test.ts— registry shape, error construction, code discrimination.src/types/common.test.ts— every schema accept-path, reject-path, and validator throw-path with the matching code.src/engine/di-container/di-container.test.ts— singleton, transient, symbol identifiers, fluent chaining, miss-throws-typed-error, has/unregister/clear/getRegisteredServices, re-register cache invalidation.
Migration impact
None — additive only. No consumer on genesis currently imports
@suaveplan/game-server.