Files
samplez/rippr-src/docs/v3/BACKLOG.md
uhryniuk 247b9cdb3f Refresh Rippr snapshot and bundle with full project documentation
Re-exported at 46a0726, which adds README.md plus docs/ARCHITECTURE,
DEVELOPMENT, TESTING, v1 history including the original brief, and a v3
backlog. 112 files, and the bundle now carries 19 commits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 08:44:48 -05:00

6.4 KiB

v3 backlog

Everything known-outstanding as of v2.0.1, with enough context to pick up cold. Nothing here is committed to — it is a menu, roughly ordered by value.

Before planning anything: run the real-ride checklist in ../TESTING.md. Several items below may turn out to be non-issues, and others may appear that nobody has thought of.


1. Carried over from v2 — the honest debt

Elevation gain accuracy · needs real data first

~30 m of phantom gain per ten stationary minutes against synthetic ±8 m uniform noise. Real GPS altitude error is correlated rather than uniform, so the true behaviour is unknown.

The current implementation is a 15-sample moving average plus reversal hysteresis (see ../ARCHITECTURE.md). A naive version reported 1498 m over a parked bike, so the guard rails matter.

Do not tune this blind. Record a flat ride, check whether the reported gain is plausible, and only then adjust. If it needs work, options are a longer smoothing window, a larger threshold, or using barometric pressure where available (much more accurate than GPS altitude, and most phones have the sensor).

Compose UI tests · the largest coverage gap

Zero UI tests across six screens. Everything was verified by manual screenshot. Worth covering: navigation record→trips→detail→back, rotation/state retention, empty states, NotFound, chart degradation below two points, selection mode enabling Merge only at two.

Unmeasured, and probably should be

  • Battery drain over a multi-hour ride — never measured, and it is the thing most likely to make the app unusable in practice
  • Map memory across repeated navigation — the osmdroid lifecycle is a known hazard and the wiring was never leak-tested
  • GPX import into Strava/Garmin — validated against an XML parser, but schema validity does not guarantee a consumer accepts it

2. The original v3 candidate — live group ride view

Deferred from v2 as "needs real server work". This was in the v1 brief's goal statement, so it has been the intended destination all along.

Already in place:

  • TelemetryUploader — batched POST, retry, offline-safe, cannot stall recording
  • synced column and backlog semantics
  • trip_id / segment_id per point, so a server can reconstruct rides and pauses
  • Config.deviceId — stable per-install id to distinguish riders

Missing:

  • A server. Nothing exists. This is the actual work.
  • UI for the endpoint — currently only reachable via Config.setUploadEndpoint()
  • Other riders' positions on a map, and a live map at all (see below)
  • Auth, rider identity, group membership

Worth deciding early: this is the point where Rippr stops being a local-only app. That brings hosting, privacy, and location-sharing consent into scope.


3. Live map — explicitly deferred, revisit deliberately

v2 has no live map by design, on Dylan's reasoning:

"we hit start, put the phone in our pocket and then stop it after the ride. So having a live map doesn't make sense at all honestly, we just wanna see the path render after."

TrackingService holds no reference to any map type, and the map exists only inside the detail screen's Compose lifecycle. That boundary is deliberate and worth preserving unless there is a real reason to cross it.

Group riding is the one plausible reason — seeing where the others are while stopped at a junction. If it happens, keep it screen-on-only and never let the service touch it.


4. Smaller items

Item Notes
Trip splitting Merge exists; split does not. The natural counterpart.
SAF export Dropped in T16 as unnecessary — share sheet covers it. Add if a real need appears.
Auto-pause Detect a stop and pause automatically. Rejected in v2 as unreliable in traffic; revisit only with real ride data showing it would help.
Distance units Metric only, hardcoded. Trivial to add a preference.
Settings screen None exists. Config has endpoint, deviceId, mapEnabled — the map toggle currently lives on trip detail because one switch did not justify a screen.
Offline tile pre-download osmdroid caches what it renders; a mountain ride with no signal shows blank tiles. Respect OSM's usage policy — no bulk prefetch of their public servers.
Notification live stats Show distance/duration in the ongoing notification, readable without unlocking.
Crash reporting None. A recorder that dies mid-ride currently leaves no trace beyond logcat.

5. Things that must not regress

Hard-won and easy to undo by accident. Each has a comment in the code explaining why.

  1. The unbounded Channel + single batched writer. Do not write to the database from the location callback.
  2. Points stamped with tripId/segmentId at creation. Refactoring this into a write-time lookup breaks the pause guarantee silently.
  3. Recording state derived from the database. Never reintroduce an in-memory flag.
  4. fallbackToDestructiveMigration() stays removed. Any schema change ships a Migration against app/schemas/com.rippr.data.AppDatabase/2.json.
  5. Decimation is render-only. It must never reach storage or export.
  6. RipprTheme's Surface. It sets LocalContentColor; without it, text without an explicit colour renders black-on-black and disappears.
  7. The map zoom clamp. zoomToBoundingBox ignores maxZoomLevel; a short ride will render an empty grid without it.
  8. Instrumented tests use in-memory databases. One previously wiped the real device database in setUp.

6. Reading order for picking this up cold

  1. ../../README.md — what the app is and its current state
  2. ../ARCHITECTURE.md — why it is built this way
  3. ../v2/PROGRESS.md — every bug found during v2 and how
  4. ../TESTING.md — especially "What the emulator cannot verify"
  5. ../DEVELOPMENT.md — when you actually need to build something

The v2 planning approach worked well and is worth repeating: one document per task with goal, context, design, acceptance criteria and risks, written before implementing, plus a running progress log recording what actually went wrong. Several bugs were caught precisely because the risk had been written down first — and one (the osmdroid lifecycle) was written down and then walked into anyway, which is its own lesson.