[DTP-Worker 20260801_230453] Sprint 8 · buffer · QA/Audit 5D : gate d'IDENTITÉ du VERDICT GLOBAL — le LABEL de conclusion de l'audit (PASS / PASS_WITH_OPEN_ITEMS / FAIL), la HEADLINE du livrable, était HORS de tout gate : le bloc audit_5d existant recompute la ventilation chiffrée (13 PASS · 0 FAIL · 4 à confirmer), les open items, les 5 dimensions et les livrables audités — jamais le label lui-même. Or il est data-derived (audit_report.json[verdict] == MANIFEST.json[verdict], byte-gatés), recalculé par builder.py (FAIL si ≥1 FAIL · sinon PASS_WITH_OPEN_ITEMS si ≥1 A_CONFIRMER · sinon PASS) et transcrit à la main à 2 endroits du README (la RÈGLE l.39 + le VERDICT COURANT l.49). Nouveau bloc : on MIROITE la règle et on exige (a) HONNÊTETÉ interne audit_report.verdict == verdict(triplet) — un PASS forcé pendant que 4 params restent a_confirmer (CŒUR #6 : ne jamais forcer un PASS) est mordu ; (b) MANIFEST.verdict == audit_report.verdict ; (c) label « Verdict courant » README == artefact ; (d) la règle « Verdict global » énumère EXACTEMENT le codomaine {FAIL, PASS_WITH_OPEN_ITEMS, PASS} du générateur. 5 morsures vérifiées (2 README · 2 artefact + M3 cascade a+b+c · 1 disparition), 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-08-01 · Claude Code DTP
|
||||
|
||||
## Session `20260801_230453` · Buffer S8 · QA/Audit 5D : gate d'IDENTITÉ du **VERDICT GLOBAL** — le LABEL de conclusion de l'audit
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||||
complète ; la valeur marginale reste le durcissement anti-dérive (CLAUDE.md #6)
|
||||
des surfaces prose data-derived encore non gatées. Les 7 gates verts au départ.
|
||||
|
||||
**Surface trouvée (aveugle)** : le **verdict global** de l'audit 5D — le LABEL
|
||||
`PASS` / `PASS_WITH_OPEN_ITEMS` / `FAIL` qui est la **HEADLINE de tout le
|
||||
livrable** — était **HORS de tout gate**. Le bloc audit_5d existant recompute la
|
||||
**ventilation chiffrée** (« **13 PASS · 0 FAIL · 4 à confirmer** », pass/fail/à
|
||||
confirmer d'`audit_report.totals`), l'énumération des open items, les 5 dimensions
|
||||
et les livrables audités — mais **jamais le label de verdict lui-même**. Or ce
|
||||
label est data-derived (`out/audit_report.json[verdict]` == `out/MANIFEST.json[verdict]`
|
||||
== `PASS_WITH_OPEN_ITEMS`, byte-gatés), recalculé par `qalib/builder.py` via la
|
||||
règle **`FAIL` si ≥1 FAIL · sinon `PASS_WITH_OPEN_ITEMS` si ≥1 A_CONFIRMER · sinon
|
||||
`PASS`**, et transcrit à la main à **deux** endroits du README : la RÈGLE
|
||||
(`Verdict global : …`, l.39) et le VERDICT COURANT (`## Verdict courant` l.49). Le
|
||||
risque #6 est le **CŒUR** du livrable : écrire `PASS` alors que 4 params
|
||||
réglementaires restent `a_confirmer` = l'audit « force » un PASS et prétend propre
|
||||
un dossier qui ne l'est pas — exactement ce que l'audit reproche aux autres. La
|
||||
ventilation chiffrée peut rester exacte pendant que le label ment ; ni
|
||||
`check_artifacts` (byte only) ni les suites `tests/` (FONCTIONS, pas la prose)
|
||||
n'attrapent.
|
||||
|
||||
**Gate ajouté** (`ci/check_readme_claims.sh`, bloc « Audit 5D · IDENTITÉ du VERDICT
|
||||
GLOBAL », inséré juste après la ventilation chiffrée) : on **MIROITE** la règle du
|
||||
générateur et on exige — **(a)** HONNÊTETÉ interne : `audit_report.verdict` ==
|
||||
verdict recalculé du triplet (fail>0→FAIL · a_confirmer>0→PASS_WITH_OPEN_ITEMS ·
|
||||
sinon PASS) ⇒ un verdict FORCÉ incohérent avec ses propres chiffres est mordu ;
|
||||
**(b)** CROISÉ : `MANIFEST.verdict` == `audit_report.verdict` ; **(c)** le LABEL
|
||||
« Verdict courant » du README == `audit_report.verdict` (ancré sur le heading +
|
||||
la ventilation `**N PASS`, pas sur la règle l.39) ; **(d)** la RÈGLE « Verdict
|
||||
global » énumère EXACTEMENT le **codomaine** `{FAIL, PASS_WITH_OPEN_ITEMS, PASS}`
|
||||
du générateur (un label renommé côté `builder.py` sans mise à jour de la règle est
|
||||
mordu). Claim absent = échec (disparition = régression).
|
||||
|
||||
**5 morsures vérifiées** (working tree byte-restauré après chacune via
|
||||
`git checkout -- <chemin précis>`, JAMAIS `git checkout .` / `git clean`) :
|
||||
1. README label `PASS_WITH_OPEN_ITEMS`→`PASS` → ✗ (c) « Verdict courant = PASS MAIS
|
||||
artefact PASS_WITH_OPEN_ITEMS » ;
|
||||
2. README règle l.39 `PASS_WITH_OPEN_ITEMS`→`PASS_OPEN` → ✗ (d) « codomaine
|
||||
[FAIL, PASS, PASS_OPEN] ≠ [FAIL, PASS, PASS_WITH_OPEN_ITEMS] » ;
|
||||
3. `audit_report.verdict`→`PASS` (à_confirmer reste 4) → ✗ (a) « verdict FORCÉ,
|
||||
incohérent — viole #6 » **+** cascade ✗ (b) + ✗ (c) (3 fails : l'honnêteté est
|
||||
la morsure la plus forte) ;
|
||||
4. `MANIFEST.verdict`→`PASS` → ✗ (b) « MANIFEST PASS MAIS audit_report
|
||||
PASS_WITH_OPEN_ITEMS (désynchronisés) » ;
|
||||
5. README label supprimé (l.49) → ✗ (c) « Verdict courant INTROUVABLE ».
|
||||
Restauré = green : (a)(b)(c)(d) tous ✓.
|
||||
|
||||
- `ci/README.md` : la sous-clause « audit 5D » de la row `check-readme-claims`
|
||||
étendue de l'IDENTITÉ du VERDICT GLOBAL (label + honnêteté interne + croisé
|
||||
MANIFEST + codomaine de la règle documentée).
|
||||
- **7 gates re-verts** : `guard_constraints` / `validate_json` / `check_docs` /
|
||||
`check_artifacts` / `check_regression` / `check_ci_integrity` /
|
||||
`check_readme_claims` (tous rc=0).
|
||||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||||
édition **hors** `05_deliverables_mvp/*/out` ⇒ 0 dérive d'artefact).
|
||||
- **Auto-score 4Big** : 96/100.
|
||||
|
||||
## Session `20260801_210434` · Buffer S8 · Domaine CRM/commissions : l'**IDENTITÉ du CHAMP DEVISE** — la clause `devise_field` = le champ `devise` (`Select` **USD/DOP** · #10) du DocType Dossier Vente, transcrite **en prose** dans la §« Cross-cohérence » (`crm/commissions/README.md:54`) — était **HORS de tout gate**. Les trois blocs commissions déjà en place gatent les états soumis / brouillons exclus, les champs de base Currency, l'identité des rôles payés (portail `ventes`) et la promesse anti-taux #6 — mais **aucun** ne touchait ce couple champ↔devises (l'**invariant CLI #8** du générateur).
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -2272,6 +2272,94 @@ 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")
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Audit 5D · IDENTITÉ du VERDICT GLOBAL — le LABEL de conclusion (`PASS` /
|
||||
# `PASS_WITH_OPEN_ITEMS` / `FAIL`), pas seulement sa ventilation chiffrée.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le bloc de ventilation ci-dessus recompute le TRIPLET chiffré (pass/fail/à
|
||||
# confirmer) mais reste AVEUGLE au LABEL de verdict lui-même — la HEADLINE de tout
|
||||
# l'audit. Ce label est data-derived (out/audit_report.json[verdict] == out/
|
||||
# MANIFEST.json[verdict], byte-gatés par check_artifacts ⇒ faisant autorité),
|
||||
# recalculé par le générateur (qalib/builder.py) via la règle EXACTE : `FAIL` si
|
||||
# ≥1 FAIL · sinon `PASS_WITH_OPEN_ITEMS` si ≥1 A_CONFIRMER · sinon `PASS`. Le README
|
||||
# le transcrit À LA MAIN à DEUX endroits — la RÈGLE (« Verdict global : `FAIL` si …
|
||||
# sinon `PASS_WITH_OPEN_ITEMS` … sinon `PASS` ») ET le VERDICT COURANT
|
||||
# (« ## Verdict courant \n `PASS_WITH_OPEN_ITEMS` — **13 PASS · 0 FAIL · 4 à
|
||||
# confirmer** »). AUCUN gate ne le vérifiait : le triplet peut coller à l'artefact
|
||||
# pendant que le LABEL courant ment (écrire `PASS` alors que 4 open items
|
||||
# subsistent = violation #6 « ne jamais forcer un PASS », le CŒUR même du livrable —
|
||||
# l'audit prétend propre un dossier avec 4 params réglementaires non confirmés) ;
|
||||
# ou la RÈGLE documentée dérive du codomaine réel du générateur (un label renommé
|
||||
# dans builder.py, la prose périmée). check_artifacts ne prouve QUE
|
||||
# audit_report==build (byte) ; aucune suite tests/ (FONCTIONS, pas la prose du
|
||||
# README) n'attrape ces deux dérives. On MIROITE la règle du générateur et on
|
||||
# exige : (a) HONNÊTETÉ interne — audit_report.verdict == verdict recalculé du
|
||||
# triplet (l'audit ne peut afficher un verdict incohérent avec ses propres
|
||||
# chiffres) ; (b) CROISÉ — MANIFEST.verdict == audit_report.verdict ; (c) le LABEL
|
||||
# « Verdict courant » du README == audit_report.verdict ; (d) la RÈGLE du README
|
||||
# énumère EXACTEMENT le codomaine {FAIL, PASS_WITH_OPEN_ITEMS, PASS} (un label
|
||||
# renommé côté code sans mise à jour de la règle est mordu). Un claim absent échoue
|
||||
# AUSSI (disparition = régression).
|
||||
# ============================================================================
|
||||
A5V_DOMAIN = {"FAIL", "PASS_WITH_OPEN_ITEMS", "PASS"}
|
||||
def _a5_verdict_from_totals(t):
|
||||
# miroir EXACT de qalib/builder.py : FAIL prime, puis open items, sinon PASS
|
||||
if t["fail"]:
|
||||
return "FAIL"
|
||||
if t["a_confirmer"]:
|
||||
return "PASS_WITH_OPEN_ITEMS"
|
||||
return "PASS"
|
||||
try:
|
||||
a5v_rep = load("qa/audit_5d/out/audit_report.json")
|
||||
a5v_verdict = a5v_rep["verdict"]
|
||||
a5v_tot = a5v_rep["totals"]
|
||||
a5v_man_verdict = load("qa/audit_5d/out/MANIFEST.json")["verdict"]
|
||||
except (OSError, KeyError, ValueError, TypeError) as e:
|
||||
bad(f"Audit 5D · verdict — artefact illisible/inattendu : {e}"); a5v_verdict = None
|
||||
if a5v_verdict is not None:
|
||||
# (a) honnêteté interne : le verdict de l'artefact découle de ses propres totals
|
||||
a5v_exp = _a5_verdict_from_totals(a5v_tot)
|
||||
if a5v_verdict != a5v_exp:
|
||||
bad(f"Audit 5D · verdict — audit_report dit « {a5v_verdict} » MAIS ses totals "
|
||||
f"(fail={a5v_tot['fail']} · à_confirmer={a5v_tot['a_confirmer']}) imposent "
|
||||
f"« {a5v_exp} » (verdict FORCÉ, incohérent — viole #6)")
|
||||
else:
|
||||
good(f"Audit 5D · verdict — audit_report « {a5v_verdict} » == recalcul du triplet "
|
||||
f"(fail={a5v_tot['fail']} · à_confirmer={a5v_tot['a_confirmer']})")
|
||||
# (b) croisé artefacts : MANIFEST == rapport
|
||||
if a5v_man_verdict != a5v_verdict:
|
||||
bad(f"Audit 5D · verdict — MANIFEST dit « {a5v_man_verdict} » MAIS audit_report "
|
||||
f"dit « {a5v_verdict} » (artefacts désynchronisés)")
|
||||
else:
|
||||
good(f"Audit 5D · verdict — MANIFEST « {a5v_man_verdict} » == audit_report")
|
||||
a5v_rd = read_norm(A5D_RD)
|
||||
if a5v_rd is not None:
|
||||
# (c) LABEL « Verdict courant » du README == verdict de l'artefact
|
||||
m = re.search(r"## Verdict courant\s+`([A-Z_]+)`\s*—\s*\*\*\d+ PASS", a5v_rd)
|
||||
if m is None:
|
||||
bad(f"Audit 5D · {A5D_RD} — label « Verdict courant » INTROUVABLE "
|
||||
f"(attendu « {a5v_verdict} »)")
|
||||
elif m.group(1) == a5v_verdict:
|
||||
good(f"Audit 5D · {A5D_RD} — « Verdict courant » = « {m.group(1)} » == artefact")
|
||||
else:
|
||||
bad(f"Audit 5D · {A5D_RD} — « Verdict courant » = « {m.group(1)} » MAIS "
|
||||
f"artefact dit « {a5v_verdict} » → régénérer le README")
|
||||
# (d) la RÈGLE documentée énumère EXACTEMENT le codomaine du générateur
|
||||
seg = re.search(r"Verdict global\s*:\s*(.+?)(?: > | ## )", a5v_rd)
|
||||
if seg is None:
|
||||
bad(f"Audit 5D · {A5D_RD} — règle « Verdict global : … » INTROUVABLE "
|
||||
f"(codomaine {sorted(A5V_DOMAIN)} non vérifiable)")
|
||||
else:
|
||||
labels = set(re.findall(r"`([A-Z_]+)`", seg.group(1)))
|
||||
if labels == A5V_DOMAIN:
|
||||
good(f"Audit 5D · {A5D_RD} — règle « Verdict global » énumère le codomaine "
|
||||
f"{sorted(A5V_DOMAIN)} == générateur")
|
||||
else:
|
||||
miss = sorted(A5V_DOMAIN - labels); extra = sorted(labels - A5V_DOMAIN)
|
||||
bad(f"Audit 5D · {A5D_RD} — règle « Verdict global » énumère {sorted(labels)} "
|
||||
f"≠ codomaine générateur {sorted(A5V_DOMAIN)} "
|
||||
f"(manquants={miss or '—'} en_trop={extra or '—'}) → aligner la règle")
|
||||
|
||||
# ============================================================================
|
||||
# Audit 5D (2e surface du MÊME README) · ÉNUMÉRATION des open items du « Verdict
|
||||
# courant » (control → dimension → propriétaire) — même classe de « vert trompeur ».
|
||||
|
||||
Reference in New Issue
Block a user