chore(wip): consolidation intermédiaire multi-tickets (sprints Statistiques, UI, Bug resolution, Serveur-client)

Regroupe l'état de travail en cours réalisé dans un même worktree sur
plusieurs tickets/sprints (#85, #136, #145, #155-160, #162-164),
mélangeant des tickets QA et inProgress. Ne constitue pas une feature
terminée : commit de sauvegarde avant triage/split par ticket en
branches feature/* dédiées. Exclut les dossiers d'environnement de
build locaux et le heap dump parasite (.gitignore mis à jour).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 16:48:54 +02:00
parent 58272e354a
commit 917777e18b
279 changed files with 13546 additions and 674 deletions

View File

@ -0,0 +1,101 @@
---
issueRef: "#156"
version: 5
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedAt: 1785248859161
---
## Entrée architecture utilisateur — Main (2026-07-27)
Architect doit cadrer une architecture permettant :
- collecte **live** fréquence cardiaque, distance, calories depuis montre compatible ;
- affichage live téléphone + montre ;
- persistance pour après-séance et historique ;
- **fréquence cardiaque min / moyenne / max** avec détail **par étape, série et exercice** ;
- fallback totalement silencieux si un capteur ou une donnée manque ;
- alimentation future de graphiques historiques.
Point important : le chantier doit être découpé en plusieurs tickets exécutables à la suite, avec dépendances claires, sans polluer les carnets des tickets non concernés.
---
## Cadrage initial Architect (2026-07-27)
### Décision darchitecture
Traiter ce lot comme un sous-système `telemetry` séparé de la projection de séance. La projection continue de porter le contrôle de la séance, tandis que la télémétrie devient un flux orthogonal, plus fréquent, avec sa propre persistance et ses propres agrégats.
### Base existante
- Le watch bridge a déjà un pipeline capteur cœur: `WatchHeartRateCollector` côté watch et ingestion sur le téléphone via `WatchWearDataLayerAdapter`.
- Le téléphone a déjà un état actif in-memory pour la FC et une écriture dhistorique `averageHeartRateBpm` / `maxHeartRateBpm`.
- La projection montre `WatchSessionProjection` ne doit pas être le réceptacle des mesures live; elle est trop liée aux commandes et à la révision.
- Les écrans historique et exécution consomment déjà un `sensorUseCases`.
### Principes figés
- ne pas mélanger la télémétrie live avec la projection de commande ;
- ne pas réutiliser `estimatedCaloriesKcal` comme substitut de calories réelles si le watch compatible ne fournit pas la mesure ;
- ne pas faire dépendre lagrégation historique du temps darrivée des messages ;
- ne pas surcharger le moteur de progression existant ;
- fallback silencieux si métrique absente.
### Contrats nécessaires
- évolution du contrat watch bridge capteur vers un payload v2 ou nouveaux types `WatchTelemetrySample` / `WatchTelemetrySummary` ;
- `WatchTelemetrySample` doit porter au minimum :
- `sampleId` unique par session pour lidempotence ;
- `sessionId` ;
- `capturedAtEpochMs` ;
- le contexte dexécution au moment de la capture ;
- `programIndex`, `exerciseIndex`, `setIndex` ;
- `passageIndex` et `stepIndex` si disponibles ;
- ids snapshot si disponibles ;
- `heartRateBpm?`, `distanceMeters?`, `caloriesKcal?`.
- `WatchTelemetrySummary` doit porter au minimum :
- `sessionId` ;
- `sampleCount` ;
- FC `min/avg/max` ;
- distance totale ;
- calories totales.
- côté application, introduire un port de type `WorkoutTelemetryRepository` ou `ActiveWorkoutTelemetryRepository`.
- côté application, introduire un use case dédié `ActiveWorkoutTelemetryUseCases` ou équivalent.
- côté historique, ajouter des tables/agrégats dédiés pour les mesures brutes et les agrégats par scope.
- les scopes à supporter doivent être stables sur les coordonnées de séance : session, exercice, série, étape.
- pour la FC, stocker `min/avg/max` à chaque scope.
- pour distance et calories, stocker le total et la dernière valeur connue ; ne pas fabriquer des min/max si le capteur ne les fournit pas.
### Modèle de persistance recommandé
- une table de samples bruts pour la session active et lhistorique ;
- une table dagrégats matérialisés par scope ;
- `WorkoutHistory` peut conserver un résumé rapide de session pour la liste et len-tête ;
- les vues détail historique doivent lire les agrégats de scope, pas recalculer en widget.
### Flux cible
- Watch compatible : collecteur natif démarre si session active et source dispo ; publie des samples live vers le téléphone ; alimente aussi lUI watch locale.
- Téléphone : ladapter ingère les samples ; le use case met à jour un état live de télémétrie ; létat live alimente lécran séance ; les samples sont persistés.
- Clôture de séance : figer le résumé live ; matérialiser les agrégats session / exercice / série / étape ; écrire le résumé dans lhistorique.
- Reprise de séance : la télémétrie continue à partir de nouveaux samples ; les scopes sont recalculés sans mélanger les périodes de pause.
### Fallback silencieux
- watch non compatible ou permission refusée : métrique absente = valeur nulle, pas de bannière, pas derreur bloquante ;
- si un seul metric est disponible, on affiche seulement celui-là ;
- si aucune donnée nest disponible, lUI reste vide sur cette zone ;
- aucune métrique ne doit être synthétisée par heuristique pour masquer un manque de source.
### Dépendance UX
Aucune dépendance bloquante sur le contenu métier des contrats. Les seuls points pilotés par le rendu final sont :
- composition exacte de la zone live téléphone ;
- composition exacte de lécran principal et de lécran secondaire watch ;
- forme des graphiques historiques et hiérarchie visuelle.
### Découpage recommandé
- Lot 1: contrat watch telemetry v2 + collecteur watch multi-métriques.
- Lot 2: ingestion téléphone + état live persistant + écriture des samples.
- Lot 3: matérialisation historique + agrégats FC par scope + repository de séries pour graphes.
- Lot 4: branchements UI téléphone/watch et historique.
- Lot 5: QA des cas silencieux et des transitions de scope.
### Points de test
- watch compatible avec FC seule ;
- watch compatible avec FC + distance + calories ;
- watch non compatible ou permission refusée ;
- sample reçu en retard rattaché au bon scope via son horodatage ;
- pause / reprise ;
- fin détape, fin de série, fin dexercice ;
- historique récupérable sans recalcul coûteux.