openspec: archive the detail catch-up changes, sync specs

Archive the three implemented + merged changes (activity-sport-type,
activity-stats, journal-elevation-profile): their deltas are promoted into
openspec/specs/, the changes move to changes/archive/2026-06-12-*, and the
three new capabilities are added to the CAPABILITIES index.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-06-12 15:58:17 +02:00
parent 1ba063a085
commit f1cae13605
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
19 changed files with 170 additions and 0 deletions

View file

@ -0,0 +1,66 @@
# activity-sport-type Specification
## Purpose
TBD - created by archiving change activity-sport-type. Update Purpose after archive.
## Requirements
### Requirement: Activity sport type field
An activity SHALL have an optional sport type drawn from a fixed set: `hike`,
`walk`, `run`, `ride`, `gravel`, `mtb`, `ski`, `other`. The field MAY be unset
(unspecified), and an unset value SHALL be valid for any activity.
#### Scenario: Sport type omitted
- **WHEN** an activity is created without a sport type
- **THEN** the activity is stored with no sport type
- **AND** it renders without a sport badge and with a generic feed verb
#### Scenario: Sport type out of range is rejected
- **WHEN** a create or update request supplies a sport type outside the fixed set
- **THEN** the request is rejected by schema validation
### Requirement: Setting sport type on create
The activity create form SHALL offer an optional sport-type selector, and the
chosen value SHALL be persisted with the activity.
#### Scenario: User selects a sport on create
- **WHEN** a user picks "Gravel" in the sport selector and creates the activity
- **THEN** the activity is stored with sport type `gravel`
- **AND** the detail page shows the gravel badge
### Requirement: Sport type normalization on import
The system SHALL normalize a connected service's sport/activity descriptor into the fixed set when importing an activity; descriptors with no confident match SHALL normalize to `other`, and providers that supply no descriptor SHALL leave the sport type unset.
#### Scenario: Komoot tour with a known sport
- **WHEN** a Komoot tour with sport `mountainbike` is imported
- **THEN** the created activity has sport type `mtb`
#### Scenario: Komoot tour with an unrecognized sport
- **WHEN** a Komoot tour with an unrecognized sport string is imported
- **THEN** the created activity has sport type `other`
#### Scenario: Provider without a sport descriptor
- **WHEN** a Garmin activity (no sport in its notification payload) is imported
- **THEN** the created activity has no sport type
### Requirement: Sport type display
The UI SHALL show a set sport type as a badge (icon plus localized label) wherever an activity is presented (detail page, feed card, profile activity list), and the feed verb SHALL reflect the sport; an unset sport type SHALL show no badge.
#### Scenario: Badge on the detail page
- **WHEN** a user views an activity whose sport type is `hike`
- **THEN** a hike badge with a localized label appears next to the title
#### Scenario: Sport-aware feed verb
- **WHEN** an activity with sport type `run` appears in the feed
- **THEN** the card phrasing reflects running (e.g. "went for a run")
#### Scenario: Localized label
- **WHEN** the UI locale is German
- **THEN** the sport badge label is rendered in German
### Requirement: Sport type federation
The ActivityPub serializer SHALL include a set sport type as an attachment when serializing an activity, without altering the existing object shape.
#### Scenario: Sport included in the Note
- **WHEN** an activity with sport type `ride` is federated as a Note
- **THEN** the Note carries a `sport` property value of `ride`
- **AND** the previously-emitted properties (distance, duration, elevation) are unchanged

View file

