Refresh the Flutter snapshot: LAUNCH.md and the iPhone verification pass

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 09:45:10 -05:00
parent e8d8bcacda
commit 14289befb0
7 changed files with 409 additions and 1 deletions

View File

@@ -0,0 +1,89 @@
# iPhone verification — what a Mac can prove, and what needs a phone
Scoped and then executed. Everything in the first table has been **run**; everything in
the second cannot be done without hardware and a rider.
Reproduce with:
```bash
xcrun simctl location booted start --speed=15 --interval=1 \
51.0447,-114.0719 51.0530,-114.0719 51.0610,-114.0800 51.0700,-114.0900 &
( for i in $(seq 1 90); do xcrun simctl privacy booted grant location-always com.rippr.port; sleep 1; done ) &
flutter test integration_test/ride_simulation_test.dart -d <sim-id>
```
---
## The finding that matters most
**The iOS simulator moves, but still reports zero speed.**
`simctl location start --speed=15` genuinely interpolates between waypoints over time —
unlike Android's `adb emu geo fix`, which teleports. That looked like it might finally
make speed testable locally. It does not:
```
RIPPR-PROBE fixes=8 speeds=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
```
Eight fixes, every one zero. Measured, not assumed — the assumption was worth attacking
and it survived.
The consequence is visible in a real recorded ride:
```
trip=1 points=18 distanceM=245.5 maxSpeedKmh=0.0 movingMs=0 segments=1
```
**245 metres travelled, zero moving time.** Distance comes from consecutive positions, so
it works. Moving time comes from `speedKmh >= 1.5`, so with speed pinned at zero every
sample falls under the noise floor. That is correct behaviour on bad input, and it is
exactly why `REAL-RIDE-CHECKLIST.md` cannot be skipped.
---
## ✅ Verified locally, on a Mac
| What | How | Evidence |
|---|---|---|
| App builds and launches on iOS | `flutter build ios --simulator`, `simctl launch` | Runs |
| The real UI renders | Screenshot of the record screen | Wordmark, SPEED headline, Ready state, 72dp button all correct |
| **The permission dialog and its usage string** | Screenshot | *"Rippr records the GPS track of your ride… Nothing is recorded until you press Start."* — the Guideline 5.1.1 item, confirmed rendering |
| Drift opens against real iOS storage | Integration test | `rippr_db.sqlite` + WAL created in the app container |
| Plugin registration resolves | Integration test | geolocator, path_provider, shared_preferences all load |
| CoreLocation delivers fixes | Integration test | 18 fixes in ~15 s |
| **Distance accumulates from real movement** | Integration test | 245.5 m, latSpan 0.00197° — consistent |
| A trip persists and is listed | Integration test | `completedTrips=1`, Card present |
| Segments are created | Integration test | `segments=1` |
| Trip detail renders, including the map | Integration test | `DISTANCE` found on screen |
| Navigation record → rides → detail | Integration test | All transitions land |
| Cold start with no ride | Integration test | Lands idle, no crash |
| App icon under the iOS mask | Rendered preview | Ring and orange accent survive the superellipse |
## ⛔ Needs a real iPhone
| What | Why a simulator cannot |
|---|---|
| **Max speed, average moving speed** | CoreLocation reports 0.0 — measured above |
| **Moving time** | Derived from speed; reads 00:00:00 locally even after 245 m |
| **Speed colouring on the map** | Every path renders in one colour |
| **Elevation gain** | Simulated altitude has no correlated GPS error; the ~30 m drift question is unanswerable here |
| **Background suspension when stationary (I3)** | The simulator does not model iOS's power-management suspension. **This decides whether `geolocator` is sufficient or the paid engine is needed.** |
| **Screen-lock continuation** | Real background lifecycle only |
| **Phone call / interruption handling** | No telephony |
| **Battery drain** | No meaningful power model |
| **The blue background-location indicator** | Real background mode only |
| **Real GPS accuracy and dropouts** | Simulated fixes are perfect; the accuracy gate never rejects anything |
| **App Store review** | Requires submission |
## 🟡 Gap in local coverage, worth naming
**No screenshot of the iOS trips list or detail screen.** They are verified
*functionally* — the integration test asserts the Card and the `DISTANCE` readout are
present — but not *visually*, because tapping the iOS simulator is not scriptable the way
`adb shell input tap` is, and every fresh install re-prompts for location, which sits over
the UI during the capture window.
Android's equivalents were checked visually. On iOS this is worth a manual look next time
the app is built for a device: launch it, record a short ride by hand, and eyeball the
list, the detail stats and the map.

View File

@@ -797,3 +797,36 @@ tests the project has ever had.
**What remains is not code.** It is a rider, two phones, and
[REAL-RIDE-CHECKLIST.md](REAL-RIDE-CHECKLIST.md).
---
## iPhone verification pass
Scoped and executed: [IOS-VERIFICATION.md](IOS-VERIFICATION.md).
**An assumption was attacked and survived.** `simctl location start --speed=15`
interpolates between waypoints over time — unlike Android's teleporting `geo fix` — which
looked like it might make speed testable locally at last. A probe captured 8 fixes, every
one reporting **0.0 m/s**. So "no simulator produces velocity" holds on iOS too, and the
real-ride checklist remains mandatory.
A full ride was recorded on the simulator through the real UI:
```
trip=1 points=18 distanceM=245.5 maxSpeedKmh=0.0 movingMs=0 segments=1
```
245 metres of travel with **zero moving time** — correct behaviour given speed is pinned
at zero, and a compact illustration of exactly what local testing cannot reach.
Also confirmed visually on iOS: the record screen renders correctly, and the location
permission dialog displays the specific usage string written for Guideline 5.1.1.
`integration_test/ride_simulation_test.dart` is kept — it is a reusable local
verification, not a throwaway.
**Named gap:** no screenshot of the iOS trips list or detail screen. Both are verified
functionally, but tapping the iOS simulator is not scriptable the way `adb shell input
tap` is, and a fresh install re-prompts for location over the UI. Android's equivalents
were checked visually.