K3 et K7 livrés : la borne couvre 12 des 13 types

flutter build apk --debug vert, APK produit. SectionArticle et
SectionEvent sont branchés dans main_view.getContent ; seul
SectionParcours reste dehors, et définitivement.

Quatre choses que l'implémentation a corrigées ou apprises, toutes
reportées dans le plan, STATUS et la maquette :

- La barre de pied de la maquette n'appartient pas aux écrans.
  section_page_detail la dessine déjà pour les treize types, avec les
  clés back/menu selon isFromMenu. La dessiner aurait affiché deux
  boutons retour. La maquette est corrigée sur ce point.
- Un seul constructeur de marqueurs au lieu des quatre de mymuseum.
  MapAnnotationDTO et MapAnnotation ont des champs rigoureusement
  identiques mais sont deux types Dart distincts. Normalisé par une
  classe interne — L5 appliqué au front, et il porte d'autant plus que
  la convention [lng, lat] est l'endroit exact où une divergence ne
  lève aucune erreur.
- L'audio d'article se résout dans contents avant l'API, donc sans
  appel réseau quand il est embarqué, donc hors ligne aussi. Mymuseum
  appelle l'API systématiquement en ligne.
- Clé i18n event.live ajoutée aux 10 langues. Sans les 10,
  getFromLocale renvoie "" et la pastille rendrait une boîte vide.
  PL, CN, UK et AR sont de ma main et demandent une relecture humaine.

Ce qui n'est pas prouvé, et qui est écrit comme tel : le rendu. Aucun
des deux écrans n'a été vu à l'œil — un build vert ne dit rien d'une
mise en page, c'est la leçon du §1bis appliquée au design. Et aucun
SectionEvent n'existe en base, le type étant né avec Postgres v3 : le
§19.13 cas E en créera un.

Kanban : la carte « Types de section manquants sur le kiosk » quitte
Urgent (2 -> 1) pour Fait récemment (40 -> 41), bandeau du haut et
libellé « Quarante et un » compris. Compteurs des six colonnes
revérifiés un à un.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Fransolet 2026-08-12 15:20:29 +02:00
parent 4a4523e3a2
commit 3fe18e088b
4 changed files with 37 additions and 22 deletions

View File

@ -335,6 +335,19 @@ Restait le contenu réel du lot, les deux avertissements du build : **NDK 27.0.1
**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`. **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`.
**✅ K3 et K7 livrés le 2026-08-12 — `flutter build apk --debug` vert, APK produit.** La borne couvre désormais **12 des 13 types** : `SectionArticle` (K7) et `SectionEvent` (K3) sont branchés dans `main_view.getContent`. Seul `SectionParcours` reste dehors, et **définitivement** — un parcours guidé fait marcher le visiteur.
Les deux écrans suivent la maquette `DOCS/claude design/kiosk-paysage-article-event.html` : rail média ancré + colonne de lecture plafonnée pour l'article, bande héros à 26 % + programme + carte vive pour l'événement, détail d'un bloc **sous la carte** plutôt qu'en `showModalBottomSheet`.
**Quatre choses que le code a dictées, contre ce que la maquette ou mymuseum annonçaient :**
- ⚠️ **La barre de pied de la maquette n'appartient pas aux écrans.** `section_page_detail:184/198` dessine déjà le bouton retour, avec les clés `back`/`menu` selon `isFromMenu`. Les écrans qui auraient dessiné le leur en auraient affiché deux. La maquette est à corriger sur ce point.
- ⚠️ **Un seul constructeur de marqueurs au lieu des quatre de mymuseum.** `MapAnnotationDTO` et `MapAnnotation` ont des champs **rigoureusement identiques** mais sont deux types Dart distincts — d'où la duplication là-bas. Normalisé ici par une classe interne à deux fabriques. C'est **L5** appliqué au front, et il porte d'autant plus que la convention `[lng, lat]` est l'endroit exact où une divergence **ne lève aucune erreur**.
- ⚠️ **L'audio d'article se résout dans `contents` avant l'API.** `ContentDTO` porte son `resource` complet — idiome déjà utilisé par `marker_view` — donc l'audio est trouvé sans appel réseau quand il est embarqué, donc **hors ligne aussi**. `resourceGetDetail` n'est qu'un repli. Mymuseum appelle l'API systématiquement en ligne.
- ⚠️ **Nouvelle clé i18n `event.live` dans les 10 langues.** Sans les 10, `getFromLocale` renvoie `""` et la pastille « en cours » rendrait une boîte vide. **FR, EN, NL, DE, IT, ES sont sûres ; PL, CN, UK et AR sont de ma main et demandent une relecture humaine.**
⚠️ **Ce qui n'est pas prouvé** : le rendu. Aucun des deux écrans n'a été vu à l'œil — build vert ne veut pas dire mise en page juste, c'est exactement la leçon du §1bis appliquée au design. Et **aucun `SectionEvent` n'existe en base** (le type est né avec Postgres v3) : c'est le §19.13 cas E qui en créera un.
**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. **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. **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.

