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) —