[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:
@@ -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