31 Commits

Author SHA1 Message Date
902d521094 v1.13.0 (web) : reco prédictive — valeur E2 au creux, régime poolé, cible de creux — miroir Android
- predictedE2 : valeur brute au creux × facteur du ester (auto-calibration
  ON requise — sinon rien, une valeur brute serait trompeuse) ; rendu
  coloré face à la cible dans labs.js + home.js.
- pooledRegimeDoses : les doses de tous les traitements partageant (ester
  effectif, mg) forment UNE séquence — le re-parenting d'historique
  (« 6d-old ») ne redémarre plus la stabilisation. Garde-fous : ester ≠
  jamais poolé, dose ≠ exclue.
- Cible de creux E2 (opt-in) : store + carte settings + backup
  (rétrocompatible — un backup ancien n'efface pas la cible locale) +
  i18n FR/EN. ⚠️ DISTINCT des seuils d'alerte : jamais de notification.
- 15 tests (pooling ×3, statut cible, round-trip backup) ; leçon E2E :
  bump WEB_VERSION sans section CHANGELOG = dialog vide.

199 tests + E2E verts (check.sh). WEB_VERSION alignée sur 1.13.0.
v1.13.0
2026-10-07 09:58:52 +02:00
0e9a5672fb Docs §10 : étape 4 (releases) jamais optionnelle — backfill v1.9.5/v1.10.0→v1.12.0 (leçon : commit + tag ≠ release) 2026-09-30 20:48:22 +02:00
4bdcd52970 v1.12.0 (web) : fix #70 (inactifs sans projection) + page Doses (glyphes de forme, marqueurs prise de sang) — miroir Android
- FIX #70 : generateForecastDoses garde !isActive — un traitement archivé
  à Posologie ne projette plus de créneaux ; l'horizon du chip Prévision
  (chart.js) ne considère que les Posologies ACTIVES. §6.bis inchangé :
  l'historique reste simulé, seul le FUTUR s'arrête. 3 tests miroirs.
- Page Doses : routeGlyph (💊💉💧🩹🧴, miroir routeIcon) + encarts
  « prise de sang le même jour » 🧪↑/🧪↓ (labMarkersForDose, miroir) ;
  i18n FR/EN ; 10 tests doses-extras.test.js (⚠️ makeDose(ts, amount,
  overrides)).

194 tests + E2E verts (check.sh). WEB_VERSION alignée sur 1.12.0.
v1.12.0
2026-09-29 23:24:18 +02:00
0dd5fa7dfd v1.11.0 (web) : inactifs regroupés en bas de la page Traitements + cartes atténuées — miroir Android
- Helper pur treatmentsForDisplay dans js/data/models.js (miroir du Kotlin,
  tri STABLE : actifs d'abord, inactifs après, ordre relatif conservé dans
  chaque groupe) — demande : « peu discernables, à placer à la fin ».
- Rendu : en-tête « Traitements inactifs » (seulement s'il en existe),
  cartes opacity 0.55 en plus du badge — lisibles et cliquables.
- Clés i18n inactive_section FR/EN ; WEB_VERSION alignée sur 1.11.0.
- 4 tests treatments-display.test.js (miroir TreatmentsDisplayTest.kt).

184 tests + E2E verts (check.sh).
v1.11.0
2026-09-29 07:30:59 +02:00
f36e25ef62 Docs : audit post-release v1.10.0 — statut README, comptes de tests (180), description lab-timing alignée sur le fix #68 2026-09-27 23:16:59 +02:00
b865b1606f v1.10.0 (web) : fix #68 — creux pré-injection dans la reco de prise de sang (miroir Android)
Le « creux » était le minimum de la fenêtre entière (créneau N−1 → N) :
pour un ester à montée lente (EEn, pic ~J+5 ≈ intervalle 7 j) il tombait
juste après l'injection PRÉCÉDENTE — date antérieure à la stabilisation
affichée sur la même carte, et « juste avant ton injection du … » faux de
plusieurs jours. Le creux est désormais le niveau PRÉ-INJECTION du créneau
(principe v1.8.0 restauré ; EV inchangé — le point pré-injection EST son
minimum de fenêtre). WEB_VERSION alignée sur 1.10.0.

180 tests + E2E verts (check.sh) ; suite lab-timing inchangée (sa
sémantique épinglée était celle du fix).
v1.10.0
2026-09-27 23:10:10 +02:00
ff4a1374db v1.9.7 (web) : tolérance ± 24 h de l'écart inter-doses — miroir Android
La règle de stabilisation comparait l'écart inter-doses EXACTEMENT à
l'écart précédent : un log 30 min plus tard cassait le régime et
repoussait la stabilisation de 5 × t½ à chaque injection (creux fuyant).

Fix : chaque écart doit rester dans l'intervalle de Posologie ± 24 h
(GAP_TOLERANCE_MS, fenêtre vs l'intervalle THÉORIQUE) — des logs à 6,8 j
puis 7,2 j ne se déstabilisent plus en cascade ; un vrai changement de
créneau reste hors fenêtre.

Tests : « interval change » ré-épinglé (+21 j) + 2 tests de tolérance
miroirs (12 verts lab-timing). WEB_VERSION 1.9.7 + CHANGELOG/README.
v1.9.7
2026-09-21 22:20:21 +02:00
048a76e540 v1.9.6 (web) : la carte Accueil liste TOUTES les prochaines doses (triées) — miroir Android
- helper PUR nextDoseLineText dans format.js (miroir du Kotlin
  nextDoseLine) : « Xj Yh · sam. 26 10:00 (nom) » > 24 h, « XhMM » sinon,
  « N min » dans l'heure
- home.js : une ligne par traitement, triées par prochaine prise, 1ʳᵉ en
  avant, titre pluriel « Prochaines doses » dès 2 lignes (i18n EN/FR)
- 3 tests miroirs dans misc.test.js (178 verts + E2E)
- WEB_VERSION 1.9.6 + CHANGELOG/README
v1.9.6
2026-09-21 21:57:04 +02:00
be4d26b3e5 v1.9.5 : revue de code — garde cutoffHours ESE, portage optimisations v1.8.2, perf canvas, docs alignées
Corrigé (audit) :
- cutoffHours : garde hasModel pour ESE (parité Kotlin) — un backup
  importé ESE + ester non couvert levait TypeError → écran vide
- min/max en une passe : les spreads Math.min(...allPoints) levaient
  RangeError au-delà de ~1e5 arguments (Nuage × zoom max) et allouaient
  par frame
- init MCMC non bloquante : data-ready garantit désormais « asset chargé »

Perf (portage v1.8.2 Android, fin de la dérive de miroir) :
- prepareE2Context/e2AtCtx : doses groupées, cutoffs précalculés, Bateman
  paresseux ; computeCurve ne recalcule plus cutoffHours par point
- résultat identique (175 tests verts)

E2E : version lue via data-version (anti-bug v1.9.3)

Docs/commentaires : pk-engine (ESE analytique), pk-calibration (JSDoc
arrondi), dialogs (ESE=6), lab-timing (import mort, JSDoc orpheline),
home (COLORS), pk-profile-store (test-only), pk_profiles.json exclu du
zip (export-ignore, −548 Ko)
v1.9.5
2026-09-20 12:55:51 +02:00
f79a180e36 v1.9.4 (web) : presets ESE étendus à 6 esters + éditeur dynamique + portage v1.9.0 complété
- presets.js : EC huile (5 mg IM), EB (1 mg IM), EUCS suspension
  cristalline (10 mg SC) — 25 entrées, champs Bateman informatifs
- pk-engine.js : Esters.EUCS manquant (portage v1.9.0 incomplet — le
  preset référençait undefined)
- models.js : choicesForModel ESE = 6 esters (parité Android v1.9.0 ;
  était resté sur la couverture des tables ODS à 3) + KDoc à jour
- treatment-editor.js : liste des esters = choicesForModel(model) —
  rebascule sur EV si l'ester sort de la couverture au changement de
  modèle (garde anti 0 pg/mL) + re-render du formulaire
- tests/presets.test.js (nouveau, 6) : couverture 6 esters ESE, unicité,
  i18n EN/FR, TFS 7 / WHSAH 6 inchangés, choicesForModel aligné dispatchs
- versions 1.9.4 (settings + e2e) + CHANGELOG/§4/§8/README
v1.9.4
2026-09-19 23:29:40 +02:00
624e047f39 v1.9.4 (web) : presets ESE étendus (EC/EB/EUCS) + i18n — miroir Android
Le modèle ESE analytique (v1.9.0) couvre 6 esters injectables : presets
ajoutés pour EC (huile), EB et EUCS (undécylate suspension cristalline,
exclusif à ce fit) — les champs Bateman reflètent les t½ terminales des
fits (informatifs). Miroir de PKPresets.kt Android.
2026-09-19 22:59:28 +02:00
6d8efc81c0 Docs : §4 arbre (estrannaise-models/cloud + tests + rounding), §8 suites estrannaise/rounding à jour 2026-09-19 22:42:41 +02:00
f8bfbdcf40 v1.9.3 (web) : correction du numéro de version annoncé
Le zip v1.9.2 publié embarquait settings.js 1.9.1 (le commit de fix du
nuage n'incluait pas WEB_VERSION). WEB_VERSION 1.9.3, CHANGELOG [1.9.3]
(méta-correction : aucune autre différence avec 1.9.2), e2e + README à
jour.
v1.9.3
2026-09-19 22:22:57 +02:00
ee953507ef v1.9.2 (suite) : WEB_VERSION 1.9.2 + e2e versions + README statut
Suivi du commit précédent : le remplacement de WEB_VERSION (1.9.0 →
cible inexistante, le fichier était en 1.9.1) avait échoué
silencieusement, laissant les assertions e2e et le README en retard.
Corrigé : WEB_VERSION 1.9.2, assertions e2e 1.9.2, README web v1.9.2
(169 tests). check --release vert.
2026-09-19 22:19:57 +02:00
fab5a2abfb v1.9.2 : fix nuage vide sans traitement stocké ESE (filtre par ester effectif) — miroir Android
- estrannaise-cloud.js : le filtre des doses ne teste PLUS le pkModel
  STOCKÉ du traitement — le nuage couvre toutes les doses E2 à profil
  injectable dont l'ESTER EFFECTIF (override compris) est couvert par le
  fit Estrannaise (identique à l'ensemble redessiné par
  computeCurve(modelOverride = "ESE")). L'exclusivité ESE reste portée
  par le chip ; l'oral Bateman reste hors nuage ; les traitements
  inactifs sont inclus (§6.bis).
- Test réécrit : « les doses d'un traitement TFS sont couvertes quand ESE
  est affiché » (épinglé des deux plateformes) ; oral seul → vide.
- WEB_VERSION 1.9.2. CHANGELOG [1.9.2], README statut.
v1.9.2
2026-09-19 22:16:13 +02:00
fc1b6e1700 v1.9.1 : fix nuage calibré (il entoure la courbe ESE calibrée) + harmonisation arrondi (miroir Android)
- estrannaise-cloud.js : paramètre scalePerEster — le nuage reçoit la
  MÊME calibration que la courbe ESE (autoByModel ESE). Avant : courbe ESE
  calibrée mais nuage BRUT → échelles différentes (remontée v1.9.1 :
  « le nuage ne s'active que autour du tracé, pas autour du modèle
  Estrannaise »).
- chart.js : autoByModel.get('ESE')?.esterScales passé au nuage ;
  DEFAULT_NB_CURVES importé.
- +1 test : nuage calibré ×2 = nuage brut ×2 (167 verts au total).
- CHANGELOG [1.9.1] : fix nuage calibré + HARMONISATION de l'arrondi de
  la médiane de calibration (le web avait la troncature historique — les
  niveaux web/android convergent ; le niveau correct = l'ARRONDI).
- WEB_VERSION 1.9.1.
v1.9.1
2026-09-19 21:14:27 +02:00
174928bb6b v1.9.0 : modèle Estrannaise ANALYTIQUE (abandon de l'ODS) + nuage d'incertitude MCMC
Miroir fidèle du Kotlin (doc Android §7.12) :
- estrannaise-models.js : forme close 3C de estrannaise.js (paramètres
  publiés EV/EU/EEn/EC/EB/EUCS), posterior MCMC (313 échantillons/ester,
  asset mcmc_samples.json ≈ 48 Ko fetché au démarrage — remplace le fetch
  des tables ODS, 550 Ko), t½ terminale analytique, mapping en objets
  {d,k1,k2,k3} (miroir du Param Kotlin).
- estrannaise-cloud.js : nuage d'incertitude — 32 courbes du posterior
  (échelonnées, déterministes) superposant les doses des porteurs ESE ;
  exclusif ESE (TFS/WHSAH sans posterior publié), gardes (sans dose,
  nbCurves<2, MCMC non chargé → vide).
- pk-engine.js : dispatch ESE → forme close (plus de fallback PKProfileStore
  au runtime) ; cutoffHours ESE → 10 × t½ analytique ; lab-timing.js t½ ESE
  analytique ; app.js fetch MCMC remplace le fetch des tables ODS
  (démarrage plus rapide).
- chart.js/chart-canvas.js : chip « Nuage » (off, activable si ESE affiché,
  coupure auto si ESE off), clé 'CLOUD' skippée des légendes (leçon #63),
  nuage dessiné en alpha faible, légende dédiée ; seed démo + traitement
  EV/ESE (2 doses) pour démontrer le nuage ; choicesForModel ESE=6.
- Tests : estrannaise-models.test.js (6 : fidélité RMS/pics, dégénérés,
  MCMC 313×6, t½ analytique, gardes) + estrannaise-cloud.test.js (5 :
  32 courbes à dispersion réelle, fenêtre, exclusivité ESE, gardes)
  → 166 verts + E2E (chip/légende/exclusivité nuage) + check --release.
- WEB_VERSION 1.9.0 (versions sync Android). CHANGELOG [1.9.0] web.
v1.9.0
2026-09-19 20:45:53 +02:00
61683ba5c4 v1.8.1 : fix stabilisation (changements récents vus) + encart Accueil (miroir Android)
- lab-timing.js : computeRegimeStartMs — le régime courant = séquence
  terminale de doses à (ester effectif, dose, écart inter-doses) constants
  (écart comparé EXACTEMENT) : tout changement récent de dose/ester/
  posologie réinitialise la stabilisation. L'ancien proxy (1ʳᵉ dose du
  traitement) disait « stabilisée depuis février » malgré des changements
  récents (remontée v1.8.0). L'encart porte l'ESTER EFFECTIF de la
  dernière dose (override compris).
- home.js : encart « Prochaine prise de sang (suggestion) » sur l'ACCUEIL
  (demande) — creux daté + créneau associé + mention de stabilisation
  seulement si le régime n'était pas déjà stable.
- 3 nouveaux tests miroirs (155 verts) : dose/intervalle/ester → reset
  épinglé. WEB_VERSION 1.8.1. CHANGELOG [1.8.1], README.
v1.8.1
2026-09-17 19:47:49 +02:00
f5951e1806 v1.8.0 : recommandation de prochaine prise de sang (portage Android, miroir)
- js/pk/lab-timing.js : miroir fidèle de pk/LabTiming.kt — creux prévisionnel
  (minimum de la courbe E2 entre 2 injections), saut au premier creux
  STABILISÉ (5 × t½ terminale : TFS/WHS analytiques, Estrannaise lue dans
  la table via le nouveau pkProfileStore.terminalHalfLifeDays — refactor
  de la pente d'extrapolation de sample(), zéro duplication), filtres
  honnêtes (injectable actif + Posologie requis, creux ≥ now+6 h et jamais
  déjà mesuré, horizon borné → null), shouldSuggestPosology (invite quand
  un injectable actif est sans Posologie — demande v1.8.0).
- labs.js : encart « Prochaine prise de sang (suggestion) » ou invite,
  mutuellement exclusifs (miroir carte Android).
- i18n FR/EN (labrec_*), WEB_VERSION 1.8.0, assertions E2E.
- tests/lab-timing.test.js : 7 tests miroirs (152 verts au total) + E2E
  (encart rendu : titre, creux daté, créneau, stabilisation).
- Doc : §4 arbre, §8 suite + E2E, CHANGELOG [1.8.0], README.
v1.8.0
2026-09-17 18:46:51 +02:00
1957b73e3c v1.7.1 : fix « une seule note sur deux » dans les Analyses (miroir Android)
- format.js : labNotesForDisplay (helper PUR, miroir du Kotlin) — notes
  DISTINCTES d'une prise E2+T → une ligne par note préfixée du marqueur
  (« E2 : … » / « T : … ») ; note identique (dialog commun) → dédupliquée ;
  vides ignorées ; note seule → brute (v1.0 préservé). L'ancien code
  (.find() première non vide) perdait la note T à l'affichage quand la
  note E2 existait aussi (conservée en base, juste non montrée).
- labs.js : affiche TOUTES les lignes du helper (l'ancienne n'en rendait
  qu'une).
- app.js (seed ?demo=1) : la dernière paire E2/T porte des notes
  distinctes → fixture du scénario E2E.
- E2E : les deux notes préfixées s'affichent sur #labs.
- tests/lab-notes.test.js : 5 tests miroirs du Kotlin (145 verts au total).
- CHANGELOG [1.7.1] (l'oubli de cette entrée aurait laissé le dialog
  « Nouveautés » vide — attrapé par l'E2E, leçon #46 miroir), §4 arbre
  tests, README. WEB_VERSION 1.7.1.
v1.7.1
2026-09-17 12:30:59 +02:00
d822af2dd2 v1.7.0 : unités des axes du graphique (portage Android) + note auto-backup
- chart-canvas.js : pg/mL (E2, axe gauche) / ng/mL (T, axe droit) au
  sommet des colonnes de labels — miroir exact du fix Android (padTop
  élargi 12 → 26 px). Universelles, PAS des clés i18n.
- WEB_VERSION 1.7.0 (versions sync Android) ; E2E assertions version.
- CHANGELOG [1.7.0] : unités portées ; auto-backup Android NON porté
  (structurellement impossible côté navigateur — cf §12 Limites :
  pas d'OPEN_DOCUMENT_TREE persisté + WorkManager ; l'export/import
  manuel couvre la même donnée).
- Doc : §12 limites, README statut. check.sh vert (140 tests + E2E +
  garde de parité §3.bis).
v1.7.0
2026-09-16 19:53:41 +02:00
524f122f15 v1.6.1 : fix — les options du graphique se réinitialisaient toutes seules
Cause (divergence de portage, bug remonté « options reset sans changer de
menu ») : renderRoute() re-crée l'écran ENTIER à chaque tick minute (60 s),
mutation du store ou resize — et l'état des options était une variable
LOCALE de renderChart, retombant aux défauts à chaque re-création.
L'Android est immunisé (remember { mutableStateOf } survit aux
recompositions).

Fix (miroir Compose) :
- chart.js : état d'interaction au NIVEAU MODULE (chartUiState) ;
  renderChart(container, ctx, { preserveState }) réutilise l'état quand
  preserveState=true, le recrée aux défauts sinon ;
- app.js : preserveChartState = (route === 'chart' && lastRoute === 'chart')
  comparé AVANT la mise à jour de lastRoute — tick/store/resize préservent
  l'état, la navigation le réinitialise (miroir du reset d'un remember
  Android quitté).

Épinglé par l'E2E : resize (même code path que le tick) → chip Tracé labs
+ légende restent en place ; navigation → retour aux défauts.

Docs : §4 « État d'interaction persistant », §8 scénario E2E, §11 leçon
#15 (tout état d'UI doit survivre au re-rendu global), CHANGELOG [1.6.1]
(fix web-only : parité fonctionnelle = Android 1.6.0), README.
v1.6.1
2026-09-15 12:49:11 +02:00
ed623b786b Docs + process (web v1.6.0) : CHANGELOG, doc §4/§8/§11, garde de parité check.sh §3.bis
- check.sh : NOUVELLE étape 3.bis — garde de PARITÉ du portage
  Android↔web (si le dépôt Android voisin existe) : les symboles clés
  des features partagées (moteur prolongation, chip, avertissement)
  sont vérifiés des DEUX côtés — attrape un portage incomplet.
- Doc : arbre §4, suite lab-trajectory-model (§8), scénario E2E (§8),
  leçons #12 étendue (LABX) et #14 (parité) (§11).
- CHANGELOG web : entrée [1.6.0] (séparé du CHANGELOG Android).
- README : statut web v1.6.0, 140 tests verts.
v1.6.0
2026-09-12 23:51:20 +02:00
551d8fa29e v1.6.0 (web, UI + E2E) : chip Prolonger, split LAB/LABX, avertissement, WEB_VERSION 1.6.0
- chart.js : chip « Prolonger » (off par défaut, désactivé tant que
  Tracé labs est off), split série "LAB" (ancrée) / "LABX" (prolongée,
  rose atténué rgba(194,24,91,0.55)), légendes dédiées (clés LAB ET LABX
  skippées de la boucle — miroir leçon #63), AVERTISSEMENT « simple
  simulation, sans garantie de correspondre au réel, labs potentiellement
  erronés » affiché sous la légende tant que la prolongation est visible
  (condition factorisée : jamais de courbe prolongée sans avertissement).
- i18n : show_lab_track_extend, legend_lab_track_extend,
  lab_track_extend_warning (FR/EN synchronisées).
- E2E : scénario v1.6.0 (chip désactivé → activation → légende +
  avertissement → disparition à la désactivation) ; assertions version
  1.6.0.
2026-09-12 23:51:20 +02:00
bd338decbf v1.6.0 (web, moteur) : prolongation du tracé labs au-delà du dernier lab
Miroir fidèle du Kotlin (doc Android §7.10.bis) :
- extendBeyondLastLab (ρ_last constant au-delà du dernier ancre),
  lastAnchorMs, extensionHorizonEndMs (dernière dose E2 + cutoff du
  moteur — même sémantique d'extinction, une seule source de vérité).
- 8 nouveaux tests unitaires miroirs (140 verts au total) : identité
  M×ρ_last, suture exacte, horizon cutoff, dose EV après le dernier lab,
  garde #61, flag off = v1.5.0 bit-compatible, gardes du helper,
  lastAnchorMs.
2026-09-12 23:51:20 +02:00
38cf62826e Docs : audit doc↔code — arbre §4 complet, leçons 12/13 (§11), 132 tests
Constats de l'audit systématique :
- arbre §4 sans les fichiers conteneurisation (Dockerfile, nginx.conf,
  compose, .dockerignore) ni container-test.sh / publish-release.py
- check.sh décrit 1→6 (actualisé : + mode --release 7→9)
- suite lab-trajectory absent de l'arbre tests/
- mentions « 121 tests » périmées → 132 (statut/démarrage/§2/§8/footer)
- leçons de portage v1.5.0 ajoutées au §11 (12 : clé LAB skippée de la
  légende, miroir #63 Android ; 13 : imports ESM = modules exacts)
2026-09-11 16:27:56 +02:00
dfef8e90ef v1.5.0 : « Tracé labs » — portage complet de l'Android v1.5.0 (versions sync)
Miroir strict de pk/LabTrajectoryModel.kt (Android v1.5.0) :
- js/pk/lab-trajectory-model.js : courbe hybride M(t)×ρ(t) ancrée sur les
  labs — passage EXACT garanti, ρ log-linéaire, garde #61 (lab hors
  fenêtre d'action pas un ancrage), E2 seul, fenêtre [1er ; dernier lab],
  < 2 labs → vide, indépendante de la calibration (sinon double
  correction). JAMAIS dans levelAt/alertes.
- UI : chip 'Tracé labs' (off par défaut) dans la rangée modèles +
  scroll horizontal CONFINÉ à la rangée (miroir du fix Android) ;
  couleur #c2185b dashed ; leçon #63 Android-miroir — clé 'LAB' SKIPPÉE
  de la boucle légende (sinon légende TFS dupliquée).
- 11 tests miroirs de LabTrajectoryModelTest.kt (132 verts total).
- WEB_VERSION = 1.5.0 + CHANGELOG [1.5.0] + docs (§4/§8, README).

Détail d'exécution épingle: les deux problèmes du portage ont été
attrapés par node --check/E2E avant release (imports ESM faux —
labIsSignificant vit dans pk-calibration.js, pas pk-engine.js).
v1.5.0
2026-09-11 16:17:36 +02:00
e078650045 Cross-arch : container-test accepte une platform cible (incident « exec format error »)
Le premier déploiement NAS a échoué avec « exec /docker-entrypoint.sh:
exec format error » : image arm64 (buildée sur Mac Apple Silicon) exécutée
sur un hôte amd64. Le test réel l'a épiné : container-test.sh accepte
désormais un paramètre PLATFORM (build cross-arch SANS émulation — le
Dockerfile n'a aucun RUN — puis run émulé + E2E complet) :
  bash scripts/container-test.sh <port> linux/amd64
→ validé vert sur linux/amd64 (healthcheck durci, E2E complet).

Docs §10 : leçon cross-arch (les 2 procédures de build — sur le serveur
cible ou multi-arch push via buildx), statut : les DEUX archs testées ;
note : l'« io_setup() failed » sous émulation Rosetta est inoffensif.
2026-09-08 21:30:18 +02:00
96e0627741 Docs : première release web publiée (v1.4.10, cloudyfy) + statut conteneur réel
- §10 : v1.4.10 = première release Gitea web (zip vérifié par
  téléchargement via scripts/publish-release.py, construit par git archive
  AU TAG) ; farewell en attente de la création du repo
- §10 : statut conteneur = build + run réels validés localement (colima) ;
  container-test en configuration durcie vert ; deux problèmes du premier
  test documentés (tmpfs /tmp requis en read-only, case header_json curl)
- README : lien releases + statut conteneur
2026-09-08 21:09:34 +02:00
a0245e72c2 Conteneurisation Docker + tests de release (container-test, mode --release)
Conteneurisation (site 100 % statique — l'image ne détient AUCUNE donnée,
vie privée identique) :
- Dockerfile : nginxinc/nginx-unprivileged:alpine (uid 101, port 8080,
  pas de root), healthcheck wget intégré, labels OCI
- nginx.conf : no-cache systématique (cohérence du jeu de fichiers à
  chaque mise à jour d'image, coût nul : ~600 Ko + gzip sur l'asset PK),
  gzip, en-têtes de sécurité, deny des dotfiles
- .dockerignore : runtime uniquement (docs/ inclus — dialog changelog) ;
  local-test-data exclu en filet de sécurité
- docker-compose.yml : read_only + tmpfs (/var/cache/nginx, /run, /tmp —
  les temporaires de nginx-unprivileged, constat au premier test réel)
  + no-new-privileges

Nouveaux tests avant release :
- scripts/container-test.sh : build + run DURCI (config compose) +
  healthcheck healthy + endpoints 200 + headers (no-cache/nosniff/DENY/
  no-referrer) + gzip réel + MIME strict des modules ES + fichiers cachés
  non servis + image propre (pas de node_modules/npm) + docs/ embarqué +
  E2E playwright complet CONTRE LE CONTENEUR (HRT_E2E_BASE)
- scripts/e2e.mjs : mode externe HRT_E2E_BASE (pilote un site déjà déployé
  — conteneur inclus, serveur local non démarré)
- scripts/check.sh --release : supplée les 9 vérifications (version ↔
  changelog ↔ tag ↔ arbre propre + test conteneur si daemon)

Runtime Docker local installé pour le CI-like (colima 2 CPU / 2 Go) :
premier build + run réel = 2 problèmes testés et corrigés (tmpfs /tmp,
key case header_json curl). CONTAINER TEST OK en configuration durcie.
2026-09-08 21:07:23 +02:00
491efef8eb v1.4.10 — portage initial de l'app Android v1.4.10
Portage navigateur complet de l'app Android HormoneTrack v1.4.10 :
- moteur PK fidèle (Estrannaise tables ODS, Transfem Science V3C,
  WHSAH fit Mona, Bateman) — paramètres identiques, invariants Android
  préservés (fixes #19-#23, #35, #52-#62), 121 tests Node épinglés
- calibration par période d'ester et par modèle affiché (#60/#61)
- UI 6 écrans + éditeur, CurveChart Canvas (zoom/pan fractionnaire,
  prévision, pics/creux, fuseau configurable), rappels web
  (Notification API), seuils d'alerte, i18n FR/EN
- sauvegarde JSON v2 compatible Android bidirectionnelle (rétrocompat v1)
- 100 % local : localStorage, aucun serveur applicatif, aucune télémétrie
- processus : scripts/check.sh (syntaxe, i18n, tests, E2E navigateur,
  smoke HTTP), docs séparées (README + DEVELOPPEMENT + CHANGELOG)
- dépôt GIT SÉPARÉ de l'Android : historique 100 % propre, versions
  alignées sur l'Android porté, changelogs indépendants

Non porté (impossible dans un navigateur, documenté §12) : agenda
récurrent, notifications onglet fermé, montre.
v1.4.10
2026-09-08 14:34:58 +02:00