Files
suaveplan/openspec/changes/enterprise-gaming-weather/proposal.md
2026-05-27 23:29:53 +01:00

145 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenSpec Change: enterprise-gaming-weather
- **Change ID**: enterprise-gaming-weather
- **Package**: `@suaveplan/weather`
- **Category**: gaming/world
- **Target path**: `gaming/world/weather`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/weather.md`
---
## Summary
Deliver `@suaveplan/weather` on the genesis branch from scratch at enterprise quality. The package provides dynamic weather simulation with smooth transitions, regional zones, and gameplay effects. A `WeatherSystem` holds the current `WeatherState` (temperature, precipitation, wind, visibility, lightning) and advances it by transitioning toward a `WeatherPreset`; `WeatherZone` maps world regions to preset overrides; a `WeatherTransition` interpolates between two presets over a configurable duration. Genesis adds Zod preset schemas, structured errors, OTel weather-state gauge, injectable clock and RNG, and 100% coverage.
---
## Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | `WeatherError`; `WEATHER.*` codes |
| `@suaveplan/types` (`workspace:^`) | `Clock`, `Rng` |
| `@suaveplan/events` (`workspace:^`) | `weather:changed`, `weather:lightning`, `weather:zone_entered` events |
| `@suaveplan/day-night` (`workspace:^`) | `DayNightClock` for time-based weather probability |
| `zod` (`catalog:forms`) | `WeatherPreset`, `WeatherZone` schemas |
| `@opentelemetry/api` (`catalog:observability`) | Weather-state change counter |
---
## Public API surface
```ts
interface WeatherPreset {
name: string
temperature: number // celsius
precipitation: number // 0–1
windSpeed: number // m/s
windDirection: number // degrees
visibility: number // 0–1 (1=clear, 0=zero visibility)
fogDensity: number // 0–1
cloudCover: number // 0–1
lightningProbability?: number // per-minute probability 0–1
}
interface WeatherState extends WeatherPreset {
readonly isTransitioning: boolean
readonly transitionProgress: number // 0–1
}
function createWeatherSystem(options: WeatherSystemOptions): WeatherSystem
interface WeatherSystemOptions {
initialPreset: WeatherPreset
transitionDuration?: number // seconds, default 60
clock?: Clock
rng?: Rng
}
interface WeatherSystem {
transitionTo(preset: WeatherPreset, duration?: number): void
tick(dt: number): void
readonly state: WeatherState
readonly currentPreset: WeatherPreset
}
// Weather zones
function createWeatherZone(options: WeatherZoneOptions): WeatherZone
interface WeatherZoneOptions {
id: string
center: Vec3
radius: number
preset: WeatherPreset
blendRadius?: number // blend distance at zone edge
}
interface WeatherZone {
readonly id: string
getBlendFactor(position: Vec3): number // 0 = outside, 1 = fully inside
}
function blendWeather(base: WeatherPreset, override: WeatherPreset, factor: number): WeatherPreset
```
### Error codes
```ts
type WeatherErrorCode =
| 'WEATHER_INVALID_PRESET'
| 'WEATHER_ZONE_NOT_FOUND'
| 'WEATHER_TRANSITION_INVALID'
```
---
## File layout
```text
gaming/world/weather/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/common.ts
types/common.md
core/
weather-system/
weather-system.ts
weather-system.md
weather-system.types.ts
weather-system.test.ts
index.ts
weather-zone/
weather-zone.ts
weather-zone.md
weather-zone.types.ts
weather-zone.test.ts
index.ts
presets/
index.ts # CLEAR, RAIN, STORM, SNOW, FOG built-in presets
utils/
blend.ts
blend.md
blend.test.ts
tests/
integration.test.ts
```
---
## Impact
**Downstream**: `@suaveplan/r3f-weather` renders rain particles, fog, lightning effects driven by `WeatherState`. Prerequisites: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/day-night`.