diff --git a/03_agents/erpnext_backend/AGENT.md b/03_agents/erpnext_backend/AGENT.md index 5177f85..7181571 100644 --- a/03_agents/erpnext_backend/AGENT.md +++ b/03_agents/erpnext_backend/AGENT.md @@ -36,8 +36,9 @@ le VPS reçoit — jamais l'inverse. `rbac_50_roles.json` est le **référentiel de rôles de tout le repo** — le workflow vente, le barème commissions, le DocType Dossier Vente et le plan e-CF **résolvent** leurs rôles depuis ce fichier, jamais un nom Frappe en dur. Total backend **RBAC 60 -tests** (10 + 11 + 12 + 11 + 16) + **e-CF 39 tests**, tous gated dans le CI (repo : -**560 tests** au total). +tests** (10 + 11 + 12 + 11 + 16) + **e-CF 39 tests**, tous gated dans le CI (matrice +de régression du repo : **558 tests · 22 suites** · verdict `PASS`, source +`qa/regression/out/regression_run.json` — jamais compté à la main · #6). ## Hand-off reçus (à appliquer sur le VPS, dans l'ordre) - **CRM** → `crm/dossier_vente/out/` (DocType porteur) **AVANT** `crm/workflow_vente/out/` diff --git a/05_activity_log/2026-07-31.md b/05_activity_log/2026-07-31.md index 9a5c6a4..e437795 100644 --- a/05_activity_log/2026-07-31.md +++ b/05_activity_log/2026-07-31.md @@ -481,3 +481,60 @@ PASS** ; artefacts `out/` reproductibles à l'identique. runner Gitea toujours du ressort DevOps). **Auto-score 4Big** : 96/100. + +--- + +## Session `20260731_043004` · Buffer S8 · Chiffre périmé dans une fiche agent (vert-trompeur ungated) + extension du gate + +**Tâche** : **Sprint 8 · buffer L75 (« Regression tests exhaustifs »)** — roadmap +fonctionnellement close (22/22 modules gated · 558 tests · 7 gates statiques verts). +Recherche d'un **défaut réel** (chiffre inventé/périmé · CLAUDE.md #6) plutôt qu'un +correctif cosmétique. + +### Défaut trouvé — `03_agents/erpnext_backend/AGENT.md` : « repo : **560 tests** au total » + +- **Symptôme** : la ligne « source unique » situait les tests backend dans le repo + par un compte agrégé **saisi à la main** (« repo : 560 tests au total »). +- **Contradiction** : `560` ne correspond **à AUCUN** compte courant — + - matrice de régression faisant autorité (`qa/regression/out/regression_run.json`) : + **558 tests · 22 suites · PASS** ; + - repo-wide (méthodes `test_*` sur disque, 23 fichiers) : **584**. + `560` = ancien `534` (matrice d'alors) `+ 26` (harnais `qa/regression`, self-exclu + INV3) — **périmé en silence** au fil de 534 → 551 → 558. Même classe de « vert + trompeur » que la fiche QA (21/534) corrigée la session précédente, mais dans une + fiche agent qu'**aucun gate ne couvrait**. +- **Vérif ciblée (#1 analyser)** : recomputé **toutes** les autres bornes chiffrées + des 13 `AGENT.md` — `crm 81=(25+31+25)`, `RBAC 60=(10+16+11+11+12)`, `e-CF 39`, + `portails 19`, `chat 31`, `confotur 44`, `seo 36` : **toutes exactes**. Le `560` + était le **seul** nombre dérivé. + +### Fix (2 volets · corriger + garder) + +1. **`03_agents/erpnext_backend/AGENT.md`** : `560` → **« matrice de régression du + repo : 558 tests · 22 suites · verdict PASS, source + `qa/regression/out/regression_run.json` — jamais compté à la main · #6 »** (le + nombre pointe désormais vers l'artefact gaté, pas une saisie). +2. **`ci/check_readme_claims.sh`** : nouveau bloc qui **recalcule** tests+suites+ + verdict depuis `regression_run` (même source que la fiche QA) et exige l'égalité + avec ce que la fiche backend **écrit** ; un claim absent échoue aussi. Header du + gate mis à jour (liste des docs couverts). + +### Preuves + +- **Passe** : `Fiche Backend · … 558/22/PASS == regression_run` (✓). +- **Morsure** : `560` réinjecté ⇒ gate **rouge** (`dit 560/22/PASS MAIS regression_run + dit 558/22/PASS → régénérer la fiche`) ; restauré ⇒ vert. +- **Régression nulle** : édition d'un `AGENT.md` (doc) → **aucune dérive** d'artefact + `out/` (`check_artifacts` vert : `quality_report.json` inchangé). + +**Vérifs** : **7 gates** locaux verts (`guard_constraints` · `validate_json` · +`check_docs` · `check_artifacts` · `check_regression` · `check_ci_integrity` · +`check_readme_claims`) ; matrice **558/22 · PASS**. + +**Anti-invention (#6)** : rien inventé — le gate **régénère** la vérité (matrice +re-agrégée) au lieu de figer un compteur ; le chiffre de la fiche **découle** de +l'artefact. + +**Hors périmètre worker (VPS · #8)** : néant (docs + gate bash/stdlib en-repo). + +**Auto-score 4Big** : 96/100. diff --git a/ci/check_readme_claims.sh b/ci/check_readme_claims.sh index 3ada550..365db8e 100755 --- a/ci/check_readme_claims.sh +++ b/ci/check_readme_claims.sh @@ -29,6 +29,9 @@ # 03_agents/qa/AGENT.md (fiche QA · « Verdict agrégé courant ») : # • N suites · M tests · M passés · E échec · E erreur · verdict # → qa/regression run +# 03_agents/erpnext_backend/AGENT.md (« source unique ») : +# • N tests · M suites · verdict (matrice de régression du repo) +# → qa/regression run # 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é). # @@ -179,6 +182,39 @@ else: bad(f"Fiche QA · {QA} dit {'/'.join(mqa.groups())} MAIS regression_run dit " f"{'/'.join(agg)} ({qa_src}) → régénérer la fiche") +# ============================================================================ +# Fiche ERPNext Backend (03_agents/erpnext_backend/AGENT.md) · même classe. +# ---------------------------------------------------------------------------- +# Sa ligne « source unique » situait les tests backend dans le repo par un +# compte agrégé (« repo : 560 tests au total ») saisi à la main. Ce nombre s'est +# PÉRIMÉ en silence (matrice 534 → 551 → 558) : 560 ne correspondait plus ni à la +# matrice (558) ni au repo-wide (584 méthodes test_*). Aucun gate ne le couvrait. +# On le RECALCULE depuis la même matrice faisant autorité (regression_run) et on +# exige tests + suites + verdict — comme la fiche QA. +# ============================================================================ +BE = "03_agents/erpnext_backend/AGENT.md" +try: + be_txt = re.sub(r"\s+", " ", open(BE, encoding="utf-8").read()) +except OSError as e: + bad(f"Fiche Backend · {BE} illisible : {e}"); be_txt = "" + +be_exp = ( + str(sum(s["ran"] for s in suites)), # tests exécutés (matrice) + str(len(suites)), # suites + run["verdict"], # verdict +) +be_pat = (r"matrice\s+de régression du repo : \*\*(\d+) tests · (\d+) suites\*\* · " + r"verdict `(PASS|FAIL)`") +be_src = f"tests={be_exp[0]} suites={be_exp[1]} verdict={be_exp[2]}" +mbe = re.search(be_pat, be_txt) +if mbe is None: + bad(f"Fiche Backend · matrice repo — claim INTROUVABLE dans {BE} (attendu {be_src})") +elif mbe.groups() == be_exp: + good(f"Fiche Backend · matrice repo — {BE} {'/'.join(mbe.groups())} == regression_run ({be_src})") +else: + bad(f"Fiche Backend · {BE} dit {'/'.join(mbe.groups())} MAIS regression_run dit " + f"{'/'.join(be_exp)} ({be_src}) → régénérer la fiche") + sys.exit(1 if FAIL else 0) PY rc=$?