[DTP-Worker 20260801_193414] Sprint 8 · buffer · Gate d'IDENTITÉ des comptes de tests self-reportés par les README de MODULE

Surface ungated distincte des fiches : chaque `05_deliverables_mvp/<suite>/README.md`
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. Tous les blocs de comptes de tests existants visent 03_agents/*
(row_re, agrégats prose, per-suite hors table) ; row_re ne lit le README de module QUE
comme cible de lien. Un test ajouté/retiré met à jour regression_plan.json (auth =
plan.suites[path].test_methods, byte-gaté) tandis que la prose du README rote en silence.

Nouveau bloc « READMEs de MODULE · comptes de tests self-reportés » (table config
MODULE_README_TESTS · motifs ancrés) : chaque motif DOIT matcher (absent = régression #6)
ET tous ses groupes == auth ; `**N/N verts**` capture 2 groupes → un 25/24 incohérent mord.
5 modules sans self-report (chat_otoia/mobile/publiciste/acceptance/audit_4big) hors table.

4 morsures vérifiées (drift commentaire · incohérence N/N · disparition de claim · drift
auto-score prose) ; restauré = 440 checks de base intacts + 27 nouveaux ; check_ci_integrity
+ check_docs re-verts. Restauration par backup ciblé (jamais git checkout ./git clean).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-01 19:45:11 +00:00
parent 861260462f
commit 18a758045f
2 changed files with 117 additions and 0 deletions
+90
View File
@@ -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/<suite>/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/<suite>/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.