diff --git a/CLAUDE.md b/CLAUDE.md index 48b7e59..f15d98f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,5 +68,6 @@ pnpm + Turborepo. `apps/api` : NestJS, Prisma, PostgreSQL (pgvector + PostGIS), - 🏁 **R5 CLOSE (17/07/2026, tag `release/r5`)** : recettĂ©e par le rĂ©fĂ©rent (revue pixel + arbitrage tableau), recette passĂ©e SANS clĂ© API, durcissement rĂ©pĂ©tĂ© en local conteneurisĂ©. **R0 → R5 : pĂ©rimĂštre v1 couvert.** - ✅ **Recette terrain mobile sur iPhone 15 Pro — 7/7 validĂ©s (19/07, ADR-005)** : Expo Go bloquĂ© par le retard d'approbation Apple (SDK 54 vs notre SDK 57) → **dĂ©cision : builds natifs locaux (Xcode/Android Studio, signature gratuite) pour la vraie recette, Expo Go conservĂ© pour l'aperçu sans installation**. 5 obstacles techniques rĂ©els corrigĂ©s et documentĂ©s (UDID plutĂŽt que nom, ne jamais contourner `expo run:*` par un xcodebuild manuel, modules Expo/RN prĂ©compilĂ©s SDK 56/57 incompatibles avec la liaison statique du projet, `fetch` global incompatible avec l'upload multipart natif — fix permanent `EXPO_PUBLIC_USE_RN_FETCH=1` dans `apps/mobile/.env`, dĂ©couverte rĂ©seau du dev client peu fiable). Recette iOS : connexion, scan camĂ©ra rĂ©el (rĂ©solution + rejet QR Ă©tranger), vrai mode avion, conflit D2 tranchĂ© par l'humain avec photo rĂ©ellement tĂ©lĂ©versĂ©e, persistance Ă  travers fermeture/reconstruction de l'app, suggestions R5 au vrai modĂšle, purge de sĂ©curitĂ© au changement de compte — tout validĂ©. Android : build natif sur Ă©mulateur, passage santĂ© complet. - ✅ **DictĂ©e implĂ©mentĂ©e (22/07, ADR-004 §5)** : Ă©cran Voix R5 (jamais construit) — `faster-whisper` local (CTranslate2, CPU, opt-in `AI_TRANSCRIPTION=off|locale`, dĂ©faut off), audio jamais persistĂ© (purge serveur ET mobile quoi qu'il arrive), transcription → relecture humaine → suggestion immĂ©diate et/ou sauvegarde dans `InterventionReport.note` (champ existant depuis R2, jamais eu d'Ă©cran jusqu'ici) → `note` rejoint le corpus Ă  la clĂŽture comme les bilans codĂ©s. Mobile : `expo-audio`/`expo-file-system`, bouton dicter sur l'Ă©cran de clĂŽture. Docker `siop2-ai` embarque le modĂšle (1,54→2,19 Go). VĂ©rifiĂ© rĂ©ellement (voix de synthĂšse → texte fidĂšle, bout en bout API, conteneur Docker construit, chaĂźne corpus complĂšte note→clĂŽture→rĂ©indexation→recherche). 80 tests API, 29 pytest ai, mobile vert. -- 🔄 **Reprise ici** : test tactile de la dictĂ©e sur iPhone (bloquĂ© par une connexion USB qui ne s'est pas rĂ©tablie malgrĂ© cĂąble/port/redĂ©marrage — reportĂ© comme la recette Android). RedĂ©ploiement Dokploy de l'instance ENSET (`AI_SERVICE_TOKEN` Ă  crĂ©er — runbook §2 — puis « RĂ©indexer tout »). Restes : recette Android sur appareil physique, calibrage `AI_SEUIL_*` et qualitĂ© darija sur corpus SPELEV rĂ©el, secret `DOKPLOY_WEBHOOK_URL`, production client SPELEV (attend les accĂšs serveur du partenaire). +- ✅ **DictĂ©e validĂ©e sur iPhone physique (01/08, ADR-004 §5)** : le blocage USB du 22/07 Ă©tait un faux nĂ©gatif de `system_profiler` (outil de diagnostic en panne, pas le cĂąble). Deux bugs rĂ©els trouvĂ©s et corrigĂ©s : `expo-audio` iOS exige `setAudioModeAsync({ allowsRecording: true })` avant `record()` (absent, jamais dĂ©tectĂ© hors appareil rĂ©el) ; le correctif des modules prĂ©compilĂ©s (ADR-005) n'avait jamais Ă©tĂ© rendu permanent dans `apps/mobile/.env` — corrigĂ©. ChaĂźne complĂšte vĂ©rifiĂ©e en vrai : micro → dictĂ©e → transcription fidĂšle → note → clĂŽture → rĂ©indexation → **retrouvĂ© par la recherche sĂ©mantique**. +- 🔄 **Reprise ici** : redĂ©ploiement Dokploy de l'instance ENSET (`AI_SERVICE_TOKEN` Ă  crĂ©er — runbook §2 — puis « RĂ©indexer tout »). Restes : recette Android sur appareil physique, calibrage `AI_SEUIL_*` et qualitĂ© darija sur corpus SPELEV rĂ©el, secret `DOKPLOY_WEBHOOK_URL`, production client SPELEV (attend les accĂšs serveur du partenaire). - DĂ©tail quotidien : `docs/journal/journal.md`. DĂ©pĂŽt : `siop-spelev/siop2` (privĂ©), jalons R0→R5. diff --git a/apps/mobile/.env b/apps/mobile/.env index 3a29651..d8c48fd 100644 --- a/apps/mobile/.env +++ b/apps/mobile/.env @@ -6,3 +6,11 @@ # boucle de retry silencieuse — trouvĂ© en recette terrain iOS (17/07/2026). # Voir ADR-005 et docs/journal/journal.md. EXPO_PUBLIC_USE_RN_FETCH=1 + +# Modules Expo/RN prĂ©compilĂ©s (XCFrameworks, SDK 56/57) incompatibles avec la +# liaison statique de ce projet (pas de use_frameworks!) : sans ce rĂ©glage, +# l'app compile mais CRASHE au lancement +# (dyld: Library not loaded: @rpath/React.framework/React, signal 6). +# Force la recompilation depuis les sources — voir ADR-005. +EXPO_USE_PRECOMPILED_MODULES=0 +RCT_USE_PREBUILT_RNCORE=0 diff --git a/apps/mobile/app/ot/[id]/cloture.tsx b/apps/mobile/app/ot/[id]/cloture.tsx index a3a97e3..d808638 100644 --- a/apps/mobile/app/ot/[id]/cloture.tsx +++ b/apps/mobile/app/ot/[id]/cloture.tsx @@ -2,7 +2,12 @@ import * as FileSystem from 'expo-file-system'; import { router, useLocalSearchParams } from 'expo-router'; import { useState } from 'react'; import { Pressable, ScrollView, Text, TextInput, View } from 'react-native'; -import { RecordingPresets, requestRecordingPermissionsAsync, useAudioRecorder } from 'expo-audio'; +import { + RecordingPresets, + requestRecordingPermissionsAsync, + setAudioModeAsync, + useAudioRecorder, +} from 'expo-audio'; import { SafeAreaView } from 'react-native-safe-area-context'; import { BILAN_FIELD_LABELS, @@ -197,6 +202,9 @@ function CarteSuggestion({ const demarrerDictee = async () => { const { granted } = await requestRecordingPermissionsAsync(); if (!granted) return; + // iOS refuse recorder.record() tant que la session audio n'a pas Ă©tĂ© + // explicitement autorisĂ©e Ă  enregistrer (RecordingDisabledException). + await setAudioModeAsync({ allowsRecording: true, playsInSilentMode: true }); await recorder.prepareToRecordAsync(); recorder.record(); setEnregistrement(true); @@ -205,6 +213,7 @@ function CarteSuggestion({ const terminerDictee = async () => { await recorder.stop(); + await setAudioModeAsync({ allowsRecording: false }); // n'arme le micro que le temps de dicter setEnregistrement(false); const uri = recorder.uri; if (!uri) return; diff --git a/docs/03-architecture/adr/ADR-004-modeles-ia.md b/docs/03-architecture/adr/ADR-004-modeles-ia.md index 48d90c5..7e97644 100644 --- a/docs/03-architecture/adr/ADR-004-modeles-ia.md +++ b/docs/03-architecture/adr/ADR-004-modeles-ia.md @@ -80,6 +80,18 @@ - ImplĂ©mentĂ©e et vĂ©rifiĂ©e le 22/07/2026 : transcription rĂ©elle (français, voix de synthĂšse) juste et rapide en local, bout en bout via l'API NestJS, et dans l'image Docker de production construite pour l'occasion (modĂšle embarquĂ©, aucun tĂ©lĂ©chargement - au dĂ©marrage). **Reste** : le test tactile sur iPhone physique (bouton dicter, permission - micro) n'a pas pu se jouer — blocage USB persistant malgrĂ© cĂąble/port/redĂ©marrage - multiples, reportĂ© comme la recette Android (attend un accĂšs matĂ©riel qui fonctionne). + au dĂ©marrage). Le test tactile sur iPhone physique n'avait pas pu se jouer ce jour-lĂ  + (blocage USB), reportĂ©. +- **Recette terrain sur iPhone physique complĂ©tĂ©e le 01/08/2026** : micro, dictĂ©e rĂ©elle, + transcription fidĂšle, sauvegarde dans le bilan, clĂŽture, puis retrouvĂ©e par la recherche + sĂ©mantique aprĂšs rĂ©indexation — la chaĂźne complĂšte (D5) est validĂ©e sur vrai matĂ©riel. + Deux bugs rĂ©els trouvĂ©s et corrigĂ©s en route : + 1. `expo-audio` sur iOS refuse `recorder.record()` tant que la session audio n'a pas + Ă©tĂ© explicitement autorisĂ©e Ă  enregistrer — `RecordingDisabledException`, corrigĂ©e + par un appel Ă  `setAudioModeAsync({ allowsRecording: true })` avant l'enregistrement + (et remis Ă  `false` aprĂšs, par hygiĂšne — le micro ne reste pas « armĂ© »). + 2. Le contournement des modules Expo/RN prĂ©compilĂ©s (`EXPO_USE_PRECOMPILED_MODULES=0`, + `RCT_USE_PREBUILT_RNCORE=0` — ADR-005) n'avait **jamais Ă©tĂ© rendu permanent** dans + `apps/mobile/.env`, contrairement au correctif FormData voisin : une reconstruction + ultĂ©rieure sans ces variables aurait reproduit le crash au lancement dĂ©jĂ  documentĂ©. + DĂ©sormais committĂ© aux cĂŽtĂ©s de `EXPO_PUBLIC_USE_RN_FETCH`. diff --git a/docs/journal/journal.md b/docs/journal/journal.md index 310e09e..4874d3c 100644 --- a/docs/journal/journal.md +++ b/docs/journal/journal.md @@ -4,6 +4,39 @@ Trace chronologique des sessions (la plus rĂ©cente en premier). Le **playbook** --- +## 2026-08-01 — Pr. Daaif (+ Claude) — DictĂ©e validĂ©e sur iPhone physique (ADR-004 §5) + +**Actions** + +- Reprise du reste laissĂ© le 22/07 : le test tactile de la dictĂ©e sur iPhone, alors bloquĂ© par une connexion + USB qui ne se rĂ©tablissait pas. Diagnostic cette fois : `system_profiler` (l'outil utilisĂ© pour vĂ©rifier la + dĂ©tection USB) Ă©tait lui-mĂȘme en panne et renvoyait un faux nĂ©gatif silencieux — `ioreg` a rĂ©vĂ©lĂ© que + l'iPhone Ă©tait en rĂ©alitĂ© dĂ©tectĂ©. Le vrai cĂąble/port n'a jamais Ă©tĂ© le problĂšme. +- Une fois l'app reconstruite (certificat gratuit expirĂ© aprĂšs plus d'une semaine — rĂ©gĂ©nĂ©rĂ© via le pipeline + officiel `expo run:ios`, jamais par un contournement manuel), **deux bugs rĂ©els trouvĂ©s et corrigĂ©s** : + 1. `expo-audio` sur iOS refuse d'enregistrer sans un appel explicite Ă  `setAudioModeAsync({ allowsRecording: + true })` avant `recorder.record()` — absent du code initial, jamais dĂ©tectĂ© hors d'un vrai appareil. + 2. Le correctif des modules Expo/RN prĂ©compilĂ©s (ADR-005, `EXPO_USE_PRECOMPILED_MODULES=0` / + `RCT_USE_PREBUILT_RNCORE=0`) n'avait **jamais Ă©tĂ© committĂ©** dans `apps/mobile/.env`, contrairement au + correctif FormData voisin dĂ©jĂ  permanent — un vrai trou qui aurait refait planter l'app Ă  la prochaine + reconstruction depuis zĂ©ro. CorrigĂ© : les deux variables vivent maintenant cĂŽte Ă  cĂŽte dans `.env`. +- **Recette rĂ©elle bout en bout** : micro → dictĂ©e d'une phrase → transcription fidĂšle (`faster-whisper` rĂ©el) + → relecture → sauvegarde dans le bilan → clĂŽture de l'OT → rĂ©indexation du corpus → **le contenu dictĂ© + retrouvĂ© par la recherche sĂ©mantique** (score 0,476). La boucle complĂšte de l'idĂ©e d'origine (« cette + transcription devrait alimenter le corpus ») est validĂ©e sur vrai matĂ©riel, vraie voix, vrai rĂ©seau. +- Infra locale relancĂ©e depuis zĂ©ro aprĂšs une semaine d'inactivitĂ© (Docker, conteneurs `siop2-*`, API, + service IA) — occasion de vĂ©rifier que le redĂ©marrage Ă  froid fonctionne proprement. + +**DĂ©cisions** + +- Aucune — cette session referme un reste dĂ©jĂ  dĂ©cidĂ©, sans nouvelle dĂ©cision de conception. + +**Prochaine Ă©tape** : recette Android sur appareil physique (toujours en attente d'un appareil) ; redĂ©ploiement +Dokploy (`AI_SERVICE_TOKEN`) ; calibrage `AI_SEUIL_*` et qualitĂ© darija sur corpus SPELEV rĂ©el ; secret +`DOKPLOY_WEBHOOK_URL`. + +--- + ## 2026-07-22 — Pr. Daaif (+ Claude) — DictĂ©e implĂ©mentĂ©e : audio → transcription locale → corpus (ADR-004 §5) **Actions**