Chaque pause effaçait jusqu'à 24 points de trace déjà parcourus
setPaused vidait `pendingRoute` pour « ne pas tracer la pause ». Mais ce tampon
ne contient que des points DÉJÀ acceptés par le filtre et DÉJÀ comptés dans
`distanceMeters` : ils attendent seulement leur écriture, qui ne part qu'au
seuil de routeFlushThreshold (25). À 1 Hz, c'est une douzaine de points en
moyenne, jusqu'à 24.
L'écart était donc visible : la distance affichée les incluait, la
HKWorkoutRoute non. Six arrêts sur une sortie VTTAE — feux, photos, ravito — et
jusqu'à 144 points manquaient à la trace, avec un D+ recalculé depuis elle qui
divergeait d'autant de celui affiché pendant la séance. Aucun log ne
mentionnait l'effacement.
Ils sont désormais écrits, via le même `Task { await flushPendingRoute() }` que
le flush au seuil. Le raisonnement du commentaire d'origine visait le point qui
SUIT la reprise, à des centaines de mètres de là — mais celui-là n'est pas
encore dans le tampon quand la pause commence, et c'est `implausibleSpeed` qui
l'écarte. Nettoyer la pause est l'affaire du filtre, pas du tampon d'écriture.
Pas de course possible : `isPaused` est posé avant, et `ingest` sort dès qu'il
est vrai — aucun point neuf ne peut s'ajouter pendant que le flush s'exécute.
Relevé § 2.5 de docs/AUDIT-2026-09-22.md, seul constat de la section vérifié
ligne à ligne avant correction. 88 tests Linux verts (RouteFilter compris), mais
ils ne couvrent pas ce fichier : CoreLocation n'existe pas sur Linux.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -142,9 +142,21 @@ final class LocationTracker: NSObject, ObservableObject {
|
||||
guard isTracking else { return }
|
||||
isPaused = paused
|
||||
if paused {
|
||||
// Le point qui suivra la reprise serait à des centaines de mètres :
|
||||
// on repart d'une origine neuve pour ne pas tracer la pause.
|
||||
pendingRoute.removeAll()
|
||||
// ⚠️ Ici se jouait une perte silencieuse. `pendingRoute` ne contient
|
||||
// que des points DÉJÀ acceptés par le filtre et DÉJÀ comptés dans
|
||||
// `distanceMeters` — ils attendent seulement leur écriture, qui ne
|
||||
// part qu'au seuil de `routeFlushThreshold` (25). À 1 Hz, c'est une
|
||||
// douzaine de points en moyenne, jusqu'à 24. Les jeter creusait un
|
||||
// écart visible entre la distance affichée et la trace enregistrée :
|
||||
// six arrêts sur une sortie, et jusqu'à 144 points manquaient à la
|
||||
// HKWorkoutRoute, avec un D+ recalculé qui divergeait d'autant.
|
||||
//
|
||||
// On les écrit donc au lieu de les perdre. Le raisonnement du
|
||||
// commentaire d'origine visait le point qui SUIT la reprise, à des
|
||||
// centaines de mètres de là — mais celui-là n'est pas encore dans
|
||||
// le tampon, et c'est `implausibleSpeed` qui l'écarte. Nettoyer la
|
||||
// pause est l'affaire du filtre, pas du tampon d'écriture.
|
||||
Task { await flushPendingRoute() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user