Files
suaveplan/openspec/archive/2026-05-05-enterprise-universe-family/specs/tides/spec.md
2026-05-27 23:29:53 +01:00

115 lines
3.9 KiB
Markdown

## ADDED Requirements
### Requirement: TidalProvider implementation
The system SHALL provide `TidalProvider` implementations for Earth (TICON, ADMIRALTY) and any planet (physics-based).
#### Scenario: Provider creation
- **WHEN** `createTiconProvider()`, `createAdmiraltyProvider(options)`, and `createPhysicsBasedProvider()` are called
- **THEN** each returns an object satisfying `TidalProvider`
### Requirement: Earth harmonic providers preserved
The system SHALL preserve TICON and ADMIRALTY provider logic, harmonic constituent engine, and station data.
#### Scenario: TICON prediction
- **WHEN** `predictHeight` is called via a TICON provider for a known UK station at a known time
- **THEN** the result matches the legacy `@suaveplan/tides` value within `0.01` metres
### Requirement: Multi-satellite physics model
The system SHALL compute tidal height from all satellites in `PlanetConfig` using superposition.
#### Scenario: Two-satellite planet
- **WHEN** a `PlanetConfig` with two satellites is used with `createPhysicsBasedProvider()`
- **AND** `predictHeight` is called
- **THEN** the result reflects the combined gravitational influence
### Requirement: Individual satellite contribution
The system SHALL export `satelliteTidalContribution` for visualising per-satellite effects.
#### Scenario: Single contribution
- **WHEN** `satelliteTidalContribution(planet, satellite, coord, time)` is called
- **THEN** the result is a number representing that satellite's height contribution
### Requirement: Zod schemas for all public options
The system SHALL validate all public option types with Zod and throw `ValidationError` on failure.
#### Scenario: Invalid options
- **WHEN** `createAdmiraltyProvider({ apiKey: "" })` is called with an invalid key
- **THEN** validation throws before any network request
### Requirement: AbortSignal on async methods
The system SHALL accept `AbortSignal` on every async provider method.
#### Scenario: Abort tide prediction
- **WHEN** `predictHeight` is called with an aborted signal
- **THEN** the promise rejects with an abort error
### Requirement: TidesError with stable codes
The system SHALL export `TidesError` extending `@suaveplan/error` with `TIDES.*` error codes.
#### Scenario: Error code stability
- **WHEN** a provider throws for a missing station
- **THEN** the error code begins with `TIDES.`
- **AND** the same condition yields the same code across calls
### Requirement: OTel instrumentation
The system SHALL create OTel spans, counters, and histograms on every provider call.
#### Scenario: Span creation
- **WHEN** `predictHeight` is called
- **THEN** an OTel span is started with the operation name
- **AND** a histogram records the prediction latency
### Requirement: Injectable fetch and clock
The system SHALL accept `fetchFn`, `clockFn`, and optional `cacheFn` in ADMIRALTY provider options.
#### Scenario: Custom fetch
- **WHEN** a custom `fetchFn` is injected into `createAdmiraltyProvider`
- **THEN** the provider uses it for all HTTP requests
### Requirement: Property-based tests on harmonic engine
The system SHALL include fast-check property tests on the harmonic prediction engine.
#### Scenario: Property test existence
- **WHEN** the test suite runs
- **THEN** fast-check properties verify monotonicity and bounds of the harmonic sum
### Requirement: TidalProvider routing
The system SHALL export `TidalProviderImpl` routing Earth to `earthProviders` and non-Earth to `physicsProvider`.
#### Scenario: Earth vs Mars routing
- **WHEN** `predictHeight` is called with `EARTH`
- **THEN** the first Earth provider is tried
- **AND** when called with a Mars-like config, the physics provider is used
### Requirement: Planet identification by name
The system SHALL identify Earth by `planet.name.toLowerCase() === "earth"`.
#### Scenario: Name-based routing
- **WHEN** a planet with `name: "Earth"` is passed
- **THEN** it routes to Earth providers
- **AND** a planet with `name: "Mars"` routes to physics