diff --git a/STATUS.md b/STATUS.md index 9174c17..d124dd5 100644 --- a/STATUS.md +++ b/STATUS.md @@ -30,7 +30,7 @@ Résumé de la table de suivi de ce fichier : |---|---|---| | manager-service | ✅ `dotnet build` et ✅ `dotnet test` **124/124** (2026-08-06) | La remise en route de la suite a révélé un **bug backend réel** : `BuildAuditEntries()` ajoutait un `AuditLog` au contexte *pendant* l'énumération du `ChangeTracker` → `InvalidOperationException: Collection was modified` sur toute écriture d'entité auditée (Section, Resource, Configuration, Device, User, Instance). Corrigé : énumération matérialisée, logs ajoutés après la boucle. Invisible jusque-là parce que les tests ne compilaient plus | | manager-app | ✅ `flutter build web` | débloqué : `// @dart=2.18` manquant dans `manager_api_new/lib/api/onboarding_api.dart` (fichier ajouté à la main pour l'onboarding, sans l'annotation de version que porte `api.dart`) — **cassait les 3 apps Flutter d'un coup** | -| mymuseum-visitapp | ❌ `flutter build apk` (**revérifié le 2026-08-11**) | Était ✅ le 2026-08-06, débloqué par la même correction + typage explicite dans `guided_step_challenge.dart:83`. **Casse maintenant côté Gradle**, pas côté Dart : `ndkVersion = "28.2.13676358"` réclamé dans `android/app/build.gradle`, avertissements KGP sur 11 plugins. Côté Dart il reste 4 erreurs, **toutes sur la branche Ray-Ban** (`kElevenLabsApiKey`/`kElevenLabsVoiceId` absents de `constants.dart`, jamais committés — voir §5bis), dans des fichiers hors du graphe de `main.dart`. Même famille que tablet-app : l'environnement Android a bougé | +| mymuseum-visitapp | ✅ `flutter build apk` — **les 3 flavors, vérifiés le 2026-08-12** (`dev`, `mdlf`, `fortsaintheribert`) | ⛔ **Le ❌ « revérifié le 2026-08-11 » était périmé.** Le build passe, et sa config Android était **déjà à niveau** — c'est `tablet-app` qui était en retard sur lui, pas l'inverse. K5 s'est donc réduit à deux alignements que le build réclamait en avertissement : NDK 27.0.12077973 → **28.2.13676358** (`speech_to_text` le réclame nommément) et Kotlin 2.1.0 → **2.3.10** (seuil 2.2.20 annoncé par Flutter ; même version que `tablet-app`). L'APK passe de 382 à **349 Mo**. Les 4 erreurs Dart Ray-Ban restent hors du graphe de `main.dart` et ne gênent pas le build (§5bis) | | visitapp-web | ✅ `npm run build` | débloqué : helper `getGeoPointLatLng()` dans `src/lib/geo.ts`, les 7 erreurs venaient d'un `unknown` non narrowé. ⚠️ ce type d'erreur est **invisible en `next dev`** | | tablet-app | ✅ `flutter build apk` — **réparé le 2026-08-12**, APK produit pour la première fois depuis le 16 avril | ⛔ **Le diagnostic « un seul défaut, purement Gradle, peut-être réglé par `5a6701d` » était doublement faux.** Il a tenu des mois parce que personne n'avait lancé la commande. Réalité : **dix crans d'outillage** (Gradle 7.5 → 8.11.1, AGP 7.2.0 → 8.9.1, Kotlin 1.9.0 → 2.3.10, option AGP supprimée, jcenter mort, heap Gradle 1536M → 4096M, Jetifier coupé, `resolutionStrategy` sur `androidx.lifecycle` retiré) — **corrigés le 2026-08-12** — **puis 132 erreurs Dart** que le Gradle masquait : l'app est restée sur **l'ancien contrat d'API**, celui d'avant Postgres v3. Détail complet et suite : **[v1-plan.md lot K](v1-plan.md)** | @@ -324,7 +324,17 @@ Les lots 1 et 2 sont terminés. **Le lot 3 et le lot médias sont tous les deux ⚠️ **Ce qui en fait un bloquant de la bascule — lien L19, que le plan ne portait nulle part.** Les tablettes en service chez MDLF et au Fort parlent l'ancien contrat. Le jour J, elles ne s'arrêteraient pas proprement : cartes sans points, écrans dégradés, **aucune erreur visible**. Et le parc des téléphones visiteurs, lui, ne se force pas — d'où la stratégie de coexistence adoptée au lot I (deux serveurs, l'ancienne prod figée, aucun DNS qui bouge). -**Périmètre kiosk tranché le 2026-08-12** : `tablet-app` couvre 11 des 13 types. `SectionParcours` est **exclu définitivement** (un parcours guidé fait marcher le visiteur — pas de sens sur borne fixe) ; `SectionEvent` est **à supporter** (borne d'accueil affichant le programme du jour, §19.13 cas E). Ni l'un ni l'autre n'est un retard : **les deux types sont nés avec Postgres v3**. S'ajoute le renommage `SectionPuzzle` → `SectionGame` et le nouveau `SlidingPuzzle`, à récupérer depuis `mymuseum-visitapp/lib/Screens/Sections/Game/` — sa version est moins buguée que le `Puzzle/` de tablet-app. +**✅ K5 livré le 2026-08-12 — et le lot n'était pas ce que le plan décrivait.** Les **trois flavors** de `mymuseum-visitapp` (`dev`, `mdlf`, `fortsaintheribert`) construisent, exit 0, APK à l'appui. **La prémisse « son APK ne compile pas » était périmée** : sa config Android était déjà à niveau (Gradle 8.11.1, AGP 8.9.0, `-Xmx4096M`, `enableJetifier=false`, aucun forçage d'`androidx.lifecycle`). Les dix crans du 12/08 ont amené **`tablet-app` jusqu'à `mymuseum`** — il n'y avait pas la même migration à refaire ici. Le réflexe du diff noté ci-dessus a donné la réponse en deux `cat`. + +Restait le contenu réel du lot, les deux avertissements du build : **NDK 27.0.12077973 → 28.2.13676358** (`speech_to_text` le réclame nommément) et **Kotlin 2.1.0 → 2.3.10** (sous le seuil 2.2.20 annoncé comme rupture par Flutter ; c'est la version de `tablet-app`, donc un alignement, pas une version neuve). Six builds — les trois flavors avant, les trois après. APK de **382 à 349 Mo**. + +⚠️ **Un cran de plus existe, délibérément non pris.** Kotlin réglé, le validateur Flutter en révèle deux autres : Gradle 8.11.1 → 8.14.0 et AGP 8.9.0 → 8.11.1, « soon be dropped ». Même cascade que les dix crans de `tablet-app` — chaque correctif découvre le suivant. Arrêté là parce que c'est du **terrain neuf pour les deux repos** (`tablet-app` est à 8.11.1/8.9.1, mêmes avertissements latents) : le faire ici seul **désaligne** les deux apps au lieu de les aligner. À faire d'un bloc sur les deux, ou pas du tout — c'est la dette d'outillage déjà parquée en V2. + +⚠️ **Question de branche, à trancher avant K6.** Le travail V1 récent de `mymuseum-visitapp` (D1, lot E, lot A) est committé sur **`Meta-Rayban-Test`**, pas sur `master` — c'est donc la branche de travail réelle, alors que le §5bis la décrit comme « un POC jamais mergé, actif commercial ». `tablet-app` est dans le même cas, sur `AI-Assistant-test`. **Publier des APK depuis une branche décrite comme un POC n'est pas neutre** : à clarifier avant K6, pas pendant. + +**Ce que K5 débloque** : **D0** (test-plan §21 sur device), donc la mesure des bugs offline D2-D5 et la confirmation du volet visiteur de D1 — qui ne tient aujourd'hui que sur `flutter analyze`. + +**Périmètre kiosk tranché le 2026-08-12** : `tablet-app` couvre 11 des 13 types — ⛔ **corrigé le 2026-08-12 : c'est 10, et le compte cachait un vrai manque.** Le `switch` de `main_view.getContent` traite Map, Slider, Video, Web, Menu, Quiz, Pdf, Game, Agenda, Weather. **`SectionArticle` (type 6) n'est pas traité** : son `case` est commenté « TODO » depuis l'origine et `Screens/Article/article_view.dart` fait 1 Ko. Un article tombe donc dans le `default` — « Ce type n'est pas supporté ». Contrairement à `SectionEvent` et `SectionParcours`, **ce type-là existait dans Mongo** : c'est un vrai retard, pas un type né avec Postgres v3. À trancher — le supporter ou l'assumer — mais pas à compter comme couvert. `SectionParcours` est **exclu définitivement** (un parcours guidé fait marcher le visiteur — pas de sens sur borne fixe) ; `SectionEvent` est **à supporter** (borne d'accueil affichant le programme du jour, §19.13 cas E). Ni l'un ni l'autre n'est un retard : **les deux types sont nés avec Postgres v3**. S'ajoute le renommage `SectionPuzzle` → `SectionGame` et le nouveau `SlidingPuzzle`, à récupérer depuis `mymuseum-visitapp/lib/Screens/Sections/Game/` — sa version est moins buguée que le `Puzzle/` de tablet-app. **Ce que ça coûte** : +3 à 5 jours. Ce n'est pas du périmètre ajouté, c'est du travail déjà dû que personne n'avait vu. @@ -710,7 +720,8 @@ Pas « le SDK est en preview » — la liste est plus concrète : - **Wake word de prod non réglé** : `porcupine_flutter` est commenté dans `pubspec.yaml` (payant), l'implémentation courante s'appuie sur `speech_to_text` / openWakeWord. - **Branche jamais mergée** dans `master`. - **Le POC ne compile plus en l'état — relevé le 2026-08-11.** `flutter analyze lib` sur `mymuseum-visitapp` remonte **4 erreurs**, toutes le même manque : `kElevenLabsApiKey` et `kElevenLabsVoiceId` sont **absents de `constants.dart`** alors que `glasses_qr_scanner_service.dart:110-111` et `wake_word_service.dart:133-134` les utilisent et importent bien `constants.dart`. La doc de `glasses_tts_service.dart:31-32` confirme l'intention (« typiquement `kElevenLabsApiKey` de `constants.dart` »). Ces deux constantes sont des **secrets qui n'ont jamais été committés** — le POC tournait avec un `constants.dart` local. Conséquence pratique : **« démontrable » suppose de les remettre**, ce n'est pas un `git checkout` qui suffit. À traiter avec la bascule TTS → Gemini ci-dessus, qui les rend inutiles. -- ⚠️ **`flutter build apk` ne passe plus non plus**, pour une raison distincte et non liée au Dart : Gradle s'arrête sur `Gradle build failed to produce an .apk file`, avec une demande de `ndkVersion = "28.2.13676358"` dans `android/app/build.gradle` et des avertissements KGP sur 11 plugins. Le §1bis le donnait ✅ au 2026-08-06 : **c'est l'environnement Android qui a bougé, pas le code.** Même famille de problème que le build `tablet-app` du lot A. +- ✅ ~~**`flutter build apk` ne passe plus non plus**~~ — **levé le 2026-08-12 par K5.** Les trois flavors construisent ; le NDK est passé à 28.2.13676358 et Kotlin à 2.3.10. Le point ci-dessus tient toujours : ce sont les **4 erreurs Dart** qui restent, et elles n'empêchent pas le build parce que ces fichiers sont **hors du graphe de `main.dart`**. Autrement dit, l'APK se construit **sans le POC dedans** — « démontrable » suppose toujours de remettre les deux constantes. +- ⚠️ **Et c'est la branche sur laquelle se fait le travail V1.** Le point « branche jamais mergée » ci-dessus décrit un POC de côté ; en réalité les commits V1 récents de `mymuseum-visitapp` (D1, lot E, lot A) sont **sur `Meta-Rayban-Test`**, pas sur `master`. Ce n'est donc pas une branche parallèle qu'on garde au chaud, c'est la branche de travail. À trancher **avant K6 (publier les APK)** : on publie depuis elle, ou on merge d'abord. `tablet-app` est dans le même cas, sur `AI-Assistant-test`. ### Ce que ça change côté commercial diff --git a/kanban.html b/kanban.html index ff2d232..d055ad1 100644 --- a/kanban.html +++ b/kanban.html @@ -454,13 +454,13 @@
-
3Urgent
+
2Urgent
2Migration v3
5Bugs ouverts
6À tester
20Planifié
8Bascule prod
-
39Fait récemment
+
40Fait récemment
@@ -486,7 +486,7 @@
-

Urgent

3
+

Urgent

2
@@ -496,19 +496,11 @@ todo-features.md — Sécurité réseau
-
-
mymuseum-visitappBuild — nouveau 11/08
-

mymuseum-visitapp ne compile plus non plus

-

Le §1bis le donnait ✅ au 06/08. Revérifié le 11/08 : flutter build apk échoue côté GradlendkVersion = "28.2.13676358" réclamé dans android/app/build.gradle, avertissements KGP sur 11 plugins. Ce n'est pas le Dart : le code applicatif analyse proprement.

-

Même famille que tablet-app : l'environnement Android a bougé sous les deux repos, le code n'a pas changé. Les traiter ensemble plutôt qu'un par un — c'est une seule migration Gradle/NDK, pas deux bugs.

-

Les 4 erreurs Dart restantes sont toutes sur la branche Ray-Ban et hors du graphe de main.dart : kElevenLabsApiKey et kElevenLabsVoiceId absents de constants.dart, jamais committés parce que ce sont des secrets. Le POC « démontrable » suppose donc de les remettre — voir §5bis.

- STATUS.md §1bis · §5bis -
-
tablet-appLot K · périmètre kiosk

Types de section manquants sur le kiosk

-

tablet-app couvre 11 des 13 types. Ce n'est pas un retard : SectionEvent et SectionParcours sont nés avec Postgres v3, ils n'ont jamais existé dans Mongo.

+

tablet-app couvre 10 des 13 types — corrigé le 12/08, les docs disaient 11. Le switch de main_view.getContent traite Map, Slider, Video, Web, Menu, Quiz, Pdf, Game, Agenda et Weather. SectionEvent et SectionParcours ne sont pas un retard — ils sont nés avec Postgres v3 et n'ont jamais existé dans Mongo. Mais SectionArticle (type 6) en est un : son case est commenté « TODO » depuis l'origine et Screens/Article/article_view.dart est un fichier d'1 Ko. Un article tombe donc dans le default — « Ce type n'est pas supporté » — alors que l'article existait dans Mongo et est du contenu kiosk parfaitement légitime. Décidé le 12/08 : le supporter, c'est K7 au plan.

+

Le travail n'est pas la copie, c'est le paysage. Reprendre mymuseum-visitapp/lib/Screens/Sections/Article/ est mécanique ; les écrans de mymuseum sont pensés pour un téléphone tenu debout, alors qu'une borne est large — un article en colonne unique sur 1280 px est illisible. K3 (SectionEvent) pose exactement la même question — héros, programme, carte — et la trancher deux fois donnerait deux mises en page différentes sur la même borne. Une seule passe de design pour les deux, même raisonnement d'économie que L5 et L15.

Tranché le 12/08SectionParcours : exclu définitivement, un parcours guidé fait marcher le visiteur avec géodéclenchement, ça n'a pas de sens sur borne fixe. SectionEvent : à supporter, une borne d'accueil qui affiche le programme du jour et le plan est le cas d'usage kiosk par excellence (§19.13 cas E).

Plus le renommage SectionPuzzleSectionGame et le nouveau SlidingPuzzle : reprendre mymuseum-visitapp/lib/Screens/Sections/Game/ (game_page.dart, sliding_puzzle_piece.dart), dont la version est moins buguée que le Puzzle/ de tablet-app. Récupération, pas réécriture.

v1-plan.md lot K — K3, K4 @@ -865,9 +857,17 @@

Fait récemment

-

Trente-neuf chantiers clos entre le 5 et le 12 août 2026.

+

Quarante chantiers clos entre le 5 et le 12 août 2026.

+
+ K5 — l'APK mymuseum-visitapp se construit, et le lot n'était pas ce qu'on croyait + La prémisse était périmée. Trois documents annonçaient « flutter build apk échoue côté Gradle/NDK », revérifié le 11/08. Les trois flavors (dev, mdlf, fortsaintheribert) construisent en exit 0, APK à l'appui. Sa config Android était déjà à niveau — Gradle 8.11.1, AGP 8.9.0, -Xmx4096M, enableJetifier=false, aucun forçage d'androidx.lifecycle. Les dix crans du 12/08 ont amené tablet-app jusqu'à mymuseum ; il ne restait pas la même migration à refaire ici. Le « réflexe du diff » noté la veille donnait la réponse en deux cat — appliqué, il l'a donnée. + Le contenu réel du lot : les deux avertissements du build. NDK 27.0.12077973 → 28.2.13676358 (speech_to_text le réclame nommément) et Kotlin 2.1.0 → 2.3.10 (sous le seuil 2.2.20 annoncé comme rupture par Flutter ; aligne sur tablet-app, aucune version neuve introduite). Six builds au total — les trois flavors avant, les trois après — logs relus intégralement, codes de sortie lus hors redirection, APK datés vérifiés sur disque : les trois pièges de vérification du 12/08 sont couverts. Effet mesuré : l'APK passe de 382 à 349 Mo. + ⚠️ Un cran de plus existe, délibérément non pris. Kotlin réglé, le validateur Flutter en révèle deux autres — Gradle 8.11.1 → 8.14.0 et AGP 8.9.0 → 8.11.1, « soon be dropped ». Même cascade que les dix crans de tablet-app. Arrêté là parce que c'est du terrain neuf pour les deux repos (tablet-app est à 8.11.1/8.9.1, mêmes avertissements latents) : le faire ici seul désaligne les deux apps au lieu de les aligner. À faire d'un bloc sur les deux, ou pas du tout — le plan parke déjà cette dette en V2. + ⚠️ Une question ouverte pour K6 : le travail V1 récent de ce repo (D1, lot E, lot A) est committé sur Meta-Rayban-Test, pas sur master. C'est la branche de travail réelle, alors que le §5bis la décrit comme « un POC jamais mergé ». À trancher avant de publier. tablet-app est dans le même cas, sur AI-Assistant-test. Ce que K5 débloque : D0 / test-plan §21 sur device, donc la mesure des bugs offline D2-D5 et la confirmation du volet visiteur de D1, qui ne tient aujourd'hui que sur flutter analyze. +
+
Lot médias terminé côté serveur — backfill (C2) et quota autoritaire (C3) C2 : POST /api/Resource/backfill-storage, SuperAdmin, dryRun à true par défaut — la migration se joue sur une base vide, ce backfill sur des lignes de production. La méthode annoncée au plan (« SizeBytes par listing du bucket Firebase ») était inapplicable : le serveur n'avait aucun client de stockage. Le sondage passe par HEAD, et le sondeur est extrait plutôt que recopié (ResourceSizeProbe, partagé avec la migration — même raisonnement que L5). ⚠️ L'extraction a bouché un trou que personne ne cherchait : l'original ne notait l'échec que dans son catch, or un HEAD sur un blob absent ne lève pas — il répond 404 sans Content-Length. Ces ressources arrivaient à 0 octet sans figurer dans le rapport. Le « 37 sur 45 » du plan n'étant pas vérifiable d'ici, le backfill rend son propre inventaire, Orphans et Unsized séparés — deux causes distinctes, jamais additionnées. diff --git a/v1-plan.md b/v1-plan.md index fa902ee..3f3e39a 100644 --- a/v1-plan.md +++ b/v1-plan.md @@ -280,10 +280,11 @@ Ordre du §2 de STATUS.md, corrigé par **L12**. |---|---|---| | ~~**K2**~~ ✅ **2026-08-12** | **Portage livré. Les 132 erreurs de contrat sont tombées** ; `flutter analyze lib` ne renvoie plus que les 6 erreurs `PuzzleDTO`, qui sont K4. Fait : `TabletAppContext.currentAppConfigurationLink` (copie du getter mymuseum), `lib/Helpers/geo.dart` avec l'extension `lat`/`lng`, 67 accès `roundedValue` rebranchés, `main_view` et les 4 vues carte portées.
⚠️ **Deux bugs latents trouvés — c'est ce qui justifiait de le faire à la main.**
**(1)** `applicationInstanceDTO` n'était assigné **que si `instanceDTO.isAssistant == true`** (`main_view:339`) : il servait de drapeau d'assistant. Ce DTO portant désormais les `AppConfigurationLink`, le getter aurait renvoyé `null` sur **toute instance sans IA — donc MDLF et le Fort** — et les cinq réglages seraient retombés sur leurs défauts, sans erreur ni log. Corrigé : assignation inconditionnelle + drapeau explicite `isAssistantEnabled`, qui **préserve le ET** instance × canal (les deux gardes de `AiController:315/360`).
**(2)** `ConfigurationDTO.isTablet` a disparu : le filtre « configurations pour tablette » de `getConfigurations` n'avait plus de source. Il porte désormais sur les `AppConfigurationLink` du canal `AppType.Tablet`, même appel que `main_view`. ⚠️ **À valider sur device (§0/§18)** : si un client a des configurations non rattachées à son canal tablette, l'écran de sélection sera **vide**. L'ancien code avait le même angle mort, mais la donnée qui pilote le filtre a changé.
⚠️ **Piège de vérification** : `flutter analyze` écrit `error - `, pas `error • ` — un grep sur la mauvaise forme a fait conclure « 0 erreur » alors qu'il en restait 10 | | ~~K2 — notes de conception~~ | ⚠️ **Deux conventions de coordonnées coexistent** dans le projet — `GeoPointDTO` en `[lng, lat]`, géométries de `GuidedStep` en `[lat, lng]`. Une confusion **ne lève aucune erreur**, elle déplace les points. Détail et tableau dans **STATUS.md §1sexies**. Fondations déjà posées le 2026-08-12 : `TabletAppContext.currentAppConfigurationLink` et `lib/Helpers/geo.dart`.
**Portage du contrat d'API** — **132 erreurs Dart, 3 causes** : `ConfigurationDTO.roundedValue`/`isDate`/`isHour`/`isSectionImageBackground`/`screenPercentageSectionsMainPage` ont migré vers **`AppConfigurationLinkDTO`** (73 err.) · `GeoPointDTO.latitude/longitude` → **`GeometryDTO? geometry`**, effet de PostGIS (40 err.) · les `min()` sur `dynamic` en découlent (19 err.) | **Le modèle est déjà écrit** : `mymuseum-visitapp` a fait ce portage (`visitAppContext.currentAppConfigurationLink?.roundedValue`, `Models/visitContext.dart`). Copier, ne pas concevoir. Les 40 sites `latitude`/`longitude` se traitent par **une extension Dart sur `GeoPointDTO`** plutôt qu'un à un | -| **K3** | **Périmètre kiosk — tranché le 2026-08-12.** `tablet-app` couvre **11 des 13** types. **`SectionParcours` : exclu définitivement** — un parcours guidé fait marcher le visiteur avec géodéclenchement, ça n'a aucun sens sur borne fixe. **`SectionEvent` : à supporter** — une borne d'accueil qui affiche le programme du jour et le plan est le cas d'usage kiosk par excellence, et c'est le scénario du §19.13 cas E | Ni l'un ni l'autre n'est un retard : les deux types **sont nés avec Postgres v3**, ils n'ont jamais existé dans Mongo (cf. lot G, écart a) | +| **K3** | **Périmètre kiosk — tranché le 2026-08-12.** ⛔ **`tablet-app` couvre 10 des 13 types, pas 11 — recompté dans le `switch` le 2026-08-12.** `main_view.getContent` traite Map, Slider, Video, Web, Menu, Quiz, Pdf, Game, Agenda, Weather. **`SectionArticle` (type 6) manque** : son `case` est commenté « TODO » et `Screens/Article/article_view.dart` fait 1 Ko — un article tombe dans le `default`, « Ce type n'est pas supporté ». **Ce type-là existait dans Mongo**, contrairement aux deux ci-dessous : c'est un vrai retard, à trancher (le supporter ou l'assumer) et non à compter comme couvert. Énoncé d'origine, qui reste valable : `tablet-app` couvre **11 des 13** types. **`SectionParcours` : exclu définitivement** — un parcours guidé fait marcher le visiteur avec géodéclenchement, ça n'a aucun sens sur borne fixe. **`SectionEvent` : à supporter** — une borne d'accueil qui affiche le programme du jour et le plan est le cas d'usage kiosk par excellence, et c'est le scénario du §19.13 cas E | Ni l'un ni l'autre n'est un retard : les deux types **sont nés avec Postgres v3**, ils n'ont jamais existé dans Mongo (cf. lot G, écart a) | | ~~**K4**~~ ✅ **2026-08-12** | **Écran Game repris de mymuseum.** Les 6 fichiers de `Screens/Sections/Game/` sont dans `tablet-app/lib/Screens/Game/`, contexte adapté ; `lib/Screens/Puzzle/` supprimé ; `main_view` bascule sur `SectionType.Game` / `GameDTO` / `GamePage`. **Gains** : le puzzle glissant (mélange par mouvements valides, donc toujours soluble), le bouton d'indice, et un dimensionnement qui respecte le ratio de l'image — 508 lignes contre 237 à l'ancien `puzzle_view`.
⚠️ **Une décision de rendu à valider à l'œil** : mymuseum code ses couleurs **en dur par flavor client** (`kMainColor0/1/2` — rouge MDLF, bleu Fort). `tablet-app` n'a pas de flavor : un seul APK sert tous les clients et la charte vient de la configuration choisie au pincode. Recopier ces constantes aurait affiché du bleu chez MDLF. Le dégradé et le bouton d'indice sont donc **dérivés de `configuration.primaryColor`** (même parsing que `audio_player`/`loading_common`, repli `kTestSecondColor`, 3 nuances par `Color.lerp`). Plus juste sur le fond, mais **le rendu diffère de la version mobile** : si le dégradé dessiné à la main est préféré, figer les trois couleurs | | ~~K4 — énoncé d'origine~~ | **`SectionPuzzle` → `SectionGame` + le type glissant.** Le serveur a renommé et porte `GameTypes { Puzzle, SlidingPuzzle }` ; `tablet-app` a encore un écran `Puzzle/` qui ne connaît que l'ancien. **Reprendre le code de `mymuseum-visitapp/lib/Screens/Sections/Game/`** — `game_page.dart` et `sliding_puzzle_piece.dart` existent déjà là-bas, et cette version est **moins buguée** que celle de tablet-app | Récupération, pas réécriture | -| **K5** | **`mymuseum-visitapp` : même rattrapage d'outillage.** Son APK ne compile pas non plus (Gradle/NDK) — c'est ce qui empêche de vérifier D1 sur device et **bloque D0 / test-plan §21** | Son code est déjà porté sur le nouveau contrat ; c'est l'outillage qui manque, pas le portage | +| ~~**K5**~~ ✅ **2026-08-12** | **Les trois flavors de `mymuseum-visitapp` construisent** (`dev`, `mdlf`, `fortsaintheribert`), exit 0, APK à l'appui. **D0 est débloqué.**
⛔ **L'énoncé était faux : il n'y avait pas de « même rattrapage » à faire.** Sa config Android était **déjà à niveau** — Gradle 8.11.1, AGP 8.9.0, `-Xmx4096M`, `enableJetifier=false`, aucun forçage d'`androidx.lifecycle`. Les dix crans de K1 ont amené **`tablet-app` jusqu'à `mymuseum`** ; le lot supposait la symétrie du problème, elle n'existait pas. Le réflexe du diff annoncé en K1 a donné la réponse en deux `cat`.
**Ce qui restait, et qui est fait** : les deux avertissements du build. NDK **27.0.12077973 → 28.2.13676358** (`speech_to_text` le réclame nommément) et Kotlin **2.1.0 → 2.3.10** (seuil 2.2.20 annoncé comme rupture ; c'est la version de `tablet-app`, donc un alignement). Six builds — trois avant, trois après. APK de **382 à 349 Mo**.
⚠️ **Un cran de plus existe, délibérément non pris** : Kotlin réglé, Flutter réclame Gradle 8.14.0 et AGP 8.11.1. C'est du **terrain neuf pour les deux repos** (`tablet-app` est à 8.11.1/8.9.1, mêmes avertissements latents) — le faire ici seul **désaligne** les deux apps. À faire d'un bloc sur les deux, ou pas du tout : c'est la dette d'outillage déjà parquée en V2 | Son code était déjà porté sur le nouveau contrat — **c'est ce qui aurait dû mettre la puce à l'oreille** : le repo qui a servi de modèle au portage K2 n'avait pas de raison d'être en retard d'outillage sur celui qui le copiait | +| **K7** | **`SectionArticle` sur le kiosk — ajouté le 2026-08-12**, en recomptant les types couverts. Son `case` est commenté « TODO » dans `main_view.getContent` et `Screens/Article/article_view.dart` fait 1 Ko : un article rend « Ce type n'est pas supporté ». **Contrairement à `SectionEvent` et `SectionParcours`, ce type existait dans Mongo** — c'est donc un vrai retard, pas un type né avec Postgres v3, et il sortira de la migration avec du contenu réel.
**Le code est une reprise de `mymuseum-visitapp/lib/Screens/Sections/Article/`**, pas une conception. **Le travail n'est pas là** : il est dans le **passage en paysage**. Les écrans de mymuseum sont pensés pour un téléphone tenu debout ; une borne est large, et un article rendu en colonne unique sur 1280 px de large est illisible. C'est le seul endroit du lot K où il y a une décision de mise en page à prendre, pas une copie à faire — d'où la maquette ci-dessous | **À traiter avec K3** : `SectionEvent` pose exactement la même question de paysage (héros, programme, carte), et la trancher deux fois donnerait deux mises en page différentes sur la même borne. Une seule passe de design pour les deux, même raisonnement d'économie que **L5** et **L15** | | **K6** | **Publier les APK à jour**, puis vérifier le renouvellement du parc | **L19**. Les tablettes kiosk sont des appareils que tu gères — mise à jour maîtrisée. **Les téléphones des visiteurs, non** : aucune manœuvre technique ne force une mise à jour, d'où la stratégie de coexistence du lot I | ### Lot J — RGPD & conformité (2 à 3 jours) — juste avant le lot I @@ -387,7 +388,7 @@ A (½-1j) ──► B (2-3j) ──► G (3-4j) ──► H (1 sem.) ──► I │ │ │ └──► C1 ──► C2 ──► C3 │ C4 (C5 ✅) - ├──► K1 ✅ ──► K5 ──► D0 (test device) ──► D1..D5 + ├──► K1 ✅ ──► K5 ✅ ──► D0 (test device) ◄── débloqué ──► D1..D5 │ └──► K2 ──► K3, K4 ──► K6 (publier) ──► bascule (L19) ├──► D-bis : DB0 ──► DB1 ──┬──► DB2 │ ├──► DB3 ──► F (job de thèmes) @@ -399,7 +400,8 @@ A (½-1j) ──► B (2-3j) ──► G (3-4j) ──► H (1 sem.) ──► I ``` - **Chemin critique : A → B → G → H → I.** Tout le reste s'y greffe. -- **Le lot K s'y greffe par la fin** : K2/K3/K4 sont parallélisables avec C, D, E et F, mais **K6 (publier les apps) précède la bascule** (**L19**). Et **K5 précède D0** : sans APK `mymuseum-visitapp`, pas de test §21 sur device, donc pas de mesure des bugs offline restants. +- **Le lot K s'y greffe par la fin** : K2/K3/K4 sont parallélisables avec C, D, E et F, mais **K6 (publier les apps) précède la bascule** (**L19**). ~~Et **K5 précède D0**~~ — **K5 est livré le 2026-08-12, D0 n'est plus bloqué** : l'APK `mymuseum-visitapp` existe pour les trois flavors, le test §21 sur device peut être joué. C'est aujourd'hui **le prochain geste qui demande un appareil**, et le seul qui dise si les bugs offline D2-D5 se manifestent réellement (**L11**). +- ⚠️ **Une question à trancher avant K6, qui n'est pas technique** : le travail V1 des deux apps visiteur est committé sur des branches qui ne sont pas `master` — `Meta-Rayban-Test` pour `mymuseum-visitapp`, `AI-Assistant-test` pour `tablet-app`. Le §5bis décrit pourtant la première comme « un POC jamais mergé ». Publier des APK depuis une branche décrite comme un POC n'est pas neutre : clarifier avant K6, pas pendant. - **C, D, D-bis, E, F sont parallélisables** entre eux, mais **C1 doit précéder G** (L5) et **B doit précéder G** (L2). - **DB3 doit précéder le job de thèmes du lot F** (L16) : c'est le seul endroit du plan où le design commande le backend. - **La boucle du graphe a disparu le 2026-08-11.** Elle venait de : I3 dépend de la rotation des secrets (dans le lot A), et H4 dépend de I3 (L12). En déplaçant la rotation en **I0**, la contrainte devient linéaire — `I0 → I3 → H4` — et il n'y a plus de cycle à contourner. **Contrepartie à ne pas rater** : H4 (test d'onboarding) exige `app.myinfomate.be` déployé, donc I3, donc I0. Concrètement, **la rotation des secrets doit être faite avant la fin du lot H**, pas au tout dernier moment. C'est le seul endroit où le report du 11/08 crée une échéance interne.