diff --git a/05_activity_log/2026-08-02.md b/05_activity_log/2026-08-02.md index 036947e..b24b32f 100644 --- a/05_activity_log/2026-08-02.md +++ b/05_activity_log/2026-08-02.md @@ -1329,3 +1329,45 @@ exit 0**. Aucune commande touchant au VPS. **Non fait (hors périmètre #8)** — runtime VPS publiciste (`publiciste.py`, systemd/ inotify, WhatsApp), déploiement serveur : hors périmètre worker. + +--- + +## Sprint 8 · buffer · Compte d'agents — ancrage des 3 surfaces vives de `GAP_ANALYSIS_SPRINT1.md` (dont la coche de couverture DoD) sur la source unique `n_agents` + +**Contexte** — Série anti-dérive Sprint 8 (CLAUDE.md #6 « zéro invention de chiffres »). +Le commit précédent (cb8d931) a ancré « 13 agents » à `git ls-files 03_agents/*/AGENT.md` +(source unique `n_agents`) sur les 2 docs de mandat de tête (AGENTS_EXISTING_ASSETS titre + +MASTER_PROMPT §28), en plus du README ×2. Un balayage de complétude a exhumé une **3ᵉ +surface entièrement HORS gate** : le **livrable Sprint 1** `05_deliverables_mvp/ +GAP_ANALYSIS_SPRINT1.md` (Definition of Done) retranscrit ce même compte à **trois +endroits vifs** — l.12 périmètre d'audit (« audit des **13 agents DTP** »), l.53 constat +global (« **12 des 13 agents** partent d'un socle existant »), et surtout l.214 la **coche +de couverture DoD** (« Couverture **13 agents** + OTOIA core ✅ »). Cette coche AFFIRME une +complétude COURANTE : elle DOIT suivre le nombre réel de fiches. + +**Le « vert trompeur » — PROUVÉ ungate avant ajout** (mémoire +`verify-uncovered-before-gating`) : `GAP_ANALYSIS` n'est référencé par AUCUN `ci/*.sh` +(`grep` = 0) ; muter l.214 « 13 »→« 14 » laissait `check_readme_claims` **exit 0**. Or ce +NOMBRE a une **dérive prouvée** : le publiciste fut ajouté comme 13ᵉ agent (12→13), forçant +la correction de cb8d931. Si un 14ᵉ agent était mandaté, la coche DoD mentirait en silence. +`check_artifacts` est aveugle (la SPEC n'est pas un `out/*.json`) ; aucune suite `tests/` ne +touche l'ancre doc↔disque. + +**Gate ajouté — EXTENSION de la boucle head-docs existante** (`ci/check_readme_claims.sh`, +bloc « Comptes d'agents dans les docs de mandat de tête »), pas un bloc neuf : 3 tuples +`(GAP, motif, label)` réutilisant le `n_agents` DÉJÀ dérivé (zéro nouvelle machinerie · +zéro re-dérivation · #5). On n'ancre QUE le **total** — le « 12 » analytique de l.53 +(agents à socle existant) N'EST PAS gaté (motif `\d+ des (\d+) agents` capture le 2ᵉ nombre). +Surface INTROUVABLE = échec (anti-évaporation #6). `ci/README.md` mis à jour : le décompte +d'agents est désormais documenté comme ancré à **7 surfaces vives**. + +**Vérif** — 3 checks verts sur l'arbre propre (les 3 == 13). **6 morsures** adversariales, +reverts par `cp` ciblé (jamais `git checkout` large — cf. incident consigné) : **M1** DoD +13→14 (mord) · **M2** périmètre 13→99 (mord) · **M3** constat total 13→12 (mord) · **M4** +ligne DoD supprimée ⇒ INTROUVABLE · **M5 no-false-positive** : muter le « 12 » analytique +(12→11), total intact ⇒ gate **exit 0** (preuve qu'on ne gate que le total) · **M6 +SILENT-GREEN** : dérive de la SOURCE (`git rm --cached` d'une fiche ⇒ `n_agents`=12), docs +figés à 13 ⇒ les **5 surfaces head-docs+GAP mordent** « dit 13 MAIS 03_agents/ en compte 12 » +(preuve que l'autorité est le git-index, pas la cohérence interne). Arbre restauré. **7 gates +re-joués → exit 0** : check_ci_integrity · check_artifacts · check_docs · check_readme_claims · +check_regression · guard_constraints · validate_json. Aucune commande touchant au VPS. diff --git a/ci/README.md b/ci/README.md index 693800f..a0dd797 100644 --- a/ci/README.md +++ b/ci/README.md @@ -124,7 +124,11 @@ docs d'entrée — `README.md` : - modules gated `N/M` à `K/100` + verdict `PASS` → `qa/audit_4big/out/quality_report.json` (`totals`) ; - `N` suites gated → `qa/regression/out/regression_plan.json` (`totals.suites`) ; - `N` promesses (`X` sprint + `Y` métriques), `Z` `in_repo`, verdict `true` → `qa/acceptance/out/acceptance_matrix.json` ; -- « 13 agents » (×2 : nav + titre) → `git ls-files 03_agents/*/AGENT.md`. +- « 13 agents » recompté depuis `git ls-files 03_agents/*/AGENT.md` (source unique) + et exigé identique à **7 surfaces vives** : `README.md` ×2 (nav + titre) · + `AGENTS_EXISTING_ASSETS.md` (titre) · `02_master_prompt/MASTER_PROMPT_DTP_v2.md` + (titre) · `GAP_ANALYSIS_SPRINT1.md` ×3 (périmètre d'audit · constat global *total* + — le « 12 » analytique n'est PAS ancré · coche de couverture DoD). Et la fiche QA `03_agents/qa/AGENT.md` (section « Verdict agrégé courant », qui se disait « jamais compté à la main » tout en portant un compte figé qui s'est périmé diff --git a/ci/check_readme_claims.sh b/ci/check_readme_claims.sh index 41d717d..460ac6d 100755 --- a/ci/check_readme_claims.sh +++ b/ci/check_readme_claims.sh @@ -226,12 +226,23 @@ else: # régression). Aucun gate ne les comparait à la réalité du disque. On réutilise # le `n_agents` DÉJÀ dérivé de `git ls-files 03_agents/*/AGENT.md` (source unique, # pas de nouvelle machinerie) et on exige que chaque doc cite exactement ce compte. +# Le GAP_ANALYSIS_SPRINT1 (livrable Sprint 1, Definition of Done) retranscrit ce +# même compte à TROIS surfaces vives non gatées : le périmètre d'audit (« audit des +# N agents DTP »), le constat global (« … des N agents partent d'un socle existant » +# — on n'ancre QUE le TOTAL, pas le « 12 » analytique des agents à socle existant), +# et surtout la coche de couverture DoD (« Couverture N agents + OTOIA core ✅ »). +# Cette coche AFFIRME une complétude courante : si un 14e agent était mandaté (comme +# le publiciste le fut, 12→13), elle mentirait en silence. Même source unique n_agents. # ============================================================================ +GAP = "05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md" for path, pat, label in [ ("AGENTS_EXISTING_ASSETS.md", r"Mapping vers les (\d+) agents DTP", "Actifs existants · titre"), ("02_master_prompt/MASTER_PROMPT_DTP_v2.md", r"Tes (\d+) agents spécialisés", "Master prompt · titre"), + (GAP, r"audit des \*\*(\d+) agents DTP", "Gap analysis · périmètre d'audit"), + (GAP, r"\d+ des (\d+) agents", "Gap analysis · constat global (total)"), + (GAP, r"Couverture (\d+) agents", "Gap analysis · couverture DoD"), ]: try: doc = re.sub(r"\s+", " ", open(path, encoding="utf-8").read())