Initial Commit
This commit is contained in:
93
openspec/archive/2026-05-24-game-server-plugins/proposal.md
Normal file
93
openspec/archive/2026-05-24-game-server-plugins/proposal.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Proposal — game-server plugins (Wave C-1)
|
||||
|
||||
## Why
|
||||
|
||||
The `PluginManager` shipped in Wave B exposes the `EnginePlugin` lifecycle
|
||||
contract but ships no concrete plugins. Wave C-1 fills that gap with seven
|
||||
production-grade plugins covering A/B testing, analytics, feature flags,
|
||||
logging, persistence, rules, and workflows. All seven plugins extend a new
|
||||
shared `BasePlugin` abstract base that implements the `EnginePlugin`
|
||||
lifecycle template-method style.
|
||||
|
||||
The plugins are universal-tier (zero browser / React deps). External
|
||||
integrations are routed through structural-type contracts from
|
||||
`@suaveplan/types` (`LoggerLike`, `StorageLike`, `Clock`, `IdGenerator`,
|
||||
`Rng`) so the package keeps its lean dep footprint.
|
||||
|
||||
## What changes
|
||||
|
||||
### ADDED `BasePlugin`
|
||||
|
||||
Abstract base for game-server plugins. Implements the `EnginePlugin`
|
||||
contract (`onInstall` / `onUninstall` / `onEnable` / `onDisable`) and
|
||||
forwards to `protected` template-method hooks. Tracks lifecycle state
|
||||
(`created → installed → enabled → disabled → destroyed`) and rejects any
|
||||
hook after destruction.
|
||||
|
||||
### ADDED concrete plugins
|
||||
|
||||
- `ABTestPlugin` — weighted, deterministic variant assignment via injectable
|
||||
`Rng`; conversion log; per-variant summary stats.
|
||||
- `AnalyticsPlugin` — subscribes to `GameEventEmitter`, accumulates
|
||||
per-session counters, dispatches structured `AnalyticsEvent` to an
|
||||
injectable sink.
|
||||
- `FeatureFlagPlugin` — thin adapter over `@suaveplan/feature-flags`
|
||||
`FlagManager`; per-player evaluation context; rolling evaluation log.
|
||||
- `LoggingPlugin` — subscribes to `GameEventEmitter`, forwards events to a
|
||||
`LoggerLike` sink, retains a bounded ring buffer for inspection.
|
||||
- `PersistencePlugin` — tracks per-session state from the emitter and
|
||||
persists via injectable `StorageLike`; explicit `save`/`load`/`delete`.
|
||||
- `RulesPlugin` — wraps `@suaveplan/rules` `RuleEngine`; three rule slots
|
||||
(move / start / end); rolling evaluation history.
|
||||
- `WorkflowPlugin` — id-keyed `WorkflowEngine` registry; `execute` records
|
||||
status + duration + error; `cancel` defers to engine.
|
||||
|
||||
### ADDED error codes (extends `GAME_SERVER.*` registry)
|
||||
|
||||
- `PLUGIN_BASE_DESTROYED`
|
||||
- `INVALID_PLUGIN_OPTIONS`
|
||||
- `AB_TEST_INVALID_VARIANT`
|
||||
- `AB_TEST_EXPERIMENT_NOT_FOUND`
|
||||
- `PERSISTENCE_SAVE_FAILED`
|
||||
- `PERSISTENCE_LOAD_FAILED`
|
||||
- `WORKFLOW_NOT_FOUND`
|
||||
- `DUPLICATE_WORKFLOW`
|
||||
- `INVALID_RULE_CONTEXT`
|
||||
|
||||
### ADDED dependencies
|
||||
|
||||
- `@suaveplan/feature-flags` (`workspace:^`)
|
||||
- `@suaveplan/rules` (`workspace:^`)
|
||||
- `@suaveplan/workflow` (`workspace:^`)
|
||||
|
||||
### Subpath exports
|
||||
|
||||
Each plugin module gets its own subpath:
|
||||
- `./plugins/base-plugin`
|
||||
- `./plugins/ab-test-plugin`
|
||||
- `./plugins/analytics-plugin`
|
||||
- `./plugins/feature-flag-plugin`
|
||||
- `./plugins/logging-plugin`
|
||||
- `./plugins/persistence-plugin`
|
||||
- `./plugins/rules-plugin`
|
||||
- `./plugins/workflow-plugin`
|
||||
|
||||
## Source mapping
|
||||
|
||||
| Requirement | Upstream | Notes |
|
||||
| --- | --- | --- |
|
||||
| BasePlugin lifecycle | `BasePlugin.ts` (1-50) | Adapted to genesis `EnginePlugin` contract; tracks state machine |
|
||||
| AnalyticsPlugin per-session counters | `AnalyticsPlugin.ts` (35-280) | Sink-based dispatch instead of OTel coupling |
|
||||
| ABTestPlugin variant bucketing | `ABTestPlugin.ts` (28-190) | Self-contained — no `@suaveplan/ab-testing` dep |
|
||||
| FeatureFlagPlugin evaluation | `FeatureFlagPlugin.ts` (30-160) | Wraps `@suaveplan/feature-flags` `FlagManager` |
|
||||
| LoggingPlugin event forwarding | `LoggingPlugin.ts` (35-430) | Bounded ring buffer; granular toggles |
|
||||
| PersistencePlugin save/load | `PersistencePlugin.ts` (30-380) | Zod-validated load; `StorageLike` injection |
|
||||
| RulesPlugin evaluation | `RulesPlugin.ts` (28-195) | Wraps `@suaveplan/rules` `RuleEngine` |
|
||||
| WorkflowPlugin orchestration | `WorkflowPlugin.ts` (35-210) | Id-keyed registry; history; cancel |
|
||||
|
||||
## Scope guard
|
||||
|
||||
This change does NOT touch `src/core/`, `src/engine/`, `src/state/`,
|
||||
`src/network/`, `src/matchmaking/`, `src/performance/`, `src/types/`, or
|
||||
`src/observability/`. `src/index.ts` is also untouched — orchestrator
|
||||
consolidation handles the unified barrel.
|
||||
Reference in New Issue
Block a user