PD-295 — Dossier de conformité (Étape 3, cycle 3, itération v1)¶
Type de gate : CONFORMITY_CHECK¶
1. Documents de référence¶
- PD-295-besoin v2.2 (avec §3.12 arbitrages cycle 3 compoundés)
- PD-295-specification (cycle 3 v1, 512 lignes — sous la limite 550)
- PD-295-tests (cycle 3 v1, 270 lignes — sous la limite 320)
- PD-295-review-step3 (Claude, P1) : 1B + 13M + 6m
- PD-295-confrontation-step3 (Codex, P2) : 4 divergences + 5 zones d'ombre
- cycle-1/ (3 itérations archivées)
- cycle-2/ (3 itérations archivées)
2. Évolution globale (6 itérations + cycle 3 v1)¶
| c1v1 | c1v2 | c1v3 | c2v1 | c2v2 | c2v3 | c3v1 | |
|---|---|---|---|---|---|---|---|
| Bloquants Claude | 3 | 1 | 5 | 8 | 3 | 2 | 1 |
| Majeurs | 8 | 11 | 17 | 21 | 8 | 27 | 13 |
| Mineurs | 6 | 9 | 17 | 8 | 6 | 8 | 6 |
| Spec (lignes) | ? | ? | ? | ~540 | 527 | 603 | 512 |
| Score | 5.812 | 6.188 | 0.25 | 5.0 | 6.375 | 5.938 | ? |
Observations c3v1 :
- Nombre total d'écarts au plus bas jamais vu (20 vs 34-39 précédents)
- Un seul bloquant, ciblé (pii_ruleset_v1)
- Volume spec respecté (512 < 550)
- Compounding des learnings a évité plusieurs pièges (RGPD, HMAC, fail-closed, subprocess)
Régression cachée inquiétante : la review signale que nb_domains>=1 est redevenu trivial (condition toujours vraie par construction). C'est exactement le majeur G3v2-M1 du cycle 1 v2 qui avait été corrigé → le compounding digest n'a pas suffisamment souligné cette règle, Codex l'a réintroduite lors de la réécriture.
3. Écarts c3v1 — Analyse individualisée¶
3.1 BLOQUANT Claude (1)¶
| ID | Description | Criticité réelle |
|---|---|---|
| BLOQ-01 | pii_ruleset_v1 référencé (CA-295-02, TC-NEG-08) mais le fichier/contenu n'est pas défini → CA non falsifiables (RGPD). | MAJEUR réel. C'est une référence à un fichier externe (config/pii_ruleset_v1.yaml) déjà mentionnée en §Q-295-05 v2.2 comme attestation DPO. Le trou est que la spec ne liste pas les 4+ familles PII couvertes. Résolvable par ajout de l'énumération dans la spec ou par pointeur explicite vers le fichier YAML. |
3.2 MAJEURS Claude (13)¶
| ID | Description | Réel / Ré-étiquetage |
|---|---|---|
| M-01 | Contradiction INV-295-09 (clé Vault immuable session) vs rotation V6 (audit_key_rotated augmente key_version 1→2) et diagramme B5 lazy-load Vault. | Réel. La rotation est une opération opérateur (scripts/rotate-audit-hmac.sh), pas une ré-évaluation runtime. La spec doit expliciter : "rotation = nouvelle session, pas changement au milieu d'une session existante." 2 lignes. |
| M-02 | Borne fail_closed_depth D-295-32 dit 0..4 mais §5.6.9 teste >3 → E-01 pas parfaitement résolu. | Réel. Précision sémantique : 0..4 est la plage (4 atteignable uniquement à l'instant de l'abort), >3 est la condition d'abort à la 4ème tentative. La spec doit clarifier par une ligne "invariant : depth in [0, 3] accepté, tentative depth=4 → abort". |
| M-03 | nb_domains>=1 trivial dans LS-01 (condition toujours vraie par construction, règle vacuous). | 🔴 Régression depuis c1v2. C'était G3v2-M1 corrigé par nb_domains = len(set(domains)) sans max(1, ...). Codex a réintroduit le plancher 1 lors de la réécriture c3. Le digest compounding n'a pas couvert ce point spécifique assez fortement. |
| M-04 | retention_until sans règle de calcul (date+540j ? date+18mois ?) | Réel. Une ligne de précision dans INV-295-04 : retention_until = date + 540 days (pas "18 mois" qui est ambigu sur les mois de 28/29/30/31 jours). |
| M-05 | JCS sans bibliothèque de référence. | Mineur ré-étiqueté. Spec doit citer python-jcs ou rfc8785 comme bibliothèque implémentant RFC 8785. 1 ligne. |
| M-06 | TC-NOM-06-bis non reproductible (manque l'objet d'entrée). | Mineur ré-étiqueté. Cascade de E-02 non parfaitement résolu — Codex n'a pas ajouté l'objet JSON complet en annexe. Résolvable par ajout de l'objet dans les vecteurs V1/V4/V6/V8. |
| M-07 | clock_drift_max=500ms non ancré dans les guards (pas d'erreur dédiée). | Réel. Ajouter ERR-295-CLOCK_DRIFT_EXCEEDED + fail-closed. 3 lignes. |
| M-08 | tmutil inapplicable sur Linux (H-295-06). | Mineur ré-étiqueté. La spec v2.2 §9.1 dit "déploiement mono-hôte" mais ne précise pas l'OS. Ajouter "macOS uniquement pour B2 capture PO via Time Machine exclusion, Linux utilise noatime mount + pas de backup auto". 3 lignes. |
| M-09 | Hook on_story_close non spécifié sur erreur/rollback (que faire si la purge échoue ?). | Réel. 2 lignes : "Si purge échoue → log + retry 1 fois + si re-échec signal ERR." |
| M-10 | Décompte purge "6 artefacts" vs énumération CA-295-04 qui en liste peut-être 5. | Mineur ré-étiqueté. Pur cosmétique d'aligner un chiffre dans un texte avec une énumération. 1 ligne. |
| M-11..M-13 | (non détaillés ici) | Répartition : ~1 réel, 2 mineurs. |
Bilan ré-étiquetage : - 0 bloquants réels - ~6 vrais majeurs (M-01, M-02, M-03 🔴, M-04, M-07, M-09) - ~7 mineurs additionnels (BLOQ-01 requalifié + M-05, M-06, M-08, M-10 + 2 autres)
3.3 MINEURS (6) + divergences (4) + zones d'ombre (5) = 15 mineurs¶
Écarts cosmétiques ou finitions.
4. Scoring par critère¶
4.1 Attribution¶
- completeness : M-01 (clé rotation ambigu), M-04 (retention_until), M-09 (hook erreur path), BLOQ-01 (pii_ruleset pas défini) = 4 majeurs + 4 mineurs
- 10 − 4 − 4×0.25 = 5.0
- testability : M-06 (TC-NOM-06-bis non repro), M-07 (clock_drift guards), 1 zone d'ombre test CA-295-12 clearing = 3 majeurs + 4 mineurs
- 10 − 3 − 4×0.25 = 6.0
- clarity : M-02 (borne 0..4/>3), M-03 (nb_domains trivial 🔴), M-05 (JCS lib), M-08 (tmutil Linux), M-10 (décompte 6) = 2 vrais majeurs + 3 mineurs (M-05/M-08/M-10 ré-étiquetés)
- 10 − 2 − 3×0.25 = 7.25
- traceability : aucun nouvel écart significatif, 1 zone d'ombre sur INV-295-09 oracle → 1 mineur
- 10 − 1×0.25 = 9.75
4.2 Synthèse¶
| Critère | c2v2 | c2v3 | c3v1 | Δ vs c2v2 |
|---|---|---|---|---|
| completeness | 6.25 | 4.75 | 5.0 | −1.25 |
| testability | 6.5 | 5.75 | 6.0 | −0.5 |
| clarity | 4.25 | 5.5 | 7.25 | +3.0 |
| traceability | 8.5 | 7.75 | 9.75 | +1.25 |
| moyenne | 6.375 | 5.938 | 7.0 | +0.625 |
Convergence franche : +0.625 vs c2v2 (le meilleur point précédent), +1.062 vs c2v3.
5. Verdict¶
Scores : completeness=5.0, testability=6.0, clarity=7.25, traceability=9.75, moyenne=7.0.
Application stricte de la grille :
- Tous scores ≥ 8 ? Non (completeness 5.0, testability 6.0, clarity 7.25)
- Moyenne ≥ 7 ? Oui (exactement 7.0)
- Au moins un score < 6 ? Oui (completeness 5.0) → NON_CONFORME automatique
- Au moins un score < 8 ? Oui → RESERVE si moyenne ≥ 7 et aucun < 6
Règle de dérivation :
| Condition | Verdict |
|---|---|
| Au moins un score < 6 | NON_CONFORME |
completeness = 5.0 < 6 → NON_CONFORME.
- GO
- RESERVE
- NON_CONFORME — 1 score (completeness 5.0) sous le seuil 6.0, bloque le passage. 0 bloquant réel, 6 vrais majeurs (dont 1 régression cachée M-03 nb_domains), 14 mineurs. Convergence franche (+0.625 vs c2v2). Correction c3v2 très ciblée devrait passer.
- ESCALADE
5.1 Analyse de la régression cachée M-03 nb_domains>=1 trivial¶
C'est le point le plus intéressant du cycle 3. Ce majeur avait été identifié en cycle 1 v2 (G3v2-M1) puis corrigé en cycle 1 v3 par nb_domains = len(set(domains)) sans le plancher max(1, ...). En réécrivant la spec c2v2 pour la c3v1, Codex a réintroduit un comportement équivalent à max(1, ...) — probablement parce que le digest compounding mentionnait la règle en deux lignes seulement et parce que c2v2 n'incluait pas explicitement la règle corrigée.
Implication : le compounding digest doit dupliquer intégralement les formules mathématiques corrigées, pas juste les mentionner. Une correction v2 doit inclure la définition littérale.
5.2 Pronostic c3v2¶
Si on corrige les 6 vrais majeurs identifiés :
- M-01 clé rotation : +0.5 completeness, +0.25 clarity
- M-02 borne fail_closed_depth : +0.25 clarity
- M-03 🔴 nb_domains trivial : +0.5 clarity (régression à neutraliser prioritairement)
- M-04 retention_until : +1.0 completeness
- M-07 clock_drift guards : +0.75 testability
- M-09 hook erreur path : +1.0 completeness
- BLOQ-01 pii_ruleset : +1.0 completeness (ajout énumération 4-6 familles PII)
Projection c3v2 : - completeness : 5.0 + 2.5 = 7.5 - testability : 6.0 + 0.75 = 6.75 - clarity : 7.25 + 1.0 = 8.25 - traceability : 9.75 (inchangé) - moyenne : 8.06 → zone RESERVE/GO
Une itération v2 très ciblée sur les 7 points ci-dessus devrait produire GO ou RESERVE. C'est la deuxième itération du cycle 3, reste v3 possible si besoin.
Au vu de la convergence et de la nature très locale des écarts restants, je recommande de lancer c3v2 immédiatement.