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>
La ligne « Confirmations préalables VPS » du README `devops/deploy_runbook` annote
CHAQUE confirmation réglementaire d'un COUPLE data-derived `nom` (OWNER · RÉF-CONTRÔLE)
— ex. `taux_commission` (Direction · audit_5d D1.1) : QUI doit confirmer le paramètre
avant déploiement + QUEL contrôle qa/audit_5d le trace. Sources faisant autorité
(double, byte-gatées) : les `confirmations` de out/deploy_runbook.json (owner + source)
CROISÉES avec qa/audit_5d/out/audit_report.json (chaque control D#.# porte son propre
owner). Les blocs DevOps amont ne gataient que le COMPTE (2) et l'ENSEMBLE des noms —
AVEUGLES à QUI porte chaque confirmation et à QUEL contrôle la trace. Piège #6 :
réaffecter `taux_commission` de Direction à Ventes (mauvais responsable escaladé),
misattribuer le contrôle (D1.1→D2.1) ou citer un contrôle FANTÔME (D9.9) laisse la
prose périmée en silence pendant que l'artefact/l'audit disent autre chose → l'agent
DevOps escaladerait le mauvais owner / contrôle ; aucune suite tests/ (FONCTIONS de
graphe) n'attrape ce « vert trompeur ». État courant : aucune annotation périmée
(anti-invention #6), le défaut est la surface ungated.
Gate ajouté (ci/check_readme_claims.sh, bloc « 2ter ») : cross-anchor à trois — owner
run-book ⊆ owner du contrôle audit_5d cité (tolère le suffixe « / UAF ») · owner
README ⊆ owner run-book (tolère l'abréviation « Fiscaliste eCF » ⊂ « Compta Fiscaliste
eCF ») · réf README == contrôle réel présent DANS audit_5d ET dans la source. Une
confirmation tracée DOIT rester annotée (traçabilité #6) ; une annotation d'un nom
fantôme échoue AUSSI.
9 morsures vérifiées (README réaffecte owner · misattribue D1.1→D2.1 · contrôle
fantôme D9.9 · annotation retirée · artefact réaffecte owner = silent green · audit_5d
owner divergent · source cite contrôle fantôme · annotation nom fantôme · réf textuelle
absente de la source), restauré vert, 7 gates re-verts. ci/README.md (récap + paragraphe
« 3ᵉ surface deploy_runbook — imputabilité des confirmations ») mis à jour.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le champ que `Encabezado.TipoMoneda` porte dans chaque e-CF DGII —
`moneda.options = ["USD","DOP"]` — vit dans `ecf_spec.json` ET, byte-gaté par
check_artifacts, dans `out/ecf_plan.json`. C'est une valeur CANONIQUE de CLAUDE.md
#10 (« **USD + DOP** devises ») dont le README se réclame « #10 » (README:37/57/77).
Or byte-gater une constante prouve la REPRODUCTIBILITÉ, PAS l'ANCRAGE :
check_artifacts prouve ecf_plan==build depuis le spec, JAMAIS que spec[moneda]==#10.
Les blocs fiscaux amont gatent le FormaPago (Cardnet · #10) + états/champs
émetteurs, AVEUGLES au jeu de devises ; le bloc « Fiches #10 » ancre les fiches
ERPNext/CRM, AVEUGLE au module fiscal.
Piège #6 : RENOMMER/ÉTENDRE les devises dans CLAUDE.md #10 (`USD + DOP`→`USD + EUR`,
ou +`EUR`) ET dans le spec de façon cohérente reste byte-VERT tout en faisant
émettre à l'e-CF un `TipoMoneda` d'une devise qui CONTREDIT le mandat — « vert
trompeur » de la classe de la marque SEO §Entités, la persona Chat OTOIA ou les
tokens branding #4, qu'aucune suite tests/ (FONCTIONS de génération, jamais l'ancre
à CLAUDE.md) n'attrape. L'agent ERPNext Backend câblerait TipoMoneda hors mandat.
Correctif de déclaration : nouveau champ `moneda.options_source` (ecf_spec.json +
requis dans ecf.schema.json) citant « CLAUDE.md #10 — devises **USD + DOP** »,
DISTINCT de `source` (taux TipoCambio, reste null/a_confirmer côté VPS · #8).
Artefact régénéré (byte-gate re-verte · 39 tests module verts).
Gate ajouté (ci/check_readme_claims.sh, bloc « Fiscal · ecf_dgii — le JEU DE
DEVISES `moneda` … ANCRÉ sur CLAUDE.md #10 ») : RÉUTILISE exp["devises"] déjà
recomputé depuis #10 (zéro duplication) ; (a) spec[moneda].options == devises #10
ORDRE exact ; (b) artefact byte-gaté idem ; (c) options_source cite CLAUDE.md #10 +
chaque devise ; (d) prose README qui se réclame de #10 == jeu exact + toute mention
moneda/devise d'une paire concordante (scan ancré sur contexte, évite le faux
positif `RNC / ITBIS`). 7 morsures vérifiées (CLAUDE.md #10 rename = 4 bites en
cascade · spec options régénéré = le vrai silent green · artefact seul · reorder ·
options_source sans ancre · README ligne #10 · README table), restauré vert, 7
gates re-verts.
ci/README.md (clause récap + paragraphe « 4e surface du MÊME README ») mis à jour.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La version MAJEURE du SDK Expo que l'app compagnon cible (`expoSdkMajor`) est data-derived : `out/app_config.json.expo.extra.expoSdkMajor = 54` (byte-gaté par check_artifacts ⇒ faisant autorité), recopié dans `out/MANIFEST.json.app.expo_sdk_major`, dérivé de `mobile_spec.json[app].expo_sdk_major` dont la SOURCE FAISANT AUTORITÉ est la roadmap Sprint 5 l.56 « Rebuild Expo 54 » (le spec le DÉCLARE via `expo_sdk_source`). Le README:4/19/35/72 recopie « Expo 54 » CINQ fois À LA MAIN — dont la ligne de source « Expo SDK **54** | roadmap Sprint 5 l.56 ». Le bloc « Mobile · récap de l'app Expo » amont ne gate QUE le quadruplet onglets/rôles/langues/identifiants a_confirmer (comptes de MANIFEST.counts), AVEUGLE au majeur du SDK. Piège #6 : BUMPER le SDK (Expo 55 sort · eas build cible 55) dans le spec/artefact SANS toucher au README (ou l'inverse), ou DÉRIVER la roadmap de l'artefact, laisse la prose PÉRIMÉE en silence pendant que le graphe byte-gaté dit autre chose → l'agent Mobile lancerait `eas build` sur le MAUVAIS SDK (le rebuild même que la ligne roadmap prescrit) — « vert trompeur » qu'aucune suite tests/ (FONCTIONS de génération, jamais la prose ni l'ancre à la roadmap) n'attrape. Même patron d'ANCRAGE que la marque SEO §Entités (Helios RD ancrée sur CLAUDE.md) ou les roadmap_line de la recette, mais sur une valeur dont la roadmap — non CLAUDE.md — est l'INPUT faisant autorité.
Gate ajouté (bloc « Mobile · le SDK MAJEUR Expo … ANCRÉ sur la roadmap Sprint 5 l.56 ») : le majeur re-dérivé de app_config.json byte-gaté, puis (a) cohérence interne artefact ⇔ MANIFEST ⇔ spec ; (b) ancrage roadmap `Rebuild Expo <N>` == artefact (ancre vive) ; (c) le spec DÉCLARE l'ancrage (expo_sdk_source cite roadmap + Expo N) ; (d) TOUTE mention prose « Expo [SDK] N » == artefact (aucune périmée) ; (e) la ligne de source du tableau cite l'ancre roadmap. Un claim absent échoue AUSSI.
7 morsures vérifiées (README 54→55 prose périmée · artefact 54→55 README+roadmap périmés = le vrai silent green · roadmap Rebuild Expo 54→55 artefact périmé · MANIFEST 54→55 chaîne incohérente · spec expo_sdk_source sans roadmap · README ligne source sans roadmap · README retire toute mention Expo N), restauré vert (git checkout --, JAMAIS git clean), 7 gates re-verts. ci/README.md (table récap + paragraphe détaillé) mis à jour.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Les deux blocs CRM/workflow existants gatent le COMPTE (« 9 états · 11 transitions ») ET l'énumération des transitions à séparation des pouvoirs (allow_self_approval=0), jamais l'identité des GARDES. Sources faisant autorité (byte-gatées par check_artifacts) : out/workflow.json (chaque transition porte `allowed` = le rôle gardien) + out/MANIFEST.json.roles_rbac_utilises[].erpnext_role_name (recomputé du contrat rbac_50_roles.json à chaque build). PIÈGE : les blocs COMPTE/séparation sont AVEUGLES à l'identité des gardes → RÉAFFECTER un pas monétaire (« Confirmer réservation » Réservations→Conseiller = élévation de privilège) · RENOMMER un rôle · AJOUTER un fantôme · en OUBLIER un laissait le README périmé pendant que l'artefact dit autre chose → l'agent ERPNext Backend câblerait le mauvais garde (le risque même que la table veut prévenir) — « vert trompeur » qu'aucune suite tests/ (qui teste des FONCTIONS de graphe/résolution RBAC, pas la prose) n'attrape. Même patron d'IDENTITÉ que la cross-cohérence PERMISSIONS Legal/CONFOTUR déjà gatée.
Nouveau bloc « CRM gardes » dans ci/check_readme_claims.sh (après le bloc Démo scénarios) : (1) identité d'ensemble — colonne « Rôle » de la table == {allowed} de workflow.json (set-diff · NFKD/casefold) ; (2) cohérence artefacts — {allowed} == roles_rbac_utilises du MANIFEST (aucun garde hors manifeste ni l'inverse) · ensemble NON VIDE ; (3) cross-cohérence par pas — les gardes des étapes SENSIBLES et uniques Confirmer réservation/Signer contrat/Approuver CONFOTUR (recomputés `allowed`, jamais figés) nommés EXACTEMENT dans leur ligne. Le (3) mord la RÉAFFECTATION vers un rôle DÉJÀ présent (rôle servant deux transitions) que le set-diff seul manquerait. Un claim absent échoue AUSSI.
7 morsures vérifiées : README réaffecte Confirmer réservation→Conseiller (absents=[réservations] + pas mordu) · artefact réaffecte Signer contrat→Conseiller (en trop=[contrats] + incohérence MANIFEST + pas mordu) · README rôle fantôme (en trop=[oto fantome]) · README retire un rôle (absents=[direction commerciale]) · artefact MANIFEST perd un garde (garde pas dans MANIFEST=[réservations]) · table supprimée (INTROUVABLE) · artefact réaffecte Approuver CONFOTUR→Directeur (rôle déjà présent, set INCHANGÉ, captée UNIQUEMENT par la cross-cohérence par pas) ; restauré = green : 7 rôles · colonne == {allowed} == roles_rbac_utilises · 3 étapes sensibles pinnées · exit 0. État courant : aucun garde périmé (anti-invention #6, rien à réécrire) — le défaut était la surface ungated. ci/README.md (table + détail « 3e surface workflow_vente ») mis à jour · working tree byte-restauré (git checkout --, JAMAIS git clean) · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le bloc « apply_plan » existant de check_readme_claims.sh (bloc 2) ne gate QUE la
ligne AGRÉGÉE « Génération réelle » (8 comptes consolidés). Les 3 colonnes
d'identité de la table run-book (README:38-46) sont data-derived de
out/apply_plan.json (byte-gaté par check_artifacts) : # = order · Responsable =
responsable (worker/vps/worker+vps) · Dépend de = les n°s d'ordre des depends_on.
Elles étaient un WILDCARD. PIÈGE : check_artifacts ne prouve QUE apply_plan==build
(byte-for-byte) et le bloc de comptes est aveugle à l'identité des lignes → passer
le Responsable de l'étape 4 (worker+vps→vps) ou retirer une dépendance de l'étape 6
(4,5→4) laissait la prose périmée pendant que l'artefact dit autre chose. Un
responsable périmé (étape VPS attribuée au worker) ou une dépendance périmée (Role
Profile importé AVANT les Role) est un hazard réel — le risque même que le run-book
veut prévenir — qu'aucune suite tests/ (qui teste des fonctions, pas la table
commitée) n'attrape. Même classe que la colonne « Type » de roleprofile_gen et la
table demo/scenarios.
Nouveau sous-bloc « 2bis) apply_plan — TABLE Run-book » : (1) IDENTITÉ par étape —
chaque ligne porte EXACTEMENT #=order + Responsable=responsable + Dépend de=n°s
d'ordre des depends_on (deps extraits par digits ⇒ robuste au séparateur/em-dash) ;
colonne « Étape » libre (paraphrase). (2) IDENTITÉ d'ensemble — {ordres des lignes}
== {ordres artefact} sans doublon (aucune ligne FANTÔME, aucune étape MANQUANTE).
Cohérences croisées (mordent un plan INTERNEMENT incohérent) : ordres contigus 1..N ·
responsable ∈ {worker,vps,worker+vps} · toute dépendance pointe en ARRIÈRE
(n° < n° de l'étape). Un claim absent échoue AUSSI.
8 morsures vérifiées : README étape4 responsable worker+vps→vps (câblage) · README
étape6 Dépend de 4,5→4 (dep manquante) · README étape3 1,2→1,2,5 (dep fantôme) ·
ligne FANTÔME #7 (7≠6) · étape 5 SUPPRIMÉE (INTROUVABLE + 5≠6) · artefact étape2
responsable vps→worker (README stale) · artefact étape2 dep en AVANT (graphe
incohérent) · artefact étape1 responsable hors domaine (robot) ; restauré = green :
6 lignes == 6 étapes · responsables/deps == artefact · ordres 1..6 · exit 0.
État courant : aucune valeur périmée (anti-invention #6, rien à réécrire) — le
défaut est la surface ungated. ci/README.md (table + détail « 2ᵉ surface
rbac/apply_plan ») mis à jour · working tree byte-restauré · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le §« Cœur du livrable : cross-cohérence » →Permissions du README legal/confotur
énumère À LA MAIN, PAR rôle, role_id + portail + actions (« mot pour mot les
permissions_cibles RBAC … ni ajout ni retrait ») : `ventes-confotur` (Ventes)
→ read/write/create/print · `legal-onapi` (Direction) → read/write/create ·
`legal-directeur` (Direction) → read/write/**submit**/report. Le bloc CONFOTUR
existant ne gate QUE le COMPTE (« 3 rôles ») — AVEUGLE à leur identité.
Ces 3 lignes sont DATA-DERIVED d'out/MANIFEST.json (roles_rbac_utilises[] : role_id
· portail · permissions, recomputé du contrat rbac_50_roles.json à chaque build) et
projetées dans out/doctype_confotur_application.json (permissions[] par nom de rôle)
— les DEUX byte-gatés par check_artifacts. PIÈGE : le compte « 3 rôles » ne voit pas
l'identité → PROMOUVOIR ventes-confotur à submit (élévation de privilège cassant la
séparation des pouvoirs dont is_submittable est déduit) · RETIRER une action ·
RÉAFFECTER un portail · RENOMMER un rôle · AJOUTER une ligne fantôme laissait la
prose périmée pendant que les artefacts disent autre chose → l'agent ERPNext Backend
câblerait le mauvais jeu de permissions (le risque même que la cross-cohérence veut
prévenir) — « vert trompeur » qu'aucune suite tests/ (qui teste des FONCTIONS de
mapping RBAC, pas la prose) n'attrape. Même patron d'IDENTITÉ que le catalogue RBAC
fixtures_gen (singleton set_user_permissions) et la cross-cohérence e-CF DGII.
Nouveau bloc dans ci/check_readme_claims.sh (après le bloc de comptes CONFOTUR) :
(1) jeu d'actions + portail de CHAQUE rôle recomputés de roles_rbac_utilises[],
prose exigée EXACTE (set-diff · casse normalisée) ; (2) identité d'ensemble
README⇔MANIFEST (aucun rôle fantôme NI manquant). Cohérences croisées en bonus
(mordent un artefact INTERNEMENT incohérent) : MANIFEST ⇄ DocType d'accord sur le
jeu d'actions par rôle · séparation des pouvoirs — submit porté par EXACTEMENT un
rôle (legal-directeur) et is_submittable==True déduit de sa présence (README:31).
Un claim absent échoue AUSSI.
7 morsures vérifiées : README promeut ventes-confotur à submit (en trop=[submit]) ·
README réaffecte legal-onapi Direction→Ventes (portail) · README retire report de
legal-directeur (absents=[report]) · README renomme un role_id (fantôme=[legal-conseil]
+ manquant=[legal-onapi]) · énumération supprimée (INTROUVABLE) · artefact MANIFEST
promeut ventes-confotur à submit (README périmé + séparation cassée + incohérence
MANIFEST⇄DocType) · artefact DocType is_submittable=false alors qu'un rôle porte
submit (incohérence interne) ; restauré = green : 3 rôles portail+actions == MANIFEST
· identité d'ensemble · submit singleton · is_submittable=True · exit 0. État courant :
aucun jeu d'actions périmé (anti-invention #6, rien à réécrire) — le défaut est la
surface ungated. ci/README.md (table + détail « 2e surface CONFOTUR ») mis à jour ·
working tree byte-restauré (git checkout --, JAMAIS git clean) · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le README `demo/scenarios` porte une table « Scénario | Projet | Audience | Angle »
(README:10-13). Le bloc « Démo » existant de check_readme_claims ne gate QUE
counts.modules_cites_uniques (le compte de modules du diagramme) — ses trois colonnes
d'identité étaient des WILDCARDS, et les libellés projets sont déclarés (README:91-92)
« proviennent verbatim de CLAUDE.md · §Projets » sans AUCUN ancrage vérifié.
Ces colonnes sont DATA-DERIVED de out/run_sheet.json.scenarios[] (id · projet ·
projet_libelle · audience), byte-gaté par check_artifacts. Le générateur ne saisit
aucune donnée métier (résolution RFC 6901 depuis le disque) ; mais check_artifacts
ne prouve QUE run_sheet==build (byte-for-byte) et la source scenario_spec.json (map
projets) recopie les libellés À LA MAIN → toute la chaîne peut DÉRIVER de CLAUDE.md
en restant byte-verte. PREUVE : classer P07 sous audience=client dans le README →
check_readme_claims EXIT 0 (le gate ne voyait que 10==10 modules). Un couple
projet/audience faux ferait pitcher au présentateur le mauvais scénario — le risque
même que la run-sheet veut éliminer — « vert trompeur » qu'aucune suite tests/ (qui
teste des FONCTIONS de résolution, pas la prose) n'attrape.
Nouveau bloc « Démo scénarios » dans ci/check_readme_claims.sh : (1) ANCRAGE — chaque
`P{code} {libellé}` du run_sheet == entrée « ## Projets » de CLAUDE.md (verbatim ·
source unique · même esprit que le catalogue projets dossier_vente) ; (2) TABLE —
chaque ligne porte EXACTEMENT id + `P{code} {libellé}` + audience (fin du wildcard ·
patron identique à la colonne « Type » de roleprofile_gen) ; (3) IDENTITÉ d'ensemble
— {ids des lignes} == {ids du run_sheet} == counts.scenarios (aucune ligne FANTÔME,
aucun scénario MANQUANT). Cohérences croisées en bonus (mordent un artefact
INTERNEMENT incohérent) : run_sheet ↔ MANIFEST d'accord sur (id,projet,audience) ·
id == S-{projet}-{AUDIENCE} · counts.scenarios == |scenarios| · ids non vides/sans
doublon. Un claim absent échoue AUSSI.
8 morsures vérifiées : prose renomme un id (INTROUVABLE) · prose classe P07 sous
audience=client · prose met le mauvais libellé projet · ligne FANTÔME S-P99-GHOST
(en trop) · artefact libellé « Aqua Terra Bay » DÉRIVE de CLAUDE.md · run_sheet↔
MANIFEST désync audience · counts.scenarios=3 (≠|scenarios|=2) · ligne S-P05-CLIENT
supprimée (MANQUANT) ; restauré = green : 2 lignes == run_sheet == counts (2) ·
libellés == CLAUDE.md §Projets · exit 0. État courant : aucune valeur périmée
(anti-invention #6, rien à réécrire) — le défaut est la surface ungated. ci/README.md
(table + détail « 2e surface demo/scenarios ») mis à jour · working tree byte-restauré
· 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>