[DTP-Worker] Sprint 8 · buffer · Frontend Console/AGENT.md : gate d'IDENTITÉ des configs runtime Chat OTOIA (persona · langues · endpoint:null #6/#8) ancré sur chat_mount.json ⨯ MANIFEST.json
Bloc anti-dérive #6 dans ci/check_readme_claims.sh : la cellule « Métrique vérifiée » de 03_agents/frontend_console/AGENT.md:29 restituait 3 attributs data-derived du montage OTOIA (persona Amélie · langues FR/EN/ES · `endpoint: null`) ; le bloc chat_otoia amont ne gate que le COMPTE blocks/mounts/portails, et le gate persona/capabilities ancré sur CLAUDE.md vise spec/mounts/MANIFEST/README/oracle, jamais cette fiche. Le nouveau bloc recompute les 3 depuis out/chat_mount.json (5 configs) + out/MANIFEST.json byte-gatés : persona==MANIFEST.persona.nom, langues==MANIFEST.langues majuscule, endpoint:null == affirmation d'honnêteté exigeant all(mount.endpoint is None) — un endpoint fabriqué mord. Cohérences croisées MANIFEST⇔chaque mount + endpoint_statut=='a_confirmer'⇔endpoints tous null. 6 morsures vérifiées · 7 gates verts · aucune écriture out/ (0 dérive artefact). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-1
File diff suppressed because one or more lines are too long
@@ -2234,6 +2234,79 @@ if co_cb is not None:
|
||||
bad(f"Chat OTOIA · {CO_RD} — dit {m.group(1)} configs runtime MAIS artefact "
|
||||
f"dit {co_mo} → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Chat OTOIA · IDENTITÉ des configs runtime (persona · langues · endpoint) —
|
||||
# ATTRIBUTS transcrits À LA MAIN dans la cellule « Métrique vérifiée » de la
|
||||
# fiche agent, AVEUGLES au gate de COMPTE ci-dessus.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le bloc précédent gate le NOMBRE de blocks/mounts/portails ; il est indifférent
|
||||
# à CE QUE chaque config runtime dit. Or la même cellule (03_agents/
|
||||
# frontend_console/AGENT.md:29) restitue TROIS attributs data-derived du montage :
|
||||
# « persona Amélie … · langues FR/EN/ES · `endpoint: null` ». Ils sortent des
|
||||
# artefacts byte-gatés out/chat_mount.json (une config par portail) + out/
|
||||
# MANIFEST.json (persona/langues/endpoint_statut consolidés) — jamais de la spec.
|
||||
# • persona.nom : le prénom de l'assistant (le « QC » est le qualificatif de
|
||||
# marque CLAUDE.md « Voix Amélie QC », gardé en littéral — non gaté ici).
|
||||
# • langues : la surface trilingue FR/EN/ES lue par le générateur dans
|
||||
# seo_spec.json (source unique des langues).
|
||||
# • endpoint : `null` est une AFFIRMATION D'HONNÊTETÉ #6/#8 — l'endpoint OTOIA
|
||||
# n'est PAS fabriqué (renseigné côté VPS). Si une config gagnait un endpoint
|
||||
# réel, la fiche « endpoint: null » deviendrait un MENSONGE en silence.
|
||||
# Cohérence croisée (bijection du générateur) : MANIFEST.persona.nom ET
|
||||
# MANIFEST.langues doivent valoir EXACTEMENT ce que porte CHAQUE mount (un mount
|
||||
# désynchronisé de son propre manifeste mord ici) ; endpoint_statut « a_confirmer »
|
||||
# doit correspondre à des endpoints TOUS `null` (sinon incohérence interne de
|
||||
# l'artefact). Un claim absent échoue AUSSI (INTROUVABLE = régression #6). Aucune
|
||||
# suite tests/ (FONCTIONS du builder, jamais la prose de la fiche) n'attrape ce
|
||||
# « vert trompeur ».
|
||||
# ============================================================================
|
||||
try:
|
||||
ci_man = load("frontend/chat_otoia/out/MANIFEST.json")
|
||||
ci_mounts = load("frontend/chat_otoia/out/chat_mount.json")
|
||||
ci_persona = ci_man["persona"]["nom"]
|
||||
ci_langs = list(ci_man["langues"])
|
||||
ci_statut = ci_man["endpoint_statut"]
|
||||
if not ci_mounts:
|
||||
bad("Chat OTOIA identité · out/chat_mount.json vide"); ci_persona = None
|
||||
except (OSError, KeyError, ValueError, TypeError) as e:
|
||||
bad(f"Chat OTOIA identité · artefact illisible/inattendu : {e}"); ci_persona = None
|
||||
if ci_persona is not None:
|
||||
# Cohérence croisée MANIFEST ⇔ chaque config runtime (bijection du générateur)
|
||||
bad_persona = sorted({m["persona"]["nom"] for m in ci_mounts if m["persona"]["nom"] != ci_persona})
|
||||
bad_langs = sorted({"/".join(m["langues"]) for m in ci_mounts if list(m["langues"]) != ci_langs})
|
||||
all_null = all(m["endpoint"] is None for m in ci_mounts)
|
||||
if bad_persona:
|
||||
bad(f"Chat OTOIA identité · persona MANIFEST={ci_persona!r} MAIS mounts portent "
|
||||
f"aussi {bad_persona} (montage désynchronisé)")
|
||||
if bad_langs:
|
||||
bad(f"Chat OTOIA identité · langues MANIFEST={ci_langs} MAIS mounts portent "
|
||||
f"aussi {bad_langs} (montage désynchronisé)")
|
||||
if all_null and ci_statut != "a_confirmer":
|
||||
bad(f"Chat OTOIA identité · endpoints TOUS null MAIS endpoint_statut={ci_statut!r} "
|
||||
f"(attendu 'a_confirmer' — incohérence interne artefact)")
|
||||
if (not all_null) and ci_statut == "a_confirmer":
|
||||
bad("Chat OTOIA identité · endpoint_statut='a_confirmer' MAIS ≥1 endpoint fabriqué "
|
||||
"(incohérence interne artefact)")
|
||||
exp_langs = "/".join(l.upper() for l in ci_langs)
|
||||
exp_endpoint = "null" if all_null else "NON-null(" + ",".join(
|
||||
sorted({str(m["endpoint"]) for m in ci_mounts if m["endpoint"] is not None})) + ")"
|
||||
co_fi2 = read_norm(CO_FI)
|
||||
if co_fi2 is not None:
|
||||
m = re.search(r"persona (\S+) QC · langues ([A-Z/]+) · `endpoint: ([^`]+)`", co_fi2)
|
||||
if m is None:
|
||||
bad(f"Chat OTOIA identité · {CO_FI} — claim « persona <nom> QC · langues "
|
||||
f"<L> · `endpoint: <e>` » INTROUVABLE (attendu {ci_persona}/{exp_langs}/{exp_endpoint})")
|
||||
else:
|
||||
got = m.groups()
|
||||
want = (ci_persona, exp_langs, exp_endpoint)
|
||||
if got == want:
|
||||
good(f"Chat OTOIA identité · {CO_FI} — persona {got[0]} · langues {got[1]} · "
|
||||
f"endpoint {got[2]} == artefact (chat_mount ×{len(ci_mounts)} ⇔ MANIFEST)")
|
||||
else:
|
||||
bad(f"Chat OTOIA identité · {CO_FI} — dit persona {got[0]}/langues {got[1]}/"
|
||||
f"endpoint {got[2]} MAIS artefact dit {want[0]}/{want[1]}/{want[2]} "
|
||||
f"→ régénérer la fiche")
|
||||
|
||||
# ============================================================================
|
||||
# Recette (module) · couple « N livrables de sprint + M métriques succès MVP »
|
||||
# transcrit À LA MAIN dans DEUX docs — même classe de « vert trompeur ».
|
||||
|
||||
Reference in New Issue
Block a user