EPIC: Return-to-start stop prompt — chime + actionable notification (iOS/Android) #997

Closed
opened 2026-08-07 03:51:11 +00:00 by spikerj · 1 comment
Owner

While recording, if you return near your starting point after actually having left, prompt "stop recording?" — the forgot-to-stop scenario, caught in the moment instead of trimmed after the fact (complement to epic #992).

Locked decisions:

  • Shared pure detector state machine ported 2× (ReturnToStartDetector.swift/.kt), fed by raw ~1 Hz fixes — the accepted-points stream starves while standing still (both recorders gate on ≥2 s AND ≥5 m), so detection cannot consume points.
  • Constants: arm after wall-clock ≥5 min from points.first.t AND having been ≥100 m from start once (ghost-race proximity precedent); trigger = fix within 25 m of start with accuracy ≤20 m (user asked ~15 ft, but the pipeline admits 50 m-accuracy fixes — this is the reliable version; worse-accuracy fixes ignored, not streak-resetting); dwell 3 consecutive qualifying fixes spanning ≥4 s (kills drive-past/jitter); re-arm only after another ≥100 m excursion AND 3 min cooldown (lap-friendly). Paused → no-op + streak reset. Never auto-stops — emits an event only.
  • On fire: audible chime (iOS: existing AudioCueService + gap-ahead.caf, works screen-locked; Android: new res/raw chime self-played by the service + vibration — must not depend on POST_NOTIFICATIONS, which can be denied while recording proceeds) + high-priority notification with Stop & save and Keep recording actions.
  • Stop & save = stop + auto-save as "Untitled activity" (data loss is the enemy; rename later). iOS local notifications are greenfield (UNUserNotificationCenter, category RETURN_TO_START, auth requested at recording start). Android: new tracking_alerts IMPORTANCE_HIGH channel (existing activity_tracking is IMPORTANCE_LOW and immutable), notification id 921, ACTION_STOP_AND_SAVE/ACTION_DISMISS_RETURN_PROMPT service actions.
  • Settings toggle default ON (@AppStorage sheet on iOS; SharedPreferences dialog on Android). No region monitoring (needs Always — apps are deliberately When-In-Use).
  • Identical detector test matrix on both platforms.

Children: iOS and Android, independent.


Child issues (per-repo, auto-close on merge)

This epic is complete when every box below is checked. Each child lives in the
repo that holds its fix, so fixes #N in a PR closes it automatically.

iOS

  • spikerj/spikersoft-ios#17 — iOS: return-to-start stop prompt (epic #997) (was #998)

Checklist generated by the umbrella-tracker migration, 2026-08-07 — Opus 5 Agent

While recording, if you return near your starting point after actually having left, prompt "stop recording?" — the forgot-to-stop scenario, caught in the moment instead of trimmed after the fact (complement to epic #992). **Locked decisions:** - Shared pure detector state machine ported 2× (`ReturnToStartDetector.swift`/`.kt`), fed by **raw ~1 Hz fixes** — the accepted-points stream starves while standing still (both recorders gate on ≥2 s AND ≥5 m), so detection cannot consume `points`. - Constants: arm after wall-clock ≥5 min from `points.first.t` AND having been ≥100 m from start once (ghost-race proximity precedent); trigger = fix within 25 m of start with accuracy ≤20 m (user asked ~15 ft, but the pipeline admits 50 m-accuracy fixes — this is the reliable version; worse-accuracy fixes ignored, not streak-resetting); dwell 3 consecutive qualifying fixes spanning ≥4 s (kills drive-past/jitter); re-arm only after another ≥100 m excursion AND 3 min cooldown (lap-friendly). Paused → no-op + streak reset. Never auto-stops — emits an event only. - On fire: audible chime (iOS: existing `AudioCueService` + `gap-ahead.caf`, works screen-locked; Android: new `res/raw` chime self-played by the service + vibration — must not depend on POST_NOTIFICATIONS, which can be denied while recording proceeds) + high-priority notification with **Stop & save** and **Keep recording** actions. - Stop & save = stop + auto-save as "Untitled activity" (data loss is the enemy; rename later). iOS local notifications are greenfield (`UNUserNotificationCenter`, category `RETURN_TO_START`, auth requested at recording start). Android: new `tracking_alerts` IMPORTANCE_HIGH channel (existing `activity_tracking` is IMPORTANCE_LOW and immutable), notification id 921, `ACTION_STOP_AND_SAVE`/`ACTION_DISMISS_RETURN_PROMPT` service actions. - Settings toggle default ON (`@AppStorage` sheet on iOS; SharedPreferences dialog on Android). No region monitoring (needs Always — apps are deliberately When-In-Use). - Identical detector test matrix on both platforms. Children: iOS and Android, independent. <!-- BEGIN MIGRATED-CHILDREN --> --- ## Child issues (per-repo, auto-close on merge) This epic is complete when every box below is checked. Each child lives in the repo that holds its fix, so `fixes #N` in a PR closes it automatically. **iOS** - [ ] spikerj/spikersoft-ios#17 — iOS: return-to-start stop prompt (epic #997) <sub>(was #998)</sub> <sub>Checklist generated by the umbrella-tracker migration, 2026-08-07 — Opus 5 Agent</sub> <!-- END MIGRATED-CHILDREN -->
spikerj added the epic label 2026-08-07 13:43:04 +00:00
Author
Owner

Dissolved into per-repo issues as part of the umbrella-tracker breakup.

This epic could never auto-close from a merge, because Gitea only resolves
fixes #N within a single repo. Its work now lives where the code is:

iOS

Already shipped — verified against master and live prod during the migration, no issue filed:

The unit is tracked by the shared [Return-to-start] title prefix and by sibling
cross-links in each issue body. Closing here — the umbrella tracker is being
emptied.

— Opus 5 Agent

Dissolved into per-repo issues as part of the umbrella-tracker breakup. This epic could never auto-close from a merge, because Gitea only resolves `fixes #N` within a single repo. Its work now lives where the code is: **iOS** - spikerj/spikersoft-ios#17 — iOS: return-to-start stop prompt **Already shipped** — verified against master and live prod during the migration, no issue filed: - spikerj/spikersoft-issues#999 (complete) The unit is tracked by the shared `[Return-to-start]` title prefix and by sibling cross-links in each issue body. Closing here — the umbrella tracker is being emptied. — Opus 5 Agent
Sign in to join this conversation.