[DTP-Worker] Sprint 8 · buffer · QA/audit_4big : gate des SEUILS STRUCTURELS de la colonne « Fait vérifié »

3e surface du MÊME README audit_4big, jamais gatée : les deux seuils que le
scorer applique (DOC « ≥ 400 octets » · TESTS « ≥ 8 méthodes def test_* »),
transcrits à la main. Le bloc BARÈME ne capture que le POIDS voisin (regex
`| `DOC` | 20 |`), aveugle à la 3e cellule. Ces nombres sont DATA-DERIVED de
quality_spec.json[thresholds] (min_doc_bytes/min_test_methods) — l'INPUT
byte-gaté par check_artifacts (report rebuild depuis lui).

Gate ajouté (check_readme_claims.sh) : (1) cross-check d'ANCRAGE — le seuil
TESTS APPLIQUÉ, lu de l'evidence « (seuil N) » de CHAQUE module du report ==
spec.min_test_methods pour tous (mord une divergence spec↔report) ; (2) prose
DOC « ≥ N octets » == spec ; (3) prose TESTS « ≥ N méthodes » == spec ; claim
absent échoue AUSSI (traçabilité #6). Élever min_test_methods (8→12 : module de
8-11 tests sous FAIL) ou changer min_doc_bytes rebuild le report SANS toucher au
README → prose périmée en silence, désormais interdite.

5 morsures vérifiées (README 400→450 · README 8→10 · ligne DOC vidée · spec
min_test_methods 8→12 rebuild : README+cross-check · spec min_doc_bytes 400→500
rebuild) ; restauré = green · 7 gates re-verts. ci/README.md (récap + paragraphe
détaillé) mis à jour. Hors périmètre VPS : néant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-01 17:12:01 +00:00
parent a52daa056f
commit b9e333ceef
3 changed files with 147 additions and 1 deletions
+72
View File
@@ -514,6 +514,78 @@ if criteria is not None and a4_txt:
bad(f"README audit_4big · archétype `{a}` — {A4} exclut {sorted(got)} MAIS "
f"le référentiel exclut {exp} → régénérer le README")
# ============================================================================
# README de l'auditeur 4Big · SEUILS STRUCTURELS de la colonne « Fait vérifié »
# (min_doc_bytes / min_test_methods) — 3e surface du MÊME README, jamais gatée.
# ----------------------------------------------------------------------------
# Le bloc BARÈME ci-dessus recompute les POIDS (2e colonne de la table
# « Critère | Poids | Fait vérifié »), mais la 3e colonne « Fait vérifié » NOMME
# les DEUX seuils structurels que le scorer applique réellement :
# • DOC « un *.md (README/SPEC) ≥ 400 octets » → thresholds.min_doc_bytes
# • TESTS « ≥ 8 méthodes def test_* dans tests/ » → thresholds.min_test_methods
# Ces deux nombres sont DATA-DERIVED de quality_spec.json[thresholds] — l'INPUT
# du générateur, byte-gaté par check_artifacts qui prouve que quality_report.json
# se rebuild depuis lui — et TRANSCRITS À LA MAIN dans la table. AUCUN gate ne
# les liait : le bloc BARÈME ne capture que le poids (`| \`DOC\` | 20 |`),
# AVEUGLE à la 3e cellule. Élever min_test_methods (8→12 : un module de 8-11
# tests tomberait sous FAIL — la barre même que le critère pose) ou changer
# min_doc_bytes dans le spec rebuild le report SANS TOUCHER au README → prose
# « ≥ 8 méthodes » / « ≥ 400 octets » PÉRIMÉE en silence, l'auditeur documentant
# un barème qu'il n'applique plus (l'invention #6 interdit). Aucune suite tests/
# (qui teste des FONCTIONS de scoring, pas la prose) n'attrape ce « vert
# trompeur ». CROSS-CHECK d'ancrage : l'evidence TESTS de CHAQUE module du report
# porte « (seuil N) » (émise par crit_tests) — on exige N == spec.min_test_methods
# pour TOUS, prouvant que le seuil ÉCRIT dans le spec == le seuil réellement
# APPLIQUÉ à la construction (mord une divergence spec↔report). Un claim absent
# échoue AUSSI (traçabilité #6).
# ============================================================================
try:
_a4_thr = load("qa/audit_4big/quality_spec.json")["thresholds"]
min_doc = int(_a4_thr["min_doc_bytes"])
min_test = int(_a4_thr["min_test_methods"])
except (OSError, KeyError, ValueError, TypeError) as e:
bad(f"README audit_4big seuils · quality_spec.json[thresholds] illisible/inattendu : {e}")
min_doc = min_test = None
if min_doc is not None and criteria is not None and a4_txt:
# cross-check d'ancrage : seuil TESTS APPLIQUÉ (evidence report) == spec
ev_seuils = set()
for m in qr_crit["modules"]:
for ck in m.get("checks", []):
if ck.get("criterion") == "TESTS":
mm = re.search(r"\(seuil (\d+)\)", ck.get("evidence", ""))
if mm:
ev_seuils.add(int(mm.group(1)))
if not ev_seuils:
bad("README audit_4big seuils · aucune evidence TESTS « (seuil N) » dans le "
"report — impossible d'ancrer le seuil réellement appliqué")
elif ev_seuils != {min_test}:
bad(f"README audit_4big seuils · seuil TESTS APPLIQUÉ (evidence report) "
f"{sorted(ev_seuils)} ≠ spec.min_test_methods ({min_test}) → spec↔report "
f"divergent (régénérer le report)")
else:
good(f"README audit_4big seuils · seuil TESTS appliqué (report) == spec "
f"({min_test}) sur tous les modules")
# prose · DOC « ≥ N octets » (3e cellule de la ligne DOC)
md = re.search(r"`DOC`[^|]*\|[^|]*\|[^|]*?≥\s*(\d+)\s*octets", a4_txt)
if md is None:
bad(f"README audit_4big seuils · ligne DOC « ≥ N octets » INTROUVABLE dans {A4} "
f"(attendu {min_doc})")
elif md.group(1) == str(min_doc):
good(f"README audit_4big seuils · DOC — « ≥ {md.group(1)} octets » == spec ({min_doc})")
else:
bad(f"README audit_4big seuils · DOC — {A4} dit « ≥ {md.group(1)} octets » MAIS "
f"spec.min_doc_bytes == {min_doc} → régénérer le README")
# prose · TESTS « ≥ N méthodes » (3e cellule de la ligne TESTS)
mt = re.search(r"`TESTS`[^|]*\|[^|]*\|[^|]*?≥\s*(\d+)\s*méthodes", a4_txt)
if mt is None:
bad(f"README audit_4big seuils · ligne TESTS « ≥ N méthodes » INTROUVABLE dans {A4} "
f"(attendu {min_test})")
elif mt.group(1) == str(min_test):
good(f"README audit_4big seuils · TESTS — « ≥ {mt.group(1)} méthodes » == spec ({min_test})")
else:
bad(f"README audit_4big seuils · TESTS — {A4} dit « ≥ {mt.group(1)} méthodes » MAIS "
f"spec.min_test_methods == {min_test} → régénérer le README")
# ============================================================================
# Fiches agents · comptes de tests PAR SUITE (colonne « Tests » des tables) —
# même classe de « vert trompeur », au grain le PLUS FIN.