Summary
Curate the default event-detail chart stack by sport mode so each activity initially shows the most relevant recorded metrics instead of every globally enabled chart that happens to be available.
This is a feature epic covering the recommendation registry, selection rules, interaction with existing chart preferences, multisport behavior, persistence, specialized chart surfaces, user-facing controls, documentation, and regression coverage.
The central product rule is:
Sport recommendations choose the best initial charts from the metrics the user allows and the activity actually contains. They never remove access to other recorded metrics and never overwrite an explicit user choice.
Problem
Event charts currently have several useful controls:
- Default chart metrics in Settings define which metrics the user generally wants.
- Include all recorded metrics expands the chartable streams available in Visible charts.
- Visible charts lets the user show or hide charts for an event.
- Show all charts explicitly displays every currently available chart.
- Per-event chart visibility is remembered locally.
However, the initial visible stack is not sport-aware. A run, bike ride, pool swim, strength workout, sailing activity, and ski activity can all inherit the same global metric ordering. This can create long stacks, surface secondary metrics before sport-defining metrics, or show charts that are technically available but not useful for that activity.
Examples:
- Running should prioritize Heart Rate, Pace, and Power when those streams exist.
- Indoor cycling should prioritize Heart Rate, Power, and Cadence rather than Altitude.
- Mountain biking should prioritize Heart Rate, Speed, and Altitude before less central metrics.
- Pool swimming should prioritize Heart Rate and Swim Pace, then swimming-specific metrics when supported.
- Team, racket, strength, and flexibility activities should not be padded with irrelevant charts merely to reach a fixed count.
- Diving activities should use the existing pinned Dive Profile without automatically duplicating the same metrics in the ordinary chart stack.
Product goals
- Show a concise, sport-relevant initial chart stack.
- Preserve existing global chart preferences as a hard user preference.
- Preserve access to all recorded chartable metrics.
- Preserve explicit per-event visibility choices.
- Make automatic versus user-customized visibility distinguishable.
- Cover every canonical Sports Lib activity type through an exact profile, family profile, or deliberate fallback.
- Handle sparse source data by choosing the next supported and available recommendation.
- Keep multisport and merged-event behavior predictable.
- Avoid duplicate charts when a specialized event surface already presents a metric.
- Keep units, derived stream families, overlays, zoom, laps, swim lengths, and chart rendering behavior unchanged.
Non-goals
- Adding new raw activity fields or changing importer/parser behavior.
- Changing Dashboard tiles or Training workspace charts.
- Changing MCP activity-chart schemas or tools.
- Replacing the Visible charts menu.
- Removing recorded metrics from the user’s reach.
- Automatically changing an existing explicit event selection.
- Treating Cadence as Stroke Rate without importer-level evidence that the stream has that meaning.
- Building editable personal per-sport presets in the first delivery. A later enhancement may add Use these charts by default for Running.
- Recommending medical or prescriptive interpretations.
Terminology and precedence
| Layer |
Responsibility |
Priority |
| Recorded chartable data |
Determines what can physically be rendered |
Base constraint |
| Include all recorded metrics |
Expands the metrics offered in Visible charts |
Discovery control only |
| Default chart metrics |
User’s global allow-list for automatic visibility |
Must outrank sport curation |
| Sport profile |
Orders the most relevant candidates for the selected sport |
Applies only to automatic selection |
| Per-event custom visibility |
Explicit selection made through Visible charts |
Highest priority |
| Pinned/specialized surface |
Owns metrics that should not be automatically duplicated |
Exclusion for automatic ordinary charts |
Required precedence
- Build the complete set of valid chart panels for the selected activities.
- Apply the existing Include all recorded metrics behavior to the discoverable menu:
- off: expose the chart families allowed by Default chart metrics;
- on: expose all recorded chartable metrics, including supported derived/unit variants.
- Restore a valid explicit per-event custom selection when one exists.
- Otherwise resolve the sport profile for the current selected-activity signature.
- Intersect the profile with:
- the user’s Default chart metrics;
- metrics currently available in the activity;
- current pinned/specialized-surface automatic exclusions.
- Select the first up to three available recommendations.
- Do not fill unused slots with unrelated metrics simply to reach three.
- Keep all other discoverable metrics unchecked in Visible charts.
- Show all charts remains an explicit user action that temporarily selects every available chart.
- Manual changes switch the selection from automatic to custom.
Concrete example
A run records Heart Rate, Pace, Power, Altitude, Cadence, Speed, and Temperature.
The user enables Heart Rate, Pace, Altitude, and Temperature under Default chart metrics.
The Running profile is:
Heart Rate → Pace → Power → Altitude → Cadence → Speed → EPOC → Vertical Speed → Temperature
The initial visible charts are therefore:
- Heart Rate
- Pace
- Altitude
Power and Cadence are skipped because the user did not enable them as default metrics. Temperature remains available but is not promoted over the more relevant enabled metrics. If Include all recorded metrics is enabled, every other recorded chartable metric appears in Visible charts without becoming visible automatically.
Automatic versus custom selection provenance
The implementation must distinguish automatic defaults from explicit user choices.
Automatic selection
- Derived from the current sport profile.
- May be recalculated when the selected activity or sport signature changes.
- May adopt compatible improvements to the curated registry.
- Must not be persisted indistinguishably from a manual choice.
Custom selection
- Begins after the user toggles a metric in Visible charts, selects Show all charts, or otherwise explicitly changes chart visibility.
- Wins over sport recommendations.
- Is restored when the event and relevant selected-activity signature are revisited.
- Drops only metric IDs that are no longer valid or available.
- Must not be overwritten by a registry update.
Existing stored selections
Existing non-empty per-event visibility values cannot reliably be classified as old automatic defaults versus user choices. Treat them as custom for migration safety.
Introduce versioned/provenance-aware storage for new state, or avoid persisting automatic selections until the user changes them. Do not destructively rewrite legacy storage.
Reset action
Add Reset to defaults to the chart actions or Visible charts menu.
Reset must:
- clear the custom selection for the current event/signature;
- immediately resolve the current curated profile;
- preserve global Default chart metrics;
- preserve the Include all recorded metrics setting;
- preserve overlays and every unrelated chart setting.
Sport profile resolution
Resolve profiles in this order:
- Exact canonical activity-type profile.
- Explicit alias mapping to an exact profile.
- Canonical activity-family profile.
- Deliberate generic fallback.
- Deliberate empty profile for modes such as Transition where ordinary charts are not useful.
Every canonical activity type returned by Sports Lib must resolve deterministically. Add an exhaustive coverage test so new Sports Lib activity types cannot silently inherit arbitrary ordering.
Metric names below are logical chart families. Unit-specific variants must resolve through existing unit settings, and derived variants must remain grouped under the same logical recommendation.
Curated sport profiles
The ordered lists below are the complete candidate priority, not a promise that every activity contains every metric. The resolver selects the first available candidates after applying user preferences and exclusions.
Multisport
| Activity modes |
Ordered candidates |
| Triathlon, Duathlon, Swimrun, Aquathlon, Multisport |
Heart Rate → Speed → Altitude → Temperature → EPOC |
For a mixed selected-activity set, use this multisport profile. When exactly one constituent activity is selected, resolve that activity’s exact sport profile instead.
Running and navigation
| Activity modes |
Ordered candidates |
| Running |
Heart Rate → Pace → Power → Altitude → Cadence → Speed → EPOC → Vertical Speed → Temperature |
| Treadmill |
Heart Rate → Pace → Power → Cadence → Speed → EPOC → Temperature |
| Trail Running, Orienteering |
Pace → Power → Altitude → Heart Rate → Vertical Speed → Cadence → Speed → EPOC → Temperature |
| Track and Field |
Heart Rate → Pace → Temperature |
Aliases/inheritance:
- Indoor Running and Virtual Running inherit Treadmill.
- Generic road/street/track running aliases inherit Running unless they canonicalize to a more specific type.
- Adventure Racing inherits Multisport unless its selected activities resolve to one homogeneous family.
Walking, hiking, outdoor travel, and altitude sports
| Activity modes |
Ordered candidates |
| Walking, Nordic Walking |
Heart Rate → Pace → Power → Cadence → Altitude → Vertical Speed → Speed → Temperature |
| Hiking, Trekking |
Heart Rate → Altitude → Speed → Vertical Speed → Temperature → Pace → Power → Cadence → EPOC |
| Ski Touring, Mountaineering |
Heart Rate → Altitude → Vertical Speed → Speed → Cadence → Pace → Temperature → EPOC |
| Paragliding |
Heart Rate → Altitude → Vertical Speed → Speed → Temperature → EPOC |
| Fishing |
Heart Rate → Altitude → Sea-level Pressure → Speed → Temperature |
| Hunting |
Pace → Altitude → Heart Rate → Temperature → Sea-level Pressure → Speed |
| Golf, Frisbee |
Heart Rate → Altitude → Pace → Temperature → Speed |
Coverage rules for related canonical types:
- Horseback Riding inherits Hiking.
- Walking-like wheelchair activity inherits Walking unless categorized as a cycling propulsion mode.
- Climbing, Rock Climbing, Canyoning, and Via Ferrata use Heart Rate → Altitude → Vertical Speed → Temperature. Pace and Speed remain hidden by default where Sports Lib already marks them as unsuitable.
- Indoor Climbing and Bouldering use Heart Rate only, with Temperature as a low-priority optional candidate.
- Floor Climbing and Stair Stepper use Heart Rate → Cadence → Vertical Speed.
- Hang Gliding and Flying inherit Paragliding.
- Sky Diving and Jumpmaster use Altitude → Vertical Speed → Speed → Heart Rate.
- Route is not assumed to be a workout; use the generic fallback only when it contains ordinary activity chart streams.
Cycling
| Activity modes |
Ordered candidates |
| Cycling, Gravel Cycling |
Heart Rate → Power → Speed → Altitude → Vertical Speed → Cadence → EPOC → Temperature |
| Indoor Cycling |
Heart Rate → Power → Cadence → Speed → EPOC → Temperature |
| Mountain Biking |
Heart Rate → Speed → Altitude → Vertical Speed → Power → Cadence → EPOC → Temperature |
Aliases/inheritance:
- E-Biking inherits Cycling.
- Virtual Cycling inherits Indoor Cycling.
- Enduro MTB and Downhill Cycling inherit Mountain Biking.
- Hand Cycle, Velomobile, and cycling-style Wheel Chair activities inherit Cycling.
- Motorcycling, Motorsports, and Driving use Speed → Altitude → Heart Rate → Temperature rather than inheriting athlete-powered cycling.
Cross-country and winter sports
| Activity modes |
Ordered candidates |
| Cross-country Skiing, Roller Skiing |
Altitude → Heart Rate → Power → Speed → EPOC → Vertical Speed → Cadence → Pace → Temperature |
| Snowshoeing |
Heart Rate → Altitude → Vertical Speed → Speed → Cadence → Pace → Temperature → EPOC |
| Alpine Skiing, Snowboarding, Telemark Skiing |
Heart Rate → Altitude → Speed → Vertical Speed → Temperature |
Aliases/inheritance:
- Nordic Skiing inherits Cross-country Skiing.
- Backcountry Skiing inherits Ski Touring unless canonical source metadata identifies it as Cross-country Skiing.
- Snowmobiling uses Speed → Altitude → Heart Rate → Temperature.
- Ice Skating follows the water/rowing-style speed profile below because its useful ordered candidates are Heart Rate → Speed → Cadence → Sea-level Pressure → Temperature.
Swimming
| Activity modes |
Ordered candidates |
| Pool Swimming |
Heart Rate → Swim Pace → Stroke Rate → SWOLF → Temperature → EPOC |
| Open Water Swimming |
Heart Rate → Swim Pace → Stroke Rate → Speed → Temperature → EPOC |
Rules:
- Logical Pace must resolve to Swim Pace for swimming activities.
- Stroke Rate and SWOLF remain valid profile concepts but are skipped when they are not available as ordinary chart panels.
- Do not silently substitute Cadence for Stroke Rate without verified source semantics.
- Swim-length tables and swim-length chart markers remain separate features and are not replaced by this profile.
- If only Heart Rate and Swim Pace are eligible, show two charts rather than adding an irrelevant third chart.
Water sports and rowing
| Activity modes |
Ordered candidates |
| Sailing |
Heart Rate → Speed in knots → Sea-level Pressure → Temperature |
| Stand Up Paddling, Surfing, Canoeing, Ice Skating, Kitesurfing, Windsurfing, Rowing |
Heart Rate → Speed → Cadence → Sea-level Pressure → Temperature |
| Indoor Rowing, Crosstrainer |
Heart Rate → Speed → Cadence → Temperature |
Aliases/inheritance:
- Kayaking, Paddling, and Rafting inherit the paddled-water profile.
- Boating inherits Sailing.
- Wakeboarding and Water Skiing use Heart Rate → Speed → Sea-level Pressure → Temperature; Cadence is not promoted.
- Speed in knots is a unit presentation of the Speed family, not a separate raw-stream requirement.
Fitness, flexibility, team, combat, and racket sports
| Activity modes |
Ordered candidates |
| Aerobics, Yoga, Circuit Training, Stretching, Gym, Cheerleading, Combat, Boxing, Bowling, Dancing, Gymnastics, Kettlebell, Crossfit |
Heart Rate → Temperature |
| Softball, Floorball, Handball, Basketball, Soccer, Ice Hockey, Volleyball, American Football, Baseball, Rugby |
Heart Rate → Temperature |
| Tennis, Badminton, Table Tennis, Racquet Ball, Squash, Cricket, Padel |
Heart Rate → Temperature |
Coverage rules for related canonical types:
- Strength Training, Weight Training, Workout, Training, Indoor Training, Fitness Equipment, HIIT, Cardio Training, Pilates, Flexibility Training, and Match inherit Heart Rate → Temperature.
- Football inherits the team-sport profile.
- Elliptical Trainer inherits Crosstrainer.
- Do not backfill Speed, Pace, Altitude, or Power merely to reach three charts.
- Temperature remains low priority and appears automatically only when the user enabled it globally and the source contains valid data.
Diving and underwater activities
| Activity modes |
Ordered candidates |
| Scuba Diving, Free Diving |
Heart Rate → Temperature |
| Snorkeling |
Depth → Temperature → Heart Rate → Speed → Swim Pace |
| Mermaiding |
Depth → Temperature → Heart Rate |
Rules:
- When the pinned Dive Profile is present, its Depth, Temperature, and Heart Rate series own the automatic presentation.
- Do not automatically duplicate a metric in the ordinary chart stack when the pinned profile already renders it.
- The metric may remain manually selectable in Visible charts if the ordinary chart implementation supports it.
- Generic Diving inherits the appropriate underwater profile based on available depth data; otherwise use Heart Rate → Temperature.
Unspecified and empty modes
| Activity modes |
Ordered candidates |
| Unknown Sport, Other, Generic, Unspecified |
Heart Rate → Altitude → Pace → Speed → EPOC → Temperature |
| General fallback |
Heart Rate → Altitude → Power → Pace → Speed → EPOC → Temperature |
| Transition |
No automatic ordinary charts |
Use the general fallback only after exact, alias, and family resolution. The fallback is still filtered by the user’s Default chart metrics and actual activity data.
Metric-family normalization
The resolver must operate on logical families rather than one unit-specific stream ID.
At minimum normalize:
- Heart Rate and its supported display form.
- Depth and Depth in feet.
- Pace and minutes-per-mile variants.
- Swim Pace and yards/meters variants.
- Speed, Speed in knots, and other unit variants.
- Grade-adjusted Pace and Speed variants without promoting them unless explicitly recommended.
- Power, Air Power, left/right Power, and supported primary Power display behavior.
- Altitude and supported display form.
- Vertical Speed and unit variants.
- Cadence.
- Temperature.
- Sea-level Pressure.
- EPOC.
Continue using existing unit settings and chart-building helpers. The profile must not hardcode a preferred unit.
Multisport, merged events, and activity selection
Define a stable selected-activity signature from canonical activity types, not activity names or provider labels.
Behavior:
- One selected activity: use its exact profile.
- Multiple selected activities with the same canonical type: use that exact profile.
- Multiple types in one coherent family: use the family profile.
- Multiple heterogeneous families: use Multisport.
- Changing the selected activity may recalculate an automatic selection.
- Changing the selected activity must not erase a custom selection stored for another signature.
- Benchmark/merged events continue to show separate series per source activity; sport curation only controls panel visibility.
- Profile resolution must not alter chart alignment, overlays, x-axis choice, source colors, or activity-selection state.
Prefer storing custom visibility by event ID plus a stable sport/selection signature. If that is too invasive for the first implementation, document and test the exact per-event compromise rather than allowing accidental state leakage between multisport parts.
Specialized surfaces and duplicate prevention
Sport-aware defaults apply only to the ordinary event chart stack.
They must coexist with:
- Dive Profile;
- Performance Charts;
- Intensity distribution/zones;
- Power Curve;
- Durability;
- Cadence/Power analysis;
- Laps;
- Swim lengths;
- MTB jumps;
- Map and chart cursor synchronization.
A metric used by a specialized surface is not automatically excluded just because it is conceptually related. Exclude it only when the same event section already renders the same time-series metric and duplication would be redundant. Keep the rule explicit and testable.
For the initial delivery, the Dive Profile is the required duplicate-prevention case.
Visible charts UX
Update Visible charts so automatic recommendations are understandable without adding a large new configuration surface.
Required behavior:
- Show recommended metrics first.
- Label or group them as Recommended for .
- Show other available metrics in a separate Other available section.
- Preserve the checked state for currently visible panels.
- Keep unavailable metrics out of the menu.
- Preserve Show all charts.
- Add Reset to defaults when the current state is custom.
- Use Reset to recommended defaults for mixed/multisport selections.
- Announce visibility changes accessibly.
- Keep keyboard navigation, focus behavior, narrow-screen layout, and touch targets consistent with the current menu.
Do not add a modal or require configuration before viewing an event.
Settings behavior
Default chart metrics remains the global user preference and hard allow-list for automatic selection.
The feature must not:
- enable a globally disabled metric;
- reorder or rewrite the user’s stored global metric settings;
- make Include all recorded metrics equivalent to Show all charts;
- hide an explicitly selected metric only because it is not sport-recommended.
Potential follow-up, not part of this epic’s first delivery:
- Reorder global preferred metrics.
- Save a custom selection as the personal default for a sport.
- Manage all personal sport profiles in Settings.
Architecture
Create a deterministic, typed recommendation registry and resolver rather than scattering sport checks through the component.
Suggested responsibilities:
- sport-profile registry;
- alias and family resolution;
- exhaustive canonical-type coverage assertion;
- logical metric-family normalization;
- availability and user-preference intersection;
- automatic/custom selection provenance;
- selected-activity signature creation;
- specialized-surface exclusion input;
- result diagnostics usable by tests and optional content-free logging.
The resolver should accept plain values and return a plain result so it can be covered by narrow unit tests without rendering ECharts.
Do not duplicate Sports Lib’s canonical activity-type normalization or activity-group resolution. Use those APIs as the canonical sport identity layer and keep the app registry focused on presentation recommendations.
Delivery plan / suggested child issues
- Registry and exhaustive sport coverage
- Add typed profiles, aliases, family inheritance, logical metric families, and coverage tests.
- Selection resolver and persistence provenance
- Implement automatic/custom behavior, legacy migration safety, per-event/signature state, and reset.
- Event chart integration
- Apply recommendations after panel construction and preserve current chart behavior.
- Visible charts UX
- Add recommended/other grouping, reset action, accessibility, and responsive behavior.
- Multisport and specialized surfaces
- Cover selected parts, merged events, mixed profiles, and Dive Profile duplicate prevention.
- Help, regression coverage, and rollout validation
- Update user-facing help and complete focused component/helper tests.
Child issues should link back to this epic and avoid redefining the sport matrix independently.
Acceptance criteria
Core selection behavior
User control and persistence
Sport coverage
Multisport and specialized charts
UX and accessibility
Testing strategy
Add narrow deterministic tests before broad component coverage.
Resolver/helper tests
- Exhaustive canonical activity-type coverage.
- Exact profile, alias, family, fallback, and empty-profile resolution.
- Up-to-three selection.
- Sparse-data fallback.
- Global allow-list intersection.
- Logical unit-family matching.
- Unsupported metric skipping.
- Pinned-surface exclusions.
- Single, homogeneous, and heterogeneous activity signatures.
- Automatic/custom provenance and legacy migration.
Event chart component tests
- First-view automatic selection.
- Existing custom selection restoration.
- Manual toggle changes provenance.
- Reset to sport defaults.
- Include-all expands choices without changing visibility.
- Show-all explicitly changes visibility.
- Rebuilds preserve a valid custom selection.
- Sport selection changes automatic defaults.
- Worker and synchronous panel-building paths produce equivalent visibility.
- Dive Profile duplicate prevention.
- Merged/multisport behavior.
UX tests
- Recommended and other sections.
- Labels for exact and mixed sports.
- Keyboard/focus behavior.
- Screen-reader announcements.
- Responsive layout.
- No-data and partial-data copy.
Run the focused frontend Vitest suites after each implementation round, followed by the relevant broader frontend test set before completion.
Documentation requirements
Update the app Help content in the same change.
The Help text must explain:
- Default chart metrics are the user’s global automatic-visibility preference.
- Sport recommendations choose among those defaults.
- Include all recorded metrics adds choices but does not show them automatically.
- Visible charts is the per-event override.
- Show all charts is explicit.
- Reset returns an event to its current sport recommendation.
- Specialized charts may own a metric without duplicating it in the ordinary stack.
If the implementation introduces a durable persistence/state contract, document that contract under the appropriate frontend architecture documentation and link any new entry point from the README architecture section.
Rollout and compatibility
- No production deployment is part of implementation completion.
- Treat legacy selections as custom to avoid surprising existing users.
- Keep the curated registry deterministic and locally testable.
- Do not require reprocessing activity data.
- Do not modify existing activity documents.
- Do not change the registered MCP chart contract.
- Verify behavior with representative FIT/GPX/TCX/JSON/SML imports where fixtures already exist.
- Report any canonical sport types that can only use the generic fallback and decide explicitly whether they need a follow-up exact profile.
Summary
Curate the default event-detail chart stack by sport mode so each activity initially shows the most relevant recorded metrics instead of every globally enabled chart that happens to be available.
This is a feature epic covering the recommendation registry, selection rules, interaction with existing chart preferences, multisport behavior, persistence, specialized chart surfaces, user-facing controls, documentation, and regression coverage.
The central product rule is:
Problem
Event charts currently have several useful controls:
However, the initial visible stack is not sport-aware. A run, bike ride, pool swim, strength workout, sailing activity, and ski activity can all inherit the same global metric ordering. This can create long stacks, surface secondary metrics before sport-defining metrics, or show charts that are technically available but not useful for that activity.
Examples:
Product goals
Non-goals
Terminology and precedence
Required precedence
Concrete example
A run records Heart Rate, Pace, Power, Altitude, Cadence, Speed, and Temperature.
The user enables Heart Rate, Pace, Altitude, and Temperature under Default chart metrics.
The Running profile is:
Heart Rate → Pace → Power → Altitude → Cadence → Speed → EPOC → Vertical Speed → Temperature
The initial visible charts are therefore:
Power and Cadence are skipped because the user did not enable them as default metrics. Temperature remains available but is not promoted over the more relevant enabled metrics. If Include all recorded metrics is enabled, every other recorded chartable metric appears in Visible charts without becoming visible automatically.
Automatic versus custom selection provenance
The implementation must distinguish automatic defaults from explicit user choices.
Automatic selection
Custom selection
Existing stored selections
Existing non-empty per-event visibility values cannot reliably be classified as old automatic defaults versus user choices. Treat them as custom for migration safety.
Introduce versioned/provenance-aware storage for new state, or avoid persisting automatic selections until the user changes them. Do not destructively rewrite legacy storage.
Reset action
Add Reset to defaults to the chart actions or Visible charts menu.
Reset must:
Sport profile resolution
Resolve profiles in this order:
Every canonical activity type returned by Sports Lib must resolve deterministically. Add an exhaustive coverage test so new Sports Lib activity types cannot silently inherit arbitrary ordering.
Metric names below are logical chart families. Unit-specific variants must resolve through existing unit settings, and derived variants must remain grouped under the same logical recommendation.
Curated sport profiles
The ordered lists below are the complete candidate priority, not a promise that every activity contains every metric. The resolver selects the first available candidates after applying user preferences and exclusions.
Multisport
For a mixed selected-activity set, use this multisport profile. When exactly one constituent activity is selected, resolve that activity’s exact sport profile instead.
Running and navigation
Aliases/inheritance:
Walking, hiking, outdoor travel, and altitude sports
Coverage rules for related canonical types:
Cycling
Aliases/inheritance:
Cross-country and winter sports
Aliases/inheritance:
Swimming
Rules:
Water sports and rowing
Aliases/inheritance:
Fitness, flexibility, team, combat, and racket sports
Coverage rules for related canonical types:
Diving and underwater activities
Rules:
Unspecified and empty modes
Use the general fallback only after exact, alias, and family resolution. The fallback is still filtered by the user’s Default chart metrics and actual activity data.
Metric-family normalization
The resolver must operate on logical families rather than one unit-specific stream ID.
At minimum normalize:
Continue using existing unit settings and chart-building helpers. The profile must not hardcode a preferred unit.
Multisport, merged events, and activity selection
Define a stable selected-activity signature from canonical activity types, not activity names or provider labels.
Behavior:
Prefer storing custom visibility by event ID plus a stable sport/selection signature. If that is too invasive for the first implementation, document and test the exact per-event compromise rather than allowing accidental state leakage between multisport parts.
Specialized surfaces and duplicate prevention
Sport-aware defaults apply only to the ordinary event chart stack.
They must coexist with:
A metric used by a specialized surface is not automatically excluded just because it is conceptually related. Exclude it only when the same event section already renders the same time-series metric and duplication would be redundant. Keep the rule explicit and testable.
For the initial delivery, the Dive Profile is the required duplicate-prevention case.
Visible charts UX
Update Visible charts so automatic recommendations are understandable without adding a large new configuration surface.
Required behavior:
Do not add a modal or require configuration before viewing an event.
Settings behavior
Default chart metrics remains the global user preference and hard allow-list for automatic selection.
The feature must not:
Potential follow-up, not part of this epic’s first delivery:
Architecture
Create a deterministic, typed recommendation registry and resolver rather than scattering sport checks through the component.
Suggested responsibilities:
The resolver should accept plain values and return a plain result so it can be covered by narrow unit tests without rendering ECharts.
Do not duplicate Sports Lib’s canonical activity-type normalization or activity-group resolution. Use those APIs as the canonical sport identity layer and keep the app registry focused on presentation recommendations.
Delivery plan / suggested child issues
Child issues should link back to this epic and avoid redefining the sport matrix independently.
Acceptance criteria
Core selection behavior
User control and persistence
Sport coverage
Multisport and specialized charts
UX and accessibility
Testing strategy
Add narrow deterministic tests before broad component coverage.
Resolver/helper tests
Event chart component tests
UX tests
Run the focused frontend Vitest suites after each implementation round, followed by the relevant broader frontend test set before completion.
Documentation requirements
Update the app Help content in the same change.
The Help text must explain:
If the implementation introduces a durable persistence/state contract, document that contract under the appropriate frontend architecture documentation and link any new entry point from the README architecture section.
Rollout and compatibility