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)¶
- NE PAS modifier :
- les écarts initiaux,
- les descriptions historiques,
- les verdicts passés.
- NE PAS ajouter :
- de nouveaux écarts,
- de nouvelles règles,
- de nouvelles exigences.
- NE PAS améliorer :
- la spécification,
- l’implémentation,
- le document lui-même.
- 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é :
- 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.
-
Classe l’écart dans un des statuts suivants uniquement :
- OUVERT
- PARTIELLEMENT RÉSOLU
- RÉSOLU
- NON RÉSOLU
⚠️ Règle stricte
-
Un écart ne peut être RÉSOLU que si tous les TC-* concernés PASSENT.
-
Sinon → PARTIELLEMENT RÉSOLU ou NON RÉSOLU.
-
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-proofportent sur la conformité formelle vérifiée par des checks Prolog déterministes (SWI-Prologrun_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)¶
||
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
/govexistant. - 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_EXPIREDen 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_PENDINGn'est defini. - En v1, aucun etat
ESCALADE_EXPIREDn'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¶
- La regex
story_idest la source de verite unique (pas de contrainte textuelle de longueur independante). - Ordre de precedance dedoublonnage:
- si
idempotency_keydeja vue avec payload identique: retour deterministe sans effet secondaire, - si
idempotency_keydeja vue avec payload different: rejet de conflit, - sinon validation/pilotage normal par
story_id. - Ordre de gardes pour
start(et seulementstart) : quota -> doublon idempotence -> validation format complete. - 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 avantfirst_liveness_timeout. - Regle
STARTING->START_FAILED:start_detection_timeoutdepasse 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(apresPO_RESPONSEvalide),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, Whenstart PD-XXX, Then etatRUNNINGavant timeout et apres first liveness valide. -
T-02 Limite capacite
Given 5 actifs, Whenstart6e story, Then rejet explicite sans nouveau peer. -
T-03 Escalade bloquante
Given story enRUNNING, When messageESCALADE, Then story enESCALADEDjusqu'aPO_RESPONSE. -
T-04 Reponse escalade
Given storyESCALADED, Whenrespondvalide, Then retourRUNNINGet 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 etatCRASHED+ alerte en <=20s (defaut). -
T-07 Idempotence commande
Givenidempotency_keydeja traitee, When repetition meme payload, Then meme resultat sans doublon d'action. -
T-08 Mobile control (manuel)
Given session One Ring accessible mobile, Whenstatus/escalade/respond/pause/resume, Then memes resultats fonctionnels que desktop. -
T-09 Pause/Resume
Given story enRUNNING, Whenpausepuisresume, Then transitionsRUNNING->PAUSED->RUNNINGobservees. -
T-10 Multi-escalade FIFO
Given 3 escalades ouvertes pour une story, Whenrespondest 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/stopavec 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
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 où 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 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: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 référencé 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 |
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 |