[DTP-Worker] Sprint 8 · buffer L75 · Domaine QA/Recette : le couple « 8 livrables de sprint · 7 métriques succès MVP » du module d'acceptation (qa/acceptance) était transcrit À LA MAIN dans DEUX docs de module (README qa/acceptance/README.md l.8-9 + cellule fiche agent qa/AGENT.md l.27 « 8 livrables + 7 métriques ») sans AUCUN gate — le bloc racine de check_readme_claims ne recompute ce couple que pour le SEUL README d'entrée (« N promesses (X sprint + Y métriques) »), jamais pour ces deux docs de module qui en dérivent. L'artefact qa/acceptance/out/acceptance_matrix.json (byte-gaté par check_artifacts) porte une ligne par promesse roadmap de kind sprint_deliverable OU mvp_metric ; le roadmap-anchor (INV11) ancre les roadmap_line de l'ARTEFACT au fichier roadmap mais ne compare PAS la prose des docs. Ajouter une promesse roadmap → l'artefact rebâtit 9/7 pendant que les deux docs restent à 8/7 en silence (« vert trompeur » qu'aucune suite tests/, qui teste des FONCTIONS pas la prose, n'attrape) → nouveau bloc dans check_readme_claims recomputant CHAQUE nombre depuis SON PROPRE genre de la matrice (n_sprint/n_metric déjà dérivés · zéro duplication #5) et exigeant l'égalité avec les DEUX docs. Recomputer les DEUX (sprint ET métriques) mord une dérive de l'un là où l'autre resterait aveugle. Cohérence croisée en bonus : MANIFEST.counts.{sprint_deliverables,mvp_metrics} == le compte de la matrice qu'il résume — mord un compteur du manifeste désynchronisé de sa liste. Un claim absent échoue AUSSI (4 morsures vérifiées : dérive sprint README captée là où métriques reste 7 · dérive métriques README captée là où sprint reste 8 · dérive fiche QA captée là où le README est intact · claim fiche disparu = red ; restauré = green). État courant : aucun nombre périmé (8/7 recoupe la matrice · anti-invention #6, rien à réécrire) — le défaut est la surface ungated. ci/README.md (table + détail) mis à jour · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,65 @@
|
||||
# Activity Log · 2026-07-31 · Claude Code DTP
|
||||
|
||||
## Session `20260731_130055` · Buffer S8 · Domaine QA/Recette : le couple « **8 livrables de sprint · 7 métriques succès MVP** » du module d'acceptation (`qa/acceptance`) était transcrit À LA MAIN dans DEUX docs de module (README du module + fiche agent QA) sans AUCUN gate — le bloc racine ne gate QUE le README d'entrée
|
||||
|
||||
**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), QA (audit 5D + audit 4big), DevOps
|
||||
(run-book), Démo (run-sheet) et Frontend/Chat OTOIA. Cette session cible le **module de
|
||||
recette** (`qa/acceptance`) — son couple data-derived « livrables de sprint /
|
||||
métriques succès MVP », cité dans deux docs de module que le bloc racine ne couvrait pas.
|
||||
|
||||
### Défaut trouvé — couple ungated, transcrit dans DEUX docs de module
|
||||
|
||||
- **`05_deliverables_mvp/qa/acceptance/README.md:8-9`** : puces « **8 livrables de
|
||||
sprint** (L33..L76) » et « **7 métriques succès MVP** (L81..L87) ».
|
||||
- **`03_agents/qa/AGENT.md:27`** : cellule « mappe chaque promesse roadmap (**8
|
||||
livrables + 7 métriques**) vers sa preuve » — **même** couple dérivé de la **même**
|
||||
matrice (source unique · #5).
|
||||
- L'artefact source est byte-gaté par `check_artifacts` :
|
||||
`qa/acceptance/out/acceptance_matrix.json` porte une ligne par promesse roadmap de
|
||||
`kind` `sprint_deliverable` OU `mvp_metric`. Le bloc racine de `check_readme_claims`
|
||||
recompute déjà ce couple pour le **SEUL README d'entrée** (« N promesses (X sprint +
|
||||
Y métriques) ») — mais **jamais** ces deux docs de **module**.
|
||||
- Le **roadmap-anchor** (INV11) ancre les `roadmap_line` de l'**ARTEFACT** au fichier
|
||||
roadmap ; il ne compare **pas** la prose des docs. Ajouter une promesse roadmap →
|
||||
l'artefact rebâtit 9/7 pendant que les deux docs restent à 8/7 en silence — « vert
|
||||
trompeur » qu'aucune suite `tests/` (qui teste des FONCTIONS, pas la prose) n'attrape.
|
||||
- **État courant** : **aucun nombre périmé** — 8/7 recoupe la matrice exactement
|
||||
(anti-invention #6 : rien à réécrire). Le défaut est la **surface ungated**.
|
||||
|
||||
**Nouveau bloc dans `ci/check_readme_claims.sh`** : recompute **chaque** nombre depuis
|
||||
**son propre** genre de la matrice (`kind` `sprint_deliverable` / `mvp_metric`,
|
||||
`n_sprint`/`n_metric` déjà dérivés plus haut · zéro duplication #5) et exige l'égalité
|
||||
avec les DEUX docs. Recomputer les DEUX (sprint ET métriques) mord une dérive de l'un
|
||||
là où l'autre resterait aveugle. Cohérence croisée en bonus :
|
||||
`MANIFEST.counts.{sprint_deliverables,mvp_metrics}` == le compte de la matrice qu'il
|
||||
résume — mord un compteur du manifeste désynchronisé de sa liste. Un claim absent
|
||||
échoue AUSSI (traçabilité).
|
||||
|
||||
### Preuve (4 morsures vérifiées + restauration verte)
|
||||
|
||||
| Injection | Résultat |
|
||||
|---|---|
|
||||
| README sprint `8→9` (métriques reste 7) | ✗ dit 9/7 MAIS matrice 8/7 · exit 1 |
|
||||
| README métriques `7→6` (sprint reste 8) | ✗ dit 8/6 MAIS matrice 8/7 · exit 1 |
|
||||
| fiche QA parenthèse `8→10` (README intact) | ✗ dit 10/7 MAIS matrice 8/7 · exit 1 |
|
||||
| fiche QA claim supprimé (reformulé) | ✗ claim INTROUVABLE · exit 1 |
|
||||
| restauré | ✓ 8/7 == matrice (2 docs) · exit 0 |
|
||||
|
||||
- **`ci/README.md`** — surface ajoutée à la table récap du pipeline + paragraphe
|
||||
descriptif (classe « module de recette `qa/acceptance` »).
|
||||
|
||||
Suite CI complète re-verte : `guard_constraints` · `validate_json` · `check_docs` ·
|
||||
`check_artifacts` · `check_regression` · `check_ci_integrity` · `check_readme_claims`.
|
||||
|
||||
**Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo).
|
||||
|
||||
**Auto-score 4Big** : 96/100.
|
||||
|
||||
---
|
||||
|
||||
## Session `20260731_123055` · Buffer S8 · Domaine Frontend/Chat OTOIA : le montage de l'assistant conversationnel par portail (`frontend/chat_otoia`) affichait « **5 `Custom Block` + 5 configs runtime** » (fiche agent frontend_console) et « **5 portails · 5 fixtures · 5 configs runtime** » (README du module) — trois nombres data-derived, TOUS = 5 (piège aveugle), transcrits À LA MAIN dans DEUX docs sans AUCUN gate
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer L75** (DevOps CI/CD · QA régression). Roadmap
|
||||
|
||||
+16
-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) **et** du run-book de déploiement VPS (phases ×2 dans la fiche devops + confirmations préalables count & énumération dans le README) **et** du run-sheet de démo (nombre de modules cités dans le diagramme du README) **et** du montage Chat OTOIA par portail (`Custom Block`/configs runtime/portails, tous = 5 aujourd'hui, ×2 docs) == 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) **et** du run-sheet de démo (nombre de modules cités dans le diagramme du README) **et** du montage Chat OTOIA par portail (`Custom Block`/configs runtime/portails, tous = 5 aujourd'hui, ×2 docs) **et** du module de recette `qa/acceptance` (couple livrables de sprint + métriques succès MVP, ×2 docs de module au-delà du README d'entrée) == 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
|
||||
@@ -274,6 +274,21 @@ croisée : `custom_blocks` == `mounts` == `portails` == |`MANIFEST.portails`| (l
|
||||
bijection 1 block ⇔ 1 mount ⇔ 1 portail du générateur) — mord un compteur
|
||||
désynchronisé de sa propre liste.
|
||||
|
||||
Même classe enfin sur le **module de recette** (`qa/acceptance`) : le couple
|
||||
« **N livrables de sprint** + **M métriques succès MVP** » est transcrit **à la
|
||||
main** dans DEUX docs que le bloc racine ne couvre pas — le README du module
|
||||
(deux puces) ET la fiche agent QA (« (N livrables + M métriques) »). Le bloc
|
||||
racine ne gate que le SEUL README d'entrée (« N promesses (X sprint + Y
|
||||
métriques) ») ; ces deux docs de module en dérivent. Ajouter une promesse roadmap
|
||||
(l'artefact rebâtit 9/7) ferait dériver les deux docs en silence — piège que ni
|
||||
les suites `tests/` ni le **roadmap-anchor** (qui ancre les `roadmap_line` de
|
||||
l'ARTEFACT, pas la prose des docs) n'attrapent. Chaque nombre est recomputé depuis
|
||||
**son propre** genre de la matrice `qa/acceptance/out/acceptance_matrix.json`
|
||||
(`kind` `sprint_deliverable` / `mvp_metric`, byte-gatée par `check_artifacts`) et
|
||||
comparé aux deux docs. Cohérence croisée en bonus :
|
||||
`MANIFEST.counts.{sprint_deliverables,mvp_metrics}` == le compte de la matrice
|
||||
qu'il résume — mord un compteur du manifeste désynchronisé de sa liste.
|
||||
|
||||
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.
|
||||
|
||||
@@ -79,6 +79,11 @@
|
||||
# MANIFEST.counts (custom_blocks/mounts/portails, recomptés du contrat RBAC,
|
||||
# byte-gatés) + cohérence croisée == |MANIFEST.portails| (bijection 1 block ⇔
|
||||
# 1 mount ⇔ 1 portail)
|
||||
# qa/acceptance/README.md + 03_agents/qa/AGENT.md (module de recette) :
|
||||
# • couple « N livrables de sprint + M métriques succès MVP » transcrit À LA MAIN
|
||||
# dans DEUX docs de module (le bloc racine ne gate que le README d'entrée)
|
||||
# → recompté depuis la matrice acceptance (kind sprint_deliverable / mvp_metric)
|
||||
# + cohérence croisée == MANIFEST.counts (compteur ⇔ matrice résumée)
|
||||
# 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é).
|
||||
#
|
||||
@@ -1125,6 +1130,69 @@ if co_cb is not None:
|
||||
bad(f"Chat OTOIA · {CO_RD} — dit {m.group(1)} configs runtime MAIS artefact "
|
||||
f"dit {co_mo} → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Recette (module) · couple « N livrables de sprint + M métriques succès MVP »
|
||||
# transcrit À LA MAIN dans DEUX docs — même classe de « vert trompeur ».
|
||||
# ----------------------------------------------------------------------------
|
||||
# La matrice d'acceptation (qa/acceptance/out/acceptance_matrix.json, byte-gatée
|
||||
# par check_artifacts ⇒ faisant autorité) porte une ligne par promesse roadmap,
|
||||
# de `kind` sprint_deliverable OU mvp_metric. Le compte de chaque genre (n_sprint,
|
||||
# n_metric déjà recalculés plus haut depuis la matrice, jamais saisis) est repris
|
||||
# À LA MAIN à DEUX endroits que le bloc racine ne couvre PAS : le README du module
|
||||
# (05_deliverables_mvp/qa/acceptance/README.md — puces « N livrables de sprint »
|
||||
# puis « M métriques succès MVP ») ET la fiche agent QA (03_agents/qa/AGENT.md —
|
||||
# « (N livrables + M métriques) »). Le bloc racine plus haut ne gate que le SEUL
|
||||
# README d'entrée (« N promesses (X sprint + Y métriques) ») ; ces deux docs de
|
||||
# module en dérivent sans gate. Ajouter une promesse roadmap (l'artefact rebâtit
|
||||
# 9/7) ferait dériver LES DEUX docs en silence pendant que la matrice dit autre
|
||||
# chose — piège que ni les suites tests/ (qui testent des FONCTIONS, pas la prose)
|
||||
# ni le roadmap-anchor (qui ancre les `roadmap_line` de l'ARTEFACT, pas la prose
|
||||
# des docs) n'attrapent. On RECOMPUTE ici chaque nombre depuis SON PROPRE genre de
|
||||
# la matrice (jamais figé · zéro duplication #5) et on exige l'égalité avec les
|
||||
# DEUX docs. Recomputer les DEUX (sprint ET métriques) mord une dérive de l'un là
|
||||
# où l'autre resterait aveugle. Cohérence croisée en bonus :
|
||||
# MANIFEST.counts.{sprint_deliverables,mvp_metrics} == (n_sprint, n_metric) — mord
|
||||
# un compteur du manifeste désynchronisé de la matrice qu'il résume. Un claim
|
||||
# absent échoue AUSSI (la disparition d'un chiffre est une régression · traçabilité).
|
||||
# ============================================================================
|
||||
ACC_RD = f"{D}/qa/acceptance/README.md"
|
||||
ACC_FI = "03_agents/qa/AGENT.md"
|
||||
acc_exp = (str(n_sprint), str(n_metric))
|
||||
acc_src = f"livrables_sprint={acc_exp[0]} métriques={acc_exp[1]}"
|
||||
try:
|
||||
acc_mc = load("qa/acceptance/out/MANIFEST.json")["counts"]
|
||||
if (str(acc_mc["sprint_deliverables"]), str(acc_mc["mvp_metrics"])) != acc_exp:
|
||||
bad(f"Recette · incohérence artefact : MANIFEST.counts dit "
|
||||
f"{acc_mc['sprint_deliverables']}/{acc_mc['mvp_metrics']} MAIS la matrice "
|
||||
f"dit {'/'.join(acc_exp)} (compteur désynchronisé de sa liste)")
|
||||
except (OSError, KeyError, ValueError) as e:
|
||||
bad(f"Recette · MANIFEST acceptance illisible/inattendu : {e}")
|
||||
# 1) README du module — deux puces distinctes (livrables sprint · métriques MVP)
|
||||
acc_rd = read_norm(ACC_RD)
|
||||
if acc_rd is not None:
|
||||
ms = re.search(r"\*\*(\d+) livrables de sprint\*\*", acc_rd)
|
||||
mm = re.search(r"\*\*(\d+) métriques succès MVP\*\*", acc_rd)
|
||||
if ms is None or mm is None:
|
||||
bad(f"Recette · {ACC_RD} — puces « N livrables de sprint » / « M métriques "
|
||||
f"succès MVP » INTROUVABLE(s) (attendu {acc_src})")
|
||||
elif (ms.group(1), mm.group(1)) == acc_exp:
|
||||
good(f"Recette · {ACC_RD} — {ms.group(1)}/{mm.group(1)} == matrice ({acc_src})")
|
||||
else:
|
||||
bad(f"Recette · {ACC_RD} — dit {ms.group(1)}/{mm.group(1)} MAIS matrice dit "
|
||||
f"{'/'.join(acc_exp)} ({acc_src}) → régénérer le README")
|
||||
# 2) Fiche agent QA — parenthèse « (N livrables + M métriques) »
|
||||
acc_fi = read_norm(ACC_FI)
|
||||
if acc_fi is not None:
|
||||
m = re.search(r"\((\d+) livrables \+ (\d+) métriques\)", acc_fi)
|
||||
if m is None:
|
||||
bad(f"Recette · {ACC_FI} — claim « (N livrables + M métriques) » INTROUVABLE "
|
||||
f"(attendu {acc_src})")
|
||||
elif m.groups() == acc_exp:
|
||||
good(f"Recette · {ACC_FI} — {'/'.join(m.groups())} == matrice ({acc_src})")
|
||||
else:
|
||||
bad(f"Recette · {ACC_FI} — dit {'/'.join(m.groups())} MAIS matrice dit "
|
||||
f"{'/'.join(acc_exp)} ({acc_src}) → régénérer la fiche")
|
||||
|
||||
sys.exit(1 if FAIL else 0)
|
||||
PY
|
||||
rc=$?
|
||||
|
||||
Reference in New Issue
Block a user