View File

@ -623,13 +623,16 @@
<div class="note"> <div class="note">
<span class="key">C</span> <span class="key">C</span>
<p> <p>
<strong>Barre de pied, hauteur de doigt.</strong> Un seul bouton, cible à <strong>Barre de pied — et elle n'appartient pas à ces écrans.</strong>
<strong>56 px minimum</strong> : on tape debout, parfois avec un enfant au bout du bras. <em>Corrigé le 12/08 en implémentant</em> : <code>section_page_detail</code> la dessine
<strong>Pas de sélecteur de langue</strong> — elle est choisie en amont, la réafficher ici déjà pour les treize types, avec les clés <code>back</code> / <code>menu</code> selon qu'on
rouvrirait une décision déjà prise. Et rien d'autre : <code>SectionPageDetail</code> ne vient d'un menu. Les deux écrans ne rendent que leur contenu — dessiner ce pied de page
reçoit qu'<em>une</em> section et un booléen <code>isFromMenu</code>, jamais la liste de ses aurait affiché <strong>deux boutons retour</strong>. Elle reste dans les maquettes parce que
voisines. Un repère du type « 3 / 8 » n'est donc adossé à aucune donnée — il faudrait le visiteur la voit, mais c'est la coquille qui la fournit.
descendre la liste jusqu'ici pour le calculer. <strong>Pas de sélecteur de langue</strong> — elle est choisie en amont. Et rien d'autre :
<code>SectionPageDetail</code> ne reçoit qu'<em>une</em> section et un booléen
<code>isFromMenu</code>, jamais la liste de ses voisines, donc un repère du type « 3 / 8 »
n'est adossé à aucune donnée.
</p> </p>
</div> </div>
</div> </div>

View File