@ -0,0 +1,56 @@
# activity-stats Specification
## Purpose
TBD - created by archiving change activity-stats. Update Purpose after archive.
## Requirements
### Requirement: Reusable stat row
The UI SHALL render activity and route headline metrics through one shared stat-row component (value, localized label, unit) used on the feed card, the activity and route detail pages, and the profile activity list.
#### Scenario: Same component across surfaces
- **WHEN** distance is shown on the feed card, the detail page, and the profile list
- **THEN** all three render it via the shared stat-row component with the same label, unit, and formatting
#### Scenario: Compact subset keeps order
- **WHEN** a surface renders a subset of the headline metrics
- **THEN** the subset preserves the canonical order and labels (no reordering or relabeling)
### Requirement: Canonical headline metric set
The system SHALL define the canonical headline metric set, in order, as distance, time, average pace or speed, ascent, and descent.
#### Scenario: Detail page shows the full set
- **WHEN** a user views an activity with distance, duration, and elevation data
- **THEN** distance, time, average pace/speed, ascent, and descent are shown in that order
### Requirement: Average pace or speed, chosen by sport
The system SHALL compute an average rate from distance and time and SHALL present it as pace for foot sports (hike, walk, run) and as speed for wheeled or ski sports (ride, gravel, mtb, ski), defaulting to speed when the sport type is unset.
#### Scenario: Pace for a run
- **WHEN** an activity with sport type `run` is shown
- **THEN** the rate is presented as pace (min/km)
#### Scenario: Speed for a ride
- **WHEN** an activity with sport type `ride` is shown
- **THEN** the rate is presented as speed (km/h)
#### Scenario: Default when sport is unset
- **WHEN** an activity has no sport type
- **THEN** the rate is presented as speed
### Requirement: Moving time and elapsed time
The system SHALL display elapsed time and SHALL additionally display moving time when it can be derived from GPX trackpoint timestamps; when timestamps are unavailable, only elapsed time SHALL be shown.
#### Scenario: Both shown when trackpoint times exist
- **WHEN** an activity's GPX has trackpoint timestamps with stationary periods
- **THEN** both moving time and elapsed time are shown, and moving time is not greater than elapsed time
#### Scenario: Elapsed only when no timestamps
- **WHEN** an activity has no trackpoint timestamps
- **THEN** only elapsed time is shown
### Requirement: Localized metric formatting
The system SHALL format metric values and unit suffixes through localized strings, covering distance, elevation, time, speed, and pace.
#### Scenario: German units
- **WHEN** the UI locale is German
- **THEN** metric labels and unit suffixes render in German

View file

@ -0,0 +1,45 @@
# journal-elevation-profile Specification
## Purpose
TBD - created by archiving change journal-elevation-profile. Update Purpose after archive.
## Requirements
### Requirement: Elevation profile chart on detail pages
The route and activity detail pages SHALL render an elevation profile chart (distance on the x-axis, elevation on the y-axis) with a gradient area fill and a summary showing the highest and lowest points, whenever the activity or route has a usable elevation series. (Ascent and descent are shown in the headline stat row above the chart.)
#### Scenario: Chart shown for a route with elevation
- **WHEN** a user views a route whose GPX contains an elevation series
- **THEN** an elevation profile chart is shown with a highest/lowest summary
#### Scenario: Chart omitted without elevation
- **WHEN** an activity's GPX has no usable elevation data
- **THEN** no chart is rendered and the existing gain/loss figures remain
### Requirement: Chart-to-map highlight
The detail page SHALL highlight the corresponding location on the map when the user points at a position on the elevation chart.
#### Scenario: Hover chart highlights map
- **WHEN** the user moves the pointer along the elevation chart
- **THEN** a marker appears on the map at the location matching that distance along the route
### Requirement: Map-to-chart highlight
The detail page SHALL highlight the corresponding position on the elevation chart when the user points at the route line on the map.
#### Scenario: Hover map highlights chart
- **WHEN** the user moves the pointer along the route line on the map
- **THEN** the elevation chart marks the position matching the nearest point on the route
### Requirement: Click chart to center map
The detail page SHALL center the map on the corresponding location when the user clicks a position on the elevation chart, without modifying any data.
#### Scenario: Click chart pans map
- **WHEN** the user clicks a point on the elevation chart
- **THEN** the map centers on the matching location
- **AND** no route or activity data is changed
### Requirement: Localized summary labels
The elevation summary strip SHALL render its labels and units through localized strings.
#### Scenario: German summary labels
- **WHEN** the UI locale is German
- **THEN** the highest and lowest labels render in German