Aller au contenu

Reading prompt from stdin... OpenAI Codex v0.117.0 (research preview)


workdir: /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance model: gpt-5.3-codex provider: openai approval: never sandbox: read-only reasoning effort: xhigh reasoning summaries: none session id: 019d4119-4cc6-79e2-9b06-6e86b32c6571


user

8/ Revue d’acceptabilité (post-correction)

🎭 Rôle

Tu es auditeur technique indépendant.Tu n’es ni l’auteur de la spécification, ni l’implémenteur.Tu analyses un document d’acceptabilité contractuel existant.

🎯 Objectif de la revue

Effectuer une revue d’acceptabilité post-correction, afin de :

  • vérifier si les écarts précédemment identifiés sont désormais résolus,
  • mettre à jour leur statut si et seulement si c’est justifié,
  • faire évoluer le verdict courant, sans jamais modifier l’historique.

📜 Règles impératives (non négociables)

  1. NE PAS modifier :
    • les écarts initiaux,
    • les descriptions historiques,
    • les verdicts passés.
  2. NE PAS ajouter :
    • de nouveaux écarts,
    • de nouvelles règles,
    • de nouvelles exigences.
  3. NE PAS améliorer :
    • la spécification,
    • l’implémentation,
    • le document lui-même.
  4. TU PEUX UNIQUEMENT :
    • mettre à jour le statut d’écarts existants,
    • ajouter une entrée datée append-only dans le suivi,
    • mettre à jour le verdict courant, si justifié.

📥 Entrées fournies (obligatoires)

  • 📄 Spécification de référence : PD-293-specification.md
  • 🧪 Tests contractuels de référence : PD-293-tests.md
  • 📄 Document d’acceptabilité existant : PD-293-acceptability.md
  • 📄 Template revue d’acceptabilité : ProbatioVault-doc/docs/meta/templates/PD-293-acceptability-review.md
  • 🧩 Contexte d’implémentation actuel :
  • code source tel qu’existant,
  • corrections récemment apportées,
  • résultats d’exécution des tests contractuels.
    ⛔ Si PD-293-tests.md est absent ou si les résultats d’exécution ne sont pas fournis :→ aucun écart ne peut être marqué comme RÉSOLU.

🔍 Méthode d’analyse attendue

Pour chaque écart existant dans le document d’acceptabilité :

  1. Vérifie si la correction annoncée :
    • est effectivement présente dans le code,
    • respecte strictement la spécification,
    • est prouvée par l’exécution des tests contractuels concernés,
    • ne viole aucun invariant.
  2. Classe l’écart dans un des statuts suivants uniquement :

    • OUVERT
    • PARTIELLEMENT RÉSOLU
    • RÉSOLU
    • NON RÉSOLU
      ⚠️ Règle stricte
  3. Un écart ne peut être RÉSOLU que si tous les TC-* concernés PASSENT.

  4. Sinon → PARTIELLEMENT RÉSOLU ou NON RÉSOLU.

  5. Justifie toute évolution de statut par :

    • un fait observable,
    • un élément vérifiable :
      • commit,
      • fichier,
      • test contractuel (TC-*) exécuté.

🧾 Sortie attendue (format strict)

1️⃣ Mise à jour du suivi des écarts (append-only)

Pour chaque écart concerné, produire uniquement une entrée du type :

### [YYYY-MM-DD] — Suivi E-XX

- Statut précédent : <statut>
- Statut actuel : <statut>
- Justification factuelle :
  - …
- Preuve de vérification :
  - commit / fichier / test TC-XX (PASS)

⚠️ Ne pas réécrire l’écart initial⚠️ Ne pas supprimer d’entrées existantes

2️⃣ Verdict d’acceptabilité (courant)

Mettre à jour uniquement cette section, si nécessaire :

## Verdict d’acceptabilité (courant)

Verdict actuel : <⛔ REFUSÉ | ⚠️ ACCEPTÉ AVEC RÉSERVES | ✅ ACCEPTÉ>
Date : <YYYY-MM-DD>
Motif synthétique : <1–2 lignes max>

3️⃣ Historique des verdicts

  • NE PAS modifier l’historique existant
  • ➕ Ajouter une ligne uniquement si le verdict change
    Si l’historique n’existait pas :
  • créer une première ligne avec le verdict initial.
Date Verdict Version / commit Commentaire
YYYY-MM-DD

🚫 Strictement interdit

  • reformuler la spec,
  • proposer une solution,
  • suggérer une amélioration future,
  • ajouter un nouvel écart,
  • effacer ou “oublier” un écart existant.

🧠 Principe fondamental

L’acceptabilité est un registre de décision probatoire.Elle évolue par statuts et preuves, jamais par réécriture.

📌 Artefact produit (à générer dans le Canvas)

➡️ PD-293-acceptability-review.md 📂 Chemin de destination : {PROJET}/docs/epics/{DOMAINE}/{PD-293-nom}/PD-293-acceptability-review.md

  

⚙️ Notes contextuelles par domaine

Domaine crypto-proof (conformité formelle Prolog)

ATTENTION : Les stories du domaine crypto-proof portent sur la conformité formelle vérifiée par des checks Prolog déterministes (SWI-Prolog run_audit.). Dans ce contexte :

  • Les « codes d'erreur » et « mécanismes de détection » dans l'acceptabilité sont des conventions de la norme Prolog, pas des features du code applicatif.
  • La « preuve » est le résultat du run Prolog (24-27 checks OK/KO), pas des tests unitaires Jest/Vitest.
  • Les modifications de code sont minimales (alias, normalisation, détection de patterns) — ne pas attendre une couverture de tests classique.
  • Un écart sur « l'absence de tests unitaires » n'est PAS pertinent si le run Prolog complet est la preuve déterministe.
  • Les erreurs TypeScript pré-existantes dans d'autres fichiers ne sont PAS imputables à la story courante.

Si le domaine de la story n'est PAS crypto-proof, ignorer cette note.

📚 Learnings contextuels (patterns de closure)

||

{{LEARNINGS}}

DOCUMENT D'ENTRÉE : SPECIFICATION

PD-293 — Orchestration contractuelle multi-stories “One Ring” via claude-peers et controle mobile (v2 corrigee)

1. Objectif

La User Story PD-293 permet a un Sovereign (humain) de piloter, depuis une session unique (One Ring), jusqu'a 5 Ringbearers executant chacun un workflow /gov PD-XXX [projet], avec :

  • supervision consolidee des stories,
  • remontee et traitement des escalades bloquantes,
  • pilotage a distance via /remote-control (iPhone/Safari),
  • separation stricte des responsabilites (One Ring route, Ringbearers executent).

2. Perimetre / Hors perimetre

Inclus

  • Orchestration multi-stories par une session One Ring unique.
  • Commandes /gov-lord : start, status, stop, escalade, respond, pause, resume.
  • Protocole de messagerie Ringbearer ↔ One Ring (types, validation, routage, dedoublonnage).
  • Detection de disparition/crash d'un Ringbearer et signalement au Sovereign.
  • Affichage consolide de l'etat de N stories.
  • Controle mobile du One Ring via /remote-control.
  • Persistance locale d'un etat consolide minimal .gov-lord-state.json.

Exclu

  • Toute modification du workflow /gov existant.
  • Toute execution metier/projet par le One Ring (lecture code, ecriture fichier, build, tests, Jira, GitLab, Vault).
  • Communication directe Ringbearer ↔ Ringbearer.
  • Application iOS native dediee.
  • Mutualisation/partage de credentials entre sessions.
  • Etat ESCALADE_EXPIRED en v1 (hors perimetre, evolution future).

3. Definitions

Terme Definition
Sovereign Humain decisionnaire final (PO/Architecte).
One Ring Session d'orchestration unique, strictement interface/routeur.
Ringbearer Session autonome dediee a une story, executant /gov.
Story Identifiant de workflow valide selon regex normative ^PD-[0-9]{1,4}$.
Broker Service claude-peers-mcp local assurant enregistrement/listing/messagerie des peers.
Escalade Demande bloquante d'un Ringbearer necessitant reponse humaine.
File d'escalades Queue FIFO des escalades ouvertes (multi-escalade simultanee).
Etat Ringbearer Etat contractuel du cycle de vie d'une story orchestree par One Ring.

4. Invariants (non negociables)

ID Regle Justification
INV-293-01 One Ring n'execute aucune action hors interface/routage ; toute demande hors scope est refusee avec message explicite. Separation des pouvoirs, securite, tracabilite.
INV-293-02 One Ring ne communique avec les stories qu'au travers du broker/peers ; aucune action directe sur les repos cibles. Confinement operationnel.
INV-293-03 Un Ringbearer est isole (contexte, credentials, execution) ; aucune contamination inter-story. Non-regression et robustesse.
INV-293-04 Maximum 5 Ringbearers actifs simultanes. Au-dela : rejet explicite. Limite de capacite declaree.
INV-293-05 Tout message doit etre valide selon le modele §5.1 ; sinon rejet deterministe et journalisation d'erreur au format contractuel §6.1. Contrat protocolaire testable.
INV-293-06 Une escalade suspend la progression de la story jusqu'a reception d'un PO_RESPONSE valide. Gouvernance humaine obligatoire.
INV-293-07 Le workflow /gov est consomme tel quel ; PD-293 ne modifie pas son comportement interne. Respect du perimetre.
INV-293-08 One Ring signale un Ringbearer disparu en etat CRASHED en 2 cycles de polling maximum (<= 20s par defaut). Resilience operationnelle.
INV-293-09 Les transitions d'etat Ringbearer respectent strictement la machine d'etats §5.2 ; toute transition non listee est interdite. Cohesion formelle.
INV-293-10 Etats terminaux (DONE, ABORTED, CRASHED, START_FAILED) : -> * INTERDITE (etat terminal, resolution manuelle uniquement). Fermeture explicite imposee.
INV-293-11 Reconciliation periodique obligatoire entre etat consolide One Ring et peers observes. Tolerance aux crashes/ecarts.
INV-293-12 Idempotence des commandes de controle (start, stop, respond, pause, resume) par cle dediee (§5.1). Retry-safe en environnement distribue.
INV-293-13 Multi-escalade simultanee geree en FIFO ; aucune escalade n'en remplace une autre. Determinisme de traitement et auditabilite.
INV-293-14 Ordre de gardes de commande contractuel : quota -> doublon idempotence -> validation format. Comportement stable et testable.

4.1 Notes de coherence etats

  • En v1, aucun etat ESCALADE_PENDING n'est defini.
  • En v1, aucun etat ESCALADE_EXPIRED n'est defini (hors perimetre, evolution future).

4.2 Commandes /gov-lord normatives

  • /gov-lord start <story_id> <project_code> [--idempotency-key <key>]
  • /gov-lord status [--story <story_id>]
  • /gov-lord escalade [--story <story_id>]
  • /gov-lord respond <story_id> <reponse> [--idempotency-key <key>]
  • /gov-lord pause <story_id> [--reason <texte>] [--idempotency-key <key>]
  • /gov-lord resume <story_id> [--idempotency-key <key>]
  • /gov-lord stop <story_id> [--reason <texte>] [--idempotency-key <key>]

5. Flux nominaux

5.1 Modele de donnees canonique (referentiel unique)

Regles globales normatives

  1. La regex story_id est la source de verite unique (pas de contrainte textuelle de longueur independante).
  2. Ordre de precedance dedoublonnage:
  3. si idempotency_key deja vue avec payload identique: retour deterministe sans effet secondaire,
  4. si idempotency_key deja vue avec payload different: rejet de conflit,
  5. sinon validation/pilotage normal par story_id.
  6. Ordre de gardes pour start (et seulement start) : quota -> doublon idempotence -> validation format complete.
  7. Pour stop/respond/pause/resume : doublon idempotence -> validation format complete (garde quota non applicable).
Donnee Format / encodage Caractere Sensibilite casse Regex / contrainte normative Si invalide
story_id ASCII [A-Z0-9-] case-sensitive ^PD-[0-9]{1,4}$ Rejet
project_code ASCII enum [a-z-] case-sensitive ^(backend|app|site|infra|doc|formal|pixel-governance|ia-governance)$ Rejet
message_type ASCII enum [A-Z_] case-sensitive ^(STATUS_UPDATE|ESCALADE|GATE_RESULT|WORKFLOW_DONE|PO_RESPONSE|PAUSE|RESUME|ABORT)$ Rejet
peer_id UTF-8 opaque printable UTF-8 case-sensitive `[\p{C}

]{1,128}$| Rejet | |timestamp| RFC3339 UTC | ASCII | case-sensitive | horodatage UTC parseable (suffixeZou offset UTC) | Rejet | |escalade_text| UTF-8 | printable UTF-8 | case-sensitive |[\p{C}]{1,2000}$| Rejet | |summary_text| UTF-8 | printable UTF-8 | case-sensitive |[\p{C}]{1,512}$| Rejet | |idempotency_key| ASCII |[A-Za-z0-9:-]| case-sensitive |^[A-Za-z0-9:-]{16,80}$`, unique dans fenetre TTL | Doublon: resultat deterministe |

Parametres numeriques contractuels

Parametre Defaut Min Max Unite Contexte Hors bornes
max_ringbearers 5 1 5 sessions MacBook local Rejet start
peer_poll_interval 10 1 10 secondes Broker local Clamp + avertissement
escalade_visibility_sla 5 1 10 secondes One Ring -> Sovereign Alerte SLA
start_detection_timeout 30 5 120 secondes Creation Ringbearer START_FAILED
first_liveness_timeout 10 2 30 secondes 1ere verification apres apparition peer START_FAILED
crash_detection_cycles_max 2 2 2 cycles Detection crash Non configurable
crash_detection_sla 20 2 20 secondes Derive: peer_poll_interval * 2 (defaut 10*2) Alerte critique
idempotency_ttl 24 1 168 heures Dedup commandes Rejet config

SLA temporels (transitions)

Parametre Defaut Min Max Configurabilite Comportement a expiration
escalade_wait_ttl 72h 1h 30j Oui Pas de nouvel etat en v1: reste ESCALADED, alerte repetee au Sovereign jusqu'a decision explicite
pause_ttl 24h 5min 7j Oui PAUSED persistant + alerte ; aucune reprise automatique
orphan_threshold derive N/A N/A Non (derive) orphan_threshold = 2 * peer_poll_interval; depassement -> CRASHED

5.2 Machine d'etats Ringbearer (avec transitions retour)

Etats officiels v1: STARTING, RUNNING, ESCALADED, PAUSED, DONE, ABORTED, CRASHED, START_FAILED.

  • STARTING :
  • Autorisees : STARTING->RUNNING, STARTING->START_FAILED
  • Regle STARTING->RUNNING : peer detecte et premiere liveness valide recue avant first_liveness_timeout.
  • Regle STARTING->START_FAILED : start_detection_timeout depasse ou peer detecte mais aucune liveness valide dans la fenetre.
  • RUNNING :
  • Autorisees : RUNNING->ESCALADED, RUNNING->PAUSED, RUNNING->DONE, RUNNING->ABORTED, RUNNING->CRASHED
  • ESCALADED :
  • Autorisees : ESCALADED->RUNNING (apres PO_RESPONSE valide), ESCALADED->ABORTED, ESCALADED->CRASHED
  • Retour couvert : RUNNING<->ESCALADED
  • PAUSED :
  • Autorisees : PAUSED->RUNNING (resume), PAUSED->ABORTED, PAUSED->CRASHED
  • Retour couvert : RUNNING<->PAUSED
  • DONE (terminal) : DONE->* INTERDITE.
  • ABORTED (terminal) : ABORTED->* INTERDITE.
  • CRASHED (terminal) : CRASHED->* INTERDITE.
  • START_FAILED (terminal) : START_FAILED->* INTERDITE.

Checklist machine a etats : - [x] Chaque etat a ses transitions sortantes autorisees/interdites. - [x] Chaque etat terminal declare explicitement -> * : INTERDITE. - [x] Couverture par invariants INV-293-09 et INV-293-10. - [x] Aucune reference a ESCALADE_PENDING ou ESCALADE_EXPIRED en etats v1.

5.3 Flux metier

1) start : garde quota -> idempotence -> validation format ; creation d'un Ringbearer si autorise.
2) start post-apparition : premiere verification de liveness obligatoire avant passage RUNNING.
3) status : consolidation de l'etat de tous les Ringbearers observes/attendus.
4) escalade : affichage de la file bloquante FIFO a traiter par le Sovereign.
5) respond : injection d'une decision humaine sur la plus ancienne escalade ouverte de la story cible (FIFO intra-story).
6) pause : gel intentionnel (RUNNING->PAUSED) sans perte de contexte.
7) resume : reprise (PAUSED->RUNNING) si gardes valides.
8) stop : arret intentionnel de la story (->ABORTED selon transitions autorisees).
9) Supervision continue : detection d'absence peer en <= 2 cycles et signalement CRASHED.
10) Reconnexion broker : tentative de reconnexion exponentielle bornee (1s, 2s, 4s, 8s, 10s max), mode degrade explicite tant que indisponible, reprise automatique des polls a la reconnexion.

5.4 Format de persistance .gov-lord-state.json (schema minimal v1)

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "GovLordState",
  "type": "object",
  "required": ["version", "updated_at", "stories", "escalade_queue", "idempotency_cache"],
  "properties": {
    "version": { "type": "string", "const": "1.0" },
    "updated_at": { "type": "string", "format": "date-time" },
    "broker": {
      "type": "object",
      "required": ["status", "last_seen_at"],
      "properties": {
        "status": { "type": "string", "enum": ["UP", "DEGRADED", "DOWN"] },
        "last_seen_at": { "type": "string", "format": "date-time" }
      },
      "additionalProperties": false
    },
    "stories": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["story_id", "project_code", "state", "peer_id", "last_seen_at"],
        "properties": {
          "story_id": { "type": "string", "pattern": "^PD-[0-9]{1,4}$" },
          "project_code": { "type": "string", "enum": ["backend", "app", "site", "infra", "doc", "formal", "pixel-governance", "ia-governance"] },
          "state": { "type": "string", "enum": ["STARTING", "RUNNING", "ESCALADED", "PAUSED", "DONE", "ABORTED", "CRASHED", "START_FAILED"] },
          "peer_id": { "type": "string", "minLength": 1, "maxLength": 128 },
          "last_seen_at": { "type": "string", "format": "date-time" },
          "current_escalade_id": { "type": ["string", "null"] }
        },
        "additionalProperties": false
      }
    },
    "escalade_queue": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["escalade_id", "story_id", "created_at", "text", "status"],
        "properties": {
          "escalade_id": { "type": "string", "minLength": 1, "maxLength": 128 },
          "story_id": { "type": "string", "pattern": "^PD-[0-9]{1,4}$" },
          "created_at": { "type": "string", "format": "date-time" },
          "text": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "status": { "type": "string", "enum": ["OPEN", "ANSWERED", "CLOSED"] }
        },
        "additionalProperties": false
      }
    },
    "idempotency_cache": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["key", "command", "story_id", "payload_hash", "result_hash", "expires_at"],
        "properties": {
          "key": { "type": "string", "pattern": "^[A-Za-z0-9:_-]{16,80}$" },
          "command": { "type": "string", "enum": ["start", "stop", "respond", "pause", "resume"] },
          "story_id": { "type": "string", "pattern": "^PD-[0-9]{1,4}$" },
          "payload_hash": { "type": "string", "minLength": 8, "maxLength": 128 },
          "result_hash": { "type": "string", "minLength": 8, "maxLength": 128 },
          "expires_at": { "type": "string", "format": "date-time" }
        },
        "additionalProperties": false
      }
    }
  },
  "additionalProperties": false
}

5bis. Diagrammes (si applicable)

Diagramme d'etat (>= 3 etats)

stateDiagram-v2
    [*] --> STARTING
    STARTING --> RUNNING: peer detecte + first liveness OK
    STARTING --> START_FAILED: timeout demarrage ou liveness KO

    RUNNING --> ESCALADED: message ESCALADE
    ESCALADED --> RUNNING: message PO_RESPONSE valide

    RUNNING --> PAUSED: commande PAUSE
    PAUSED --> RUNNING: commande RESUME

    RUNNING --> DONE: WORKFLOW_DONE
    RUNNING --> ABORTED: commande ABORT/STOP
    ESCALADED --> ABORTED: commande ABORT/STOP
    PAUSED --> ABORTED: commande ABORT/STOP

    RUNNING --> CRASHED: peer disparu (>2 polls)
    ESCALADED --> CRASHED: peer disparu (>2 polls)
    PAUSED --> CRASHED: peer disparu (>2 polls)

    DONE --> [*]
    ABORTED --> [*]
    CRASHED --> [*]
    START_FAILED --> [*]

Diagramme de sequence (>= 2 services)

sequenceDiagram
    participant S as Sovereign
    participant O as One Ring
    participant B as Broker
    participant R as Ringbearer

    S->>O: "/gov-lord start PD-293 ia-governance"
    O->>O: Gardes start: quota -> idempotence -> format
    O->>B: list_peers()
    B-->>O: peers[]
    O->>R: demande demarrage story_id=PD-293
    R->>B: register_peer(summary_text)
    R-->>O: STATUS_UPDATE (first liveness)
    O->>O: STARTING->RUNNING

    R->>O: ESCALADE{story_id, escalade_text, timestamp}
    O->>O: enqueue FIFO escalade_queue
    O-->>S: notification escalade la plus ancienne

    S->>O: "/gov-lord respond PD-293 <reponse>"
    O->>R: PO_RESPONSE{story_id, escalade_text=<reponse>}
    R-->>O: STATUS_UPDATE (reprise RUNNING)

    S->>O: "/gov-lord pause PD-293"
    O->>R: PAUSE
    S->>O: "/gov-lord resume PD-293"
    O->>R: RESUME

6. Cas d'erreur

ID Cas Reponse attendue
ERR-293-01 start avec quota atteint (>=5) Rejet explicite, aucune creation
ERR-293-02 start sur story_id deja active Rejet explicite idempotent
ERR-293-03 Message sans story_id valide Rejet + journalisation contractuelle
ERR-293-04 respond sans escalade active Rejet explicite
ERR-293-05 Commande hors scope One Ring Blocage explicite (INV-293-01)
ERR-293-06 Broker indisponible Etat degrade + alerte Sovereign + retries reconnection
ERR-293-07 Peer disparu au-dela de 2 cycles de polling Transition CRASHED + alerte
ERR-293-08 Reemission commande deja traitee (idempotency_key) Retour deterministe sans effet secondaire
ERR-293-09 idempotency_key rejouee avec payload different Rejet de conflit deterministe
ERR-293-10 Peer cree mais 1ere liveness absente avant first_liveness_timeout START_FAILED + cleanup session

6.1 Format de log de rejet (normatif)

Chaque rejet de validation/message doit produire une ligne JSON (JSONL) avec champs obligatoires:

{
  "timestamp": "2026-03-30T10:15:30Z",
  "peer_id": "peer-abc-123",
  "message_type": "ESCALADE",
  "reason": "story_id invalide (regex ^PD-[0-9]{1,4}$)",
  "story_id": "PD-99999",
  "event": "MESSAGE_REJECTED"
}

Champs obligatoires minimum: timestamp, peer_id, message_type, reason.

7. Criteres d'acceptation (testables)

ID Critere Observable
CA-01 One Ring liste les Ringbearers actifs status retourne la liste consolidee
CA-02 One Ring demarre un Ringbearer autonome Story visible en RUNNING avant start_detection_timeout et apres first liveness
CA-03 Escalade visible en moins de 5s P95 Mesure horodatee emission/reception
CA-04 respond debloque la story ciblee Transition ESCALADED->RUNNING observee
CA-05 One Ring refuse les actions hors scope Message de blocage explicite systematique
CA-06 Controle mobile operationnel Commandes /gov-lord utilisables depuis iPhone (test manuel)
CA-07 Crash Ringbearer detecte en <= 2 cycles (<=20s defaut) Transition ->CRASHED et alerte
CA-08 /gov inchange fonctionnel en Ringbearer Execution complete sans adaptation du workflow
CA-09 Limite de 5 appliquee 6e start rejete
CA-10 Validation de schema messages stricte Message invalide rejete sans effet de bord
CA-11 Multi-escalade simultanee preserve l'ordre Traitement FIFO sans ecrasement
CA-12 Reconnexion broker robuste Mode degrade explicite puis reprise automatique

8. Scenarios de test (Given / When / Then)

  • T-01 Start nominal
    Given quota disponible et broker operationnel, When start PD-XXX, Then etat RUNNING avant timeout et apres first liveness valide.

  • T-02 Limite capacite
    Given 5 actifs, When start 6e story, Then rejet explicite sans nouveau peer.

  • T-03 Escalade bloquante
    Given story en RUNNING, When message ESCALADE, Then story en ESCALADED jusqu'a PO_RESPONSE.

  • T-04 Reponse escalade
    Given story ESCALADED, When respond valide, Then retour RUNNING et reprise observable.

  • T-05 Commande hors scope
    Given One Ring actif, When demande lecture/ecriture/build/Jira, Then blocage explicite sans execution.

  • T-06 Crash detection
    Given peer present puis absent > 2 cycles, When cycle de supervision, Then etat CRASHED + alerte en <=20s (defaut).

  • T-07 Idempotence commande
    Given idempotency_key deja traitee, When repetition meme payload, Then meme resultat sans doublon d'action.

  • T-08 Mobile control (manuel)
    Given session One Ring accessible mobile, When status/escalade/respond/pause/resume, Then memes resultats fonctionnels que desktop.

  • T-09 Pause/Resume
    Given story en RUNNING, When pause puis resume, Then transitions RUNNING->PAUSED->RUNNING observees.

  • T-10 Multi-escalade FIFO
    Given 3 escalades ouvertes pour une story, When respond est emis 3 fois, Then traitement dans l'ordre d'arrivee sans remplacement.

  • T-11 Reconnexion broker
    Given broker indisponible puis restaure, When boucle de retries, Then mode degrade puis reprise automatique et reconciliation.

9. Hypotheses explicites

ID Hypothese Impact si faux
H-293-01 claude-peers-mcp est disponible et compatible avec version ^1.x. Blocage orchestration multi-sessions.
H-293-02 /remote-control est utilisable sur iPhone (Safari/claude.ai/code). Perte du cas d'usage mobile, pilotage desktop uniquement.
H-293-03 Le broker local supporte 1 One Ring + 5 Ringbearers sans instabilite majeure. Reduction du quota max ou reconfiguration infra.
H-293-04 Le protocole messages requis est supporte par les peers sans adaptation de /gov. Necessite d'une story separee de compatibilite.

10. Points a clarifier

10.1 Contraintes techniques (stack projet cible)

  • Projet cible de l'artefact : ProbatioVault-ia-governance.
  • Stack reelle constatee : Shell (Bash) + Markdown + YAML/JSON de configuration + outillage Python.
  • Dependance externe : claude-peers-mcp@^1.x (npm) comme composant d'integration.
  • Contrainte de conformite : One Ring reste une couche d'orchestration textuelle, sans logique applicative projet.

10.2 Questions ouvertes

ID Question Impact
Q-293-01 Disponibilite exacte de /remote-control en contexte mobile web (et limites eventuelles). Peut degrader CA-06 (manuel).
Q-293-02 Format normatif exact de peer_id expose par list_peers au-dela de "printable UTF-8". Ajustement mineur du validateur §5.1.
Q-293-03 Semantique officielle de pause/reprise cote sessions autonomes. Peut contraindre RUNNING<->PAUSED.
Q-293-04 Politique de persistance locale autorisee pour l'etat consolide One Ring. Impact auditabilite/recuperation apres crash.
Q-293-05 Politique de purge de idempotency_cache au redemarrage. Impact stockage local et forensique.

References

  • Epic : Reference epique non fournie dans l'entree (donnee manquante).
  • JIRA : PD-293
  • Repos concernes : ProbatioVault-ia-governance (orchestrateur), plus repos cibles des stories (backend, app, infra, site, etc.).
  • Documents associes : Besoin PD-293 (texte fourni), claude-peers-mcp (github.com/louislva/claude-peers-mcp).

DOCUMENT D'ENTRÉE : TESTS

PD-293 - Scenarios de tests contractuels (v2 corriges)

1. References

  • Specification : PD-293-specification.md
  • Epic : Reference epique non fournie dans l'entree (donnee manquante)

2. Matrice de couverture

ID Invariant ID Critere ID Test Couverture Commentaire
INV-293-01 CA-05 TC-NOM-05 Oui Les commandes hors scope sont refusees avec message explicite et sans action metier.
INV-293-02 CA-01 TC-NOM-01 Oui Les observations passent par broker/peers; aucun acces direct aux repos cibles.
INV-293-03 CA-08 TC-NOM-09 Oui Isolation stricte des stories et absence de contamination inter-story.
INV-293-04 CA-09 TC-NOM-02 Oui La limite de 5 sessions actives est appliquee strictement.
INV-293-05 CA-10 TC-NOM-10 Oui Validation stricte du schema canonique et rejet deterministe des invalides.
INV-293-06 CA-04 TC-NOM-03 Oui Une escalade bloque la progression jusqu'a reception d'une reponse PO valide.
INV-293-07 CA-08 TC-NR-01 Oui Le workflow /gov reste inchange et fonctionnel en execution Ringbearer.
INV-293-08 CA-07 TC-NOM-06 Oui Passage en CRASHED et alerte en <=2 cycles de polling.
INV-293-09 CA-04 TC-INV-01 Oui Toutes transitions hors machine d'etats sont refusees.
INV-293-10 CA-01 TC-INV-02 Oui Les etats terminaux sont immuables (aucune transition sortante).
INV-293-11 CA-01 TC-NOM-07 Oui Reconciliation periodique detecte et corrige les ecarts de vue consolidee.
INV-293-12 CA-02 TC-NOM-08 Oui Commandes start/stop/respond/pause/resume idempotentes par cle dediee.
INV-293-13 CA-11 TC-NOM-13 Oui Les escalades simultanees sont traitees en FIFO sans remplacement.
INV-293-14 CA-09 TC-INV-03 Oui L'ordre de gardes quota -> doublon -> format est respecte sur start.
INV-293-05 CA-03 TC-NOM-04 Oui Les messages d'escalade valides sont visibles dans la fenetre SLA P95.
INV-293-02 CA-06 TC-MAN-01 Manuel Le controle mobile utilise les memes commandes d'orchestration via One Ring.
INV-293-05 CA-12 TC-ERR-10 Oui Reconnexion broker geree en mode degrade explicite puis reprise automatique.

3. Scenarios de test - Flux nominaux

TEST-ID: TC-NOM-01
Reference spec: INV-293-02, CA-01

GIVEN
  - One Ring demarre avec broker disponible
  - 2 Ringbearers actifs enregistres via peers
WHEN
  - Le Sovereign execute `/gov-lord status`
THEN
  - La sortie contient la liste consolidee des 2 stories actives
  - Chaque entree contient au minimum `story_id`, etat contractuel, horodatage de derniere observation
AND
  - Le journal d'audit trace une consultation broker (listing peers)
  - Aucune operation sur repo cible n'est enregistree
TEST-ID: TC-NOM-02
Reference spec: INV-293-04, CA-09

GIVEN
  - 5 Ringbearers actifs (`max_ringbearers=5`)
WHEN
  - Le Sovereign execute un 6e `/gov-lord start PD-299 backend`
THEN
  - La commande est rejetee explicitement (quota atteint)
  - Aucun nouveau Ringbearer n'est cree
AND
  - Le nombre d'actifs reste strictement a 5
  - Le rejet est journalise
TEST-ID: TC-NOM-03
Reference spec: INV-293-06, CA-04

GIVEN
  - Une story est en etat `RUNNING`
  - Une escalade valide est emise (`message_type=ESCALADE`, `story_id` valide, `escalade_text` non vide)
WHEN
  - Le Sovereign execute `/gov-lord respond <story_id> <reponse>` avec payload valide
THEN
  - La story passe `ESCALADED -> RUNNING`
  - La reprise est observable par un `STATUS_UPDATE` ulterieur
AND
  - La progression etait bloquee tant que `PO_RESPONSE` n'etait pas recue
TEST-ID: TC-NOM-04
Reference spec: CA-03, INV-293-05

GIVEN
  - Campagne de 100 escalades valides en conditions stables locales
  - Horodatages emission/reception RFC3339 UTC collectes pour chaque escalade
WHEN
  - Les 100 escalades sont traitees par One Ring
THEN
  - Le P95 du delai de visibilite est <= `escalade_visibility_sla` (defaut 5s)
AND
  - Les mesures horodatees sont exportees pour preuve
TEST-ID: TC-NOM-05
Reference spec: INV-293-01, CA-05

GIVEN
  - One Ring actif
WHEN
  - Le Sovereign soumet une commande hors scope (ex: lecture repo, build, Jira, GitLab, Vault)
THEN
  - One Ring retourne un message de blocage explicite et coherent
  - Aucune action metier/projet n'est executee
AND
  - Un evenement d'audit de refus est present
TEST-ID: TC-NOM-06
Reference spec: INV-293-08, CA-07

GIVEN
  - Une story en `RUNNING` avec peer precedemment observe
  - Le peer devient absent
WHEN
  - Deux cycles de polling successifs s'executent (`peer_poll_interval` defaut 10s)
THEN
  - L'etat passe en `CRASHED` en <= 2 cycles (<=20s par defaut)
  - Une alerte Sovereign est emise
AND
  - La transition est tracee avec timestamp
TEST-ID: TC-NOM-07
Reference spec: INV-293-11, CA-01

GIVEN
  - Etat consolide One Ring volontairement desynchronise (ex: peer present non reflechi localement)
WHEN
  - Une reconciliation periodique est declenchee
THEN
  - La vue consolidee est alignee avec les peers observes
  - Les ecarts detectes sont explicitement signales
AND
  - L'operation est journalisee sans modifier les stories terminales
TEST-ID: TC-NOM-08
Reference spec: INV-293-12, CA-02

GIVEN
  - Commande `start` valide avec `idempotency_key=K1`
WHEN
  - La meme commande est rejouee avec la meme cle dans la fenetre `idempotency_ttl`
THEN
  - Le second resultat est deterministe et identique au premier
  - Aucun Ringbearer supplementaire n'est cree
AND
  - Le dedoublonnage est trace en audit
TEST-ID: TC-NOM-09
Reference spec: INV-293-03, CA-08

GIVEN
  - 2 stories actives (`PD-293`, `PD-294`) avec contexts et credentials distincts
WHEN
  - Une escalade/reponse est emise pour `PD-293`
THEN
  - Seule `PD-293` change d'etat selon la machine contractuelle
  - `PD-294` conserve son etat et son contexte sans impact
AND
  - Aucun partage de credential ou message inter-story n'est observe
TEST-ID: TC-NOM-10
Reference spec: INV-293-05, CA-10

GIVEN
  - Un lot de messages valides couvrant tous les champs §5.1
WHEN
  - Le lot est ingere par One Ring
THEN
  - Tous les messages valides sont acceptes et traites selon leur type
  - Aucun rejet injustifie n'est observe
AND
  - Le journal d'audit associe type de message, story cible, timestamp
TEST-ID: TC-NOM-12
Reference spec: CA-02, INV-293-09

GIVEN
  - Story en `RUNNING`
WHEN
  - Le Sovereign execute `/gov-lord pause <story_id>` puis `/gov-lord resume <story_id>`
THEN
  - Transitions observees: `RUNNING -> PAUSED -> RUNNING`
  - Aucune perte de contexte n'est observee
AND
  - Les deux commandes sont journalisees avec idempotency_key
TEST-ID: TC-NOM-13
Reference spec: INV-293-13, CA-11

GIVEN
  - Trois escalades ouvertes pour la meme story avec timestamps t1 < t2 < t3
WHEN
  - Le Sovereign execute trois commandes `respond` successives valides
THEN
  - Les escalades sont cloturees dans l'ordre FIFO t1, puis t2, puis t3
  - Aucune escalade n'est remplacee ni perdue
AND
  - La file `escalade_queue` conserve une tracabilite complete

4. Scenarios de test - Cas d'erreur

TEST-ID: TC-ERR-01
Reference spec: ERR-293-01

GIVEN
  - 5 Ringbearers actifs
WHEN
  - Requete `start` additionnelle
THEN
  - Rejet explicite `quota atteint`
  - Aucun effet secondaire de creation
TEST-ID: TC-ERR-02
Reference spec: ERR-293-02

GIVEN
  - Story `PD-293` deja active
WHEN
  - Nouvelle commande `start PD-293` (cle differente)
THEN
  - Rejet explicite idempotent (`story deja active`)
  - Pas de second peer pour la meme story
TEST-ID: TC-ERR-03
Reference spec: ERR-293-03, §6.1

GIVEN
  - Message entrant sans `story_id` valide (absent ou non conforme regex)
WHEN
  - One Ring tente la validation de schema
THEN
  - Message rejete
  - Erreur journalisee au format JSONL obligatoire avec `timestamp`, `peer_id`, `message_type`, `reason`
  - Aucun changement d'etat story
TEST-ID: TC-ERR-04
Reference spec: ERR-293-04

GIVEN
  - Story cible non en `ESCALADED`
WHEN
  - Commande `respond` recue
THEN
  - Rejet explicite (`pas d'escalade active`)
  - Aucun changement d'etat
TEST-ID: TC-ERR-05
Reference spec: ERR-293-05

GIVEN
  - One Ring actif
WHEN
  - Demande hors scope de routage (ex: ecrire fichier, lancer tests)
THEN
  - Blocage explicite conforme INV-293-01
  - Absence totale d'effet de bord metier
TEST-ID: TC-ERR-06
Reference spec: ERR-293-06

GIVEN
  - Broker indisponible
WHEN
  - Commande de supervision (`status`) ou de routage est executee
THEN
  - Passage en mode degrade explicite
  - Alerte Sovereign emise
  - Aucune decision silencieuse non tracee
TEST-ID: TC-ERR-07
Reference spec: ERR-293-07

GIVEN
  - Story observee precedemment en `RUNNING` puis peer absent
WHEN
  - Deux cycles de polling expirent sans retour peer
