Aller au contenu

PD-295 — Review de spécification (Gate 3)

Auditeur indépendant. Aucune correction proposée. Aucune reformulation. Aucune implémentation.

Documents audités : - PD-295-specification.md - PD-295-tests.md (audit limité aux ambiguïtés/contradictions/non-testabilités/risques, sans verdict de couverture)

Synthèse des écarts

# Type Référence Gravité
1 Contradiction INV-295-07 vs §5.1.4 (reuse_score) Bloquant
2 Contradiction ERR-295-10 vs §5.12 (clé idempotence) Bloquant
3 Non testable CA-295-20 / INV-295-17 (CS-1 baseline non figée) Bloquant
4 Ambiguïté INV-295-09 (nb_domains non défini) Majeur
5 Incohérence Spec↔Tests ST-295-07 vs INV-295-07 Majeur
6 Contradiction INV-295-04 (Ringbearer-only) vs INV-295-05 / CA-295-05 Majeur
7 Non testable CA-295-17, CA-295-18, CA-295-19 Majeur
8 Ambiguïté Q-295-02 / CA-295-13 (cardinalité clarifications B5) Majeur
9 Contradiction Q-295-06 — /morning "optionnel" vs "intégration" Majeur
10 Hypothèse dangereuse §5.12 — scope du lock vs B5 (race read/write) Majeur
11 Ambiguïté §5.7 step 4 — couplage tri par reuse_score ↔ fichier parallèle Majeur
12 Non testable TC-ERR-04 ne couvre qu'--domain (pas --project) Mineur
13 Hypothèse dangereuse §5.12 réconciliation — exécutant non spécifié Mineur
14 Ambiguïté §5.6 — fenêtre d'indexation des clarifications nouvelles Mineur
15 Ambiguïté §5.12 — query_hash non défini comme champ persistant Mineur
16 Risque sécu/conformité Clarifications PO — rétention/anonymisation non définies (Q-295-04) Mineur
17 Hypothèse dangereuse H-295-06 — bloc {{LEARNINGS}} "considéré vide" dans la spec elle-même Mineur

1. Contradiction — Formule reuse_score vs bornes du champ persisté

Type        : Contradiction
Référence   : INV-295-07, §5.1.4 (`data/learnings-scores.jsonl`.`reuse_score`),
              §5.2 (`score_weight_sum=1.00`), CA-295-08, TC-NOM-08
