[DTP-Worker] Sprint 8 · buffer · Fiches agents/voix : gate d'ANCRAGE du pied de page « Voix Amélie QC (multilingual_v2) pour toute interaction OTOIA » — répété dans 11 des 13 fiches 03_agents/*/AGENT.md (hors faisabilite/publiciste) — sur CLAUDE.md §Architecture cible

Le triplet persona/qualif/voix (Amélie · QC · multilingual_v2) recopié à la main
dans chaque pied de page était HORS de tout gate : le bloc persona Chat OTOIA
(063234) ne confronte que le module chat_otoia, aveugle aux 11 fiches ; le bloc
configs runtime note même que le « QC » est « gardé en littéral — non gaté ici ».

Bloc ajouté (check_readme_claims.sh) : RE-DÉRIVATION INDÉPENDANTE du triplet de
§Architecture cible (regex qui ne fige PAS le qualificatif en dur ⇒ QC→… mord ici,
pas seulement via l'INTROUVABLE du bloc persona) · 3 tokens == CLAUDE.md exigés sur
chaque fiche portant le pied de page · pied de page malformé & évaporation totale du
recensement échouent AUSSI (#6). 6 morsures vérifiées (CLAUDE.md voix v2→v3 : 11
fiches + cascade persona · CLAUDE.md qualif QC→BC : 11 fiches, bloc indépendant ·
seo voix · crm persona · bim malformé · surface évaporée) · restauré green · 7 gates
re-verts. ci/README.md (récap + paragraphe détaillé) mis à jour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-01 17:44:15 +00:00
parent b9e333ceef
commit e874717f0f
3 changed files with 170 additions and 1 deletions
+27 -1
View File
File diff suppressed because one or more lines are too long
+87
View File
@@ -5781,6 +5781,93 @@ if cm_persona is not None and chat_spec is not None:
else:
good("Chat OTOIA · (e) oracle du test persona/capabilities == CLAUDE.md")
# ============================================================================
# Fiches agents · le PIED DE PAGE canonique « Voix Amélie QC (multilingual_v2) »
# répété dans CHAQUE fiche 03_agents/*/AGENT.md — ANCRÉ sur CLAUDE.md
# §Architecture cible, jamais gaté.
# ----------------------------------------------------------------------------
# 11 des 13 fiches agents (toutes sauf faisabilite/publiciste, qui n'orchestrent
# pas OTOIA) se terminent par la ligne « - Voix <persona> <qualif> (<voix>) pour
# toute interaction OTOIA ». Elle RECOPIE À LA MAIN les TROIS tokens de la
# contrainte CLAUDE.md §Architecture cible « Voix Amélie QC (multilingual_v2) » :
# le prénom de la persona (`Amélie`), le qualificatif de marque (`QC`) et le
# modèle de voix ElevenLabs (`multilingual_v2`). Le bloc « Chat OTOIA · IDENTITÉ
# de la persona » (ci-dessus) RE-DÉRIVE bien persona+voix de CLAUDE.md, MAIS ne
# confronte QUE le module chat_otoia (spec + out/ + son propre README + l'oracle
# du test) — AVEUGLE aux 11 pieds de page des fiches. L'autre bloc (« Chat OTOIA ·
# IDENTITÉ des configs runtime ») note même explicitement que le « QC » est
# « gardé en littéral — non gaté ici ». Aucune suite tests/ (FONCTIONS du builder,
# jamais la prose des fiches) n'attrape ce « vert trompeur ».
# Piège #6 : le jour où ElevenLabs déprécie `multilingual_v2` (→ `multilingual_v3`)
# ou qu'on renomme la persona/le qualificatif dans CLAUDE.md, ces 11 pieds de page
# annonceraient EN SILENCE une voix/persona que le mandat ne prescrit plus, chaque
# fiche affirmant orchestrer « toute interaction OTOIA » avec le mauvais modèle.
# On RE-DÉRIVE le triplet (persona · qualif · voix) de CLAUDE.md §Architecture cible
# (source unique · zéro duplication — mêmes `nom`/`voix` que le bloc persona
# ci-dessus, plus le qualificatif jusqu'ici jamais ancré) et on exige de CHAQUE
# fiche portant le pied de page que ses trois tokens == CLAUDE.md. Direction
# fiche→CLAUDE.md. La disparition TOTALE du pied de page échoue AUSSI (le
# recensement qui s'évapore est lui-même une régression #6). État courant : aucune
# valeur périmée.
# ============================================================================
if True:
# RE-DÉRIVATION INDÉPENDANTE de CLAUDE.md (ne dépend PAS du parse persona
# ci-dessus, dont la regex fige « QC » en dur : un renommage du qualificatif
# doit mordre ICI, pas seulement via l'INTROUVABLE du bloc persona).
try:
_cm_af = open("CLAUDE.md", encoding="utf-8").read()
# triplet canonique : « Voix <nom> <qualif> (<voix>) » (qualif jamais figé en dur)
_maf = re.search(r"Voix\s+(\S+)\s+(\S+)\s*\(([^)]+)\)", _cm_af)
if _maf is None:
raise ValueError("« Voix <persona> <qualif> (<voix>) » INTROUVABLE "
"dans CLAUDE.md §Architecture cible")
af_nom, af_qual, af_voix = (_nfc(_maf.group(1)), _nfc(_maf.group(2)),
_nfc(_maf.group(3)))
# cohérence avec le bloc persona quand il a pu parser (zéro duplication —
# même source, mêmes valeurs) ; s'il a échoué (cm_persona None), on continue.
if cm_persona is not None and (af_nom != cm_persona["nom"]
or af_voix != cm_persona["voix"]):
raise ValueError(f"triplet {af_nom!r}/{af_voix!r} incohérent avec le bloc "
f"persona {cm_persona} (parse divergent de CLAUDE.md)")
except (OSError, ValueError) as e:
bad(f"Fiches agents · pied de page voix CLAUDE.md §Architecture cible "
f"illisible/inattendu : {e}")
af_nom = None
if af_nom is not None:
_fiches = subprocess.run(["git", "ls-files", "03_agents/*/AGENT.md"],
capture_output=True, text=True).stdout.split()
_foot_re = re.compile(
r"Voix\s+(\S+)\s+(\S+)\s*\(([^)]+)\)\s+pour toute interaction OTOIA")
af_seen = 0
for _fi in _fiches:
try:
_ftxt = open(_fi, encoding="utf-8").read()
except OSError as e:
bad(f"Fiches agents · {_fi} illisible : {e}"); continue
_mfoot = _foot_re.search(_nfc(_ftxt))
# Fiche sans OTOIA (faisabilite/publiciste) : pas de pied de page attendu.
if _mfoot is None:
if "interaction OTOIA" in _ftxt:
bad(f"Fiches agents · {_fi} — prose « interaction OTOIA » présente "
f"MAIS pied de page « Voix <nom> <qualif> (<voix>) » malformé/"
f"INTROUVABLE (attendu {af_nom} {af_qual} ({af_voix}))")
continue
af_seen += 1
got = (_nfc(_mfoot.group(1)), _nfc(_mfoot.group(2)), _nfc(_mfoot.group(3)))
want = (af_nom, af_qual, af_voix)
if got == want:
good(f"Fiches agents · {_fi} — pied de page « Voix {got[0]} {got[1]} "
f"({got[2]}) » == CLAUDE.md §Architecture cible")
else:
bad(f"Fiches agents · {_fi} — pied de page dit « {got[0]} {got[1]} "
f"({got[2]}) » MAIS CLAUDE.md §Architecture cible dit « {want[0]} "
f"{want[1]} ({want[2]}) » → persona/qualif/voix périmé (mettre la "
f"fiche à jour)")
if af_seen == 0:
bad("Fiches agents · AUCUNE fiche ne porte le pied de page « Voix "
f"{af_nom} {af_qual} ({af_voix}) pour toute interaction OTOIA » — la "
f"surface d'identité voix OTOIA s'est évaporée (régression #6)")
# ============================================================================
# Mobile · le SDK MAJEUR Expo (« Expo 54 ») — ANCRÉ sur la roadmap Sprint 5 l.56,
# transcrit À LA MAIN dans le README sans AUCUN gate d'IDENTITÉ ni d'ancrage.