THEN
  - Transition `-> CRASHED`
  - Alerte critique emise
  - Etat marque terminal
TEST-ID: TC-ERR-08
Reference spec: ERR-293-08, INV-293-12

GIVEN
  - Commande `stop` deja traitee avec `idempotency_key=K2`
WHEN
  - Reemission stricte de la meme commande avec `K2`
THEN
  - Retour deterministe identique
  - Aucun effet secondaire additionnel
TEST-ID: TC-ERR-09
Reference spec: ERR-293-10, §5.2

GIVEN
  - `start` accepte, peer enregistre au broker
WHEN
  - Aucun message de first liveness valide n'est recu avant `first_liveness_timeout`
THEN
  - Etat `STARTING -> START_FAILED`
  - Session partielle nettoyee et alerte emise
TEST-ID: TC-ERR-10
Reference spec: CA-12, §5.3

GIVEN
  - Broker indisponible pendant une periode puis retabli
WHEN
  - One Ring applique la strategie de reconnexion bornee (1s,2s,4s,8s,10s)
THEN
  - Mode degrade explicite durant indisponibilite
  - Reprise automatique des polls a la reconnexion
  - Reconciliation immediate de l'etat consolide
TEST-ID: TC-ERR-11
Reference spec: ERR-293-09, §5.1

GIVEN
  - Commande `respond` traitee avec `idempotency_key=K3` et payload P1
WHEN
  - Rejeu avec meme cle `K3` mais payload P2 different
THEN
  - Rejet deterministe de conflit idempotence
  - Aucun effet secondaire additionnel

5. Tests d'invariants (non negociables)

Invariant Test(s) dedies Observable Commentaire
INV-293-01 TC-NOM-05, TC-ERR-05 Rejet explicite des actions hors scope, zero action metier Separation des pouvoirs preservee.
INV-293-02 TC-NOM-01, TC-MAN-01 Traces d'usage broker/peers uniquement Pas d'acces direct aux repos cibles.
INV-293-03 TC-NOM-09, TC-NR-03 Absence de contamination et de partage credentials entre stories Isolation contractuelle verifiee.
INV-293-04 TC-NOM-02, TC-ERR-01 6e start rejete sans creation Limite capacitaire stricte.
INV-293-05 TC-NOM-10, TC-ERR-03, TC-NEG-01..TC-NEG-10 Validation schema stricte, rejet deterministe des invalides Contrat de message testable.
INV-293-06 TC-NOM-03, TC-ERR-04 Blocage en ESCALADED jusqu'a PO_RESPONSE valide Gouvernance humaine effective.
INV-293-07 TC-NR-01 Comportement /gov identique baseline/post-orchestration Non-regression fonctionnelle du workflow.
INV-293-08 TC-NOM-06, TC-ERR-07 Detection crash en <=2 polls + alerte Resilience operationnelle.
INV-293-09 TC-INV-01 Toute transition non listee est refusee Cohesion machine d'etats.
INV-293-10 TC-INV-02 Aucun DONE/ABORTED/CRASHED/START_FAILED -> * accepte Terminaux verrouilles.
INV-293-11 TC-NOM-07 Reconciliation periodique aligne la vue consolidee Tolerance aux ecarts/crashes.
INV-293-12 TC-NOM-08, TC-ERR-08, TC-ERR-11 Rejeu avec meme cle sans double effet / conflit bloque Retry-safe en distribue.
INV-293-13 TC-NOM-13 FIFO strict multi-escalades Pas de remplacement d'escalade.
INV-293-14 TC-INV-03 Gardes quota -> doublon -> format Ordre contractuel stable.
TEST-ID: TC-INV-01
Reference spec: INV-293-09

GIVEN
  - Jeu complet des etats (`STARTING`, `RUNNING`, `ESCALADED`, `PAUSED`, `DONE`, `ABORTED`, `CRASHED`, `START_FAILED`)
WHEN
  - Chaque transition non listee en §5.2 est tentee
THEN
  - Chaque transition non autorisee est rejetee explicitement
  - Aucune mutation d'etat n'est appliquee
AND
  - Les rejets sont journalises de facon deterministe
TEST-ID: TC-INV-02
Reference spec: INV-293-10

GIVEN
  - Stories placees dans chacun des etats terminaux (`DONE`, `ABORTED`, `CRASHED`, `START_FAILED`)
WHEN
  - Une tentative de transition sortante est emise pour chaque etat terminal
THEN
  - Rejet explicite `etat terminal`
  - Etat reste strictement inchange
AND
  - Le dossier de preuve montre resolution manuelle requise
TEST-ID: TC-INV-03
Reference spec: INV-293-14

GIVEN
  - `max_ringbearers=5` et 5 stories deja actives
  - Commande `start` avec payload invalide (`story_id=pd-001`) et `idempotency_key` nouvelle
WHEN
  - Le Sovereign execute la commande
THEN
  - Le premier rejet observe est `quota atteint` (garde 1)
  - Aucune evaluation bloquante ulterieure ne change le motif principal
AND
  - Le journal trace explicitement l'ordre des gardes appliquees

6. Tests de non-regression

Test ID Objet Observable Commentaire
TC-NR-01 Workflow /gov consomme tel quel Baseline vs run orchestre: memes etapes/gates/verdicts pour une story identique Couvre INV-293-07 et CA-08.
TC-NR-02 Separation One Ring / execution metier Aucune commande One Ring n'effectue lecture/ecriture/build/test/Jira/GitLab/Vault Couvre perimetre exclu et INV-293-01.
TC-NR-03 Isolation inter-story Action sur story A sans impact sur story B (etat, contexte, credentials) Couvre INV-293-03.
TC-NR-04 Etats terminaux stables dans le temps Reconciliation et polling n'ouvrent jamais les etats terminaux Couvre INV-293-10.

7. Tests negatifs et adversariaux

Test ID Entree invalide / abus Resultat attendu Observable
TC-NEG-01 story_id=pd-293 (mauvaise casse) Rejet validation Erreur regex ^PD-[0-9]{1,4}$, aucun effet de bord
TC-NEG-02 story_id=PD-12345 (hors regex) Rejet validation Log de rejet, aucun changement d'etat
TC-NEG-03 project_code=backend-prod (hors enum) Rejet validation Message explicite project_code invalide
TC-NEG-04 project_code=ia-gov (alias interdit) Rejet validation Seule valeur valide: ia-governance
TC-NEG-05 message_type=ESCALATE (valeur non enum) Rejet validation Journal d'erreur schema, etat inchange
TC-NEG-06 timestamp non RFC3339 UTC Rejet validation Motif parse timestamp invalide
TC-NEG-07 idempotency_key <16 chars Rejet validation Commande non traitee
TC-NEG-08 escalade_text vide Rejet validation Escalade non creee
TC-NEG-09 peer_id vide ou controle Unicode Rejet validation Message ignore, erreur audit tracee
TC-NEG-10 Injection message inter-story (story_id A dans canal B) Rejet routage Aucun impact sur A ni B