@ -454,13 +454,13 @@
</header> </header>
<section class="summary" aria-label="Chiffres clés"> <section class="summary" aria-label="Chiffres clés">
<div class="stat"><span class="n n-critical">2</span><span class="k">Urgent</span></div> <div class="stat"><span class="n n-critical">1</span><span class="k">Urgent</span></div>
<div class="stat"><span class="n n-info">2</span><span class="k">Migration v3</span></div> <div class="stat"><span class="n n-info">2</span><span class="k">Migration v3</span></div>
<div class="stat"><span class="n n-warn">5</span><span class="k">Bugs ouverts</span></div> <div class="stat"><span class="n n-warn">5</span><span class="k">Bugs ouverts</span></div>
<div class="stat"><span class="n">6</span><span class="k">À tester</span></div> <div class="stat"><span class="n">6</span><span class="k">À tester</span></div>
<div class="stat"><span class="n">22</span><span class="k">Planifié</span></div> <div class="stat"><span class="n">22</span><span class="k">Planifié</span></div>
<div class="stat"><span class="n n-gate">8</span><span class="k">Bascule prod</span></div> <div class="stat"><span class="n n-gate">8</span><span class="k">Bascule prod</span></div>
<div class="stat"><span class="n n-good">40</span><span class="k">Fait récemment</span></div> <div class="stat"><span class="n n-good">41</span><span class="k">Fait récemment</span></div>
</section> </section>
<div class="filters" role="group" aria-label="Filtrer par domaine"> <div class="filters" role="group" aria-label="Filtrer par domaine">
@ -486,7 +486,7 @@
<!-- URGENT --> <!-- URGENT -->
<section class="col" style="--stripe: var(--critical)"> <section class="col" style="--stripe: var(--critical)">
<div class="col-head"><h2>Urgent</h2><span class="count">2</span></div> <div class="col-head"><h2>Urgent</h2><span class="count">1</span></div>
<div class="stack"> <div class="stack">
<article class="card" data-area="infra"> <article class="card" data-area="infra">
@ -496,15 +496,6 @@
<span class="src">todo-features.md — Sécurité réseau</span> <span class="src">todo-features.md — Sécurité réseau</span>
</article> </article>
<article class="card" data-area="manager" data-horizon="v1">
<div class="card-meta"><span class="tag">tablet-app</span><span class="flag f-warn">Lot K · périmètre kiosk</span></div>
<h3>Types de section manquants sur le kiosk</h3>
<p><code>tablet-app</code> couvre <strong>10 des 13</strong> types — <em>corrigé le 12/08, les docs disaient 11</em>. Le <code>switch</code> de <code>main_view.getContent</code> traite Map, Slider, Video, Web, Menu, Quiz, Pdf, Game, Agenda et Weather. <code>SectionEvent</code> et <code>SectionParcours</code> ne sont pas un retard — ils <strong>sont nés avec Postgres v3</strong> et n'ont jamais existé dans Mongo. <strong>Mais <code>SectionArticle</code> (type 6) en est un</strong> : son <code>case</code> est commenté « TODO » depuis l'origine et <code>Screens/Article/article_view.dart</code> est un fichier d'1 Ko. Un article tombe donc dans le <code>default</code> — « Ce type n'est pas supporté » — alors que l'article existait dans Mongo et est du contenu kiosk parfaitement légitime. <strong>Décidé le 12/08 : le supporter, c'est K7 au plan.</strong></p>
<p><strong>Le travail n'est pas la copie, c'est le paysage.</strong> Reprendre <code>mymuseum-visitapp/lib/Screens/Sections/Article/</code> est mécanique ; les écrans de mymuseum sont pensés pour un <strong>téléphone tenu debout</strong>, alors qu'une borne est large — un article en colonne unique sur 1280 px est illisible. <strong>K3 (<code>SectionEvent</code>) pose exactement la même question</strong> — héros, programme, carte — et la trancher deux fois donnerait deux mises en page différentes sur la même borne. <strong>Une seule passe de design pour les deux</strong>, même raisonnement d'économie que L5 et L15.</p>
<p><strong>Tranché le 12/08</strong><code>SectionParcours</code> : <strong>exclu définitivement</strong>, un parcours guidé fait marcher le visiteur avec géodéclenchement, ça n'a pas de sens sur borne fixe. <code>SectionEvent</code> : <strong>à supporter</strong>, 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).</p>
<p>Plus le renommage <code>SectionPuzzle</code><code>SectionGame</code> et le nouveau <code>SlidingPuzzle</code> : <strong>reprendre <code>mymuseum-visitapp/lib/Screens/Sections/Game/</code></strong> (<code>game_page.dart</code>, <code>sliding_puzzle_piece.dart</code>), dont la version est <strong>moins buguée</strong> que le <code>Puzzle/</code> de tablet-app. Récupération, pas réécriture.</p>
<span class="src">v1-plan.md lot K — K3, K4</span>
</article>
</div> </div>
</section> </section>
@ -875,9 +866,17 @@
<section class="done"> <section class="done">
<h2>Fait récemment</h2> <h2>Fait récemment</h2>
<p>Quarante chantiers clos entre le 5 et le 12 août 2026.</p> <p>Quarante et un chantiers clos entre le 5 et le 12 août 2026.</p>
<div class="done-grid"> <div class="done-grid">
<div class="done-item">
<strong>La borne couvre 12 des 13 types — SectionArticle (K7) et SectionEvent (K3) livrés</strong>
<span><code>flutter build apk --debug</code> <strong>vert</strong>, APK produit. Seul <code>SectionParcours</code> reste dehors, et <strong>définitivement</strong> — un parcours guidé fait marcher le visiteur. Les deux écrans suivent la maquette paysage : rail média ancré + colonne de lecture plafonnée pour l'article, bande héros à 26 % + programme + carte vive pour l'événement, détail d'un bloc <strong>sous la carte</strong> et non en <code>showModalBottomSheet</code>.</span>
<span>⚠️ <strong>La barre de pied de la maquette n'appartenait pas aux écrans</strong> : <code>section_page_detail</code> dessine déjà le bouton retour, avec les clés <code>back</code>/<code>menu</code> selon <code>isFromMenu</code>. Les dessiner aurait donné deux boutons. ⚠️ <strong>Un seul constructeur de marqueurs au lieu des quatre de mymuseum</strong> : <code>MapAnnotationDTO</code> et <code>MapAnnotation</code> ont des champs rigoureusement identiques mais sont deux types Dart distincts. Normalisé par une classe interne à deux fabriques — c'est L5 appliqué au front, et il porte d'autant plus que la convention <code>[lng, lat]</code> est l'endroit exact où une divergence <em>ne lève aucune erreur</em>.</span>
<span>⚠️ <strong>L'audio d'article se résout dans <code>contents</code> avant l'API</strong> : <code>ContentDTO</code> porte son <code>resource</code> complet, donc l'audio est trouvé sans appel réseau quand il est embarqué — donc hors ligne aussi. Mymuseum appelle l'API systématiquement en ligne. ⚠️ <strong>Clé i18n <code>event.live</code> ajoutée aux 10 langues</strong> — sans les 10, <code>getFromLocale</code> renvoie <code>""</code> et la pastille rendrait une boîte vide. <strong>PL, CN, UK et AR sont de ma main et demandent une relecture humaine.</strong></span>
<span>⚠️ <strong>Ce qui n'est pas prouvé : le rendu.</strong> Aucun des deux écrans n'a été vu à l'œil — un build vert ne dit rien d'une mise en page, c'est la leçon du §1bis appliquée au design. Et <strong>aucun <code>SectionEvent</code> n'existe en base</strong>, le type étant né avec Postgres v3 : c'est le §19.13 cas E qui en créera un.</span>
</div>
<div class="done-item"> <div class="done-item">
<strong>K5 — l'APK <code>mymuseum-visitapp</code> se construit, et le lot n'était pas ce qu'on croyait</strong> <strong>K5 — l'APK <code>mymuseum-visitapp</code> se construit, et le lot n'était pas ce qu'on croyait</strong>
<span><strong>La prémisse était périmée.</strong> Trois documents annonçaient « <code>flutter build apk</code> échoue côté Gradle/NDK », revérifié le 11/08. Les <strong>trois flavors</strong> (<code>dev</code>, <code>mdlf</code>, <code>fortsaintheribert</code>) construisent en exit 0, APK à l'appui. Sa config Android était <strong>déjà à niveau</strong> — Gradle 8.11.1, AGP 8.9.0, <code>-Xmx4096M</code>, <code>enableJetifier=false</code>, aucun forçage d'<code>androidx.lifecycle</code>. Les dix crans du 12/08 ont amené <strong>tablet-app jusqu'à mymuseum</strong> ; il ne restait pas la même migration à refaire ici. Le « réflexe du diff » noté la veille donnait la réponse en deux <code>cat</code> — appliqué, il l'a donnée.</span> <span><strong>La prémisse était périmée.</strong> Trois documents annonçaient « <code>flutter build apk</code> échoue côté Gradle/NDK », revérifié le 11/08. Les <strong>trois flavors</strong> (<code>dev</code>, <code>mdlf</code>, <code>fortsaintheribert</code>) construisent en exit 0, APK à l'appui. Sa config Android était <strong>déjà à niveau</strong> — Gradle 8.11.1, AGP 8.9.0, <code>-Xmx4096M</code>, <code>enableJetifier=false</code>, aucun forçage d'<code>androidx.lifecycle</code>. Les dix crans du 12/08 ont amené <strong>tablet-app jusqu'à mymuseum</strong> ; il ne restait pas la même migration à refaire ici. Le « réflexe du diff » noté la veille donnait la réponse en deux <code>cat</code> — appliqué, il l'a donnée.</span>

File diff suppressed because one or more lines are too long