PD-86 — Rapport de confrontation (Etape 5)¶
Ce rapport est produit par l'orchestrateur Claude avant la gate PMO 5 (AMBIGUITY). Il confronte la specification, les tests et le plan d'implementation + code contracts pour identifier convergences, divergences et zones d'ombre.
1. Sources confrontees¶
PD-86-specification.md(Etape 1 — v2.0.0, 2026-02-24)PD-86-tests.md(Etape 2 — TC-86-01 a TC-86-34, SEC/PERF/ERR/UX)PD-86-plan.md(Etape 4 — v1.0.0, 2026-02-24)PD-86-code-contracts.yaml(Etape 4 — v1.0.0, 2026-02-24)- Contexte : verdict Gate 3 v2 = RESERVE (7.75/10), ecarts ECT-v2-01 a ECT-v2-11 identifies
2. Convergences¶
2.1 Architecture locale-only et zero-knowledge¶
Spec (INV-86-01, CA-86-04, S7), tests (TC-86-04, TC-86-18/19/20, SEC-86-01) et plan (C21 NetworkGuard, architecture offline-only, mapping INV-86-01) sont strictement alignes sur l'interdiction de toute transmission reseau de contenu, scores ou metadonnees d'analyse. Le code contract classification-engine renforce en interdisant tout import fetch/axios/XMLHttpRequest. Le plan va au-dela avec NetworkGuard actif en dev/test — approche conservatrice coherente.
2.2 Detection uniquement au viewer¶
Spec (INV-86-02), tests (TC-86-17) et plan (C22, hook useSensitiveDetection exclusivement dans MediaPreviewScreen) sont alignes. Aucune ambiguite.
2.3 Integrite probatoire¶
Spec (INV-86-03, CA-86-05), tests (TC-86-05) et plan (C14 BufferZeroizer, pipeline in-memory) convergent : le fichier source n'est jamais modifie, hash probatoire inchange. Le code contract classification-engine interdit toute ecriture sur le filesystem.
2.4 Whitelist des categories¶
Spec (INV-86-04 : VIOLENCE | NUDITE | SEXUEL | CHOQUANT), tests (TC-86-14), plan (C1 types.ts, C13 ThresholdEvaluator) et code contract types-config sont parfaitement alignes. Enforcement compile-time via union litterale TypeScript.
2.5 Gate de consentement (image, video, PDF)¶
Spec (INV-86-05, CA-86-01/02/03), tests (TC-86-01/02/03) et plan (C16 ViewerGate R3, C17 ViewerGateModal) convergent : modal obligatoire avant tout rendu si status=SUCCESS && isSensitive=true.
2.6 Politique prudente sur erreurs¶
Les 6 codes d'erreur (spec S9, INV-86-09), les 6 tests (TC-86-08/09/18/19/20 + ERR-86-01..06) et le plan (C16 ViewerGate R2, S6 DetectionService) sont alignes. Le plan documente explicitement les messages UI par code d'erreur — coherent avec la spec.
2.7 Cache local chiffre, sans derives visuels¶
Spec (INV-86-07, INV-86-08, CA-86-06), tests (TC-86-06, SEC-86-02/03) et plan (C10/C11, AES-256-GCM) convergent. Le code contract store-cache renforce avec interdiction explicite de tout stockage de pixels/frames/thumbnails/embeddings/OCR.
2.8 Idempotence et serialisation concurrente¶
Spec (INV-86-19, CA-86-17), tests (TC-86-31/32) et plan (C15 DetectionService, mutex par (documentId, modelVersion)) sont alignes. L'unicite de persistance et l'idempotence d'ecriture sont couvertes.
2.9 Regles mineur (confirmation, suppressWarning, seuils)¶
Spec (INV-86-06/16/17, CA-86-14/15), tests (TC-86-13/27/28/30) et plan (C16 R4, C18 MinorConfirmation, C13 clamp) convergent sur les trois axes mineur : confirmation additionnelle, suppressWarning ignore, seuils plafonnes aux defauts. Exception : voir DIV-01.
2.10 Sampling video et PDF¶
Spec (Q3/Q4/Q8), tests (TC-86-02/24/25/26, PERF-86-04/05) et plan (C7/C8/C12 SamplingStrategy) convergent : 12 frames video (uniforme + 2 premieres secondes, agregation max), 5 pages PDF max (premiere + derniere + 3 interieures uniformes), rendu memoire uniquement.
2.11 Zeroization best-effort¶
Spec (INV-86-10, CA-86-13), tests (TC-86-16, SEC-86-04) et plan (C14 BufferZeroizer try/finally) convergent. Le plan documente la limitation runtime JS/GC comme dette technique — coherent avec le signalement ST-86-01 des tests.
2.12 Logs whitelist/blacklist¶
Spec (INV-86-12, S7), tests (TC-86-15, SEC-86-05) et plan (C19 DetectionLogger) convergent sur la whitelist exacte de champs autorisables. Le code contract security reproduit fidelement la whitelist spec.
2.13 Invalidation par modelVersion¶
Spec (INV-86-13, CA-86-12), tests (TC-86-12) et plan (C11 verdictCache.get() compare modelVersion) sont alignes.
2.14 Desactivation globale¶
Spec (INV-86-14/18, CA-86-10/19), tests (TC-86-10/29) et plan (C22 court-circuit, C16 R1) convergent. Le plan adresse explicitement ECT-v2-01 de Gate 3 : enabled=false = skip complet, y compris pour verdicts sensibles en cache.
2.15 Reevaluation seuils sans re-inference¶
Spec (INV-86-20, CA-86-16), tests (TC-86-30) et plan (C13 ThresholdEvaluator.reevaluate) convergent. Le chemin negatif (rawScores absents -> reclassification) est couvert dans le plan (S2.5 etape c) — adresse la zone d'ombre signalee en Gate 3.
2.16 Warm-up moteur¶
Spec (Q9, S8), tests (TC-86-22, PERF-86-02) et plan (C9 EngineWarmup) convergent : warm-up a l'ouverture du coffre, lazy fallback au premier document.
2.17 Checklist INV/CA complete¶
Le plan (S12) fournit un mapping complet 20/20 INV et 19/19 CA vers taches et tests. Aucune ligne vide. La matrice de tests (S1.1, S1.2) couvre 20/20 INV et 19/19 CA. Convergence confirmee.
2.18 Ecarts Gate 3 adresses¶
Le plan (S9 "Ecarts Gate 3 adresses") documente les 11 ecarts ECT-v2 identifies lors de la confrontation Gate 3 et indique pour chacun le mecanisme d'adressage. C'est un point de convergence notable entre le plan et les attentes formulees en Gate 3.
3. Divergences¶
Les conflits ne doivent JAMAIS etre lisses. Chaque divergence est rendue visible.
- DIV-01 : Extension de la formule
requiresExplicitConfirmationau-dela de la spec. - Source A (Spec S5.2, regle explicite) :
requiresExplicitConfirmation = isMinor && isSensitive - Source B (Plan S3 INV-86-06, S6 regle transverse #7) :
requiresExplicitConfirmation = isMinor && (isSensitive || isErrorStatus) - Constat : Le plan etend la formule pour couvrir aussi les modals prudents en cas d'erreur pour les mineurs. C'est un comportement additionnel non specifie.
-
Impact : Ecart contractuel — le plan introduit une protection supplementaire non tracee dans la spec. Si cette extension est souhaitee, la spec doit etre mise a jour pour acter ce comportement. Sinon, l'implementation ne doit pas l'inclure.
-
DIV-02 : Politique TTL 90 jours absente de la spec.
- Source A (Spec) : Aucune mention de TTL ou de politique de purge du cache de verdicts. Le cache est decrit comme "local minimal" (INV-86-08) et chiffre, mais sans duree de vie.
- Source B (Plan S7) : Introduit une politique TTL de 90 jours par defaut avec purge au deverrouillage du coffre, en reponse a ECT-v2-05 de Gate 3.
- Constat : Le plan ajoute un mecanisme de lifecycle non specifie. La spec ne contredit pas cette politique mais ne la mandate pas non plus.
-
Impact : Si le TTL est contractuel, il doit apparaitre dans la spec comme invariant ou contrainte explicite. Sinon, c'est un detail d'implementation acceptable — mais non testable contractuellement.
-
DIV-03 :
rawScoresdans la blacklist logging du plan mais pas de la spec. - Source A (Spec S7, whitelist logging) : Liste des champs autorises inclut
rawScoresimplicitement via CA-86-06 qui autoriserawScoresdans le cache. La whitelist de logging ne mentionne pas explicitementrawScoresdans les champs autorises, mais ne les interdit pas explicitement non plus. - Source B (Plan S7 Journalisation, blacklist) : Le plan ajoute explicitement
rawScoresa la blacklist des logs : "rawScores (scores bruts = data sensible potentielle)". - Source C (Code contract
security) : La whitelist INV-86-12 reproduite dans le code contract n'inclut pasrawScoresdans les champs autorises. - Constat : La spec autorise
rawScoresdans le cache (CA-86-06) mais sa whitelist de logging (INV-86-12) les omet silencieusement. Le plan prend la position conservatrice d'interdire leur logging. Pas de contradiction stricte, mais un durcissement non contractualise. -
Impact : Mineur. Le durcissement est defense-in-depth. Si les
rawScoress'averent necessaires au debugging, il faudrait mettre a jour la spec pour clarifier leur statut de loggabilite. -
DIV-04 : Invariants supplementaires dans les code contracts non traces en spec.
- Source A (Spec) : 20 invariants INV-86-01 a INV-86-20.
- Source B (Code contracts) : Ajoutent des invariants hors spec, notamment :
classification-engine: "Le classifieur est stateless — aucune persistance interne"store-cache: "Politique TTL: 90 jours par defaut, purge au deverrouillage du coffre"sampling-strategy: "Aucune source d'aleatoire (Math.random, crypto.random) — determinisme strict"media-analyzers: "Warm-up declenche a l'ouverture du coffre, lazy fallback au premier document"
- Constat : Ces invariants sont coherents avec l'esprit de la spec mais ne sont pas traces dans le referentiel contractuel (INV-86-XX).
-
Impact : Moyen. L'ajout d'invariants non traces dilue la frontiere entre exigences contractuelles et decisions d'implementation. Les invariants supplementaires devraient etre distingues (ex: IMPL-86-XX) ou integres a la spec si contractuels.
-
DIV-05 : Niveau de test TC-86-05 — "Unit" dans le plan vs nature du test.
- Source A (Tests TC-86-05) : "Verifier que l'analyse ne modifie jamais le fichier original" — necessite ouverture, analyse, puis verification hash.
- Source B (Plan S5) : Classifie TC-86-05 comme "Unit".
- Constat : Un test qui ouvre un document, execute une analyse complete puis verifie l'integrite hash est plus proche d'un test d'integration que d'un test unitaire.
-
Impact : Mineur — erreur de classification du niveau de test, pas de consequence fonctionnelle.
-
DIV-06 : Stub
isMinorretournefalse— incompatibilite avec TC-86-34. - Source A (Tests TC-86-34) : "Verifier que
isMinorprovient du profil authentifie serveur et ne peut pas etre override localement." - Source B (Plan Phase 0) : "
isMinorstub retournefalsepar defaut. TODO(PD-84)." - Constat : TC-86-34 est non demonstrable tant que PD-84 n'est pas livre. Le plan documente le stub mais ne propose pas de mecanisme de verification partielle.
-
Impact : BLOQUANT pour la demonstration de conformite TC-86-34. Le plan doit preciser comment ce test sera gere : report explicite a post-PD-84, ou mock authentifie simulant le flag serveur.
-
DIV-07 : Spec iOS natif (Swift/SwiftUI) vs Plan React Native Expo.
- Source A (Spec S10) : "Domaine : iOS (Swift/SwiftUI), traitement visuel local hors ligne."
- Source B (Plan, Metadata + S1) : "Projet : ProbatioVault-app (iOS / React Native Expo)". Architecture en TypeScript/React Native avec native modules pour ONNX, PDF et video.
- Constat : La spec mentionne explicitement "Swift/SwiftUI" comme stack technique. Le plan utilise React Native Expo avec des bridges natifs. Le reste du projet (
ProbatioVault-app) est effectivement en React Native Expo — le plan est coherent avec la realite du projet, pas la spec. - Impact : MAJEUR — La spec doit etre corrigee pour referer "React Native Expo (avec bridges natifs Swift si necessaire)" au lieu de "Swift/SwiftUI". Cet ecart pourrait induire le reviewer de Gate 5 en erreur sur la stack attendue.
4. Zones d'ombre¶
-
ZO-01 : Absence de test pour la frontiere contractuelle
InMemoryHandle64 MB. Le plan (S6 OUT_OF_MEMORY, ECT-v2-10) documente le guard, mais aucun TC dedie ne verifie que le seuil 64 MB est respecte et que le comportementOUT_OF_MEMORYse declenche exactement a cette limite. Les tests couvrentOUT_OF_MEMORY(ERR-86-06) mais pas la valeur seuil. -
ZO-02 : Benchmark modele ML absente du plan de test. La spec (Q1) exige un "benchmark documente (precision/latence/taille) avant mise en production". Le plan (H-01/H-03/H-09) documente cette exigence comme hypothese, mais aucun test ne verifie que le benchmark a ete effectue et documente. Le plan dit "benchmark obligatoire avant Gate 8" — sans protocole de verification.
-
ZO-03 : Algorithme PDF pour cas limites
totalPagesproches de 5. La spec (Q8) decrit la strategie de deduplication et "completion par la page interieure non selectionnee la plus proche si necessaire". Le plan (S2.3) reprend l'algorithme aux quartiles. Aucun test ne couvre specifiquement les castotalPages = 5,totalPages = 6(frontiere exacte), ou le mecanisme de completion en cas de collision de quartiles. -
ZO-04 : Controles iOS anti-apercus persistants (App Switcher, Spotlight, QuickLook). Le plan (C20
iOSPrivacyGuard) et le code contract (security) documentent les mecanismes. SEC-86-07 les liste. Mais aucun TC detaille pas-a-pas ne decrit comment verifier l'overlay de redaction, l'exclusion Spotlight ou la desactivation QuickLook. Cette zone d'ombre etait deja signalee en Gate 3 (confrontation v2). Le plan (ECT-v2-04) dit "tests unitaires individuels" mais les tests ne les ajoutent pas. -
ZO-05 : Comportement exact en cas de combinaison
enabled=false+ erreur persistee en cache. La spec (S5.2 R1) indique queenabled=false= pas de modal, rendu direct. Le plan l'adresse (ECT-v2-01). Mais aucun TC ne couvre explicitement le cas ou un verdict d'erreur (ex:TIMEOUT) est en cache ETenabled=false: le viewer rend-il directement sans modal ? La logique de precedence R1 > R2 l'implique mais n'est pas testee explicitement. -
ZO-06 : Strategie de migration si le modele ML change entre versions de l'app (ex: v1.0 avec modele A, v2.0 avec modele B). La spec (INV-86-13, CA-86-12) couvre l'invalidation par
modelVersion. Le plan gere le changement. Mais aucun document ne couvre le scenario de mise a jour de l'app ou tous les verdicts cache sont invalides simultanement — impact performance potentiel (re-classification en masse au premier usage post-update). -
ZO-07 : Format exact de
thresholdsVersion(entier incrementant) et demodelVersion(string). La spec definitthresholdsVersion: IntetmodelVersion: Stringdans le modele de donnees. Le plan reprend. Mais aucun document ne precise le format demodelVersion(semver ? hash ? nom+version ?) ni commentthresholdsVersionest incremente (automatique au save ? gestion de conflit entre settings concurrent ?).
5. Recommandation¶
- Proceder — convergence confirmee, aucun conflit bloquant
- Rework necessaire — divergences a resoudre avant de continuer
- Escalade — decision humaine requise sur un point structurant
Justification : Les convergences sont solides (17 points de convergence confirmes, mapping INV/CA complet 20/20 + 19/19). Cependant, 7 divergences sont identifiees dont : - 1 BLOQUANT (DIV-06 : TC-86-34 non demonstrable avec stub isMinor) - 1 MAJEUR (DIV-07 : spec dit Swift/SwiftUI, plan dit React Native Expo) - 1 MAJEUR (DIV-01 : extension non contractualisee de requiresExplicitConfirmation) - 4 MINEURS (DIV-02 TTL non specifie, DIV-03 rawScores blacklist, DIV-04 invariants supplementaires, DIV-05 niveau test)
Les zones d'ombre ZO-01 a ZO-07 ne sont pas bloquantes mais meritent clarification pour eviter des ecarts en Gate 8.