Files
rippr/docs/v3
uhryniuk 37fba4784a V3-02 + V3-03: settings screen, and metric/imperial units
Built together because V3-02's settings screen needed something real for
V3-03's units to control -- executed in reverse of the ticket numbering, but
both tickets are independently complete.

V3-03: UnitSystem (metric/imperial) lives in domain/models.dart alongside
Activity, defaulting from Platform.localeName on first launch. Storage stays
SI everywhere -- conversion happens only in ui/format.dart, at the last
possible moment, which is now documented as the file's central invariant.
Threaded through all three screens plus the speed histogram's bucket labels,
which relabel for display without changing how speedHistogram itself bins.
Export was deliberately left untouched: gpx()/geoJson() take no UnitSystem
parameter at all, a stronger guarantee than validating one would be.

V3-02: SettingsScreen reachable from the record screen. Map render toggle
(nothing previously exposed mapEnabledProvider to the user, despite it
existing since T15 -- there was nothing to "move off trip detail" as drafted),
unit selector, upload endpoint with http(s) validation, a copyable device id,
and a licences page via Flutter's built-in showLicensePage. Skipped
package_info_plus (static version string instead) and a privacy-policy link
(none published yet) as disproportionate to an S-sized ticket.

Neither ticket needed the ConfigNotifier the implementation notes proposed:
unitSystemProvider reuses the exact StateProvider-seeded-from-Config pattern
mapEnabledProvider already established, since Config mutates its own backing
SharedPreferences in place and re-assigning the same instance would never
notify a watcher anyway.

A real locale-dependent flake was caught, not just anticipated: a test
asserting a fresh Config defaults to metric failed, because this machine's own
locale resolves to a region in the imperial set. Fixed by seeding an explicit
value before asserting, and config_test.dart's locale test was written from
the start to only prove the fallback path doesn't throw, not to assert which
value it returns.

221 tests (211 -> 221): 13 format_test, 9 config_test, 9 settings_screen_test,
1 confirming the record screen's settings button is genuinely wired. Analyze
clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 14:23:43 -05:00
..
2026-08-17 10:41:35 -05:00
2026-08-17 10:41:35 -05:00
2026-08-17 10:41:35 -05:00
2026-08-17 10:41:35 -05:00
2026-08-17 10:41:35 -05:00
2026-08-17 10:41:35 -05:00

v3 tickets

One file per feature, in the shape that worked for v2: Goal · Context · Design · Implementation · Acceptance criteria · Tests · Risks · Out of scope. Written before implementing, so the risks are on paper before they are walked into.

Menu, not a commitment. Nothing here is scheduled.

Everything in v3 is buildable with no server. Group rides, accounts and paid cloud backup are v4 — see ../BACKLOG.md.

Before starting anything: ../port/REAL-RIDE-CHECKLIST.md. The port has never recorded a real ride, and item I3 may still force a change of GPS engine — which would land underneath several of these tickets.

The tickets

# Ticket Size Depends on
V3-01 Activity type per ride M —
V3-02 Settings screen S —
V3-03 Distance and speed units S V3-02
V3-04 Live map on the recording screen M —
V3-05 Mounted (handlebar) mode M V3-04
V3-06 Live stats in the notification S —
V3-07 Route drawing (pins, straight lines) M —
V3-08 Road-snapped routing and ETA L V3-07, V3-01
V3-09 Follow a planned route M V3-04, V3-08
V3-10 Trip splitting S —
V3-11 Offline tile pre-download M V3-04
V3-12 Crash reporting S —
V3-13 Real-ride measurements M riding
V3-14 GPX interoperability S V3-01
V3-15 Auto-pause M V3-13 (gated)
V3-16 Visual identity M V3-04, V3-05

Dependencies

V3-01 ──┬────────────► V3-08 ──► V3-09
        └──► V3-14           ▲
V3-07 ──────► V3-08          │
V3-02 ──► V3-03              │
V3-04 ──┬──► V3-05 ──┬───────┘
        ├──► V3-11   └──► V3-16
        └──► V3-09
V3-13 ──► V3-15  (gate: may close unbuilt)

no dependencies: V3-01 · V3-02 · V3-04 · V3-06 · V3-07 · V3-10 · V3-12

Three that carry more weight than their size suggests

V3-01 ships the port's first real migration. The destructive fallback is gone, so getting addColumn plus a v1-database test right matters more than the feature does — V3-07 and V3-09 both add migrations behind it.

V3-08 forces a routing-engine decision with ongoing cost and vendor implications. Behind a RoutingService interface, mirroring what LocationSource did for GPS.

V3-13 is not code. It answers the three questions that have been open since v2, and V3-15 may close unbuilt as a result — a legitimate and probably likely outcome.

Suggested order, if starting cold

  1. V3-01 — proves the migration path while the stakes are low, and unblocks V3-08/14
  2. V3-02 + V3-03 — small, self-contained, gives V3-01 a home
  3. V3-04 — the most visible change, and the gateway to four other tickets
  4. V3-07 — entirely independent; useful on its own before the routing decision
  5. V3-13 — as soon as there is a ride to measure

V3-12 is a good filler at any point. V3-16 should wait until the screens stop moving.