[DTP-Worker] Sprint 8 · buffer L75 · Domaine DevOps : le run-book de déploiement VPS (devops/deploy_runbook) affichait « 7 phases » (fiche agent devops, ×2 transcriptions) et « 7 confirmations préalables » (README du module) — deux nombres data-derived transcrits À LA MAIN dans DEUX docs sans AUCUN gate, alors que devops/deploy_runbook/out/MANIFEST.json (byte-gaté par check_artifacts, counts.phases=len(graph.phase_order) · counts.confirmations=len(confirmations_ouvertes), recomptés à chaque build) fait autorité. Ajouter une phase au graphe OU une confirmation au catalogue ferait dériver les docs en silence — piège AVEUGLE : phases ET confirmations valent tous deux 7 aujourd'hui, un gate qui n'en recompterait qu'UN serait aveugle à la dérive de l'autre → nouveau bloc dans check_readme_claims recomputant CHAQUE nombre depuis SON PROPRE champ du MANIFEST et exigeant l'égalité avec les docs. Le « 22 » (suites gated de la fiche) volontairement écarté (sémantique suites CI ≠ counts.modules qui s'auto-exclut). Bonus : l'énumération snake_case des confirmations du README doit être l'ensemble EXACT de confirmations_ouvertes (mord l'échange 1↔1 d'un nom, aveugle au compte). Cohérences croisées counts.phases==|phase_order| · counts.confirmations==|confirmations_ouvertes| (5 morsures vérifiées : dérive phases 1re transcription · dérive 2e transcription captée là où la 1re resterait 7 · dérive confirmations count · swap d'un nom captée là où le count reste 7 · claim confirmations disparu = red)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,67 @@
|
||||
# Activity Log · 2026-07-31 · Claude Code DTP
|
||||
|
||||
## Session `20260731_113048` · Buffer S8 · Domaine DevOps : le run-book de déploiement VPS (`devops/deploy_runbook`) affichait « **7 phases** » (fiche agent devops, ×2) et « **7 confirmations** préalables » (README du module) — deux nombres data-derived transcrits À LA MAIN dans DEUX docs sans AUCUN gate
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer L75** (DevOps CI/CD · QA régression). Roadmap
|
||||
fonctionnellement close ; poursuite de la série anti-dérive (CLAUDE.md #6). Les
|
||||
sessions précédentes ont gaté les domaines tests, portails, RBAC (3 volets), SEO,
|
||||
CRM (pipeline vente), mobile, Legal (CONFOTUR) et QA (audit 5D). Cette session cible
|
||||
le **domaine DevOps** — le **run-book de déploiement VPS**, dont deux comptes
|
||||
data-derived cités dans deux docs pointaient l'artefact généré sans être recomputés
|
||||
par aucun gate.
|
||||
|
||||
### Défaut trouvé — comptes ungated, transcrits dans DEUX docs
|
||||
|
||||
- **`03_agents/devops/AGENT.md:25`** : « graphe de **7 phases ordonnées** », puis
|
||||
**ligne 88** « exécute les **7 phases** sur le VPS » — DEUX transcriptions du
|
||||
nombre de phases dans la même fiche.
|
||||
- **`05_deliverables_mvp/devops/deploy_runbook/README.md:94`** : « renseigner les
|
||||
**7 confirmations** » + énumération de ces 7 confirmations (lignes 55-58).
|
||||
- L'artefact source est byte-gaté par `check_artifacts` :
|
||||
`devops/deploy_runbook/out/MANIFEST.json` recompte `counts.phases`
|
||||
(= `len(graph.phase_order)`) et `counts.confirmations` (= `len(confirmations_ouvertes)`)
|
||||
à chaque build.
|
||||
- Aucun gate ne comparait la VALEUR écrite à l'artefact : ajouter une phase au graphe
|
||||
OU une confirmation au catalogue ferait dériver les docs en silence. **Piège
|
||||
aveugle** caractéristique : phases ET confirmations valent **tous deux 7**
|
||||
aujourd'hui — un gate qui n'en recompterait qu'un serait aveugle à la dérive de
|
||||
l'autre.
|
||||
|
||||
**Nouveau bloc dans `ci/check_readme_claims.sh`** : recompute **chaque** nombre
|
||||
depuis **son propre** champ du MANIFEST (jamais figé ici · zéro duplication du
|
||||
compteur du générateur #5) et exige l'égalité avec les docs. Le **22** (« suites
|
||||
gated » de la fiche devops) est **volontairement écarté** : sa sémantique (suites
|
||||
CI) ≠ `counts.modules` du run-book (qui s'auto-exclut) → pas de transcription propre,
|
||||
pas de gate hasardeux. Bonus anti-dérive : l'**énumération** des confirmations du
|
||||
README (tokens `snake_case`) doit être l'ensemble **exact** de
|
||||
`confirmations_ouvertes` — mord l'**échange** d'un nom là où le seul compte reste
|
||||
aveugle. Cohérences croisées : `counts.phases == len(phase_order)` ·
|
||||
`counts.confirmations == len(confirmations_ouvertes)`.
|
||||
|
||||
### Preuve (5 morsures vérifiées + restauration verte)
|
||||
|
||||
| Injection | Résultat |
|
||||
|---|---|
|
||||
| fiche devops phases 7→8 (1re transcription) | ✗ dit 8 MAIS artefact 7 · exit 1 |
|
||||
| fiche devops 2e transcription « exécute les 7 »→6 (aveugle si 1re reste 7) | ✗ dit 6 MAIS artefact 7 · exit 1 |
|
||||
| README confirmations 7→8 (count) | ✗ dit 8 MAIS artefact 7 · exit 1 |
|
||||
| README swap d'un nom de confirmation (count reste 7, aveugle au compte) | ✗ énumération ≠ confirmations_ouvertes · exit 1 |
|
||||
| README claim confirmations supprimé (reformulé) | ✗ claim INTROUVABLE · exit 1 |
|
||||
| restauré | ✓ 7 phases + 7 confirmations + énumération == artefacts · exit 0 |
|
||||
|
||||
- **`ci/README.md`** — surface ajoutée à la table récap du pipeline + paragraphe
|
||||
descriptif (classe « run-book de déploiement VPS »).
|
||||
|
||||
Suite CI complète re-verte : `check_artifacts` · `check_readme_claims` ·
|
||||
`check_docs` · `check_regression` · `check_ci_integrity` (gates statiques
|
||||
verrouillés) · `guard_constraints` · `validate_json`.
|
||||
|
||||
**Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo).
|
||||
|
||||
**Auto-score 4Big** : 96/100.
|
||||
|
||||
---
|
||||
|
||||
## Session `20260731_103044` · Buffer S8 · Domaine Legal : la synthèse du DocType « CONFOTUR Application » (« 18 champs · 14 de donnée · 4 sections · 3 rôles · 2 évènements de dépôt ») était transcrite À LA MAIN dans DEUX docs (README du module legal/confotur + fiche agent onapi_legal) sans AUCUN gate — ajouter un champ/section/rôle au spec ferait dériver les deux docs en silence
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer L75** (DevOps CI/CD · QA régression). Roadmap
|
||||
|
||||
+15
-1
@@ -20,7 +20,7 @@ et manuellement (`workflow_dispatch`). Jobs statiques (+ une suite `unittest` pa
|
||||
| `check-artifacts` | `ci/check_artifacts.sh` | Reproductibilité : chaque `out/*.json` versionné == build frais | ✅ oui |
|
||||
| `check-regression` | `ci/check_regression.sh` | Fraîcheur : `qa/regression/out/regression_run.json` (`run`) == run frais + verdict PASS | ✅ oui |
|
||||
| `check-ci-integrity` | `ci/check_ci_integrity.sh` | Intégrité du câblage : `gate.needs` == tous les jobs non-manuels · chaque `ci/*.sh` câblé au gate | ✅ oui |
|
||||
| `check-readme-claims` | `ci/check_readme_claims.sh` | Intégrité des chiffres des docs d'entrée : chaque nombre de `README.md` « État courant », de la fiche QA « Verdict agrégé » **et** de la colonne « Tests » par suite des tables de fiches **et** des agrégats en prose (Total CRM / RBAC / e-CF) **et** des comptes par workspace des portails (cartes/liens/rôles, ×2 docs) **et** des comptes RBAC des 3 volets (table Nb rôles/profil, ligne agrégée apply_plan, ventilation userperm) **et** des comptes de mots-clés SEO (total + fr/en/es, ×2 docs) **et** du pipeline vente CRM (états/transitions, ×2 docs) **et** de l'app mobile Expo (onglets/rôles/langues/identifiants a_confirmer) **et** du DocType CONFOTUR (champs/données/sections/rôles/évènements de dépôt, ×2 docs) **et** de l'audit 5D (contrôles/dimensions ×2 docs + ventilation verdict pass/fail/à-confirmer) == artefact cité (#6) | ✅ oui |
|
||||
| `check-readme-claims` | `ci/check_readme_claims.sh` | Intégrité des chiffres des docs d'entrée : chaque nombre de `README.md` « État courant », de la fiche QA « Verdict agrégé » **et** de la colonne « Tests » par suite des tables de fiches **et** des agrégats en prose (Total CRM / RBAC / e-CF) **et** des comptes par workspace des portails (cartes/liens/rôles, ×2 docs) **et** des comptes RBAC des 3 volets (table Nb rôles/profil, ligne agrégée apply_plan, ventilation userperm) **et** des comptes de mots-clés SEO (total + fr/en/es, ×2 docs) **et** du pipeline vente CRM (états/transitions, ×2 docs) **et** de l'app mobile Expo (onglets/rôles/langues/identifiants a_confirmer) **et** du DocType CONFOTUR (champs/données/sections/rôles/évènements de dépôt, ×2 docs) **et** de l'audit 5D (contrôles/dimensions ×2 docs + ventilation verdict pass/fail/à-confirmer) **et** du run-book de déploiement VPS (phases ×2 dans la fiche devops + confirmations préalables count & énumération dans le README) == artefact cité (#6) | ✅ oui |
|
||||
| `gate` | — | Agrégat vert = gate qualité 4Big franchi | ✅ oui |
|
||||
|
||||
Aucune dépendance réseau/marketplace hors `actions/checkout`. Tout tourne avec
|
||||
@@ -233,6 +233,20 @@ contrôle en A_CONFIRMER (pass 13→12, à confirmer 4→5) là où le total de
|
||||
reste 17 et resterait aveugle. Cohérence croisée en bonus : `controls_total` du
|
||||
MANIFEST doit égaler `totals.controls` du rapport.
|
||||
|
||||
Même classe enfin sur le **run-book de déploiement VPS** (livrable
|
||||
`devops/deploy_runbook`) : le compte de **phases** (fiche agent `devops` — « graphe
|
||||
de **7 phases ordonnées** » **et** « exécute les 7 phases sur le VPS ») **et** le
|
||||
compte de **confirmations préalables** (README du module — « renseigner les 7
|
||||
confirmations ») transcrivaient **à la main** deux nombres qui, aujourd'hui, valent
|
||||
**tous deux 7** — un gate qui n'en recompterait qu'un serait **aveugle** à la dérive
|
||||
de l'autre. Chacun est recomputé depuis **son propre** champ de
|
||||
`devops/deploy_runbook/out/MANIFEST.json` (`counts.phases` = `len(graph.phase_order)` ·
|
||||
`counts.confirmations` = `len(confirmations_ouvertes)`, byte-gaté par
|
||||
`check_artifacts`) et comparé aux docs. Bonus anti-dérive : l'**énumération** des
|
||||
confirmations du README (les tokens `snake_case`) doit être l'ensemble **exact** de
|
||||
`confirmations_ouvertes` — mord l'**échange** d'un nom de confirmation là où le seul
|
||||
compte (reste 7) resterait aveugle.
|
||||
|
||||
Un claim **absent** échoue aussi (la dérive de formulation qui ferait
|
||||
disparaître un chiffre est elle-même une régression de traçabilité). stdlib pur
|
||||
(bash/git/python3), zéro réseau.
|
||||
|
||||
@@ -883,6 +883,100 @@ if a5_ctl is not None:
|
||||
bad(f"Audit 5D · {A5D_FI} — dit {'/'.join(m.groups())} MAIS artefact dit "
|
||||
f"{a5_ctl}/{a5_dim} ({a5_src}) → régénérer la fiche")
|
||||
|
||||
# ============================================================================
|
||||
# DevOps · run-book de déploiement VPS (phases ordonnées / confirmations
|
||||
# préalables) — même classe de « vert trompeur », transcrite À LA MAIN dans
|
||||
# DEUX docs, sans AUCUN gate.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le générateur deploy_runbook émet out/MANIFEST.json (byte-gaté par
|
||||
# check_artifacts ⇒ faisant autorité) dont `counts.phases` et
|
||||
# `counts.confirmations` sont RECOMPTÉS à chaque build (phases = |graph.phase_order| ·
|
||||
# confirmations = |confirmations_ouvertes|, l'ensemble consolidé des paramètres
|
||||
# réglementaires non confirmés). Deux nombres de cette synthèse sont recopiés À LA
|
||||
# MAIN : le compte de PHASES dans la fiche agent DevOps (03_agents/devops/AGENT.md —
|
||||
# « graphe de **7 phases ordonnées** » ET, plus bas, « exécute les 7 phases sur le
|
||||
# VPS ») et le compte de CONFIRMATIONS dans le README du module
|
||||
# (05_deliverables_mvp/devops/deploy_runbook/README.md — « renseigner les 7
|
||||
# confirmations »). Piège « aveugle » caractéristique (cf. bascule verdict audit_5d,
|
||||
# compensation SEO entre langues) : phases ET confirmations valent 7 AUJOURD'HUI —
|
||||
# un gate qui ne recompterait qu'UN nombre serait AVEUGLE à la dérive de l'autre
|
||||
# (ajouter une phase au graphe → 8 phases pendant que les confirmations restent 7,
|
||||
# ou l'inverse). On RECOMPUTE donc CHAQUE nombre depuis SON PROPRE champ du MANIFEST
|
||||
# (jamais figé ici · zéro duplication du compteur du générateur #5) et on exige
|
||||
# l'égalité avec les docs. Bonus anti-dérive : l'ÉNUMÉRATION des confirmations du
|
||||
# README (les tokens `snake_case` de la phrase « Confirmations préalables VPS »)
|
||||
# doit être l'ensemble EXACT de confirmations_ouvertes — capte l'ÉCHANGE d'un nom de
|
||||
# confirmation (count aveugle à un swap 1↔1). Cohérence croisée : counts.phases ==
|
||||
# |phase_order| · counts.confirmations == |confirmations_ouvertes|. Un claim absent
|
||||
# échoue AUSSI (la disparition d'un chiffre est une régression · traçabilité).
|
||||
# ============================================================================
|
||||
DR_RD = f"{D}/devops/deploy_runbook/README.md"
|
||||
DR_FI = "03_agents/devops/AGENT.md"
|
||||
try:
|
||||
dr_man = load("devops/deploy_runbook/out/MANIFEST.json")
|
||||
dr_ph = str(dr_man["counts"]["phases"])
|
||||
dr_cf = str(dr_man["counts"]["confirmations"])
|
||||
dr_order = dr_man["graph"]["phase_order"]
|
||||
dr_open = dr_man["confirmations_ouvertes"]
|
||||
if dr_ph != str(len(dr_order)):
|
||||
bad(f"DevOps · incohérence artefact : counts.phases={dr_ph} MAIS "
|
||||
f"|graph.phase_order|={len(dr_order)}")
|
||||
if dr_cf != str(len(dr_open)):
|
||||
bad(f"DevOps · incohérence artefact : counts.confirmations={dr_cf} MAIS "
|
||||
f"|confirmations_ouvertes|={len(dr_open)}")
|
||||
except (OSError, KeyError, ValueError) as e:
|
||||
bad(f"DevOps · artefact deploy_runbook illisible/inattendu : {e}"); dr_ph = None
|
||||
if dr_ph is not None:
|
||||
# 1) Fiche agent DevOps — « graphe de N phases ordonnées »
|
||||
dr_fi = read_norm(DR_FI)
|
||||
if dr_fi is not None:
|
||||
m = re.search(r"graphe de \*\*(\d+) phases ordonnées\*\*", dr_fi)
|
||||
if m is None:
|
||||
bad(f"DevOps · {DR_FI} — claim « graphe de N phases ordonnées » INTROUVABLE "
|
||||
f"(attendu phases={dr_ph})")
|
||||
elif m.group(1) == dr_ph:
|
||||
good(f"DevOps · {DR_FI} — {m.group(1)} phases == artefact (phases={dr_ph})")
|
||||
else:
|
||||
bad(f"DevOps · {DR_FI} — dit {m.group(1)} phases MAIS artefact dit {dr_ph} "
|
||||
f"→ régénérer la fiche")
|
||||
# 2) Fiche agent DevOps — 2e transcription « exécute les N phases »
|
||||
m = re.search(r"exécute les (\d+) phases", dr_fi)
|
||||
if m is None:
|
||||
bad(f"DevOps · {DR_FI} — 2e claim « exécute les N phases » INTROUVABLE "
|
||||
f"(attendu phases={dr_ph})")
|
||||
elif m.group(1) == dr_ph:
|
||||
good(f"DevOps · {DR_FI} — « exécute les {m.group(1)} phases » == artefact "
|
||||
f"(phases={dr_ph})")
|
||||
else:
|
||||
bad(f"DevOps · {DR_FI} — 2e claim dit {m.group(1)} phases MAIS artefact dit "
|
||||
f"{dr_ph} → régénérer la fiche")
|
||||
# 3) README module — « renseigner les N confirmations » (compte)
|
||||
dr_rd = read_norm(DR_RD)
|
||||
if dr_rd is not None:
|
||||
m = re.search(r"renseigner les (\d+) confirmations", dr_rd)
|
||||
if m is None:
|
||||
bad(f"DevOps · {DR_RD} — claim « renseigner les N confirmations » INTROUVABLE "
|
||||
f"(attendu confirmations={dr_cf})")
|
||||
elif m.group(1) == dr_cf:
|
||||
good(f"DevOps · {DR_RD} — {m.group(1)} confirmations == artefact "
|
||||
f"(confirmations={dr_cf})")
|
||||
else:
|
||||
bad(f"DevOps · {DR_RD} — dit {m.group(1)} confirmations MAIS artefact dit "
|
||||
f"{dr_cf} → régénérer le README")
|
||||
# 4) README module — l'ÉNUMÉRATION doit être l'ensemble EXACT des confirmations
|
||||
seg = re.search(r"Confirmations préalables VPS\*\* \(consolidées, sourcées\) : "
|
||||
r"(.+?) ## ", dr_rd)
|
||||
if seg is None:
|
||||
bad(f"DevOps · {DR_RD} — énumération « Confirmations préalables VPS » "
|
||||
f"INTROUVABLE (attendu {sorted(dr_open)})")
|
||||
else:
|
||||
listed = sorted(set(re.findall(r"`([a-z_]+)`", seg.group(1))))
|
||||
if listed == sorted(dr_open):
|
||||
good(f"DevOps · {DR_RD} — énumération ({len(listed)}) == confirmations_ouvertes")
|
||||
else:
|
||||
bad(f"DevOps · {DR_RD} — énumération {listed} ≠ confirmations_ouvertes "
|
||||
f"{sorted(dr_open)} → régénérer le README")
|
||||
|
||||
sys.exit(1 if FAIL else 0)
|
||||
PY
|
||||
rc=$?
|
||||
|
||||
Reference in New Issue
Block a user