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.
- 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.
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).
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.