Two copies for two jobs. rippr-src/ is a browsable git archive export of the tracked tree at 2f76983 - no build outputs, no local.properties, no nested .git - which is convenient to read in gitea but carries no history and will drift. rippr-full-history.bundle is the real backup: all 18 commits, verified as "records a complete history" and test-cloned before committing. This matters because ~/dojo/rippr has no git remote and otherwise exists only on one machine. rippr-src/SNAPSHOT.md explains the difference and how to restore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.7 KiB
T18 — End-to-end verification + remove destructive migration
Phase 7 · Depends on all · Status Done (automated); real-ride checklist outstanding
Goal
Prove v2 works end to end, and close the one deliberate time bomb left in the schema.
Done when the full suite is green, a synthetic paused ride verifies correctly on the
emulator, the real-ride checklist passes, and fallbackToDestructiveMigration() is gone.
Context
v1's verification harness is proven and should be reused rather than reinvented — it caught real problems and produced the coordinate-exactness check that confirmed the pipeline end to end.
Two lessons from that round, both of which cost time:
- Wait for the UI, do not sleep. A cold start took 8.7 s; a 4 s sleep produced a
silently-missed tap and a false "the service didn't start" conclusion. Poll
uiautomator dumpfor the expected text. - The emulator cannot produce velocity.
adb emu geo fixteleports, soLocation.speedis always 0 and every recordedspeedKmhis 0.00. Anything speed-derived — max speed, moving time, average moving speed, speed colouring — is unverifiable on the emulator and must be checked on a real ride.
The destructive migration — remove it
AppDatabase carries fallbackToDestructiveMigration() from T02. It was correct: v1 data
was a test and Dylan explicitly authorised nuking it.
It is not correct once real rides are being kept. Left in place, the next schema change silently deletes every ride with no warning and no recovery. This is the single most dangerous line in the v2 codebase.
Removal:
- Delete the
fallbackToDestructiveMigration()call. - Confirm
app/schemas/com.rippr.data.AppDatabase/2.jsonis committed — it is the baseline every future migration is written against. - Add a short note to
docs/v2/README.mdrecording that migrations are now mandatory. - Verify a fresh install still creates the database correctly.
Verification
Automated
./gradlew assembleDebug testDebugUnitTest lintDebug connectedDebugAndroidTest
Expected coverage by this point: geo maths, statistics with the noisy-altitude regression case, GPX/GeoJSON structure and escaping, uploader behaviour, DAO relations and CASCADE, trip lifecycle transitions, merge correctness.
Emulator end-to-end
emulator -avd Medium_Phone_API_35 -no-window -no-audio -no-boot-anim -gpu swiftshader_indirect
adb install -r app/build/outputs/apk/debug/app-debug.apk
for p in ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION POST_NOTIFICATIONS; do
adb shell pm grant com.rippr android.permission.$p
done
Drive the UI (the service is exported=false, so am start-foreground-service is
correctly refused). Feed a ride, pause partway, feed more, stop. Then:
adb exec-out run-as com.rippr cat databases/rippr_db > /tmp/check.db # plus -wal
Assert: one Trip; two Segments; contiguous point ids; distance non-zero; no point in a closed segment; the rendered path shows a visible gap at the pause.
Real-ride checklist
The only way to validate anything speed-derived:
- Start, pocket the phone, ride, stop — matching actual usage
- Max speed plausible (this worked in v1 and must not regress)
- Distance plausible against the bike's odometer
- Moving time excludes stops
- Elevation gain plausible — not thousands of metres on flat ground, the classic hysteresis failure
- Path renders with no straight-line artefact across pauses
- Speed colouring visibly varies
- GPX export opens correctly in Google Earth or Strava
- Battery drain over a multi-hour ride acceptable
- Pause/resume survives a screen-off stretch
Outstanding work inherited from earlier tasks
- Compose UI tests for all four screens (T08–T11). None exist. Verification there was
manual screenshots plus the unit/instrumented suites. Needed: navigation
record→trips→detail→back, rotation state retention, empty state,
NotFound, and chart degradation below two points.
Acceptance criteria
fallbackToDestructiveMigration()removed2.jsoncommitted as the migration baseline- Full gradle verification green
- Emulator paused-ride assertions pass
- Real-ride checklist complete
- Compose UI tests written for T08–T11 screens
- Debug APK copied to
~/dojo/samplezand committed (matching the v1 handoff)
Risks / gotchas
- Forgetting the migration removal is the failure this task exists to prevent. Do it first, not last.
- Do not claim speed-derived features verified from emulator runs. State plainly what the emulator cannot test.
- Elevation gain is the most likely silent bug. Flat ground must read near zero.
Out of scope
v3+ work: live map, group ride view, settings UI for the upload endpoint.