[DTP-Worker] Sprint 8 · buffer L75 · Domaine QA/Audit 4Big : le BARÈME de notation de l'auditeur (« 5 critères 4Big déterministes » + la table Critère|Poids DOC 20/CONTRAT 20/TESTS 25/CLI 15/HANDOFF 20 + l'archétype « generator (5 critères) ») était transcrit À LA MAIN dans le README du module sans AUCUN gate — ironie du module qui NOTE les autres retranscrivant son propre référentiel de scoring. Le bloc racine de check_readme_claims ne gatait que la ligne « Résultat courant » (verdict/modules/min_score), jamais le barème lui-même, alors que qa/audit_4big/out/quality_report.json (byte-gaté par check_artifacts, criteria[] recomputé du référentiel à chaque build) fait autorité. Ajouter/retirer un critère OU changer un poids ferait dériver le README en silence pendant que l'artefact dit autre chose — « vert trompeur » qu'aucune suite tests/ (qui teste des FONCTIONS, pas la prose) n'attrape → nouveau bloc recomputant le nombre de critères (prose « N critères 4Big déterministes » + archétype « generator (N critères) », generator appliquant TOUS les critères) et CHAQUE poids depuis criteria[].weight (zéro duplication du barème du générateur #6), exigeant l'égalité avec le README. Contrôle PAR CRITÈRE et pas seulement de la somme : une compensation de poids (+5/−5) laisserait Σ==100 juste et deux lignes fausses. Cohérences croisées en bonus : Σ poids == 100 (base de renormalisation documentée) ET tout module d'archétype generator porte EXACTEMENT len(criteria) checks (« generator = tous les critères » — 18 modules generator × 5 checks vérifiés). Un claim absent échoue AUSSI (4 morsures vérifiées : prose 5→6 captée là où les poids restent justes · poids TESTS 25→30 capté là où le compte reste 5 · generator 5→4 · claim prose disparu = red ; restauré = green). 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:
+23
-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) **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 |
|
||||
| `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) **et** du barème de l'auditeur 4Big (nombre de critères en prose + poids par critère de la table + « generator (N critères) », recomputés de `quality_report.criteria`) == 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
|
||||
@@ -289,6 +289,28 @@ 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.
|
||||
|
||||
Même classe enfin sur le **barème de l'auditeur 4Big** (livrable `qa/audit_4big`).
|
||||
Ironie déjà notée : le module qui NOTE les autres retranscrit son propre référentiel
|
||||
de scoring **à la main** dans son README (`05_deliverables_mvp/qa/audit_4big/README.md`)
|
||||
— la prose « Note chaque module sur **N critères 4Big déterministes** », la table
|
||||
« Critère | Poids | … » (une ligne `id`→poids par critère) et l'archétype
|
||||
« `generator` (**N** critères) ». Ces trois surfaces DÉRIVENT de
|
||||
`quality_report.json.criteria` (byte-gaté par `check_artifacts`, recomputé du
|
||||
référentiel à chaque build) ; ajouter/retirer un critère ou changer un poids ferait
|
||||
dériver le README en silence pendant que l'artefact dit autre chose — dérive qu'aucune
|
||||
suite `tests/` (qui teste des FONCTIONS, pas la prose) n'attrape. Le bloc racine ne
|
||||
gate que la ligne « Résultat courant » (verdict/modules), jamais le barème. On
|
||||
recompute donc le **nombre de critères** (prose + « generator »), et **chaque poids**
|
||||
depuis `criteria[].weight` (zéro duplication du barème du générateur · #6). Cohérences
|
||||
croisées : `Σ poids == 100` (base de renormalisation documentée) ET tout module
|
||||
d'archétype `generator` porte EXACTEMENT `len(criteria)` `checks` — c.-à-d.
|
||||
« generator = tous les critères », ce qui rend le « generator (N critères) » du README
|
||||
vérifiablement vrai (mord une dérive du modèle qui le rendrait faux). Une **compensation**
|
||||
(un poids +5 / un autre −5) laisserait `Σ == 100` juste et deux lignes fausses : d'où
|
||||
le contrôle **par critère**, pas seulement de la somme. 4 morsures vérifiées : dérive
|
||||
prose `5→6` (poids intacts) · dérive poids `TESTS 25→30` (compte intact) · dérive
|
||||
`generator (5→4)` · claim prose disparu ; restauré = vert.
|
||||
|
||||
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.
|
||||
|
||||
@@ -301,6 +301,84 @@ else:
|
||||
bad(f"README audit_4big · {A4} dit {'/'.join(ma4.groups())} MAIS quality_report "
|
||||
f"dit {'/'.join(a4_exp)} ({a4_src}) → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# README de l'auditeur 4Big · BARÈME de notation (N critères + poids par critère)
|
||||
# — même classe de « vert trompeur », au grain du référentiel de scoring.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le barème 4Big est DATA-DERIVED : quality_report.json.criteria (byte-gaté par
|
||||
# check_artifacts, RECOMPUTÉ du référentiel à chaque build) porte la liste des
|
||||
# critères et leur poids. Le README les RETRANSCRIT À LA MAIN à trois endroits :
|
||||
# • la prose « Note chaque module sur N critères 4Big déterministes »,
|
||||
# • la table « Critère | Poids | Fait vérifié » (une ligne id→poids par critère),
|
||||
# • l'archétype « generator (N critères) » (generator applique TOUS les critères).
|
||||
# Ajouter/retirer un critère ou changer un poids ferait dériver ces trois surfaces
|
||||
# en silence pendant que l'artefact dit autre chose — aucune suite tests/ (qui teste
|
||||
# des FONCTIONS, pas la prose du README) ne l'attrape. On RECOMPUTE ici chaque nombre
|
||||
# depuis `criteria` (zéro duplication du barème du générateur · #6) et on exige
|
||||
# l'égalité avec ce que la doc ÉCRIT. Cohérences croisées : Σ poids == 100 (base de
|
||||
# renormalisation) ET tout module d'archétype `generator` porte EXACTEMENT
|
||||
# len(criteria) checks — c.-à-d. « generator = tous les critères » (mord une dérive
|
||||
# du modèle qui rendrait le « generator (N critères) » du README faux). Un claim
|
||||
# absent échoue AUSSI (disparition = régression de traçabilité).
|
||||
# ============================================================================
|
||||
try:
|
||||
qr_crit = load("qa/audit_4big/out/quality_report.json")
|
||||
criteria = qr_crit["criteria"]
|
||||
except (OSError, KeyError, ValueError) as e:
|
||||
bad(f"README audit_4big · quality_report illisible : {e}"); criteria = None
|
||||
if criteria is not None and a4_txt:
|
||||
n_crit = len(criteria)
|
||||
# 1) prose « N critères 4Big déterministes »
|
||||
mc = re.search(r"sur (\d+) critères 4Big déterministes", a4_txt)
|
||||
if mc is None:
|
||||
bad(f"README audit_4big · prose « N critères 4Big » — claim INTROUVABLE dans "
|
||||
f"{A4} (attendu {n_crit})")
|
||||
elif mc.group(1) == str(n_crit):
|
||||
good(f"README audit_4big · prose critères — {mc.group(1)} == criteria ({n_crit})")
|
||||
else:
|
||||
bad(f"README audit_4big · prose critères — {A4} dit {mc.group(1)} MAIS criteria "
|
||||
f"en compte {n_crit} → régénérer le README")
|
||||
# 2) table « Critère | Poids | … » — une ligne id→poids par critère
|
||||
for c in criteria:
|
||||
cid, w = c["id"], str(c["weight"])
|
||||
mw = re.search(rf"\| `{re.escape(cid)}` \| (\d+) \|", a4_txt)
|
||||
if mw is None:
|
||||
bad(f"README audit_4big · critère {cid} — ligne INTROUVABLE dans {A4} "
|
||||
f"(attendu poids={w})")
|
||||
elif mw.group(1) == w:
|
||||
good(f"README audit_4big · critère {cid} — poids {mw.group(1)} == criteria ({w})")
|
||||
else:
|
||||
bad(f"README audit_4big · critère {cid} — {A4} dit poids {mw.group(1)} MAIS "
|
||||
f"criteria dit {w} → régénérer le README")
|
||||
# 3) archétype « generator (N critères) » — generator applique TOUS les critères
|
||||
mg = re.search(r"`generator` \((\d+) critères\)", a4_txt)
|
||||
if mg is None:
|
||||
bad(f"README audit_4big · archétype « generator (N critères) » — claim "
|
||||
f"INTROUVABLE dans {A4} (attendu {n_crit})")
|
||||
elif mg.group(1) == str(n_crit):
|
||||
good(f"README audit_4big · generator — {mg.group(1)} critères == criteria ({n_crit})")
|
||||
else:
|
||||
bad(f"README audit_4big · generator — {A4} dit {mg.group(1)} MAIS l'archétype "
|
||||
f"generator applique les {n_crit} critères → régénérer le README")
|
||||
# 4) cohérence croisée : Σ poids == 100 (base de renormalisation)
|
||||
w_sum = sum(c["weight"] for c in criteria)
|
||||
if w_sum == 100:
|
||||
good(f"README audit_4big · Σ poids critères == {w_sum} (base 100 cohérente)")
|
||||
else:
|
||||
bad(f"README audit_4big · Σ poids critères == {w_sum} ≠ 100 — barème incohérent "
|
||||
f"avec la renormalisation documentée")
|
||||
# 5) cohérence croisée : tout module `generator` porte len(criteria) checks
|
||||
gen = [m for m in qr_crit["modules"] if m.get("archetype") == "generator"]
|
||||
gen_bad = [m["id"] for m in gen if len(m.get("checks", [])) != n_crit]
|
||||
if not gen:
|
||||
good("README audit_4big · aucun module d'archétype generator (rien à recouper)")
|
||||
elif gen_bad:
|
||||
bad(f"README audit_4big · modules generator avec ≠ {n_crit} checks : {gen_bad} "
|
||||
f"→ « generator = tous les critères » violé")
|
||||
else:
|
||||
good(f"README audit_4big · {len(gen)} module(s) generator portent {n_crit} "
|
||||
f"checks (« generator = tous les critères » vérifié)")
|
||||
|
||||
# ============================================================================
|
||||
# Fiches agents · comptes de tests PAR SUITE (colonne « Tests » des tables) —
|
||||
# même classe de « vert trompeur », au grain le PLUS FIN.
|
||||
|
||||
Reference in New Issue
Block a user