Description : INV-295-07 définit reuse_score = 0.4*nb_injections
              + 0.4*nb_stories_gate8_go_apres_injection
              + 0.2*nb_domains_distincts. Les trois opérandes sont des
              entiers non bornés (§5.1.4 : `nb_injections` 0..1e9,
              `nb_stories_gate8_go_apres_injection` 0..1e9,
              `nb_domains_distincts` 0..1e6). La somme pondérée produit
              donc des valeurs potentiellement >> 1. Or §5.1.4 contraint
              `reuse_score` au domaine `0.00..1.00` ("Comportement si
              invalide : Ligne exclue + log erreur"). Aucune normalisation
              (max-scaling, log, division par référentiel) n'est spécifiée.
              Conséquence directe : pour tout learning ayant ne serait-ce
              que `nb_injections=3`, le score brut dépasse 1 et la ligne
              doit être exclue par sa propre validation de format.
Impact      : (a) la formule contractuelle est mathématiquement
              incompatible avec son propre format de stockage ; (b) les
              seuils de promotion 0.30/0.60 (INV-295-09) deviennent
              incohérents ; (c) TC-NOM-08 ne peut pas passer sans choisir
              implicitement une convention non spécifiée.
Gravité     : Bloquant

2. Contradiction — Clé d'idempotence vs comportement de rejeu différent

Type        : Contradiction
Référence   : ERR-295-10, TC-ERR-10, §5.12 ("Clé `story_id:step:source:query_hash`")
Description : §5.12 définit la clé d'idempotence comme incluant
              `query_hash`. ERR-295-10 et TC-ERR-10 décrivent un cas de
              "rejeu idempotence avec payload différent" devant être
              rejeté en conflit. Or si le payload diffère, son hash
              diffère, donc la clé composée diffère, donc il s'agit d'une
              nouvelle entrée et non d'un rejeu : aucun conflit ne peut
              survenir avec la définition donnée. Le critère de
              déclenchement de ERR-295-10 est inatteignable.
Impact      : Cas d'erreur contractuel non observable. TC-ERR-10 ne peut
              pas être implémenté de manière déterministe.
Gravité     : Bloquant

3. Règle non testable — CS-1 baseline non figée

Type        : Non testable
Référence   : CA-295-20, INV-295-17, Q-295-05, TC-NOM-24
Description : CA-295-20 exige une "amélioration Gate 8 GO v1 vs baseline
              gelée". Q-295-05 reconnaît que la fenêtre baseline avant/
              après B5 n'est pas contractualisée. Sans bornes temporelles
              officielles ni définition de la métrique de comparaison
              (delta absolu, ratio, seuil de significativité), aucun
              verdict binaire reproductible n'est possible. La spec se
              renvoie elle-même à une question ouverte pour un critère
              d'acceptation.
Impact      : Critère d'acceptation non vérifiable en l'état. Le verdict
              Gate 8 sur ce CA est arbitraire.
Gravité     : Bloquant

4. Ambiguïté — nb_domains dans INV-295-09

Type        : Ambiguïté
Référence   : INV-295-09, INV-295-07 (`nb_domains_distincts`), §5.4
Description : INV-295-09 utilise `nb_domains` comme condition de
              promotion (`>=1` puis `>=2`). Le terme n'est défini nulle
              part : s'agit-il du nombre de domaines distincts dans
              lesquels le learning a été injecté, du nombre de domaines
              distincts ayant produit Gate 8 GO après injection, ou du
              nombre de domaines référencés dans `tags[]` ? §5.1.4
              utilise `nb_domains_distincts` sans préciser non plus la
              source. Pour un learning `scope=story` rattaché à un seul
              domaine d'origine, `nb_domains>=1` est trivialement vrai et
              la promotion `story->domain` se réduit à `reuse_score>=0.30`.
Impact      : Règle de promotion non déterministe. TC-NOM-11 ("aux
              frontières de seuil ... domaines contrôlés") ne peut pas
              fixer un jeu de fixtures sans interpréter la définition.
Gravité     : Majeur

5. Incohérence Spec↔Tests — ST-295-07 vs formule reuse_score

Type        : Incohérence Spec↔Tests
Référence   : ST-295-07 (PD-295-tests.md §3 implicite via TC-NOM-11),
              ST-295-07 (PD-295-specification.md §8), INV-295-07
Description : ST-295-07 affirme : "Given un learning story avec
              reuse_score=0.30 et nb_domains=1, When promotion B4, Then
              état devient DOMAIN_ACTIVE." Aucun jeu d'entrées
              (nb_injections, nb_stories_gate8_go, nb_domains_distincts)
              ne permet d'obtenir simultanément reuse_score=0.30 ET
              nb_domains=1 sans choisir une convention de normalisation
              non spécifiée (cf. écart #1). Le test est sous-spécifié.
Impact      : Le test ne peut pas être réalisé sans hypothèse implicite ;
              deux implémentations conformes peuvent diverger sur le
              verdict.
Gravité     : Majeur

6. Contradiction — INV-295-04 conditionne la persistance au mode Ringbearer

Type        : Contradiction
Référence   : INV-295-04 vs INV-295-05, CA-295-04, CA-295-05, TC-NOM-04, TC-NOM-05
Description : INV-295-04 stipule que "en mode Ringbearer" les
              clarifications sont persistées avant reprise. INV-295-05
              (verbatim) et CA-295-04/CA-295-05 ne sont pas conditionnés
              au mode. Statut en mode local : la persistance verbatim
              est-elle obligatoire ou facultative ? Les tests TC-NOM-04
              et TC-NOM-05 reprennent un préambule "step 0 Ringbearer"
              comme s'il était la seule modalité.
Impact      : Soit la spec laisse un trou de couverture pour le mode
              local (B2 inopérante hors Ringbearer), soit l'invariant
              INV-295-04 est mal scopé. La machine d'états des
              clarifications est sous-spécifiée hors Ringbearer.
Gravité     : Majeur

7. Règles non testables — KPIs CS-2/CS-3/CS-4

Type        : Non testable
Référence   : CA-295-17, CA-295-18, CA-295-19, INV-295-17, TC-NOM-21..23
Description : Trois critères d'acceptation reposent sur un horizon
              temporel post-déploiement (2-3 mois, mensuel, "5 premières
              stories post-B5") qui n'est pas vérifiable au moment de la
              recette de PD-295. La spec confirme cet état (Verdict QA
              "testable partiellement") mais maintient ces points dans
              les critères d'acceptation contractuels au lieu de les
              déplacer en KPIs post-livraison ou en jalons de
              vérification différée explicites.
Impact      : Trois CA non vérifiables au moment du Gate 8 nominal de
              PD-295. Risque de fermeture artificielle.
Gravité     : Majeur

8. Ambiguïté — Cardinalité des clarifications injectées en B5

Type        : Ambiguïté
Référence   : Q-295-02, CA-295-13, INV-295-12, TC-NOM-13
Description : INV-295-12 et CA-295-13 figent la cardinalité des
              learnings (5) et de la veille (3) injectés en B5, mais
              laissent celle des clarifications non spécifiée. TC-NOM-13
              ne peut donc vérifier que la présence de la section, pas
              sa borne. La spec elle-même renvoie à Q-295-02 (question
              ouverte) pour un comportement injecté en production.
Impact      : Comportement d'injection non déterministe sur une des
              trois sources. Verdict Gate 8 sur INV-295-12 incomplet.
Gravité     : Majeur

9. Contradiction — /morning optionnel vs intégré

Type        : Contradiction
Référence   : Q-295-06, CA-295-19 implicite, §5.2 (`morning_top_reused=3`),
              §5.7 step 6
Description : §5.7 step 6 et §5.2 fixent une borne `morning_top_reused=3`
              comme paramètre obligatoire (`Min=Max=3`, "Rejet
              exécution"), ce qui suppose une intégration `/morning`
              effective. Q-295-06 reconnaît que le besoin oscille entre
              "optionnel" et "intégration". L'invariant correspondant
              n'existe pas (aucun INV-295-* ne contractualise
              `/morning`).
Impact      : Hauteur d'engagement contractuel indéterminée. Si
              optionnel, `morning_top_reused` ne devrait pas avoir un
              défaut "rejet exécution". Si obligatoire, un invariant
              dédié manque.
Gravité     : Majeur

10. Hypothèse dangereuse — Scope du lock B4 vs lectures B5

Type        : Hypothèse dangereuse
Référence   : §5.12 ("Scope global sur ressources mutables B4"),
              §5.9 (B5 lit learnings + scores), INV-295-18
Description : Le lock contractuel n'est défini que sur les opérations
              mutantes de B4 (`learnings.jsonl`,
              `learnings-archive.jsonl`, index actifs). B5 lit ces
              mêmes ressources en parallèle au step 0. Aucune garantie
              d'isolation lecteur/écrivain (snapshot, lock partagé,
              version stamping) n'est spécifiée. Lecture pendant
              promotion/éviction/réindexation peut produire une
              injection sur un index incohérent ou amputé.
Impact      : Race condition silencieuse côté B5. Aucun observable
              contractuel ne la détecte ; aucun test ne la couvre
              (TC-NOM-17..20 testent uniquement écrivain vs écrivain).
Gravité     : Majeur

11. Ambiguïté — Couplage du tri sur reuse_score parallèle

Type        : Ambiguïté
Référence   : §5.7 step 4, INV-295-06, §5.1.4
Description : INV-295-06 impose que B3 écrive `learnings-scores.jsonl`
              en fichier parallèle SANS modifier `learnings.jsonl`.
              §5.7 step 4 exige un tri secondaire par `reuse_score`
              côté recherche. Le mécanisme de jonction (clé de jointure
              entre une ligne de `learnings.jsonl` et une ligne de
              `learnings-scores.jsonl`) n'est pas spécifié : `story` et
              `gate` (§5.1.4) ne suffisent pas à identifier un learning
              individuel si plusieurs learnings sont produits par la
              même story/gate.
Impact      : Tri secondaire non implémentable de manière déterministe.
              Test TC-NOM-09 sous-spécifié.
Gravité     : Majeur

12. Couverture insuffisante — TC-ERR-04 ne teste qu'un argument manquant

Type        : Incohérence Spec↔Tests
Référence   : INV-295-14, CA-295-06, ERR-295-04, TC-ERR-04, ST-295-04
Description : INV-295-14 exige `--domain` ET `--project`. TC-ERR-04 et
              ST-295-04 ne testent que l'absence de `--domain`. Le cas
              "absence de `--project`" et le cas "les deux absents" ne
              sont pas couverts.
Impact      : L'invariant n'est que partiellement observable.
Gravité     : Mineur

13. Hypothèse dangereuse — Exécutant de la réconciliation non spécifié

Type        : Hypothèse dangereuse
Référence   : §5.12 ("Réconciliation : Intervalle 5 min"), TC-NOM-20
Description : Le mécanisme de déclenchement périodique de la
              réconciliation (cron, daemon, hook step 0, job manuel)
              n'est pas spécifié. La spec présume l'existence d'un
              ordonnanceur externe sans le contractualiser. TC-NOM-20
              dépend donc d'un composant non couvert par PD-295.
Impact      : INV-295-18 partiellement reposé sur une infrastructure
              hors périmètre. Risque d'illusion de couverture.
Gravité     : Mineur

14. Ambiguïté — Indexation incrémentale des clarifications

Type        : Ambiguïté
Référence   : §5.6 step 4, INV-295-15, ERR-295-05
Description : §5.6 dit "Indexer le corpus clarifications" sans préciser
              si l'indexation est continue, batch (déclenchée par
              `reindex-all`), ou hookée step 0. Entre deux exécutions
              de `reindex-all`, les nouvelles clarifications produites
              par d'autres stories ne sont pas interrogeables. La spec
              n'expose pas explicitement cette latence.
Impact      : Comportement temporel des recherches B5 non déterministe.
Gravité     : Mineur

15. Ambiguïté — query_hash non défini comme champ

Type        : Ambiguïté
Référence   : §5.12 ("Clé `story_id:step:source:query_hash`"), §5.1.6
Description : `query_hash` est utilisé comme composant de clé
              d'idempotence mais n'apparaît pas dans le schéma de
              `learnings-injections.jsonl` (§5.1.6 ne liste que `query`
              brut, 1..500 UTF-8). L'algorithme de hash (SHA-256,
              FNV...), sa normalisation pré-hash (lowercase, NFKC,
              trim) et son lieu de persistance ne sont pas spécifiés.
Impact      : Vérification d'idempotence non reproductible.
Gravité     : Mineur

16. Risque sécu/conformité — Rétention et anonymisation des clarifications

Type        : Risque sécu/conformité
Référence   : Q-295-04, INV-295-05 (verbatim), §5.6
Description : La spec impose la persistance verbatim de réponses PO et
              l'indexation cross-projets, mais reconnaît (Q-295-04) que
              la durée de conservation et l'anonymisation ne sont pas
              définies. Verbatim cross-projet sans politique de
              rétention expose à un risque RGPD si une réponse PO
              contient une donnée personnelle ou un secret.
Impact      : Trou de conformité documentaire. Aucun cas d'erreur
              contractuel ne couvre la suppression sur demande.
Gravité     : Mineur

17. Hypothèse dangereuse — Auto-relativisation de la spec

Type        : Hypothèse dangereuse
Référence   : H-295-06 ("Le bloc {{LEARNINGS}} contextuel n'est pas
              injecté ... considéré vide")
Description : La spec contractuelle déclare elle-même comme hypothèse
              que son propre mécanisme de contexte historique est
              désactivé pour la story qui le définit. Ce n'est pas une
              hypothèse fonctionnelle sur l'environnement cible mais un
              aveu méta sur la rédaction du document. Sa place dans
              §9 (hypothèses fonctionnelles) introduit une confusion
              entre cadrage produit et conditions de rédaction.
Impact      : Lisibilité contractuelle dégradée ; risque que le
              relecteur considère que l'absence de learnings injectés
              au step 0 est admise en run.
Gravité     : Mineur

Cohérence des diagrammes (axe 5bis)

Diagramme d'état (§5bis)

Les transitions du diagramme correspondent intégralement à §5.4 et à INV-295-09 / INV-295-10 / INV-295-11. Les transitions interdites sont toutes représentées explicitement avec leur libellé "INTERDITE". Aucun écart détecté sur cet axe.

Diagramme de séquence (§5bis)

Les trois sources (learning, veille, clarification) sont tracées en parallèle avec leurs filtres et leurs traces. Format des vecteurs explicite (vector[768]). Un point reste implicite : la jonction learnings.jsonllearnings-scores.jsonl (cf. écart #11) n'apparaît ni sur le diagramme ni dans le pseudo-code (tri(distance,reuse_score) est posé comme primitive sans clé de jointure). Ce point est déjà remonté en écart Majeur au §11 ci-dessus, le diagramme reflète fidèlement la spec sans introduire d'incohérence supplémentaire.


Verdict de revue

Spécification globalement structurée et testable, mais comportant 3 écarts Bloquants (formule reuse_score incompatible avec son propre format de stockage, clé d'idempotence rendant ERR-295-10 inatteignable, CA-295-20 non testable par renvoi à une question ouverte) qui empêchent en l'état la production d'une implémentation déterministe et l'émission d'un verdict Gate 8 reproductible.

Les écarts Majeurs (8) portent essentiellement sur des trous de définition (nb_domains, cardinalité clarifications B5, scope du lock B4 vs lectures B5, jonction de tri sur fichier parallèle) et sur des CA dont l'horizon temporel sort du périmètre de recette de PD-295 (CS-2/CS-3/CS-4).