diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e73382a..8b3fdd2 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -15,3 +15,18 @@ # Énumérations : converties en String par Room et Gson (par nom) -keepclassmembers enum com.hormonetrack.data.model.** { *; } + +# --- Moteur PK : « Tracé labs » (v1.6.0, bug #64 — trouvé en émulateur) --- +# Symptôme : en RELEASE SEULE, la courbe « Tracé labs » restait vide (ni +# dessinée ni légendée) alors que le même calcul fonctionne en debug et +# donne 276 points sur les mêmes données (régression web-miroir). Cause +# Prouvée au mapping R8 : `LabTrajectoryModel -> R8$$REMOVED$$CLASS$$...` — +# R8 full mode a SUPPRIMÉ la classe en inlinant computeLabAnchoredCurve +# (et son synthétique $default des paramètres par défaut) dans le call +# site du producer Compose ; le résultat n'y était plus correct. FIX : +# garder la classe ENTIÈRE — c'est le cœur scientifique de l'app (fonctions +# pures, zéro réflexion) : coût = quelques Ko de dex non compactés. +# ⚠️ Toute nouvelle fonctionnalité du pk/ qui « ne marche qu'en debug » : +# vérifier le mapping (`app/build/outputs/mapping/release/mapping.txt`) +# et étendre cette garde si besoin. +-keep class com.hormonetrack.pk.LabTrajectoryModel { *; } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index c7ee351..713e917 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -45,6 +45,11 @@ Versionnage : [SemVer](https://semver.org/). Releases taguées dans git (`v1.4.1 traitement, montée après une dose EV loguée après le dernier lab, flag off = comportement v1.5.0 bit-compatible, garde #61 sur la prolongation, gardes du helper d'horizon, `lastAnchorMs`. +- **Validé sur émulateur** (recette §16.ter, APK release + données + réelles seedées) — et heureusement : la validation a TROUVÉ le bug + #64 (courbe vide en release seule, inlining destructeur de R8 full + mode sur `LabTrajectoryModel`, cf doc §14). FIX : garde R8 explicite ; + re-validé en release : ancrée, prolongée, avertissement, 0 crash. ## [1.5.0] — 2026-09-11 (versionCode 31) diff --git a/docs/DEVELOPPEMENT.md b/docs/DEVELOPPEMENT.md index 7406030..c56d224 100644 --- a/docs/DEVELOPPEMENT.md +++ b/docs/DEVELOPPEMENT.md @@ -63,7 +63,7 @@ Fonctionnalités v1 : | Date | Événement | |---|---| -| 12 sept. 2026 (session v1.6.0) | **« Tracé labs » PROLONGÉ au-delà du dernier lab** (demande) : le tracé s'arrêtait AU dernier lab (v1.5.0) — justement la période la plus récente était invisible. FIX : chip `Prolonger` (5ᵉ de la rangée, off par défaut, désactivé tant que Tracé labs est off) → au-delà du dernier lab significatif, `courbe(t) = M(t) × ρ_last` (ρ CONSTANT — pas d'extrapolation de pente, elle divergerait sans base physiologique) ; M(t) inclut AUTOMATIQUEMENT les doses loguées après le dernier lab (une injection EV après des labs EEn refait monter la courbe — épinglé par test) ; horizon = dernière dose E2 + cutoffHours de son traitement (une seule source de vérité : `cutoffHours` rendu public) ; série SPLITTÉE en "LAB" (ancré) / "LABX" (prolongé, rose atténué α 0,55 + légende dédiée — l'estimation ne se confond pas avec le mesuré) ; branche "LABX" EXPLICITE dans le when de légende AVANT le else (leçon #63) ; **AVERTISSEMENT visible sous la légende quand la prolongation est affichée** (demande) : « simple simulation, sans garantie de correspondre au réel, basée sur tes labs qui peuvent eux-mêmes être erronés » (string FR/EN `lab_track_extend_warning`). < 2 ancres, modèle déjà éteint au dernier lab, ou demande finissant avant → pas de prolongation (retour v1.5.0 exact, épinglé bit-compatible). 8 nouveaux tests (191 verts / 168 sans données locales) + lint vert. | +| 12 sept. 2026 (session v1.6.0) | **« Tracé labs » PROLONGÉ au-delà du dernier lab** (demande) : le tracé s'arrêtait AU dernier lab (v1.5.0) — justement la période la plus récente était invisible. FIX : chip `Prolonger` (5ᵉ de la rangée, off par défaut, désactivé tant que Tracé labs est off) → au-delà du dernier lab significatif, `courbe(t) = M(t) × ρ_last` (ρ CONSTANT — pas d'extrapolation de pente, elle divergerait sans base physiologique) ; M(t) inclut AUTOMATIQUEMENT les doses loguées après le dernier lab (une injection EV après des labs EEn refait monter la courbe — épinglé par test) ; horizon = dernière dose E2 + cutoffHours de son traitement (une seule source de vérité : `cutoffHours` rendu public) ; série SPLITTÉE en "LAB" (ancré) / "LABX" (prolongé, rose atténué α 0,55 + légende dédiée — l'estimation ne se confond pas avec le mesuré) ; branche "LABX" EXPLICITE dans le when de légende AVANT le else (leçon #63) ; **AVERTISSEMENT visible sous la légende quand la prolongation est affichée** (demande) : « simple simulation, sans garantie de correspondre au réel, basée sur tes labs qui peuvent eux-mêmes être erronés » (string FR/EN `lab_track_extend_warning`). < 2 ancres, modèle déjà éteint au dernier lab, ou demande finissant avant → pas de prolongation (retour v1.5.0 exact, épinglé bit-compatible). 8 nouveaux tests (191 verts / 168 sans données locales) + lint vert. **+ Rattrapage validation émulateur §16.ter (oubliée, demandée par l'utilisatrice) → bug #64 TROUVÉ** : « Tracé labs » vide EN RELEASE SEULE (R8 full mode avait REMOVÉ la classe — mapping `R8$$REMOVED$$CLASS` — et inliné le calcul dans le producer ; debug OK, 191 tests JVM aveugles). FIX : `-keep class ...LabTrajectoryModel { *; }` ; validé émulateur APK release re-buildé avec les données réelles seedées : ancrée (7090 px rose + légende), prolongée (légende + avertissement), 0 crash. Tag v1.6.0 reposé sur le commit de fix AVANT publication d'APK (checklist §16 étape 4). **Checklist §16 : étape 3.bis « validation émulateur release OBLIGATOIRE avant tag » ajoutée.** | | 11 sept. 2026 (session v1.5.0) | **« Tracé labs »** (demande débattue) : courbe hybride `M(t)×ρ(t)` ancrée sur les labs — ρ log-linéaire entre labs, garde #61, E2 seul, fenêtre labs, chip off par défaut + scroll horizontal CONFINÉ (chip 4ᵉ coupé hors fenêtre, constat émulateur) + leçon #63 légende dupliquée ("LAB" tombant dans else TFS) ; ChartSeries.showExtrema=false pour la série ; 11 tests LabTrajectoryModelTest (183 verts) + lint ; validé émulateur (courbe passe exactement sur le lab 248, 0 crash). | | 5 sept. 2026 (session 1) | Plan, vérification GT 3 = Lite Wearable, création couche données + ancien moteur Bateman + ancien ReminderManager. Extraction des modèles du `Estrogen.ods` → `/tmp/pk_models.json` (6 profils × 8001 h + params D/k1–k3). | | 5 sept. 2026 | L'utilisatrice mentionne un travail d'un assistant tiers « **Mimo V2.5** » : **aucune trace trouvée** (fichiers identiques à la session 1, timestamps identiques). Reprise depuis l'état existant. Bugs trouvés au passage : settings.gradle, BootReceiver, cancel PendingIntent. | @@ -1478,7 +1478,33 @@ trace = d'abord le reproduire** (émulateur + données réelles, §16.ter) — l deux « fixes » aveugles de v1.3.2/v1.3.3 (#41/#45) ont laissé passer un bug trivial (#48) seulement visible sur l'émulateur ; (n) `./gradlew lint` fait désormais partie de la vérification avant release : `StringFormatMatches` -aurait signalé #47 dès v1.3.1. +aurait signalé #47 dès v1.3.1 ; (o) **les tests unitaires JVM ne voient +JAMAIS la minification R8 — la recette §16.ter sur l'APK RELEASE est la +seule filet** (bug #64 : feature parfaite en debug, vide en release) ; +(p) quand une classe pure disparaît du mapping R8 (`R8$$REMOVED$$CLASS`), +la garder explicitement dans proguard-rules.pro plutôt que débattre avec +l'optimiseur. + +### #64 (v1.6.0) — « Tracé labs » vide EN RELEASE SEULE (R8 full mode) + +**Symptôme** (émulateur §16.ter, APK release v1.6.0, données réelles seedées) : +le chip « Lab track » s'active MAIS la courbe n'est ni dessinée (0 pixel +#C2185B au screencap) ni légendée ; « Prolonger » idem. En DEBUG, le même +chip sur les mêmes données fonctionne (légende + 7090 px rose après fix). +**Les 191 tests JVM sont verts** (ils ne passent JAMAIS par R8). + +**Diagnostic** (méthode de bisection debug/release puis `mapping.txt`) : +`com.hormonetrack.pk.LabTrajectoryModel -> R8$$REMOVED$$CLASS$$…` — R8 full +mode a SUPPRIMÉ la classe en inlinant `computeLabAnchoredCurve` (et son +synthétique `computeLabAnchoredCurve$default` qui gère les paramètres par +défaut) dans le call site du producer Compose ; après fusion, le calcul +renvoyait une courbe vide. Les courbes des modèles (même moteur e2At, +même fichier) fonctionnaient — seul le chemin inliné cassait. + +**FIX** : `-keep class com.hormonetrack.pk.LabTrajectoryModel { *; }` dans +proguard-rules.pro (garde commentée + renvoi au mapping). Validé émulateur +sur l'APK release re-buildé : ancrée (courbe + légende), prolongée (légende ++ avertissement), 0 crash. ## 15. Comment régénérer l'asset pk_profiles.json @@ -1613,8 +1639,26 @@ vérifie pas en tests JVM). 3. **Docs** : section `## [X.Y.Z]` en tête de `docs/CHANGELOG.md` (le corps des releases Gitea en sera extrait automatiquement par le script), + §14 si bug corrigé, + §2 (historique) si notable. +3.bis. **⚠️ VALIDATION ÉMULATEUR §16.ter — OBLIGATOIRE AVANT LE TAG (leçon + #64, v1.6.0 : oubliée puis rattrapée, un bug release-only est passé + jusque dans l'APK taggué)** : recette complète §16.ter (émulateur + headless hrt36 + seed `scripts/seed-emulator.py` avec le dernier + backup de `local-test-data/` + APK release installé PAR-DESSUS) sur + **l'APK RELEASE** (JAMAIS le debug seul : **R8 ne se vérifie qu'ici** — + les 191 tests JVM ne le voient jamais, cf #64). Parcours minimum : + l'app démarre 0 crash → écran Graphiques → activer les chips de la + release (rangée modèles défilable : `adb shell input swipe 900 716 150 + 716 400` puis tap aux bounds du `uiautomator dump`) → vérifier dans le + dump `text=` que la légende attendue apparaît → `adb logcat -b crash + -d | grep -c FATAL` reste à 0. Limites : le pan/pinch n'est PAS + testable par adb (§16.ter 4.bis) — le geste reste validé par + l'utilisatrice sur Pixel 9. 4. **Commit** (message descriptif par couche) + **tag annoté** : - `git tag -a vX.Y.Z -m "…"`. + `git tag -a vX.Y.Z -m "…"`. ⚠️ Si un fix arrive APRÈS le tag mais + AVANT la publication d'APK (cas #64) : AUCUNE release n'existe encore → + `git tag -d vX.Y.Z` + re-tag sur le commit de fix + `push --tags` + (jamais de re-tag sur une release PUBLIÉE : bump en X.Y.(Z+1) à la + place). 4.bis. **Release SYNC web** (depuis le 8 sept. 2026) : le portage web vit dans son PROPRE dépôt `~/projects/HormoneTrack-web` (2 Gitea, `Siphonight/HormoneTrack-web` — historique 100 % propre, séparé de la