# Wave A — `@suaveplan/game-server` core foundation **Package**: `@suaveplan/game-server` **Status**: PROPOSED **Type**: extends existing genesis package (0.1.0) **Design**: ./design.md (inline below) **Spec delta**: ./specs/game-server/spec.md ## Why Wave A ships the core foundation of `@suaveplan/game-server` that every later wave (engine, session, state, matchmaking, transport) depends on: the four core interfaces (`IGameLogic`, `IPlayerManager`, `ISessionManager`, `IStateManager`) with runtime conformance harnesses, the `GameEvents` typed payload map plus its `GAME_EVENT_KEYS` registry, the `GameEventEmitter` typed pub/sub with ergonomic helpers (`safeEmit`, `waitFor`, `onN`, `onMultiple`), and the `AbstractGameLogic` Template-Method base class for concrete games. The package already shipped `DIContainer`, the `GameServerError` registry, and the Zod-validated core types in the prior change `enterprise-game-server-core`; Wave A is an additive extension that fills the interfaces / events / abstract-base layer behind a single 0.1.0 publish. Without this Wave the downstream waves (B: session manager + player manager, C: state manager + replay, D: matchmaking + transport plugins) have no contract to implement against. Shipping it as one isolated wave keeps the surface reviewable, the coverage gate enforceable on the whole package, and the dependent slices unblocked. ## What changes - ADDED: `core/types/core.types.ts` — `ConnectionStatus`, `PlayerConnection`, `SessionNode`, `SessionData`, `StateChangeEvent`, `GameEvents` map. - ADDED: `core/interfaces/i-game-logic/` — `IGameLogic` interface and `runIGameLogicConformance` harness. - ADDED: `core/interfaces/i-player-manager/` — `IPlayerManager` and `runIPlayerManagerConformance`. - ADDED: `core/interfaces/i-session-manager/` — `ISessionManager` and `runISessionManagerConformance`. - ADDED: `core/interfaces/i-state-manager/` — `IStateManager` and `runIStateManagerConformance`. - ADDED: `core/events/game-events/` — `GAME_EVENT_KEYS` array + `isGameEventKey` predicate. - ADDED: `core/events/game-event-emitter/` — `GameEventEmitter` typed pub/sub with `safeEmit` / `waitFor` / `onN` / `onMultiple` / per-key listener cap. - ADDED: `core/abstract-game-logic/` — `AbstractGameLogic` Template-Method base class with injected `Clock` + `IdGenerator` and OTel instrumentation. - EXTENDED: `errors/game-server-error.ts` — six new codes (`INVALID_MOVE`, `PLAYER_ALREADY_EXISTS`, `PLAYER_NOT_FOUND`, `LISTENER_LIMIT_EXCEEDED`, `INVALID_LISTENER_COUNT`, `EVENT_WAIT_TIMEOUT`) raised by the new core surface. - EXTENDED: root `src/index.ts` — additive named re-exports for the new Wave A surface. - EXTENDED: `package.json` exports map — 8 new subpath entries, one per feature module. ## Impact ### Affected dependents `bunx turbo ls --filter=...@suaveplan/game-server` enumerates dependents of this package. As of Wave A landing, no genesis package consumes `@suaveplan/game-server` yet — this is a foundation wave for `@suaveplan/game-loop`, `@suaveplan/game-state-schemas`, and the `api-plugin-game-server` family that will land in Waves B–D. - `@suaveplan/game-server` (self) — [x] tests run / [x] docs reviewed / [ ] no action needed. - No external dependents — verified by `bunx turbo ls --filter=...@suaveplan/game-server`. ## Parity Checklist | Capability | Upstream | Migrated | Notes | | --- | --- | --- | --- | | `IGameLogic` interface | YES | YES | Genesis tightens `any` → generic `TState`/`TMove`. | | Inline `AbstractGameLogic` in `IGameLogic.ts` | YES | UP | Genesis splits to its own feature dir. | | `IPlayerManager` interface | YES | YES | Returns `ReadonlyArray`. | | `ISessionManager` interface | YES | YES | Returns `ReadonlyArray`. | | `IStateManager` interface | YES | YES | `Readonly` instead of `DeepReadonly`. | | `GameEvents` map | YES | UP | Variadic tuples collapsed to single-payload objects. | | `GameEventEmitter` extending Node `EventEmitter` | YES | UP | Self-contained typed emitter; same surface +typed errors. | | Wildcard `[key: string]: any[]` index signature | YES | NO | Scoped out: closed map keeps lint/type safety; downstream needing wildcard analytics can subscribe to `GAME_EVENT_KEYS` directly. | | `AbstractGameLogic` Template Method | YES | UP | Adds injected `Clock` + `IdGenerator`, typed errors, OTel instruments. | | `cloneState` JSON round-trip | YES | YES | | | Hook methods (`beforeMoveProcessing`, etc.) | YES | YES | | | Player roster (`addPlayer` / `removePlayer`) | YES | UP | Throws `GameServerError` not plain `Error`. | | Conformance harnesses | NO | UP | Genesis-original — makes interfaces runtime-testable. | Rationale for the single scope-out (`wildcard analytics:*`): the upstream signature `[key: symbol]: any[]` defeats type safety and is unused inside the `core/` slice; downstream analytics packages can extend `GameEvents` via module augmentation if needed. ## Migration Wave A is additive — no existing public-surface item is renamed or removed. Consumers of the prior `0.1.0` surface (`DIContainer`, `GameServerError`, Zod parsers, types) keep working unchanged. The new error codes extend the registry; pattern-match consumers should not care because none of the new codes were thrown previously.