row_re du gate check_readme_claims §comptes-par-suite exigeait un lien …/README.md ;
la fiche erpnext_backend pointe rbac/ via RBAC_50_ROLES_SPEC.md (son point d'entrée
contrat), donc sa cellule « Tests | 10 | » échappait au recompute depuis
regression_plan.json. Mutation-test 10→99 : gate restait VERT (vrai angle mort,
classe « vert trompeur »). Extension : accepte tout *.md d'entrée du dossier module
(/[\w.-]+.md) ; le garde path-not-in-auth protège l'élargissement. rbac désormais
vue+mordue ; 7 gates verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le seul survivant en dur du paramètre canonique #9 (point d'équilibre 52 %)
vivait au cœur de l'oracle anti-invention de bancable_gen.py — alors que le
module PRÊCHE la source unique (deps.py « une seule source de vérité » ;
finance._pct « jamais codé en dur »). Transitivement protégé (donc gate
redondant, #5) mais BUG LATENT inverse : #9 52 %→55 % aurait fait rejeter
en silence un dossier bancable VALIDE. Fix = dériver le taux de
CANONICAL (finance._pct), pas un checker de plus.
Vérif : validate byte-identique à 52 % (pe=21) · 22 tests verts · preuve
levée du bug (source→55 % ⇒ pe=22, invariants OK) · 6 gates CI exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recompute le compte « 12 invariants » depuis le SEUL registre-source
(`# Invariant N ·` de `_validate_bundle`) — 4 surfaces prose hand-transcrites
(CLI .py, 2× README, docstring test) ancrées, aucune n'était gatée. Style de
marqueur `# Invariant N ·` + fonction `_validate_bundle` = deux différences
structurelles vs les 7 blocs `# N ·`/`_validate` précédents ; ajoute la surface
fichier-de-tests (b'). 4 verts arbre propre · 8 morsures adversariales · 6 gates
CI exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extension du bloc « RBAC fixtures » (points 4 & 5) : la 3e surface prose du fait
de sécurité set_user_permissions (SPEC §2 encadré + §6 row) était NON gatée. Le
test test_rbac impose scope/famille à tout détenteur mais jamais le NOM du rôle ni
la prose §2. Réutilise fx_sup (singleton déjà byte-gaté · pas de doublon d'unicité,
#5) comme nom-autorité + src_roles pour scope/famille.
Prouvé M6 SILENT-GREEN : rename détenteur dans le contrat + régen artefacts =>
check_artifacts VERT mais §2 name-gate RED (autorité = artefact, pas cohérence SPEC).
6 morsures adversariales, 6 gates re-verts exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nouvelle surface anti-dérive (#6) : la table §3 « Cartographie portails ↔
familles » porte deux colonnes data-derived du contrat ; « Nb rôles » était
gatée, « Familles rattachées » (SET des `famille` distinctes par portail) ne
l'était pas — le count-gate l'avale via `[^|]*`.
Gate « 1quater-bis » : recompute le SET de familles par portail depuis
rbac_50_roles.json[roles][].famille, égalité par ENSEMBLE (absent + fantôme)
avec les jetons bruts de la cellule (parenthèses éditoriales exclues, ordre
non gaté). Silent-green prouvé : reclasser les 2 rôles `legal` de `direction`
en `finance` garde le compte 9==9 VERT mais fait mordre FANTÔME {legal}.
6 verts arbre propre · 5 morsures adversariales · 6 gates re-verts exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le document-modèle CANONIQUE que toute faisabilité doit reproduire recopiait à la
main les 6 valeurs #9/#10 à 5 surfaces structurées, aucune gatée. Nouveau bloc
« TEMPLATE FAISABILITÉ CANONIQUE v1.0 » (réutilise exp/exp_excl déjà recomputés de
CLAUDE.md · zéro dup) : intro#9, 3 lignes table #9, intro#10, 3 lignes table #10
(+ exclusion ❌), checklist 6 marqueurs. 5 verts sur arbre propre · 11 morsures
adversariales dont M10/M11 (mutation CLAUDE.md #9/#10 SEULE ⇒ cascade sur 3 régions =
anchor-is-live). 6 gates exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le bloc « Fiscal · CONTRAT DE FORMAT » ancrait le format DGII
(E + tipoeCF(2) + secuencia(10) = 13 · Ley 32-23) sur ecf_plan.json[e_ncf]
byte-gaté, mais UNIQUEMENT sur 4 surfaces de PROSE (README x3 + fiche
erpnext_backend). Le composeur d'exécution ecflib/ncf.py — qui VALIDE et
COMPOSE réellement l'e-NCF cote VPS — portait 3 copies INDÉPENDANTES du
format (ENCF_RE regex de validation · FORMULE publiée par compose_encf ·
docstring/commentaire), + un oracle de test hardcodé, tous NON gatés.
Silent-green : un rango DGII a 12 chiffres régénère ecf_spec->ecf_plan (les
4 proses suivent) mais laisse ENCF_RE a {2}{10} => is_valid_encf REJETTE un
e-NCF valide (bug runtime) pendant que tests/ reste VERT (oracle == FORMULE
périmée). check_artifacts (pas un out/*.json) et tests/ (teste les fonctions,
pas leur ancrage) sont aveugles.
Gate : extension du bloc e-NCF (surfaces 5->9) réutilisant prefix/tipo/seq/
total + ecf_check déja dérivés (zéro re-dérivation du format · #6). 7 morsures
adversariales dont M6 SILENT-GREEN (artefact seq 10->12, ncf.py inchangé =>
les 5 surfaces mordent, autorité = artefact). 39 tests unittest verts. 6 gates
CI re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RECOMPUTE le ledger d'invariants depuis le SEUL registre-source (les `# N ·` de
`_validate` de audit_5d_gen.py) et gate les 6 transcriptions manuelles de « 15
invariants » (4 dans le .py, 2 dans le README), toutes invisibles à
check_artifacts. Ledger PROPRE 1..15 (schéma compté à part). Exige : (a) ledger
contigu 1..N (lacune/doublon nu mordu) ; (b) toute mention « N invariants » du
.py == |ledger| ; (d) toute mention README == |ledger|. Le distinct « 17
contrôles » est exclu nativement par l'ancre sur le mot « invariants » (aucun
faux positif). 6 morsures adversariales dont M3 (ajout `# 16 ·` mord .py+README,
preuve que l'autorité est le CODE) et M6 (« 17 contrôles » reste invisible).
6 gates re-verts exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5ᵉ instance de la classe « ledger d'invariants » (après Chat OTOIA · SEO ·
Fiscal e-CF · Legal CONFOTUR). Le compte « 12 invariants » de
crm/dossier_vente/doctype_dossier_vente_gen.py était transcrit à la main à
7 endroits (4 chaînes du .py + 3 du README : commande, titre « ## Les 12
invariants », prose de score), aucun gaté — invisibles à check_artifacts
(le .py n'est pas un out/*.json) et aux suites tests/ (qui testent des
fonctions, pas la prose). Ajouter un contrôle # 13 · sans toucher les 7
chaînes ⇒ CI applique 13 contrôles pendant que docs+self-reports disent 12
en silence (vert trompeur · #6).
Ledger PROPRE 1..12 (≈ CONFOTUR) : schéma compté à part (« schéma + N
invariants »), pas de schéma-#1 non marqué, pas de split a/b ; détection de
doublon nu conservée en filet. Le gate RECOMPUTE le ledger depuis le seul
registre-source (# N · de _validate) et exige (a) ledger contigu 1..N ;
(b) toute mention « N invariants » du .py == |ledger| ; (c) annonce du titre
README == |ledger| ; (d) toute mention README == |ledger| ; (e) énumération
numérotée de la section contiguë 1..N.
5 checks verts sur l'arbre propre. 7 morsures adversariales (M1 self-report
.py · M2 titre README · M3 prose README · M4 ajout # 13 · = ledger 13 vs
prose 12, mord .py+README+énumération = autorité au CODE · M5 gap # 7 · ·
M6 doublon nu # 5 · · M7 énumération 7→8). 6 gates re-verts exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4ᵉ application du pattern « ledger d'invariants » (après Chat OTOIA · SEO ·
Fiscal e-CF) à legal/confotur/confotur_application_gen.py. Le compte « 14
invariants » y est transcrit à la main à SIX endroits non gatés, tous
invisibles à check_artifacts (le .py n'est pas un out/*.json) : 4 chaînes du
.py (docstrings module + _validate, succès CLI, aide du sous-parseur) + 2 du
README (bloc de commande, commentaire d'arborescence). Ajouter un contrôle
# 15 · à _validate sans toucher les 6 chaînes ⇒ README + self-reports mentent
en silence pendant que la CI applique 15 contrôles — « vert trompeur » que ni
tests/ (FONCTIONS, pas la prose) ni le byte-gate d'artefact n'attrapent.
Particularité CONFOTUR (≠ Fiscal) : ledger PROPRE 1..14 (pas de schéma-#1 non
marqué, pas de split a/b) MAIS le README porte AUSSI un compte de SOUS-ENSEMBLE
éditorial (« 2 invariants refusent tout champ monétaire ») à ne pas confondre
avec le total — un \d+ invariants naïf mordrait l'arbre propre. Le gate exclut
le sous-ensemble par lookahead négatif (\d+)\s+invariants(?!\s+refusent),
appliqué au .py comme au README.
Nouveau bloc (ci/check_readme_claims.sh) : RECOMPUTE le ledger depuis le SEUL
registre-source (# N · de _validate) et exige (a) ledger CONTIGU 1..N (lacune
OU doublon nu = vrai défaut) ; (b) toute mention-total du .py == |ledger| ;
(c) toute mention-total du README (hors « refusent ») == |ledger|. 3 checks
verts sur l'arbre propre. 6 morsures vérifiées (M1 self-report .py 14→15 · M2
README commande 14→15 · M3 README arborescence 14→13 · M4 ajout # 15 · ⇒
ledger→15 vs prose 14, mord .py ET README · M5 gap # 7 · · M6 doublon nu # 5 ·)
+ M7 no-false-positive (sous-ensemble 2→3 reste vert). 6 gates re-verts exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3ᵉ application du pattern « ledger d'invariants » (après Chat OTOIA + SEO) : le
nombre magique « 12 invariants » du générateur fiscal ecf_dgii_gen.py est
transcrit à la main à 7 endroits (4 chaînes du .py : docstrings module/_validate
+ succès CLI + aide sous-parseur ; 3 du README : bloc commande + titre « ## Les
12 invariants » + prose de score), aucun gaté, tous invisibles à check_artifacts
(le .py source n'est pas un out/*.json). Ajouter un contrôle # 13 · à _validate
sans toucher les 7 chaînes = 13 contrôles appliqués pendant que README et
self-reports mentent en silence — vert trompeur qu'aucune suite tests/ (fonctions,
pas la prose) n'attrape.
Gate (bloc « Fiscal · e-CF DGII · IDENTITÉ du COMPTE D'INVARIANTS ») : RECOMPUTE
le ledger depuis le SEUL registre-source (# N · de _validate) et exige (a) ledger
CONTIGU 1..N ; (b) toute mention « N invariants » du .py == |ledger| ; (c) annonce
du titre README == |ledger| ; (d) toute mention README == |ledger| ; (e)
énumération numérotée prose du README contiguë 1..N. Particularité fiscale (≠
SEO/Chat OTOIA propres 1..N) : invariant 1 = validation de SCHÉMA non marquée
# 1 · (marqueurs 2..N), invariant 12 SPLITTÉ en # 12a ·/# 12b · (2 volets d'un
même invariant). Le ledger = {1:schéma} ∪ marqueurs-top-level, collapse 12a/12b
mais MORD un vrai doublon nu.
5 checks verts (ledger 1..12). 8 morsures : M1 self-report .py 12→13 (b) · M2
titre 12→13 (c+d) · M3 mention README 12→13 (d) · M4 ajout # 13 · ⇒ ledger→13
pendant que prose reste 12 (b+c+d, preuve que l'autorité est le CODE) · M5 drop
# 7 · = gap non contigu (a) · M6 doublon nu # 5 · · M7 énumération 7.→8. (e) ·
M8 drop validate(bundle, schema) = invariant 1 introuvable. 6 gates re-verts
(check_artifacts · check_docs · guard_constraints · check_ci_integrity ·
check_readme_claims · check_regression) exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le bloc Publiciste/branding existant ancre les 4 tokens DESIGN (#4 : couleurs +
typographies). Le MÊME module porte une 2e constante constitutionnelle NON gatée :
les devises CLAUDE.md #10 (« **USD + DOP** »), recopiées à 4 endroits data-derived,
tous invisibles à check_artifacts (pas un out/*.json) : (a) branding.py
DEVISE_PRIMAIRE/SECONDAIRE (auto-étiquetées « #10 · USD + DOP » sans gate) ; (b)
generator.py _fmt_usd/_fmt_dop — les formateurs qui IMPRIMENT le code devise sur
la grille de prix du site public vente.otov7.com (sortie face-public) ; (c) footer
HTML « Prix … en USD + DOP (Cardnet) » ; (d) l'oracle hardcodé
assertIn("USD 150 000") du test — une copie jamais comparée à CLAUDE.md. Aucune
suite tests/ (FONCTIONS de rendu, pas l'ancre à CLAUDE.md) n'attrape la dérive.
Nouveau bloc : RE-PARSE les 2 devises depuis la ligne #10 de CLAUDE.md
(indépendamment de exp amont · aucun skip hérité), exige (a) constantes branding ==
#10 ordre inclus ; (b) ensemble des codes émis par les formateurs == #10 ; (c)
footer cite les 2 devises dans l'ordre + (Cardnet) ; (d) oracle test == devise
primaire. Claim absent échoue AUSSI (#6). 6 morsures vérifiées (M5 : rename #10
CLAUDE.md-only cascade sur les 4 copies = preuve ancre live), 4 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>