PD-86 — Rapport de confrontation (Gate 8 — CLOSURE)¶
Ce rapport est produit par l'orchestrateur Claude avant la gate PMO 8. Il confronte les documents produits pour identifier convergences, divergences et zones d'ombre.
1. Sources confrontées¶
| # | Document | Étape d'origine | Version |
|---|---|---|---|
| S1 | PD-86-specification.md | Étape 1 (Spécification) | 2.0.0 |
| S2 | PD-86-tests.md | Étape 2 (Tests & Validation) | — |
| S3 | PD-86-plan.md (Plan) | Étape 4 (Plan d'implémentation) | 1.0.0 |
| S4 | PD-86-acceptability.md | Étape 7 (Acceptabilité) | — |
| S5 | PD-86-agent-agent-developer-types-config.md | Étape 6b (Livrable agent) | — |
2. Convergences¶
2.1 Modèle de données et types¶
- CONV-01 : Les 4 catégories whitelistées (
VIOLENCE,NUDITE,SEXUEL,CHOQUANT) sont identiques dans S1 (§3.2), S2 (TC-86-14), S3 (C1 types.ts, §3 INV-86-04) et S5 (types.ts:12). Enforcement compile-time confirmé par S5 viaas const. - CONV-02 : Les 7 valeurs de
analysisStatus(SUCCESS,TIMEOUT,MODEL_UNAVAILABLE,UNSUPPORTED_FORMAT,CORRUPTED_INPUT,OUT_OF_MEMORY,INTERNAL_ERROR) sont cohérentes entre S1 (§3.2), S3 (§6) et S5 (types.ts:27, 7 valeurs confirmées). - CONV-03 : Le modèle de données local (entités
SensitiveDetectionSettings,DocumentSensitiveVerdict,DocumentSensitivePreference,ViewerGateDecision) est fidèlement transposé de S1 (§3.1) vers S3 (§1 composants C1/C10) et S5 (interfaces TypeScript). Champs identiques. - CONV-04 : Unicité
(documentId, modelVersion): spécifiée en S1 (§3.1), testée en S2 (TC-86-31, TC-86-32), implémentée par mutex + écriture idempotente en S3 (C15 DetectionService), confirmée fonctionnelle par S4 (187/187 tests).
2.2 Invariants et règles métier¶
- CONV-05 : Les 20 invariants (INV-86-01 à INV-86-20) sont intégralement couverts par au moins un test dans S2 (§1.1 matrice couverture : 20/20), mappés à des mécanismes dans S3 (§3 : 20/20 lignes), et les tests correspondants passent selon S4 (187/187 OK).
- CONV-06 : Les 19 critères d'acceptation (CA-86-01 à CA-86-19) sont intégralement couverts en S2 (§1.2 : 19/19), mappés dans S3 (§4 : 19/19), et validés en S4.
- CONV-07 : La règle de précédence du gate viewer (6 règles ordonnées) est identique entre S1 (§5.2), S3 (§2.1 flux nominal, étape 6), et couverte par les tests S2 (TC-86-10, TC-86-08/09, TC-86-01/02/03, TC-86-27, TC-86-11, TC-86-21, TC-86-29).
- CONV-08 : Politique prudente prime sur
suppressWarning: S1 (INV-86-09), S2 (TC-86-08/09/18/19/20/26), S3 (§6 règle transverse #3), S4 (corrections R-03/S-01 appliquées).
2.3 Échantillonnage et performance¶
- CONV-09 : Vidéo = 12 frames, stratégie uniforme + 2 premières secondes, agrégation
max(score): S1 (Q3, Q4), S2 (TC-86-02, TC-86-24), S3 (§2.2, C7/C12). - CONV-10 : PDF = max 5 pages, première + dernière + 3 intérieures uniformes, déterministe : S1 (Q8), S2 (TC-86-26), S3 (§2.3, C8/C12).
- CONV-11 : Timeout inférence 5000 ms : S1 (Q7, §4.2), S2 (TC-86-08), S3 (§6 TIMEOUT, C2 config.ts), S5 (config
INFERENCE_TIMEOUT_MS = 5000). - CONV-12 : Budget P95 ≤ 700 ms sur iPhone 12 (A14, iOS 16+) : S1 (§8), S2 (TC-86-23, PERF-86-01), S3 (§1 C2).
2.4 Sécurité¶
- CONV-13 : Architecture zero-knowledge stricte (zéro réseau) : S1 (INV-86-01, §7), S2 (TC-86-04, SEC-86-01), S3 (C21 NetworkGuard, §7), S4 (aucune faille réseau signalée).
- CONV-14 : Zeroization best-effort via
try/finally: S1 (INV-86-10, §7), S2 (TC-86-16, SEC-86-04), S3 (C14 BufferZeroizer), S5 (confirmé pattern existantSecureBuffer.destroy()). - CONV-15 : Logging whitelist/blacklist stricte : S1 (§7), S2 (TC-86-15, SEC-86-05), S3 (C19 DetectionLogger), S5 (impact mineur
readonly Category[]corrigé dans S4). - CONV-16 : Interdiction de fichiers temporaires média en clair : S1 (INV-86-11), S2 (TC-86-07, TC-86-25, SEC-86-03), S3 (C6-C8 pipeline mémoire, C14).
2.5 Gestion des mineurs¶
- CONV-17 :
isMinor=true→suppressWarningignoré + confirmation additionnelle obligatoire : S1 (INV-86-06, INV-86-16), S2 (TC-86-13, TC-86-27), S3 (ViewerGate R4, MinorConfirmation C18). - CONV-18 : Seuils mineur plafonnés aux défauts (pas de relaxation) : S1 (INV-86-17, Q5), S2 (TC-86-28, TC-86-30), S3 (C13 ThresholdEvaluator clamp).
- CONV-19 : Stub
isMinor=falsepar défaut (PD-84 non encore livré) : S3 (§Phase 0), S4 (ECT-01 documenté, TODO tracé).
2.6 Corrections et acceptabilité¶
- CONV-20 : Les écarts Gate 3 (ECT-v2-01 à ECT-v2-11) identifiés lors de la spécification/review ont tous été adressés dans S3 (§9 "Écarts Gate 3 adressés" : 11/11 lignes avec section de plan référencée).
- CONV-21 : Les corrections post-review LLM (R-02 boucle infinie context, R-03/S-01 showContent stale) sont documentées dans S4 (commit
f1d6e55), avec 0 régression (1667/1668 tests passent, 1 skip pré-existant).
3. Divergences¶
DIV-01 — Cache chiffré : spécification vs implémentation réelle¶
- Source S1 (INV-86-08) : "Le cache local des verdicts est chiffré" — invariant NON NÉGOCIABLE.
- Source S3 (§7) : "Persistance via
expo-secure-storepour clé de chiffrement +AsyncStoragechiffré AES-256-GCM pour données". - Source S4 (ECT-04, R-01, S-02) : "AsyncStorage non chiffré (INV-86-08)" — classé MINEUR, "sandboxing iOS protège", "TODO tracé pour SecureStore".
- Source S5 : Aucune mention du chiffrement au niveau type.
- Conflit : Le plan (S3) affirme que le cache est chiffré AES-256-GCM. L'acceptabilité (S4) constate que l'implémentation utilise AsyncStorage en clair avec un TODO pour SecureStore. L'invariant INV-86-08 est donc non satisfait en l'état.
- Impact : Écart direct avec un invariant de spécification. La mitigation "sandboxing iOS protège" est une mesure de compensation, pas une conformité. Gate 8 doit statuer sur l'acceptabilité de cet écart résiduel.
DIV-02 — Sonar Quality Gate non exécuté¶
- Source S4 (Phase 1.5) : "Quality Gate : NON EXÉCUTÉE — Token Sonar non disponible dans Vault (path
kv/data/ci/sonarvide)". - Source CLAUDE.md (règle constitutionnelle) : "Scan Sonar local BLOQUANT [...] Si Sonar QG ERROR → STOP avant reviews LLM".
- Conflit : Le processus de gouvernance définit Sonar Phase 1.5 comme BLOQUANT. L'acceptabilité l'a classé "SKIP (non bloquant — validation différée au pipeline)". Ce skip contrevient à la règle issue des rétrospectives PD-55, PD-107, PD-31, PD-44, PD-82, PD-248.
- Impact : Risque de découvrir des écarts Sonar post-Gate 8, ce qui a été la cause de corrections tardives sur 6+ stories précédentes. L'acceptabilité a été produite sans la couche de validation Sonar.
DIV-03 — Review Tests QA qualifiée de "partielle"¶
- Source S4 (Review Tests) : "Review QA partielle (OpenCode n'a pas traité le code inliné correctement). Couverture TC vérifiée manuellement : 34/34 scénarios implémentés."
- Source S4 (T-01, T-03) : Deux écarts classés "FAUX POSITIF" car le reviewer LLM n'a pas vu le code.
- Source S2 : 34 scénarios TC + 7 SEC + 5 PERF + 6 ERR + 8 UX.
- Conflit : La review QA LLM n'a pas effectivement analysé le code de test. La vérification manuelle "34/34 scénarios implémentés" est affirmée mais non traçable par un tiers. L'un des objectifs de la validation croisée (Article II constitutionnel — séparation des pouvoirs) est compromis si la review LLM est inopérante.
- Impact : La couverture TC est déclarée complète mais la review croisée n'a pas réellement eu lieu sur le volet tests.
DIV-04 — rawScores dans la blacklist de logging vs stocké en cache¶
- Source S3 (§7 Journalisation) : "
rawScores(scores bruts = data sensible potentielle)" est listé dans la blacklist de logging. - Source S1 (§3.1) :
DocumentSensitiveVerdictcontientrawScores: Map<Category, Float>— stocké en cache. - Source S1 (§7 Logging whitelist) : La whitelist autorisée ne mentionne pas
rawScores. La blacklist ne mentionne pasrawScoresexplicitement non plus. - Source S3 : Le plan ajoute
rawScoresà la blacklist de logging (absente de la spec). - Conflit : Le plan (S3) est plus restrictif que la spécification (S1) concernant
rawScoresdans les logs. C'est une divergence conservatrice (le plan est plus sûr que la spec), pas un relâchement. Pas de conflit fonctionnel mais écart documentaire à noter. - Impact : Faible — approche conservatrice acceptable. Clarification possible en mettant à jour la blacklist dans la spec.
DIV-05 — Confirmation additionnelle mineur sur erreurs : spec vs plan¶
- Source S1 (INV-86-06) : "Pour mineur, l'action 'Afficher quand même' nécessite confirmation explicite additionnelle." — Contexte : contenu sensible détecté.
- Source S1 (§5.2) :
requiresExplicitConfirmation = isMinor && isSensitive. - Source S3 (§6 règle transverse #7) :
requiresExplicitConfirmation = isMinor && (isSensitive || isErrorStatus)— extension aux cas d'erreur. - Conflit : Le plan étend la confirmation mineur aux cas d'erreur (
TIMEOUT,MODEL_UNAVAILABLE, etc.), ce qui n'est pas explicitement requis par la spécification. La spec ne demande la double confirmation que pourisSensitive=true. - Impact : Divergence conservatrice (plus protecteur pour les mineurs). Fonctionnellement, le plan est plus restrictif que la spec. Cette extension est documentée comme adressant l'écart ECT-v2-02 de Gate 3.
DIV-06 — Nombre de tests : cahier vs exécution¶
- Source S2 : 34 TC fonctionnels + 7 SEC + 5 PERF + 6 ERR + 8 UX = potentiellement 60 scénarios.
- Source S4 : "17/17 suites PD-86, 187/187 tests passent".
- Conflit apparent : Les 187 tests unitaires/intégration couvrent les 34 TC principaux et les complètent par des cas internes (edge cases, sous-fonctions). Les suites SEC, PERF, ERR, UX sont des vues thématiques qui recoupent les TC (pas des tests additionnels indépendants). Pas de conflit réel, mais la traçabilité TC → test unitaire n'est pas documentée individuellement dans S4.
- Impact : Faible — les 34 TC sont déclarés implémentés. La traçabilité fine TC→test est dans le code, pas dans le rapport d'acceptabilité.
4. Zones d'ombre¶
ZO-01 — Modèle ML concret : choix toujours reporté¶
- Source S1 (Q1) : "Décision d'implémentation. Exigence contractuelle : modèle hors ligne avec benchmark documenté (précision/latence/taille) avant mise en production."
- Source S3 (H-01, H-02, H-03) : "Choix reporté après benchmark", hypothèses documentées.
- Source S4 (ECT-02) : "MockClassifier en production (H-01) — OnnxClassifier prêt mais modèle ML non intégré".
- Question : Le
MockClassifierest en production dans la branche. L'interfaceContentClassifierabstraite existe mais aucun modèle réel n'a été benchmarké. Gate 8 doit statuer : leMockClassifierest-il acceptable comme livrable PD-86, avec le modèle ML réel comme story séparée ?
ZO-02 — Extraction vidéo native : stub total¶
- Source S3 (H-04) : "L'extraction de frames vidéo in-memory est possible via un module React Native natif sans écriture disque" — hypothèse non validée.
- Source S4 (ECT-03) : "Extraction vidéo native (H-04) — FFmpeg/AVFoundation requis, simulation acceptable pour MVP".
- Question : Le flux vidéo (TC-86-02, TC-86-24) est testé avec un mock d'extraction. La détection vidéo ne fonctionne pas avec de vraies vidéos en l'état. Gate 8 doit statuer sur l'acceptabilité de ce stub pour le scope PD-86.
ZO-03 — Tests de performance sur device réel : non exécutés¶
- Source S2 (TC-86-23, PERF-86-01) : "iPhone 12 (A14, iOS 16+) ; N=30 exécutions".
- Source S4 : Aucune mention de tests de performance sur device réel. Les 187 tests sont Jest (en CI/local), pas sur device.
- Question : Le budget P95 ≤ 700 ms n'a pas été validé sur device réel. Ceci est attendu (les tests device relèvent du benchmark post-merge), mais Gate 8 doit le noter comme validation différée.
ZO-04 — Mécanismes iOS spécifiques (App Switcher, Spotlight, QuickLook) : non testés¶
- Source S1 (§7, §10) : "Contrôle des mécanismes iOS pouvant générer des aperçus persistants non maîtrisés".
- Source S2 (SEC-86-07) : "Aucun snapshot/indexation/preview non maîtrisé".
- Source S3 (C20 iOSPrivacyGuard) : Composant planifié.
- Source S4 : Aucune mention explicite de
iOSPrivacyGuarddans les résultats de test ou de review. - Question : Le composant C20 est-il implémenté et testé ? L'acceptabilité ne le mentionne ni en réussite ni en écart. Zone non couverte par le rapport.
ZO-05 — Politique TTL/purge 90 jours : implémentée ?¶
- Source S3 (§7) : "TTL par défaut : 90 jours après
analyzedAt(configurable)", "Purge au déverrouillage". - Source S4 : Aucune mention de TTL ou purge dans les résultats de test ou les corrections.
- Question : La politique TTL/purge (adressant ECT-v2-05 de Gate 3) est-elle implémentée et testée, ou reste-t-elle à l'état de plan ?
ZO-06 — thresholdsVersion dans le verdict : incrémentation et cohérence¶
- Source S1 (§3.1) :
SensitiveDetectionSettingscontientthresholdsVersion: Int. - Source S1 (§3.1) :
DocumentSensitiveVerdictcontientthresholdsVersionAtDecision: Int. - Source S3 (§2.5) : "Incrémentation thresholdsVersion" à chaque changement de seuils.
- Source S5 :
thresholdsVersionest dans l'interfaceSensitiveDetectionSettings(confirmé). - Question : Le mécanisme d'incrémentation automatique de
thresholdsVersionest décrit dans le plan mais aucun test spécifique ne vérifie que la version s'incrémente correctement (S2 teste la réévaluation TC-86-30, pas l'incrémentation elle-même). Point mineur mais non couvert.
5. Synthèse quantitative¶
| Catégorie | Nombre |
|---|---|
| Convergences confirmées | 21 |
| Divergences identifiées | 6 (dont 2 conservatrices, 1 traçabilité, 1 invariant non satisfait, 1 process, 1 review partielle) |
| Zones d'ombre | 6 |
Classification des divergences par gravité¶
| ID | Gravité | Nature |
|---|---|---|
| DIV-01 | MAJEUR | INV-86-08 (cache chiffré) non satisfait — invariant de spécification |
| DIV-02 | MAJEUR | Sonar BLOQUANT contourné — règle constitutionnelle process |
| DIV-03 | MOYEN | Review QA inopérante — séparation des pouvoirs compromise |
| DIV-04 | MINEUR | rawScores dans blacklist log — conservatif |
| DIV-05 | MINEUR | Confirmation mineur étendue aux erreurs — conservatif |
| DIV-06 | MINEUR | Traçabilité TC→test unitaire absente du rapport |
6. Recommandation¶
- Procéder — convergence confirmée, aucun conflit bloquant
- Rework nécessaire — divergences à résoudre avant de continuer
- Escalade — décision humaine requise sur un point structurant
Justification :
-
DIV-01 (INV-86-08 cache chiffré) : Un invariant de spécification est explicitement non satisfait. L'acceptabilité le reconnaît (ECT-04) mais le classe MINEUR alors que la spec le déclare comme invariant. Gate 8 doit statuer : soit accepter l'écart avec une story de remédiation tracée, soit exiger la correction avant verdict GO.
-
DIV-02 (Sonar BLOQUANT skip) : Le processus de gouvernance (issu de 6+ rétrospectives) impose Sonar Phase 1.5 comme bloquant. Le contournement crée un précédent. Gate 8 doit statuer sur l'acceptabilité de la validation différée au pipeline CI/CD.
-
ZO-01/ZO-02 : Le MockClassifier et le stub vidéo constituent des livrables partiels. Gate 8 doit statuer sur le périmètre réellement livré vs le périmètre spécifié.
Les 21 convergences attestent d'une cohérence forte entre spécification, tests, plan et implémentation sur le plan fonctionnel et sécuritaire. Les divergences restantes portent principalement sur des écarts d'implémentation (chiffrement, stubs) et de process (Sonar), pas sur des incohérences entre documents.