Files
samplez/rippr-src/docs/v1/README.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

69 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# v1 — the original recorder
v1 was specified as **MotoTrack**, a "bare-bones, highly resilient" recorder to capture GPS
telemetry during motorcycle group rides. Renamed to Rippr partway through.
The original brief is preserved verbatim in [original-spec.md](original-spec.md).
**Design priority, quoted from the brief:** *"Unbreakable execution over UI beauty."*
That framing drove every architectural choice and still holds.
## What shipped
A single-screen app with an un-killable foreground service writing GPS fixes to Room, plus
a REST uploader. Validated on a real ride — including max speed, which the emulator cannot
produce.
## Deviations from the spec, and why
The spec was written as complete, paste-ready code. Most of it was sound; these parts were
not, and were changed deliberately.
| Spec said | What shipped | Why |
|---|---|---|
| `super.onCreate()` in `MainActivity` | `super.onCreate(savedInstanceState)` | Would not compile |
| `kapt` for Room | **KSP** | kapt is 2–3× slower and unreliable on modern Kotlin/JDK |
| Hardcoded `material3:1.2.1` beside a Compose BOM | Version catalog + BOM | Version conflict |
| `insertPoint()` per fix from the callback | Unbounded `Channel` + batched writer | A coroutine per fix gives no back-pressure guarantee; disk latency could block GPS |
| Activity-local `isRecording` | Process-wide state (later, in v2, the database) | Lied after process death |
| 1 Hz polling of two suspend DAO queries | Room `Flow` | Push, not poll |
| No stop action on the notification | Stop action + tap-to-open | |
| Nothing countering Doze / OEM killers | Battery-optimisation exemption prompt | A multi-hour ride must survive |
| No `Theme.MotoTrack`, no launcher icon | Generated both | Referenced by the manifest but never defined |
| "Streams over HTTP/REST" in the goal, no task for it | Full uploader: `synced` column, batched POST, retry, offline-safe | Stated as a goal, so it was built |
## Verification
The emulator harness built here was reused throughout v2:
- Merged manifest checked inside the APK — `foregroundServiceType=0x8` (location) confirmed
- 25 synthetic GPS fixes fed; final stored coordinate matched the fed value **exactly**
- Foreground service confirmed via `dumpsys` (`isForeground=true`, ongoing notification)
- Stop path verified: service gone, notification removed, final flush landed, 81 contiguous
point ids
**Speed was never verified in v1's automated testing** — the emulator reports zero
velocity. It was confirmed only on Dylan's first real ride.
## What v1 lacked
Feedback after that ride, which became the v2 brief:
> "app is simple and clean. I like that but it's missing stuff. There is no reset or pause
> button, there is no concept of a trip, it captures speed data but not path data."
Three of those four were the same missing concept — no `Trip` boundary. The fourth was a
misconception worth recording: **path data was already being captured.** Every point stored
latitude, longitude, altitude and bearing at 1–2 Hz from day one. What was missing was a
map to draw it on.
## Icon work
The launcher icon was designed in this phase. Five motorcycle-themed concepts were
generated locally as SVG, using Google Material Symbols (Apache-2.0) as reference geometry;
Dylan picked **Route** — a switchback trace inside a ring.
Lesson from that round: the first attempt hand-authored bezier paths without ever rendering
them, and they were poor. Building a rasterise-and-look loop (`rsvg-convert`) changed the
output quality completely. Generators live in `design/`.