[DTP-Worker] Sprint 8 · buffer L75 · Domaine Frontend/Chat OTOIA : le montage de l'assistant conversationnel par portail (frontend/chat_otoia) affichait « 5 Custom Block + 5 configs runtime » (fiche agent frontend_console) et « 5 portails · 5 fixtures · 5 configs runtime » (README du module) — trois nombres data-derived, TOUS = 5 (piège aveugle), transcrits À LA MAIN dans DEUX docs sans AUCUN gate, alors que frontend/chat_otoia/out/MANIFEST.json (byte-gaté par check_artifacts, counts.custom_blocks/mounts/portails recomptés du contrat RBAC à chaque build via la bijection 1 block ⇔ 1 mount ⇔ 1 portail métier, plateforme exclu) fait autorité. Piège aveugle caractéristique : les trois valent 5 aujourd'hui — un gate qui n'en recompterait qu'UN serait aveugle à la dérive des deux autres (ajouter un portail au contrat RBAC → chat_otoia rebâtit 6 blocks/6 mounts/6 portails pendant que les docs restent à 5 en silence) → nouveau bloc dans check_readme_claims recomputant CHAQUE nombre depuis SON PROPRE champ du MANIFEST et exigeant l'égalité avec les deux docs. Cohérence croisée : custom_blocks == mounts == portails == |MANIFEST.portails| (la bijection du générateur) — mord un compteur désynchronisé de sa propre liste. Un claim absent échoue AUSSI (5 morsures vérifiées : dérive custom_block fiche captée là où mounts reste 5 · dérive configs runtime fiche captée là où blocks reste 5 · dérive portails README · dérive fixtures README · claim configs runtime disparu = red ; restauré = green). ci/README.md (table + détail) mis à jour · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -72,6 +72,13 @@
|
||||
# de dépôt » transcrit À LA MAIN dans DEUX docs → confotur
|
||||
# MANIFEST.counts (fields/data_fields/sections/roles/depot_events, recomptés
|
||||
# de confotur_spec.json, byte-gatés)
|
||||
# frontend/chat_otoia/README.md + 03_agents/frontend_console/AGENT.md (montage
|
||||
# du Chat OTOIA par portail) :
|
||||
# • triplet « N `Custom Block` · M configs runtime · P portails » (tous = 5
|
||||
# aujourd'hui — piège aveugle) transcrit À LA MAIN dans DEUX docs → chat_otoia
|
||||
# MANIFEST.counts (custom_blocks/mounts/portails, recomptés du contrat RBAC,
|
||||
# byte-gatés) + cohérence croisée == |MANIFEST.portails| (bijection 1 block ⇔
|
||||
# 1 mount ⇔ 1 portail)
|
||||
# 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é).
|
||||
#
|
||||
@@ -1028,6 +1035,96 @@ if demo_n is not None:
|
||||
bad(f"Démo · {DEMO_RD} — dit {m.group(1)} modules cités MAIS artefact dit "
|
||||
f"{demo_n} → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Chat OTOIA · montage de l'assistant conversationnel par portail (nombre de
|
||||
# Custom Block / configs runtime / portails) — même classe de « vert trompeur »,
|
||||
# transcrit À LA MAIN dans DEUX docs, sans AUCUN gate.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le générateur chat_otoia_gen émet out/MANIFEST.json (byte-gaté par
|
||||
# check_artifacts ⇒ faisant autorité) dont `counts.custom_blocks`, `counts.mounts`
|
||||
# et `counts.portails` sont RECOMPTÉS à chaque build depuis le contrat RBAC (un
|
||||
# `Custom Block` ⇔ une config runtime ⇔ un portail métier, `plateforme` exclu —
|
||||
# invariant 2 du générateur : bijection 1 block ⇔ 1 mount ⇔ 1 portail). Ces
|
||||
# nombres sont recopiés À LA MAIN : la fiche agent Frontend Console
|
||||
# (03_agents/frontend_console/AGENT.md — « **N `Custom Block` + M configs
|
||||
# runtime** ») ET le README du module (05_deliverables_mvp/frontend/chat_otoia/
|
||||
# README.md — « Portails (N, `plateforme` exclu) », « N fixtures `Custom Block` »,
|
||||
# « M configs runtime »). Piège « aveugle » caractéristique (cf. DevOps phases ⁄
|
||||
# confirmations, bascule verdict audit_5d) : custom_blocks, mounts ET portails
|
||||
# valent TOUS TROIS 5 AUJOURD'HUI — un gate qui n'en recompterait qu'un serait
|
||||
# AVEUGLE à la dérive des autres (ajouter un portail au contrat RBAC → chat_otoia
|
||||
# rebâtit 6 blocks ⁄ 6 mounts ⁄ 6 portails pendant que les docs restent à 5). On
|
||||
# RECOMPUTE donc CHAQUE nombre depuis SON PROPRE champ du MANIFEST (jamais figé
|
||||
# ici · zéro duplication du compteur du générateur #5) et on exige l'égalité avec
|
||||
# les docs. Cohérence croisée : counts.custom_blocks == counts.mounts ==
|
||||
# counts.portails == |MANIFEST.portails| (la bijection du générateur) — mord un
|
||||
# compteur désynchronisé de sa propre liste. Un claim absent échoue AUSSI (la
|
||||
# disparition d'un chiffre est une régression · traçabilité).
|
||||
# ============================================================================
|
||||
CO_RD = f"{D}/frontend/chat_otoia/README.md"
|
||||
CO_FI = "03_agents/frontend_console/AGENT.md"
|
||||
try:
|
||||
co_man = load("frontend/chat_otoia/out/MANIFEST.json")
|
||||
co_cb = str(co_man["counts"]["custom_blocks"])
|
||||
co_mo = str(co_man["counts"]["mounts"])
|
||||
co_po = str(co_man["counts"]["portails"])
|
||||
co_nlist = len(co_man["portails"])
|
||||
if not (co_cb == co_mo == co_po == str(co_nlist)):
|
||||
bad(f"Chat OTOIA · incohérence artefact : custom_blocks={co_cb} · "
|
||||
f"mounts={co_mo} · portails={co_po} · |portails|={co_nlist} "
|
||||
f"(bijection 1 block ⇔ 1 mount ⇔ 1 portail attendue)")
|
||||
except (OSError, KeyError, ValueError) as e:
|
||||
bad(f"Chat OTOIA · artefact chat_otoia illisible/inattendu : {e}"); co_cb = None
|
||||
if co_cb is not None:
|
||||
# 1) Fiche agent Frontend Console — « N `Custom Block` + M configs runtime »
|
||||
co_fi = read_norm(CO_FI)
|
||||
if co_fi is not None:
|
||||
m = re.search(r"\*\*(\d+) `Custom Block` \+ (\d+) configs runtime\*\*", co_fi)
|
||||
if m is None:
|
||||
bad(f"Chat OTOIA · {CO_FI} — claim « N `Custom Block` + M configs runtime » "
|
||||
f"INTROUVABLE (attendu {co_cb}/{co_mo})")
|
||||
elif m.groups() == (co_cb, co_mo):
|
||||
good(f"Chat OTOIA · {CO_FI} — {'/'.join(m.groups())} == artefact "
|
||||
f"(custom_blocks={co_cb} · mounts={co_mo})")
|
||||
else:
|
||||
bad(f"Chat OTOIA · {CO_FI} — dit {'/'.join(m.groups())} MAIS artefact dit "
|
||||
f"{co_cb}/{co_mo} → régénérer la fiche")
|
||||
# 2) README module — « Portails (N, `plateforme` exclu) »
|
||||
co_rd = read_norm(CO_RD)
|
||||
if co_rd is not None:
|
||||
m = re.search(r"Portails \((\d+), `plateforme` exclu\)", co_rd)
|
||||
if m is None:
|
||||
bad(f"Chat OTOIA · {CO_RD} — claim « Portails (N, `plateforme` exclu) » "
|
||||
f"INTROUVABLE (attendu portails={co_po})")
|
||||
elif m.group(1) == co_po:
|
||||
good(f"Chat OTOIA · {CO_RD} — {m.group(1)} portails == artefact "
|
||||
f"(portails={co_po})")
|
||||
else:
|
||||
bad(f"Chat OTOIA · {CO_RD} — dit {m.group(1)} portails MAIS artefact dit "
|
||||
f"{co_po} → régénérer le README")
|
||||
# 3) README module — « N fixtures `Custom Block` »
|
||||
m = re.search(r"(\d+) fixtures `Custom Block`", co_rd)
|
||||
if m is None:
|
||||
bad(f"Chat OTOIA · {CO_RD} — claim « N fixtures `Custom Block` » INTROUVABLE "
|
||||
f"(attendu custom_blocks={co_cb})")
|
||||
elif m.group(1) == co_cb:
|
||||
good(f"Chat OTOIA · {CO_RD} — {m.group(1)} fixtures == artefact "
|
||||
f"(custom_blocks={co_cb})")
|
||||
else:
|
||||
bad(f"Chat OTOIA · {CO_RD} — dit {m.group(1)} fixtures MAIS artefact dit "
|
||||
f"{co_cb} → régénérer le README")
|
||||
# 4) README module — « M configs runtime » (2e transcription des mounts)
|
||||
m = re.search(r"(\d+) configs runtime", co_rd)
|
||||
if m is None:
|
||||
bad(f"Chat OTOIA · {CO_RD} — claim « M configs runtime » INTROUVABLE "
|
||||
f"(attendu mounts={co_mo})")
|
||||
elif m.group(1) == co_mo:
|
||||
good(f"Chat OTOIA · {CO_RD} — {m.group(1)} configs runtime == artefact "
|
||||
f"(mounts={co_mo})")
|
||||
else:
|
||||
bad(f"Chat OTOIA · {CO_RD} — dit {m.group(1)} configs runtime MAIS artefact "
|
||||
f"dit {co_mo} → régénérer le README")
|
||||
|
||||
sys.exit(1 if FAIL else 0)
|
||||
PY
|
||||
rc=$?
|
||||
|
||||
Reference in New Issue
Block a user