18 base profiles — and four levels of locality on top
A profile is not one global curve. The catalogue (v2.0.0) is a five-level hierarchy: a call resolves spatially to the most specific calibrated level available, and the confidence reflects how local that match was.
- 01Base
18 base profiles across water · snow · air · land — what counts as good wind, swell or snow for a sport.
- 02Region
Regional overrides — the Mediterranean kite season is not the North Sea's.
- 03Cluster
Groups of nearby spots that share a regime.
- 04Sub-spot
A named break, launch or face with its own calibrated curve.
- 05Micro
The finest grain, once enough paired outcomes accrue there.
Hierarchical Bayesian shrinkage
A brand-new sub-spot has almost no outcomes — so its curve would be noise. Instead the engine shrinks each level toward its parent's prior: a sparse sub-spot borrows strength from its cluster, region and base profile, and only earns independence as real paired outcomes accumulate.
Every score carries a calibration_provenance block recording which level resolved and how much data backed it — and the confidence scales from 0.85 (base only) up to 1.0 (a sub-spot with n ≥ 100). Honest by construction.
Why open the data but not the engine
Activity definitions, curves, citations and review status live in a public repo and ship as an npm package. Anyone can audit the curve scoring their slot, or submit a regional variant by PR. The Zod schema is byte-identical across both repos — CI fails if they drift.
The physics synthesis, the spatial resolver, the Bayesian calibration and the scoring pipeline stay closed. Open definitions make the verdicts auditable; the engine is the moat.
Adding a profile is a pull request
A new activity or regional variant is a single YAML file at catalog/<family>/<slug>/index.yaml. pnpm validate gates the PR; merge auto-publishes a patch bump on npm, and the engine picks it up — no code change on our side.