33 Commits

Author SHA1 Message Date
274f82b6c1 Docs §16.bis : releases ≤ v1.2.4 restent à APK debug unique (backfill abandonné — best effort, app-release-unsigned.apk sans signing config d'époque) 2026-09-06 00:10:23 +02:00
48a1cc7c2f scripts/gitea-release.py : régénération complète — ensure_asset vérifie par TÉLÉCHARGEMENT (le listing a menti pendant les uploads rapprochés) ; retry DELETE+re-upload ×2 ; échec bruyant ; docs/code commentés 2026-09-05 23:51:23 +02:00
3f1378f6ba scripts/gitea-release.py : ensure_asset (upload + vérif nom/taille + retry PATCH + échec bruyant) — les ?name=/PATCH pouvaient être ignorés (v1.2.6/v1.2.10) ; docs §16.bis/§14 #37 2026-09-05 23:45:45 +02:00
15c667132b v1.2.10 : sens des boutons de zoom inversé (+ = zoom avant / fenêtre courte, convention carte — retour utilisateur) ; docs ; versionCode 13 2026-09-05 23:36:30 +02:00
186c446562 Docs/scripts : correction d'attribution — le nom d'asset générique venait de l'upload interrompu (extinction machine), pas d'un quirk Gitea ; renommage PATCH conservé comme défense 2026-09-05 23:28:02 +02:00
ab84f5e0ce v1.2.9 : zoom du graphique (pinch + boutons, 6 h → 300 j, focal stable, pas adaptatif) + disclaimer IA dans le README
- ChartScreen : detectTransformGestures unique (pan 1 doigt + pinch 2 doigts,
  pas de conflit de consommation) ; zoom autour du point focal (le temps sous
  le doigt reste fixe) ; plage bornée 6 h → 300 j (MIN/MAX_RANGE_H) ;
  boutons − / + en accessibilité
- CurveChart : stepForRange (15 min ≤ 12 h, 30 min ≤ 24 h, sinon 1 h) passé à
  computeCurve (courbes lisses à fort zoom) ; labels X adaptatifs 1 h/3 h
- README : disclaimer IA en en-tête (développé avec l'IA, contribution
  humaine essentielle = feedback/retours/suggestions, renvoi §2 doc dev)
  ; DEVELOPPEMENT §1 mention IA-assistée, §11 zoom, §8 67 tests
- ChartZoomTest : 3 tests stepForRange — 67 tests verts
- versionCode 12, versionName 1.2.9
2026-09-05 22:51:27 +02:00
139f818172 v1.2.8 : « Fréquence d'injection » renommé « Posologie » ; script : renommage d'asset après upload (quirk Gitea)
- strings EN « Dosage » / FR « Posologie » ; hint « dernière prise » (au lieu
  de « dernière injection ») — adapté aux voies non injectables
- quirk Gitea découvert : le nom d'asset passé à l'upload peut être normalisé
  (observé : -release.apk → .apk générique) → le script renomme l'asset via
  l'API d'édition (PATCH …/assets/{id}) après chaque upload
- release v1.2.8 publiée avec les 2 APK (release 2,5 Mo + debug 21 Mo)
- docs : §16.bis quirk, §8 (64 tests), historique, footer, README
- versionCode 11, versionName 1.2.8
2026-09-05 22:29:08 +02:00
8468bcbd65 CHANGELOG : entrée v1.2.8 (renommage Posologie) — étape 3 de la checklist §16.bis, appliquée à la lettre cette fois 2026-09-05 22:25:07 +02:00
df706aaedf UI : « Fréquence d'injection » renommé « Posologie » (terme inadapté aux voies non injectables) ; hint généralisé « dernière prise » ; docs à jour
- strings EN (Dosage) / FR (Posologie) ; freq_hint : « dernière injection » →
  « dernière prise » (les deux langues)
- README, GUIDE, DEVELOPPEMENT §10/§21 : mentions mises à jour
- versionCode 11, versionName 1.2.8 ; 64 tests verts
2026-09-05 22:24:24 +02:00
8d54770a71 Docs : guide d'installation — section « télécharger sans compiler » (releases Gitea, différences APK release vs debug) ; README statut v1.2.7/64 tests (replace silencieux raté corrigé) 2026-09-05 22:18:20 +02:00
89805cef89 v1.2.7 : prévision robuste aux oublis/retards + rattrapage complet de la doc de dev
- generateForecastDoses : les créneaux déjà passés (oubli d'injection) ne sont
  plus simulés — avant, dernier+intervalle tombait dans le passé → faux pic
  dans l'historique + rythme décalé ; la prévision démarre au premier créneau
  strictement futur, au rythme configuré
- un retard décale toute la prévision (part de la dernière prise réelle) —
  comportement voulu, épinglé par 2 tests
- doc §7.3b corrigée (mismatch doc-code détecté par l'utilisatrice)
- docs : §13 écrasement, §19/§20 import, §14 #34/#35, §21, historique
  (lignes v1.2.2/6/7), footer — vérification intégrée dans le script de patch
- versionCode 10, versionName 1.2.7 ; 64 tests verts
2026-09-05 22:14:19 +02:00
8f262fd789 scripts/gitea-release.py : DELETE renvoie {} (204 sans corps) ; nettoyage des assets v1.2.6 (release 2,4 Mo + debug 20 Mo) 2026-09-05 21:59:18 +02:00
33138eaad9 scripts/gitea-release.py : gère les réponses 204 sans corps (DELETE d'asset) — crash json.loads sur réponse vide 2026-09-05 21:56:23 +02:00
35a5ffba39 CHANGELOG : entrée v1.2.6 (extrema avec valeurs + import écrasement) 2026-09-05 21:49:58 +02:00
3a647c596d v1.2.6 : valeurs des pics/creux sur le graphique + import JSON en mode écrasement
- CurveChart : drawExtremum = triangle ▲▼ + VALEUR estimée de l'extremum
  (au-dessus d'un pic, en dessous d'un creux), couleur de la série
- Import JSON : mode ÉCRASEMENT (bug remonté : échec dès que l'app contenait
  des données — conflit d'IDs backup vs existants)
  · DAOs : deleteAll() sur les 3 tables (ordre enfants → parents, FK CASCADE)
  · BackupManager.importJson : wipe puis restauration (IDs conservés → FK
    valides), retourne aussi le tConfig du backup
  · SettingsScreen : après import → tConfig restauré dans DataStore + rappels
    reprogrammés (rescheduleAll) ; dialog renommé « Effacer & restaurer »
    avec avertissement explicite
- docs : §13 (écrasement), §11 (valeurs extrema), §14 #34, §16.bis CHECKLIST
  DE DÉPLOIEMENT complète numérotée (version → tests → docs → commit/tag →
  push 2 remotes → build 2 APK → releases 2 instances → smoke-test R8),
  §20/§21, CHANGELOG, README
- versionCode 9, versionName 1.2.6
2026-09-05 21:41:58 +02:00
58f107f78e Docs : audit de complétude post-release-build (§16 workflow assembleRelease, §16.bis les deux APK par tag, §20 keystore dédié restant, §19 smoke-test R8, historique, README) 2026-09-05 20:28:47 +02:00
a8a9ee47c8 v1.2.5 : builds release optimisés (R8 + shrink, 20 Mo → 2,4 Mo), APK release + debug publiés
- build release signé avec la CLÉ DEBUG (même signature → mise à jour
  par-dessus l'app installée sans perte de données) mais avec R8 full mode
  + isShrinkResources : 20 Mo → 2,4 Mo, démarrage et fluidité améliorés
- proguard-rules.pro : -keep explicites pour la réflexion Gson (data.model,
  BackupData, TConfig) — sinon export/import JSON cassé en release uniquement
- release v1.2.5 : deux APK publiés (release recommandé 2,4 Mo + debug 20 Mo)
- docs : §16.bis (deux APK par release, garde-fous R8), CHANGELOG
2026-09-05 20:27:05 +02:00
5ad0719105 Release script multi-instances (cloudyfy + farewell), remotes et docs §16
- scripts/gitea-release.py : argument d'instance (URL/owner/trousseau par hôte),
  usage inchangé sinon ; tokens par instance dans le trousseau macOS
- remotes : origin (cloudyfy, HTTPS) + farewell (SSH, alias giteassh:2222)
- docs §16/§16.bis : deux remotes, scopes des tokens, commande d'ajout au
  trousseau pour farewell
2026-09-05 20:21:35 +02:00
d6e4c45fe0 v1.2.5 : edge-to-edge propre (fix du double espace en haut de l'écran)
- enableEdgeToEdge() dans MainActivity (Material You)
- insets consommés UNE SEULE FOIS : TopAppBar M3 = barre de statut,
  NavigationBar = barre de navigation
- Scaffold racine + imbriqués (Doses/Analyses) : contentWindowInsets = 0
  pour ne pas cumuler (avant : fenêtre AppCompat + padding interne TopAppBar
  = double espace vide en haut)
- docs : §10 (pattern insets), §14 bug #33, historique, CHANGELOG
- versionCode 8, versionName 1.2.5
2026-09-05 20:15:33 +02:00
54b2ffe8a0 v1.2.4 : traitement inactif = drapeau administratif, jamais un filtre de données
Bug remonté : passer un traitement à inactif effaçait sa simulation du graphique
(Home/Chart collectaient activeTreatments) et faussait la calibration, tout en
permettant d'y loger des doses.

- HomeScreen / ChartScreen : simulation + calibration avec ALLTreatments
  (actifs + inactifs) — l'historique EV d'un traitement archivé reste simulé
- Home : chips « Log rapide », dialog de création et carte « prochaine dose »
  sur les traitements ACTIFS uniquement
- DosesScreen : création → actifs uniquement ; édition d'une dose existante →
  tous les traitements (rattachement préservé)
- Rappels : annulés pour les inactifs (save, boot via getAllOnce, prochaine dose)
- RegressionUserCase3Test (6 tests, données réelles HORS dépôt gitignoré) :
  transition complète EV inactif (29 doses) → EEn actif (9 doses), 22 labs sur
  les deux périodes, calibration par période couvrant EV + EEN, k T par ester,
  continuité de courbe, niveau actuel — 62 tests verts
- docs : §6.bis (sémantique isActive), §14 bug #32, §8, §21, CHANGELOG,
  README, GUIDE ; versionCode 7, versionName 1.2.4
2026-09-05 20:05:07 +02:00
bbc580b95b README : arbre du dépôt à jour (scripts/, CHANGELOG, local-test-data gitignoré, Gradle 9.7.1) 2026-09-05 19:50:04 +02:00
a44717881e Docs : audit de complétude pour reprise par session sans contexte
- §8 : 56 tests, V120FeaturesTest (10) incluant calibration T par ester
- §14 : bugs 25-31 (calibration par période, lab T en unité aberrante,
  commentaires imbriqués dans les KDoc, XML de test périmés, idempotence
  du scrub d'historique, préfixe « v » des releases) + leçons (f)(g)(h)
- §20 : état des faits / reste à faire mis à jour
- §21 : checklist des features v1.2.x
- README : arbre (scripts/, CHANGELOG, local-test-data gitignoré)
2026-09-05 19:49:44 +02:00
65a17ba2b9 scripts/gitea-release.py : releases automatisées (corps = section CHANGELOG, APK en pièce jointe)
- le corps de chaque release Gitea est extrait de docs/CHANGELOG.md (la section
  [X.Y.Z] de la version) — les 5 releases existantes ont été mises à jour (le
  1er script cherchait [vX.Y.Z] et était tombé sur le fallback)
- crée ou met à jour la release (PATCH), remplace l'asset APK du même nom
- token Gitea lu dans le trousseau macOS, scope write:repository suffisant
- §16.bis documente le script + le piège du préfixe « v »
2026-09-05 19:46:10 +02:00
cb4f5f02c0 Docs v1.2.3 : données de test hors dépôt (§8.bis, sécurité), releases Gitea avec APK (§16.bis), statut à jour
- §8.bis : les données de santé de test vivent dans local-test-data/ (gitignoré),
  tests Assume-skippés si absentes, historique nettoyé avant premier push
  (filter-branch) — aucune donnée de santé dans le dépôt ni l'historique
- §16.bis : procédure de release Gitea (API + upload APK par tag)
- README : statut v1.2.3, section Vie privée (dépôt sans données), Git à jour
2026-09-05 19:24:31 +02:00
fe3bf3c87c Tests de régression : données réelles hors dépôt (local-test-data gitignoré)
- RegressionUserCase{,2}Test chargent le backup réel depuis local-test-data/
  (gitignoré) et sont IGNORÉS proprement (Assume) si le fichier est absent —
  plus aucune donnée de santé personnelle embarquée dans le dépôt
- KDoc LabDialog : exemple 300.0 (au lieu d'une valeur réelle)
- script d'anonymisation /tmp/scrub.py prêt pour filter-branch (historique)
2026-09-05 19:20:14 +02:00
5f5244d8eb v1.2.3 : pics/creux estimés sur le graphique (toggle) + calibration T par période d'ester
- detectExtrema : extrema locaux stricts (plateaux fusionnés), alternance
  pic/creux imposée, filtre d'amplitude (2 pg/mL E2, 0,02 ng/mL T) — sémantique
  zigzag documentée (oscillation sous le seuil = un seul pivot)
- CurveChart : triangles ▲▼ aux extrema de chaque série (couleur de la série),
  chip « Pics / creux » + légende (désactivé par défaut)
- computeTKPerEster : le k du modèle T est calibré PAR PÉRIODE D'ESTER (labs T
  attribués à la période de la dernière dose ≤ lab, médiane) — la suppression T
  diffère valerate vs enanthate ; la courbe T utilise le k de l'ester ACTIF à
  chaque instant (activeEsterAt + curseur de doses triées dans computeCurve)
- Fix : la calibration T automatique utilise désormais l'E2 CALIBRÉE
  (scalePerEster) — calibrer contre l'E2 brute faussait les k
- levelAt/currentLevel : paramètre tKPerEster (fallback = tConfig.k stocké)
- ExtremaTest : 6 tests (alternance, monotone, plat, court, filtre d'amplitude,
  anti-corrélation E2/T) — 56 tests verts
- versionCode 6, versionName 1.2.3 ; docs mises à jour (§7.5/§7.6, §11, README, guide)
2026-09-05 18:58:10 +02:00
4731e4c159 v1.2.2 : prise de sang E2 + T en une entrée, affichage côte à côte, toggle T masque aussi les labs T
- LabDialog : mode création avec deux sections (E2 et T, chacune optionnelle,
  au moins une valeur requise) → insère 1 ou 2 LabResult au même timestamp ;
  mode édition inchangé (un seul marqueur, pré-rempli)
- LabsScreen : regroupement par timestamp (groupLabsForDisplay : E2 avant T,
  autres ensuite, tri desc) → affichage « E2 306 pg/mL · T 45 ng/dL » côte à
  côte ; tap sur une paire → sélecteur « Quelle entrée modifier ? » puis
  édition pré-remplie ; suppression = la prise entière (confirm nommant les
  valeurs) ; formatLabValue préserve les décimales
- ChartScreen : le toggle T masque désormais aussi les labs T (avant : seuls
  les points restaient visibles)
- LabsGroupingTest : 4 tests de regroupement (48 tests verts au total)
- versionCode 5, versionName 1.2.2 ; docs mises à jour
2026-09-05 18:33:19 +02:00
571e346b73 v1.2.1 : calibration par période d'ester, édition des labs, tap accueil→Graphiques, auto-cal fusionnée E2+T, lab T en unité aberrante neutralisé
- computeEsterScaleFactors : chaque lab est attribué à la période d'injection
  dans laquelle il tombe (dernière dose E2 <= lab → son ester) ; facteur final
  par ester = médiane des ratios de cette période. Corrige le mélange des
  périodes valerate/enanthate qui gonflait les courbes (250-375 pg/mL)
- e2At/computeCurve : paramètre scalePerEster (chaque dose scalée par le facteur
  de SON ester, fallback = scaleFactor stocké du traitement)
- autoCalibrated : renvoie esterScales + tConfig recalibré, traitements inchangés
- convertTToNgMl : conversion défensive pg/mL et µg/L (un lab T « 38 pg/mL »
  écrasait l'axe T et rendait la courbe T invisible — remonté utilisateur)
- LabDialog create/edit : tap sur une ligne de l'écran Analyses → édition
  pré-remplie (formatLabValue préserve les décimales)
- Home : tap sur le mini-graphique → écran Graphiques + mini-légende E2/T
- Settings : UNE seule option « Calibration automatique (E2 + T) » (E2 par
  période d'ester + modèle T), placée au-dessus des réglages T manuels
- RegressionUserCase2Test : 2e export réel épinglé (9 doses EEn/TFS, 8 labs,
  fréquence 6 j) — vérifie l'état d'équilibre EEn (~270 pg/mL calibré, cohérent
  labs 306/248 ; non calibré ≈ 367 = les « 375 » rapportés)
- V120FeaturesTest : attribution des labs par période d'ester + scalePerEster
- 44 tests verts ; versionCode 4, versionName 1.2.1
- Docs : CHANGELOG, DEVELOPPEMENT (§7.6 réécrit), GUIDE, README
2026-09-05 17:38:08 +02:00
24423be3ff Documentation v1.2.0 : changelog, guide (fonctions du graphique), doc de dev (AGP 9, migrations, panoramique, prévision, auto-cal), README (git, features)
- docs/CHANGELOG.md : entrée v1.2.0 complète
- docs/DEVELOPPEMENT.md : versions épinglées à jour, note Material Expressive
  (API encore internal), migration Room v1→v2, §7.3b (override modèle/prévision/
  auto-cal), §8 (36 tests), §10/§11 (panoramique, multi-séries), §16 (workflow git),
  §18 (disque), historique des sessions
- README : statut v1.2.0, features à jour, section Git (tags de release)
- GUIDE : nouvelle section « Fonctions du graphique » (panoramique, toggles
  modèles, prévision, calibration auto)
2026-09-05 16:58:32 +02:00
4bc82226e3 UI v1.2.0 : graphique multi-séries panoramique, toggles modèles/prévision, intervalles de dosage, TimePicker centré
- CurveChart : API ChartSeries/CurveStyle (superposition de plusieurs modèles,
  styles plein/pointillé), labs T normalisés en ng/mL au rendu
- ChartScreen : panoramique horizontal (remonter dans le passé, bouton
  « Revenir à maintenant »), toggles Estrannaise/TFS indépendants, chip Prévision
  (horizon = 2× l'intervalle configuré, borné 7-30 j), auto-calibration intégrée,
  légende dynamique
- HomeScreen : données auto-calibrées pour la courbe 24 h
- DosesScreen : intervalle en jours entre chaque dose et la précédente du même
  traitement (colonne « Interval (d) » du .ods)
- TreatmentEditorScreen : section « Fréquence » (switch + intervalle en jours)
- SettingsScreen : option Calibration automatique
- TimePicker : centré dans ses dialogs (bug d'alignement à gauche signalé)
- strings FR/EN complètes pour toutes les nouveautés
2026-09-05 16:53:53 +02:00
693ab24f3d Moteur v1.2.0 : override de modèle PK, doses prévisionnelles (« Fréquence »), calibration automatique
- concentrationOfDose/e2At/computeCurve : paramètre modelOverride (dessiner
  Estrannaise et Transfem Science simultanément, indépendamment du pkModel stocké)
- generateForecastDoses : projette les doses à venir depuis la dernière injection
  réelle + forecastIntervalDays (jamais persistées, ester override conservé)
- autoCalibrated : recalcul à la volée des scale factors et du modèle T depuis les
  labs (copies uniquement — les valeurs stockées ne changent jamais)
- Treatment.forecastIntervalDays + migration Room v1→v2 (ALTER TABLE), sans
  fallbackToDestructiveMigration (données réelles de l'utilisatrice protégées)
- AppSettings.autoCalibrate (DataStore, désactivé par défaut)
- V120FeaturesTest : 6 tests (rythme des prévisions, override d'ester projeté,
  divergence des deux modèles, auto-cal appliquée et préservation des originaux)
2026-09-05 16:53:53 +02:00
977d40baa1 Toolchain : AGP 9.4.0 (Kotlin intégré), Gradle 9.7.1, Kotlin 2.3.21, KSP 2.3.11, Compose BOM 2026.06.01 (Material 3 Expressive), compileSdk 36, targetSdk 36
- kotlinOptions -> supprimé (retiré d'AGP 9) ; target JVM via compileOptions
- BOM 2026.08 rejeté : Compose 1.12 exige compileSdk 37 (API 37 en preview) ;
  2026.06.01 = dernier BOM compatible compileSdk 36
- version 1.2.0 (versionCode 3)
2026-09-05 16:42:27 +02:00
5c5d9c542a v1.1.0 : suivi THS avec courbes E2/T, modèles Estrannaise & Transfem Science, calibration labs, rappels (GT 3), backup JSON, FR/EN
- Moteur PK par tables horaires (8001 h) extraites de Estrogen.ods + Bateman fallback
- Lookup profils insensible à la casse (fix courbes EEn plates)
- Conversion unités T (ng/dL, ng/L, nmol/L -> ng/mL)
- Édition des doses + override d'ester par injection
- 30 tests unitaires dont régression sur données réelles
- UI Compose Material 3, i18n FR/EN, sauvegarde JSON SAF
2026-09-05 16:32:44 +02:00