From 2d9eaf74dc49e3474a1833f9e78537ac428a26ed Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Thu, 13 Aug 2026 16:50:58 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9veloppement=20V1=20clos=20=E2=80=94=20ST?= =?UTF-8?q?ATUS,=20plan=20et=20kanban=20align=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STATUS.md portait encore le lot J et D5 comme à faire, et son « 📍 Reprendre ici » datait du 10/08 alors que ses trois étapes sont terminées : il est marqué périmé et renvoie vers v1-plan.md. La ligne « mode offline » du §1 décrivait un pipeline commenté, corrigé depuis D1 puis D5. Nouveau § qui consolide la journée : les lots F et J clos, et les cinq pièges rencontrés — la garde du proactif qui aurait coûté des jetons pour rien, l'écran de téléchargement qui ne concluait jamais, le choix de voix du client jamais honoré, les trois écrans qui journalisaient de fausses questions de visiteur, et le même code copié trois fois ne portant sa décision qu'une seule. Kanban : le bandeau annonce que le dev V1 est clos. Compteurs mesurés — Fait récemment 60, aucun bug ouvert. Republié sur l'artifact. Co-Authored-By: Claude Opus 5 --- STATUS.md | 26 ++++++++++++++++++++++++-- kanban.html | 3 ++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/STATUS.md b/STATUS.md index 623bcf5..a6323f8 100644 --- a/STATUS.md +++ b/STATUS.md @@ -12,7 +12,7 @@ Résumé de la table de suivi de ce fichier : - **Fait** : SectionEvent, Escape/Puzzle games, GuidedPath + progression carte, push, stats tracking, sync agenda/météo, traduction IA, quotas (IA/stockage/stats) par plan, audit log backend fiabilisé, refacto SectionParcours/GuidedPath/SectionGame (backend, vérifié 2026-07-15). -- **Partiel** : Beacons/geofencing (manager-app UI ⚠️), AI Assistant (manager-app ⚠️), **mode offline — diagnostic posé le 2026-08-07, bien pire qu'un « sélectif » : le pipeline de collecte des ressources est commenté des deux côtés, une visite téléchargée n'embarque ni images d'articles ni audios → [v2/offline-visit-plan.md](v2/offline-visit-plan.md)**, repasse UI globale, refacto SectionParcours côté manager-app/visitapp-web/mymuseum-visitapp (UI présente mais sous-comportements non revérifiés en détail — voir section "Refactoring majeur" de todo-features.md). +- **Partiel** : Beacons/geofencing (manager-app UI ⚠️), AI Assistant (manager-app ⚠️), ~~**mode offline**~~ ✅ **corrigé le 2026-08-11 (D1) puis complété le 13/08 (D5)** — le pipeline de collecte n'est plus commenté, une visite embarque désormais contenus, audios et icônes, et une visite incomplète ne s'annonce plus téléchargée. **Reste à confirmer sur device** (§21 / D0), c'est le seul point encore ouvert du volet offline. Repasse UI globale, refacto SectionParcours côté manager-app/visitapp-web/mymuseum-visitapp (UI présente mais sous-comportements non revérifiés en détail — voir section "Refactoring majeur" de todo-features.md). - **🧪 Implémenté mais jamais testé (2026-08-05)** : **onboarding self-service complet** — inscription sur myinfomate-landing (`/[lang]/signup`), création auto de l'instance + du premier user, essai 14j, Stripe (customer/Checkout/webhook/Tax), 9 emails Resend (domaine vérifié, envoi réel validé), job Hangfire du cycle d'essai, watermark « Aperçu » visitapp-web, écran Abonnement manager-app, mot de passe oublié + invitation user, plafond IA d'essai. Les 4 repos compilent, migrations appliquées en base locale, **aucun parcours exécuté** → checklist de test dans `todo-features.md` (section "🧪 Checklist de test end-to-end"). Reste à faire côté config : alias mail `onboarding@myinfomate.be`, et `whsec_` de la Stripe CLI pour tester le webhook en local. - **À faire** : dashboard super-admin V2, facturation V2. ✅ **Le Stripe Customer Portal est complet le 2026-08-13** (backend + bouton manager-app). - ⚠️ **Cette ligne était périmée sur six points, revérifiés dans le code le 2026-08-13.** Sont **faits** : écran audit log manager-app (front livré le 12/08), **rate limiting API Keys** (livré, pas seulement décidé — politique `ai` dans `Startup.cs:279`, `UseRateLimiter()` en `:344`, les deux endpoints décorés), gestion des users par instance (plafond serveur + compteur UI, 12/08), nettoyage `SectionEvent.ParcoursIds` (11/08), et le **backend** du Customer Portal (13/08). L'**unification `QuestionType`** n'est pas « à faire » mais **écartée** : le trio TextLibre/Digicode/ExpectedAnswer n'a jamais existé dans le code, l'enum a trois valeurs et le digicode est un comportement dérivé, pas un type — reste une propreté front, elle aussi livrée (alias nommés, 11/08). @@ -290,7 +290,9 @@ Ingestion documentaire (PdfPig + OCR + formats + UI `IncludeInAiKnowledge`, avec **Ordre de grandeur total : ~3 semaines**, dont une bonne moitié dans le lot 3 et les 13 sous-types. -### 📍 Reprendre ici — ordre arrêté le 2026-08-10 +### 📍 ~~Reprendre ici~~ — périmé, conservé pour la trace (ordre arrêté le 2026-08-10) + +> ⛔ **Ne plus repartir d'ici : les trois étapes ci-dessous sont terminées** (A le 10/08, B le 10/08, C le 12/08), et le développement V1 est clos depuis le 2026-08-13. **Le point d'entrée est [v1-plan.md](v1-plan.md)** ; l'état du jour est au § « Les lots F et J sont clos » ci-dessus. Ce qui reste avant la prod est du test, du juridique et de l'infra — plus une ligne de code applicatif. Les lots 1 et 2 sont terminés. **Le lot 3 et le lot médias sont tous les deux obligatoires** — l'ordre ci-dessous ne trie pas par importance mais par coût de report. Ni l'un ni l'autre ne bloque plus la bascule : ce qui devait partir avec la migration, c'était le schéma, et il est en place. @@ -439,6 +441,26 @@ Remplacé par `GetReferencedResourceIds()`, déjà implémentée sur les 13 sous > ⚠️ **Ce qui reste du lot F n'est plus dans `manager-service`** : le bouton du portail et le diviseur `aiTokensPerQuestion` dans `manager-app` (petit), et surtout les trois chantiers `mymuseum-visitapp` — déclenchement proactif (+ M3), miroir de la conversation vocale, émission des événements vocaux. Plus l'aperçu de conversation (**L9**), indépendant. +--- + +### 🎉 Les lots F et J sont clos le 2026-08-13 — il ne reste plus de développement V1 + +> Tout ce qui suit a été livré dans la même journée, sur 5 repos. `dotnet test` **229** (213 passés, 16 sautés faute de démon Docker), APK `dev` de `mymuseum-visitapp` ✅, `flutter build web` de `manager-app` ✅, `npm run build` de `visitapp-web` ✅, `flutter analyze lib` **sans erreur** sur les deux apps Flutter. + +**Lot F** — Stripe Customer Portal (backend + bouton), ratio jetons → questions mesuré, déclenchement proactif, **M3**, miroir de la conversation vocale, `conversationId`, émission des événements vocaux. **L9 n'était pas un chantier** : la « cible Assistant / Persona » du Mode preview est ce que le §5 du Guide IA a livré le 11/08 — un malentendu entre deux documents, pas du travail. + +**Lot J** — table d'agrégats de thèmes, job de regroupement quotidien, interrupteur de collecte par instance (avec son UI), mention d'information dans les **deux** apps visiteur, purge du journal d'audit. **D5** est livré avec eux. + +**Les cinq pièges de la journée, à ne pas re-découvrir :** + +1. ⚠️ **La garde du proactif recommandée par le plan aurait coûté de l'argent.** `_trigger` appelle le LLM **avant** de parler, et le `?.` sur l'orchestrateur avale le cas « aucun mode vocal actif » : un visiteur traversant une zone avec l'app en poche et le vocal éteint consommait des jetons facturés au client pour une phrase que personne n'entend. La garde interroge l'orchestrateur, pas le matériel. +2. ⚠️ **Un écran peut mentir sans erreur.** Sans état d'échec, une visite incomplète restait sur « téléchargement en cours » **indéfiniment** — le compteur n'étant incrémenté qu'en cas de succès, il n'atteignait jamais le total. Le bug d'origine (D5) était le `print` avalé ; celui-là était pire et n'était écrit nulle part. +3. ⚠️ **Le choix de voix du client n'était pas honoré.** Le sélecteur Viva/Marco existait depuis le 07/08 et écrivait `GuideVoiceId` ; l'app visiteur ne lisait jamais ce champ. **Même forme que W1.** Et aucun APK ne parlait avec la voix du produit, `GEMINI_API_KEY` n'étant injectée nulle part — repli **silencieux** sur la voix système. +4. ⚠️ **Trois écrans journalisaient de fausses questions de visiteur** : le mode proactif (son prompt machine) et l'aperçu de conversation (le gestionnaire testant sa personnalité). Le drapeau s'appelle `IsVisitorQuestion`, défaut `true` — un client publié qui ne l'envoie pas continue de journaliser. +5. ⚠️ **Le même code copié trois fois porte sa décision une seule fois.** `_toLangCode` limitait le vocal à FR/NL/EN/DE dans les trois copies, mais ne le **disait** que dans une : les deux autres ressemblaient à un oubli à corriger. Idem pour les trois `AssistantService`, qui coupaient la conversation en morceaux. + +**Ce qui reste, et qui ne s'écrit pas en code** : la relecture juridique du §8 des CGU, les conditions réelles de Google, le DPA séparé, et les traductions relues de la mention visiteurs (FR/NL/EN aujourd'hui, repli anglais assumé). Puis **K6**, **K9**, le **lot H** (tests, dont D0 sur device) et le **lot I**. + **1. Le journal d'audit voyait tout sauf le contenu.** `AuditedTypes.Contains(entry.Entity.GetType())` exigeait l'égalité **exacte** de type, or `Section` est **abstraite** : le type runtime est toujours `SectionMap`, `SectionQuiz`… Aucune des 13 sortes de section n'était journalisée — soit précisément ce que l'écran du 12/08 devait tracer. `Resource`, `Configuration`, `Device`, `User` et `Instance` passaient, eux : ils sont concrets, et **c'est ce qui rendait le trou invisible**. Remplacé par une remontée à la classe de base auditée (`IsInstanceOfType`). > **Tranché : normalisation côté serveur.** `EntityType` porte `Section`, pas `SectionMap`. Trois raisons : le filtre « Section » **déjà présent** dans l'écran se met à rendre des lignes sans toucher `manager-app`, donc sans coordonner deux repos ; élargir le filtre front aurait coûté 13 entrées de liste et 39 clés i18n **et** laissé tout futur sous-type sortir du filtre en silence — la classe de panne exacte qu'on ferme ici ; et le sous-type concret **n'est pas perdu**, le discriminateur TPH est une propriété du modèle, donc sérialisée dans `NewValues` (`"Discriminator": "Article"`). Un test le vérifie — ce n'était pas une supposition. diff --git a/kanban.html b/kanban.html index bbaf9aa..670ffd6 100644 --- a/kanban.html +++ b/kanban.html @@ -446,10 +446,11 @@

MyInfoMate — tableau de chantiers

Vue d'état consolidée depuis DOCS/. Source de vérité : STATUS.md — cette page en est le reflet, pas le remplaçant. Filtrez sur V1 pour ne voir que ce qui reste avant la mise en prod. L'ordre d'exécution, lui, est dans v1-plan.md : ce tableau dit où en est chaque chantier, pas lequel bloque lequel.

+

🎉 Le développement V1 est clos depuis le 13/08. Les lots F et J sont terminés et il ne reste aucun bug ouvert. Ce qui suit est du test (dont le §21 sur device, qui n'a jamais été joué), du juridique (relecture du §8 des CGU, conditions Google, DPA) et de l'infra (secrets, pg_dump, bascule) — plus une ligne de code applicatif à écrire, hors K9 qui est du confort visuel sacrifiable.

Mise à jour · 2026-08-13
- Postgres v3 · pas encore en prod + Dev V1 clos · pas encore en prod