From abc9b62214110515713ea933caae9b5df6f3969f Mon Sep 17 00:00:00 2001 From: Claude Code DTP Worker Date: Fri, 31 Jul 2026 14:08:51 +0000 Subject: [PATCH] =?UTF-8?q?[DTP-Worker]=20Sprint=208=20=C2=B7=20buffer=20L?= =?UTF-8?q?75=20=C2=B7=20Domaine=20QA/Audit=204Big=20(2e=20surface)=20:=20?= =?UTF-8?q?la=20CARTE=20DE=20RENORMALISATION=20PAR=20ARCH=C3=89TYPE=20de?= =?UTF-8?q?=20l'auditeur=20(=C2=AB=20data=5Froom=20(sans=20HANDOFF)=20?= =?UTF-8?q?=C2=B7=20parser=20(sans=20CONTRAT=20=E2=80=A6=20ni=20HANDOFF)?= =?UTF-8?q?=20=C2=B7=20contract=20(sans=20CLI=20ni=20HANDOFF)=20=C2=BB)=20?= =?UTF-8?q?=C3=A9tait=20transcrite=20=C3=80=20LA=20MAIN=20dans=20le=20READ?= =?UTF-8?q?ME=20du=20module=20sans=20AUCUN=20gate.=20La=20session=20pr?= =?UTF-8?q?=C3=A9c=C3=A9dente=20a=20gat=C3=A9=20le=20BAR=C3=88ME=20(nombre?= =?UTF-8?q?=20de=20crit=C3=A8res=20+=20poids=20par=20crit=C3=A8re=20de=20l?= =?UTF-8?q?a=20table=20+=20=C2=AB=20generator=20(N=20crit=C3=A8res)=20?= =?UTF-8?q?=C2=BB,=20recomput=C3=A9s=20de=20quality=5Freport.criteria)=20m?= =?UTF-8?q?ais=20PAS=20les=20exclusions=20des=20trois=20autres=20arch?= =?UTF-8?q?=C3=A9types=20=E2=80=94=20surface=20data-derived=20distincte=20?= =?UTF-8?q?du=20M=C3=8AME=20README.=20Cette=20carte=20d=C3=A9rive=20de=20q?= =?UTF-8?q?uality=5Freport.json.modules=20(byte-gat=C3=A9=20par=20check=5F?= =?UTF-8?q?artifacts)=20:=20pour=20un=20arch=C3=A9type,=20l'ensemble=20des?= =?UTF-8?q?=20crit=C3=A8res=20APPLICABLES=20=3D=20{check.criterion}=20de?= =?UTF-8?q?=20ses=20modules=20(les=20non-applicables=20sont=20ABSENTS=20de?= =?UTF-8?q?s=20checks)=20=E2=87=92=20EXCLUS=20=3D=20ordre=20du=20bar=C3=A8?= =?UTF-8?q?me=20=E2=88=92=20applicables.=20Changer=20la=20r=C3=A8gle=20de?= =?UTF-8?q?=20renormalisation=20d'un=20arch=C3=A9type=20(ex.=20data=5Froom?= =?UTF-8?q?=20exclut=20aussi=20CLI)=20ferait=20d=C3=A9river=20la=20prose?= =?UTF-8?q?=20en=20silence=20pendant=20que=20l'artefact=20dit=20autre=20ch?= =?UTF-8?q?ose=20=E2=80=94=20=C2=AB=20vert=20trompeur=20=C2=BB=20qu'aucune?= =?UTF-8?q?=20suite=20tests/=20(qui=20teste=20des=20FONCTIONS,=20pas=20la?= =?UTF-8?q?=20prose)=20n'attrape=20=E2=86=92=20nouveau=20bloc=20(6)=20dans?= =?UTF-8?q?=20check=5Freadme=5Fclaims=20recomputant=20PAR=20arch=C3=A9type?= =?UTF-8?q?=20l'ensemble=20des=20crit=C3=A8res=20exclus=20depuis=20les=20c?= =?UTF-8?q?hecks=20de=20quality=5Freport.modules=20(z=C3=A9ro=20duplicatio?= =?UTF-8?q?n=20du=20mod=C3=A8le=20de=20renormalisation=20#6)=20et=20exigea?= =?UTF-8?q?nt=20que=20la=20parenth=C3=A8se=20du=20README=20l'=C3=A9num?= =?UTF-8?q?=C3=A8re=20EXACTEMENT.=20Contr=C3=B4le=20par=20ensemble=20(mauv?= =?UTF-8?q?ais=20crit=C3=A8re,=20sous-ensemble=20ET=20sur-ensemble=20mordu?= =?UTF-8?q?s),=20pas=20seulement=20pr=C3=A9sence.=20Bonus=20d'uniformit?= =?UTF-8?q?=C3=A9=20:=20tous=20les=20modules=20d'un=20m=C3=AAme=20arch?= =?UTF-8?q?=C3=A9type=20portent=20le=20M=C3=8AME=20jeu=20applicable=20(?= =?UTF-8?q?=C2=AB=201=20arch=C3=A9type=20=E2=86=92=201=20jeu=20de=20crit?= =?UTF-8?q?=C3=A8res=20=C2=BB,=20base=20m=C3=AAme=20de=20la=20carte).=20Un?= =?UTF-8?q?=20claim=20absent=20=C3=A9choue=20AUSSI=20(3=20morsures=20v?= =?UTF-8?q?=C3=A9rifi=C3=A9es=20:=20data=5Froom=20=C2=AB=20sans=20HANDOFF?= =?UTF-8?q?=20=C2=BB=E2=86=92=C2=AB=20sans=20CLI=20=C2=BB=20capt=C3=A9=20?= =?UTF-8?q?=C2=B7=20parser=20exclusion=20HANDOFF=20retir=C3=A9e=20=3D=20so?= =?UTF-8?q?us-ensemble=20capt=C3=A9=20=C2=B7=20=C3=A9num=C3=A9ration=20con?= =?UTF-8?q?tract=20disparue=20=3D=20red=20;=20restaur=C3=A9=20=3D=20green?= =?UTF-8?q?=20:=204=20arch=C3=A9types=20uniformes=20=C2=B7=20data=5Froom/p?= =?UTF-8?q?arser/contract=20=3D=3D=20r=C3=A9f=C3=A9rentiel).=20=C3=89tat?= =?UTF-8?q?=20courant=20:=20aucune=20exclusion=20p=C3=A9rim=C3=A9e=20(anti?= =?UTF-8?q?-invention=20#6,=20rien=20=C3=A0=20r=C3=A9=C3=A9crire)=20?= =?UTF-8?q?=E2=80=94=20le=20d=C3=A9faut=20est=20la=20surface=20ungated.=20?= =?UTF-8?q?ci/README.md=20(table=20+=20d=C3=A9tail)=20mis=20=C3=A0=20jour?= =?UTF-8?q?=20=C2=B7=207=20gates=20re-verts.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- 05_activity_log/2026-07-31.md | 58 +++++++++++++++++++++++++++++++++++ ci/README.md | 19 +++++++++++- ci/check_readme_claims.sh | 51 ++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 1 deletion(-) diff --git a/05_activity_log/2026-07-31.md b/05_activity_log/2026-07-31.md index 39a148b..8b40cf8 100644 --- a/05_activity_log/2026-07-31.md +++ b/05_activity_log/2026-07-31.md @@ -1,5 +1,63 @@ # Activity Log · 2026-07-31 · Claude Code DTP +## Session `20260731_140101` · Buffer S8 · Domaine QA/Audit 4Big (2e surface) : la **carte de renormalisation PAR ARCHÉTYPE** de l'auditeur (« `data_room` (sans HANDOFF) · `parser` (sans CONTRAT … ni HANDOFF) · `contract` (sans CLI ni HANDOFF) ») était transcrite À LA MAIN dans le README du module — la session précédente a gaté le barème (critères + poids + `generator (N critères)`) mais PAS les exclusions des trois autres archétypes. + +**Tâche** : **Sprint 8 · buffer L75** (DevOps CI/CD · QA). Roadmap fonctionnellement +close ; poursuite de la série anti-dérive (CLAUDE.md #6). La session `133057` a gaté le +**barème** de l'auditeur (nombre de critères + poids par critère + `generator (5 +critères)`). Restait, dans le **même README**, une surface data-derived distincte : la +**carte de renormalisation par archétype**, qui dit quels critères CHAQUE archétype +**exclut** du dénominateur. + +**Dérive silencieuse fermée** : +- `05_deliverables_mvp/qa/audit_4big/README.md:32-34` énumère + « `generator` (5 critères) · `data_room` (**sans HANDOFF**) · `parser` (**sans + CONTRAT** local ni **HANDOFF**) · `contract` (**sans CLI** ni **HANDOFF**) ». +- Cette carte est **DATA-DERIVED** : pour un archétype, l'ensemble des critères + **applicables** = `{check.criterion}` de ses modules dans + `out/quality_report.json` (byte-gaté par `check_artifacts`) — les critères + non-applicables sont **absents** des `checks`. Donc **exclus** = ordre du barème − + applicables. +- Le bloc barème de la session précédente ne recompute QUE `generator` (« 5 critères », + zéro exclusion). Les **exclusions** de `data_room`/`parser`/`contract` n'étaient + recomputées par AUCUN gate : changer la règle de renormalisation d'un archétype + (ex. `data_room` exclut aussi `CLI`) ferait dériver la prose en silence pendant que + `quality_report` dit autre chose — « vert trompeur » qu'aucune suite `tests/` (qui + teste des FONCTIONS, pas la prose) n'attrape. +- **État courant** : **aucune exclusion périmée** — les 3 cartes recoupent l'artefact + exactement (anti-invention #6 : rien à réécrire). Le défaut est la **surface ungated**. + +**Nouveau bloc (6) dans `ci/check_readme_claims.sh`** (section barème `qa/audit_4big`) : +recompute **par archétype** l'ensemble des critères exclus depuis les `checks` de +`quality_report.modules` (zéro duplication du modèle de renormalisation du générateur · +#6) et exige que la parenthèse du README l'énumère **exactement** (mauvais critère, +sous-ensemble, sur-ensemble → tous mordus). Bonus d'uniformité : tous les modules d'un +même archétype portent le **même** jeu applicable (« 1 archétype → 1 jeu de critères », +base même de la carte — mord un référentiel où un module d'un archétype divergerait des +autres). Un claim (énumération) absent échoue AUSSI (traçabilité). + +### Preuve (3 morsures vérifiées + restauration verte) + +| Injection | Résultat | +|---|---| +| `data_room` « sans HANDOFF » → « sans CLI » (mauvais critère exclu) | ✗ exclut `[CLI]` MAIS référentiel `[HANDOFF]` · exit 1 | +| `parser` exclusion `HANDOFF` retirée (sous-ensemble) | ✗ exclut `[CONTRAT]` MAIS référentiel `[CONTRAT, HANDOFF]` · exit 1 | +| énumération `contract` supprimée (claim disparu) | ✗ énumération `contract` INTROUVABLE · exit 1 | +| restauré | ✓ 4 archétypes uniformes · `data_room`/`parser`/`contract` == référentiel · exit 0 | + +- **`ci/README.md`** — surface ajoutée à la table récap du pipeline + paragraphe + descriptif (classe « carte de renormalisation par archétype 4Big »). + +Suite CI complète re-verte (7 gates) : `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_133057` · Buffer S8 · Domaine QA/Audit 4Big : le **barème de notation** de l'auditeur (« **5 critères 4Big déterministes** » + la table `Critère | Poids` + l'archétype « `generator` (5 critères) ») était transcrit À LA MAIN dans le README du module sans AUCUN gate — le bloc racine ne gatait que sa ligne « Résultat courant » (verdict/modules), jamais le référentiel de scoring lui-même. **Tâche** : **Sprint 8 · buffer L75** (DevOps CI/CD · QA). Roadmap fonctionnellement diff --git a/ci/README.md b/ci/README.md index 1d1b06e..1369397 100644 --- a/ci/README.md +++ b/ci/README.md @@ -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) **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 | +| `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`) **et** de la carte de renormalisation par archétype de l'auditeur 4Big (critères EXCLUS de `data_room`/`parser`/`contract`, recomputés des `checks` par archétype de `quality_report.modules`) == 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 @@ -311,6 +311,23 @@ le contrôle **par critère**, pas seulement de la somme. 4 morsures vérifiées prose `5→6` (poids intacts) · dérive poids `TESTS 25→30` (compte intact) · dérive `generator (5→4)` · claim prose disparu ; restauré = vert. +Une **autre surface** du même README est la carte de **renormalisation par +archétype** : « `generator` (5 critères) · `data_room` (**sans HANDOFF**) · +`parser` (**sans CONTRAT** local ni **HANDOFF**) · `contract` (**sans CLI** ni +**HANDOFF**) ». Le bloc barème ne recomputait QUE `generator` ; les **exclusions** +des trois autres archétypes n'étaient recomputées par AUCUN gate. Or elles sont +DATA-DERIVED : pour un archétype, l'ensemble des critères **applicables** = +`{check.criterion}` de ses modules dans `quality_report.json` (les non-applicables +sont **absents** des `checks`) ⇒ **exclus** = ordre du barème − applicables. Changer +la règle de renormalisation d'un archétype (ex. `data_room` exclut aussi `CLI`) +ferait dériver cette prose en silence. On recompute donc, PAR archétype, l'ensemble +des critères exclus et on exige que la parenthèse du README l'énumère **exactement**. +Bonus d'uniformité : tous les modules d'un même archétype portent le **même** jeu +applicable (« 1 archétype → 1 jeu de critères », base même de la carte). 3 morsures +vérifiées : `data_room` « sans HANDOFF »→« sans CLI » (mauvais critère) · `parser` +exclusion `HANDOFF` retirée (sous-ensemble) · énumération `contract` supprimée ; +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. diff --git a/ci/check_readme_claims.sh b/ci/check_readme_claims.sh index 8889937..575dc52 100755 --- a/ci/check_readme_claims.sh +++ b/ci/check_readme_claims.sh @@ -320,6 +320,12 @@ else: # 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é). +# Bloc (6) : la carte de RENORMALISATION PAR ARCHÉTYPE (« data_room sans HANDOFF · +# parser sans CONTRAT ni HANDOFF · contract sans CLI ni HANDOFF ») est elle aussi +# data-derived — critères applicables d'un archétype = {check.criterion} de ses +# modules ⇒ exclus = barème − applicables. Recomputés par archétype, comparés à la +# parenthèse du README (exclusions des 3 archétypes non-generator, jamais gatées +# avant), + uniformité « 1 archétype → 1 jeu ». # ============================================================================ try: qr_crit = load("qa/audit_4big/out/quality_report.json") @@ -378,6 +384,51 @@ if criteria is not None and a4_txt: else: good(f"README audit_4big · {len(gen)} module(s) generator portent {n_crit} " f"checks (« generator = tous les critères » vérifié)") + # 6) carte « archétype → critères EXCLUS » (renormalisation) : le README énumère + # data_room « sans HANDOFF », parser « sans CONTRAT … ni HANDOFF », contract + # « sans CLI ni HANDOFF ». Cette carte est DATA-DERIVED : pour un archétype, + # l'ensemble des critères APPLICABLES = {check.criterion} de ses modules (les + # non-applicables sont ABSENTS des checks) ⇒ EXCLUS = ordre du barème − appl. + # Le bloc (3) ne recompute QUE generator (5 critères) ; les exclusions des + # trois autres archétypes n'étaient recomputées par AUCUN gate. Changer la + # règle de renormalisation d'un archétype (ex. data_room exclut aussi CLI) + # ferait dériver cette prose en silence pendant que quality_report dit autre + # chose. On recompute par archétype + on exige que la parenthèse du README + # énumère EXACTEMENT cet ensemble. Uniformité en bonus : tous les modules + # d'un même archétype portent le MÊME ensemble applicable (sinon la carte + # « 1 archétype → 1 jeu de critères » n'a pas de sens). + crit_ids = [c["id"] for c in criteria] + crit_set = set(crit_ids) + by_arch, uni_bad = {}, [] + for m in qr_crit["modules"]: + a = m.get("archetype") + appl = frozenset(ck["criterion"] for ck in m.get("checks", [])) + if a in by_arch and by_arch[a] != appl: + uni_bad.append(m["id"]) + else: + by_arch.setdefault(a, appl) + if uni_bad: + bad(f"README audit_4big · archétypes NON uniformes (modules aux critères " + f"applicables divergents) : {uni_bad} → renormalisation incohérente") + else: + good(f"README audit_4big · {len(by_arch)} archétype(s) à critères applicables " + f"uniformes (« 1 archétype → 1 jeu » vérifié)") + for a in sorted(by_arch): + if a == "generator": + continue # traité en (3) : « generator (N critères) », zéro exclusion + exp = [c for c in crit_ids if c not in by_arch[a]] # ordre du barème, stable + ma = re.search(rf"`{re.escape(a)}` \(([^)]*)\)", a4_txt) + if ma is None: + bad(f"README audit_4big · archétype `{a}` — énumération INTROUVABLE dans " + f"{A4} (attendu « sans {' ni '.join(exp)} »)") + continue + got = set(re.findall(r"[A-Z]{2,}", ma.group(1))) & crit_set + if got == set(exp): + good(f"README audit_4big · archétype `{a}` — exclus {sorted(got)} == " + f"référentiel ({exp})") + else: + 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") # ============================================================================ # Fiches agents · comptes de tests PAR SUITE (colonne « Tests » des tables) —