• v1.4.10 Stable

    Siphonight released this 2026-09-07 19:28:41 +02:00 | 35 commits to main since this release

    Corrigé

    • Le pan du graphique ne fonctionnait pas sur la vue 24 h (#62, remontée
      par test utilisateur sur Pixel 9 : « le glisser horizontal ne marche pas
      sur une échelle de 24 h, uniquement au-dessus ») : les deltas de mouvement
      du doigt (~30 px ≈ 0,67 h à 24 h) étaient tronqués à 0 par le cast
      en heures entières à CHAQUE événement de mouvement → le pan ne bougeait
      jamais sur 24 h (alors que sur 7 j le même delta ≈ 4,7 h). FIX : cumul
      fractionnaire
      — le résiduel < 1 h est conservé d'un événement au
      suivant (panDeltaHours, pur et testé) : le pan se déclenche dès que le
      cumul franchit une heure entière. Aucun impact sur les vues larges.
    • Nettoyage : instrumentation de diagnostic retirée ; 2 imports/
      constantes morts supprimés.

    Ajouté

    • 4 nouveaux tests (172 au total / 150 sans les données locales) :
      cumul fractionnaire à 24 h (2 deltas → 1 h), 7 j (delta immédiat),
      deltas négatifs (troncature vers zéro), cas dégénérés.
    • Limitation de test documentée (§16.ter) : l'émulateur headless ne
      délivre pas les mouvements intermédiaires au graphique via adb input swipe → le pan n'est PAS testable par adb sur cet environnement ; le
      test humain sur Pixel 9 reste la référence pour les gestes.
    Downloads
  • v1.4.9 Stable

    Siphonight released this 2026-09-07 18:54:43 +02:00 | 37 commits to main since this release

    Corrigé

    • La calibration tombait à ×2,21 (auto ET manuelle) sur un traitement
      basculé sous un autre modèle
      (#61, remontée : « le bouton Calibrer avec
      les analyses du traitement EEn WHSAH me met toujours à ×2,21 ») :
      diagnostic par reproduction sur données réelles — l'export contient une
      dose EEn de test logguée en janvier ; les labs de janvier-mars
      tombaient 15–76 j après cette dose, quand la prédiction WHSAH est
      RÉSIDUELLE (184 → 1 pg/mL) → ratios aberrants (3,3 / 15,9 / 89,6 / 383)
      → la MÉDIANE tombait à ×2,21, dans les deux pipelines (manuel ET
      auto — même défaut de frontière). FIX : garde de significativité
      (labIsSignificant) — un lab ne calibre que si la prédiction reste
      ≥ 15 % du max déjà observé (l'injection « gouverne » encore le taux) ;
      appliquée aux 3 pipelines (manuel, échelles par ester, k T), labs
      traités par timestamp croissant. Résultat : le facteur WHSAH retombe à
      0,55 (physiologique).
    • Hint UX (demande) : dans l'éditeur de traitement, quand l'auto-
      calibration est ON, la carte Calibration affiche que le facteur manuel
      est ignoré à l'affichage (l'auto recouvre les courbes).

    Ajouté

    • 4 nouveaux tests (168 au total / 146 sans les données locales) :
      reproduction épinglée du ×2,21 (facteur manuel WHSAH 0,55, plus jamais
      2,21), garde de significativité (séquence réelle + cas aux frontières),
      cohérence auto↔manuel.
    Downloads
  • v1.4.8 Stable

    Siphonight released this 2026-09-07 18:28:15 +02:00 | 38 commits to main since this release

    Corrigé

    • La calibration automatique était fausse pour les modèles autres que le
      modèle stocké du traitement
      (#60, remontée : « la calibration auto sur
      WHSAH met ×2,21 alors que l'idéal serait < 1 ») : un SEUL jeu de facteurs
      était calculé depuis la prédiction du modèle STOCKÉ puis partagé par
      toutes les courbes — en basculant un traitement (ex. EEn TFS → WHSAH),
      les facteurs devenaient absurdes (les prédictions WHSAH diffèrent de TFS :
      creux plus profonds, montée plus rapide). FIX (demande : « la calibration
      doit être active sur tous les modèles mais s'adapter à chaque profil ») :
      la calibration est désormais PAR MODÈLE — le graphique calcule un jeu
      de facteurs (et de k T) PAR modèle affiché (ESE/TFS/WHS), chacun calibré
      avec la prédiction DE SON modèle → chaque courbe calibrée passe par tes
      labs, quel que soit le modèle superposé. Home conserve la calibration du
      modèle stocké (inchangé). Épinglé par test : chaque courbe calibrée passe
      par le lab (±2 %) et les échelles TFS/WHS diffèrent.

    Ajouté

    • 5 nouveaux tests (164 au total / 142 sans les données locales) :
      CalibrationPerModelTest — les 3 modèles calibrés atterrissent sur le
      lab (ESE inclus), échelles distinctes (ESE↔TFS ~2 %, WHS ~11 %),
      délégation autoCalibrated(modelOverride) → computeEsterScaleFactors
      (implémentation unique), k T par modèle (k ∝ 1/E2 calibrée — et les
      k post-calibration CONVERGENT entre modèles : même E2 cible, comportement
      voulu), labs antérieurs à la 1ʳᵉ dose → échelles vides (par modèle).
    Downloads
  • v1.4.7 Stable

    Siphonight released this 2026-09-07 17:45:45 +02:00 | 39 commits to main since this release

    Modifié

    • Toggles de modèles pré-cochés selon TES traitements (#58, demande :
      « les seules courbes activées par défaut sont celles qui se rapportent au
      modèle PK des traitements en cours ou passés ») : au chargement du
      graphique, les chips Estrannaise/Transfem/WHSAH sont alignés sur les
      modèles RÉELLEMENT utilisés par des traitements à PROFIL PK
      (usesProfileModel — le traitement inactif compte, l'oral/anti-androgène
      non) ; les autres restent activables au tap. Cas de l'utilisatrice :
      EV historique TFS + EEn actuel (qu'elle passe sous WHSAH) → TFS + WHSAH
      ON, Estrannaise OFF. Garde-fou testé : aucun modèle profil utilisé → TFS
      ON (les traitements Bateman sont tracés identiquement dans chaque série).
      Une seule initialisation : les toggles ensuite modifiés ne sont pas
      re-rencontrés. (defaultModelToggles, helper pur testé.)

    Corrigé

    • La carte de traitement affichait « EEN Estrannaise » pour un traitement
      sous WHSAH
      (#59, remontée) : le ternaire à 2 branches du chip
      TreatmentsScreen tombait WHSAH dans le else → label « Estrannaise ».
      FIX : helper centralisé modelLabelRes (unique source de vérité du
      label : ESE/TFS/WHS) utilisé par la carte — le dropdown de l'éditeur et
      le chip du graphique étaient déjà corrects. Règle : TOUT nouvel affichage
      de modèle passe par le helper, jamais un ternaire.

    Ajouté

    • Épinglage : la calibration s'applique à TOUTES les courbes (2ᵉ partie
      de la demande — vérification) : le facteur par ESTER (scalePerEster)
      est appliqué par DOSE (doseEster), indépendamment du modelOverride →
      les 3 courbes (ESE/TFS/WHS) d'un même traitement sont scalées
      IDENTIQUEMENT (2× le facteur = 2× la courbe, test calibration applies to ALL model curves equally). C'était déjà le comportement ; il est
      désormais garanti par test. Subtilité documentée (§7.6) : le facteur est
      calculé depuis la prédiction du modèle STOCKÉ du traitement — les
      courbes des autres modèles partagent ce facteur (un facteur par
      ester/période, pas par modèle).
    • 3 nouveaux tests (158 au total / 136 sans les données locales) :
      defaultModelToggles (2) + calibration universelle (1).
    Downloads
  • v1.4.6 Stable

    Siphonight released this 2026-09-07 17:01:28 +02:00 | 40 commits to main since this release

    Ajouté

    • 3ᵉ modèle PK superposable : WHSAH (demande : « ajouter le nouveau
      modèle à côté de tous les autres comme un 3ᵉ choix possible, au même
      niveau ») : le fit « license-free » du WHSAH Collective publié dans
      l'app open-source Mona (libre d'usage par leurs auteurs — crédit :
      alix / WHSAH Collective via Mona). Même famille mathématique (tri-
      exponentielle en forme close) mais paramètres refittés avec une
      biodisponibilité explicite F < 1 : montée plus rapide à J+1 (EEn
      ~70 pg/mL vs ~22 chez TFS pour 5 mg) et t½ terminale plus longue
      (EEn 7,3 j vs 4,5 j). PEP non couvert par ce fit (comme chez Mona).
    • 6 presets WHSAH (EV/EU/EEn/EB/EC/ECS) + dropdown « PK model » à 3
      choix dans l'éditeur ; l'override d'ester par dose suit la couverture du
      modèle (helper Esters.choicesForModel, testé : TFS=7 / WHS=6 / ESE=3).
    • Écran Graphiques : 3 toggles de modèles indépendants (Estrannaise /
      Transfem Science / WHSAH superposables simultanément — légende en 3
      couleurs : bleu / turquoise / vert) + l'écran défile verticalement
      (la rangée des toggles était coupée sous le pli, #57).
    • 7 nouveaux tests (155 au total / 133 sans les données locales) :
      WhsahModelsTest (fidélité au comportement de Mona : EV 367,5 @ 1,69 j,
      EEn 187,9 @ 4,99 j, t½ 7,34 j), WhsahEngineTest (dispatch, coupure
      10×t½, PEP → 0, 3 courbes distinctes), choicesForModel.

    Corrigé

    • Écran Graphiques : rangée des toggles de modèles coupée sous le pli
      (#57, découvert en validant sur émulateur) : le Column ne défilait pas —
      le chip WHSAH était littéralement hors écran sur un téléphone standard.
      FIX : écran à défilement vertical.
    Downloads
  • v1.4.5 Stable

    Siphonight released this 2026-09-07 11:27:38 +02:00 | 41 commits to main since this release

    Corrigé

    • Boucle de recomposition sur le graphique (#56, découvert en validant
      #54) : nowMs était relu frais à CHAQUE recomposition → endMs dérivait
      → les keys du producteur de courbes changeaient à chaque frame →
      re-calcul perpétuel → main thread saturé (« Skipped 52 frames ») → les
      taps sur les chips étaient perdus. FIX : nowMs mémoïsé sur le tick
      minute ; le calcul des créneaux prévisionnels mémoïsé aussi.
    • La projection paraissait décalée d'un jour (#55, remontée : « la
      prévision simule mon injection le 13 au lieu du 12 ») : diagnostic sur
      données réelles — la GÉNÉRATION est exacte (créneau = dernière dose
      loguée + intervalle exact ; samedi 12 à 18:54) ; l'illusion venait de
      (a) l'ABSENCE de marqueur des doses simulées, (b) les labels X alignés
      sur minuit UTC (= 02:00 du matin FR), (c) la courbe qui continue de
      descendre après le créneau (physiologie EEn — contribution à J+0,5
      ~4 pg/mL). ⚠️ Subtilité documentée : la dose d'hier avait été LOGUÉE le
      lendemain de l'injection réelle → le rythme 6 j décale d'un jour par
      cycle ; l'app suit les LOGS (édition de la dose pour recadrer).

    Ajouté

    • Marqueurs de doses sur le graphique : les doses PRÉVISIONNELLES
      (ligne verticale pointillée + triangle + heure, dans le fuseau de
      lecture) et les doses RÉELLES (petits triangles discrets au bas) — la
      projection devient non ambiguë.
    • Labels X alignés sur minuit LOCAL (xLabelTicks, testé) au lieu de
      multiples UTC.
    • Fuseau horaire du graphique configurable : Paramètres → « Fuseau
      horaire du graphique » (vide = fuseau du téléphone) ; s'applique à
      l'alignement des jours et à l'heure des marqueurs.
    • 6 nouveaux tests (145 au total / 123 sans les données locales) :
      ticks minuit local, fuseau choisi (America/New_York), cas dégénérés,
      créneau prévisionnel = dernière dose + intervalle exact (régression #4).
    Downloads
  • v1.4.4 Stable

    Siphonight released this 2026-09-07 07:56:32 +02:00 | 42 commits to main since this release

    Corrigé

    • La prévision était inaccessible depuis la v1.4.1 (#54, remontée : « en
      1.4.3 je ne peux même pas drag le graphique vers la gauche pour voir les
      prévisions ; le toggle activé ne génère pas les prévisions ») : deux
      causes emboîtées
      —
      1. Captures FIGÉES dans le gestionnaire de gestes : la closure de
        pointerInput(Unit) est créée une seule fois et les val calculées
        (futurePanHorizon…) y étaient figées à leur valeur de la PREMIÈRE
        composition (0, chip désactivé) → le clamp interdisait DÉFINITIVEMENT
        le pan vers le futur. FIX : les vals de fenêtre sont exposées au geste
        via rememberUpdatedState (alias gesture*, lectures à jour).
        Garde de non-régression : ChartScreenSourceGuardTest fait échouer
        toute réintroduction de lecture figée dans la closure (le lint Compose
        ne détecte pas ce pattern).
      2. Toggle sans effet visible : à l'activation, endMs = now faisait
        que generateForecastDoses(..., toMs = now, ...) ne générait AUCUNE
        dose. FIX : à l'activation, la fenêtre s'ÉTEND à droite (sans déplacer
        son début — pas de saut) jusqu'au premier créneau projeté (+12 h de
        contexte), sinon 1/3 de la plage, borné par l'horizon
        (forecastExtensionHours, testé). Désactiver → retour à la fenêtre
        standard. Le drag vers la gauche continue au-delà (jusqu'à 1 an).

    Ajouté

    • 3 nouveaux tests (140 au total / 118 sans les données locales) :
      extension de fenêtre (bornes, garde-fous) et garde de source anti-captures
      figées. Validation émulateur : drag gauche → panHours < 0 (« Revenir à
      maintenant » apparaît) et la courbe est dessinée au-delà de la ligne
      « maintenant » (analyse du screencap).
    Downloads
  • v1.4.3 Stable

    Siphonight released this 2026-09-07 07:35:54 +02:00 | 44 commits to main since this release

    Corrigé

    • Le delta « vs il y a 6 h » de la carte d'accueil comparait en réalité
      il y a ~24 h
      (#53, remontée : « 238 pg/mL avec −11 vs 6 h malgré mon
      injection d'hier ») : curve.firstOrNull { écart ≥ 6 h } sur une fenêtre
      de 24 h retournait le PREMIER point de la liste (il y a 24 h), pas un
      point à 6 h. FIX : nouveau helper pur pointHoursBefore (le point
      dont l'écart au dernier est le plus petit au-dessus de l'offset —
      testé : grille 1 h, grille 30 min, points irréguliers, courbe courte).
      Le delta affiché est désormais VRAIMENT un delta 6 h.

    Ajouté

    • Régression n°4 épinglée sur le 4ᵉ export réel (HORS dépôt, gitignoré)
      le scénario « injection EEn hier, l'estimation ne remonte pas » —
      export v1.4.2 (3 traitements, 52 doses, 26 labs, settings v2 avec seuils
      et auto-calibration). Le test épine, avec le VRAI moteur : la
      contribution d'une dose EEn à J+1 est marginale (< 12 % du total —
      Tmax 6,5 j), le plateau d'équilibre (swing 48 h ≤ 25 % du niveau),
      l'absence de fausse alerte à l'observation, et le parsing des settings
      v2. Réponse à la question posée : comportement pharmacocinétique
      normal
      de l'énanthate (courbe plate en équilibre), pas un bug — le
      seul bug était l'étiquette du delta (ci-dessus).
    • 8 nouveaux tests (137 au total / 115 sans les données locales) :
      RegressionUserCase4Test (4) + pointHoursBefore (4, dans ChartZoomTest).
    Downloads
  • v1.4.2 Stable

    Siphonight released this 2026-09-07 00:02:22 +02:00 | 45 commits to main since this release

    Ajouté

    • Seuils d'alerte configurables (E2 et T) : dans Paramètres, une limite
      HAUTE et une limite BASSE par marqueur (E2 en pg/mL, T en ng/mL), chacune
      optionnelle (champ vide = pas d'alerte), validées (haut > bas requis) et
      évaluées contre le taux ESTIMÉ actuel (le même que la carte « niveau
      actuel », calibration incluse — pas une mesure de labo). En cas de
      dépassement : carte d'avertissement rouge sur l'accueil (« ▲ E2 estimé
      ≈ 259 pg/mL — au-dessus de ta limite haute (200) ») + disclaimer «
      estimation, pas une mesure ». Comparaison STRICTE (valeur == limite → rien).
    • Notification d'alerte : la vérification tourne toutes les 15 min
      même app fermée
      (worker WorkManager — la dépendance déclarée depuis v1.0
      est enfin utilisée) + check immédiat au save des seuils. Anti-spam :
      l'état des alertes déjà notifiées est mémorisé — pas de re-notification
      du même franchissement ; le retour à la normale ré-arme la prochaine
      alerte ; pas de notification de « retour à la normale ». Canal de
      notification dédié (réglable séparément des rappels, remonte sur la
      Watch GT 3). Journalisation AppLog complète (debug à distance).
    • 9 nouveaux tests (129 au total / 111 sans les données locales) :
      AlertsTest (12 : logique pure des seuils, codec d'état anti-spam) et
      AlertsEngineTest (4 : la notification évalue EXACTEMENT le niveau de la
      carte accueil ; déclenchement sur niveau réel).
    • Backup JSON avec les paramètres utilisateur : l'export embarque
      désormais langue, auto-calibration et seuils d'alerte ("settings",
      format v2) ; l'import les restaure (la langue est appliquée au retour).
      Rétrocompatible : les anciens exports (sans settings) restent
      importables ; 2 tests round-trip + compat v1.
    Downloads
  • v1.4.1 Stable

    Siphonight released this 2026-09-06 23:00:43 +02:00 | 46 commits to main since this release

    Ajouté

    • Prévision étendue ET sans saut temporel (remontées utilisateur) :
      • activer le chip Prévision ne déplace PLUS le graphique « tout à
        droite » dans le futur — la fenêtre reste exactement où elle était ;
        la courbe projetée s'étend au-delà et on la parcourt en tirant vers
        la gauche
        (« scroller à l'infini » = jusqu'à 1 an de projection) ;
        « Revenir à maintenant » ramène depuis le passé ou le futur ;
      • l'horizon passe de « 2 × Posologie, borné 7–30 j » à 12 × Posologie,
        borné 30 j – 1 an
        (forecastHorizonHours, épinglé par ChartZoomTest).
      • désactiver la prévision pendant qu'on est dans le futur → retour
        automatique à « maintenant » (sinon fenêtre sans données).
    • Delta en JOURS sur la carte « Prochaine dose » (remontée : les heures
      deviennent illisibles au-delà de 24 h) : à partir d'un jour, la carte
      affiche « 5 j 2 h · sam. 6 18:00 (traitement) » avec le jour de la
      semaine ; en dessous, format heures/minutes inchangé
      (HrtDuration.daysAndHours + string next_dose_days FR/EN).
    • 5 nouveaux tests (112 au total / 94 sans les données locales) :
      bornes d'horizon et clamp de panoramique (ChartZoomTest ×4 — le clamp
      unique drag/zoom est centralisé dans clampPanHours),
      conversion heures→jours (HrtDurationTest ×1).
    Downloads