chore(ideai): synchronise etat de suivi (tickets, agents)

This commit is contained in:
2026-07-29 11:22:17 +02:00
parent 30c6259748
commit dd0c124818
32 changed files with 1415 additions and 75 deletions

View File

@ -0,0 +1,103 @@
---
issueRef: "#172"
version: 2
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedAt: 1785272880017
---
## #172 — Cadrage Main (2026-07-28)
### Décision produit
Direction validée :
- la montre reste un **capteur + télécommande** ;
- le téléphone reste **source de vérité métier** ;
- on optimise le trafic et la chauffe par **batching côté montre**, pas par déplacement de logique métier.
### 1. Télémétrie stats montre
Deux modes à cadrer :
- **écran montre allumé** : cadence plus fréquente pour un live crédible ;
- **écran montre éteint / ambient** : flush agrégé toutes les ~30s, inspiré du comportement observé sur Heavy.
La montre ne calcule pas les agrégats métier finaux. Elle bufferise seulement des échantillons ou micro-agrégats transport :
- FC : min/max/moy locale de fenêtre + latest utile à l'affichage ;
- distance/calories : latest cumulée de fenêtre, jamais recalcul métier final ;
- timestamps de capture et contexte d'exécution.
Le téléphone :
- persiste ;
- fusionne ;
- construit les agrégats de séance / étape / série / exercice / historique ;
- résout les conflits et les trous.
### 2. Score manuel montre
Décision : **oui au debounce 500ms, non au "score final sans contexte"**.
Le flux cible minimal :
- la montre met à jour le score **optimistement** à chaque tap ;
- chaque tap reset un timer de 500ms ;
- au silence de 500ms, la montre envoie au téléphone une intention de type `setManualScore` contextualisée ;
- le téléphone valide, persiste, reprojette ;
- la montre se recale silencieusement sur la projection confirmée.
### 3. Garde-fous architecture
- Pas de logique métier durable sur la montre.
- Pas de calcul d'historique ni de règle d'invariants sur la montre.
- Chaque message montre -> téléphone doit embarquer le contexte minimal : `sessionId`, indices d'exécution, `baseRevision`, horodatage.
- Rejet/conflit côté téléphone : la projection confirmée gagne toujours.
- Crash montre avant flush : perte limitée à la fenêtre non flushée, acceptable pour le score seulement si la montre ne prétend jamais avoir persisté côté téléphone.
### 4. Contrat à cadrer ensuite
Ticket attendu après celui-ci :
- extension ou adaptation du contrat watch bridge pour batches télémétrie ;
- ajout d'une commande contextualisée `setManualScore` ou équivalent ;
- stratégie de flush explicite selon état écran / foreground / ambient ;
- QA device sur chauffe, batterie, cohérence de resync.
## Cadrage Architect (2026-07-28)
Statut : **cadrage exploitable, prêt pour découpage dev**.
### Architecture cible minimale
- Garder `phone = source de vérité`, `watch = capteur + télécommande`.
- Conserver `WatchCompanionCommandHandler` comme point d'entrée unique des intentions montre.
- Ajouter un flux applicatif téléphone dédié pour la télémétrie batchée : `WatchTelemetryBatchIngress` -> validation -> appel de `WorkoutTelemetryUseCases.recordTelemetrySample(...)` pour chaque sample -> `WorkoutHistoryUseCases.updateHeartRateSummary(...)` au flush final.
- La montre ne calcule ni score final ni agrégats métier ; elle ne bufferise que du transport.
### Télémétrie batchée watch -> phone
- Recommandation : nouveau DTO `WatchTelemetryBatch`, `schemaVersion = 5`, nouveau path message `/gametime/watch/telemetry-batch`.
- Le téléphone déduplique au niveau **sample** (`sampleId` stable), pas au niveau batch.
- `WatchSensorSummary` est conservé pour le résumé final de séance, pas remplacé.
### Stratégie interactive vs ambient/screenOff
- `interactive` : flush toutes les `5s` max.
- `ambient/screenOff` : flush toutes les `30s` max.
- Flush immédiat aussi sur : fin de séance, pause explicite si la collecte s'arrête, reconnexion téléphone, changement d'état écran, buffer plein.
- Cap de sécurité : couper les batches trop gros (~60 samples).
- Une petite outbox locale de télémétrie côté montre est acceptable pour survivre à un crash : c'est du transport, pas du métier.
### Score manuel debounce
- Décision Architect : **ne pas faire de `setManualScore(value)` comme contrat principal**.
- Recommandation : un batch d'intentions delta, type `applyManualScoreDeltaBatch`.
- La montre accumule les taps `+/-` pendant `500 ms`, puis envoie un seul delta net avec `sessionId`, position courante, `baseRevision`, horodatage.
- Le téléphone applique le delta seulement si la cible métier est toujours la même ; sinon rejet et resync.
### Invariants et risques
- La montre ne calcule jamais la valeur finale du score.
- Les écritures d'historique et agrégats durables restent côté téléphone.
- Une intention score batchée n'est applicable que si `sessionId + scope + position courante` correspondent encore.
- Les retries de télémétrie ne doivent jamais dupliquer les samples : `sampleId` stable obligatoire.
- En cas de crash montre :
- score pending perdu puis recalage sur projection téléphone ;
- télémétrie non flushée reprise depuis l'outbox local.
- En reconnexion :
- resync projection immédiat ;
- flush immédiat de l'outbox télémétrie ;
- aucun replay d'anciennes intentions score.
### Lots recommandés
1. `B1 [DevBackend] Contrat bridge v5 et ingress télémétrie batchée`
2. `B2 [DevBackend] Application téléphone score debounce + validation de cible`
3. `B3 [DevBackend] Déduplication, retries, flush final`
4. `F1 [DevFrontend] Buffer montre télémétrie et stratégie interactive vs ambient`
5. `F2 [DevFrontend] Score optimiste debounce 500 ms`
6. `QA1 [QA] Matrice de cohérence et robustesse`

View File

@ -0,0 +1,20 @@
---
id: "7536c1ce-3683-4fb6-989f-7a6d3365cc69"
number: 172
title: "[Architect] Cadrage batching stats montre et debounce score montre -> téléphone"
status: "closed"
priority: "high"
sprint: "2c0dd1ea-8809-49ff-adc1-aa8820815ee7"
links: [{"target":"#119","kind":"relatesTo"},{"target":"#155","kind":"relatesTo"},{"target":"#156","kind":"relatesTo"},{"target":"#158","kind":"relatesTo"},{"target":"#163","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
createdAt: 1785257860728
updatedAt: 1785272880017
version: 2
---
Formaliser une architecture montre/téléphone plus économe en batterie et en requêtes :
- statistiques montre collectées localement puis envoyées au téléphone par batch/flush périodique, notamment écran montre éteint ;
- téléphone propriétaire des agrégats métier, de l'historique et des décisions ;
- montre limitée aux capteurs qu'elle seule connaît et aux commandes utilisateur ;
- score manuel montre avec UI optimiste locale et envoi debounce au téléphone, sans déplacer la logique métier sur la montre.