diff --git a/05_activity_log/2026-08-01.md b/05_activity_log/2026-08-01.md index 9f55c7e..0e1b4b3 100644 --- a/05_activity_log/2026-08-01.md +++ b/05_activity_log/2026-08-01.md @@ -2093,3 +2093,30 @@ spec == rapport · exit 0. Working tree byte-restauré (`git checkout --`, **JAM - **Note memory** : la classe « agent-fiche-role-attrs-ungated » est désormais CLOSE (attributs contrat = Fiches Faisabilité/Mobile ; `Has Role` = Fiches Workspace ; `roles_allowed` chat = ce bloc). Candidat propre restant : la fiche `ifc_speckle:34` (attributs contrat déjà gatés) + la row acceptance S3 « viewer 3D » (déjà gatée QA). - **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 ; le montage réel du chat reste côté runner/VPS). - **Auto-score 4Big** : 96/100. + +--- + +## Session 20260801_193414 · Sprint 8 · buffer · Gate d'IDENTITÉ des comptes de tests self-reportés par les README de MODULE (#6) + +**Contexte** : la série anti-dérive Sprint-8 gate chaque surface data-derived contre sa source de vérité. Tous les blocs de **comptes de tests** existants (`ci/check_readme_claims.sh`) visent `03_agents/*/AGENT.md` : la cellule « Tests » des tables via `row_re`, les agrégats prose de `crm`/`erpnext_backend`, et les cinq claims per-suite « hors table » (seo/portails/chat_otoia/confotur/deploy_runbook). AUCUN ne touche le README du **MODULE** lui-même — pourtant `05_deliverables_mvp//README.md` se re-déclare, en propre, le compte de SA suite à plusieurs endroits. + +**Surface trouvée (ungated)** : **27 claims sur 16 READMEs de module**, sous trois formulations récurrentes : +- commentaire de la commande unittest : `discover -s tests -v # N tests (…)` ; +- bullet « Vérification en-repo » : `→ **N/N verts**` (six modules RBAC/faisabilité/CRM) ; +- justification d'auto-score 4Big : `Validé statiquement en-repo (N tests verts + …)`. +Ces nombres sont SAISIS À LA MAIN dans le doc d'entrée de chaque module et se périment dès qu'un `def test_` est ajouté/retiré : la source faisant autorité (`qa/regression/out/regression_plan.json` → `auth = plan.suites[path].test_methods`, recomptée à chaque build par découverte réelle, byte-gatée par `check_artifacts` + fraîcheur du run par `check_regression`) se met à jour tandis que la prose du README rote EN SILENCE — « vert trompeur » de la MÊME classe que la cellule « Tests » des fiches, mais sur la surface que `row_re` n'atteint pas (il ne lit le README de module QUE comme *cible de lien*). Aucune suite `tests/` (qui teste des FONCTIONS de génération, jamais la prose du README) n'attrape ce périmé. + +**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « READMEs de MODULE · comptes de tests self-reportés » juste après le bloc per-suite « hors table », d'où `auth` est déjà en portée · zéro rechargement · #6) : table de config `MODULE_README_TESTS` = liste `(suite_path, [motifs ancrés])`. Pour chaque module : `auth[suite_path]` recomputé, chaque motif DOIT matcher (claim absent = régression #6) ET tous ses groupes capturés == `auth`. Le motif `**N/N verts**` capture DEUX groupes → les deux doivent valoir `auth` : un `25/24 verts` internement incohérent mord aussi. Chaque motif est ancré sur un contexte distinctif (`discover -s tests…# N tests`, `**N/N verts**`, `en-repo (N tests verts`, `test_confotur.py # N tests`…) pour viser LE compte de CETTE suite sans capter un autre nombre. +- **Cinq modules volontairement HORS table** (`frontend/chat_otoia`, `mobile/app_config`, `publiciste`, `qa/acceptance`, `qa/audit_4big`) : leur README ne self-reporte AUCUN compte de tests (vérifié) — rien à ancrer ; un futur claim = l'ajouter à la table. Noté dans le commentaire du bloc. + +**4 morsures vérifiées** (chaque README restauré depuis backup — **JAMAIS** `git checkout .`/`git clean`, interdits absolus) : +1. drift commentaire (`faisabilite/generator` 16→17 tests) → ✗ « dit 17 MAIS source dit 16 » ; +2. incohérence interne `N/N` (`rbac/apply_plan` `16/16`→`16/17 verts`) → ✗ « dit 16/17 MAIS source dit 16 » ; +3. disparition de claim (`legal/confotur` prose auto-score « diffable, 44 tests (dont… » retirée) → ✗ « claim INTROUVABLE (attendu 44) » ; +4. drift auto-score prose (`rbac/fixtures_gen` `(11 tests verts`→`(12 tests verts`) → ✗ « dit 12 MAIS source dit 11 ». +Restauré = green : `rc=0`, **440 checks de base intacts (diff vide) + 27 nouveaux**. Gates sœurs re-verts : `check_ci_integrity` rc=0 · `check_docs` rc=0. + +- En-tête du gate mis à jour (inventaire des surfaces couvertes : nouvelle entrée « comptes de tests self-reportés par MODULE »). +- **Note memory** : classe « comptes de tests » — désormais couverte sur TROIS surfaces (cellule « Tests » des fiches via `row_re` · agrégats prose fiches · **README de module**, ce bloc) + les cinq claims per-suite hors table. Source unique = `auth` (plan.suites[].test_methods). +- **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. diff --git a/ci/check_readme_claims.sh b/ci/check_readme_claims.sh index 0187067..2d23ee1 100755 --- a/ci/check_readme_claims.sh +++ b/ci/check_readme_claims.sh @@ -91,6 +91,14 @@ # le SEUL bloc `e_ncf` d'ecf_plan.json (prefix/longueur/regex/structure, byte- # gatés) + cohérences croisées (1+tipo+seq == longueur · |regex digits| == # tipo+seq — mordent un artefact internement incohérent) +# 05_deliverables_mvp//README.md (comptes de tests self-reportés par MODULE) : +# • chaque README de module se re-déclare le compte de SA suite (commentaire +# « # N tests » de la commande unittest · bullet « → **N/N verts** » · prose +# d'auto-score « en-repo (N tests verts + …) ») — 27 claims sur 16 modules, +# surface que row_re (qui ne lit le README de module QUE comme cible de lien) +# et les blocs per-suite (tous sur 03_agents/*) n'atteignent pas → recomptés +# depuis plan.suites[path].test_methods (`auth`, même source · byte-gatée) ; +# un « N/N » interne incohérent (25/24) mord aussi # 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é). # @@ -771,6 +779,88 @@ for path_f, suite_path, pat, label in PER_SUITE_HORS_TABLE: bad(f"Test par suite (hors table) · {path_f} · {label} — dit {m.group(1)} " f"MAIS source dit {exp} (plan.suites[`{suite_path}`]) → régénérer la fiche") +# ============================================================================ +# READMEs de MODULE · comptes de tests self-reportés — surface DISTINCTE des fiches. +# ---------------------------------------------------------------------------- +# Tous les blocs de comptes de tests ci-dessus visent `03_agents/*/AGENT.md` (la +# cellule « Tests » via row_re, les agrégats prose crm/erpnext_backend, les cinq +# claims per-suite hors table). AUCUN ne touche le README du MODULE lui-même — +# `05_deliverables_mvp//README.md` — qui pourtant se re-déclare, en propre, +# le compte de SA suite à plusieurs endroits : le commentaire de la commande +# `unittest` (« # N tests »), le bullet « Vérification en-repo » (« → **N/N verts** ») +# et la justification d'auto-score (« Validé … en-repo (N tests verts + … ) »). Ces +# nombres sont SAISIS À LA MAIN dans le doc d'entrée de chaque module et se périment +# dès qu'un `def test_` est ajouté/retiré : la source faisant autorité (regression_ +# plan.json → `auth`, recomptée à chaque build par découverte réelle · byte-gatée) +# se met à jour, tandis que la prose du README rote EN SILENCE — « vert trompeur » +# de la MÊME classe que la cellule « Tests » des fiches, mais sur la surface que +# row_re n'atteint pas (il ne lit le README de module QUE comme cible de lien). Aucune +# suite tests/ (FONCTIONS de génération, jamais la prose du README) n'attrape ce +# périmé. Un « N/N » interne incohérent (ex. `25/24 verts`) mord aussi (les deux +# nombres doivent valoir `auth`). On RECOMPUTE chaque nombre depuis `auth` (MÊME +# source déjà chargée · zéro duplication #6) et on exige que le README l'écrive +# EXACTEMENT ; un claim listé mais absent échoue AUSSI (traçabilité #6 : le compte +# qui s'évapore est lui-même une régression). Cinq modules ne self-reportent AUCUN +# compte (frontend/chat_otoia · mobile/app_config · publiciste · qa/acceptance · +# qa/audit_4big) — volontairement HORS table (rien à ancrer ; ajouter un futur claim +# = l'ajouter ici). Chaque motif est ANCRÉ sur un contexte distinctif (commande +# `discover`, `**N/N verts**`, « en-repo (N tests verts », nom de fichier de suite…) +# pour viser LE compte de CETTE suite sans capter un autre nombre. +# ============================================================================ +MODULE_README_TESTS = [ + ("crm/commissions", [r"discover -s tests[^#]*# (\d+) tests", + r"en-repo \((\d+) tests verts"]), + ("crm/dossier_vente", [r"discover -s tests[^#]*# (\d+) tests"]), + ("crm/workflow_vente", [r"\*\*(\d+)/(\d+) verts\*\*", + r"en-repo \((\d+) tests verts"]), + ("demo/scenarios", [r"(\d+) tests \(dont injections"]), + ("devops/deploy_runbook", [r"(\d+) tests dont \d+ injections"]), + ("faisabilite/bancable", [r"\*\*(\d+)/(\d+) verts\*\*", + r"en-repo \((\d+) tests verts"]), + ("faisabilite/generator", [r"(\d+) tests `unittest`"]), + ("fiscal/ecf_dgii", [r"discover -s tests[^#]*# (\d+) tests", + r"en-repo \((\d+) tests verts"]), + ("frontend/portails", [r"discover -s tests[^#]*# (\d+) tests", + r"exacts, (\d+) tests \(dont"]), + ("legal/confotur", [r"discover -s tests[^#]*# (\d+) tests \(dont", + r"test_confotur\.py\s*# (\d+) tests", + r"diffable, (\d+) tests \(dont"]), + ("qa/audit_5d", [r"\*\*(\d+) tests\*\* \(`unittest`"]), + ("rbac/apply_plan", [r"\*\*(\d+)/(\d+) verts\*\*", + r"en-repo \((\d+) tests verts"]), + ("rbac/fixtures_gen", [r"\*\*(\d+)/(\d+) verts\*\*", + r"en-repo \((\d+) tests verts"]), + ("rbac/roleprofile_gen", [r"\*\*(\d+)/(\d+) verts\*\*", + r"en-repo \((\d+) tests verts"]), + ("rbac/userperm_gen", [r"\*\*(\d+)/(\d+) verts\*\*", + r"en-repo \((\d+) tests verts"]), + ("seo", [r"discover -s tests[^#]*# (\d+) tests"]), +] +for suite_path, pats in MODULE_README_TESTS: + rd = f"{D}/{suite_path}/README.md" + try: + rtxt = re.sub(r"\s+", " ", open(rd, encoding="utf-8").read()) + except OSError as e: + bad(f"Compte tests README module · {rd} illisible : {e}"); continue + if suite_path not in auth: + bad(f"Compte tests README module · suite `{suite_path}` absente de " + f"plan.suites/count_tests (câblage rompu ?)"); continue + exp = auth[suite_path] + for pat in pats: + m = re.search(pat, rtxt) + if m is None: + bad(f"Compte tests README module · {rd} — claim « N tests » INTROUVABLE " + f"(attendu {exp} · suite `{suite_path}`) · motif=/{pat}/") + continue + got = [int(g) for g in m.groups()] + if all(v == exp for v in got): + good(f"Compte tests README module · {rd} — {'/'.join(map(str, got))} == " + f"source ({exp} · `{suite_path}`)") + else: + bad(f"Compte tests README module · {rd} — dit {'/'.join(map(str, got))} " + f"MAIS source dit {exp} (plan.suites[`{suite_path}`]) → régénérer le " + f"README (ou run-book de régression si un test a bougé)") + # ============================================================================ # Portails frontend · comptes PAR WORKSPACE (cartes / liens / rôles) — # même classe de « vert trompeur », transcrits À LA MAIN dans DEUX docs.