Les artefacts `out/chat_mount.json` (5 configs runtime, une par portail) +
`out/MANIFEST.json` portent la persona + les capabilities, BYTE-GATÉS pour la
REPRODUCTIBILITÉ par check_artifacts (reconstruction depuis `chat_spec.json`) mais
JAMAIS ANCRÉS à CLAUDE.md §Architecture cible (l.30 « Voix Amélie QC (multilingual_v2) »
· l.28 « OTOIA capabilities : aec.py + knowledge.py + prompt_engine.py + chat.py »),
leur source faisant autorité. Le bloc chat_otoia amont ne gate que la COMPOSITION
(portails métier · 1 block⇔1 mount) ; le SEUL contrôle d'identité vit dans tests/
(`test_persona_amelie_sourcee`/`test_capabilities_sourcees_sans_ajout`) mais son ORACLE
est HARDCODÉ (`"Amélie"`, `["aec.py",…]`) — une copie de plus, jamais comparée à
CLAUDE.md. Piège #6 : renommer la persona (`Amélie`→`Sophie`), changer la voix, ou
renommer/RETIRER une capability dans `chat_spec.json` (ou dans CLAUDE.md) reconstruit
l'artefact fidèlement (byte-gate VERTE) sans toucher l'oracle (tests VERTS) → le chat
monté dans CHAQUE portail annoncerait une persona/voix/capabilities CONTREDISANT le
mandat — « vert trompeur » de la classe des tokens branding ancrés sur #4 et de la
marque SEO §Entités. Aucune suite tests/ (FONCTIONS de génération, jamais l'ancre à
CLAUDE.md) ne l'attrape.
Gate ajouté (bloc « Chat OTOIA · persona + capabilities ancrées CLAUDE.md ») :
persona+capabilities re-dérivées de §Architecture cible (regex `Voix … QC (…)` +
`OTOIA capabilities : …` split `+`, NFC), puis (a) `chat_spec.json`
persona/capabilities == CLAUDE.md (ordre exact) · (b) le spec DÉCLARE l'ancrage
(`persona.source` + chaque `capability.source` citent CLAUDE.md) · (c) CHACUN des 5
mounts + le MANIFEST == CLAUDE.md · (d) README cite l'ancre §Architecture cible + nomme
persona + chaque capability (notation compacte matchée par radical) · (e) l'ORACLE du
test == CLAUDE.md (set-diff). Un claim absent échoue AUSSI.
8 morsures vérifiées : CLAUDE.md `Amélie→Sophie` (mord SIMULTANÉMENT
spec/mount/README/oracle — l'ancre est vive) · CLAUDE.md retire `chat.py` · spec
`aec.py→exfil.py` (capability injectée) · spec `persona.source` sans CLAUDE.md · UN
SEUL mount à voix altérée (byte-gate aveugle) · README retire le radical
`prompt_engine` · oracle du test persona `Amélie→Bob` · oracle du test capabilities
réordonné/tronqué ; restauré = green, exit 0. Working tree byte-restauré
(`git checkout --`, JAMAIS `git clean`) · 7 gates re-verts · unittest module re-vert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gate ajouté (bloc « Fiches agents · colonne Job CI ») : on RECOMPUTE l'ensemble des jobs depuis la clé `jobs:` de ci.yml (la section `on:` push/pull_request/workflow_dispatch est AVANT `jobs:` et donc exclue ; jamais une liste à la main) et on exige que chaque token `*-tests` cité dans une fiche y figure. Direction fiche→ci.yml (le consommateur) : ci.yml peut définir des jobs non cités (légitime), une fiche ne peut pas citer un job absent ; la disparition totale de la colonne échoue AUSSI. 33 références vérifiées == jobs ci.yml ; 2 morsures (token de fiche `seo-tests`→`seo-suite-tests` fantôme · job ci.yml `rbac-tests` renommé → mord SIMULTANÉMENT les 4 fiches qui le citent : erpnext_backend/ifc_speckle/mobile/rendu), restauré vert, 7 gates re-verts. ci/README.md + activity log MAJ.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le bloc e-NCF gate le FORMAT de l'identifiant ; le bloc cross-cohérence (2e surface) gate états émetteurs/champs de base/FormaPago ; mais AUCUN ne comparait l'IDENTITÉ de ce rôle à ses DEUX sources faisant autorité : (a) out/ecf_plan.json (byte-gaté) — chaque emission_events[] porte role_id + erpnext_role_name ; (b) rbac_50_roles.json (contrat) — le rôle porte portail:"compta". Le `portail` n'est PAS dans l'artefact ; il n'est vérifiable QUE contre le contrat.
Même classe d'IDENTITÉ que la Fiche Mobile / les Fiches Faisabilité ou les gardes CRM/workflow_vente, appliquée à une 3e surface distincte du MÊME README fiscal. Piège : la seule vérification existante (tests/) teste des FONCTIONS (ncf/résolution), jamais la prose. RÉAFFECTER l'émission à un autre rôle, le RENOMMER, ou DÉPLACER le rôle hors du portail compta (e-CF émis HORS Compta — séparation cassée) laisse la prose périmée pendant que l'artefact/contrat disent autre chose → l'agent ERPNext Backend câblerait le mauvais rôle émetteur.
Gate ajouté (ci/check_readme_claims.sh, bloc « Fiscal rôle émetteur ») : role_id/erpnext_role_name recomputés de emission_events + portail/nom Frappe du contrat, prose EXACTE ; cohérences croisées : tous les emission_events pointent UN SEUL rôle (fonction · non vide) · role_id unique au contrat · nom artefact == contrat (zéro-dup) · portail == compta. Un claim absent échoue AUSSI. 6 morsures vérifiées (README renomme role_id/nom/portail · artefact réaffecte les 2 events à ventes-directeur (5 mords cascade) · contrat déplace le rôle vers ventes · artefact diverge du contrat sur le nom), restauré vert, 7 gates re-verts. ci/README.md mis à jour.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Les blocs Fiches Faisabilité / Fiche Mobile ne gataient que les attributs du CONTRAT ; le bloc « triplets par workspace » ne gate que le COMPTE de rôles par Workspace (`nb_roles`), AVEUGLE à QUEL rôle. Rattacher le rôle mobile à `OTO Ventes` (SUR-EXPOSITION console : le dev mobile gagnerait l'accès au portail Ventes — la restriction même que la note #6 pose), retirer/déplacer le rôle rendu de `OTO Construction`, laissait la fiche périmée en silence pendant que l'artefact dit autre chose ⇒ l'agent ERPNext Backend câblerait le mauvais accès console.
Gate ajouté (nouveau bloc « Fiches agents · rattachement Workspace ») : index recomputé `erpnext_role_name → {titres de Workspace le portant}` depuis workspace.json (nom résolu du contrat par id, zéro duplication). 3 formes d'assertion : in_named (rendu — prose cite CE Workspace ET membership == {lui seul}) · in_any (ifc — membership ≥1) · not_in_named (mobile — assertion NÉGATIVE #6, rôle ABSENT du Has Role du Workspace nommé). Garde anti-typo : Workspace nommé absent de l'artefact ⇒ ROUGE. Claim absent ⇒ ROUGE (traçabilité).
9 morsures vérifiées (4 artefact + 5 fiche/bord) ; restauré vert ; 7 gates re-verts. ci/README.md (récap + paragraphe détaillé) + activity log + mémoire mis à jour.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Même classe que la Fiche Mobile (session précédente) — surface 03_agents/*/AGENT.md transcrivant à la main les attributs d'un rôle depuis le contrat, gatée (si tant est) seulement sur des comptes agrégés. Gate ajouté (bloc « Fiches Faisabilité », config-table par fiche : fichier · role_id · attributs restitués) : par attribut recomputé du contrat, prose EXACTE exigée ; permissions rendues en ORDRE CANONIQUE (read→R · write→W · create/delete/… en toutes lettres — élargir/rétrécir change la chaîne, `R/W/create` ne satisfait plus `R/W/create/delete`) ; verbe inconnu ⇒ ROUGE ; claim absent échoue AUSSI.
#6 (honnêteté) vérifié AVANT édition : la DESCRIPTION de ces deux fiches est une PARAPHRASE éditoriale (le contrat porte « (… — CLAUDE.md) » / « les modèles » que la fiche condense) — donc NON gatée verbatim (ne rien réécrire de correct pour un gate), seuls les attributs structurés (transcrits à l'exact) sont contraints. État courant : aucun attribut structuré périmé (12 recomputes == contrat).
11 morsures vérifiées (5 contrat + 6 fiche) : rendu Faisabilité +write (R→R/W) · rendu niveau 2→3 · rendu WA SRL→WAF · rendu rôle renommé · ifc Faisabilité R/W→R · fiche rendu File R/W/create→…/delete · fiche ifc R/W→R/W/create · fiche rendu module Faisabilité→Selling · fiche ifc WA SRL→WAF · fiche rendu nom_fr retiré (absent) · ligne contact ifc supprimée (INTROUVABLE) ; restauré vert, 7 gates re-verts. ci/README.md + activity log MAJ.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ces 4 figures sont Σ quantités · Σ(qté×prix_usd) · Σ(qté×prix_dop) · ⌈point_equilibre_pct × Σ unités⌉ calculées sur la fixture COMMITÉE fixtures/brief_bancable.json, le 52 % ancré sur CLAUDE.md #9 (« Point équilibre 52% pré-vente »). PIÈGE : la seule vérification existante (tests/) teste des FONCTIONS (l'arithmétique de recoupement _check_derived_arithmetic) avec des oracles HARDCODÉS dans le test — une copie de plus, jamais comparée à la PROSE du README. Éditer une typologie de la fixture (quantité/prix), en ajouter/retirer une, ou déplacer le point d'équilibre de CLAUDE.md #9, laisse les 4 chiffres du README périmés pendant que le générateur produit autre chose → le banquier lit un dossier faux (l'invention même que #6 interdit) — « vert trompeur » qu'aucune suite tests/ n'attrape.
Nouveau bloc « Faisabilité/bancable figures » dans ci/check_readme_claims.sh (avant sys.exit), même esprit que le bloc faisabilite/generator ancré sur CLAUDE.md #9/#10 mais appliqué à une surface dont la source de vérité n'est PAS un out/*.json : (1) recompute indépendant des 4 figures depuis la fixture commitée ; (2) cohérence croisée — le manifeste GÉNÉRÉ (bancable_gen validate, exécuté via subprocess stdlib pur, encoding utf-8) == le recompute (mord un générateur/fixture incohérents) ; (3) prose — un seul pattern d'identité exige les 4 valeurs EXACTES avec séparateur de milliers pour USD/DOP + la formule ⌈pct × Σ unités⌉ dont le pct == CLAUDE.md #9 et le total == Σ unités. Un claim absent échoue AUSSI (traçabilité).
État courant : aucun chiffre périmé (anti-invention #6, rien à réécrire) — le défaut est la surface ungated (module entièrement hors CI). 7 morsures vérifiées : README USD 8,560,000→9,560,000 (figure périmée) · README retire le séparateur de milliers (8,560,000→8560000) · README breakeven 21→20 (formule périmée) · README formule 52 %→55 % (dérive CLAUDE.md #9) · README supprime la ligne entière (INTROUVABLE) · fixture Studio qté 12→13 (5 morsures : units/USD/DOP/breakeven README périmés + manifeste) · fixture 2 Chambres prix_usd 320000→300000 (catalogue USD périmé) ; restauré = green : 4 figures == génération réelle · manifeste == recompute · pct 52 % == CLAUDE.md #9 · exit 0. Working tree byte-restauré via git checkout -- (JAMAIS git clean) · 7 gates re-verts. ci/README.md (ligne récap check-readme-claims) mis à jour · log 05_activity_log/2026-08-01.md. Auto-score 4Big 96/100.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>