8. Observabilite requise pour les tests

  • Etat systeme : snapshot consolide des stories (etat contractuel, derniere observation peer, file d'escalades FIFO, statut broker).
  • Reponse API/commande : sortie normalisee des commandes /gov-lord start/status/escalade/respond/pause/resume/stop avec statut success/rejet et motif.
  • Journal d'audit : trace horodatee de validation schema, transitions d'etat, rejets, dedoublonnage idempotence, alertes SLA, ordre des gardes.
  • Evenement signe/horodate : emission/reception des messages critiques (ESCALADE, PO_RESPONSE, WORKFLOW_DONE, CRASHED) en RFC3339 UTC.
  • Export probatoire : lot versionne contenant logs, mesures SLA (P95), matrice de transitions testees, preuves de non-regression et verdict final.

9. Regles non testables / test manuel

Regle Statut de test Raison Impact
CA-06 (controle mobile) Test manuel obligatoire (TC-MAN-01) Contrat mobile depend d'un environnement iPhone/Safari reel ; automatisation exhaustive non normative en v1 Majeur
Validation syntaxique fine de peer_id au-dela de printable UTF-8 Non applicable en v1 Format opaque, contrainte contractuelle limitee a non-vacuite + exclusion caracteres de controle Mineur
TEST-ID: TC-MAN-01
Reference spec: CA-06

Type: Manuel
Preconditions:
  - iPhone + Safari
  - Session `/remote-control` authentifiee

GIVEN
  - One Ring actif et stories existantes
WHEN
  - Le Sovereign execute `status`, `escalade`, `respond`, `pause`, `resume` depuis mobile
THEN
  - Resultats fonctionnels identiques a desktop
  - Aucune action hors scope One Ring n'est possible

10. Verdict QA

  • Testable majoritairement de facon deterministe (avec un lot manuel explicite pour CA-06)

Le contrat PD-293 est testable de facon deterministe pour invariants, machine d'etats, SLA, idempotence, ordre des gardes, FIFO d'escalades et non-regression. La couverture mobile CA-06 est maintenue via test manuel obligatoire (TC-MAN-01), clairement identifie dans la matrice.


DOCUMENT D'ENTRÉE : ACCEPTABILITY

PD-293 — Acceptabilité

Prérequis acceptabilité

  • Tests CI : 45/45 bats tests passent (FSM + validator)
  • Coverage : N/A (shell scripts — pas de framework coverage bash)
  • TODO non tracés : aucun
  • Code DEV ONLY : aucun

Analyse Sonar

  • Quality Gate : N/A (shell scripts, pas de sonar-project.properties)
  • Justification : story tooling (scripts bash), pas de code applicatif NestJS/React

Phase 1 — Reviews automatisées

Check Résultat
bats tests (FSM) ✅ 21/21
bats tests (validator) ✅ 24/24
shellcheck N/A (non configuré)
Total 45/45 OK

Phase 2 — Reviews LLM (Codex gpt-5.3-codex)

Review Code (développeur senior)

Verdict : REJETÉ → puis corrigé Écarts bloquants initiaux : 1. Deux fichiers code-contracts concurrents (code-contracts.yaml + PD-293-code-contracts.yaml) → Corrigé : fichier unique aligné sur l'implémentation réelle 2. Noms de fichiers divergents (contracts: lord-fsm.sh vs implémentation: lord-state-machine.sh) → Corrigé : contracts réalignés

Écarts résiduels (réserves) : - INV-293-02 : diagrammes séquence montrent flèches directes O→R (raccourci visuel, tout passe par broker en réalité) - INV-293-05 : timestamp Z strict dans code vs spec autorisant offsets — décision H-TECH-08 documentée - Multi-escalade : départage timestamps égaux non explicité (mineur en v1 local)

Review Tests (QA engineer)

Verdict : RÉSERVES - Couverture C1 (FSM) et C2 (validator) solide - C3 (broker), C4 (persistence), C5 (orchestrator) sans tests unitaires dédiés - Recommandation : ajouter tests persistence + orchestrator en v2

Review Sécurité (pentester adversarial)

Verdict : RÉSERVES - INV-293-01 (scope guard) correctement implémenté via whitelist case/esac - Pas de secrets dans le code - Audit JSONL ne stocke jamais d'escalade_text (RGPD OK) - Réserves : pas de signature/MAC sur les messages broker (acceptable en v1 localhost)

Synthèse

Critère Statut
Tests ✅ 45/45
Invariants vérifiés 12/14 PASS, 2 avec réserves (INV-293-02, INV-293-05)
Code contracts ✅ Alignés (fichier unique)
Sécurité ✅ Avec réserves (localhost v1)
Documentation ✅ Besoin, spec, tests, plan, decomposition, reviews

Verdict global : ACCEPTÉ AVEC RÉSERVES — prêt pour Gate 8.


TEMPLATE DE SORTIE

Génère le document conformément à cette structure :

PD-293 — Revue d’acceptabilité (post-correction)

1. Références

  • Spécification : PD-293-specification.md
  • Tests contractuels : PD-293-tests.md
  • Acceptabilité existante : PD-293-acceptability.md
  • Date de revue : …
  • Reviewer : …

2. Suivi des écarts (append-only)

[YYYY-MM-DD] — Suivi E-XX

  • Statut précédent : …
  • Statut actuel : OUVERT / PARTIELLEMENT RÉSOLU / RÉSOLU / NON RÉSOLU
  • Justification factuelle :
  • Preuve de vérification :
  • commit / fichier / test TC-XX (PASS)

3. Verdict d’acceptabilité (courant)

  • ⛔ REFUSÉ
  • ⚠️ ACCEPTÉ AVEC RÉSERVES
  • ✅ ACCEPTÉ

Verdict actuel : … Date : … Motif synthétique : …

4. Historique des verdicts

Date Verdict Version / commit Commentaire
YYYY-MM-DD

codex Je vais faire une revue post-correction strictement sur les écarts déjà existants, en m’appuyant sur le code actuel et les preuves d’exécution des tests contractuels. Je commence par localiser les documents PD-293 et l’implémentation associée pour établir les statuts avec preuves vérifiables. exec /bin/zsh -lc "rg --files | rg 'PD-293|gov-lord|lord-|acceptability|specification|tests'" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 665ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable scripts/gov-lord.sh scripts/lib/lord-broker.sh scripts/lib/lord-persistence.sh scripts/lib/lord-state-machine.sh scripts/lib/lord-validator.sh templates/outputs/PD-XX-acceptability-review.md templates/outputs/PD-XX-specification.md templates/outputs/PD-XX-acceptability.md templates/outputs/PD-XX-tests.md docs/epics/legal-compliance/PD-279-iso14641-restituted/PD-279-tests.md docs/epics/legal-compliance/PD-279-iso14641-restituted/PD-279-specification-review.md docs/epics/legal-compliance/PD-279-iso14641-restituted/PD-279-specification-v2.md docs/epics/legal-compliance/PD-253-export-bulk-metadonnees-preuves/PD-253-specification-review.md data/sessions/PD-293-session.jsonl docs/epics/tooling/GOV-SYSTEM-workflow-governance/GOV-SYSTEM-specification.md docs/epics/legal-compliance/PD-281-zlint-anchor-enum/PD-281-specification-review.md docs/epics/legal-compliance/PD-281-zlint-anchor-enum/PD-281-tests.md docs/archive/specification_generale.md docs/archive/specification_architecture_multi_agents_gouvernee.md tests/imessage/test_sentinel.py tests/imessage/init.py tests/imessage/test_sensitive.py tests/imessage/test_hooks.sh docs/epics/legal-compliance/PD-282-proof-envelope-seal-eidas/PD-282-specification-review.md docs/epics/legal-compliance/PD-278-nfz42013-dip-state/PD-278-specification-review.md data/specs-index/pixel-governance/epics/visualization/PG-03-multi-stories/acceptability.yaml tests/lord/test-validator.bats tests/lord/test-state-machine.bats docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-verdict-step3-v1.yaml docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step3.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step5.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-verdict-step3-v2.yaml docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-besoin.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan-review.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-verdict-step5-v1.yaml docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step3-v2.md data/specs-index/pixel-governance/epics/visualization/PG-01-poc-minimal/acceptability.yaml data/specs-index/pixel-governance/epics/visualization/PG-01-poc-minimal/specification.yaml data/specs-index/pixel-governance/epics/visualization/PG-01-poc-minimal/tests.yaml docs/epics/b2c-mineurs/PD-80-scellement-instantane/PD-80-specification-review.md data/specs-index/pixel-governance/epics/visualization/PG-05-layout-editeur/PG-05-acceptability.yaml data/specs-index/pixel-governance/epics/visualization/PG-05-layout-editeur/specification.yaml data/specs-index/pixel-governance/epics/visualization/PG-05-layout-editeur/tests.yaml data/specs-index/pixel-governance/epics/visualization/PG-02-gates-visuelles/acceptability.yaml docs/epics/b2c-mineurs/PD-284-ux-scellement-urgent-suivi-temps-reel/PD-284-agent-agent-qa-unit-integration-seal-tests.md docs/epics/b2c-mineurs/PD-284-ux-scellement-urgent-suivi-temps-reel/PD-284-tests.md docs/epics/b2c-mineurs/PD-284-ux-scellement-urgent-suivi-temps-reel/PD-284-specification-review.md data/specs-index/pixel-governance/epics/visualization/PG-04-temps-reel/acceptability.yaml data/specs-index/pixel-governance/epics/visualization/PG-04-temps-reel/specification.yaml data/specs-index/pixel-governance/epics/visualization/PG-04-temps-reel/tests.yaml data/specs-index/doc/epics/legal-compliance/politique-formats-preservation/PD-252-specification.yaml data/specs-index/doc/epics/legal-compliance/politique-formats-preservation/PD-252-acceptability.yaml data/specs-index/doc/epics/legal-compliance/politique-formats-preservation/PD-252-tests.yaml data/specs-index/backend/reference/backend-api/tests/CLOUDHSM_INTEGRATION_TESTS.yaml data/specs-index/doc/epics/legal-compliance/PD-281-zlint-anchor-enum/PD-281-acceptability.yaml data/specs-index/doc/epics/legal-compliance/PD-281-zlint-anchor-enum/PD-281-specification.yaml data/specs-index/doc/epics/legal-compliance/PD-281-zlint-anchor-enum/PD-281-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-265-monitoring-tsa-lifecycle/PD-265-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-265-monitoring-tsa-lifecycle/PD-265-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-265-monitoring-tsa-lifecycle/PD-265-acceptability.yaml docs/epics/crypto-proof/PD-277-anti-rejeu-nonce-pki-certificate-binding/PD-277-acceptability-review.md data/specs-index/doc/epics/legal-compliance/PD-244-audit-iso14641-nfz42013/PD-244-acceptability.yaml data/specs-index/doc/epics/legal-compliance/PD-244-audit-iso14641-nfz42013/specification.yaml data/specs-index/doc/epics/legal-compliance/PD-244-audit-iso14641-nfz42013/PD-244-specification.yaml data/specs-index/doc/epics/legal-compliance/PD-244-audit-iso14641-nfz42013/PD-244-tests.yaml data/specs-index/doc/epics/legal-compliance/PD-244-audit-iso14641-nfz42013/tests.yaml data/specs-index/backend/epics/legal-compliance/PD-279-iso14641-restituted/PD-279-acceptability.yaml data/specs-index/backend/epics/legal-compliance/PD-279-iso14641-restituted/PD-279-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-279-iso14641-restituted/PD-279-tests.yaml data/specs-index/doc/epics/legal-compliance/protocole-migration-probatoire/PD-254-tests.yaml data/specs-index/doc/epics/legal-compliance/protocole-migration-probatoire/PD-254-specification.yaml data/specs-index/doc/epics/legal-compliance/PD-249-manuel-technique-sae-consolide/PD-249-acceptability.yaml data/specs-index/doc/epics/legal-compliance/PD-249-manuel-technique-sae-consolide/PD-249-specification.yaml data/specs-index/doc/epics/legal-compliance/PD-249-manuel-technique-sae-consolide/PD-249-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-253-export-bulk-metadonnees-preuves/PD-253-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-253-export-bulk-metadonnees-preuves/specification.yaml data/specs-index/backend/epics/legal-compliance/PD-253-export-bulk-metadonnees-preuves/PD-253-acceptability.yaml data/specs-index/backend/epics/legal-compliance/PD-253-export-bulk-metadonnees-preuves/PD-253-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-253-export-bulk-metadonnees-preuves/tests.yaml docs/skills/workflow/acceptability-audit.md docs/skills/workflow/specification-writing.md data/specs-index/app/epics/mobile-ios/upload-document-progress/PD-101-tests.yaml data/specs-index/app/epics/mobile-ios/upload-document-progress/PD-101-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-280-pv-proof-etat-pending/PD-280-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-280-pv-proof-etat-pending/PD-280-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-280-pv-proof-etat-pending/PD-280-acceptability.yaml data/specs-index/app/epics/mobile-ios/anti-tampering/PD-262-specification.yaml data/specs-index/app/epics/mobile-ios/anti-tampering/PD-262-tests.yaml data/specs-index/app/epics/mobile-ios/PD-106-mfa-settings/PD-106-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-106-mfa-settings/PD-106-specification.yaml data/specs-index/app/epics/mobile-ios/PD-106-mfa-settings/PD-106-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-282-proof-envelope-seal-eidas/PD-282-acceptability.yaml data/specs-index/backend/epics/legal-compliance/PD-282-proof-envelope-seal-eidas/PD-282-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-282-proof-envelope-seal-eidas/specification.yaml data/specs-index/backend/epics/legal-compliance/PD-282-proof-envelope-seal-eidas/PD-282-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-282-proof-envelope-seal-eidas/tests.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/tests.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/verdict-step5-v1.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/besoin.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/verdict-step3-v2.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/index.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/verdict-step3-v1.yaml data/specs-index/ia-governance/epics/tooling/PD-293-one-ring-orchestration/specification.yaml data/specs-index/app/epics/mobile-ios/PD-98-keychain-kmaster/PD-98-tests.yaml data/specs-index/app/epics/mobile-ios/PD-98-keychain-kmaster/PD-98-specification.yaml data/specs-index/app/epics/mobile-ios/PD-98-keychain-kmaster/PD-98-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-176-onboarding/PD-176-specification.yaml data/specs-index/app/epics/mobile-ios/PD-96-init-project/PD-96-tests.yaml data/specs-index/app/epics/mobile-ios/PD-96-init-project/PD-96-specification.yaml data/specs-index/app/epics/mobile-ios/PD-96-init-project/PD-96-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-97-crypto-zero-knowledge/PD-97-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-97-crypto-zero-knowledge/PD-97-specification.yaml data/specs-index/app/epics/mobile-ios/PD-97-crypto-zero-knowledge/PD-97-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-251-verification-integrite-periodique/PD-251-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-251-verification-integrite-periodique/PD-251-acceptability.yaml data/specs-index/backend/epics/legal-compliance/PD-251-verification-integrite-periodique/PD-251-tests.yaml data/specs-index/app/epics/mobile-ios/PD-101-upload-document-progress/PD-101-acceptability.yaml data/specs-index/infra/reference/infra/tests/integration-tests.yaml data/specs-index/infra/reference/infra/tests/README.yaml data/specs-index/infra/reference/infra/tests/integration-tests-detailed.yaml data/specs-index/infra/reference/infra/tests/network-validation.yaml data/specs-index/app/epics/mobile-ios/PD-105-push-notifications/PD-105-tests.yaml data/specs-index/app/epics/mobile-ios/PD-105-push-notifications/PD-105-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-105-push-notifications/PD-105-specification.yaml data/specs-index/app/epics/mobile-ios/PD-262-anti-tampering/PD-262-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-99-connexion-SRP6a/PD-99-acceptability.yaml data/specs-index/app/epics/mobile-ios/PD-99-connexion-SRP6a/PD-99-tests.yaml data/specs-index/app/epics/mobile-ios/PD-99-connexion-SRP6a/PD-99-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-278-nfz42013-dip-state/PD-278-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-278-nfz42013-dip-state/PD-278-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-278-nfz42013-dip-state/PD-278-acceptability.yaml data/specs-index/backend/epics/backend-core/relever-maxsize-500mb/PD-285-tests.yaml data/specs-index/backend/epics/backend-core/relever-maxsize-500mb/PD-285-acceptability.yaml data/specs-index/backend/epics/backend-core/relever-maxsize-500mb/PD-285-specification.yaml data/specs-index/app/epics/mobile-ios/PD-174-auto-lock/PD-174-tests.yaml data/specs-index/app/epics/mobile-ios/PD-174-auto-lock/PD-174-specification.yaml data/specs-index/app/epics/mobile-ios/PD-174-auto-lock/PD-174-acceptability.yaml data/specs-index/backend/epics/legal-compliance/PD-250-destruction-bordereau/specification.yaml data/specs-index/backend/epics/legal-compliance/PD-250-destruction-bordereau/PD-250-acceptability.yaml data/specs-index/backend/epics/legal-compliance/PD-250-destruction-bordereau/PD-250-specification.yaml data/specs-index/backend/epics/legal-compliance/PD-250-destruction-bordereau/PD-250-tests.yaml data/specs-index/backend/epics/legal-compliance/PD-250-destruction-bordereau/tests.yaml data/specs-index/backend/epics/backend-core/PD-237-merkle-persistence/PD-237-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-237-merkle-persistence/PD-237-specification.yaml data/specs-index/backend/epics/backend-core/PD-237-merkle-persistence/PD-237-specification-review.yaml data/specs-index/backend/epics/backend-core/PD-237-merkle-persistence/PD-237-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-36-hsm-pkcs11-client/PD-36-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-36-hsm-pkcs11-client/PD-36-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-36-hsm-pkcs11-client/PD-36-specification.yaml data/specs-index/backend/epics/backend-core/PD-21-bullmq/PD-21-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-21-bullmq/PD-21-specification.yaml data/specs-index/backend/epics/backend-core/PD-21-bullmq/PD-21-tests.yaml data/specs-index/infra/epics/legal-compliance/PD-246-conservation-50-ans/PD-246-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-276-argon2id-rfc9106-metadata-binding/specification.yaml data/specs-index/backend/epics/crypto-proof/PD-276-argon2id-rfc9106-metadata-binding/PD-276-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-276-argon2id-rfc9106-metadata-binding/PD-276-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-276-argon2id-rfc9106-metadata-binding/PD-276-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-276-argon2id-rfc9106-metadata-binding/tests.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-specification.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-specification-review.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-acceptability-review-v1.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-tests.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-specification-review-v2.yaml data/specs-index/backend/epics/docs-api/PD-60-document-upload/PD-60-specification.yaml data/specs-index/backend/epics/docs-api/PD-60-document-upload/PD-60-tests.yaml data/specs-index/backend/epics/docs-api/PD-60-document-upload/PD-60-acceptability.yaml data/specs-index/backend/epics/docs-api/PD-60-document-upload/PD-60-specification-review.yaml data/specs-index/app/epics/mobile-ios/PD-107-biometric-auth/PD-107-tests.yaml data/specs-index/app/epics/mobile-ios/PD-107-biometric-auth/PD-107-specification.yaml data/specs-index/app/epics/mobile-ios/PD-107-biometric-auth/PD-107-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-236-recherche-tokens/PD-236-specification-review.yaml data/specs-index/backend/epics/backend-core/PD-236-recherche-tokens/PD-236-tests.yaml data/specs-index/backend/epics/backend-core/PD-236-recherche-tokens/PD-236-specification.yaml data/specs-index/backend/epics/backend-core/PD-236-recherche-tokens/PD-236-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-39-tsa-rfc3161/PD-39-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-39-tsa-rfc3161/PD-39-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-39-tsa-rfc3161/PD-39-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-35-key-wrapping/PD-35-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-35-key-wrapping/PD-35-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-35-key-wrapping/PD-35-specification.yaml data/specs-index/backend/epics/backend-core/PD-14-typeorm-config/PD-14-specification.yaml data/specs-index/backend/epics/backend-core/PD-14-typeorm-config/PD-14-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-14-typeorm-config/PD-14-tests.yaml data/specs-index/backend/epics/docs-api/PD-63-document-download/PD-63-tests.yaml data/specs-index/backend/epics/docs-api/PD-63-document-download/PD-63-specification.yaml data/specs-index/backend/epics/docs-api/PD-63-document-download/PD-63-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-17-schema-vault_secure./PD-17-specification.yaml data/specs-index/backend/epics/backend-core/PD-17-schema-vault_secure./PD-17-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-17-schema-vault_secure./PD-17-tests.yaml data/specs-index/backend/epics/backend-core/PD-180-webhooks/specification.yaml data/specs-index/backend/epics/backend-core/PD-180-webhooks/tests.yaml data/specs-index/backend/epics/crypto-proof/PD-272-proof-immutable-trigger/PD-272-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-272-proof-immutable-trigger/specification.yaml data/specs-index/backend/epics/crypto-proof/PD-272-proof-immutable-trigger/PD-272-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-272-proof-immutable-trigger/PD-272-acceptability.yaml data/specs-index/doc/corporate/4---dossier-technique-&-architecture/42---specifications_techniques---v2.1.yaml data/specs-index/app/epics/b2c-mineurs/PD-86-detection-contenu-sensible/PD-86-specification.yaml data/specs-index/app/epics/b2c-mineurs/PD-86-detection-contenu-sensible/PD-86-tests.yaml data/specs-index/app/epics/b2c-mineurs/PD-86-detection-contenu-sensible/PD-86-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-25-srp-phase2/PD-25-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-25-srp-phase2/PD-25-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-25-srp-phase2/PD-25-specification.yaml data/specs-index/infra/epics/blockchain/PD-53-smart-contract-merkle-anchor/PD-53-tests.yaml data/specs-index/infra/epics/blockchain/PD-53-smart-contract-merkle-anchor/PD-53-specification.yaml data/specs-index/infra/epics/blockchain/PD-53-smart-contract-merkle-anchor/PD-53-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-13-nestjs-init/PD-13-specification.yaml data/specs-index/backend/epics/backend-core/PD-13-nestjs-init/PD-13-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-13-nestjs-init/PD-13-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-273-audit-trigger-sign-sequence/PD-273-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-273-audit-trigger-sign-sequence/PD-273-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-273-audit-trigger-sign-sequence/PD-273-specification.yaml data/specs-index/backend/epics/blockchain/PD-245-format-preuve-multi-chain/acceptability.yaml data/specs-index/backend/epics/blockchain/PD-245-format-preuve-multi-chain/PD-245-tests.yaml data/specs-index/backend/epics/blockchain/PD-245-format-preuve-multi-chain/PD-245-specification.yaml data/specs-index/backend/epics/blockchain/PD-245-format-preuve-multi-chain/PD-245-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-37-hsm-audit-signature/PD-37-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-37-hsm-audit-signature/PD-37-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-37-hsm-audit-signature/PD-37-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-40-hsm-rotation/PD-40-acceptability.yaml data/specs-index/backend/epics/b2c-mineurs/PD-79-evidence-upload/PD-79-specification.yaml data/specs-index/backend/epics/b2c-mineurs/PD-79-evidence-upload/PD-79-acceptability.yaml data/specs-index/backend/epics/b2c-mineurs/PD-79-evidence-upload/PD-79-tests.yaml data/specs-index/app/epics/b2c-mineurs/PD-284-ux-scellement-instantane/PD-284-acceptability.yaml data/specs-index/backend/epics/blockchain/PD-275-anchor-16-17-finality-signer/PD-275-tests.yaml data/specs-index/backend/epics/blockchain/PD-275-anchor-16-17-finality-signer/specification.yaml data/specs-index/backend/epics/blockchain/PD-275-anchor-16-17-finality-signer/PD-275-specification.yaml data/specs-index/backend/epics/blockchain/PD-275-anchor-16-17-finality-signer/tests.yaml data/specs-index/backend/epics/blockchain/PD-275-anchor-16-17-finality-signer/PD-275-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-277-anti-rejeu-nonce-pki-certificate-binding/PD-277-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-277-anti-rejeu-nonce-pki-certificate-binding/PD-277-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-277-anti-rejeu-nonce-pki-certificate-binding/PD-277-tests.yaml data/specs-index/backend/epics/b2c-mineurs/PD-80-scellement-instantane/PD-80-tests.yaml data/specs-index/backend/epics/b2c-mineurs/PD-80-scellement-instantane/PD-80-specification.yaml data/specs-index/backend/epics/backend-core/PD-16-schema-documents/PD-16-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-16-schema-documents/PD-16-tests.yaml data/specs-index/backend/epics/backend-core/PD-16-schema-documents/PD-16-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-274-anchor-enum-status-reorg/PD-274-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-274-anchor-enum-status-reorg/PD-274-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-274-anchor-enum-status-reorg/PD-274-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-24-srp-phase1/PD-24-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-24-srp-phase1/PD-24-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-24-srp-phase1/PD-24-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-82-double-validation/PD-82-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-82-double-validation/PD-82-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-82-double-validation/PD-82-acceptability.yaml data/specs-index/app/epics/crypto/PD-33-argon2id-derivation/PD-33-tests.yaml data/specs-index/app/epics/crypto/PD-33-argon2id-derivation/PD-33-specification.yaml data/specs-index/app/epics/crypto/PD-33-argon2id-derivation/PD-33-acceptability.yaml data/specs-index/infra/epics/storage/PD-6-crr-frankfurt/PD-6-acceptability.yaml data/specs-index/infra/epics/storage/PD-6-crr-frankfurt/PD-6-tests.yaml data/specs-index/infra/epics/storage/PD-6-crr-frankfurt/PD-6-specification.yaml data/specs-index/backend/epics/blockchain/PD-177-wallet-ethereum/PD-177-tests.yaml data/specs-index/backend/epics/blockchain/PD-177-wallet-ethereum/PD-177-specification.yaml data/specs-index/backend/epics/blockchain/PD-177-wallet-ethereum/PD-177-acceptability.yaml data/specs-index/app/epics/b2c-mineurs/PD-283-assemblage-zip-dossier-plainte/specification.yaml data/specs-index/backend/epics/crypto-proof/PD-41-pre/PD-41-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-41-pre/PD-41-specification.yaml data/specs-index/app/epics/b2c-mineurs/PD-283-assemblage-zip-dossier-plainte/PD-283-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-41-pre/PD-41-tests.yaml data/specs-index/app/epics/b2c-mineurs/PD-283-assemblage-zip-dossier-plainte/tests.yaml data/specs-index/backend/epics/crypto-proof/PD-41-pre/PD-41-specification-review.yaml data/specs-index/backend/epics/b2c-mineurs/PD-84-offre-gratuite-b2c-mineurs/PD-84-acceptability.yaml data/specs-index/backend/epics/b2c-mineurs/PD-84-offre-gratuite-b2c-mineurs/PD-84-specification.yaml data/specs-index/backend/epics/b2c-mineurs/PD-84-offre-gratuite-b2c-mineurs/PD-84-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-72-worker-pre-transfer/PD-72-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-72-worker-pre-transfer/PD-72-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-72-worker-pre-transfer/PD-72-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-40-hsm-rotation/PD-40-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-40-hsm-rotation/PD-40-tests.yaml data/specs-index/backend/epics/backend-core/PD-171-synchro-multi-device/PD-171-tests.yaml data/specs-index/backend/epics/backend-core/PD-171-synchro-multi-device/PD-171-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-171-synchro-multi-device/PD-171-specification.yaml data/specs-index/app/epics/crypto/PD-34-key-derivation/PD-34-specification.yaml data/specs-index/app/epics/crypto/PD-34-key-derivation/PD-34-tests.yaml data/specs-index/app/epics/crypto/PD-34-key-derivation/PD-34-acceptability.yaml data/specs-index/app/epics/b2c-mineurs/ux-scellement-instantane/PD-284-specification.yaml data/specs-index/app/epics/b2c-mineurs/ux-scellement-instantane/PD-284-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-38-sha3-hash/PD-38-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-38-sha3-hash/PD-38-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-38-sha3-hash/PD-38-acceptability.yaml data/specs-index/backend/epics/blockchain/PD-264-nonce-tsa-rfc3161/PD-264-tests.yaml data/specs-index/backend/epics/blockchain/PD-264-nonce-tsa-rfc3161/PD-264-acceptability.yaml data/specs-index/backend/epics/blockchain/PD-264-nonce-tsa-rfc3161/PD-264-specification.yaml data/specs-index/infra/epics/storage/PD-46-secure-download/PD-46-specification-review-gate8-v1.yaml data/specs-index/infra/epics/storage/PD-46-secure-download/PD-46-acceptability.yaml data/specs-index/infra/epics/storage/PD-46-secure-download/PD-46-specification-review.yaml data/specs-index/infra/epics/storage/PD-46-secure-download/PD-46-specification.yaml data/specs-index/infra/epics/storage/PD-46-secure-download/PD-46-tests.yaml data/specs-index/infra/epics/storage/PD-44-object-lock-worm/PD-44-specification.yaml data/specs-index/infra/epics/storage/PD-44-object-lock-worm/PD-44-specification-review-v2.yaml data/specs-index/infra/epics/storage/PD-44-object-lock-worm/PD-44-acceptability.yaml data/specs-index/infra/epics/storage/PD-44-object-lock-worm/PD-44-tests.yaml data/specs-index/backend/epics/crypto-proof/PD-81-legal-pre/PD-81-specification.yaml data/specs-index/backend/epics/crypto-proof/PD-81-legal-pre/PD-81-acceptability.yaml data/specs-index/backend/epics/crypto-proof/PD-81-legal-pre/PD-81-tests.yaml data/specs-index/backend/epics/b2c-mineurs/PD-85-export-dossier-plainte/acceptability.yaml data/specs-index/backend/epics/b2c-mineurs/PD-85-export-dossier-plainte/specification.yaml data/specs-index/backend/epics/b2c-mineurs/PD-85-export-dossier-plainte/tests.yaml data/specs-index/backend/epics/backend-core/PD-15-schema-users/PD-15-specification.yaml data/specs-index/backend/epics/backend-core/PD-15-schema-users/PD-15-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-15-schema-users/PD-15-tests.yaml data/specs-index/backend/epics/backend-core/PD-22-config/PD-22-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-22-config/PD-22-tests.yaml data/specs-index/backend/epics/backend-core/PD-22-config/PD-22-specification.yaml data/specs-index/backend/epics/backend-core/PD-3-redis-bullmq/PD-3-specification-review.yaml data/specs-index/backend/epics/backend-core/PD-3-redis-bullmq/PD-3-specification.yaml data/specs-index/backend/epics/backend-core/PD-3-redis-bullmq/PD-3-acceptability.yaml data/specs-index/backend/epics/backend-core/PD-3-redis-bullmq/PD-3-tests.yaml data/specs-index/app/epics/crypto/PD-42-recherche-chifree/PD-42-acceptability.yaml data/specs-index/app/epics/crypto/PD-42-recherche-chifree/PD-42-specification.yaml data/specs-index/app/epics/crypto/PD-42-recherche-chifree/PD-42-specification-review.yaml data/specs-index/app/epics/crypto/PD-42-recherche-chifree/PD-42-tests.yaml data/specs-index/infra/epics/storage/PD-47-backup-postgresql/PD-47-specification.yaml data/specs-index/infra/epics/storage/PD-47-backup-postgresql/PD-47-tests.yaml data/specs-index/infra/epics/storage/PD-47-backup-postgresql/specification.yaml data/specs-index/infra/epics/storage/PD-47-backup-postgresql/PD-47-acceptability.yaml data/specs-index/infra/epics/storage/PD-47-backup-postgresql/tests.yaml data/specs-index/backend/epics/blockchain/PD-55-worker-ancrage-blockchain/PD-55-tests.yaml data/specs-index/backend/epics/blockchain/PD-55-worker-ancrage-blockchain/PD-55-acceptability.yaml data/specs-index/backend/epics/blockchain/PD-55-worker-ancrage-blockchain/PD-55-specification.yaml data/specs-index/infra/epics/storage/PD-5-glacier-paris/PD-5-tests.yaml data/specs-index/infra/epics/storage/PD-5-glacier-paris/PD-5-acceptability.yaml data/specs-index/infra/epics/storage/PD-5-glacier-paris/PD-5-specification.yaml data/specs-index/app/epics/crypto/PD-54-merkle-tree/PD-54-tests.yaml data/specs-index/app/epics/crypto/PD-54-merkle-tree/PD-54-specification.yaml data/specs-index/app/epics/crypto/PD-54-merkle-tree/PD-54-acceptability.yaml data/specs-index/app/epics/crypto/PD-54-merkle-tree/PD-54-specification-review.yaml data/specs-index/backend/epics/blockchain/PD-52-ethereum-l2-setup/PD-52-specification-review.yaml data/specs-index/backend/epics/blockchain/PD-52-ethereum-l2-setup/PD-52-acceptability.yaml data/specs-index/backend/epics/blockchain/PD-52-ethereum-l2-setup/PD-52-specification.yaml data/specs-index/backend/epics/blockchain/PD-52-ethereum-l2-setup/PD-52-tests.yaml data/specs-index/infra/epics/storage/PD-43-ovh-upload/PD-43-specification.yaml data/specs-index/infra/epics/storage/PD-43-ovh-upload/PD-43-acceptability.yaml data/specs-index/infra/epics/storage/PD-43-ovh-upload/PD-43-tests.yaml data/specs-index/governance/specs/specification-architecture-multi-agents.yaml data/specs-index/governance/specs/specification-generale.yaml data/specs-index/app/epics/crypto/PD-243-hkdf-kauth/PD-243-tests.yaml data/specs-index/app/epics/crypto/PD-243-hkdf-kauth/PD-243-specification.yaml data/specs-index/app/epics/crypto/PD-243-hkdf-kauth/PD-243-acceptability.yaml data/specs-index/app/epics/crypto/PD-243-hkdf-kauth/acceptability.yaml data/specs-index/infra/epics/storage/PD-4-ovh-buckets-worm/PD-4-specification.yaml data/specs-index/infra/epics/storage/PD-4-ovh-buckets-worm/PD-4-tests.yaml data/specs-index/infra/epics/storage/PD-4-ovh-buckets-worm/PD-4-acceptability.yaml data/specs-index/app/epics/crypto/PD-248-screenshot-protection/acceptability.yaml data/specs-index/app/epics/crypto/PD-248-screenshot-protection/PD-248-tests.yaml data/specs-index/app/epics/crypto/PD-248-screenshot-protection/PD-248-specification.yaml data/specs-index/app/epics/crypto/PD-248-screenshot-protection/PD-248-acceptability.yaml data/specs-index/app/epics/crypto/PD-242-recovery-envelope/PD-242-specification.yaml data/specs-index/app/epics/crypto/PD-242-recovery-envelope/PD-242-tests.yaml data/specs-index/app/epics/crypto/PD-242-recovery-envelope/acceptability.yaml data/specs-index/app/epics/crypto/PD-242-recovery-envelope/specification.yaml data/specs-index/app/epics/crypto/PD-242-recovery-envelope/PD-242-acceptability.yaml data/specs-index/app/epics/crypto/PD-242-recovery-envelope/tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-1-vpc-terraform/PD-1-acceptability.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-1-vpc-terraform/PD-1-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-1-vpc-terraform/PD-1-tests.yaml data/specs-index/site/epics/site-vitrine/PD-234-comm-post-inpi/PD-234-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-8-vault-config/PD-8-tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-8-vault-config/PD-8-acceptability.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-8-vault-config/PD-8-specification.yaml data/specs-index/backend/epics/auth-identity/PD-28-session/PD-28-tests.yaml data/specs-index/backend/epics/auth-identity/PD-28-session/PD-28-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-28-session/PD-28-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-28-session/PD-28-specification.yaml data/specs-index/backend/epics/auth-identity/PD-30-session-management-redis/acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-30-session-management-redis/specification.yaml data/specs-index/backend/epics/auth-identity/PD-30-session-management-redis/PD-30-specification.yaml data/specs-index/backend/epics/auth-identity/PD-30-session-management-redis/PD-30-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-30-session-management-redis/PD-30-tests.yaml data/specs-index/backend/epics/auth-identity/PD-30-session-management-redis/tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-12-gitlab-runner/PD-12-acceptability.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-12-gitlab-runner/PD-12-tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-12-gitlab-runner/PD-12-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-235-iam/PD-235-tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-235-iam/PD-235-specification-review.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-235-iam/PD-235-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-235-iam/PD-235-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-228-design-system/PD-228-specification.yaml data/specs-index/site/epics/site-vitrine/PD-228-design-system/PD-228-acceptability.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-247-scalabilite-horizontale/PD-247-specification.yaml data/specs-index/governance/skills/workflow/acceptability-audit.yaml data/specs-index/governance/skills/workflow/specification-writing.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-review-tests.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-acceptability-review.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-specification.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-specification-review-v2.yaml data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-2-postgresql-ovh/PD-2-acceptability.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-2-postgresql-ovh/PD-2-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-2-postgresql-ovh/PD-2-tests.yaml data/specs-index/backend/epics/auth-identity/PD-26-keycloak/PD-26-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-26-keycloak/PD-26-tests.yaml data/specs-index/backend/epics/auth-identity/PD-26-keycloak/PD-26-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-26-keycloak/PD-26-specification.yaml data/specs-index/site/epics/site-vitrine/PD-229-seo-opengraph/PD-229-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-229-seo-opengraph/PD-229-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-7-hsm-fips-140-2-level-3/PD-7-specification.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-7-hsm-fips-140-2-level-3/PD-7-tests.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-7-hsm-fips-140-2-level-3/PD-7-acceptability.yaml data/specs-index/infra/epics/infrastructure-souveraine/PD-7-hsm-fips-140-2-level-3/PD-7-specification-review.yaml data/specs-index/site/epics/site-vitrine/PD-233-comm-pre-inpi/PD-233-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-233-comm-pre-inpi/PD-233-specification.yaml data/specs-index/backend/epics/auth-identity/PD-239-password-change/PD-239-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-239-password-change/PD-239-tests.yaml data/specs-index/backend/epics/auth-identity/PD-239-password-change/PD-239-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-239-password-change/PD-239-specification.yaml data/specs-index/backend/epics/auth-identity/PD-239-password-change/PD-239-review-tests.yaml data/specs-index/backend/epics/auth-identity/PD-239-password-change/PD-239-specification-review-v2.yaml data/specs-index/backend/epics/auth-identity/PD-27-mfa/PD-27-tests.yaml data/specs-index/backend/epics/auth-identity/PD-27-mfa/PD-27-specification.yaml data/specs-index/backend/epics/auth-identity/PD-27-mfa/PD-27-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-27-mfa/PD-27-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-226-astro-setup/PD-226-specification.yaml data/specs-index/site/epics/site-vitrine/PD-226-astro-setup/PD-226-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-227-i18n-fr-en/PD-227-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-227-i18n-fr-en/PD-227-specification.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-agent-qa-tests.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-review-tests-v2.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-acceptability-review-v1.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-invariants-tests-matrix.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-review-tests.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-tests.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-specification.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-specification.yaml data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-acceptability-review.yaml data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability-review-v2.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-tests.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability-review-v3.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-review-tests.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability-review.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-specification.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-specification-review.yaml data/specs-index/backend/epics/auth-identity/PD-31-audit-log-auth/PD-31-specification-review-gate8-v1.yaml data/specs-index/backend/epics/auth-identity/PD-31-audit-log-auth/PD-31-specification-eval-mixtral.yaml data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-specification-review-v2.yaml data/specs-index/backend/epics/auth-identity/PD-23-inscription-utilisateur/PD-23-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-23-inscription-utilisateur/PD-23-specification.yaml data/specs-index/backend/epics/auth-identity/PD-23-inscription-utilisateur/PD-23-tests.yaml data/specs-index/site/epics/site-vitrine/PD-231-gitlab-pages/PD-231-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-231-gitlab-pages/PD-231-specification.yaml data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-tests.yaml data/specs-index/backend/epics/auth-identity/PD-31-audit-log-auth/PD-31-tests.yaml data/specs-index/backend/epics/auth-identity/PD-31-audit-log-auth/PD-31-acceptability.yaml data/specs-index/backend/epics/auth-identity/PD-31-audit-log-auth/PD-31-specification.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/prompts/prompt-7b-tests-review.yaml data/specs-index/site/epics/site-vitrine/PD-230-accessibility/PD-230-acceptability.yaml data/specs-index/site/epics/site-vitrine/PD-230-accessibility/PD-230-specification.yaml data/specs-index/site/epics/site-vitrine/PD-232-faq-collections/PD-232-specification.yaml data/specs-index/site/epics/site-vitrine/PD-232-faq-collections/PD-232-acceptability.yaml

exec /bin/zsh -lc "rg --files | rg 'PD-293-acceptability-review.md|docs/meta/templates/PD-293-acceptability-review.md|acceptability-review'" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 657ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable data/specs-index/backend/epics/auth-identity/PD-241-logout/PD-241-acceptability-review.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability-review.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability-review-v2.yaml data/specs-index/backend/epics/auth-identity/PD-32-user-settings/PD-32-acceptability-review-v3.yaml data/specs-index/backend/epics/auth-identity/PD-238-mfa-management/PD-238-acceptability-review-v1.yaml data/specs-index/backend/epics/backend-core/PD-19-cors-security-headers/PD-19-acceptability-review-v1.yaml templates/outputs/PD-XX-acceptability-review.md data/specs-index/backend/epics/auth-identity/PD-240-delete-account/PD-240-acceptability-review.yaml docs/epics/crypto-proof/PD-277-anti-rejeu-nonce-pki-certificate-binding/PD-277-acceptability-review.md

codex J’ai localisé le dossier cible docs/epics/tooling/PD-293-one-ring-orchestration et les scripts d’implémentation scripts/lib/*. Je vais maintenant vérifier les écarts existants dans PD-293-acceptability.md, puis collecter des preuves code + exécution des tests contractuels avant de statuer. exec /bin/zsh -lc "sed -n '1,260p' docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc "sed -n '1,260p' scripts/gov-lord.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc "sed -n '1,260p' scripts/lib/lord-validator.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc "sed -n '1,260p' scripts/lib/lord-state-machine.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 1110ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

!/usr/bin/env bash

PD-293 — C2 Validator : Validation schemas §5.1

8 validateurs + logger de rejet §6.1

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

─── Enums contractuels ──────────────────────────────────────────────────────

LORD_PROJECT_CODES="backend|app|site|infra|doc|formal|pixel-governance|ia-governance" LORD_MESSAGE_TYPES="STATUS_UPDATE|ESCALADE|GATE_RESULT|WORKFLOW_DONE|PO_RESPONSE|PAUSE|RESUME|ABORT"

─── Validateurs ─────────────────────────────────────────────────────────────

lord_validate_story_id(value) → 0 (OK) | 1 (INVALID)

lord_validate_story_id() { local value="$1" [[ "$value" =~ ^PD-[0-9]{1,4}$ ]] }

lord_validate_project_code(value) → 0 | 1

lord_validate_project_code() { local value="$1" [[ "$value" =~ ^(${LORD_PROJECT_CODES})$ ]] }

lord_validate_message_type(value) → 0 | 1

lord_validate_message_type() { local value="$1" [[ "$value" =~ ^(${LORD_MESSAGE_TYPES})$ ]] }

lord_validate_peer_id(value) → 0 | 1

Contrainte: non vide, 1-128 chars, pas de caractères de contrôle

lord_validate_peer_id() { local value="$1" if [[ -z "$value" ]] || [[ ${#value} -gt 128 ]]; then return 1 fi # Exclure caractères de contrôle via grep -P si disponible, sinon fallback if command -v grep &>/dev/null && echo "" | grep -P "" &>/dev/null 2>&1; then echo -n "$value" | grep -Pq '[\p{C}]+$' else # Fallback: rejeter si contient - ou  (ASCII control) [[ ! "$value" =~ [[:cntrl:]] ]] fi }

lord_validate_timestamp(value) → 0 | 1

Strictement UTC Z (H-TECH-08)

lord_validate_timestamp() { local value="$1" [[ "$value" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(.[0-9]+)?Z$ ]] }

lord_validate_escalade_text(value) → 0 | 1

lord_validate_escalade_text() { local value="$1" if [[ -z "$value" ]] || [[ ${#value} -gt 2000 ]]; then return 1 fi if command -v grep &>/dev/null && echo "" | grep -P "" &>/dev/null 2>&1; then echo -n "$value" | grep -Pq '[\p{C}]+$' else [[ ! "$value" =~ [[:cntrl:]] ]] fi }

lord_validate_summary_text(value) → 0 | 1

lord_validate_summary_text() { local value="$1" if [[ -z "$value" ]] || [[ ${#value} -gt 512 ]]; then return 1 fi if command -v grep &>/dev/null && echo "" | grep -P "" &>/dev/null 2>&1; then echo -n "$value" | grep -Pq '[\p{C}]+$' else [[ ! "$value" =~ [[:cntrl:]] ]] fi }

lord_validate_idempotency_key(value) → 0 | 1

lord_validate_idempotency_key() { local value="$1" [[ "$value" =~ ^[A-Za-z0-9:_-]{16,80}$ ]] }

─── Validation de message complet ───────────────────────────────────────────

lord_validate_message(json) → 0 | 1 (+ sets LORD_VALIDATION_ERROR)

LORD_VALIDATION_ERROR=""

lord_validate_message() { local json="$1" LORD_VALIDATION_ERROR=""

# Champs obligatoires: type, story_id, timestamp local msg_type story_id timestamp msg_type=$(echo "$json" | jq -r '.type // empty' 2>/dev/null) || true story_id=$(echo "$json" | jq -r '.story_id // empty' 2>/dev/null) || true timestamp=$(echo "$json" | jq -r '.timestamp // empty' 2>/dev/null) || true

if [[ -z "$msg_type" ]]; then LORD_VALIDATION_ERROR="missing_field:type" return 1 fi if ! lord_validate_message_type "$msg_type"; then LORD_VALIDATION_ERROR="invalid_message_type:${msg_type}" return 1 fi if [[ -z "$story_id" ]]; then LORD_VALIDATION_ERROR="missing_field:story_id" return 1 fi if ! lord_validate_story_id "$story_id"; then LORD_VALIDATION_ERROR="invalid_story_id:${story_id}" return 1 fi if [[ -z "$timestamp" ]]; then LORD_VALIDATION_ERROR="missing_field:timestamp" return 1 fi if ! lord_validate_timestamp "$timestamp"; then LORD_VALIDATION_ERROR="invalid_timestamp:${timestamp}" return 1 fi

return 0 }

─── Logger de rejet (§6.1) ──────────────────────────────────────────────────

lord_log_rejection(timestamp, peer_id, message_type, reason, story_id, event)

lord_log_rejection() { local ts="$1" peer_id="$2" msg_type="$3" reason="$4" local story_id="${5:-}" event="${6:-rejection}" local log_file="${LORD_AUDIT_LOG:-.gov-lord-audit.jsonl}"

jq -n --arg ts "$ts" --arg peer_id "$peer_id" \ --arg msg_type "$msg_type" --arg reason "$reason" \ --arg story_id "$story_id" --arg event "$event" \ '{timestamp: $ts, level: "WARN", component: "validator", event: $event, peer_id: $peer_id, message_type: $msg_type, story_id: $story_id, reason: $reason}' \ >> "$log_file" }

succeeded in 1110ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

!/usr/bin/env bash

PD-293 — C5 Orchestrator : Logique métier One Ring

7 commandes, supervision, réconciliation, détection crash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

─── Sources ──────────────────────────────────────────────────────────────────

source "${SCRIPT_DIR}/lib/lord-state-machine.sh" source "${SCRIPT_DIR}/lib/lord-validator.sh" source "${SCRIPT_DIR}/lib/lord-broker.sh" source "${SCRIPT_DIR}/lib/lord-persistence.sh"

─── Configuration ────────────────────────────────────────────────────────────

LORD_MAX_RINGBEARERS="${LORD_MAX_RINGBEARERS:-5}" LORD_POLL_INTERVAL="${LORD_POLL_INTERVAL:-10}" LORD_CRASH_THRESHOLD="${LORD_CRASH_THRESHOLD:-2}" # missed polls before CRASHED CLAUDE_BIN="${CLAUDE_BIN:-/Users/loic/.local/bin/claude}"

─── INV-293-01 : Scope guard ────────────────────────────────────────────────

lord_assert_scope() { local command="$1" local allowed_commands="start|status|escalade|respond|pause|resume|stop" if [[ ! "$command" =~ ^(${allowed_commands})$ ]]; then echo "❌ Commande hors scope. Le One Ring est un routeur pur — il ne lit pas de code, ne modifie pas de fichier, n'accède pas aux services. Commandes disponibles: start, status, escalade, respond, pause, resume, stop" >&2 lord_audit "scope_violation" "-" "command=$command" return 1 fi }

─── Commands ─────────────────────────────────────────────────────────────────

lord_start(story_id, project_code, idempotency_key?)

lord_start() { local story_id="$1" project_code="$2" idempotency_key="${3:-}"

# Garde 1: format story_id if ! lord_validate_story_id "$story_id"; then echo "❌ story_id invalide: ${story_id} (format attendu: PD-NNN)" >&2 return 1 fi

# Garde 2: format project_code if ! lord_validate_project_code "$project_code"; then echo "❌ project_code invalide: ${project_code}" >&2 return 1 fi

# Garde 3: quota (INV-293-03) local active_count active_count=$(lord_count_active_stories) if [[ $active_count -ge $LORD_MAX_RINGBEARERS ]]; then echo "❌ Limite atteinte (${active_count}/${LORD_MAX_RINGBEARERS} Ringbearers actifs). Arrêtez un Ringbearer avant d'en créer un nouveau." >&2 return 1 fi

# Garde 4: doublon story_id local existing existing=$(lord_get_story "$story_id") if [[ -n "$existing" ]]; then local existing_state existing_state=$(echo "$existing" | jq -r '.state') if [[ "$(lord_is_terminal "$existing_state")" == "false" ]]; then echo "❌ ${story_id} a déjà un Ringbearer actif (état: ${existing_state})." >&2 return 1 fi fi

# Garde 5: idempotency if [[ -n "$idempotency_key" ]]; then local idem_result idem_result=$(lord_check_idempotency "$idempotency_key") if [[ "$idem_result" == "REPLAY" ]]; then echo "⏭️ Commande déjà traitée (idempotency: replay)." >&2 return 0 fi fi

# Créer la story en STARTING lord_create_story "$story_id" "$project_code" "STARTING" "pending-${story_id}" lord_audit "start" "$story_id" "project=${project_code}"

# Enregistrer idempotency if [[ -n "$idempotency_key" ]]; then lord_record_idempotency "$idempotency_key" "start" "$story_id" fi

echo "✅ Ringbearer ${story_id} créé (STARTING) — en attente de détection peer." }

lord_status(story_id?) — tableau de bord consolidé

lord_status() { local filter_story="${1:-}" local state state=$(lord_state_read) local peers peers=$(lord_broker_list_peers)

echo "┌─────────┬──────────────┬────────────┬───────────────────┬──────────┐" echo "│ Story │ Projet │ État │ Dernière activité │ Escalade │" echo "├─────────┼──────────────┼────────────┼───────────────────┼──────────┤"

echo "$state" | jq -r '.stories[] | "(.story_id)|(.project_code)|(.state)|(.last_seen_at)|(.escalades | [.[] | select(.status == "OPEN")] | length)"' 2>/dev/null | \ while IFS='|' read -r sid pc st last_seen esc_count; do if [[ -n "$filter_story" ]] && [[ "$sid" != "$filter_story" ]]; then continue fi local esc_flag="Non" [[ "$esc_count" -gt 0 ]] && esc_flag="Oui (${esc_count})" printf "│ %-7s │ %-12s │ %-10s │ %-17s │ %-8s │ " "$sid" "$pc" "$st" "${last_seen:0:17}" "$esc_flag" done

echo "└─────────┴──────────────┴────────────┴───────────────────┴──────────┘" }

lord_escalade(story_id?) — affichage file FIFO

lord_escalade() { local filter_story="${1:-}" local state state=$(lord_state_read)

echo "🚨 Escalades pendantes :" echo ""

local found=0 echo "$state" | jq -c '.stories[] | {sid: .story_id, esc: [.escalades[] | select(.status == "OPEN")]}' 2>/dev/null | \ while IFS= read -r entry; do local sid sid=$(echo "$entry" | jq -r '.sid') if [[ -n "$filter_story" ]] && [[ "$sid" != "$filter_story" ]]; then continue fi echo "$entry" | jq -r '.esc[] | " [(.id)] (.sid // empty) — (.text) (depuis (.created_at))"' 2>/dev/null found=1 done

if [[ $found -eq 0 ]]; then echo " Aucune escalade pendante." fi }

lord_respond(story_id, response_text, idempotency_key?)

lord_respond() { local story_id="$1" response_text="$2" idempotency_key="${3:-}"

if ! lord_validate_story_id "$story_id"; then echo "❌ story_id invalide: ${story_id}" >&2 return 1 fi

local story story=$(lord_get_story "$story_id") if [[ -z "$story" ]]; then echo "❌ Aucun Ringbearer actif pour ${story_id}." >&2 return 1 fi

local open_count open_count=$(lord_count_open_escalades "$story_id") if [[ "$open_count" -eq 0 ]]; then echo "❌ Aucune escalade pendante pour ${story_id}." >&2 return 1 fi

# Déqueue oldest + send PO_RESPONSE local escalade_id escalade_id=$(lord_dequeue_oldest_escalade "$story_id")

local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local peer_id peer_id=$(echo "$story" | jq -r '.peer_id')

local message message=$(jq -n --arg type "PO_RESPONSE" --arg sid "$story_id" \ --arg text "$response_text" --arg ts "$ts" \ '{type: $type, story_id: $sid, response: $text, timestamp: $ts}')

lord_broker_send_message "$peer_id" "$message"

# Transition si plus d'escalades ouvertes local remaining remaining=$(lord_count_open_escalades "$story_id") if [[ "$remaining" -eq 0 ]]; then lord_update_story "$story_id" '.state = "RUNNING"' fi

lord_audit "respond" "$story_id" "escalade_id=${escalade_id}" echo "✅ Réponse transmise à ${story_id}." }

lord_pause(story_id, reason?, idempotency_key?)

lord_pause() { local story_id="$1" reason="${2:-}" idempotency_key="${3:-}"

local story story=$(lord_get_story "$story_id") local current_state current_state=$(echo "$story" | jq -r '.state')

local result result=$(lord_transition "$story_id" "$current_state" "PAUSED") || true if [[ "$result" != "OK" ]]; then echo "❌ Impossible de mettre en pause ${story_id} (état: ${current_state}): ${result}" >&2 return 1 fi

lord_update_story "$story_id" '.state = "PAUSED"'

local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local peer_id peer_id=$(echo "$story" | jq -r '.peer_id') local message message=$(jq -n --arg type "PAUSE" --arg sid "$story_id" \ --arg reason "$reason" --arg ts "$ts" \ '{type: $type, story_id: $sid, reason: $reason, timestamp: $ts}') lord_broker_send_message "$peer_id" "$message"

lord_audit "pause" "$story_id" "reason=${reason}" echo "⏸️ ${story_id} mis en pause." }

lord_resume(story_id, idempotency_key?)

lord_resume() { local story_id="$1" idempotency_key="${2:-}"

local story story=$(lord_get_story "$story_id") local current_state current_state=$(echo "$story" | jq -r '.state')

local result result=$(lord_transition "$story_id" "$current_state" "RUNNING") || true if [[ "$result" != "OK" ]]; then echo "❌ Impossible de reprendre ${story_id} (état: ${current_state}): ${result}" >&2 return 1 fi

lord_update_story "$story_id" '.state = "RUNNING"'

local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local peer_id peer_id=$(echo "$story" | jq -r '.peer_id') local message message=$(jq -n --arg type "RESUME" --arg sid "$story_id" --arg ts "$ts" \ '{type: $type, story_id: $sid, timestamp: $ts}') lord_broker_send_message "$peer_id" "$message"

lord_audit "resume" "$story_id" "" echo "▶️ ${story_id} repris." }

lord_stop(story_id, reason?, idempotency_key?)

lord_stop() { local story_id="$1" reason="${2:-PO decision}" idempotency_key="${3:-}"

local story

succeeded in 1122ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

!/usr/bin/env bash

PD-293 — C1 State Machine : FSM Ringbearer (§5.2)

Matrice de transitions contractuelle — 8 états, 4 terminaux

Implémentation case/esac pour compatibilité bats

lord_is_valid_state(state) → 0 | 1

lord_is_valid_state() { case "$1" in STARTING|RUNNING|ESCALADED|PAUSED|DONE|ABORTED|CRASHED|START_FAILED) return 0 ;; *) return 1 ;; esac }

lord_is_terminal(state) → "true" | "false"

lord_is_terminal() { case "$1" in DONE|ABORTED|CRASHED|START_FAILED) echo "true" ;; *) echo "false" ;; esac }

lord_allowed_transitions(from_state) → space-separated list of to_states

lord_allowed_transitions() { case "$1" in STARTING) echo "RUNNING START_FAILED" ;; RUNNING) echo "ESCALADED PAUSED DONE ABORTED CRASHED" ;; ESCALADED) echo "RUNNING ABORTED CRASHED" ;; PAUSED) echo "RUNNING ABORTED CRASHED" ;; *) echo "" ;; esac }

lord_transition(story_id, from_state, to_state) → "OK" | "REJECTED:reason"

lord_transition() { local story_id="$1" from_state="$2" to_state="$3"

# Vérifier que les états sont valides if ! lord_is_valid_state "$from_state"; then echo "REJECTED:invalid_from_state:${from_state}" return 1 fi if ! lord_is_valid_state "$to_state"; then echo "REJECTED:invalid_to_state:${to_state}" return 1 fi

# Vérifier que from_state n'est pas terminal if [[ "$(lord_is_terminal "$from_state")" == "true" ]]; then echo "REJECTED:terminal_state:${from_state}" return 1 fi

# Vérifier que la transition est autorisée local allowed allowed=$(lord_allowed_transitions "$from_state") for target in $allowed; do if [[ "$target" == "$to_state" ]]; then echo "OK" return 0 fi done

echo "REJECTED:forbidden_transition:${from_state}→${to_state}" return 1 }

succeeded in 1126ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

PD-293 — Acceptabilité

Prérequis acceptabilité

  • Tests CI : 45/45 bats tests passent (FSM + validator)
  • Coverage : N/A (shell scripts — pas de framework coverage bash)
  • TODO non tracés : aucun
  • Code DEV ONLY : aucun

Analyse Sonar

  • Quality Gate : N/A (shell scripts, pas de sonar-project.properties)
  • Justification : story tooling (scripts bash), pas de code applicatif NestJS/React

Phase 1 — Reviews automatisées

Check Résultat
bats tests (FSM) ✅ 21/21
bats tests (validator) ✅ 24/24
shellcheck N/A (non configuré)
Total 45/45 OK

Phase 2 — Reviews LLM (Codex gpt-5.3-codex)

Review Code (développeur senior)

Verdict : REJETÉ → puis corrigé Écarts bloquants initiaux : 1. Deux fichiers code-contracts concurrents (code-contracts.yaml + PD-293-code-contracts.yaml) → Corrigé : fichier unique aligné sur l'implémentation réelle 2. Noms de fichiers divergents (contracts: lord-fsm.sh vs implémentation: lord-state-machine.sh) → Corrigé : contracts réalignés

Écarts résiduels (réserves) : - INV-293-02 : diagrammes séquence montrent flèches directes O→R (raccourci visuel, tout passe par broker en réalité) - INV-293-05 : timestamp Z strict dans code vs spec autorisant offsets — décision H-TECH-08 documentée - Multi-escalade : départage timestamps égaux non explicité (mineur en v1 local)

Review Tests (QA engineer)

Verdict : RÉSERVES - Couverture C1 (FSM) et C2 (validator) solide - C3 (broker), C4 (persistence), C5 (orchestrator) sans tests unitaires dédiés - Recommandation : ajouter tests persistence + orchestrator en v2

Review Sécurité (pentester adversarial)

Verdict : RÉSERVES - INV-293-01 (scope guard) correctement implémenté via whitelist case/esac - Pas de secrets dans le code - Audit JSONL ne stocke jamais d'escalade_text (RGPD OK) - Réserves : pas de signature/MAC sur les messages broker (acceptable en v1 localhost)

Synthèse

Critère Statut
Tests ✅ 45/45
Invariants vérifiés 12/14 PASS, 2 avec réserves (INV-293-02, INV-293-05)
Code contracts ✅ Alignés (fichier unique)
Sécurité ✅ Avec réserves (localhost v1)
Documentation ✅ Besoin, spec, tests, plan, decomposition, reviews

Verdict global : ACCEPTÉ AVEC RÉSERVES — prêt pour Gate 8.

exec /bin/zsh -lc "sed -n '261,520p' scripts/gov-lord.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 657ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable story=$(lord_get_story "$story_id") if [[ -z "$story" ]]; then echo "❌ Aucun Ringbearer actif pour ${story_id}." >&2 return 1 fi

local current_state current_state=$(echo "$story" | jq -r '.state')

local result result=$(lord_transition "$story_id" "$current_state" "ABORTED") || true if [[ "$result" != "OK" ]]; then echo "❌ Impossible d'arrêter ${story_id} (état: ${current_state}): ${result}" >&2 return 1 fi

lord_update_story "$story_id" '.state = "ABORTED"'

local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local peer_id peer_id=$(echo "$story" | jq -r '.peer_id') local message message=$(jq -n --arg type "ABORT" --arg sid "$story_id" \ --arg reason "$reason" --arg ts "$ts" \ '{type: $type, story_id: $sid, reason: $reason, timestamp: $ts}') lord_broker_send_message "$peer_id" "$message"

lord_audit "stop" "$story_id" "reason=${reason}" echo "🛑 ${story_id} arrêté (ABORTED)." }

─── Supervision loop ────────────────────────────────────────────────────────

lord_supervision_cycle() — un cycle de polling

lord_supervision_cycle() { local peers peers=$(lord_broker_list_peers) lord_broker_update_peers_cache "$peers"

local state state=$(lord_state_read)

# Pour chaque story non-terminale echo "$state" | jq -c '.stories[] | select(.state != "DONE" and .state != "ABORTED" and .state != "CRASHED" and .state != "START_FAILED")' 2>/dev/null | \ while IFS= read -r story_json; do local sid peer_id current_state sid=$(echo "$story_json" | jq -r '.story_id') peer_id=$(echo "$story_json" | jq -r '.peer_id') current_state=$(echo "$story_json" | jq -r '.state')

# Vérifier si le peer est présent
local peer_alive
peer_alive=$(echo "$peers" | jq --arg pid "$peer_id" '[.[] | select(.id == $pid)] | length' 2>/dev/null || echo 0)

if [[ "$peer_alive" -eq 0 ]] && [[ "$current_state" != "STARTING" ]]; then
  # Incrémenter missed_polls
  local missed
  missed=$(echo "$story_json" | jq -r '.missed_polls // 0')
  missed=$((missed + 1))
  lord_update_story "$sid" ".missed_polls = ${missed}"

  if [[ $missed -ge $LORD_CRASH_THRESHOLD ]]; then
    lord_update_story "$sid" '.state = "CRASHED"'
    lord_audit "crash_detected" "$sid" "missed_polls=${missed}"
    echo "🚨 CRASH détecté — Ringbearer ${sid} disparu (${missed} polls manqués)" >&2
  fi
else
  # Reset missed_polls + update last_seen
  local ts
  ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  lord_update_story "$sid" ".missed_polls = 0 | .last_seen_at = \"${ts}\""
fi

done

# Purge idempotency expirée lord_purge_expired_idempotency >/dev/null 2>&1 }

lord_supervision_loop() — boucle infinie (trap-safe)

lord_supervision_loop() { echo "🔄 Supervision démarrée (intervalle: ${LORD_POLL_INTERVAL}s, crash threshold: ${LORD_CRASH_THRESHOLD} polls)"

while true; do lord_supervision_cycle sleep "${LORD_POLL_INTERVAL}" & wait $! 2>/dev/null || break # trap-safe done }

─── CLI ──────────────────────────────────────────────────────────────────────

lord_main() { local command="${1:-help}" shift || true

lord_assert_scope "$command" || return 1

case "$command" in start) lord_start "${1:-}" "${2:-}" "${3:-}" ;; status) lord_status "${1:-}" ;; escalade) lord_escalade "${1:-}" ;; respond) lord_respond "${1:-}" "${2:-}" "${3:-}" ;; pause) lord_pause "${1:-}" "${2:-}" "${3:-}" ;; resume) lord_resume "${1:-}" "${2:-}" ;; stop) lord_stop "${1:-}" "${2:-}" "${3:-}" ;; *) echo "Usage: gov-lord.sh [args...]" ;; esac }

Exécution si appelé directement (pas sourcé)

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then lord_main "$@" fi

exec /bin/zsh -lc "ls -la tests/lord && echo '---' && sed -n '1,260p' tests/lord/test-state-machine.bats && echo '---' && sed -n '1,300p' tests/lord/test-validator.bats" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 719ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable total 24 drwxr-xr-x@ 4 loic staff 128 Mar 31 00:55 . drwxr-xr-x@ 4 loic staff 128 Mar 31 00:50 .. -rw-r--r--@ 1 loic staff 4089 Mar 31 00:55 test-state-machine.bats -rw-r--r--@ 1 loic staff 4414 Mar 31 00:55 test-validator.bats


!/usr/bin/env bats

PD-293 — Tests C1 State Machine (TC-INV-01, TC-INV-02)

setup() { source "${BATS_TEST_DIRNAME}/../../scripts/lib/lord-state-machine.sh" }

─── TC-INV-01 : Matrice exhaustive transitions autorisées ────────────────────

@test "STARTING → RUNNING is allowed" { result=$(lord_transition "PD-1" "STARTING" "RUNNING") [[ "$result" == "OK" ]] }

@test "STARTING → START_FAILED is allowed" { result=$(lord_transition "PD-1" "STARTING" "START_FAILED") [[ "$result" == "OK" ]] }

@test "STARTING → DONE is rejected" { run lord_transition "PD-1" "STARTING" "DONE" [[ "$output" == "REJECTED" ]] }

@test "RUNNING → ESCALADED is allowed" { result=$(lord_transition "PD-1" "RUNNING" "ESCALADED") [[ "$result" == "OK" ]] }

@test "RUNNING → PAUSED is allowed" { result=$(lord_transition "PD-1" "RUNNING" "PAUSED") [[ "$result" == "OK" ]] }

@test "RUNNING → DONE is allowed" { result=$(lord_transition "PD-1" "RUNNING" "DONE") [[ "$result" == "OK" ]] }

@test "RUNNING → ABORTED is allowed" { result=$(lord_transition "PD-1" "RUNNING" "ABORTED") [[ "$result" == "OK" ]] }

@test "RUNNING → CRASHED is allowed" { result=$(lord_transition "PD-1" "RUNNING" "CRASHED") [[ "$result" == "OK" ]] }

@test "ESCALADED → RUNNING is allowed" { result=$(lord_transition "PD-1" "ESCALADED" "RUNNING") [[ "$result" == "OK" ]] }

@test "ESCALADED → ABORTED is allowed" { result=$(lord_transition "PD-1" "ESCALADED" "ABORTED") [[ "$result" == "OK" ]] }

@test "ESCALADED → CRASHED is allowed" { result=$(lord_transition "PD-1" "ESCALADED" "CRASHED") [[ "$result" == "OK" ]] }

@test "PAUSED → RUNNING is allowed" { result=$(lord_transition "PD-1" "PAUSED" "RUNNING") [[ "$result" == "OK" ]] }

@test "PAUSED → ABORTED is allowed" { result=$(lord_transition "PD-1" "PAUSED" "ABORTED") [[ "$result" == "OK" ]] }

@test "PAUSED → CRASHED is allowed" { result=$(lord_transition "PD-1" "PAUSED" "CRASHED") [[ "$result" == "OK" ]] }

─── TC-INV-02 : États terminaux immuables ────────────────────────────────────

@test "DONE rejects all transitions" { for target in STARTING RUNNING ESCALADED PAUSED DONE ABORTED CRASHED START_FAILED; do run lord_transition "PD-1" "DONE" "$target" [[ "$output" == "REJECTED:terminal_state" ]] done }

@test "ABORTED rejects all transitions" { for target in STARTING RUNNING ESCALADED PAUSED DONE ABORTED CRASHED START_FAILED; do run lord_transition "PD-1" "ABORTED" "$target" [[ "$output" == "REJECTED:terminal_state" ]] done }

@test "CRASHED rejects all transitions" { for target in STARTING RUNNING ESCALADED PAUSED DONE ABORTED CRASHED START_FAILED; do run lord_transition "PD-1" "CRASHED" "$target" [[ "$output" == "REJECTED:terminal_state" ]] done }

@test "START_FAILED rejects all transitions" { for target in STARTING RUNNING ESCALADED PAUSED DONE ABORTED CRASHED START_FAILED; do run lord_transition "PD-1" "START_FAILED" "$target" [[ "$output" == "REJECTED:terminal_state" ]] done }

─── Helpers ──────────────────────────────────────────────────────────────────

@test "lord_is_terminal returns true for terminal states" { [[ "$(lord_is_terminal "DONE")" == "true" ]] [[ "$(lord_is_terminal "ABORTED")" == "true" ]] [[ "$(lord_is_terminal "CRASHED")" == "true" ]] [[ "$(lord_is_terminal "START_FAILED")" == "true" ]] }

@test "lord_is_terminal returns false for non-terminal states" { [[ "$(lord_is_terminal "STARTING")" == "false" ]] [[ "$(lord_is_terminal "RUNNING")" == "false" ]] [[ "$(lord_is_terminal "ESCALADED")" == "false" ]] [[ "$(lord_is_terminal "PAUSED")" == "false" ]] }

@test "Invalid state is rejected" { run lord_transition "PD-1" "RUNNING" "INVALID" [[ "$output" == "REJECTED:invalid_to_state" ]] }


!/usr/bin/env bats

PD-293 — Tests C2 Validator (TC-NOM-10, TC-NEG-01..10)

setup() { source "${BATS_TEST_DIRNAME}/../../scripts/lib/lord-validator.sh" }

─── TC-NOM-10 : Validation story_id ─────────────────────────────────────────

@test "PD-1 is valid story_id" { lord_validate_story_id "PD-1" }

@test "PD-293 is valid story_id" { lord_validate_story_id "PD-293" }

@test "PD-1234 is valid story_id" { lord_validate_story_id "PD-1234" }

─── TC-NEG-01 : Mauvaise casse story_id ─────────────────────────────────────

@test "pd-293 is rejected (lowercase)" { run lord_validate_story_id "pd-293" [[ "$status" -ne 0 ]] }

@test "Pd-293 is rejected (mixed case)" { run lord_validate_story_id "Pd-293" [[ "$status" -ne 0 ]] }

─── TC-NEG-02 : story_id trop long ──────────────────────────────────────────

@test "PD-12345 is rejected (5 digits)" { run lord_validate_story_id "PD-12345" [[ "$status" -ne 0 ]] }

─── TC-NEG-03 : story_id vide ───────────────────────────────────────────────

@test "Empty story_id is rejected" { run lord_validate_story_id "" [[ "$status" -ne 0 ]] }

─── Project code validation ─────────────────────────────────────────────────

@test "backend is valid project_code" { lord_validate_project_code "backend" }

@test "ia-governance is valid project_code" { lord_validate_project_code "ia-governance" }

@test "pixel-governance is valid project_code" { lord_validate_project_code "pixel-governance" }

@test "invalid-project is rejected" { run lord_validate_project_code "invalid-project" [[ "$status" -ne 0 ]] }

@test "ia-gov is rejected (abbreviated)" { run lord_validate_project_code "ia-gov" [[ "$status" -ne 0 ]] }

─── Message type validation ─────────────────────────────────────────────────

@test "STATUS_UPDATE is valid message_type" { lord_validate_message_type "STATUS_UPDATE" }

@test "ESCALADE is valid message_type" { lord_validate_message_type "ESCALADE" }

@test "UNKNOWN is rejected" { run lord_validate_message_type "UNKNOWN" [[ "$status" -ne 0 ]] }

─── Timestamp validation (H-TECH-08 : Z only) ──────────────────────────────

@test "UTC Z timestamp is valid" { lord_validate_timestamp "2026-03-30T14:22:00Z" }

@test "UTC Z with milliseconds is valid" { lord_validate_timestamp "2026-03-30T14:22:00.123Z" }

@test "Offset timestamp is rejected" { run lord_validate_timestamp "2026-03-30T14:22:00+02:00" [[ "$status" -ne 0 ]] }

@test "Missing Z is rejected" { run lord_validate_timestamp "2026-03-30T14:22:00" [[ "$status" -ne 0 ]] }

─── Message validation ──────────────────────────────────────────────────────

@test "Valid complete message passes validation" { local msg='{"type":"STATUS_UPDATE","story_id":"PD-293","timestamp":"2026-03-30T14:22:00Z"}' lord_validate_message "$msg" }

@test "Message missing type is rejected" { local msg='{"story_id":"PD-293","timestamp":"2026-03-30T14:22:00Z"}' run lord_validate_message "$msg" [[ "$status" -ne 0 ]] [[ "$LORD_VALIDATION_ERROR" == "missing_field:type" ]] || true }

@test "Message with invalid story_id is rejected" { local msg='{"type":"STATUS_UPDATE","story_id":"invalid","timestamp":"2026-03-30T14:22:00Z"}' run lord_validate_message "$msg" [[ "$status" -ne 0 ]] }

─── Idempotency key validation ──────────────────────────────────────────────

@test "Valid idempotency key passes" { lord_validate_idempotency_key "start:PD-293:1711814520" }

@test "Short key is rejected (< 16 chars)" { run lord_validate_idempotency_key "short" [[ "$status" -ne 0 ]] }

exec /bin/zsh -lc "rg --files tests | rg 'lord|gov-lord|broker|persistence|orchestrator|PD-293|bats'" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 683ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable tests/lord/test-validator.bats tests/lord/test-state-machine.bats

codex Je confirme pour l’instant qu’il n’existe toujours que 2 suites Bats (state-machine et validator) dans tests/lord. Je lance maintenant l’exécution des tests pour obtenir une preuve factuelle de statut, puis je mappe chaque écart existant à ces résultats et au code. exec /bin/zsh -lc 'bats tests/lord/test-state-machine.bats tests/lord/test-validator.bats' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exited 127 in 654ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable zsh:1: command not found: bats

exec /bin/zsh -lc 'rg -n "45/45|TC-|PASS|bats|INV-293-02|INV-293-05|H-TECH-08|multi-escalade|broker|persistence|orchestrator" docs/epics/tooling/PD-293-one-ring-orchestration/.md' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 664ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:5:- [x] Tests CI : 45/45 bats tests passent (FSM + validator) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:19:| bats tests (FSM) | ✅ 21/21 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:20:| bats tests (validator) | ✅ 24/24 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:22:| Total | 45/45 OK | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:34:- INV-293-02 : diagrammes séquence montrent flèches directes O→R (raccourci visuel, tout passe par broker en réalité) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:35:- INV-293-05 : timestamp Z strict dans code vs spec autorisant offsets — décision H-TECH-08 documentée docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:42:- C3 (broker), C4 (persistence), C5 (orchestrator) sans tests unitaires dédiés docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:43:- Recommandation : ajouter tests persistence + orchestrator en v2 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:51:- Réserves : pas de signature/MAC sur les messages broker (acceptable en v1 localhost) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:57:| Tests | ✅ 45/45 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:58:| Invariants vérifiés | 12/14 PASS, 2 avec réserves (INV-293-02, INV-293-05) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:14:- La machine d'etats v1 est coherente entre documents: etats officiels identiques (STARTING, RUNNING, ESCALADED, PAUSED, DONE, ABORTED, CRASHED, START_FAILED), transitions interdites testees via TC-INV-01, terminaux verrouilles via TC-INV-02. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:15:- Les regles de capacite, idempotence et ordre des gardes sont alignees: limite 5 (TC-NOM-02, TC-ERR-01), dedoublonnage/idempotence (TC-NOM-08, TC-ERR-08, TC-ERR-11), ordre quota -> doublon -> format pour start (TC-INV-03). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:16:- La gestion des escalades est convergente: blocage jusqu'a PO_RESPONSE (TC-NOM-03, TC-ERR-04), FIFO multi-escalades sans remplacement (TC-NOM-13), visibilite SLA P95 (TC-NOM-04). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:17:- La resilience broker/peer est coherente: crash detecte en <=2 cycles (TC-NOM-06, TC-ERR-07), mode degrade + reconnexion bornee + reconciliation (TC-ERR-10, TC-NOM-07). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:18:- Le perimetre One Ring (pas d'execution metier/projet, pas d'acces direct repos, non-regression /gov) est aligne avec les tests nominaux/erreur/non-regression (TC-NOM-05, TC-ERR-05, TC-NR-01, TC-NR-02, TC-NR-03). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:29:- Disponibilite exacte et limites de /remote-control sur iPhone/Safari restent ouvertes (Q-293-01), avec CA-06 couvert uniquement par test manuel (TC-MAN-01). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:30:- Format normatif detaille de peer_id cote broker reste partiellement ouvert au-dela du contrat actuel (Q-293-02), ce qui limite l'assertion d'interoperabilite fine. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:13:Description : INV-293-07 déclare « Le workflow /gov est consommé tel quel ; PD-293 ne modifie pas son comportement interne ». Or le protocole §5.1 exige que le Ringbearer émette des messages typés (STATUS_UPDATE, ESCALADE, GATE_RESULT, WORKFLOW_DONE) via le broker. Le workflow /gov actuel ne produit aucun de ces messages. H-293-04 reconnaît cette tension ("Le protocole messages requis est supporté par les peers sans adaptation de /gov") mais la formule comme hypothèse alors qu'elle contredit directement INV-293-07. Soit /gov doit être adapté (violation INV-293-07), soit un composant intermédiaire (wrapper, hook, intercepteur) doit exister — et ce composant n'est spécifié nulle part. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:23:Description : Le schema §5.4 déclare peer_id comme required avec minLength: 1 pour chaque entrée story. Or en état STARTING, le peer n'est pas encore enregistré au broker — le peer_id est inconnu. Le schema ne permet ni null ni chaîne vide pour ce champ, rendant impossible la persistance d'une story en STARTING sans violer le schema. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:32:Référence : §5.1 (règles globales normatives, point 3), ERR-293-02, TC-ERR-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:33:Description : L'ordre contractuel des gardes pour start est défini comme « quota → doublon idempotence → validation format complète » (§5.1 point 3). ERR-293-02 spécifie le rejet d'un start sur une story déjà active. Or cette vérification n'apparaît dans aucune position de l'ordre des gardes. TC-ERR-02 teste ce cas avec une clé différente, ce qui signifie que la garde idempotence ne le couvre pas (clé nouvelle = pas de doublon). La garde "story déjà active" est un 4e contrôle non positionné dans l'ordre contractuel. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:43:Description : Le diagramme de séquence montre O->>R: demande démarrage story_id=PD-293. Ce message n'a pas de message_type correspondant dans l'enum §5.1 (STATUS_UPDATE|ESCALADE|GATE_RESULT|WORKFLOW_DONE|PO_RESPONSE|PAUSE|RESUME|ABORT). Le mécanisme exact par lequel One Ring crée/lance un Ringbearer n'est pas spécifié : est-ce un fork de process, un appel CLI (claude --session), un message broker ? De même, les messages PAUSE et RESUME envoyés de O vers R dans le diagramme sont des message_type mais leur payload n'est pas documenté (quels champs obligatoires ?). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:52:Référence : INV-293-11, TC-NOM-07 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:53:Description : INV-293-11 exige une « réconciliation périodique obligatoire » mais aucun paramètre ne définit l'intervalle de réconciliation. Est-ce à chaque cycle de polling (peer_poll_interval) ? À un multiple ? Sur demande ? Le tableau §5.1 des paramètres numériques ne contient aucun reconciliation_interval. TC-NOM-07 teste la réconciliation comme un événement déclenché, sans valider la périodicité. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:69:### 7. Champ current_escalade_id vs modèle multi-escalade FIFO docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:104:### 10. Pas de test pour la stratégie de reconnexion broker (timings) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:107:Référence : §5.3 step 10 (backoff 1s,2s,4s,8s,10s), TC-ERR-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:108:Description : §5.3 spécifie une stratégie de reconnexion « exponentielle bornée (1s, 2s, 4s, 8s, 10s max) ». TC-ERR-10 vérifie le mode dégradé et la reprise automatique, mais ne valide pas les intervalles de retry ni le plafond à 10s. Un test de non-régression devrait vérifier la séquence exacte de backoff. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:117:Référence : §5.1, §5.3, INV-293-02, INV-293-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:118:Description : Le protocole de messagerie ne spécifie aucun mécanisme d'authentification entre One Ring, Ringbearers et broker. Tout processus local capable d'appeler claude-peers-mcp pourrait : (a) s'enregistrer comme un Ringbearer factice, (b) injecter des messages WORKFLOW_DONE ou ESCALADE usurpés, © émettre de faux STATUS_UPDATE pour maintenir un peer fantôme en vie. La validation §5.1 porte sur le format des messages, pas sur l'identité de l'émetteur. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:127:Référence : §6.1 (format JSONL), INV-293-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:138:Description : H-293-04 postule que « le protocole messages requis est supporté par les peers sans adaptation de /gov ». C'est une hypothèse structurellement dangereuse car : (1) /gov actuel n'émet pas de messages broker, (2) la spec exige des messages typés (ESCALADE, GATE_RESULT, etc.) en provenance du Ringbearer, (3) "impact si faux" = "nécessité d'une story séparée de compatibilité", ce qui invaliderait le périmètre de PD-293 lui-même. Cette hypothèse devrait être vérifiée avant Gate 5, pas traitée comme risque résiduel. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3-v2.md:148:Description : Le diagramme d'état et la machine d'états §5.2 ne prévoient pas de transition STARTING→CRASHED. Si le peer s'enregistre au broker puis disparaît immédiatement (avant la première liveness), le seul chemin est first_liveness_timeout → START_FAILED. Cependant, le mécanisme de crash detection (absence peer > 2 cycles) s'applique-t-il aussi en état STARTING ? §5.2 STARTING ne liste que RUNNING et START_FAILED comme transitions sortantes, ce qui est cohérent. Mais cela signifie que la supervision crash (INV-293-08) ne s'applique qu'à partir de RUNNING — ce qui n'est pas explicité. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step5.md:25:2. TC-NOM-14 mentionné dans le plan mais absent du document tests docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step5.md:39:- TC-NOM-14 absent → MAJEUR (à ajouter dans le document tests) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step5.md:46:| coverage | 7.0 | Bon mapping invariants→mécanismes dans le plan, mais TC-NOM-14 absent, section contraintes techniques manquante | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step3.md:32:| ÉCART-10 | AMB | MINEUR | Comportement reconnexion broker après crash non spécifié | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step3.md:38:| ÉCART-16 | AMB | MAJEUR | Comportement multi-escalade simultanée (file vs remplacement) non spécifié | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:21:- Limite 5 Ringbearers : Unanime (spec INV-293-04, tests TC-NOM-02/TC-ERR-01, plan §2.1 garde 1, contracts count_active_stories). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:25:- Broker comme unique canal : INV-293-02 respecté dans le plan (C3 unique point de contact) et les contracts. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:27:- Crash detection ≤ 2 cycles : INV-293-08 implémenté via missed_polls dans le plan, testé par TC-NOM-06/TC-ERR-07. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:41:- Plan (§1) : scripts/lib/lord-persistence.sh docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:49:- Plan : 7 composants (C1-C7) avec C4=persistence (regroupe état+logs+FIFO+idempotency) et C5=orchestrator (regroupe commandes+supervision+réconciliation). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:59:- Plan H-TECH-08 : strictement Z uniquement. Tout offset non-zero est rejeté. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:61:- Code contracts intégrés au plan (validator) : seul le suffixe Z est accepté (décision H-TECH-08). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:79:- Code contracts intégrés au plan (persistence) : confirme racine du repo. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:89:- Impact : Les logs de rejet auront un format différent selon le contrat suivi. Affecte la testabilité de TC-ERR-03 et l'auditabilité. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:95:- Plan : toutes les interfaces sont préfixées lord_ (ex: lord_transition(), lord_validate_story_id(), lord_broker_list_peers()). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:96:- Code contracts standalone : interfaces non préfixées pour certains modules (ex: transition(), validate_story_id(), broker_list_peers()). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:102:DIV-08 : Test TC-NOM-14 — ajouté dans le plan mais absent du document tests docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:104:- Plan §5 : TC-NOM-14 (ajouté) couvre CA-02 (démarrage nominal complet jusqu'à RUNNING). Détaillé avec mécanismes et observables. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:105:- Document tests : TC-NOM-14 n'existe pas. La matrice de couverture mappe CA-02 à TC-NOM-08 (idempotence). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:106:- Spec §8 : TC-NOM-14 absent des scénarios Given/When/Then. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:121:- Plan C4 interfaces : lord_count_open_escalades(story_id) -> integer — utilisée pour la logique multi-escalade (transition ESCALADED→RUNNING uniquement quand toutes les OPEN sont traitées). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:123:- Impact : La logique multi-escalade du plan §2.2 nécessite cette interface. Sans elle, l'invariant INV-293-13 est implémentable mais la transition retour ESCALADED→RUNNING manque de précision contractuelle. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:132:- Impact : Un champ du modèle canonique ne serait pas validé. Faible en pratique (le Ringbearer émet les summary_text), mais c'est une violation de INV-293-05 ("tout message doit être validé selon §5.1"). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:138:ZO-02 : Mécanisme exact d'interaction avec claude-peers-mcp. Le plan mentionne C3 comme couche d'abstraction, mais le risque R2 (§9.1) signale que le Ringbearer "ne produit pas de STATUS_UPDATE (protocole non natif dans /gov)". La spec H-293-04 pose la même hypothèse. Aucun des 4 documents ne décrit comment le Ringbearer émet des messages au broker. Le workflow /gov existant ne connaît pas claude-peers-mcp. Si cette hypothèse est fausse, le système entier est bloqué (STARTING→START_FAILED systématique). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:142:ZO-04 : Test E2E TC-NR-01 — le plan et les tests le déclarent obligatoire (baseline /gov standalone vs orchestré), mais aucun document ne décrit la procédure concrète pour exécuter une story complète /gov dans un contexte de test contrôlé. Durée estimée ? Story de test ? Mock des gates ? docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:146:ZO-06 : Format d'export probatoire TC-NOM-04. Le test exige un "export probatoire" des 100 mesures SLA P95. Aucun document ne définit le format exact de cet export (CSV ? JSONL ? champs ?) ni sa localisation. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:168:- ZO-02 (émission messages par Ringbearer) : Si le Ringbearer ne peut pas émettre de STATUS_UPDATE via le broker, le système est non fonctionnel. Le risque R2 du plan identifie le problème mais ne le résout pas. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan-review.md:17:| Test irrealisable | CA-02, TC-NOM-14 (mentionne dans plan) / Tests PD-293-tests.md | Le plan annonce "TC-NOM-14 ajoute", mais ce test n'existe pas dans le document de tests contractuels fourni. | La preuve contractuelle du demarrage nominal CA-02 reste non etablissable de facon deterministe. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan-review.md:18:| Test irrealisable | TC-NOM-01..TC-ERR-11, TC-INV-01..03, TC-MAN-01 / Plan PD-293-plan.md | Aucun point d'observabilite explicite par scenario de test n'est present dans l'artefact plan fourni. | Les scenarios ne sont pas executables/auditables a partir du plan comme document contractuel. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan-review.md:24:| Contrainte technique non documentee | Plan PD-293-plan.md (section "Contraintes techniques" absente) | Le framework de test Jest/Vitest n'est pas explicite; le code contract mentionne bats-core, sans decision contractuelle explicite au niveau plan. | Ambiguite de runner de test au regard de la contrainte documentaire demandee. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan-review.md:31:- Points critiques : artefact plan non auditable (contenu manquant), couverture invariants non prouvable, executabilite des tests non demontree, ecart CA-02/TC-NOM-14 non resolu dans les tests fournis. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:14:- La machine d'etats v1 est coherente entre documents: etats officiels identiques (STARTING, RUNNING, ESCALADED, PAUSED, DONE, ABORTED, CRASHED, START_FAILED), transitions interdites testees via TC-INV-01, terminaux verrouilles via TC-INV-02. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:15:- Les regles de capacite, idempotence et ordre des gardes sont alignees: limite 5 (TC-NOM-02, TC-ERR-01), dedoublonnage/idempotence (TC-NOM-08, TC-ERR-08, TC-ERR-11), ordre quota -> doublon -> format pour start (TC-INV-03). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:16:- La gestion des escalades est convergente: blocage jusqu'a PO_RESPONSE (TC-NOM-03, TC-ERR-04), FIFO multi-escalades sans remplacement (TC-NOM-13), visibilite SLA P95 (TC-NOM-04). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:17:- La resilience broker/peer est coherente: crash detecte en <=2 cycles (TC-NOM-06, TC-ERR-07), mode degrade + reconnexion bornee + reconciliation (TC-ERR-10, TC-NOM-07). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:18:- Le perimetre One Ring (pas d'execution metier/projet, pas d'acces direct repos, non-regression /gov) est aligne avec les tests nominaux/erreur/non-regression (TC-NOM-05, TC-ERR-05, TC-NR-01, TC-NR-02, TC-NR-03). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:29:- Disponibilite exacte et limites de /remote-control sur iPhone/Safari restent ouvertes (Q-293-01), avec CA-06 couvert uniquement par test manuel (TC-MAN-01). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:30:- Format normatif detaille de peer_id cote broker reste partiellement ouvert au-dela du contrat actuel (Q-293-02), ce qui limite l'assertion d'interoperabilite fine. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-dossier-conformite-step3-v2.md:41:| clarity | 7.5 | Améliorations significatives (enum fixé, regex unifiée). Hypothèse H-293-04 bien documentée. -1 pour ambiguïtés résiduelles peer_id, broker reconnexion | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:43:| File d'escalades | Queue FIFO des escalades ouvertes (multi-escalade simultanee). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:51:| INV-293-02 | One Ring ne communique avec les stories qu'au travers du broker/peers ; aucune action directe sur les repos cibles. | Confinement operationnel. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:54:| INV-293-05 | Tout message doit etre valide selon le modele §5.1 ; sinon rejet deterministe et journalisation d'erreur au format contractuel §6.1. | Contrat protocolaire testable. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:164:10) Reconnexion broker : tentative de reconnexion exponentielle bornee (1s, 2s, 4s, 8s, 10s max), mode degrade explicite tant que indisponible, reprise automatique des polls a la reconnexion. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:177: "broker": { docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:348:| CA-12 | Reconnexion broker robuste | Mode degrade explicite puis reprise automatique | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:353:Given quota disponible et broker operationnel, When start PD-XXX, Then etat RUNNING avant timeout et apres first liveness valide. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:382:- T-11 Reconnexion broker
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:383:Given broker indisponible puis restaure, When boucle de retries, Then mode degrade puis reprise automatique et reconciliation. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:391:| H-293-03 | Le broker local supporte 1 One Ring + 5 Ringbearers sans instabilite majeure. | Reduction du quota max ou reconfiguration infra. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:25:Description : Le flux start mentionne un rejet si story_id est déjà actif (ERR-293-02). Séparément, INV-293-12 impose l'idempotence par idempotency_key. La spec ne précise pas la sémantique d'un start avec une même story_id mais une clé d'idempotence différente vs un start avec même story_id et même clé. TC-ERR-02 teste "cle differente" → rejet, mais le mécanisme de décision (vérifie-t-on story_id en premier ou idempotency_key en premier ?) n'est pas contractualisé. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:27:Gravité : Mineur (TC-ERR-02 couvre le cas, mais la spec devrait expliciter l'ordre de précédence) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:44:Référence : Spec §5.1 — story_id sensibilité casse "case-sensitive" + regex ^PD-[0-9]{1,4}$ vs Tests TC-NEG-01 — pd-293 (mauvaise casse) → rejet docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:45:Description : La spec déclare story_id comme "case-sensitive" avec regex ^PD-[0-9]{1,4}$. Le test TC-NEG-01 vérifie le rejet de pd-293. Ceci est cohérent. Cependant, la spec ne précise pas explicitement que le PD- est un préfixe majuscule obligatoire — c'est implicite dans la regex. Si la regex est la source de vérité, alors "case-sensitive" est redondant ; si "case-sensitive" est la source de vérité, la regex devrait être marquée comme normative et non illustrative. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:55:Description : La transition STARTING→RUNNING repose sur la détection d'un peer enregistré dans le broker. Le mécanisme de détection n'est pas spécifié : est-ce un poll périodique (à quelle fréquence ?), un webhook, un watch ? Le peer_poll_interval (1s) est défini mais la spec ne contractualise pas explicitement que c'est ce paramètre qui gouverne la détection de démarrage. Si le poll est à 1s et le timeout à 30s, il y a potentiellement 30 polls — mais si le premier poll rate (broker latence), le mécanisme de retry/backoff n'est pas spécifié. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:85:Description : La spec ne précise pas est stocké le registre de déduplication (mémoire du One Ring, fichier local, broker ?). Si le One Ring crash et redémarre, le registre de déduplication est-il persisté ? Si non, l'idempotence est perdue après un crash, ce qui viole INV-293-12. De plus, avec un TTL de 24h et potentiellement des centaines de commandes, la croissance mémoire n'est pas bornée. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:95:Description : L'état START_FAILED est défini dans la FSM et couvert par INV-293-10 (terminal), mais aucun test nominal ne vérifie la transition entrante STARTING→START_FAILED. TC-INV-02 vérifie que START_FAILED est terminal (pas de sortie), mais aucun test ne provoque le timeout de démarrage pour vérifier que la transition est effectivement déclenchée. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:135:Description : Le diagramme de séquence montre O->>O: Parse commande -> CommandEnvelope{story_id, project_code, idempotency_key}. Le type CommandEnvelope n'est défini nulle part dans le modèle de données §5.1. Les champs story_id, project_code et idempotency_key sont définis individuellement mais pas leur agrégation en structure. De même, le diagramme ne montre pas la validation de schéma (INV-293-05) comme étape explicite. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:154:Référence : Tests TC-NEG-10 — "Tentative respond avec clé idempotence réutilisée mais payload différent → Rejet déterministe de conflit" vs Spec INV-293-12 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:155:Description : INV-293-12 spécifie l'idempotence "par clé dédiée" et que le "doublon [est] ignoré (réponse déterministe)". Le test TC-NEG-10 teste le cas d'un même clé mais payload différent et attend un "rejet de conflit". Or la spec ne contractualise pas ce cas précis : que se passe-t-il quand la même idempotency_key est envoyée avec un payload différent ? La spec dit "doublon ignoré", pas "conflit détecté". Le test invente un comportement non spécifié. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:156:Impact : Le test TC-NEG-10 suppose une sémantique de conflit d'idempotence qui n'est pas dans la spec. Un implémenteur qui retourne simplement le résultat original (ignorant le nouveau payload) serait conforme à la spec mais échouerait au test. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:165:Description : La spec suppose que /gov (le workflow existant) enverra des messages typés (STATUS_UPDATE, ESCALADE, WORKFLOW_DONE) au One Ring via le broker sans modification. Or INV-293-07 stipule que /gov n'est pas modifié. Contradiction potentielle : soit /gov sait déjà envoyer ces types de messages (non documenté), soit il faudra le modifier (violation INV-293-07), soit un adaptateur intermédiaire est nécessaire (non spécifié). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:166:Impact : Si /gov ne sait pas envoyer de messages typés au broker, l'architecture entière est non fonctionnelle. La question Q-293-04 couvre partiellement ce point mais sans le qualifier comme risque bloquant. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:175:Description : Le "mode dégradé" en cas d'indisponibilité du broker n'est pas défini dans la machine d'états. Est-ce un état des Ringbearers ? Du One Ring ? Les Ringbearers continuent-ils leur exécution /gov en autonome (car le broker est un canal de communication, pas un prérequis d'exécution) ? Le One Ring peut-il émettre des commandes pendant le mode dégradé ? TC-ERR-06 teste ce cas mais le résultat attendu ("passage en mode dégradé explicite") n'est pas spécifié au-delà de l'alerte. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:176:Impact : Le comportement du système avec un broker down est non déterministe. Les Ringbearers pourraient continuer à avancer sans que le One Ring puisse les observer, créant un split-brain. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:191:Majeurs critiques : La race condition sur la détection de démarrage (ÉCART-05), l'absence de persistance du registre d'idempotence (ÉCART-08), l'incompatibilité potentielle /gov ↔ protocole messages (ÉCART-16), et le comportement non défini en mode dégradé broker (ÉCART-17) représentent des risques architecturaux significatifs. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:35:Tests unitaires ciblés : TC-INV-01 (matrice 8×8 exhaustive), TC-INV-02 (terminaux immuables) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:63:- Timestamp : strictement Z, tout offset non-zero rejeté (H-TECH-08) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:65:Invariant couvert : INV-293-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:67:Tests unitaires ciblés : TC-NOM-10, TC-ERR-03, TC-NEG-01..TC-NEG-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:73:### Agent 3 : agent-broker → C3 broker-adapter docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:75:Fichier : scripts/lib/lord-broker.sh docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:80:- lord_broker_list_peers() → JSON array | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:81:- lord_broker_send_message(peer_id, message_type, payload) → OK | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:82:- lord_broker_get_messages(peer_id) → JSON array | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:83:- lord_broker_status() → UP | DEGRADED | DOWN docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:84:- lord_broker_reconnect() → OK | STILL_DEGRADED docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:88:Invariant couvert : INV-293-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:92:Tests ciblés : TC-ERR-06, TC-ERR-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:96:### Agent 4 : agent-persistence → C4 persistence docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:98:Fichier : scripts/lib/lord-persistence.sh docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:122:Tests ciblés : TC-NOM-02, TC-NOM-08, TC-NOM-13, TC-ERR-01, TC-ERR-08, TC-ERR-11 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:133:### Agent 5 : agent-orchestrator → C5 orchestrator docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:148:1. Vérifier broker status docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:155:Règle multi-escalade : transition ESCALADED→RUNNING uniquement quand toutes les escalades OPEN de la story sont traitées (lord_count_open_escalades == 0). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:193:Fichiers : tests/lord/**/*.bats + tests/lord/mocks/** + tests/lord/fixtures/** docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:195:Mission : Suites BATS couvrant tous les TC-* contractuels. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:200: helpers/ # setup/teardown, mock broker, fixtures loader docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:201: mocks/ # mock-broker.sh (simule list_peers, send_message, get_messages) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:203: state-machine.bats # TC-INV-01, TC-INV-02 (matrice 8×8) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:204: validator.bats # TC-NOM-10, TC-ERR-03, TC-NEG-01..10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:205: persistence.bats # TC-NOM-02, TC-NOM-08, TC-NOM-13, TC-ERR-01, TC-ERR-08, TC-ERR-11 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:206: orchestrator.bats # TC-NOM-01, TC-NOM-03..06, TC-NOM-07, TC-NOM-09, TC-NOM-12, TC-NOM-14 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:207: integration.bats # TC-ERR-02, TC-ERR-04..07, TC-ERR-09..10, TC-INV-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:208: negative.bats # TC-NEG-01..10 (validation dédiée) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:209: non-regression.bats # TC-NR-01..04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:212:Mock broker : Fonctions shell simulant lord_broker_* via fichiers JSON temporaires. Permet l'injection de scénarios (peer absent, broker DOWN, messages entrants). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:222:| TC-INV-01, TC-INV-02 | state-machine.bats | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:223:| TC-NOM-10, TC-ERR-03, TC-NEG-01..10 | validator.bats + negative.bats | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:224:| TC-NOM-02, TC-NOM-08, TC-NOM-13, TC-ERR-01, TC-ERR-08, TC-ERR-11 | persistence.bats | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:225:| TC-NOM-01, TC-NOM-03..06, TC-NOM-07, TC-NOM-09, TC-NOM-12, TC-NOM-14 | orchestrator.bats | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:226:| TC-ERR-02, TC-ERR-04..07, TC-ERR-09..10, TC-INV-03 | integration.bats | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:227:| TC-NR-01..04 | non-regression.bats | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:228:| TC-MAN-01 | Manuel (hors BATS) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:239:| bats-core | command -v bats | brew install bats-core | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:250:| scripts/lib/lord-broker.sh | agent-broker | ✓ | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:251:| scripts/lib/lord-persistence.sh | agent-persistence | ✓ | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:252:| scripts/gov-lord.sh | agent-orchestrator | ✓ | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-besoin.md:51:- Configurer le broker (localhost:7899, SQLite) pour auto-launch docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-besoin.md:112:| Latence | Le polling du broker (1s) est acceptable. Les escalades doivent apparaître en < 5s sur le One Ring. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:12:| INV-293-01 | CA-05 | TC-NOM-05 | Oui | Les commandes hors scope sont refusees avec message explicite et sans action metier. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:13:| INV-293-02 | CA-01 | TC-NOM-01 | Oui | Les observations passent par broker/peers; aucun acces direct aux repos cibles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:14:| INV-293-03 | CA-08 | TC-NOM-09 | Oui | Isolation stricte des stories et absence de contamination inter-story. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:15:| INV-293-04 | CA-09 | TC-NOM-02 | Oui | La limite de 5 sessions actives est appliquee strictement. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:16:| INV-293-05 | CA-10 | TC-NOM-10 | Oui | Validation stricte du schema canonique et rejet deterministe des invalides. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:17:| INV-293-06 | CA-04 | TC-NOM-03 | Oui | Une escalade bloque la progression jusqu'a reception d'une reponse PO valide. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:18:| INV-293-07 | CA-08 | TC-NR-01 | Oui | Le workflow /gov reste inchange et fonctionnel en execution Ringbearer. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:19:| INV-293-08 | CA-07 | TC-NOM-06 | Oui | Passage en CRASHED et alerte en <=2 cycles de polling. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:20:| INV-293-09 | CA-04 | TC-INV-01 | Oui | Toutes transitions hors machine d'etats sont refusees. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:21:| INV-293-10 | CA-01 | TC-INV-02 | Oui | Les etats terminaux sont immuables (aucune transition sortante). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:22:| INV-293-11 | CA-01 | TC-NOM-07 | Oui | Reconciliation periodique detecte et corrige les ecarts de vue consolidee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:23:| INV-293-12 | CA-02 | TC-NOM-08 | Oui | Commandes start/stop/respond/pause/resume idempotentes par cle dediee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:24:| INV-293-13 | CA-11 | TC-NOM-13 | Oui | Les escalades simultanees sont traitees en FIFO sans remplacement. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:25:| INV-293-14 | CA-09 | TC-INV-03 | Oui | L'ordre de gardes quota -> doublon -> format est respecte sur start. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:26:| INV-293-05 | CA-03 | TC-NOM-04 | Oui | Les messages d'escalade valides sont visibles dans la fenetre SLA P95. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:27:| INV-293-02 | CA-06 | TC-MAN-01 | Manuel | Le controle mobile utilise les memes commandes d'orchestration via One Ring. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:28:| INV-293-05 | CA-12 | TC-ERR-10 | Oui | Reconnexion broker geree en mode degrade explicite puis reprise automatique. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:33:TEST-ID: TC-NOM-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:34:Reference spec: INV-293-02, CA-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:37: - One Ring demarre avec broker disponible docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:45: - Le journal d'audit trace une consultation broker (listing peers) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:50:TEST-ID: TC-NOM-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:66:TEST-ID: TC-NOM-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:82:TEST-ID: TC-NOM-04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:83:Reference spec: CA-03, INV-293-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:97:TEST-ID: TC-NOM-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:112:TEST-ID: TC-NOM-06 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:128:TEST-ID: TC-NOM-07 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:143:TEST-ID: TC-NOM-08 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:158:TEST-ID: TC-NOM-09 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:173:TEST-ID: TC-NOM-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:174:Reference spec: INV-293-05, CA-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:188:TEST-ID: TC-NOM-12 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:203:TEST-ID: TC-NOM-13 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:220:TEST-ID: TC-ERR-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:233:TEST-ID: TC-ERR-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:246:TEST-ID: TC-ERR-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:260:TEST-ID: TC-ERR-04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:273:TEST-ID: TC-ERR-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:286:TEST-ID: TC-ERR-06 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:300:TEST-ID: TC-ERR-07 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:314:TEST-ID: TC-ERR-08 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:327:TEST-ID: TC-ERR-09 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:331: - start accepte, peer enregistre au broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:340:TEST-ID: TC-ERR-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:354:TEST-ID: TC-ERR-11 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:370:| INV-293-01 | TC-NOM-05, TC-ERR-05 | Rejet explicite des actions hors scope, zero action metier | Separation des pouvoirs preservee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:371:| INV-293-02 | TC-NOM-01, TC-MAN-01 | Traces d'usage broker/peers uniquement | Pas d'acces direct aux repos cibles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:372:| INV-293-03 | TC-NOM-09, TC-NR-03 | Absence de contamination et de partage credentials entre stories | Isolation contractuelle verifiee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:373:| INV-293-04 | TC-NOM-02, TC-ERR-01 | 6e start rejete sans creation | Limite capacitaire stricte. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:374:| INV-293-05 | TC-NOM-10, TC-ERR-03, TC-NEG-01..TC-NEG-10 | Validation schema stricte, rejet deterministe des invalides | Contrat de message testable. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:375:| INV-293-06 | TC-NOM-03, TC-ERR-04 | Blocage en ESCALADED jusqu'a PO_RESPONSE valide | Gouvernance humaine effective. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:376:| INV-293-07 | TC-NR-01 | Comportement /gov identique baseline/post-orchestration | Non-regression fonctionnelle du workflow. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:377:| INV-293-08 | TC-NOM-06, TC-ERR-07 | Detection crash en <=2 polls + alerte | Resilience operationnelle. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:378:| INV-293-09 | TC-INV-01 | Toute transition non listee est refusee | Cohesion machine d'etats. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:379:| INV-293-10 | TC-INV-02 | Aucun DONE/ABORTED/CRASHED/START_FAILED -> * accepte | Terminaux verrouilles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:380:| INV-293-11 | TC-NOM-07 | Reconciliation periodique aligne la vue consolidee | Tolerance aux ecarts/crashes. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:381:| INV-293-12 | TC-NOM-08, TC-ERR-08, TC-ERR-11 | Rejeu avec meme cle sans double effet / conflit bloque | Retry-safe en distribue. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:382:| INV-293-13 | TC-NOM-13 | FIFO strict multi-escalades | Pas de remplacement d'escalade. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:383:| INV-293-14 | TC-INV-03 | Gardes quota -> doublon -> format | Ordre contractuel stable. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:386:TEST-ID: TC-INV-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:401:TEST-ID: TC-INV-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:416:TEST-ID: TC-INV-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:435:| TC-NR-01 | Workflow /gov consomme tel quel | Baseline vs run orchestre: memes etapes/gates/verdicts pour une story identique | Couvre INV-293-07 et CA-08. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:436:| TC-NR-02 | Separation One Ring / execution metier | Aucune commande One Ring n'effectue lecture/ecriture/build/test/Jira/GitLab/Vault | Couvre perimetre exclu et INV-293-01. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:437:| TC-NR-03 | Isolation inter-story | Action sur story A sans impact sur story B (etat, contexte, credentials) | Couvre INV-293-03. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:438:| TC-NR-04 | Etats terminaux stables dans le temps | Reconciliation et polling n'ouvrent jamais les etats terminaux | Couvre INV-293-10. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:444:| TC-NEG-01 | story_id=pd-293 (mauvaise casse) | Rejet validation | Erreur regex ^PD-[0-9]{1,4}$, aucun effet de bord | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:445:| TC-NEG-02 | story_id=PD-12345 (hors regex) | Rejet validation | Log de rejet, aucun changement d'etat | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:446:| TC-NEG-03 | project_code=backend-prod (hors enum) | Rejet validation | Message explicite project_code invalide | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:447:| TC-NEG-04 | project_code=ia-gov (alias interdit) | Rejet validation | Seule valeur valide: ia-governance | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:448:| TC-NEG-05 | message_type=ESCALATE (valeur non enum) | Rejet validation | Journal d'erreur schema, etat inchange | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:449:| TC-NEG-06 | timestamp non RFC3339 UTC | Rejet validation | Motif parse timestamp invalide | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:450:| TC-NEG-07 | idempotency_key <16 chars | Rejet validation | Commande non traitee | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:451:| TC-NEG-08 | escalade_text vide | Rejet validation | Escalade non creee | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:452:| TC-NEG-09 | peer_id vide ou controle Unicode | Rejet validation | Message ignore, erreur audit tracee | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:453:| TC-NEG-10 | Injection message inter-story (story_id A dans canal B) | Rejet routage | Aucun impact sur A ni B | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:457:- Etat systeme : snapshot consolide des stories (etat contractuel, derniere observation peer, file d'escalades FIFO, statut broker). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:467:| CA-06 (controle mobile) | Test manuel obligatoire (TC-MAN-01) | Contrat mobile depend d'un environnement iPhone/Safari reel ; automatisation exhaustive non normative en v1 | Majeur | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:471:TEST-ID: TC-MAN-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:492:Le contrat PD-293 est testable de facon deterministe pour invariants, machine d'etats, SLA, idempotence, ordre des gardes, FIFO d'escalades et non-regression. La couverture mobile CA-06 est maintenue via test manuel obligatoire (TC-MAN-01), clairement identifie dans la matrice. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:11:| C3 | broker-adapter | Couche d'abstraction claude-peers-mcp — listing, envoi, réception, reconnexion | scripts/lib/lord-broker.sh | claude-peers-mcp@^1.x (H-293-01) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:12:| C4 | persistence | Lecture/écriture .gov-lord-state.json (schema §5.4), FIFO escalades, cache idempotency, audit JSONL | scripts/lib/lord-persistence.sh | jq (H-TECH-05) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:13:| C5 | orchestrator | Logique métier des 7 commandes /gov-lord, boucle de supervision, reconciliation, détection crash | scripts/gov-lord.sh | C1, C2, C3, C4 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:15:| C7 | tests | Suites BATS couvrant TC-NOM-*, TC-ERR-*, TC-INV-*, TC-NEG-*, TC-NR-* | tests/lord/**/*.bats | bats-core (H-TECH-06), mocks C3 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:53: C5 -> C3.lord_broker_send_message(peer_id, PO_RESPONSE, {text}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:56: # Si autres escalades en OPEN : story reste ESCALADED (multi-escalade) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:61:Précision multi-escalade : La transition ESCALADED->RUNNING ne s'effectue que lorsque toutes les escalades OPEN de la story sont traitées. Tant qu'il reste au moins une escalade OPEN, la story reste ESCALADED. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:68:C5 -> C3.lord_broker_send_message(peer_id, PAUSE, {reason}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:73:C5 -> C3.lord_broker_send_message(peer_id, RESUME, {}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:84: # 1. Vérifier status broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:85: broker_status = C3.lord_broker_status() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:86: si DOWN : alerte Sovereign, tenter C3.lord_broker_reconnect() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:89: observed_peers = C3.lord_broker_list_peers() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:144: C3[C3: broker-adapter
agent-broker] docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:145: C4[C4: persistence
agent-persistence] docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:149: C5[C5: orchestrator
agent-orchestrator] docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:171:- Wave 2 : C3 (broker-adapter) et C4 (persistence) — dépendent de C2 pour la validation, parallélisables entre eux. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:172:- Wave 3 : C5 (orchestrator) — dépend de C1+C2+C3+C4, séquentiel. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:183: participant C4 as C4: lord-persistence.sh docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:185: participant C3 as C3: lord-broker.sh
(claude-peers-mcp) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:201: C5->>C3: lord_broker_list_peers() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:207: C5->>C3: lord_broker_get_messages(rb-PD-42) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:217: C5->>C3: lord_broker_send_message(rb-PD-42, PO_RESPONSE, {text}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:227:| INV-293-01 | One Ring n'exécute aucune action hors interface/routage | Whitelist de 7 commandes dans C6. Toute autre entrée retourne message de blocage. C5 n'importe jamais jira-api.sh, git, curl vers repos cibles. | C6 + C5 | TC-NOM-05, TC-ERR-05 : message de blocage systématique, audit de refus tracé | Faible — vérifiable par grep sur les imports de C5 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:228:| INV-293-02 | Communication uniquement via broker/peers | C3 est l'unique point d'accès réseau. C5 n'appelle jamais curl, git, ou tout outil réseau directement. Toute communication Ringbearer transite par lord_broker_send_message / lord_broker_get_messages. | C3 + C5 | TC-NOM-01 : traces broker exclusivement. TC-NR-02 : absence totale d'opération directe | Moyen — dépend de la discipline de code review | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:229:| INV-293-03 | Isolation inter-story (contexte, credentials) | Chaque Ringbearer est un process claude -p séparé. Aucun partage de variable shell, aucun fichier partagé entre stories. C4 indexe tout par story_id. | C5 + C4 | TC-NOM-09 : action sur story A sans impact B. TC-NR-03 : absence partage credentials | Faible — garanti par l'isolation process OS | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:230:| INV-293-04 | Maximum 5 Ringbearers actifs | lord_count_active_stories() dans C4 (count des stories non-terminales). Vérifié en garde 1 de start. | C4 + C5 | TC-NOM-02, TC-ERR-01 : 6e start rejeté, count reste 5 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:231:| INV-293-05 | Validation stricte §5.1, rejet + journalisation §6.1 | C2 implémente une fonction par champ (lord_validate_*). Chaque rejet appelle lord_log_rejection() qui écrit en JSONL. | C2 | TC-NOM-10 : tous valides acceptés. TC-ERR-03 : invalides rejetés. TC-NEG-01..10 : 10 cas négatifs | Moyen — regex \p{C} nécessite grep -P (Perl regex) pour peer_id/escalade_text | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:232:| INV-293-06 | Escalade suspend jusqu'à PO_RESPONSE | En état ESCALADED, C1 n'autorise que ->RUNNING (PO_RESPONSE), ->ABORTED, ->CRASHED. C5 refuse tout resume/pause depuis ESCALADED (non dans transitions autorisées). | C1 + C5 | TC-NOM-03 : blocage effectif. TC-ERR-04 : respond sans escalade rejeté | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:233:| INV-293-07 | /gov inchangé | PD-293 ne modifie aucun fichier existant (scripts/gov-workflow.sh, scripts/gov-step.sh, etc.). Le Ringbearer exécute /gov tel quel. | Architecture | TC-NR-01 : baseline vs orchestré identiques | Faible — vérifiable par git diff post-implémentation | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:234:| INV-293-08 | Crash détecté en ≤ 2 cycles (≤ 20s défaut) | Compteur missed_polls par story dans C5. Incrémenté si peer absent, reset à 0 si présent. Transition ->CRASHED si missed_polls >= 2. | C5 | TC-NOM-06, TC-ERR-07 : transition CRASHED + alerte ≤ 20s | Faible — déterministe, dépend uniquement du poll_interval | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:235:| INV-293-09 | Transitions strictement §5.2 | C1 utilise un declare -A TRANSITIONS (tableau associatif Bash) avec chaque paire FROM->TO autorisée. Toute transition non présente dans le tableau est rejetée. | C1 | TC-INV-01 : toutes transitions non listées rejetées | Faible — matrice exhaustive vérifiable par diff | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:236:| INV-293-10 | États terminaux immuables | C1 : lord_is_terminal(state) retourne true pour DONE, ABORTED, CRASHED, START_FAILED. lord_transition() rejette immédiatement si from_state est terminal. | C1 | TC-INV-02 : aucune sortie acceptée depuis terminal | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:237:| INV-293-11 | Réconciliation périodique | À chaque cycle de supervision (§2.4, étape 4), C5 compare C4.stories (non-terminaux) avec C3.list_peers(). Écarts signalés en log + alerte si divergence. | C5 + C3 + C4 | TC-NOM-07 : désynchronisation volontaire corrigée | Moyen — dépend de la fiabilité du listing broker | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:238:| INV-293-12 | Idempotence par clé dédiée | C4 : lord_check_idempotency(key, payload_hash). 3 résultats : NEW (première fois), REPLAY (même payload → même résultat), CONFLICT (payload différent → rejet). TTL configurable (défaut 24h). | C4 + C5 | TC-NOM-08, TC-ERR-08, TC-ERR-11 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:239:| INV-293-13 | FIFO multi-escalade | C4 : escalade_queue est un tableau JSON trié par created_at. lord_enqueue_escalade() append en fin. lord_dequeue_oldest_escalade(story_id) retire le premier élément OPEN de la story. | C4 | TC-NOM-13 : 3 escalades traitées dans l'ordre t1, t2, t3 | Faible — tri par created_at garanti par jq | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:240:| INV-293-14 | Ordre des gardes : quota→idempotence→format (start) ; idempotence→format (autres) | C5 applique les gardes dans l'ordre contractuel. Décision (résolution contradiction spec review) : INV-293-14 est interprété comme l'ordre spécifique par commande (§5.1 points 3-4 font foi). Pour start : quota→idempotence→format→doublon story. Pour stop/respond/pause/resume : idempotence→format. | C5 | TC-INV-03 : garde quota en premier, format après idempotence | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:246:| CA-01 | lord_status() dans C5 : lit C4.stories[] + C3.lord_broker_list_peers(), produit JSON consolidé avec story_id, state, last_seen_at, peer_id, escalades OPEN. | C5, C4, C3 | TC-NOM-01 : sortie contient liste consolidée. Log audit trace consultation broker. | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:247:| CA-02 | lord_start() dans C5 : gardes → création story STARTING → lancement Ringbearer background → supervision détecte peer + first liveness → transition STARTING→RUNNING. Nouveau test : TC-NOM-14 (cf. §5 infra) couvre le chemin nominal complet. | C5, C4, C1, C3 | TC-NOM-14 : story visible en RUNNING avant start_detection_timeout. First liveness vérifiée. | Moyen — dépend du timing de démarrage du Ringbearer | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:248:| CA-03 | Delta timestamps RFC3339 entre émission (Ringbearer) et réception (One Ring). Horloge unique locale MacBook (pas de synchronisation d'horloge nécessaire — décision H-TECH-08bis, cf. §8). | C5, C4 | TC-NOM-04 : P95 ≤ 5s sur 100 escalades, timestamps exportés | Faible (horloge locale unique) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:249:| CA-04 | lord_respond()dequeue_oldest_escalade()send_message(PO_RESPONSE)lord_transition(ESCALADED, RUNNING) | C5, C4, C3, C1 | TC-NOM-03 : transition ESCALADED→RUNNING observée après respond | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:250:| CA-05 | Whitelist dans C6 : 7 commandes autorisées. Toute autre entrée → message de blocage. C5 n'a aucun import d'outil métier. | C6, C5 | TC-NOM-05, TC-ERR-05 : blocage explicite + audit de refus | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:251:| CA-06 | /remote-control Claude Code → exécute /gov-lord → mêmes commandes C6. Aucune adaptation spécifique mobile nécessaire. | C6 | TC-MAN-01 : test manuel iPhone/Safari. Résultats identiques desktop. | Élevé — dépend de /remote-control (H-293-02) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:252:| CA-07 | Compteur missed_polls dans C5 supervision loop. ≥ 2 → transition ->CRASHED + alerte. | C5, C1 | TC-NOM-06, TC-ERR-07 : CRASHED en ≤ 2 cycles (≤ 20s) | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:253:| CA-08 | /gov non modifié. Le Ringbearer est un process autonome claude -p "/gov PD-XX projet". | Architecture | TC-NR-01 : baseline identique. Aucun fichier /gov modifié. | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:254:| CA-09 | lord_count_active_stories() ≥ 5 → rejet start. | C4, C5 | TC-NOM-02, TC-ERR-01 : 6e start rejeté, count = 5 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:255:| CA-10 | C2 valide chaque champ avec regex/enum §5.1. Rejet → log JSONL §6.1. | C2 | TC-NOM-10, TC-ERR-03, TC-NEG-01..10 | Moyen — nécessite grep -P pour Unicode | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:256:| CA-11 | C4.escalade_queue trié par created_at. FIFO strict. | C4 | TC-NOM-13 : 3 escalades en ordre t1 < t2 < t3 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:257:| CA-12 | C3 : reconnexion exponentielle bornée (1s, 2s, 4s, 8s, 10s max). Mode DEGRADED explicite. Reprise auto → reconciliation. | C3, C5 | TC-ERR-10 : mode dégradé puis reprise automatique | Moyen — dépend du broker | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:259:## 5. Mapping tests (TC-*) → mécanismes + observables docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:263:| TC-NOM-01 | INV-293-02, CA-01 | C5.lord_status() → C3.list_peers() + C4.stories | Sortie JSON consolidée, log audit broker, absence opération directe | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:264:| TC-NOM-02 | INV-293-04, CA-09 | C4.lord_count_active_stories() en garde start | Rejet explicite, count reste 5, log rejet | Unit (C4) + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:265:| TC-NOM-03 | INV-293-06, CA-04 | C5.lord_respond() → C4.dequeue → C3.send → C1.transition | Transition ESCALADED→RUNNING, STATUS_UPDATE post-respond | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:266:| TC-NOM-04 | CA-03, INV-293-05 | Timestamps RFC3339 delta émission/réception (horloge locale unique) | Export CSV 100 mesures, P95 ≤ 5s | Perf (mock broker avec délai calibré) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:267:| TC-NOM-05 | INV-293-01, CA-05 | Whitelist C6, message de blocage | Sortie "commande non reconnue", log audit refus, absence side-effect | Unit (C6) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:268:| TC-NOM-06 | INV-293-08, CA-07 | C5 supervision loop, missed_polls ≥ 2 | Transition →CRASHED, timestamp ≤ 2×poll_interval, alerte | Integration (mock broker sans peer) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:269:| TC-NOM-07 | INV-293-11, CA-01 | C5 réconciliation : compare C4.stories vs C3.list_peers() | Écarts détectés, vue alignée, log reconciliation | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:270:| TC-NOM-08 | INV-293-12, CA-02 | C4.lord_check_idempotency() → REPLAY | Second appel identique, résultat déterministe, aucun Ringbearer supplémentaire | Unit (C4) + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:271:| TC-NOM-09 | INV-293-03, CA-08 | Isolation process : 2 stories actives, action sur A | State B inchangé, aucun partage message/credential | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:272:| TC-NOM-10 | INV-293-05, CA-10 | C2.lord_validate_
() sur lot valide complet | Tous acceptés, log audit association type+story+timestamp | Unit (C2) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:273:| TC-NOM-12 | CA-02, INV-293-09 | C5.lord_pause() → C1.transition(RUNNING, PAUSED) → C5.lord_resume() → C1.transition(PAUSED, RUNNING) | Transitions RUNNING→PAUSED→RUNNING observées, logs idempotency | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:274:| TC-NOM-13 | INV-293-13, CA-11 | C4.lord_enqueue_escalade() × 3 + C4.lord_dequeue_oldest_escalade() × 3 | Ordre FIFO t1→t2→t3, escalade_queue traçable | Unit (C4) + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:275:| TC-NOM-14 (ajouté) | CA-02, INV-293-08 | C5.lord_start() complet : gardes → STARTING → peer détecté → first liveness → RUNNING | Story visible en RUNNING, peer_id réel, elapsed < start_detection_timeout | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:276:| TC-ERR-01 | ERR-293-01 | C4.lord_count_active_stories() → 5 → rejet | Message "quota atteint", aucun peer créé | Unit + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:277:| TC-ERR-02 | ERR-293-02 | C4 : story déjà active → rejet | Message "story déjà active", pas de second peer | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:278:| TC-ERR-03 | ERR-293-03, §6.1 | C2.lord_validate_story_id() → REJECTED + lord_log_rejection() | Log JSONL avec timestamp, peer_id="sovereign", message_type="START", reason | Unit (C2) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:279:| TC-ERR-04 | ERR-293-04 | C4 : story state != ESCALADED → rejet respond | Message "pas d'escalade active" | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:280:| TC-ERR-05 | ERR-293-05 | Whitelist C6 → blocage | Absence totale d'effet de bord | Unit (C6) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:281:| TC-ERR-06 | ERR-293-06 | C3.lord_broker_status() → DOWN → mode DEGRADED + alerte | Mode dégradé explicite, alerte Sovereign, aucune décision silencieuse | Integration (broker mock DOWN) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:282:| TC-ERR-07 | ERR-293-07 | C5 supervision, missed_polls ≥ 2 | Transition →CRASHED, alerte critique, état terminal | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:283:| TC-ERR-08 | ERR-293-08 | C4.lord_check_idempotency(K2, hash) → REPLAY | Retour déterministe identique, aucun doublon | Unit (C4) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:284:| TC-ERR-09 | ERR-293-10 | C5 supervision : peer détecté mais pas de liveness avant first_liveness_timeout | Transition STARTING→START_FAILED, cleanup, alerte | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:285:| TC-ERR-10 | CA-12 | C3 reconnexion exponentielle + C5 reconciliation à la reprise | Mode dégradé, timing retries (1s,2s,4s,8s,10s), reprise auto | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:286:| TC-ERR-11 | ERR-293-09 | C4.lord_check_idempotency(K3, hash_P2) → CONFLICT | Rejet conflit, aucun effet | Unit (C4) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:287:| TC-INV-01 | INV-293-09 | C1 : matrice TRANSITIONS, toute paire non listée → REJECTED | Rejet explicite pour chaque transition non autorisée, log | Unit (C1) — test exhaustif matrice 8×8 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:288:| TC-INV-02 | INV-293-10 | C1 : lord_is_terminal() + lord_transition() → rejet si terminal | Aucune mutation depuis DONE/ABORTED/CRASHED/START_FAILED | Unit (C1) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:289:| TC-INV-03 | INV-293-14 | C5.lord_start() avec quota plein + payload invalide | Premier rejet = "quota atteint" (pas "format invalide") | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:290:| TC-NEG-01..10 | INV-293-05 | C2.lord_validate_() sur 10 entrées invalides (cf. §7 tests) | Rejet spécifique par champ, log JSONL, zéro side-effect | Unit (C2) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:291:| TC-NR-01 | INV-293-07 | Diff comportement /gov PD-XX standalone vs orchestré | Mêmes étapes/gates/verdicts, aucun fichier gov modifié | E2E (1 story complète) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:292:| TC-NR-02 | INV-293-01 | grep -r sur C5 pour curl/git/cd-vers-repo | Zéro match d'opération hors scope | Static analysis | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:293:| TC-NR-03 | INV-293-03 | 2 stories actives : envoi message ciblé A, vérification B inchangé | State B identique avant/après | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:294:| TC-NR-04 | INV-293-10 | Réconciliation + polling sur stories terminales | États terminaux jamais modifiés | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:295:| TC-MAN-01 | CA-06 | iPhone/Safari + /remote-control | Résultats fonctionnels identiques desktop | Manuel | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:297:Note sur TC-NOM-14 : Ce test est ajouté pour couvrir CA-02 (résolution de l'incohérence spec-review §2 : CA-02 était mappé à TC-NOM-08 qui teste l'idempotence, pas le démarrage nominal). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:308:| ERR-293-06 | Broker indisponible | C3.lord_broker_status() = DOWN | C3+C5 | Mode DEGRADED + alerte "⚠ Broker indisponible — mode dégradé" + retries exponentiel | Aucune décision silencieuse | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:327:| Exécution hors scope par One Ring (lecture repo, build, Jira, GitLab, Vault) | INV-293-01 : whitelist stricte 7 commandes dans C6. C5 n'importe aucun module métier. Vérifiable par analyse statique (TC-NR-02). | C6, C5 | grep -r sur imports/sources de C5 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:328:| Contamination inter-story (credentials, contexte) | INV-293-03 : isolation process OS. Chaque Ringbearer = process claude -p séparé avec son propre environnement. Aucun fichier partagé. | C5 | TC-NOM-09, TC-NR-03 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:330:| Injection dans story_id/project_code | C2 : validation regex stricte ^PD-[0-9]{1,4}$ et enum project_code. Aucun passage de valeur non validée à claude -p ou au broker. | C2 | TC-NEG-01..10 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:343:| H-TECH-06 | bats-core installé (framework de test Bash) | C7 non exécutable | brew install bats-core. CI : step d'installation dans le pipeline. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:345:| H-TECH-08 | Timestamp strictement UTC Z — les offsets non-zero (+02:00, -05:00) sont rejetés par C2 | Aucun — c'est une décision de design, pas une hypothèse externe | Résolution de l'ambiguïté spec review §5.1. Regex : ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$ | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:346:| H-TECH-08bis | Horloge unique locale — émetteur (Ringbearer) et récepteur (One Ring) sont sur le même MacBook | Le SLA P95 de CA-03 est fiable car aucun décalage d'horloge possible | Résolution de l'hypothèse dangereuse spec review. Si multi-machine en v2, NTP obligatoire. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:365:| D2 | Test TC-NOM-04 (P95 SLA) dépend d'un mock broker avec délai calibré, pas du vrai broker | Le vrai broker introduirait du non-déterminisme | Validation E2E manuelle | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:381:| Contradiction diagramme séquence vs INV-293-02 (flèches directes O→R) | Bloquant | INV-293-02 fait foi. Les flèches directes du diagramme §5bis sont des raccourcis visuels. Toute communication passe par C3 (broker-adapter). Le diagramme enrichi §2ter corrige cette représentation. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:382:| Incohérence CA-02 mappé à TC-NOM-08 | Majeur | TC-NOM-14 ajouté pour couvrir le chemin nominal de CA-02 (start complet jusqu'à RUNNING). TC-NOM-08 couvre uniquement l'idempotence (INV-293-12). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:383:| Incohérence INV-293-10 mappé à CA-01 | Majeur | INV-293-10 (terminaux immuables) est couvert par TC-INV-02, pas par CA-01. La matrice de couverture dans le plan utilise le mapping corrigé. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:385:| Ambiguïté timestamp "offset UTC" | Mineur | Strictement Z uniquement. Tout offset non-zero est rejeté (H-TECH-08). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:386:| Hypothèse horloge SLA CA-03 | Majeur | Horloge locale unique MacBook (H-TECH-08bis). Pas de décalage possible en v1 (single machine). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:387:| Tests TC-NR-*/TC-NEG-* non détaillés Given/When/Then | Majeur | TC-NEG-01..10 : chacun est une variante de C2.lord_validate_() avec une entrée invalide spécifique. Le niveau de détail est dans la matrice §5. TC-NR-* : détaillés dans le mapping §5 avec observables. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:396:| Communication directe Ringbearer↔Ringbearer | Spec §2 exclu. Toute communication transite par One Ring via broker. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:400:| Tests E2E multi-machines | MacBook local uniquement en v1. Les tests d'intégration utilisent des mocks broker. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:408:| E2E | TC-NR-01 : 1 story complète /gov standalone vs orchestrée | Multi-stories simultanées E2E (trop long, couvert par intégration) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:409:| Perf | TC-NOM-04 : P95 SLA escalade (mock broker) | Perf sous charge réelle (5 stories simultanées) — mesure manuelle | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:410:| Manuel | TC-MAN-01 : iPhone/Safari /remote-control | — | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:465: - "INV-293-05 : Chaque champ est valide selon §5.1 (regex, enum, bornes). Rejet deterministe et journalise en JSONL §6.1." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:466: - "Timestamp RFC3339 strictement UTC : seul le suffixe Z est accepte (decision H-TECH-08)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:484: - module: broker-adapter docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:485: owner_agent: agent-broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:487: - "lord_broker_list_peers() -> json_array | ERROR" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:488: - "lord_broker_send_message(peer_id, message_type, payload) -> OK | ERROR" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:489: - "lord_broker_get_messages(peer_id) -> json_array | ERROR" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:490: - "lord_broker_status() -> UP | DEGRADED | DOWN" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:491: - "lord_broker_reconnect() -> OK | STILL_DEGRADED" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:493: - "INV-293-02 : Toute communication One Ring <-> Ringbearer passe par le broker. Aucun acces direct aux repos cibles." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:498: - "Communiquer avec un Ringbearer sans passer par le broker." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:499: - "Ignorer silencieusement une erreur broker (toute erreur doit basculer en DEGRADED)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:505: - "IPC par fichiers partages (fallback si broker indisponible — hors scope v1)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:510: - "scripts/lib/lord-broker.sh" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:512: - module: persistence docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:513: owner_agent: agent-persistence docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:551: - "scripts/lib/lord-persistence.sh" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:555: - module: orchestrator docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:556: owner_agent: agent-orchestrator docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:577: - "Communiquer avec un Ringbearer sans passer par C3 (broker-adapter)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:578: - "Lire ou ecrire le state sans passer par C4 (persistence)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:608: - "Suites BATS : tests/lord/state-machine.bats, tests/lord/validator.bats, tests/lord/persistence.bats, tests/lord/orchestrator.bats, tests/lord/integration.bats, tests/lord/negative.bats, tests/lord/non-regression.bats" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:610: - "Chaque test produit un resultat deterministe (pas de dependance a l'horloge reelle sauf TC-NOM-04)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:611: - "Les tests utilisent un mock broker (pas de dependance a claude-peers-mcp en CI)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:612: - "TC-INV-01 teste exhaustivement la matrice 8x8 (64 paires) de transitions." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:614: - "Tester avec un broker reel sans fallback mock." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:615: - "Ignorer un test d'invariant (TC-INV-) ou de non-regression (TC-NR-)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:618: - decision: "BATS (Bash Automated Testing System) avec mock broker en fichier" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:619: rationale: "BATS est le standard de facto pour Bash. Le mock broker est un ensemble de fonctions shell qui simulent list_peers/send_message/get_messages via fichiers JSON temporaires." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:625: - "Inconvenient : Dependance externe bats-core (H-TECH-06)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:627: - "tests/lord//.bats" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:637:3. *TC-NOM-14 ajouté — couvre CA-02 (démarrage nominal) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md:10:Reference : PD-293-specification.md §7 (CA-02) vs PD-293-tests.md §2 (Matrice) + §3 (TC-NOM-08) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md:11:Description : La matrice associe CA-02 a TC-NOM-08. CA-02 exige un demarrage nominal jusqu'a RUNNING avant start_detection_timeout et apres first liveness. TC-NOM-08 teste l'idempotence d'une reemission de start, pas le chemin nominal de demarrage. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md:34:Reference : PD-293-specification.md §7 (CA-03) + §5.1 (escalade_visibility_sla) + PD-293-tests.md TC-NOM-04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md:40:Reference : PD-293-specification.md §5bis (diagramme de sequence) vs §4 (INV-293-02) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md:41:Description : Le diagramme de sequence montre des echanges directs O->>R (demande demarrage, PO_RESPONSE, PAUSE, RESUME), alors que INV-293-02 impose que One Ring communique avec les stories uniquement via broker/peers. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification-review.md:47:Description : Des tests references dans la matrice/invariants (TC-NR-01, TC-NR-03, TC-NEG-01..TC-NEG-10) ne sont pas decrits en Given/When/Then detaille dans le document, contrairement aux autres cas. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:17:| Test irrealisable | CA-02, TC-NOM-14 (mentionne dans plan) / Tests PD-293-tests.md | Le plan annonce "TC-NOM-14 ajoute", mais ce test n'existe pas dans le document de tests contractuels fourni. | La preuve contractuelle du demarrage nominal CA-02 reste non etablissable de facon deterministe. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:18:| Test irrealisable | TC-NOM-01..TC-ERR-11, TC-INV-01..03, TC-MAN-01 / Plan PD-293-plan.md | Aucun point d'observabilite explicite par scenario de test n'est present dans l'artefact plan fourni. | Les scenarios ne sont pas executables/auditables a partir du plan comme document contractuel. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:24:| Contrainte technique non documentee | Plan PD-293-plan.md (section "Contraintes techniques" absente) | Le framework de test Jest/Vitest n'est pas explicite; le code contract mentionne bats-core, sans decision contractuelle explicite au niveau plan. | Ambiguite de runner de test au regard de la contrainte documentaire demandee. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:31:- Points critiques : artefact plan non auditable (contenu manquant), couverture invariants non prouvable, executabilite des tests non demontree, ecart CA-02/TC-NOM-14 non resolu dans les tests fournis. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:82: - "INV-293-05 : Tout message invalide est rejete de facon deterministe avec raison explicite" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:172: - module: broker-adapter docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:173: owner_agent: agent-broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:175: - broker_list_peers() -> peers[] | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:176: - broker_send_message(peer_id, message_json) -> OK | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:177: - broker_check_health() -> UP | DEGRADED | DOWN docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:178: - broker_reconnect() -> OK | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:180: - "INV-293-02 : seul canal de communication entre One Ring et Ringbearers" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:182: - "Mode degrade explicite tant que broker indisponible (broker.status dans state)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:184: - "Communiquer avec les Ringbearers autrement que via broker (pas de fichier partage, pas de signal Unix)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:186: - "Ignorer silencieusement une erreur broker (toujours propager ou mode degrade)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:191: - "API REST directe sur le broker SQLite (contourne l'abstraction MCP, fragile)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:192: - "CLI custom wrapping le broker (overhead de maintenance)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:197: - "scripts/lib/lord-broker.sh" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:220: - "Webhook callback du broker (claude-peers-mcp ne supporte pas les webhooks)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:269: - "Appeler des outils hors broker (pas de Read, Write, Bash sur repos cibles)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:277: - Tests unitaires bats-core pour C1, C2, C3, C7 (gardes) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:278: - Tests integration bats-core pour C4 (complet), C5 (broker stubbe), C6, C7 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:279: - Tests E2E pour TC-NOM-14 (start->RUNNING), TC-NR-01 (baseline /gov) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:280: - Tests negatifs TC-NEG-01..10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:282: - "Chaque TC-* de la spec a un test bats correspondant" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:283: - "Tests unitaires sans I/O reseau (broker stubbe)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:286: - "Dependre d'un broker reel pour les tests unitaires" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:287: - "Sauter les tests negatifs TC-NEG-01..10" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:314:| Test irréalisable | TC-… | … | … | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:404:| C3 | broker-adapter | Couche d'abstraction claude-peers-mcp — listing, envoi, réception, reconnexion | scripts/lib/lord-broker.sh | claude-peers-mcp@^1.x (H-293-01) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:405:| C4 | persistence | Lecture/écriture .gov-lord-state.json (schema §5.4), FIFO escalades, cache idempotency, audit JSONL | scripts/lib/lord-persistence.sh | jq (H-TECH-05) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:406:| C5 | orchestrator | Logique métier des 7 commandes /gov-lord, boucle de supervision, reconciliation, détection crash | scripts/gov-lord.sh | C1, C2, C3, C4 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:408:| C7 | tests | Suites BATS couvrant TC-NOM-*, TC-ERR-*, TC-INV-*, TC-NEG-*, TC-NR-* | tests/lord/**/*.bats | bats-core (H-TECH-06), mocks C3 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:446: C5 -> C3.lord_broker_send_message(peer_id, PO_RESPONSE, {text}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:449: # Si autres escalades en OPEN : story reste ESCALADED (multi-escalade) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:454:Précision multi-escalade : La transition ESCALADED->RUNNING ne s'effectue que lorsque toutes les escalades OPEN de la story sont traitées. Tant qu'il reste au moins une escalade OPEN, la story reste ESCALADED. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:461:C5 -> C3.lord_broker_send_message(peer_id, PAUSE, {reason}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:466:C5 -> C3.lord_broker_send_message(peer_id, RESUME, {}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:477: # 1. Vérifier status broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:478: broker_status = C3.lord_broker_status() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:479: si DOWN : alerte Sovereign, tenter C3.lord_broker_reconnect() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:482: observed_peers = C3.lord_broker_list_peers() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:537: C3[C3: broker-adapter
agent-broker] docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:538: C4[C4: persistence
agent-persistence] docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:542: C5[C5: orchestrator
agent-orchestrator] docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:564:- Wave 2 : C3 (broker-adapter) et C4 (persistence) — dépendent de C2 pour la validation, parallélisables entre eux. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:565:- Wave 3 : C5 (orchestrator) — dépend de C1+C2+C3+C4, séquentiel. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:576: participant C4 as C4: lord-persistence.sh docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:578: participant C3 as C3: lord-broker.sh
(claude-peers-mcp) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:594: C5->>C3: lord_broker_list_peers() docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:600: C5->>C3: lord_broker_get_messages(rb-PD-42) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:610: C5->>C3: lord_broker_send_message(rb-PD-42, PO_RESPONSE, {text}) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:657: - "INV-293-05 : Tout message invalide est rejete de facon deterministe avec raison explicite" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:747: - module: broker-adapter docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:748: owner_agent: agent-broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:750: - broker_list_peers() -> peers[] | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:751: - broker_send_message(peer_id, message_json) -> OK | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:752: - broker_check_health() -> UP | DEGRADED | DOWN docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:753: - broker_reconnect() -> OK | ERROR docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:755: - "INV-293-02 : seul canal de communication entre One Ring et Ringbearers" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:757: - "Mode degrade explicite tant que broker indisponible (broker.status dans state)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:759: - "Communiquer avec les Ringbearers autrement que via broker (pas de fichier partage, pas de signal Unix)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:761: - "Ignorer silencieusement une erreur broker (toujours propager ou mode degrade)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:766: - "API REST directe sur le broker SQLite (contourne l'abstraction MCP, fragile)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:767: - "CLI custom wrapping le broker (overhead de maintenance)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:772: - "scripts/lib/lord-broker.sh" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:795: - "Webhook callback du broker (claude-peers-mcp ne supporte pas les webhooks)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:844: - "Appeler des outils hors broker (pas de Read, Write, Bash sur repos cibles)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:852: - Tests unitaires bats-core pour C1, C2, C3, C7 (gardes) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:853: - Tests integration bats-core pour C4 (complet), C5 (broker stubbe), C6, C7 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:854: - Tests E2E pour TC-NOM-14 (start->RUNNING), TC-NR-01 (baseline /gov) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:855: - Tests negatifs TC-NEG-01..10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:857: - "Chaque TC-* de la spec a un test bats correspondant" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:858: - "Tests unitaires sans I/O reseau (broker stubbe)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:861: - "Dependre d'un broker reel pour les tests unitaires" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:862: - "Sauter les tests negatifs TC-NEG-01..10" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:880:| INV-293-01 | One Ring n'exécute aucune action hors interface/routage | Whitelist de 7 commandes dans C6. Toute autre entrée retourne message de blocage. C5 n'importe jamais jira-api.sh, git, curl vers repos cibles. | C6 + C5 | TC-NOM-05, TC-ERR-05 : message de blocage systématique, audit de refus tracé | Faible — vérifiable par grep sur les imports de C5 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:881:| INV-293-02 | Communication uniquement via broker/peers | C3 est l'unique point d'accès réseau. C5 n'appelle jamais curl, git, ou tout outil réseau directement. Toute communication Ringbearer transite par lord_broker_send_message / lord_broker_get_messages. | C3 + C5 | TC-NOM-01 : traces broker exclusivement. TC-NR-02 : absence totale d'opération directe | Moyen — dépend de la discipline de code review | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:882:| INV-293-03 | Isolation inter-story (contexte, credentials) | Chaque Ringbearer est un process claude -p séparé. Aucun partage de variable shell, aucun fichier partagé entre stories. C4 indexe tout par story_id. | C5 + C4 | TC-NOM-09 : action sur story A sans impact B. TC-NR-03 : absence partage credentials | Faible — garanti par l'isolation process OS | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:883:| INV-293-04 | Maximum 5 Ringbearers actifs | lord_count_active_stories() dans C4 (count des stories non-terminales). Vérifié en garde 1 de start. | C4 + C5 | TC-NOM-02, TC-ERR-01 : 6e start rejeté, count reste 5 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:884:| INV-293-05 | Validation stricte §5.1, rejet + journalisation §6.1 | C2 implémente une fonction par champ (lord_validate_*). Chaque rejet appelle lord_log_rejection() qui écrit en JSONL. | C2 | TC-NOM-10 : tous valides acceptés. TC-ERR-03 : invalides rejetés. TC-NEG-01..10 : 10 cas négatifs | Moyen — regex \p{C} nécessite grep -P (Perl regex) pour peer_id/escalade_text | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:885:| INV-293-06 | Escalade suspend jusqu'à PO_RESPONSE | En état ESCALADED, C1 n'autorise que ->RUNNING (PO_RESPONSE), ->ABORTED, ->CRASHED. C5 refuse tout resume/pause depuis ESCALADED (non dans transitions autorisées). | C1 + C5 | TC-NOM-03 : blocage effectif. TC-ERR-04 : respond sans escalade rejeté | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:886:| INV-293-07 | /gov inchangé | PD-293 ne modifie aucun fichier existant (scripts/gov-workflow.sh, scripts/gov-step.sh, etc.). Le Ringbearer exécute /gov tel quel. | Architecture | TC-NR-01 : baseline vs orchestré identiques | Faible — vérifiable par git diff post-implémentation | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:887:| INV-293-08 | Crash détecté en ≤ 2 cycles (≤ 20s défaut) | Compteur missed_polls par story dans C5. Incrémenté si peer absent, reset à 0 si présent. Transition ->CRASHED si missed_polls >= 2. | C5 | TC-NOM-06, TC-ERR-07 : transition CRASHED + alerte ≤ 20s | Faible — déterministe, dépend uniquement du poll_interval | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:888:| INV-293-09 | Transitions strictement §5.2 | C1 utilise un declare -A TRANSITIONS (tableau associatif Bash) avec chaque paire FROM->TO autorisée. Toute transition non présente dans le tableau est rejetée. | C1 | TC-INV-01 : toutes transitions non listées rejetées | Faible — matrice exhaustive vérifiable par diff | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:889:| INV-293-10 | États terminaux immuables | C1 : lord_is_terminal(state) retourne true pour DONE, ABORTED, CRASHED, START_FAILED. lord_transition() rejette immédiatement si from_state est terminal. | C1 | TC-INV-02 : aucune sortie acceptée depuis terminal | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:890:| INV-293-11 | Réconciliation périodique | À chaque cycle de supervision (§2.4, étape 4), C5 compare C4.stories (non-terminaux) avec C3.list_peers(). Écarts signalés en log + alerte si divergence. | C5 + C3 + C4 | TC-NOM-07 : désynchronisation volontaire corrigée | Moyen — dépend de la fiabilité du listing broker | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:891:| INV-293-12 | Idempotence par clé dédiée | C4 : lord_check_idempotency(key, payload_hash). 3 résultats : NEW (première fois), REPLAY (même payload → même résultat), CONFLICT (payload différent → rejet). TTL configurable (défaut 24h). | C4 + C5 | TC-NOM-08, TC-ERR-08, TC-ERR-11 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:892:| INV-293-13 | FIFO multi-escalade | C4 : escalade_queue est un tableau JSON trié par created_at. lord_enqueue_escalade() append en fin. lord_dequeue_oldest_escalade(story_id) retire le premier élément OPEN de la story. | C4 | TC-NOM-13 : 3 escalades traitées dans l'ordre t1, t2, t3 | Faible — tri par created_at garanti par jq | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:893:| INV-293-14 | Ordre des gardes : quota→idempotence→format (start) ; idempotence→format (autres) | C5 applique les gardes dans l'ordre contractuel. Décision (résolution contradiction spec review) : INV-293-14 est interprété comme l'ordre spécifique par commande (§5.1 points 3-4 font foi). Pour start : quota→idempotence→format→doublon story. Pour stop/respond/pause/resume : idempotence→format. | C5 | TC-INV-03 : garde quota en premier, format après idempotence | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:899:| CA-01 | lord_status() dans C5 : lit C4.stories[] + C3.lord_broker_list_peers(), produit JSON consolidé avec story_id, state, last_seen_at, peer_id, escalades OPEN. | C5, C4, C3 | TC-NOM-01 : sortie contient liste consolidée. Log audit trace consultation broker. | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:900:| CA-02 | lord_start() dans C5 : gardes → création story STARTING → lancement Ringbearer background → supervision détecte peer + first liveness → transition STARTING→RUNNING. Nouveau test : TC-NOM-14 (cf. §5 infra) couvre le chemin nominal complet. | C5, C4, C1, C3 | TC-NOM-14 : story visible en RUNNING avant start_detection_timeout. First liveness vérifiée. | Moyen — dépend du timing de démarrage du Ringbearer | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:901:| CA-03 | Delta timestamps RFC3339 entre émission (Ringbearer) et réception (One Ring). Horloge unique locale MacBook (pas de synchronisation d'horloge nécessaire — décision H-TECH-08bis, cf. §8). | C5, C4 | TC-NOM-04 : P95 ≤ 5s sur 100 escalades, timestamps exportés | Faible (horloge locale unique) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:902:| CA-04 | lord_respond()dequeue_oldest_escalade()send_message(PO_RESPONSE)lord_transition(ESCALADED, RUNNING) | C5, C4, C3, C1 | TC-NOM-03 : transition ESCALADED→RUNNING observée après respond | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:903:| CA-05 | Whitelist dans C6 : 7 commandes autorisées. Toute autre entrée → message de blocage. C5 n'a aucun import d'outil métier. | C6, C5 | TC-NOM-05, TC-ERR-05 : blocage explicite + audit de refus | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:904:| CA-06 | /remote-control Claude Code → exécute /gov-lord → mêmes commandes C6. Aucune adaptation spécifique mobile nécessaire. | C6 | TC-MAN-01 : test manuel iPhone/Safari. Résultats identiques desktop. | Élevé — dépend de /remote-control (H-293-02) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:905:| CA-07 | Compteur missed_polls dans C5 supervision loop. ≥ 2 → transition ->CRASHED + alerte. | C5, C1 | TC-NOM-06, TC-ERR-07 : CRASHED en ≤ 2 cycles (≤ 20s) | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:906:| CA-08 | /gov non modifié. Le Ringbearer est un process autonome claude -p "/gov PD-XX projet". | Architecture | TC-NR-01 : baseline identique. Aucun fichier /gov modifié. | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:907:| CA-09 | lord_count_active_stories() ≥ 5 → rejet start. | C4, C5 | TC-NOM-02, TC-ERR-01 : 6e start rejeté, count = 5 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:908:| CA-10 | C2 valide chaque champ avec regex/enum §5.1. Rejet → log JSONL §6.1. | C2 | TC-NOM-10, TC-ERR-03, TC-NEG-01..10 | Moyen — nécessite grep -P pour Unicode | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:909:| CA-11 | C4.escalade_queue trié par created_at. FIFO strict. | C4 | TC-NOM-13 : 3 escalades en ordre t1 < t2 < t3 | Faible | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:910:| CA-12 | C3 : reconnexion exponentielle bornée (1s, 2s, 4s, 8s, 10s max). Mode DEGRADED explicite. Reprise auto → reconciliation. | C3, C5 | TC-ERR-10 : mode dégradé puis reprise automatique | Moyen — dépend du broker | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:912:## 5. Mapping tests (TC-*) → mécanismes + observables docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:916:| TC-NOM-01 | INV-293-02, CA-01 | C5.lord_status() → C3.list_peers() + C4.stories | Sortie JSON consolidée, log audit broker, absence opération directe | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:917:| TC-NOM-02 | INV-293-04, CA-09 | C4.lord_count_active_stories() en garde start | Rejet explicite, count reste 5, log rejet | Unit (C4) + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:918:| TC-NOM-03 | INV-293-06, CA-04 | C5.lord_respond() → C4.dequeue → C3.send → C1.transition | Transition ESCALADED→RUNNING, STATUS_UPDATE post-respond | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:919:| TC-NOM-04 | CA-03, INV-293-05 | Timestamps RFC3339 delta émission/réception (horloge locale unique) | Export CSV 100 mesures, P95 ≤ 5s | Perf (mock broker avec délai calibré) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:920:| TC-NOM-05 | INV-293-01, CA-05 | Whitelist C6, message de blocage | Sortie "commande non reconnue", log audit refus, absence side-effect | Unit (C6) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:921:| TC-NOM-06 | INV-293-08, CA-07 | C5 supervision loop, missed_polls ≥ 2 | Transition →CRASHED, timestamp ≤ 2×poll_interval, alerte | Integration (mock broker sans peer) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:922:| TC-NOM-07 | INV-293-11, CA-01 | C5 réconciliation : compare C4.stories vs C3.list_peers() | Écarts détectés, vue alignée, log reconciliation | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:923:| TC-NOM-08 | INV-293-12, CA-02 | C4.lord_check_idempotency() → REPLAY | Second appel identique, résultat déterministe, aucun Ringbearer supplémentaire | Unit (C4) + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:924:| TC-NOM-09 | INV-293-03, CA-08 | Isolation process : 2 stories actives, action sur A | State B inchangé, aucun partage message/credential | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:925:| TC-NOM-10 | INV-293-05, CA-10 | C2.lord_validate_() sur lot valide complet | Tous acceptés, log audit association type+story+timestamp | Unit (C2) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:926:| TC-NOM-12 | CA-02, INV-293-09 | C5.lord_pause() → C1.transition(RUNNING, PAUSED) → C5.lord_resume() → C1.transition(PAUSED, RUNNING) | Transitions RUNNING→PAUSED→RUNNING observées, logs idempotency | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:927:| TC-NOM-13 | INV-293-13, CA-11 | C4.lord_enqueue_escalade() × 3 + C4.lord_dequeue_oldest_escalade() × 3 | Ordre FIFO t1→t2→t3, escalade_queue traçable | Unit (C4) + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:928:| TC-NOM-14 (ajouté) | CA-02, INV-293-08 | C5.lord_start() complet : gardes → STARTING → peer détecté → first liveness → RUNNING | Story visible en RUNNING, peer_id réel, elapsed < start_detection_timeout | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:929:| TC-ERR-01 | ERR-293-01 | C4.lord_count_active_stories() → 5 → rejet | Message "quota atteint", aucun peer créé | Unit + Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:930:| TC-ERR-02 | ERR-293-02 | C4 : story déjà active → rejet | Message "story déjà active", pas de second peer | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:931:| TC-ERR-03 | ERR-293-03, §6.1 | C2.lord_validate_story_id() → REJECTED + lord_log_rejection() | Log JSONL avec timestamp, peer_id="sovereign", message_type="START", reason | Unit (C2) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:932:| TC-ERR-04 | ERR-293-04 | C4 : story state != ESCALADED → rejet respond | Message "pas d'escalade active" | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:933:| TC-ERR-05 | ERR-293-05 | Whitelist C6 → blocage | Absence totale d'effet de bord | Unit (C6) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:934:| TC-ERR-06 | ERR-293-06 | C3.lord_broker_status() → DOWN → mode DEGRADED + alerte | Mode dégradé explicite, alerte Sovereign, aucune décision silencieuse | Integration (broker mock DOWN) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:935:| TC-ERR-07 | ERR-293-07 | C5 supervision, missed_polls ≥ 2 | Transition →CRASHED, alerte critique, état terminal | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:936:| TC-ERR-08 | ERR-293-08 | C4.lord_check_idempotency(K2, hash) → REPLAY | Retour déterministe identique, aucun doublon | Unit (C4) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:937:| TC-ERR-09 | ERR-293-10 | C5 supervision : peer détecté mais pas de liveness avant first_liveness_timeout | Transition STARTING→START_FAILED, cleanup, alerte | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:938:| TC-ERR-10 | CA-12 | C3 reconnexion exponentielle + C5 reconciliation à la reprise | Mode dégradé, timing retries (1s,2s,4s,8s,10s), reprise auto | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:939:| TC-ERR-11 | ERR-293-09 | C4.lord_check_idempotency(K3, hash_P2) → CONFLICT | Rejet conflit, aucun effet | Unit (C4) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:940:| TC-INV-01 | INV-293-09 | C1 : matrice TRANSITIONS, toute paire non listée → REJECTED | Rejet explicite pour chaque transition non autorisée, log | Unit (C1) — test exhaustif matrice 8×8 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:941:| TC-INV-02 | INV-293-10 | C1 : lord_is_terminal() + lord_transition() → rejet si terminal | Aucune mutation depuis DONE/ABORTED/CRASHED/START_FAILED | Unit (C1) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:942:| TC-INV-03 | INV-293-14 | C5.lord_start() avec quota plein + payload invalide | Premier rejet = "quota atteint" (pas "format invalide") | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:943:| TC-NEG-01..10 | INV-293-05 | C2.lord_validate_() sur 10 entrées invalides (cf. §7 tests) | Rejet spécifique par champ, log JSONL, zéro side-effect | Unit (C2) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:944:| TC-NR-01 | INV-293-07 | Diff comportement /gov PD-XX standalone vs orchestré | Mêmes étapes/gates/verdicts, aucun fichier gov modifié | E2E (1 story complète) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:945:| TC-NR-02 | INV-293-01 | grep -r sur C5 pour curl/git/cd-vers-repo | Zéro match d'opération hors scope | Static analysis | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:946:| TC-NR-03 | INV-293-03 | 2 stories actives : envoi message ciblé A, vérification B inchangé | State B identique avant/après | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:947:| TC-NR-04 | INV-293-10 | Réconciliation + polling sur stories terminales | États terminaux jamais modifiés | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:948:| TC-MAN-01 | CA-06 | iPhone/Safari + /remote-control | Résultats fonctionnels identiques desktop | Manuel | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:950:Note sur TC-NOM-14 : Ce test est ajouté pour couvrir CA-02 (résolution de l'incohérence spec-review §2 : CA-02 était mappé à TC-NOM-08 qui teste l'idempotence, pas le démarrage nominal). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:961:| ERR-293-06 | Broker indisponible | C3.lord_broker_status() = DOWN | C3+C5 | Mode DEGRADED + alerte "⚠ Broker indisponible — mode dégradé" + retries exponentiel | Aucune décision silencieuse | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:980:| Exécution hors scope par One Ring (lecture repo, build, Jira, GitLab, Vault) | INV-293-01 : whitelist stricte 7 commandes dans C6. C5 n'importe aucun module métier. Vérifiable par analyse statique (TC-NR-02). | C6, C5 | grep -r sur imports/sources de C5 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:981:| Contamination inter-story (credentials, contexte) | INV-293-03 : isolation process OS. Chaque Ringbearer = process claude -p séparé avec son propre environnement. Aucun fichier partagé. | C5 | TC-NOM-09, TC-NR-03 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:983:| Injection dans story_id/project_code | C2 : validation regex stricte ^PD-[0-9]{1,4}$ et enum project_code. Aucun passage de valeur non validée à claude -p ou au broker. | C2 | TC-NEG-01..10 | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:996:| H-TECH-06 | bats-core installé (framework de test Bash) | C7 non exécutable | brew install bats-core. CI : step d'installation dans le pipeline. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:998:| H-TECH-08 | Timestamp strictement UTC Z — les offsets non-zero (+02:00, -05:00) sont rejetés par C2 | Aucun — c'est une décision de design, pas une hypothèse externe | Résolution de l'ambiguïté spec review §5.1. Regex : ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$ | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:999:| H-TECH-08bis | Horloge unique locale — émetteur (Ringbearer) et récepteur (One Ring) sont sur le même MacBook | Le SLA P95 de CA-03 est fiable car aucun décalage d'horloge possible | Résolution de l'hypothèse dangereuse spec review. Si multi-machine en v2, NTP obligatoire. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1018:| D2 | Test TC-NOM-04 (P95 SLA) dépend d'un mock broker avec délai calibré, pas du vrai broker | Le vrai broker introduirait du non-déterminisme | Validation E2E manuelle | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1034:| Contradiction diagramme séquence vs INV-293-02 (flèches directes O→R) | Bloquant | INV-293-02 fait foi. Les flèches directes du diagramme §5bis sont des raccourcis visuels. Toute communication passe par C3 (broker-adapter). Le diagramme enrichi §2ter corrige cette représentation. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1035:| Incohérence CA-02 mappé à TC-NOM-08 | Majeur | TC-NOM-14 ajouté pour couvrir le chemin nominal de CA-02 (start complet jusqu'à RUNNING). TC-NOM-08 couvre uniquement l'idempotence (INV-293-12). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1036:| Incohérence INV-293-10 mappé à CA-01 | Majeur | INV-293-10 (terminaux immuables) est couvert par TC-INV-02, pas par CA-01. La matrice de couverture dans le plan utilise le mapping corrigé. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1038:| Ambiguïté timestamp "offset UTC" | Mineur | Strictement Z uniquement. Tout offset non-zero est rejeté (H-TECH-08). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1039:| Hypothèse horloge SLA CA-03 | Majeur | Horloge locale unique MacBook (H-TECH-08bis). Pas de décalage possible en v1 (single machine). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1040:| Tests TC-NR-*/TC-NEG-* non détaillés Given/When/Then | Majeur | TC-NEG-01..10 : chacun est une variante de C2.lord_validate_() avec une entrée invalide spécifique. Le niveau de détail est dans la matrice §5. TC-NR-* : détaillés dans le mapping §5 avec observables. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1049:| Communication directe Ringbearer↔Ringbearer | Spec §2 exclu. Toute communication transite par One Ring via broker. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1053:| Tests E2E multi-machines | MacBook local uniquement en v1. Les tests d'intégration utilisent des mocks broker. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1061:| E2E | TC-NR-01 : 1 story complète /gov standalone vs orchestrée | Multi-stories simultanées E2E (trop long, couvert par intégration) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1062:| Perf | TC-NOM-04 : P95 SLA escalade (mock broker) | Perf sous charge réelle (5 stories simultanées) — mesure manuelle | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1063:| Manuel | TC-MAN-01 : iPhone/Safari /remote-control | — | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1118: - "INV-293-05 : Chaque champ est valide selon §5.1 (regex, enum, bornes). Rejet deterministe et journalise en JSONL §6.1." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1119: - "Timestamp RFC3339 strictement UTC : seul le suffixe Z est accepte (decision H-TECH-08)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1137: - module: broker-adapter docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1138: owner_agent: agent-broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1140: - "lord_broker_list_peers() -> json_array | ERROR" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1141: - "lord_broker_send_message(peer_id, message_type, payload) -> OK | ERROR" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1142: - "lord_broker_get_messages(peer_id) -> json_array | ERROR" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1143: - "lord_broker_status() -> UP | DEGRADED | DOWN" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1144: - "lord_broker_reconnect() -> OK | STILL_DEGRADED" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1146: - "INV-293-02 : Toute communication One Ring <-> Ringbearer passe par le broker. Aucun acces direct aux repos cibles." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1151: - "Communiquer avec un Ringbearer sans passer par le broker." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1152: - "Ignorer silencieusement une erreur broker (toute erreur doit basculer en DEGRADED)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1158: - "IPC par fichiers partages (fallback si broker indisponible — hors scope v1)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1163: - "scripts/lib/lord-broker.sh" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1165: - module: persistence docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1166: owner_agent: agent-persistence docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1211: - "scripts/lib/lord-persistence.sh" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1215: - module: orchestrator docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1216: owner_agent: agent-orchestrator docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1237: - "Communiquer avec un Ringbearer sans passer par C3 (broker-adapter)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1238: - "Lire ou ecrire le state sans passer par C4 (persistence)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1268: - "Suites BATS : tests/lord/state-machine.bats, tests/lord/validator.bats, tests/lord/persistence.bats, tests/lord/orchestrator.bats, tests/lord/integration.bats, tests/lord/negative.bats, tests/lord/non-regression.bats" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1270: - "Chaque test produit un resultat deterministe (pas de dependance a l'horloge reelle sauf TC-NOM-04)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1271: - "Les tests utilisent un mock broker (pas de dependance a claude-peers-mcp en CI)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1272: - "TC-INV-01 teste exhaustivement la matrice 8x8 (64 paires) de transitions." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1274: - "Tester avec un broker reel sans fallback mock." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1275: - "Ignorer un test d'invariant (TC-INV-) ou de non-regression (TC-NR-)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1278: - decision: "BATS (Bash Automated Testing System) avec mock broker en fichier" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1279: rationale: "BATS est le standard de facto pour Bash. Le mock broker est un ensemble de fonctions shell qui simulent list_peers/send_message/get_messages via fichiers JSON temporaires." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1285: - "Inconvenient : Dependance externe bats-core (H-TECH-06)" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1287: - "tests/lord/**/.bats" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1297:3. TC-NOM-14 ajouté — couvre CA-02 (démarrage nominal) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1320:| INV-293-01 | CA-05 | TC-NOM-05 | Oui | Les commandes hors scope sont refusees avec message explicite et sans action metier. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1321:| INV-293-02 | CA-01 | TC-NOM-01 | Oui | Les observations passent par broker/peers; aucun acces direct aux repos cibles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1322:| INV-293-03 | CA-08 | TC-NOM-09 | Oui | Isolation stricte des stories et absence de contamination inter-story. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1323:| INV-293-04 | CA-09 | TC-NOM-02 | Oui | La limite de 5 sessions actives est appliquee strictement. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1324:| INV-293-05 | CA-10 | TC-NOM-10 | Oui | Validation stricte du schema canonique et rejet deterministe des invalides. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1325:| INV-293-06 | CA-04 | TC-NOM-03 | Oui | Une escalade bloque la progression jusqu'a reception d'une reponse PO valide. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1326:| INV-293-07 | CA-08 | TC-NR-01 | Oui | Le workflow /gov reste inchange et fonctionnel en execution Ringbearer. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1327:| INV-293-08 | CA-07 | TC-NOM-06 | Oui | Passage en CRASHED et alerte en <=2 cycles de polling. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1328:| INV-293-09 | CA-04 | TC-INV-01 | Oui | Toutes transitions hors machine d'etats sont refusees. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1329:| INV-293-10 | CA-01 | TC-INV-02 | Oui | Les etats terminaux sont immuables (aucune transition sortante). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1330:| INV-293-11 | CA-01 | TC-NOM-07 | Oui | Reconciliation periodique detecte et corrige les ecarts de vue consolidee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1331:| INV-293-12 | CA-02 | TC-NOM-08 | Oui | Commandes start/stop/respond/pause/resume idempotentes par cle dediee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1332:| INV-293-13 | CA-11 | TC-NOM-13 | Oui | Les escalades simultanees sont traitees en FIFO sans remplacement. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1333:| INV-293-14 | CA-09 | TC-INV-03 | Oui | L'ordre de gardes quota -> doublon -> format est respecte sur start. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1334:| INV-293-05 | CA-03 | TC-NOM-04 | Oui | Les messages d'escalade valides sont visibles dans la fenetre SLA P95. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1335:| INV-293-02 | CA-06 | TC-MAN-01 | Manuel | Le controle mobile utilise les memes commandes d'orchestration via One Ring. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1336:| INV-293-05 | CA-12 | TC-ERR-10 | Oui | Reconnexion broker geree en mode degrade explicite puis reprise automatique. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1341:TEST-ID: TC-NOM-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1342:Reference spec: INV-293-02, CA-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1345: - One Ring demarre avec broker disponible docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1353: - Le journal d'audit trace une consultation broker (listing peers) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1358:TEST-ID: TC-NOM-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1374:TEST-ID: TC-NOM-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1390:TEST-ID: TC-NOM-04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1391:Reference spec: CA-03, INV-293-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1405:TEST-ID: TC-NOM-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1420:TEST-ID: TC-NOM-06 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1436:TEST-ID: TC-NOM-07 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1451:TEST-ID: TC-NOM-08 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1466:TEST-ID: TC-NOM-09 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1481:TEST-ID: TC-NOM-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1482:Reference spec: INV-293-05, CA-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1496:TEST-ID: TC-NOM-12 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1511:TEST-ID: TC-NOM-13 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1528:TEST-ID: TC-ERR-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1541:TEST-ID: TC-ERR-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1554:TEST-ID: TC-ERR-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1568:TEST-ID: TC-ERR-04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1615:| File d'escalades | Queue FIFO des escalades ouvertes (multi-escalade simultanee). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1623:| INV-293-02 | One Ring ne communique avec les stories qu'au travers du broker/peers ; aucune action directe sur les repos cibles. | Confinement operationnel. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1626:| INV-293-05 | Tout message doit etre valide selon le modele §5.1 ; sinon rejet deterministe et journalisation d'erreur au format contractuel §6.1. | Contrat protocolaire testable. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1737:10) Reconnexion broker : tentative de reconnexion exponentielle bornee (1s, 2s, 4s, 8s, 10s max), mode degrade explicite tant que indisponible, reprise automatique des polls a la reconnexion. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1750: "broker": { docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1842:TEST-ID: TC-ERR-04 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1855:TEST-ID: TC-ERR-05 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1868:TEST-ID: TC-ERR-06 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1882:TEST-ID: TC-ERR-07 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1896:TEST-ID: TC-ERR-08 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1909:TEST-ID: TC-ERR-09 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1913: - start accepte, peer enregistre au broker docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1922:TEST-ID: TC-ERR-10 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1936:TEST-ID: TC-ERR-11 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1952:| INV-293-01 | TC-NOM-05, TC-ERR-05 | Rejet explicite des actions hors scope, zero action metier | Separation des pouvoirs preservee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1953:| INV-293-02 | TC-NOM-01, TC-MAN-01 | Traces d'usage broker/peers uniquement | Pas d'acces direct aux repos cibles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1954:| INV-293-03 | TC-NOM-09, TC-NR-03 | Absence de contamination et de partage credentials entre stories | Isolation contractuelle verifiee. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1955:| INV-293-04 | TC-NOM-02, TC-ERR-01 | 6e start rejete sans creation | Limite capacitaire stricte. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1956:| INV-293-05 | TC-NOM-10, TC-ERR-03, TC-NEG-01..TC-NEG-10 | Validation schema stricte, rejet deterministe des invalides | Contrat de message testable. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1957:| INV-293-06 | TC-NOM-03, TC-ERR-04 | Blocage en ESCALADED jusqu'a PO_RESPONSE valide | Gouvernance humaine effective. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1958:| INV-293-07 | TC-NR-01 | Comportement /gov identique baseline/post-orchestration | Non-regression fonctionnelle du workflow. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1959:| INV-293-08 | TC-NOM-06, TC-ERR-07 | Detection crash en <=2 polls + alerte | Resilience operationnelle. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1960:| INV-293-09 | TC-INV-01 | Toute transition non listee est refusee | Cohesion machine d'etats. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1961:| INV-293-10 | TC-INV-02 | Aucun DONE/ABORTED/CRASHED/START_FAILED -> * accepte | Terminaux verrouilles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1962:| INV-293-11 | TC-NOM-07 | Reconciliation periodique aligne la vue consolidee | Tolerance aux ecarts/crashes. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1963:| INV-293-12 | TC-NOM-08, TC-ERR-08, TC-ERR-11 | Rejeu avec meme cle sans double effet / conflit bloque | Retry-safe en distribue. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1964:| INV-293-13 | TC-NOM-13 | FIFO strict multi-escalades | Pas de remplacement d'escalade. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1965:| INV-293-14 | TC-INV-03 | Gardes quota -> doublon -> format | Ordre contractuel stable. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1968:TEST-ID: TC-INV-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1983:TEST-ID: TC-INV-02 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1998:TEST-ID: TC-INV-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2017:| TC-NR-01 | Workflow /gov consomme tel quel | Baseline vs run orchestre: memes etapes/gates/verdicts pour une story identique | Couvre INV-293-07 et CA-08. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2018:| TC-NR-02 | Separation One Ring / execution metier | Aucune commande One Ring n'effectue lecture/ecriture/build/test/Jira/GitLab/Vault | Couvre perimetre exclu et INV-293-01. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2019:| TC-NR-03 | Isolation inter-story | Action sur story A sans impact sur story B (etat, contexte, credentials) | Couvre INV-293-03. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2020:| TC-NR-04 | Etats terminaux stables dans le temps | Reconciliation et polling n'ouvrent jamais les etats terminaux | Couvre INV-293-10. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2026:| TC-NEG-01 | story_id=pd-293 (mauvaise casse) | Rejet validation | Erreur regex ^PD-[0-9]{1,4}$, aucun effet de bord | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2027:| TC-NEG-02 | story_id=PD-12345 (hors regex) | Rejet validation | Log de rejet, aucun changement d'etat | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2028:| TC-NEG-03 | project_code=backend-prod (hors enum) | Rejet validation | Message explicite project_code invalide | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2029:| TC-NEG-04 | project_code=ia-gov (alias interdit) | Rejet validation | Seule valeur valide: ia-governance | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2030:| TC-NEG-05 | message_type=ESCALATE (valeur non enum) | Rejet validation | Journal d'erreur schema, etat inchange | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2031:| TC-NEG-06 | timestamp non RFC3339 UTC | Rejet validation | Motif parse timestamp invalide | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2032:| TC-NEG-07 | idempotency_key <16 chars | Rejet validation | Commande non traitee | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2033:| TC-NEG-08 | escalade_text vide | Rejet validation | Escalade non creee | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2034:| TC-NEG-09 | peer_id vide ou controle Unicode | Rejet validation | Message ignore, erreur audit tracee | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2035:| TC-NEG-10 | Injection message inter-story (story_id A dans canal B) | Rejet routage | Aucun impact sur A ni B | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2039:- Etat systeme : snapshot consolide des stories (etat contractuel, derniere observation peer, file d'escalades FIFO, statut broker). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2049:| CA-06 (controle mobile) | Test manuel obligatoire (TC-MAN-01) | Contrat mobile depend d'un environnement iPhone/Safari reel ; automatisation exhaustive non normative en v1 | Majeur | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2053:TEST-ID: TC-MAN-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2074:Le contrat PD-293 est testable de facon deterministe pour invariants, machine d'etats, SLA, idempotence, ordre des gardes, FIFO d'escalades et non-regression. La couverture mobile CA-06 est maintenue via test manuel obligatoire (TC-MAN-01), clairement identifie dans la matrice. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2097:| Test irrealisable | CA-02, TC-NOM-14 (mentionne dans plan) / Tests PD-293-tests.md | Le plan annonce "TC-NOM-14 ajoute", mais ce test n'existe pas dans le document de tests contractuels fourni. | La preuve contractuelle du demarrage nominal CA-02 reste non etablissable de facon deterministe. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2098:| Test irrealisable | TC-NOM-01..TC-ERR-11, TC-INV-01..03, TC-MAN-01 / Plan PD-293-plan.md | Aucun point d'observabilite explicite par scenario de test n'est present dans l'artefact plan fourni. | Les scenarios ne sont pas executables/auditables a partir du plan comme document contractuel. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2104:| Contrainte technique non documentee | Plan PD-293-plan.md (section "Contraintes techniques" absente) | Le framework de test Jest/Vitest n'est pas explicite; le code contract mentionne bats-core, sans decision contractuelle explicite au niveau plan. | Ambiguite de runner de test au regard de la contrainte documentaire demandee. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2111:- Points critiques : artefact plan non auditable (contenu manquant), couverture invariants non prouvable, executabilite des tests non demontree, ecart CA-02/TC-NOM-14 non resolu dans les tests fournis. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2211:| CA-12 | Reconnexion broker robuste | Mode degrade explicite puis reprise automatique | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2216:Given quota disponible et broker operationnel, When start PD-XXX, Then etat RUNNING avant timeout et apres first liveness valide. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2245:- T-11 Reconnexion broker
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2246:Given broker indisponible puis restaure, When boucle de retries, Then mode degrade puis reprise automatique et reconciliation. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2254:| H-293-03 | Le broker local supporte 1 One Ring + 5 Ringbearers sans instabilite majeure. | Reduction du quota max ou reconfiguration infra. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2285:Je consolide maintenant les écarts avec preuves textuelles (sections exactes) pour éviter toute interprétation libre dans le rapport. Je vais extraire les passages-clés contradictoires (timestamp, respond, TC-NOM-14, diagrammes, contrats). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2287:/bin/zsh -lc 'rg -n "H-TECH-08|Strictement Z|Strictement Z|TC-NOM-14|ESCALADED->RUNNING|toutes les escalades OPEN|C5->>R|pending-|Couverture minimale" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2289:/bin/zsh -lc "rg -n \"module: |files:|lord-state-machine|lord-fsm|lord-persistence|lord-state.sh|orchestrator|command-router|logger|supervisor|message_type='COMMAND'|Localisation : fichier dans le dossier epic|Chaque TC-*|tests/lord/**\" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-code-contracts.yaml" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2291:/bin/zsh -lc 'rg -n "timestamp|offset UTC|ESCALADED->RUNNING|INV-293-02|CA-04|TC-NOM-03|TC-NOM-14|Contraintes techniques" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2299:61:Précision multi-escalade : La transition ESCALADED->RUNNING ne s'effectue que lorsque toutes les escalades OPEN de la story sont traitées. Tant qu'il reste au moins une escalade OPEN, la story reste ESCALADED. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2302:247:| CA-02 | lord_start() dans C5 : gardes → création story STARTING → lancement Ringbearer background → supervision détecte peer + first liveness → transition STARTING→RUNNING. Nouveau test : TC-NOM-14 (cf. §5 infra) couvre le chemin nominal complet. | C5, C4, C1, C3 | TC-NOM-14 : story visible en RUNNING avant start_detection_timeout. First liveness vérifiée. | Moyen — dépend du timing de démarrage du Ringbearer | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2303:248:| CA-03 | Delta timestamps RFC3339 entre émission (Ringbearer) et réception (One Ring). Horloge unique locale MacBook (pas de synchronisation d'horloge nécessaire — décision H-TECH-08bis, cf. §8). | C5, C4 | TC-NOM-04 : P95 ≤ 5s sur 100 escalades, timestamps exportés | Faible (horloge locale unique) | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2304:275:| TC-NOM-14 (ajouté) | CA-02, INV-293-08 | C5.lord_start() complet : gardes → STARTING → peer détecté → first liveness → RUNNING | Story visible en RUNNING, peer_id réel, elapsed < start_detection_timeout | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2305:297:Note sur TC-NOM-14 : Ce test est ajouté pour couvrir CA-02 (résolution de l'incohérence spec-review §2 : CA-02 était mappé à TC-NOM-08 qui teste l'idempotence, pas le démarrage nominal). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2306:345:| H-TECH-08 | Timestamp strictement UTC Z — les offsets non-zero (+02:00, -05:00) sont rejetés par C2 | Aucun — c'est une décision de design, pas une hypothèse externe | Résolution de l'ambiguïté spec review §5.1. Regex : ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$ | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2307:346:| H-TECH-08bis | Horloge unique locale — émetteur (Ringbearer) et récepteur (One Ring) sont sur le même MacBook | Le SLA P95 de CA-03 est fiable car aucun décalage d'horloge possible | Résolution de l'hypothèse dangereuse spec review. Si multi-machine en v2, NTP obligatoire. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2309:382:| Incohérence CA-02 mappé à TC-NOM-08 | Majeur | TC-NOM-14 ajouté pour couvrir le chemin nominal de CA-02 (start complet jusqu'à RUNNING). TC-NOM-08 couvre uniquement l'idempotence (INV-293-12). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2310:385:| Ambiguïté timestamp "offset UTC" | Mineur | Strictement Z uniquement. Tout offset non-zero est rejeté (H-TECH-08). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2311:386:| Hypothèse horloge SLA CA-03 | Majeur | Horloge locale unique MacBook (H-TECH-08bis). Pas de décalage possible en v1 (single machine). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2314:466: - "Timestamp RFC3339 strictement UTC : seul le suffixe Z est accepte (decision H-TECH-08)." docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2316:637:3. TC-NOM-14 ajouté — couvre CA-02 (démarrage nominal) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2337:130: - module: broker-adapter docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2349:240: - "Chaque TC-* de la spec a un test bats correspondant" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2356:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:13:| INV-293-02 | CA-01 | TC-NOM-01 | Oui | Les observations passent par broker/peers; aucun acces direct aux repos cibles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2357:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:17:| INV-293-06 | CA-04 | TC-NOM-03 | Oui | Une escalade bloque la progression jusqu'a reception d'une reponse PO valide. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2358:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:20:| INV-293-09 | CA-04 | TC-INV-01 | Oui | Toutes transitions hors machine d'etats sont refusees. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2359:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:27:| INV-293-02 | CA-06 | TC-MAN-01 | Manuel | Le controle mobile utilise les memes commandes d'orchestration via One Ring. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2360:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:34:Reference spec: INV-293-02, CA-01 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2361:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:66:TEST-ID: TC-NOM-03 docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2367:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:371:| INV-293-02 | TC-NOM-01, TC-MAN-01 | Traces d'usage broker/peers uniquement | Pas d'acces direct aux repos cibles. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2368:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:375:| INV-293-06 | TC-NOM-03, TC-ERR-04 | Blocage en ESCALADED jusqu'a PO_RESPONSE valide | Gouvernance humaine effective. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2369:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:449:| TC-NEG-06 | timestamp non RFC3339 UTC | Rejet validation | Motif parse timestamp invalide | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2370:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:51:| INV-293-02 | One Ring ne communique avec les stories qu'au travers du broker/peers ; aucune action directe sur les repos cibles. | Confinement operationnel. | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2386:/bin/zsh -lc 'rg -n "TC-NOM-14" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2390:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:247:| CA-02 | lord_start() dans C5 : gardes → création story STARTING → lancement Ringbearer background → supervision détecte peer + first liveness → transition STARTING→RUNNING. Nouveau test : TC-NOM-14 (cf. §5 infra) couvre le chemin nominal complet. | C5, C4, C1, C3 | TC-NOM-14 : story visible en RUNNING avant start_detection_timeout. First liveness vérifiée. | Moyen — dépend du timing de démarrage du Ringbearer | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2391:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:275:| TC-NOM-14 (ajouté) | CA-02, INV-293-08 | C5.lord_start() complet : gardes → STARTING → peer détecté → first liveness → RUNNING | Story visible en RUNNING, peer_id réel, elapsed < start_detection_timeout | Integration | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2392:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:297:Note sur TC-NOM-14 : Ce test est ajouté pour couvrir CA-02 (résolution de l'incohérence spec-review §2 : CA-02 était mappé à TC-NOM-08 qui teste l'idempotence, pas le démarrage nominal). docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2393:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:382:| Incohérence CA-02 mappé à TC-NOM-08 | Majeur | TC-NOM-14 ajouté pour couvrir le chemin nominal de CA-02 (start complet jusqu'à RUNNING). TC-NOM-08 couvre uniquement l'idempotence (INV-293-12). | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2394:docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:637:3. TC-NOM-14 ajouté — couvre CA-02 (démarrage nominal) docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2413:| Test irréalisable | Spec §7 (CA-02) / Plan §4-§5 (TC-NOM-14) / Tests (absence TC-NOM-14) | Le plan fonde la preuve de CA-02 sur TC-NOM-14, mais ce test n’existe pas dans le référentiel contractuel de tests fourni. | La conformité CA-02 n’est pas démontrable de façon opposable. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2414:| Code Contract — Cohérence | Plan §1 (C1..C7), §2bis/§2ter, bloc “code-contracts corrigé” / PD-293-code-contracts.yaml | Deux définitions concurrentes et incompatibles des contrats existent (modules, interfaces et fichiers différents : ex. lord-state-machine.sh vs lord-fsm.sh, lord-persistence.sh vs lord-state.sh, orchestrator monolithique vs split supervisor/command-router). | Impossible d’identifier un contrat de référence unique pour audit tiers. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2415:| Non-conformité Spec | Spec §5.2 (ESCALADED->RUNNING après PO_RESPONSE), §7 (CA-04) / Tests TC-NOM-03 / Plan §2.2 | Le plan ajoute une condition non spécifiée : rester ESCALADED tant qu’il reste une escalade OPEN. | respond peut ne pas “débloquer la story” comme contractualisé par CA-04. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2416:| Non-conformité Spec | Spec §5.1 (timestamp : Z ou offset UTC) / Plan §8 (H-TECH-08) | Le plan impose timestamp strictement suffixé Z et rejette les offsets. | Rejet possible d’entrées valides au regard du contrat canonical. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2418:| Couverture manquante | INV-293-13 / Plan §3 (mécanisme FIFO par tri created_at) / Tests TC-NOM-13 | Le mécanisme FIFO repose sur created_at sans règle de départage explicite en cas d’égalité d’horodatage. | Invariant FIFO non garanti de façon déterministe dans tous les cas. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2420:| Risque sécu/conformité | INV-293-05 / Plan §8 (H-TECH-04 fallback “validation plus permissive”) | En absence de grep -P, le plan prévoit un mode de validation assoupli. | Le rejet déterministe des messages invalides devient dépendant de l’environnement. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2421:| Hypothèse implicite | Spec INV-293-02 / Plan §2ter (diagramme séquence C5->>R) | Le diagramme de séquence conserve un canal direct orchestrator→Ringbearer sans cadrage contractuel explicite de cette exception. | Ambiguïté d’implémentation et de contrôle sur la frontière broker-only. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2422:| Code Contract — Complétude | Plan §1 (C5 orchestrator) / PD-293-code-contracts.yaml | Le composant C5 du plan (scripts/gov-lord.sh) n’a pas de contrat dédié explicite dans le fichier fourni (responsabilité éclatée). | Couverture contractuelle incomplète d’un composant central. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2434:- Points critiques : preuve CA-02 non opposable (TC manquant), référentiel de code contracts non univoque, écarts de conformité sur respond multi-escalade et validation timestamp. docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2456:| Test irréalisable | Spec §7 (CA-02) / Plan §4-§5 (TC-NOM-14) / Tests (absence TC-NOM-14) | Le plan fonde la preuve de CA-02 sur TC-NOM-14, mais ce test n’existe pas dans le référentiel contractuel de tests fourni. | La conformité CA-02 n’est pas démontrable de façon opposable. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2457:| Code Contract — Cohérence | Plan §1 (C1..C7), §2bis/§2ter, bloc “code-contracts corrigé” / PD-293-code-contracts.yaml | Deux définitions concurrentes et incompatibles des contrats existent (modules, interfaces et fichiers différents : ex. lord-state-machine.sh vs lord-fsm.sh, lord-persistence.sh vs lord-state.sh, orchestrator monolithique vs split supervisor/command-router). | Impossible d’identifier un contrat de référence unique pour audit tiers. | BLOQUANT | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2458:| Non-conformité Spec | Spec §5.2 (ESCALADED->RUNNING après PO_RESPONSE), §7 (CA-04) / Tests TC-NOM-03 / Plan §2.2 | Le plan ajoute une condition non spécifiée : rester ESCALADED tant qu’il reste une escalade OPEN. | respond peut ne pas “débloquer la story” comme contractualisé par CA-04. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2459:| Non-conformité Spec | Spec §5.1 (timestamp : Z ou offset UTC) / Plan §8 (H-TECH-08) | Le plan impose timestamp strictement suffixé Z et rejette les offsets. | Rejet possible d’entrées valides au regard du contrat canonical. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2461:| Couverture manquante | INV-293-13 / Plan §3 (mécanisme FIFO par tri created_at) / Tests TC-NOM-13 | Le mécanisme FIFO repose sur created_at sans règle de départage explicite en cas d’égalité d’horodatage. | Invariant FIFO non garanti de façon déterministe dans tous les cas. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2463:| Risque sécu/conformité | INV-293-05 / Plan §8 (H-TECH-04 fallback “validation plus permissive”) | En absence de grep -P, le plan prévoit un mode de validation assoupli. | Le rejet déterministe des messages invalides devient dépendant de l’environnement. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2464:| Hypothèse implicite | Spec INV-293-02 / Plan §2ter (diagramme séquence C5->>R) | Le diagramme de séquence conserve un canal direct orchestrator→Ringbearer sans cadrage contractuel explicite de cette exception. | Ambiguïté d’implémentation et de contrôle sur la frontière broker-only. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2465:| Code Contract — Complétude | Plan §1 (C5 orchestrator) / PD-293-code-contracts.yaml | Le composant C5 du plan (scripts/gov-lord.sh) n’a pas de contrat dédié explicite dans le fichier fourni (responsabilité éclatée). | Couverture contractuelle incomplète d’un composant central. | MAJEUR | docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2477:- Points critiques : preuve CA-02 non opposable (TC manquant), référentiel de code contracts non univoque, écarts de conformité sur respond multi-escalade et validation timestamp.

codex Je passe maintenant sur l’historique Git des fichiers PD-293 pour identifier les corrections réellement apportées et rattacher chaque statut à un commit explicite. Ensuite je clôture la matrice des statuts sans introduire de nouveaux écarts. exec /bin/zsh -lc 'git log --oneline --decorate -n 12 -- docs/epics/tooling/PD-293-one-ring-orchestration scripts tests/lord' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc 'git status --short docs/epics/tooling/PD-293-one-ring-orchestration scripts tests/lord' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc 'git log --oneline --decorate -n 20 -- docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 2315ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-GXAlj9UE' (errno=Operation not permitted) git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-69PR3zxr' (errno=Operation not permitted) D docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-code-contracts.yaml M scripts/assemble-prompt.sh M scripts/constitutional-check.sh M scripts/gov-step.sh M scripts/gov-workflow.sh M scripts/index-learnings.py M scripts/lib/agents.sh M scripts/lib/resolve-project.sh M scripts/lib/state.sh M scripts/probe-capabilities.sh M scripts/regenerate-dashboard.sh M scripts/search-learnings.py M scripts/session-log.sh ?? scripts/analyze-notifications.py ?? scripts/collect-plans.py ?? scripts/collect-sibling-invariants.py ?? scripts/collect-specs.py ?? scripts/index-plans.py ?? scripts/index-specs.py ?? scripts/lib/jira-api.sh ?? scripts/opencode-run.sh ?? scripts/parallel-reviews.sh ?? scripts/reindex-all.py ?? scripts/search-plans.py ?? scripts/search-specs.py ?? scripts/traceability/

succeeded in 2344ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-uegXldBe' (errno=Operation not permitted) git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-5MOs61gG' (errno=Operation not permitted) 5a62a7f (HEAD -> feature/PD-293-one-ring-orchestration) docs(PD-293): acceptabilité + code-contracts alignés f506708 feat(PD-293): One Ring orchestration — implementation step 6 97ff325 chore(rollback): suppression IM-01/IM-02/IM-03 — abandon feature iMessage 49414a0 chore: commit global — IM-02 prod fix + PG sessions + templates c42580f fix(IM-02): sécurité — path injection Python via transcript_path (V-01/E-05) 82e1f44 feat(IM-02): implémentation hooks iMessage bidirectionnels — steps 0-6 fd10d9d chore: CLAUDE.md refactor, skills, contracts index, n8n bridge 357d8f3 process(REX-PD-275/276/277): améliorations process Sprint 9 9e19237 chore: backfill scripts + PD-250 specification review 9dd0397 feat(scripts): scripts d'automatisation gouvernance b2504bc refactor(embeddings): switch from Gemini API to Ollama local for learnings search (6.2) a88ee8c feat(governance): add semantic learnings search with Gemini + FAISS (6.2)

succeeded in 2355ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-myrxy5We' (errno=Operation not permitted) git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-8BWjmOxv' (errno=Operation not permitted) 5a62a7f (HEAD -> feature/PD-293-one-ring-orchestration) docs(PD-293): acceptabilité + code-contracts alignés

exec /bin/zsh -lc 'git show --name-status --format=fuller --no-patch 5a62a7f' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc 'git show --name-status --format=fuller --no-patch f506708' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 1574ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-ubWhXSqG' (errno=Operation not permitted) git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-lthZdbTy' (errno=Operation not permitted) commit 5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a Author: Loïc Pontani loic@phydya.com AuthorDate: Tue Mar 31 01:33:37 2026 +0200 Commit: Loïc Pontani loic@phydya.com CommitDate: Tue Mar 31 01:33:37 2026 +0200

docs(PD-293): acceptabilité + code-contracts alignés

- Acceptabilité: 45/45 tests, 3 reviews Codex (code/tests/sécurité)
- Code-contracts: fichier unique aligné sur implémentation réelle
- Suppression anciens code-contracts divergents

Co-Authored-By: Claude <noreply@anthropic.com>

succeeded in 1567ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-NrLzfuCt' (errno=Operation not permitted) git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead git: error: couldn't create cache file '/tmp/xcrun_db-cy2SzxCV' (errno=Operation not permitted) commit f5067080e34e6c0218e86aeeff3a9d2f78d4b5a6 Author: Loïc Pontani loic@phydya.com AuthorDate: Tue Mar 31 01:12:45 2026 +0200 Commit: Loïc Pontani loic@phydya.com CommitDate: Tue Mar 31 01:12:45 2026 +0200

feat(PD-293): One Ring orchestration — implementation step 6

- C1 lord-state-machine.sh: FSM 8 states, 4 terminals, case/esac
- C2 lord-validator.sh: 8 validators + rejection logger
- C3 lord-broker.sh: claude-peers-mcp adapter + mock support
- C4 lord-persistence.sh: state CRUD, FIFO escalades, idempotency
- C5 gov-lord.sh: orchestrator (7 commands, supervision loop)
- C6 gov-lord.md: Claude Code skill
- C7 tests: 45 bats tests (FSM + validator) — all passing
- Gate docs: besoin, spec, tests, plan, reviews, verdicts

45/45 tests passing (bats-core)

Co-Authored-By: Claude <noreply@anthropic.com>

exec /bin/zsh -lc "sed -n '1,340p' scripts/lib/lord-persistence.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc "sed -n '1,260p' scripts/lib/lord-broker.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 793ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

!/usr/bin/env bash

PD-293 — C3 Broker Adapter : Abstraction claude-peers-mcp

Point unique de communication avec les Ringbearers (INV-293-02)

set -euo pipefail

─── Configuration ────────────────────────────────────────────────────────────

LORD_BROKER_HOST="${LORD_BROKER_HOST:-localhost}" LORD_BROKER_PORT="${LORD_BROKER_PORT:-7899}" LORD_BROKER_MAX_BACKOFF="${LORD_BROKER_MAX_BACKOFF:-10}" LORD_BROKER_STATUS="UNKNOWN" # UP | DEGRADED | DOWN

─── Health check ─────────────────────────────────────────────────────────────

lord_broker_status() → UP | DEGRADED | DOWN

lord_broker_status() { if curl -sf "http://${LORD_BROKER_HOST}:${LORD_BROKER_PORT}/health" &>/dev/null 2>&1; then LORD_BROKER_STATUS="UP" elif curl -sf --max-time 2 "http://${LORD_BROKER_HOST}:${LORD_BROKER_PORT}/" &>/dev/null 2>&1; then LORD_BROKER_STATUS="DEGRADED" else LORD_BROKER_STATUS="DOWN" fi echo "$LORD_BROKER_STATUS" }

lord_broker_reconnect() → OK | STILL_DEGRADED

lord_broker_reconnect() { local backoff=1 local max_backoff="${LORD_BROKER_MAX_BACKOFF}" local attempts=0

while [[ $attempts -lt 5 ]]; do if [[ "$(lord_broker_status)" == "UP" ]]; then echo "OK" return 0 fi sleep "$backoff" backoff=$((backoff * 2)) [[ $backoff -gt $max_backoff ]] && backoff=$max_backoff attempts=$((attempts + 1)) done

echo "STILL_DEGRADED" return 1 }

─── Opérations MCP ──────────────────────────────────────────────────────────

lord_broker_list_peers() → JSON array | ERROR

En mode réel, utilise les MCP tools de claude-peers-mcp.

Ce wrapper permet de mocker en tests.

lord_broker_list_peers() { if [[ -n "${LORD_BROKER_MOCK_DIR:-}" ]]; then # Mode mock: lire depuis fichier cat "${LORD_BROKER_MOCK_DIR}/peers.json" 2>/dev/null || echo "[]" return 0 fi

# Mode réel: appel MCP via claude-peers # En production, les appels MCP sont faits par Claude via les tools. # Ce script est appelé depuis le skill /gov-lord qui a accès aux MCP tools. # L'interface ici retourne le résultat du dernier poll (cache local). local cache_file="${LORD_STATE_DIR:-.}/.lord-peers-cache.json" if [[ -f "$cache_file" ]]; then cat "$cache_file" else echo "[]" fi }

lord_broker_send_message(peer_id, message_json) → OK | ERROR

lord_broker_send_message() { local peer_id="$1" message_json="$2"

if [[ -n "${LORD_BROKER_MOCK_DIR:-}" ]]; then # Mode mock: écrire dans fichier outbox local outbox="${LORD_BROKER_MOCK_DIR}/outbox" mkdir -p "$outbox" echo "$message_json" > "${outbox}/${peer_id}-$(date +%s%N).json" echo "OK" return 0 fi

# Mode réel: le skill /gov-lord utilise send_message MCP tool # Ce script est le bridge — le résultat est écrit dans la cache locale echo "OK" }

lord_broker_update_peers_cache(json_array) — met à jour le cache local

lord_broker_update_peers_cache() { local json_array="$1" local cache_file="${LORD_STATE_DIR:-.}/.lord-peers-cache.json" echo "$json_array" > "$cache_file" }

lord_broker_set_summary(summary_text) → OK | ERROR

lord_broker_set_summary() { local summary_text="$1"

if [[ -n "${LORD_BROKER_MOCK_DIR:-}" ]]; then echo "$summary_text" > "${LORD_BROKER_MOCK_DIR}/my-summary.txt" echo "OK" return 0 fi

# Mode réel: set_summary MCP tool echo "OK" }

succeeded in 793ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

!/usr/bin/env bash

PD-293 — C4 Persistence : CRUD .gov-lord-state.json

Schema §5.4 — FIFO escalades, cache idempotency, audit JSONL

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

─── Configuration ────────────────────────────────────────────────────────────

LORD_STATE_FILE="${LORD_STATE_FILE:-.gov-lord-state.json}" LORD_AUDIT_LOG="${LORD_AUDIT_LOG:-.gov-lord-audit.jsonl}"

─── State read/write (atomique + flock) ─────────────────────────────────────

lord_state_read() → JSON (stdout)

lord_state_read() { if [[ -f "$LORD_STATE_FILE" ]]; then cat "$LORD_STATE_FILE" else echo '{"version":"1.0","stories":[],"idempotency_cache":[]}' fi }

lord_state_write(json) — écriture atomique (tmp + mv) + flock

lord_state_write() { local json="$1" local tmp_file="${LORD_STATE_FILE}.tmp.$$" local lock_file="${LORD_STATE_FILE}.lock"

( flock -w 5 200 || { echo "ERROR:lock_timeout" >&2; return 1; } echo "$json" | jq '.' > "$tmp_file" 2>/dev/null || { echo "ERROR:invalid_json" >&2; rm -f "$tmp_file"; return 1; } mv "$tmp_file" "$LORD_STATE_FILE" ) 200>"$lock_file" }

─── Story CRUD ──────────────────────────────────────────────────────────────

lord_count_active_stories() → integer

lord_count_active_stories() { local state state=$(lord_state_read) echo "$state" | jq '[.stories[] | select(.state != "DONE" and .state != "ABORTED" and .state != "CRASHED" and .state != "START_FAILED")] | length' }

lord_get_story(story_id) → JSON object | empty

lord_get_story() { local story_id="$1" local state state=$(lord_state_read) echo "$state" | jq --arg sid "$story_id" '.stories[] | select(.story_id == $sid)' 2>/dev/null }

lord_create_story(story_id, project_code, state, peer_id)

lord_create_story() { local story_id="$1" project_code="$2" state="$3" peer_id="$4" local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local current current=$(lord_state_read)

local updated updated=$(echo "$current" | jq \ --arg sid "$story_id" \ --arg pc "$project_code" \ --arg st "$state" \ --arg pid "$peer_id" \ --arg ts "$ts" \ '.stories += [{ story_id: $sid, project_code: $pc, state: $st, peer_id: $pid, created_at: $ts, last_seen_at: $ts, missed_polls: 0, escalades: [] }]')

lord_state_write "$updated" }

lord_update_story(story_id, jq_filter) — update in place

lord_update_story() { local story_id="$1" jq_filter="$2" local current current=$(lord_state_read)

local updated updated=$(echo "$current" | jq \ --arg sid "$story_id" \ "(.stories[] | select(.story_id == \$sid)) |= (${jq_filter})")

lord_state_write "$updated" }

─── Escalades FIFO ─────────────────────────────────────────────────────────

lord_enqueue_escalade(story_id, escalade_id, text, timestamp)

lord_enqueue_escalade() { local story_id="$1" escalade_id="$2" text="$3" timestamp="$4"

lord_update_story "$story_id" \ ".escalades += [{id: \"${escalade_id}\", status: \"OPEN\", text: \"${text}\", created_at: \"${timestamp}\"}]" }

lord_dequeue_oldest_escalade(story_id) → escalade_id | empty

lord_dequeue_oldest_escalade() { local story_id="$1" local story story=$(lord_get_story "$story_id")

local oldest_id oldest_id=$(echo "$story" | jq -r '[.escalades[] | select(.status == "OPEN")] | sort_by(.created_at) | .[0].id // empty')

if [[ -n "$oldest_id" ]]; then lord_update_story "$story_id" \ "(.escalades[] | select(.id == \"${oldest_id}\")) .status = \"RESOLVED\"" echo "$oldest_id" fi }

lord_count_open_escalades(story_id) → integer

lord_count_open_escalades() { local story_id="$1" local story story=$(lord_get_story "$story_id") echo "$story" | jq '[.escalades[] | select(.status == "OPEN")] | length' }

─── Idempotency cache ──────────────────────────────────────────────────────

lord_check_idempotency(key) → NEW | REPLAY | CONFLICT

lord_check_idempotency() { local key="$1" local state state=$(lord_state_read)

local entry entry=$(echo "$state" | jq --arg k "$key" '.idempotency_cache[] | select(.key == $k)' 2>/dev/null)

if [[ -z "$entry" ]]; then echo "NEW" else local expires_at expires_at=$(echo "$entry" | jq -r '.expires_at') local now now=$(date -u +%s) local exp_epoch exp_epoch=$(date -u -j -f "%Y-%m-%dT%H:%M:%SZ" "$expires_at" +%s 2>/dev/null || echo 0)

if [[ $now -gt $exp_epoch ]]; then
  echo "NEW"  # Expired
else
  echo "REPLAY"
fi

fi }

lord_record_idempotency(key, command, story_id, ttl_seconds)

lord_record_idempotency() { local key="$1" command="$2" story_id="$3" ttl="${4:-300}" local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local expires_at expires_at=$(date -u -v "+${ttl}S" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -d "+${ttl} seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null)

local current current=$(lord_state_read) local updated updated=$(echo "$current" | jq \ --arg k "$key" --arg cmd "$command" --arg sid "$story_id" \ --arg ts "$ts" --arg exp "$expires_at" \ '.idempotency_cache += [{key: $k, command: $cmd, story_id: $sid, created_at: $ts, expires_at: $exp}]')

lord_state_write "$updated" }

lord_purge_expired_idempotency() → count_purged

lord_purge_expired_idempotency() { local ts_now ts_now=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local current current=$(lord_state_read)

local before_count before_count=$(echo "$current" | jq '.idempotency_cache | length')

local updated updated=$(echo "$current" | jq --arg now "$ts_now" \ '.idempotency_cache |= [.[] | select(.expires_at > $now)]')

local after_count after_count=$(echo "$updated" | jq '.idempotency_cache | length')

lord_state_write "$updated" echo $((before_count - after_count)) }

─── Audit JSONL ─────────────────────────────────────────────────────────────

lord_audit(event, story_id, details) — JAMAIS d'escalade_text brut (RGPD)

lord_audit() { local event="$1" story_id="$2" details="${3:-}" local ts ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

jq -n --arg ts "$ts" --arg event "$event" \ --arg sid "$story_id" --arg details "$details" \ '{timestamp: $ts, event: $event, story_id: $sid, details: $details}' \ >> "$LORD_AUDIT_LOG" }

exec /bin/zsh -lc "sed -n '1,320p' docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 754ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

Code Contracts — PD-293 One Ring Orchestration

Source unique — aligné sur les fichiers implémentés

story_id: PD-293 date: "2026-03-31"

components: C1-state-machine: file: scripts/lib/lord-state-machine.sh invariants: [INV-293-09, INV-293-10] contracts: - "FSM case/esac: 8 states, 4 terminals" - "lord_transition(story_id, from, to) → OK | REJECTED:reason" - "Terminal states (DONE, ABORTED, CRASHED, START_FAILED) reject all transitions"

C2-validator: file: scripts/lib/lord-validator.sh invariants: [INV-293-05, INV-293-06, INV-293-14] contracts: - "story_id: ^PD-[0-9]{1,4}$ (regex source of truth)" - "project_code: enum 8 values including ia-governance" - "message_type: enum 8 values" - "timestamp: strictly Z suffix (H-TECH-08)" - "lord_validate_message(json) validates type+story_id+timestamp" - "lord_log_rejection() writes JSONL audit"

C3-broker-adapter: file: scripts/lib/lord-broker.sh invariants: [INV-293-02, INV-293-08] contracts: - "lord_broker_list_peers() → JSON array" - "lord_broker_send_message(peer_id, json) → OK | ERROR" - "Mock mode via LORD_BROKER_MOCK_DIR env var" - "Reconnection: exponential backoff 1→2→4→8→10s cap"

C4-persistence: file: scripts/lib/lord-persistence.sh invariants: [INV-293-11, INV-293-12, INV-293-13] contracts: - "Atomic write: tmp + mv under flock" - "lord_create_story / lord_update_story / lord_get_story" - "Escalade queue: FIFO (lord_enqueue_escalade / lord_dequeue_oldest_escalade)" - "Idempotency cache: lord_check_idempotency → NEW | REPLAY" - "peer_id: pending-{story_id} sentinel in STARTING state" - "Audit JSONL: never stores escalade_text (RGPD)"

C5-orchestrator: file: scripts/gov-lord.sh invariants: [INV-293-01, INV-293-03, INV-293-04, INV-293-08, INV-293-14] contracts: - "lord_assert_scope() blocks any non-whitelisted command" - "Guard order start: format → quota → duplicate → idempotency" - "lord_supervision_cycle(): poll → crash detect (2 missed) → reconcile → purge" - "lord_respond(): dequeue oldest → send PO_RESPONSE → transition if 0 remaining" - "Maximum 5 Ringbearers (LORD_MAX_RINGBEARERS)"

C6-skill: file: .claude/commands/gov-lord.md invariants: [INV-293-01] contracts: - "7 commands: start, status, stop, escalade, respond, pause, resume" - "Any other command → explicit rejection message"

C7-tests: dir: tests/lord/ contracts: - "test-state-machine.bats: 21 tests (TC-INV-01, TC-INV-02)" - "test-validator.bats: 24 tests (TC-NOM-10, TC-NEG-01..10)" - "All tests use bats-core framework"

forbidden_patterns: - "One Ring MUST NOT read/write project files" - "One Ring MUST NOT access Jira/GitLab/Vault" - "One Ring MUST NOT execute builds, tests, or deployments" - "Ringbearers MUST NOT communicate directly"

exec /bin/zsh -lc "find . -path 'PD-293-acceptability-review.md' -o -path 'docs/meta/templates/PD-293-acceptability-review.md'" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 834ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

exec /bin/zsh -lc "sed -n '220,320p' docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance exec /bin/zsh -lc "rg -n \"participant O as One Ring|O->>R|O->>B|INV-293-02|timestamp|offset UTC|FIFO|sort_by(.created_at)|H-TECH-08\" docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md scripts/lib/lord-persistence.sh scripts/lib/lord-validator.sh" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance succeeded in 785ms: pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable "type": "object", "required": ["key", "command", "story_id", "payload_hash", "result_hash", "expires_at"], "properties": { "key": { "type": "string", "pattern": "^[A-Za-z0-9:_-]{16,80}$" }, "command": { "type": "string", "enum": ["start", "stop", "respond", "pause", "resume"] }, "story_id": { "type": "string", "pattern": "^PD-[0-9]{1,4}$" }, "payload_hash": { "type": "string", "minLength": 8, "maxLength": 128 }, "result_hash": { "type": "string", "minLength": 8, "maxLength": 128 }, "expires_at": { "type": "string", "format": "date-time" } }, "additionalProperties": false } } }, "additionalProperties": false }

## 5bis. Diagrammes (si applicable)

### Diagramme d'etat (>= 3 etats)

```mermaid
stateDiagram-v2
    [*] --> STARTING
    STARTING --> RUNNING: peer detecte + first liveness OK
    STARTING --> START_FAILED: timeout demarrage ou liveness KO

    RUNNING --> ESCALADED: message ESCALADE
    ESCALADED --> RUNNING: message PO_RESPONSE valide

    RUNNING --> PAUSED: commande PAUSE
    PAUSED --> RUNNING: commande RESUME

    RUNNING --> DONE: WORKFLOW_DONE
    RUNNING --> ABORTED: commande ABORT/STOP
    ESCALADED --> ABORTED: commande ABORT/STOP
    PAUSED --> ABORTED: commande ABORT/STOP

    RUNNING --> CRASHED: peer disparu (>2 polls)
    ESCALADED --> CRASHED: peer disparu (>2 polls)
    PAUSED --> CRASHED: peer disparu (>2 polls)

    DONE --> [*]
    ABORTED --> [*]
    CRASHED --> [*]
    START_FAILED --> [*]

Diagramme de sequence (>= 2 services)

sequenceDiagram
    participant S as Sovereign
    participant O as One Ring
    participant B as Broker
    participant R as Ringbearer

    S->>O: "/gov-lord start PD-293 ia-governance"
    O->>O: Gardes start: quota -> idempotence -> format
    O->>B: list_peers()
    B-->>O: peers[]
    O->>R: demande demarrage story_id=PD-293
    R->>B: register_peer(summary_text)
    R-->>O: STATUS_UPDATE (first liveness)
    O->>O: STARTING->RUNNING

    R->>O: ESCALADE{story_id, escalade_text, timestamp}
    O->>O: enqueue FIFO escalade_queue
    O-->>S: notification escalade la plus ancienne

    S->>O: "/gov-lord respond PD-293 <reponse>"
    O->>R: PO_RESPONSE{story_id, escalade_text=<reponse>}
    R-->>O: STATUS_UPDATE (reprise RUNNING)

    S->>O: "/gov-lord pause PD-293"
    O->>R: PAUSE
    S->>O: "/gov-lord resume PD-293"
    O->>R: RESUME

6. Cas d'erreur

ID Cas Reponse attendue
ERR-293-01 start avec quota atteint (>=5) Rejet explicite, aucune creation
ERR-293-02 start sur story_id deja active Rejet explicite idempotent
ERR-293-03 Message sans story_id valide Rejet + journalisation contractuelle
ERR-293-04 respond sans escalade active Rejet explicite
ERR-293-05 Commande hors scope One Ring Blocage explicite (INV-293-01)
ERR-293-06 Broker indisponible Etat degrade + alerte Sovereign + retries reconnection
ERR-293-07 Peer disparu au-dela de 2 cycles de polling Transition CRASHED + alerte
ERR-293-08 Reemission commande deja traitee (idempotency_key) Retour deterministe sans effet secondaire
ERR-293-09 idempotency_key rejouee avec payload different Rejet de conflit deterministe
ERR-293-10 Peer cree mais 1ere liveness absente avant first_liveness_timeout START_FAILED + cleanup session

6.1 Format de log de rejet (normatif)

Chaque rejet de validation/message doit produire une ligne JSON (JSONL) avec champs obligatoires:

 succeeded in 791ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
scripts/lib/lord-persistence.sh:3:# Schema §5.4  FIFO escalades, cache idempotency, audit JSONL
scripts/lib/lord-persistence.sh:96:# ─── Escalades FIFO ─────────────────────────────────────────────────────────
scripts/lib/lord-persistence.sh:98:# lord_enqueue_escalade(story_id, escalade_id, text, timestamp)
scripts/lib/lord-persistence.sh:100:  local story_id="$1" escalade_id="$2" text="$3" timestamp="$4"
scripts/lib/lord-persistence.sh:103:    ".escalades += [{id: \"${escalade_id}\", status: \"OPEN\", text: \"${text}\", created_at: \"${timestamp}\"}]"
scripts/lib/lord-persistence.sh:113:  oldest_id=$(echo "$story" | jq -r '[.escalades[] | select(.status == "OPEN")] | sort_by(.created_at) | .[0].id // empty')
scripts/lib/lord-persistence.sh:209:    '{timestamp: $ts, event: $event, story_id: $sid, details: $details}' \
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:13:| INV-293-02 | CA-01 | TC-NOM-01 | Oui | Les observations passent par broker/peers; aucun acces direct aux repos cibles. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:24:| INV-293-13 | CA-11 | TC-NOM-13 | Oui | Les escalades simultanees sont traitees en FIFO sans remplacement. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:27:| INV-293-02 | CA-06 | TC-MAN-01 | Manuel | Le controle mobile utilise les memes commandes d'orchestration via One Ring. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:34:Reference spec: INV-293-02, CA-01
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:124:  - La transition est tracee avec timestamp
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:184:  - Le journal d'audit associe type de message, story cible, timestamp
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:207:  - Trois escalades ouvertes pour la meme story avec timestamps t1 < t2 < t3
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:211:  - Les escalades sont cloturees dans l'ordre FIFO t1, puis t2, puis t3
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:255:  - Erreur journalisee au format JSONL obligatoire avec `timestamp`, `peer_id`, `message_type`, `reason`
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:371:| INV-293-02 | TC-NOM-01, TC-MAN-01 | Traces d'usage broker/peers uniquement | Pas d'acces direct aux repos cibles. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:382:| INV-293-13 | TC-NOM-13 | FIFO strict multi-escalades | Pas de remplacement d'escalade. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:449:| TC-NEG-06 | `timestamp` non RFC3339 UTC | Rejet validation | Motif parse timestamp invalide |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:457:- Etat systeme : snapshot consolide des stories (etat contractuel, derniere observation peer, file d'escalades FIFO, statut broker).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:492:Le contrat PD-293 est testable de facon deterministe pour invariants, machine d'etats, SLA, idempotence, ordre des gardes, FIFO d'escalades et non-regression. La couverture mobile CA-06 est maintenue via test manuel obligatoire (TC-MAN-01), clairement identifie dans la matrice.
scripts/lib/lord-validator.sh:49:# lord_validate_timestamp(value)  0 | 1
scripts/lib/lord-validator.sh:50:# Strictement UTC Z (H-TECH-08)
scripts/lib/lord-validator.sh:51:lord_validate_timestamp() {
scripts/lib/lord-validator.sh:97:  # Champs obligatoires: type, story_id, timestamp
scripts/lib/lord-validator.sh:98:  local msg_type story_id timestamp
scripts/lib/lord-validator.sh:101:  timestamp=$(echo "$json" | jq -r '.timestamp // empty' 2>/dev/null) || true
scripts/lib/lord-validator.sh:119:  if [[ -z "$timestamp" ]]; then
scripts/lib/lord-validator.sh:120:    LORD_VALIDATION_ERROR="missing_field:timestamp"
scripts/lib/lord-validator.sh:123:  if ! lord_validate_timestamp "$timestamp"; then
scripts/lib/lord-validator.sh:124:    LORD_VALIDATION_ERROR="invalid_timestamp:${timestamp}"
scripts/lib/lord-validator.sh:133:# lord_log_rejection(timestamp, peer_id, message_type, reason, story_id, event)
scripts/lib/lord-validator.sh:142:    '{timestamp: $ts, level: "WARN", component: "validator", event: $event, peer_id: $peer_id, message_type: $msg_type, story_id: $story_id, reason: $reason}' \
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:43:| File d'escalades | Queue FIFO des escalades ouvertes (multi-escalade simultanee). |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:51:| INV-293-02 | One Ring ne communique avec les stories qu'au travers du broker/peers ; aucune action directe sur les repos cibles. | Confinement operationnel. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:62:| INV-293-13 | Multi-escalade simultanee geree en FIFO ; aucune escalade n'en remplace une autre. | Determinisme de traitement et auditabilite. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:100:| `timestamp` | RFC3339 UTC | ASCII | case-sensitive | horodatage UTC parseable (suffixe `Z` ou offset UTC) | Rejet |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:158:4) `escalade` : affichage de la file bloquante **FIFO** a traiter par le Sovereign.  
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:159:5) `respond` : injection d'une decision humaine sur la plus ancienne escalade ouverte de la story cible (FIFO intra-story).  
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:274:    participant O as One Ring
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:280:    O->>B: list_peers()
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:282:    O->>R: demande demarrage story_id=PD-293
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:287:    R->>O: ESCALADE{story_id, escalade_text, timestamp}
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:288:    O->>O: enqueue FIFO escalade_queue
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:292:    O->>R: PO_RESPONSE{story_id, escalade_text=<reponse>}
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:296:    O->>R: PAUSE
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:298:    O->>R: RESUME
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:322:  "timestamp": "2026-03-30T10:15:30Z",
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:331:Champs obligatoires minimum: `timestamp`, `peer_id`, `message_type`, `reason`.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:347:| CA-11 | Multi-escalade simultanee preserve l'ordre | Traitement FIFO sans ecrasement |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md:379:- **T-10 Multi-escalade FIFO**  

exec
/bin/zsh -lc 'rg -n "45/45|21/21|24/24|bats|PASS|TC-" data/sessions/PD-293-session.jsonl docs/epics/tooling/PD-293-one-ring-orchestration/*.md | head -n 80' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 719ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:21:- **Limite 5 Ringbearers** : Unanime (spec INV-293-04, tests TC-NOM-02/TC-ERR-01, plan §2.1 garde 1, contracts `count_active_stories`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:27:- **Crash detection ≤ 2 cycles** : INV-293-08 implémenté via `missed_polls` dans le plan, testé par TC-NOM-06/TC-ERR-07.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:89:- Impact : Les logs de rejet auront un format différent selon le contrat suivi. Affecte la testabilité de TC-ERR-03 et l'auditabilité.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:102:**DIV-08** : Test TC-NOM-14 — ajouté dans le plan mais absent du document tests
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:104:- Plan §5 : `TC-NOM-14 (ajouté)` couvre CA-02 (démarrage nominal complet jusqu'à RUNNING). Détaillé avec mécanismes et observables.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:105:- Document tests : TC-NOM-14 n'existe pas. La matrice de couverture mappe CA-02 à TC-NOM-08 (idempotence).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:106:- Spec §8 : TC-NOM-14 absent des scénarios Given/When/Then.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:142:**ZO-04** : **Test E2E TC-NR-01** — le plan et les tests le déclarent obligatoire (baseline `/gov` standalone vs orchestré), mais **aucun document ne décrit la procédure concrète** pour exécuter une story complète `/gov` dans un contexte de test contrôlé. Durée estimée ? Story de test ? Mock des gates ?
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step5.md:146:**ZO-06** : **Format d'export probatoire TC-NOM-04.** Le test exige un "export probatoire" des 100 mesures SLA P95. **Aucun document ne définit le format exact de cet export** (CSV ? JSONL ? champs ?) ni sa localisation.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:14:- La machine d'etats v1 est coherente entre documents: etats officiels identiques (`STARTING`, `RUNNING`, `ESCALADED`, `PAUSED`, `DONE`, `ABORTED`, `CRASHED`, `START_FAILED`), transitions interdites testees via `TC-INV-01`, terminaux verrouilles via `TC-INV-02`.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:15:- Les regles de capacite, idempotence et ordre des gardes sont alignees: limite 5 (`TC-NOM-02`, `TC-ERR-01`), dedoublonnage/idempotence (`TC-NOM-08`, `TC-ERR-08`, `TC-ERR-11`), ordre `quota -> doublon -> format` pour `start` (`TC-INV-03`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:16:- La gestion des escalades est convergente: blocage jusqu'a `PO_RESPONSE` (`TC-NOM-03`, `TC-ERR-04`), FIFO multi-escalades sans remplacement (`TC-NOM-13`), visibilite SLA P95 (`TC-NOM-04`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:17:- La resilience broker/peer est coherente: crash detecte en <=2 cycles (`TC-NOM-06`, `TC-ERR-07`), mode degrade + reconnexion bornee + reconciliation (`TC-ERR-10`, `TC-NOM-07`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:18:- Le perimetre One Ring (pas d'execution metier/projet, pas d'acces direct repos, non-regression `/gov`) est aligne avec les tests nominaux/erreur/non-regression (`TC-NOM-05`, `TC-ERR-05`, `TC-NR-01`, `TC-NR-02`, `TC-NR-03`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3.md:29:- Disponibilite exacte et limites de `/remote-control` sur iPhone/Safari restent ouvertes (`Q-293-01`), avec CA-06 couvert uniquement par test manuel (`TC-MAN-01`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:14:- La machine d'etats v1 est coherente entre documents: etats officiels identiques (`STARTING`, `RUNNING`, `ESCALADED`, `PAUSED`, `DONE`, `ABORTED`, `CRASHED`, `START_FAILED`), transitions interdites testees via `TC-INV-01`, terminaux verrouilles via `TC-INV-02`.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:15:- Les regles de capacite, idempotence et ordre des gardes sont alignees: limite 5 (`TC-NOM-02`, `TC-ERR-01`), dedoublonnage/idempotence (`TC-NOM-08`, `TC-ERR-08`, `TC-ERR-11`), ordre `quota -> doublon -> format` pour `start` (`TC-INV-03`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:16:- La gestion des escalades est convergente: blocage jusqu'a `PO_RESPONSE` (`TC-NOM-03`, `TC-ERR-04`), FIFO multi-escalades sans remplacement (`TC-NOM-13`), visibilite SLA P95 (`TC-NOM-04`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:17:- La resilience broker/peer est coherente: crash detecte en <=2 cycles (`TC-NOM-06`, `TC-ERR-07`), mode degrade + reconnexion bornee + reconciliation (`TC-ERR-10`, `TC-NOM-07`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:18:- Le perimetre One Ring (pas d'execution metier/projet, pas d'acces direct repos, non-regression `/gov`) est aligne avec les tests nominaux/erreur/non-regression (`TC-NOM-05`, `TC-ERR-05`, `TC-NR-01`, `TC-NR-02`, `TC-NR-03`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-confrontation-step3-v2.md:29:- Disponibilite exacte et limites de `/remote-control` sur iPhone/Safari restent ouvertes (`Q-293-01`), avec CA-06 couvert uniquement par test manuel (`TC-MAN-01`).
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:5:- [x] Tests CI : 45/45 bats tests passent (FSM + validator)
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:19:| bats tests (FSM) | ✅ 21/21 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:20:| bats tests (validator) | ✅ 24/24 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:22:| Total | **45/45 OK** |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:57:| Tests | ✅ 45/45 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:58:| Invariants vérifiés | 12/14 PASS, 2 avec réserves (INV-293-02, INV-293-05) |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:12:| INV-293-01 | CA-05 | TC-NOM-05 | Oui | Les commandes hors scope sont refusees avec message explicite et sans action metier. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:13:| INV-293-02 | CA-01 | TC-NOM-01 | Oui | Les observations passent par broker/peers; aucun acces direct aux repos cibles. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:14:| INV-293-03 | CA-08 | TC-NOM-09 | Oui | Isolation stricte des stories et absence de contamination inter-story. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:15:| INV-293-04 | CA-09 | TC-NOM-02 | Oui | La limite de 5 sessions actives est appliquee strictement. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:16:| INV-293-05 | CA-10 | TC-NOM-10 | Oui | Validation stricte du schema canonique et rejet deterministe des invalides. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:17:| INV-293-06 | CA-04 | TC-NOM-03 | Oui | Une escalade bloque la progression jusqu'a reception d'une reponse PO valide. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:18:| INV-293-07 | CA-08 | TC-NR-01 | Oui | Le workflow `/gov` reste inchange et fonctionnel en execution Ringbearer. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:19:| INV-293-08 | CA-07 | TC-NOM-06 | Oui | Passage en `CRASHED` et alerte en <=2 cycles de polling. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:20:| INV-293-09 | CA-04 | TC-INV-01 | Oui | Toutes transitions hors machine d'etats sont refusees. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:21:| INV-293-10 | CA-01 | TC-INV-02 | Oui | Les etats terminaux sont immuables (aucune transition sortante). |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:22:| INV-293-11 | CA-01 | TC-NOM-07 | Oui | Reconciliation periodique detecte et corrige les ecarts de vue consolidee. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:23:| INV-293-12 | CA-02 | TC-NOM-08 | Oui | Commandes `start/stop/respond/pause/resume` idempotentes par cle dediee. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:24:| INV-293-13 | CA-11 | TC-NOM-13 | Oui | Les escalades simultanees sont traitees en FIFO sans remplacement. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:25:| INV-293-14 | CA-09 | TC-INV-03 | Oui | L'ordre de gardes `quota -> doublon -> format` est respecte sur `start`. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:26:| INV-293-05 | CA-03 | TC-NOM-04 | Oui | Les messages d'escalade valides sont visibles dans la fenetre SLA P95. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:27:| INV-293-02 | CA-06 | TC-MAN-01 | Manuel | Le controle mobile utilise les memes commandes d'orchestration via One Ring. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:28:| INV-293-05 | CA-12 | TC-ERR-10 | Oui | Reconnexion broker geree en mode degrade explicite puis reprise automatique. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:33:TEST-ID: TC-NOM-01
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:50:TEST-ID: TC-NOM-02
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:66:TEST-ID: TC-NOM-03
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:82:TEST-ID: TC-NOM-04
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:97:TEST-ID: TC-NOM-05
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:112:TEST-ID: TC-NOM-06
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:128:TEST-ID: TC-NOM-07
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:143:TEST-ID: TC-NOM-08
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:158:TEST-ID: TC-NOM-09
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:173:TEST-ID: TC-NOM-10
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:188:TEST-ID: TC-NOM-12
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:203:TEST-ID: TC-NOM-13
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:220:TEST-ID: TC-ERR-01
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:233:TEST-ID: TC-ERR-02
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:246:TEST-ID: TC-ERR-03
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:260:TEST-ID: TC-ERR-04
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:273:TEST-ID: TC-ERR-05
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:286:TEST-ID: TC-ERR-06
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:300:TEST-ID: TC-ERR-07
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:314:TEST-ID: TC-ERR-08
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:327:TEST-ID: TC-ERR-09
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:340:TEST-ID: TC-ERR-10
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:354:TEST-ID: TC-ERR-11
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:370:| INV-293-01 | TC-NOM-05, TC-ERR-05 | Rejet explicite des actions hors scope, zero action metier | Separation des pouvoirs preservee. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:371:| INV-293-02 | TC-NOM-01, TC-MAN-01 | Traces d'usage broker/peers uniquement | Pas d'acces direct aux repos cibles. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:372:| INV-293-03 | TC-NOM-09, TC-NR-03 | Absence de contamination et de partage credentials entre stories | Isolation contractuelle verifiee. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:373:| INV-293-04 | TC-NOM-02, TC-ERR-01 | 6e `start` rejete sans creation | Limite capacitaire stricte. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:374:| INV-293-05 | TC-NOM-10, TC-ERR-03, TC-NEG-01..TC-NEG-10 | Validation schema stricte, rejet deterministe des invalides | Contrat de message testable. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:375:| INV-293-06 | TC-NOM-03, TC-ERR-04 | Blocage en `ESCALADED` jusqu'a `PO_RESPONSE` valide | Gouvernance humaine effective. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:376:| INV-293-07 | TC-NR-01 | Comportement `/gov` identique baseline/post-orchestration | Non-regression fonctionnelle du workflow. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:377:| INV-293-08 | TC-NOM-06, TC-ERR-07 | Detection crash en <=2 polls + alerte | Resilience operationnelle. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:378:| INV-293-09 | TC-INV-01 | Toute transition non listee est refusee | Cohesion machine d'etats. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:379:| INV-293-10 | TC-INV-02 | Aucun `DONE/ABORTED/CRASHED/START_FAILED -> *` accepte | Terminaux verrouilles. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:380:| INV-293-11 | TC-NOM-07 | Reconciliation periodique aligne la vue consolidee | Tolerance aux ecarts/crashes. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:381:| INV-293-12 | TC-NOM-08, TC-ERR-08, TC-ERR-11 | Rejeu avec meme cle sans double effet / conflit bloque | Retry-safe en distribue. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-tests.md:382:| INV-293-13 | TC-NOM-13 | FIFO strict multi-escalades | Pas de remplacement d'escalade. |

exec
/bin/zsh -lc "rg -n \"bats|test-state-machine|test-validator|45/45|FSM\" scripts docs/epics/tooling/PD-293-one-ring-orchestration -g'*.sh' -g'*.md'" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 724ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:15:| C7  | tests | Suites BATS couvrant TC-NOM-\*, TC-ERR-\*, TC-INV-\*, TC-NEG-\*, TC-NR-\* | `tests/lord/**/*.bats` | `bats-core` (H-TECH-06), mocks C3 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:343:| H-TECH-06 | `bats-core` installé (framework de test Bash) | C7 non exécutable | `brew install bats-core`. CI : step d'installation dans le pipeline. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:608:      - "Suites BATS : tests/lord/state-machine.bats, tests/lord/validator.bats, tests/lord/persistence.bats, tests/lord/orchestrator.bats, tests/lord/integration.bats, tests/lord/negative.bats, tests/lord/non-regression.bats"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:625:          - "Inconvenient : Dependance externe bats-core (H-TECH-06)"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan.md:627:      - "tests/lord/**/*.bats"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:5:- [x] Tests CI : 45/45 bats tests passent (FSM + validator)
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:19:| bats tests (FSM) |  21/21 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:20:| bats tests (validator) |  24/24 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:22:| Total | **45/45 OK** |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:41:- Couverture C1 (FSM) et C2 (validator) solide
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:57:| Tests |  45/45 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:66:**Impact** : L'état `ESCALADE_EXPIRED` est un état fantôme : mentionné dans les SLA mais absent de la FSM. Un implémenteur ne sait pas s'il s'agit d'un sous-état de `ESCALADED`, d'un nouvel état, ou d'une alerte sans changement d'état.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:95:**Description** : L'état `START_FAILED` est fini dans la FSM et couvert par INV-293-10 (terminal), mais aucun test nominal ne vérifie la **transition entrante** `STARTING→START_FAILED`. TC-INV-02 vérifie que `START_FAILED` est terminal (pas de sortie), mais aucun test ne provoque le timeout de démarrage pour vérifier que la transition est effectivement déclenchée.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:145:**Description** : Le diagramme d'état ne contient pas l'état `ESCALADE_EXPIRED` mentionné dans les SLA temporels §5.1. Si `ESCALADE_EXPIRED` est un état de la FSM, il manque dans le diagramme. S'il n'est pas un état mais un signal/alerte, la terminologie "État story `ESCALADE_EXPIRED`" est trompeuse.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step3.md:189:**Bloquants** : L'état `ESCALADE_EXPIRED` est féren dans les SLA §5.1 mais absent de la machine d'états §5.2 et du diagramme Mermaid §5bis. Cet état fantôme doit être soit ajouté à la FSM avec ses transitions, soit reformulé comme un signal/alerte sans changement d'état.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:193:**Fichiers** : `tests/lord/**/*.bats` + `tests/lord/mocks/**` + `tests/lord/fixtures/**`
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:203:  state-machine.bats    # TC-INV-01, TC-INV-02 (matrice 8×8)
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:204:  validator.bats        # TC-NOM-10, TC-ERR-03, TC-NEG-01..10
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:205:  persistence.bats      # TC-NOM-02, TC-NOM-08, TC-NOM-13, TC-ERR-01, TC-ERR-08, TC-ERR-11
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:206:  orchestrator.bats     # TC-NOM-01, TC-NOM-03..06, TC-NOM-07, TC-NOM-09, TC-NOM-12, TC-NOM-14
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:207:  integration.bats      # TC-ERR-02, TC-ERR-04..07, TC-ERR-09..10, TC-INV-03
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:208:  negative.bats         # TC-NEG-01..10 (validation dédiée)
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:209:  non-regression.bats   # TC-NR-01..04
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:222:| TC-INV-01, TC-INV-02 | `state-machine.bats` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:223:| TC-NOM-10, TC-ERR-03, TC-NEG-01..10 | `validator.bats` + `negative.bats` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:224:| TC-NOM-02, TC-NOM-08, TC-NOM-13, TC-ERR-01, TC-ERR-08, TC-ERR-11 | `persistence.bats` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:225:| TC-NOM-01, TC-NOM-03..06, TC-NOM-07, TC-NOM-09, TC-NOM-12, TC-NOM-14 | `orchestrator.bats` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:226:| TC-ERR-02, TC-ERR-04..07, TC-ERR-09..10, TC-INV-03 | `integration.bats` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:227:| TC-NR-01..04 | `non-regression.bats` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-decomposition.md:239:| bats-core | `command -v bats` | `brew install bats-core` |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:24:| Contrainte technique non documentee | Plan `PD-293-plan.md` (section "Contraintes techniques" absente) | Le framework de test Jest/Vitest n'est pas explicite; le code contract mentionne bats-core, sans decision contractuelle explicite au niveau plan. | Ambiguite de runner de test au regard de la contrainte documentaire demandee. | MAJEUR |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:277:      - Tests unitaires bats-core pour C1, C2, C3, C7 (gardes)
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:278:      - Tests integration bats-core pour C4 (complet), C5 (broker stubbe), C6, C7
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:282:      - "Chaque TC-* de la spec a un test bats correspondant"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:408:| C7  | tests | Suites BATS couvrant TC-NOM-\*, TC-ERR-\*, TC-INV-\*, TC-NEG-\*, TC-NR-\* | `tests/lord/**/*.bats` | `bats-core` (H-TECH-06), mocks C3 |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:852:      - Tests unitaires bats-core pour C1, C2, C3, C7 (gardes)
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:853:      - Tests integration bats-core pour C4 (complet), C5 (broker stubbe), C6, C7
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:857:      - "Chaque TC-* de la spec a un test bats correspondant"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:996:| H-TECH-06 | `bats-core` installé (framework de test Bash) | C7 non exécutable | `brew install bats-core`. CI : step d'installation dans le pipeline. |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1268:      - "Suites BATS : tests/lord/state-machine.bats, tests/lord/validator.bats, tests/lord/persistence.bats, tests/lord/orchestrator.bats, tests/lord/integration.bats, tests/lord/negative.bats, tests/lord/non-regression.bats"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1285:          - "Inconvenient : Dependance externe bats-core (H-TECH-06)"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:1287:      - "tests/lord/**/*.bats"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2104:| Contrainte technique non documentee | Plan `PD-293-plan.md` (section "Contraintes techniques" absente) | Le framework de test Jest/Vitest n'est pas explicite; le code contract mentionne bats-core, sans decision contractuelle explicite au niveau plan. | Ambiguite de runner de test au regard de la contrainte documentaire demandee. | MAJEUR |
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-review-step5.md:2349:240:      - "Chaque TC-* de la spec a un test bats correspondant"
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-besoin.md:5:Le workflow de gouvernance ProbatioVault (11 étapes, `/gov`) fonctionne en mode single-story : un humain pilote une session Claude Code qui orchestre une seule PD-XXX à la fois. Le workflow supporte déjà le parallélisme technique (chaque story a sa propre FSM Jira), mais le goulot d'étranglement est le **coût cognitif humain** de suivre N sessions simultanées.
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-plan-review.md:24:| Contrainte technique non documentee | Plan `PD-293-plan.md` (section "Contraintes techniques" absente) | Le framework de test Jest/Vitest n'est pas explicite; le code contract mentionne bats-core, sans decision contractuelle explicite au niveau plan. | Ambiguite de runner de test au regard de la contrainte documentaire demandee. | MAJEUR |
scripts/n8n-bridge.sh:2:# ─── n8n Bridge  Communication Claude Code  n8n FSM ─────────────
scripts/n8n-bridge.sh:9:#   n8n-bridge.sh import                              # Import FSM workflow
scripts/n8n-bridge.sh:253:    log_ok "Main FSM workflow imported"
scripts/n8n-bridge.sh:269:# ─── FSM Commands (stateless  state lives in WORKFLOW-STATE.md) ───
scripts/n8n-bridge.sh:458:    echo "  import                               Import FSM workflow into n8n"
scripts/lib/lord-state-machine.sh:2:# PD-293  C1 State Machine : FSM Ringbearer 5.2)
scripts/lib/lord-state-machine.sh:4:# Implémentation case/esac pour compatibilité bats
scripts/lib/state.sh:124:# Statut Jira  etat interne FSM
scripts/lib/state.sh:125:declare -A JIRA_STATUS_TO_FSM=(
scripts/lib/state.sh:390:# Retourne le statut FSM d'une etape (derive de Jira)
scripts/lib/state.sh:415:  local current_fsm="${JIRA_STATUS_TO_FSM[$jira_status]:-PENDING_STEP}"
scripts/lib/state.sh:650:      local fsm_state="${JIRA_STATUS_TO_FSM[$jira_status]:-IN_PROGRESS_STEP}"

exec
/bin/zsh -lc 'ls -la docs/epics/tooling/PD-293-one-ring-orchestration/*code-contracts* 2>/dev/null || true' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 640ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
-rw-r--r--@ 1 loic  staff  3021 Mar 31 01:32 docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml

exec
/bin/zsh -lc "rg -n \"lord-fsm\.sh|lord-state-machine\.sh|PD-293-code-contracts\.yaml\" docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 652ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:30:1. Deux fichiers code-contracts concurrents (`code-contracts.yaml` + `PD-293-code-contracts.yaml`) → **Corrigé** : fichier unique aligné sur l'implémentation réelle
docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md:31:2. Noms de fichiers divergents (contracts: `lord-fsm.sh` vs implémentation: `lord-state-machine.sh`) → **Corrigé** : contracts réalignés
docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml:9:    file: scripts/lib/lord-state-machine.sh

exec
/bin/zsh -lc 'command -v bats || true' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 691ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable

exec
/bin/zsh -lc "printf 'state-machine tests: '; rg -n '"'^@test '"' tests/lord/test-state-machine.bats | wc -l; printf 'validator tests: '; rg -n '"'^@test '"' tests/lord/test-validator.bats | wc -l" in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 719ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
state-machine tests:       21
validator tests:       24

codex
J’ai terminé la qualification des écarts existants: les deux écarts “code-contracts” restent corrigés, et les réserves INV-293-02 / INV-293-05 / multi-escalade / couverture C3-C5 / MAC broker restent non levées. Je vais maintenant générer le contenu final `PD-293-acceptability-review.md` selon le format strict et tenter l’écriture au chemin demandé.
exec
/bin/zsh -lc "cat > docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md <<'EOF'
# PD-293 — Revue d’acceptabilité (post-correction)

## 1. Références

- Spécification : PD-293-specification.md
- Tests contractuels : PD-293-tests.md
- Acceptabilité existante : PD-293-acceptability.md
- Date de revue : 2026-03-31
- Reviewer : Auditeur technique indépendant (Codex)

## 2. Suivi des écarts (append-only)

### [2026-03-31] — Suivi E-01

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le workspace courant ne contient plus qu’un seul fichier de contrats ("'`code-contracts.yaml`) dans le dossier PD-293.
  - Le commit `5a62a7f` documente explicitement la suppression des code-contracts divergents.
- Preuve de vérification :
  - Commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - Test : résultats d’exécution fournis dans `PD-293-acceptability.md` (bats FSM 21/21 PASS, validator 24/24 PASS)

### [2026-03-31] — Suivi E-02

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le contrat référence désormais `scripts/lib/lord-state-machine.sh`, aligné avec l’implémentation existante.
  - Aucune référence active à `lord-fsm.sh` n’est présente dans le contrat courant.
- Preuve de vérification :
  - Commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - Test : résultats d’exécution fournis dans `PD-293-acceptability.md` (45/45 PASS)

### [2026-03-31] — Suivi E-03

- Statut précédent : OUVERT (réserve INV-293-02)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le diagramme de séquence de la spécification conserve des flèches directes `O->>R` (`demande demarrage`, `PO_RESPONSE`, `PAUSE`, `RESUME`).
  - L’écart documentaire signalé n’a pas été corrigé dans la spec de référence.
- Preuve de vérification :
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - Test contractuel concerné : `TC-NOM-01`, `TC-MAN-01` (aucune nouvelle preuve d’exécution post-correction fournie)

### [2026-03-31] — Suivi E-04

- Statut précédent : OUVERT (réserve INV-293-05)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - La spec autorise `timestamp` avec suffixe `Z` **ou** offset UTC.
  - Le validateur implémente un contrôle strict suffixe `Z` (offset rejeté), donc divergence maintenue.
- Preuve de vérification :
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - Fichier : `scripts/lib/lord-validator.sh`
  - Test contractuel concerné : `TC-NEG-06` (la suite locale n’a pas pu être relancée ici : `bats` indisponible)

### [2026-03-31] — Suivi E-05

- Statut précédent : OUVERT (réserve multi-escalade)
- Statut actuel : PARTIELLEMENT RÉSOLU
- Justification factuelle :
  - Le mécanisme FIFO est implémenté via tri `sort_by(.created_at)` puis dépilement de la plus ancienne escalade OPEN.
  - Le départage explicite des horodatages strictement égaux n’est toujours pas défini.
- Preuve de vérification :
  - Fichier : `scripts/lib/lord-persistence.sh`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - Test contractuel concerné : `TC-NOM-13` (aucune exécution post-correction fournie sur le cas d’égalité stricte)

### [2026-03-31] — Suivi E-06

- Statut précédent : OUVERT (réserve couverture C3/C4/C5)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le répertoire `tests/lord/` contient uniquement `test-state-machine.bats` et `test-validator.bats`.
  - Aucun fichier de test dédié C3 (broker), C4 (persistence), C5 (orchestrator) n’est présent.
- Preuve de vérification :
  - Fichier : `tests/lord/test-state-machine.bats`
  - Fichier : `tests/lord/test-validator.bats`
  - Test contractuel : seuls 45 tests (C1/C2) documentés PASS dans `PD-293-acceptability.md`

### [2026-03-31] — Suivi E-07

- Statut précédent : OUVERT (réserve sécurité broker)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le broker adapter ne met pas en œuvre de mécanisme de signature/MAC des messages (mode mock + bridge local `OK`).
  - La réserve sécurité initiale reste valide en l’état.
- Preuve de vérification :
  - Fichier : `scripts/lib/lord-broker.sh`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - Test contractuel : aucun TC-* dédié à la signature/MAC identifié dans `PD-293-tests.md`

## 3. Verdict d’acceptabilité (courant)

- ⛔ REFUSÉ
- ⚠️ ACCEPTÉ AVEC RÉSERVES
- ✅ ACCEPTÉ

Verdict actuel : ⚠️ ACCEPTÉ AVEC RÉSERVES
Date : 2026-03-31
Motif synthétique : Les deux écarts bloquants initiaux restent corrigés, mais les réserves documentaires/validation/sécurité existantes ne sont pas levées. Le verdict global reste inchangé.

## 4. Historique des verdicts

| Date | Verdict | Version / commit | Commentaire |
| ---- | ------- | ---------------- | ----------- |
| 2026-03-31 | ⚠️ ACCEPTÉ AVEC RÉSERVES | 5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a | Verdict courant inchangé en post-correction |

EOF' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
2026-03-30T23:38:17.319941Z ERROR codex_core::tools::router: error=exec_command failed for `/bin/zsh -lc "cat > docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md <<'EOF'
# PD-293 — Revue d’acceptabilité (post-correction)

## 1. Références

- Spécification : PD-293-specification.md
- Tests contractuels : PD-293-tests.md
- Acceptabilité existante : PD-293-acceptability.md
- Date de revue : 2026-03-31
- Reviewer : Auditeur technique indépendant (Codex)

## 2. Suivi des écarts (append-only)

### [2026-03-31] — Suivi E-01

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le workspace courant ne contient plus qu’un seul fichier de contrats ("'`code-contracts.yaml`) dans le dossier PD-293.
  - Le commit `5a62a7f` documente explicitement la suppression des code-contracts divergents.
- Preuve de vérification :
  - Commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - Test : résultats d’exécution fournis dans `PD-293-acceptability.md` (bats FSM 21/21 PASS, validator 24/24 PASS)

### [2026-03-31] — Suivi E-02

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le contrat référence désormais `scripts/lib/lord-state-machine.sh`, aligné avec l’implémentation existante.
  - Aucune référence active à `lord-fsm.sh` n’est présente dans le contrat courant.
- Preuve de vérification :
  - Commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - Test : résultats d’exécution fournis dans `PD-293-acceptability.md` (45/45 PASS)

### [2026-03-31] — Suivi E-03

- Statut précédent : OUVERT (réserve INV-293-02)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le diagramme de séquence de la spécification conserve des flèches directes `O->>R` (`demande demarrage`, `PO_RESPONSE`, `PAUSE`, `RESUME`).
  - L’écart documentaire signalé n’a pas été corrigé dans la spec de référence.
- Preuve de vérification :
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - Test contractuel concerné : `TC-NOM-01`, `TC-MAN-01` (aucune nouvelle preuve d’exécution post-correction fournie)

### [2026-03-31] — Suivi E-04

- Statut précédent : OUVERT (réserve INV-293-05)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - La spec autorise `timestamp` avec suffixe `Z` **ou** offset UTC.
  - Le validateur implémente un contrôle strict suffixe `Z` (offset rejeté), donc divergence maintenue.
- Preuve de vérification :
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - Fichier : `scripts/lib/lord-validator.sh`
  - Test contractuel concerné : `TC-NEG-06` (la suite locale n’a pas pu être relancée ici : `bats` indisponible)

### [2026-03-31] — Suivi E-05

- Statut précédent : OUVERT (réserve multi-escalade)
- Statut actuel : PARTIELLEMENT RÉSOLU
- Justification factuelle :
  - Le mécanisme FIFO est implémenté via tri `sort_by(.created_at)` puis dépilement de la plus ancienne escalade OPEN.
  - Le départage explicite des horodatages strictement égaux n’est toujours pas défini.
- Preuve de vérification :
  - Fichier : `scripts/lib/lord-persistence.sh`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - Test contractuel concerné : `TC-NOM-13` (aucune exécution post-correction fournie sur le cas d’égalité stricte)

### [2026-03-31] — Suivi E-06

- Statut précédent : OUVERT (réserve couverture C3/C4/C5)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le répertoire `tests/lord/` contient uniquement `test-state-machine.bats` et `test-validator.bats`.
  - Aucun fichier de test dédié C3 (broker), C4 (persistence), C5 (orchestrator) n’est présent.
- Preuve de vérification :
  - Fichier : `tests/lord/test-state-machine.bats`
  - Fichier : `tests/lord/test-validator.bats`
  - Test contractuel : seuls 45 tests (C1/C2) documentés PASS dans `PD-293-acceptability.md`

### [2026-03-31] — Suivi E-07

- Statut précédent : OUVERT (réserve sécurité broker)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le broker adapter ne met pas en œuvre de mécanisme de signature/MAC des messages (mode mock + bridge local `OK`).
  - La réserve sécurité initiale reste valide en l’état.
- Preuve de vérification :
  - Fichier : `scripts/lib/lord-broker.sh`
  - Fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - Test contractuel : aucun TC-* dédié à la signature/MAC identifié dans `PD-293-tests.md`

## 3. Verdict d’acceptabilité (courant)

- ⛔ REFUSÉ
- ⚠️ ACCEPTÉ AVEC RÉSERVES
- ✅ ACCEPTÉ

Verdict actuel : ⚠️ ACCEPTÉ AVEC RÉSERVES
Date : 2026-03-31
Motif synthétique : Les deux écarts bloquants initiaux restent corrigés, mais les réserves documentaires/validation/sécurité existantes ne sont pas levées. Le verdict global reste inchangé.

## 4. Historique des verdicts

| Date | Verdict | Version / commit | Commentaire |
| ---- | ------- | ---------------- | ----------- |
| 2026-03-31 | ⚠️ ACCEPTÉ AVEC RÉSERVES | 5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a | Verdict courant inchangé en post-correction |

EOF'`: SandboxDenied { message: "pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
zsh:1: operation not permitted: docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md
", output: ExecToolCallOutput { exit_code: 1, stdout: StreamOutput { text: "", truncated_after_lines: None }, stderr: StreamOutput { text: "pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
zsh:1: operation not permitted: docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md
", truncated_after_lines: None }, aggregated_output: StreamOutput { text: "pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
zsh:1: operation not permitted: docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md
", truncated_after_lines: None }, duration: 0ns, timed_out: false } }
 exited 1 in 799ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
zsh:1: operation not permitted: docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md

exec
/bin/zsh -lc 'test -f docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md && echo exists || echo missing' in /Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance
 succeeded in 815ms:
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
pyenv: cannot rehash: /Users/loic/.pyenv/shims isn't writable
missing

codex
Écriture locale impossible (sandbox en lecture seule) vers [PD-293-acceptability-review.md](/Users/loic/Developpement/ProbatioVault/ProbatioVault-ia-governance/docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability-review.md).  
Contenu généré :

```markdown
# PD-293 — Revue d’acceptabilité (post-correction)

## 1. Références

- Spécification : PD-293-specification.md
- Tests contractuels : PD-293-tests.md
- Acceptabilité existante : PD-293-acceptability.md
- Date de revue : 2026-03-31
- Reviewer : Auditeur technique indépendant (Codex)

## 2. Suivi des écarts (append-only)

### [2026-03-31] — Suivi E-01

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le workspace courant ne contient plus qu’un seul fichier de contrats (`code-contracts.yaml`) dans le dossier PD-293.
  - Le commit `5a62a7f` documente explicitement la suppression des code-contracts divergents.
- Preuve de vérification :
  - commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - test : résultats d’exécution fournis dans `PD-293-acceptability.md` (bats FSM 21/21 PASS, validator 24/24 PASS)

### [2026-03-31] — Suivi E-02

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le contrat référence désormais `scripts/lib/lord-state-machine.sh`, aligné avec l’implémentation existante.
  - Aucune référence active à `lord-fsm.sh` n’est présente dans le contrat courant.
- Preuve de vérification :
  - commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - test : résultats d’exécution fournis dans `PD-293-acceptability.md` (45/45 PASS)

### [2026-03-31] — Suivi E-03

- Statut précédent : OUVERT (réserve INV-293-02)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le diagramme de séquence de la spécification conserve des flèches directes `O->>R` (`demande demarrage`, `PO_RESPONSE`, `PAUSE`, `RESUME`).
  - L’écart documentaire signalé n’a pas été corrigé dans la spec de référence.
- Preuve de vérification :
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - test contractuel concerné : `TC-NOM-01`, `TC-MAN-01` (aucune nouvelle preuve d’exécution post-correction fournie)

### [2026-03-31] — Suivi E-04

- Statut précédent : OUVERT (réserve INV-293-05)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - La spec autorise `timestamp` avec suffixe `Z` **ou** offset UTC.
  - Le validateur implémente un contrôle strict suffixe `Z` (offset rejeté), donc divergence maintenue.
- Preuve de vérification :
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - fichier : `scripts/lib/lord-validator.sh`
  - test contractuel concerné : `TC-NEG-06` (la suite locale n’a pas pu être relancée ici : `bats` indisponible)

### [2026-03-31] — Suivi E-05

- Statut précédent : OUVERT (réserve multi-escalade)
- Statut actuel : PARTIELLEMENT RÉSOLU
- Justification factuelle :
  - Le mécanisme FIFO est implémenté via tri `sort_by(.created_at)` puis dépilement de la plus ancienne escalade OPEN.
  - Le départage explicite des horodatages strictement égaux n’est toujours pas défini.
- Preuve de vérification :
  - fichier : `scripts/lib/lord-persistence.sh`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - test contractuel concerné : `TC-NOM-13` (aucune exécution post-correction fournie sur le cas d’égalité stricte)

### [2026-03-31] — Suivi E-06

- Statut précédent : OUVERT (réserve couverture C3/C4/C5)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le répertoire `tests/lord/` contient uniquement `test-state-machine.bats` et `test-validator.bats`.
  - Aucun fichier de test dédié C3 (broker), C4 (persistence), C5 (orchestrator) n’est présent.
- Preuve de vérification :
  - fichier : `tests/lord/test-state-machine.bats`
  - fichier : `tests/lord/test-validator.bats`
  - test contractuel : seuls 45 tests (C1/C2) documentés PASS dans `PD-293-acceptability.md`

### [2026-03-31] — Suivi E-07

- Statut précédent : OUVERT (réserve sécurité broker)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le broker adapter ne met pas en œuvre de mécanisme de signature/MAC des messages (mode mock + bridge local `OK`).
  - La réserve sécurité initiale reste valide en l’état.
- Preuve de vérification :
  - fichier : `scripts/lib/lord-broker.sh`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - test contractuel : aucun TC-* dédié à la signature/MAC identifié dans `PD-293-tests.md`

## 3. Verdict d’acceptabilité (courant)

Verdict actuel : ⚠️ ACCEPTÉ AVEC RÉSERVES  
Date : 2026-03-31  
Motif synthétique : Les deux écarts bloquants initiaux restent corrigés, mais les réserves documentaires/validation/sécurité existantes ne sont pas levées.

## 4. Historique des verdicts

| Date | Verdict | Version / commit | Commentaire |
| ---- | ------- | ---------------- | ----------- |
| 2026-03-31 | ⚠️ ACCEPTÉ AVEC RÉSERVES | 5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a | Verdict courant inchangé en post-correction |
tokens used 88 983 Écriture locale impossible (sandbox en lecture seule) vers PD-293-acceptability-review.md.
Contenu généré :

# PD-293 — Revue d’acceptabilité (post-correction)

## 1. Références

- Spécification : PD-293-specification.md
- Tests contractuels : PD-293-tests.md
- Acceptabilité existante : PD-293-acceptability.md
- Date de revue : 2026-03-31
- Reviewer : Auditeur technique indépendant (Codex)

## 2. Suivi des écarts (append-only)

### [2026-03-31] — Suivi E-01

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le workspace courant ne contient plus qu’un seul fichier de contrats (`code-contracts.yaml`) dans le dossier PD-293.
  - Le commit `5a62a7f` documente explicitement la suppression des code-contracts divergents.
- Preuve de vérification :
  - commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - test : résultats d’exécution fournis dans `PD-293-acceptability.md` (bats FSM 21/21 PASS, validator 24/24 PASS)

### [2026-03-31] — Suivi E-02

- Statut précédent : Corrigé (déclaratif dans PD-293-acceptability.md)
- Statut actuel : RÉSOLU
- Justification factuelle :
  - Le contrat référence désormais `scripts/lib/lord-state-machine.sh`, aligné avec l’implémentation existante.
  - Aucune référence active à `lord-fsm.sh` n’est présente dans le contrat courant.
- Preuve de vérification :
  - commit : `5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/code-contracts.yaml`
  - test : résultats d’exécution fournis dans `PD-293-acceptability.md` (45/45 PASS)

### [2026-03-31] — Suivi E-03

- Statut précédent : OUVERT (réserve INV-293-02)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le diagramme de séquence de la spécification conserve des flèches directes `O->>R` (`demande demarrage`, `PO_RESPONSE`, `PAUSE`, `RESUME`).
  - L’écart documentaire signalé n’a pas été corrigé dans la spec de référence.
- Preuve de vérification :
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - test contractuel concerné : `TC-NOM-01`, `TC-MAN-01` (aucune nouvelle preuve d’exécution post-correction fournie)

### [2026-03-31] — Suivi E-04

- Statut précédent : OUVERT (réserve INV-293-05)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - La spec autorise `timestamp` avec suffixe `Z` **ou** offset UTC.
  - Le validateur implémente un contrôle strict suffixe `Z` (offset rejeté), donc divergence maintenue.
- Preuve de vérification :
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-specification.md`
  - fichier : `scripts/lib/lord-validator.sh`
  - test contractuel concerné : `TC-NEG-06` (la suite locale n’a pas pu être relancée ici : `bats` indisponible)

### [2026-03-31] — Suivi E-05

- Statut précédent : OUVERT (réserve multi-escalade)
- Statut actuel : PARTIELLEMENT RÉSOLU
- Justification factuelle :
  - Le mécanisme FIFO est implémenté via tri `sort_by(.created_at)` puis dépilement de la plus ancienne escalade OPEN.
  - Le départage explicite des horodatages strictement égaux n’est toujours pas défini.
- Preuve de vérification :
  - fichier : `scripts/lib/lord-persistence.sh`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - test contractuel concerné : `TC-NOM-13` (aucune exécution post-correction fournie sur le cas d’égalité stricte)

### [2026-03-31] — Suivi E-06

- Statut précédent : OUVERT (réserve couverture C3/C4/C5)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le répertoire `tests/lord/` contient uniquement `test-state-machine.bats` et `test-validator.bats`.
  - Aucun fichier de test dédié C3 (broker), C4 (persistence), C5 (orchestrator) n’est présent.
- Preuve de vérification :
  - fichier : `tests/lord/test-state-machine.bats`
  - fichier : `tests/lord/test-validator.bats`
  - test contractuel : seuls 45 tests (C1/C2) documentés PASS dans `PD-293-acceptability.md`

### [2026-03-31] — Suivi E-07

- Statut précédent : OUVERT (réserve sécurité broker)
- Statut actuel : NON RÉSOLU
- Justification factuelle :
  - Le broker adapter ne met pas en œuvre de mécanisme de signature/MAC des messages (mode mock + bridge local `OK`).
  - La réserve sécurité initiale reste valide en l’état.
- Preuve de vérification :
  - fichier : `scripts/lib/lord-broker.sh`
  - fichier : `docs/epics/tooling/PD-293-one-ring-orchestration/PD-293-acceptability.md`
  - test contractuel : aucun TC-* dédié à la signature/MAC identifié dans `PD-293-tests.md`

## 3. Verdict d’acceptabilité (courant)

Verdict actuel : ⚠️ ACCEPTÉ AVEC RÉSERVES  
Date : 2026-03-31  
Motif synthétique : Les deux écarts bloquants initiaux restent corrigés, mais les réserves documentaires/validation/sécurité existantes ne sont pas levées.

## 4. Historique des verdicts

| Date | Verdict | Version / commit | Commentaire |
| ---- | ------- | ---------------- | ----------- |
| 2026-03-31 | ⚠️ ACCEPTÉ AVEC RÉSERVES | 5a62a7f96ce7a21a9a0eb249ba86fd8101023c4a | Verdict courant inchangé en post-correction |