Dernier des 22 modules livrés orphelin de fiche (grep -rl sur 03_agents/*/AGENT.md). Mirroir exact du pattern CRM 071201 : sous-section dédiée + 1 ligne de table AUTO-GATÉE par 3 gates indépendants de check_readme_claims (résolution par cible de lien mobile/app_config ∈ plan.suites) — cellule Tests 22==source · job CI mobile-app-config-tests==ci.yml · verbes CLI build|validate==subparsers. Pas de piège des 2 cadres de sprint : S5 dans les deux (acceptance evidence_modules S5 · roadmap ## SPRINT 5 ligne Mobile L56) → cité L56. 3 énumérations « ancrage in-repo » réconciliées (sinon contradiction avec la nouvelle section), toutes sourcées. 0 out/ régénéré (git status = fiche seule) · 0 gate ajouté (#5) · 0 édition d'autorité · 0 chiffre inventé (#6, 22 lu dans regression_plan) · CI 33 PASS.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Classe prose FACT count ungated (prose-facts-vs-numeric-drift). Défaut : README:9 « la structure des 6 sections » + fiche CRM AGENT.md:47 « cœur du gate + 6 sections » décrivaient le livrable avec un compte périmé. Le bon compte = 7 est triple-sourcé et byte-gaté : out/MANIFEST.json counts.sections=7 · financement_spec.json bloc sections=7 (apport_initial,info_achat,choix_banque,formulaires,exigences,autorisations,envoi) · et le README se contredisait lui-même (L49 énumère 7, L57 « 7 sections » annotée source=MANIFEST). Origine du 6 : la DIRECTIVE originale énumérait 6 sections non-gating puis fut amendée pour ajouter apport_initial (gating, pos.1) → 7 ; spec+module ont suivi, les 2 prose L9/L47 non.
Correctif 6→7 sur les 2 SEULES surfaces d'implémentation. Les 4 « 6 sections » restantes sont des snapshots directive gelés (DIRECTIVE_FINANCEMENT L106/122/131 + DIRECTIVE_WORKFLOW_V10 L22/47) — input-specs datés de Michel, jamais réécrits (directive-vs-implementation · spec=authority) ; leur « 6 » est exact au cadre pré-amendement → INTACTS.
0 gate ajouté (#5 · un gate structuré ne mordrait pas la prose L9, hors-cible ; SIGNAL surfacé : financement seul module dont MANIFEST.counts n'est pas recompté par check_readme_claims). 0 chiffre inventé (#6). 0 production éditée. 0 commande VPS (#8). run_ci.sh 33 PASS 0 FAIL 0 SKIP.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le rapport stakeholder du jour (session 004112) s'arrêtait au jalon 33 jobs et
PRÉCÉDAIT toute la série d'attestation teeth des suites de MODULE (BATCH 1→4,
034144→051154, clôture 25/25). Le canal daily_reports ne captait donc aucun des
deux axes de « dents ». Section « fin de journée » ajoutée :
· axe A — 8/8 gates statiques mutation-prouvés (9fe8bf1/031134)
· axe B — 25/25 suites de module mutation-prouvées (6+6+6+7)
Chaque chiffre sourcé sur une structure commitée (ls ci/*.sh=8 · gate.needs=25 ·
série de commits) — 0 saisi à la main (#6). Message : les tables prouvent la CI
VERTE, les attestations teeth prouvent qu'elle MORD (gate/suite toujours-vert =
faux vert invisible).
Avant de choisir : chasse docstring↔code drift sur les 21 générateurs (classe
récurrente) → 0 contradiction réelle ; les « docstrings sans liste-sorties »
sont des faux positifs (sorties documentées dans Sous-commandes), uniformiser =
churn écartée (#5).
0 édition de production · 0 gate ajouté (#5) · aucune commande VPS (#8) ·
aucun git clean · CI 33 PASS.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Continuation de l'axe des DENTS des suites de MODULE ([[module-suite-teeth-mutation]]) : batches 034144+041149 avaient prouvé 12/25 ; ce batch 3 en couvre 6 de plus → 18/25 · 7 restantes non-couvertes ≠ édentées (pas de plafond silencieux).
6 BITES (chaque suite mord sur une dérive de LOGIQUE de son générateur, jamais un écho d'artefact) :
- rbac/fixtures_gen builder:43 if_owner ==→!= (test_if_owner_reflete_scope_own)
- rbac/userperm_gen builder:43 by_mechanism += 1→+=2 (sum==50)
- rbac/apply_plan aggregator:174 chaîne bijective 2e ==→!= (assertTrue couverture_bijective)
- mobile/app_config builder:105 roles=sorted(...)+reverse=True (==sorted(roles_map[portail]))
- qa/audit_5d builder:60 count(_FAIL)→count(_PASS) (totals fail:0→13)
- frontend/chat_otoia builder:114 sum(nb_roles)→sum(1) (test_44_roles_couverts 44→~5)
Axe distinct des DENTS des 8 gates STATIQUES (031134, 8/8) : une suite qui rechargerait out/*.json contre elle-même serait édentée = faux vert Sprint 8 · les suites reconstruisent en mémoire depuis le contrat.
LEÇON réappliquée (désambiguïser TOOTHLESS-test vs mutation INERTE) : le 1er pick mobile (:192 roles_couverts sum→len) était édenté pour la suite de MODULE (agrégat jamais ré-asserté en mémoire) ; basculé sur :105 (tri, réellement contraint). Idem fixtures :68 → :43.
Harnais /tmp read-only, remplacement d'octets littéral (assert 1 occurrence), run de la seule suite, restore byte-exact cp+cmp, trap EXIT, jamais git clean, arbre pristine · 0 gate ajouté (#5) · 0 chiffre inventé (#6) · 0 édition prod · CI 33 PASS
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Continuation honnête de l'axe DENTS-des-suites (034144 : 6/25, 19 non-couvertes≠édentées). Batch 2 couvre 6 de plus → 12/25. Chaque suite doit sortir NONZERO sur une dérive de LOGIQUE de son générateur (jamais un écho d'artefact) : scorer completude 20*filled, bancable point-équilibre math.ceil, workflow-vente tri-déterminisme .sort, dossier is_submittable seuil, financement apport /100.0, publiciste _fmt_usd séparateur espace.
LEÇON : un verdict TOOTHLESS doit être désambiguïsé — (a) test réellement édenté vs (b) mutation comportementalement INERTE pour la donnée du contrat. 2 mutations ont d'abord lu TOOTHLESS mais étaient (b), PAS des défauts : dossier >= '1'→>'1' inerte car max doc_status='2' (les 2 branches donnent 1) → une mutation qui FAIT BASCULER le résultat (>= '3') mord ; publiciste min→max inerte car _prix_depuis n'alimente que la gate is-not-None, sa valeur min n'est jamais affichée (obs. honnête, pas un défaut #5/#6) → on mute une logique observée (_fmt_usd). Règle : confirmer que la mutation change la SORTIE pour la fixture avant de croire un TOOTHLESS.
Axe distinct des DENTS des 8 gates STATIQUES (031134, 8/8). Portée honnête : 13 restantes non-couvertes≠édentées (pas de plafond silencieux). Harnais /tmp read-only, restore byte-exact cp+cmp, trap EXIT, jamais git clean, arbre pristine. 0 gate ajouté (#5) · 0 chiffre inventé (#6) · 0 édition prod · CI 33 PASS
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>