Files
suaveplan/openspec/archive/2026-05-11-enterprise-tides/tasks.md
2026-05-27 23:29:53 +01:00

4.1 KiB

Tasks: enterprise-tides

Change ID: enterprise-tides Package: @suaveplan/tides Target path: universal/geo/tides Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/geo


1. Scaffold

  • Create universal/geo/tides/ with src/, tests/, src/__benchmarks__/ and all feature subdirectories per the layout in proposal.md.
  • Write package.json at version 0.1.0 with "type": "module", "sideEffects": false, correct exports map, dependencies, and devDependencies.
  • Write tsconfig.json extending @suaveplan/typescript-config/library.json.
  • Write vitest.config.ts using createTestConfig() from @suaveplan/testing/config.
  • Add lint, typecheck, test, test:coverage, build, docs:check scripts.

2. Types + errors

  • src/types/common.ts — TidalPort, TidalConstituent, TidePrediction, TideTable, TidePredictorOptions.
  • src/types/common.md (≥200 words, both examples, API reference).
  • src/error-codes.ts — TidesErrorCode (5 codes), metadata, register, eager call.
  • src/constants/index.ts — DEGREES_PER_HOUR, EPOCH_1900 (for ADMIRALTY-style time base).
  • src/types/schemas.ts + schemas.md — Zod schemas.

3. Core modules

  • src/core/harmonic-engine/ — harmonicHeight(constituents, time): number: for each constituent compute amplitude * cos(speed * t + phase) where t is hours since a reference epoch; sum all constituents. Tests: known published tide heights at 3 reference ports at known times (deterministic); result in [-maxAmplitude, +maxAmplitude].
  • src/core/extrema-finder/ — findExtrema(predictor, portId, from, to): TidePrediction[]: samples at 15-minute intervals, applies 3-point peak/trough detection, refines each extremum to 1-minute resolution via golden-section search. Tests: at least one high and one low in a 24-hour window; alternating high/low ordering; extrema height is a local maximum/minimum relative to neighbours.
  • src/data/ticon-loader/ — parseTiconData(raw): TidalPort[]: parses a structured text format (space-delimited columns: port code, name, lat, lng, constituent rows). loadBuiltinPorts(): imports builtin-ports.json (bundled data for ≥30 UK ports). Tests: round-trip parse for 3 manually constructed port entries.
  • src/core/tide-predictor/ — TidePredictor: loadPort, listPorts, predict(portId, time), predictRange, findExtrema, generateTable, generateTables, stream(portId, from, to, interval). stream is an AsyncGenerator<TidePrediction>. generateTable includes highWaters, lowWaters, range, meanLevel. Tests: predict at known time matches harmonicHeight directly; generateTable for 24h has ≥2 extrema; stream yields predictions in order; stream abort exits.
  • src/data/builtin-ports.json — bundled TICON-format data for ≥30 UK ports (curated from publicly available harmonic constituent data).

4. OTel instrumentation

  • Span tides.predict_range with attributes tides.port_id, tides.interval_minutes; counter tides.table_generate_total; histogram tides.predict_duration_ms.

5. Property-based tests (tests/property.test.ts)

  • Harmonic height bounds: for arbitrary constituent arrays with amplitudes ≤5 m, result is always in [-sum(amplitudes), +sum(amplitudes)].
  • Extrema ordering: findExtrema always returns alternating high/low types.
  • Prediction continuity: for any two adjacent predictions 1 minute apart, |height_t+1 - height_t| < 0.5 (no discontinuities).

6. Benchmarks (src/__benchmarks__/tides.bench.ts)

  • predictRange for 7-day window at 1-minute resolution for one port.
  • findExtrema for 30-day window.

7. Docs + verify

  • One .md per implementation file (≥200 words, both examples, API reference). Root README.md.
  • bunx turbo lint typecheck test --filter=@suaveplan/tides — green.
  • bunx turbo test:coverage --filter=@suaveplan/tides — 100%.
  • bun scripts/publish.ts --package @suaveplan/tides.
  • Archive: openspec/archive/2026-04-24-enterprise-tides/.