One file per feature, in the v2 shape that worked: goal, context, design, implementation, acceptance criteria, tests, risks, out of scope -- written before implementing so the risks are on paper rather than walked into. Three carry more weight than their size suggests. V3-01 ships the port's first real migration, and since the destructive fallback is gone, getting addColumn and a v1-database test right matters more than the feature. V3-08 forces a routing-engine decision with ongoing cost, so it sits behind a RoutingService interface mirroring what LocationSource did for GPS. V3-13 is not code at all -- it answers the three questions open since v2, and V3-15 may close unbuilt as a result, which is a legitimate outcome. Several tickets record constraints that are easy to lose: no activity picker in front of Start, because the founding premise is press-and-go with gloves; the Route-to-Trip foreign key must not cascade, or deleting an old plan deletes the ride; V3-14 will deliberately break the parity harness by adding GPX <type>, and that expectation should be updated rather than the check dropped; and V3-16 must not regress the explicit text colours that exist because of the black-on-black bug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2.8 KiB
V3-13 — Real-ride measurements: elevation, battery, map lifecycle
Phase Quality · Depends on the real-ride checklist · Size M · Status Blocked on riding
Goal
Answer three questions that no amount of code can answer, then act on the answers.
Context
Three items have been carried since v2 because nothing but a real ride settles them. Grouped into one ticket because they share a prerequisite: riding, with instruments.
The three questions
1. Is elevation gain actually wrong?
~30 m of phantom gain per ten stationary minutes against synthetic ±8 m uniform noise. Real GPS altitude error is correlated — it wanders rather than jitters — so the true behaviour is unknown.
Do not tune this blind. Record a flat ride and see what it reports. Only then consider a longer smoothing window, a larger threshold, or the barometer — which most phones have and which is far more accurate than GPS altitude.
The port has an advantage the native app did not: tool/parity/run.sh proves the algorithm
is bit-identical to the Kotlin original, so any change can be measured against a known
baseline rather than guessed at.
2. What does it actually cost in battery?
Never measured, on either app. And V3-04/V3-05 make it worse: a lit screen and continuous map rendering are a different order of cost from a background service.
Measure three configurations over a multi-hour ride: pocketed with no map, pocketed with the live map on, and mounted with the screen awake.
3. Does the map leak?
flutter_map's lifecycle was wired carefully but never leak-tested across repeated
navigation. The native repo flagged the osmdroid equivalent as a known hazard.
Implementation
- Run the checklist in ../port/REAL-RIDE-CHECKLIST.md
- Record elevation on a known-flat route; compare against a barometric or surveyed source
- Battery: note the percentage at start and end for each configuration, with duration
- Memory: navigate rides → detail → back fifty times with DevTools attached, watching for monotonic growth
- Write the numbers into this file. The point is a record, not a vibe.
Acceptance criteria
- Flat-ride elevation gain recorded, with a verdict: acceptable or not
- Battery cost per hour recorded for all three configurations
- Memory across fifty navigations recorded, with a leak verdict
- Any resulting code change is justified by a number written down here
Tests
Measurement, not tests. Any fix that follows gets its own regression test, and elevation changes must be re-checked against the parity harness.
Risks
The temptation to tune elevation on a hunch. The v2 backlog says do not, twice, and the existing bound was already shown to pass on seed luck.
Out of scope
Fixes themselves. This ticket produces evidence; the fixes are separate work.