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.
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 -->
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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:
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 consumepoints.points.first.tAND 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.AudioCueService+gap-ahead.caf, works screen-locked; Android: newres/rawchime 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.UNUserNotificationCenter, categoryRETURN_TO_START, auth requested at recording start). Android: newtracking_alertsIMPORTANCE_HIGH channel (existingactivity_trackingis IMPORTANCE_LOW and immutable), notification id 921,ACTION_STOP_AND_SAVE/ACTION_DISMISS_RETURN_PROMPTservice actions.@AppStoragesheet on iOS; SharedPreferences dialog on Android). No region monitoring (needs Always — apps are deliberately When-In-Use).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 #Nin a PR closes it automatically.iOS
Checklist generated by the umbrella-tracker migration, 2026-08-07 — 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 #Nwithin 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 siblingcross-links in each issue body. Closing here — the umbrella tracker is being
emptied.
— Opus 5 Agent