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