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

3.9 KiB

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