You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The app currently models exactly one boat — the Salona 45 from pipeline/polars-source.json — with exactly two foresails baked into the type system (Rig = 'genoa' | 'fock', app/src/types.ts:6). Crews sailing with Schoenicke SKIPPERTEAM (yachts based at Marina Im Jaich, Flensburg — exactly this app's routing area) sail a mixed fleet, so the planner should support selecting the boat you're actually on, and the foresail inventory that boat carries.
Not all 14 are Baltic-based (e.g. SKIATHOS sails the Atlantic) — during grooming, confirm which models are actually stationed in Flensburg and prioritize those.
Polar sourcing should follow the existing pattern: ORC certificates / VPP data per model where available (build_polars.mjs documents the Salona 45 derivation), with the same validation gates — note the current sanity anchors and the v < 12 kn plausibility bound are Salona-45-specific and must become per-boat.
Part 2 — Multiple foresail types, selectable
Generalize the hard-coded genoa/fock pair into a per-boat sail inventory the user selects from (e.g. ~135% genoa, ~110% fock/jib, self-tacking jib — whatever the boat actually carries; white-sails scope stays, no spinnaker legs).
Plan hard-codes genoaReason / fockReason (app/src/types.ts:118-119) and recommended: Rig → becomes a per-sail result list. IndexedDB schema migration needed so existing saved plans still load (Plan must stay structured-clone-safe).
The router currently runs twice per plan (genoa + fock polars) and recommends the faster rig — with N foresails that's N solver runs. Either cap the comparison to the user's selected subset (e.g. pick 1–2 sails to compare per plan) or make the run count explicit in progress reporting; worker-time budget matters.
Static assets: app/public/data/polar-genoa.json / polar-fock.json → per-boat, per-sail files; all committed and precached (offline planning of the polars themselves must keep working — only wind needs network).
UI: boat picker + sail inventory in settings/planner; all labels through both i18n dicts (de/en).
Constraints
Boat/sail selection is a user setting resolved at plan time — like safety depth, it must never require regenerating data assets, and a saved plan must keep rendering with the boat/sails it was computed with.
The design spec (docs/superpowers/specs/2026-07-14-sail-command-design.md) currently fixes the Salona 45 and the two-rig comparison — this feature needs a spec addendum (main-session edit, user-approved) before implementation.
Polar honesty: each new polar must carry its source note (certificate / VPP estimate) like the existing ones — user-facing copy must not overstate calibration.
Acceptance criteria
User can select a boat type; at least the Flensburg-based Skipperteam models above are available with sourced, validated polars.
Each boat exposes its own foresail inventory; the user selects which sails to plan with; router compares the selected sails and recommends the fastest, as today.
Boat draft drives the safety-depth default/floor; motor speed and maneuver penalty defaults are per-boat (still user-tunable).
Saved plans from before the change still load (schema migration) and always render with their original boat/sail/polars.
Pipeline validation (build_polars.mjs) generalized: per-boat sanity anchors, no Salona-45 constants applied to other hulls.
de/en i18n complete; spec addendum merged first.
Related: #53 (safety-depth relaxation floor = boat draft — becomes per-boat with this issue).
Motivation
The app currently models exactly one boat — the Salona 45 from
pipeline/polars-source.json— with exactly two foresails baked into the type system (Rig = 'genoa' | 'fock',app/src/types.ts:6). Crews sailing with Schoenicke SKIPPERTEAM (yachts based at Marina Im Jaich, Flensburg — exactly this app's routing area) sail a mixed fleet, so the planner should support selecting the boat you're actually on, and the foresail inventory that boat carries.Part 1 — More boat types (Skipperteam fleet)
Fleet per skipperteam.de/toerns/yachten (14 own yachts):
Notes:
build_polars.mjsdocuments the Salona 45 derivation), with the same validation gates — note the current sanity anchors and thev < 12 knplausibility bound are Salona-45-specific and must become per-boat.Part 2 — Multiple foresail types, selectable
Generalize the hard-coded genoa/fock pair into a per-boat sail inventory the user selects from (e.g. ~135% genoa, ~110% fock/jib, self-tacking jib — whatever the boat actually carries; white-sails scope stays, no spinnaker legs).
Touchpoints this implies (from current code):
Rig = 'genoa' | 'fock'(app/src/types.ts:6) → data-driven sail identifiers;PolarTable.rigfollows.Planhard-codesgenoaReason/fockReason(app/src/types.ts:118-119) andrecommended: Rig→ becomes a per-sail result list. IndexedDB schema migration needed so existing saved plans still load (Plan must stay structured-clone-safe).app/public/data/polar-genoa.json/polar-fock.json→ per-boat, per-sail files; all committed and precached (offline planning of the polars themselves must keep working — only wind needs network).Constraints
docs/superpowers/specs/2026-07-14-sail-command-design.md) currently fixes the Salona 45 and the two-rig comparison — this feature needs a spec addendum (main-session edit, user-approved) before implementation.Acceptance criteria
build_polars.mjs) generalized: per-boat sanity anchors, no Salona-45 constants applied to other hulls.Related: #53 (safety-depth relaxation floor = boat draft — becomes per-boat with this issue).