[DTP-Worker 20260801_233454] Sprint 8 · buffer · RBAC SPEC §5 : gate de la LIGNE D'AUTO-CONTRÔLE du « résumé »
La SPEC RBAC a déjà 3 gates (§3 ventilation par portail · §4 colonne Entité · §7 run-book) mais son §5 « Les N rôles (résumé) » restait AVEUGLE. Ce §5 restitue le total de rôles sur 3 surfaces prose : le compte-titre « ## 5. Les 50 rôles », NEUF comptes parenthétiques de regroupement (`**Ventes (8)**` …) et une ligne d'auto-contrôle arithmétique `_(6+8+4+7+5+8+4+2+6 = 50.)_`. AJOUTER un rôle au contrat (|rôles| 50→51) laisse titre/somme/`= 50` périmés en silence ; ÉDITER `Ventes (8)→(7)` sans toucher la ligne casse la cohérence titre↔somme — ni les suites tests/ (FONCTIONS RBAC, jamais la prose) ni le byte-gate d'artefact ne l'attrapent. Subtilité (memory rbac-spec-portail-count-gate : « §5 by-family is editorial ») : les 9 regroupements sont ÉDITORIAUX (« Direction / Gouvernance » agrège des rôles de familles direction+finance ≠ colonne `famille`) ⇒ AUCUN mapping groupe↔famille (dérive fausse). On gate UNIQUEMENT ce qui est data-derived sans ce mapping. Nouveau bloc « 1septies) §5 » : on recompute N = |rôles| du contrat (rbac_50_roles.json, byte-gaté) et on exige (a) compte-titre == N ; (b) les 9 comptes de regroupement == EXACTEMENT dans l'ordre les termes de la ligne (comparaison de LISTES ⇒ mord valeur ET position) ; (c) Σ termes == membre droit ; (d) membre droit == N. Section/titre/ligne/comptes absents = échec (#6). 5 morsures vérifiées (working tree byte-restauré via git checkout -- <fichier>, gate rc=1 sous mutation · rc=0 restauré) : titre 50→51 (a) · Ventes (8)→(9) (b) · = 50.→= 49. (c+d double) · terme 6+→7+ (b+c double) · suppression ligne (absence). ci/README.md : row check-readme-claims étendue de la clause §5. 7 gates re-verts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
@@ -1377,6 +1377,78 @@ if src_roles is not None and spec_rd is not None:
|
||||
good(f"RBAC SPEC §4 · (c) les {len(cm4)} entités nommées du mandat sont "
|
||||
f"portées ≥1× par le contrat")
|
||||
|
||||
# 1septies) RBAC_50_ROLES_SPEC.md §5 — « Les N rôles (résumé) » : compte-titre,
|
||||
# comptes de regroupement éditoriaux et LIGNE d'auto-contrôle arithmétique -------
|
||||
# Le §5 « résumé » restitue le total de rôles sur TROIS surfaces prose qu'aucun
|
||||
# gate ne touchait — (i) le TITRE « ## 5. Les N rôles (résumé) », (ii) NEUF comptes
|
||||
# parenthétiques de regroupement (« **Ventes (8)** » …) et (iii) une LIGNE
|
||||
# d'auto-contrôle arithmétique « _(6+8+…+6 = 50.)_ ». Le §3 gate la ventilation par
|
||||
# PORTAIL, le §7 le run-book, le §4 les entités — TOUS aveugles à ce §5. NB : les 9
|
||||
# regroupements sont ÉDITORIAUX (« Direction / Gouvernance » agrège des rôles de
|
||||
# familles direction+finance ; ≠ la colonne `famille` du contrat, cf. memory
|
||||
# rbac-spec-portail-count-gate « §5 by-family is editorial ») → on NE mappe PAS
|
||||
# groupe↔famille (ce serait une dérive fausse). On gate ce qui EST data-derived et
|
||||
# vérifiable SANS ce mapping : (a) le compte-titre N == |rôles| du contrat (byte-
|
||||
# gaté par check_artifacts) ; (b) les 9 comptes de regroupement == EXACTEMENT, dans
|
||||
# l'ordre, les termes de la ligne arithmétique (cohérence interne prose↔somme) ;
|
||||
# (c) l'arithmétique est VRAIE (Σ termes == membre droit) ; (d) le membre droit ==
|
||||
# |rôles|. AJOUTER un rôle au contrat (|rôles| 50→51) laisse le titre, la somme et
|
||||
# le « = 50 » PÉRIMÉS en silence ; ÉDITER « Ventes (8) »→« (7) » sans toucher la
|
||||
# ligne casse (b) puis (c). Section/titre/ligne/comptes absents = échec (#6).
|
||||
if src_roles is not None and spec_rd is not None:
|
||||
N5 = len(src_roles)
|
||||
_m5 = re.search(r"## 5\..*?(?=## 6\.)", spec_rd)
|
||||
if _m5 is None:
|
||||
bad(f"RBAC SPEC §5 · section « ## 5. » INTROUVABLE dans {SPEC_RD} "
|
||||
f"(claim absent = régression #6)")
|
||||
else:
|
||||
sec5 = _m5.group(0)
|
||||
# (a) compte-titre « ## 5. Les N rôles »
|
||||
mt5 = re.search(r"## 5\. Les (\d+) rôles", sec5)
|
||||
if mt5 is None:
|
||||
bad(f"RBAC SPEC §5 · titre « ## 5. Les N rôles » INTROUVABLE dans {SPEC_RD}")
|
||||
elif mt5.group(1) == str(N5):
|
||||
good(f"RBAC SPEC §5 · (a) compte-titre {mt5.group(1)} == |rôles| "
|
||||
f"rbac_50_roles.json ({N5})")
|
||||
else:
|
||||
bad(f"RBAC SPEC §5 · (a) titre dit {mt5.group(1)} rôles MAIS le contrat "
|
||||
f"en compte {N5} → corriger la SPEC")
|
||||
# 9 comptes de regroupement (gras · « (N) » collant au **fermant)
|
||||
heads = [int(m.group(1)) for m in
|
||||
re.finditer(r"\*\*[^*]+?\((\d+)\)\*\*", sec5)]
|
||||
# ligne d'auto-contrôle « _(a+b+… = T.)_ »
|
||||
ma5 = re.search(r"_\(((?:\d+\+)+\d+) = (\d+)\.\)_", sec5)
|
||||
if ma5 is None:
|
||||
bad(f"RBAC SPEC §5 · ligne d'auto-contrôle « _(a+b+… = T.)_ » "
|
||||
f"INTROUVABLE dans {SPEC_RD} (claim absent = régression #6)")
|
||||
elif not heads:
|
||||
bad(f"RBAC SPEC §5 · aucun compte de regroupement « **… (N)** » trouvé "
|
||||
f"dans {SPEC_RD} (claim absent = régression #6)")
|
||||
else:
|
||||
addends = [int(x) for x in ma5.group(1).split("+")]
|
||||
rhs = int(ma5.group(2))
|
||||
# (b) comptes de regroupement == termes de la ligne, EN ORDRE
|
||||
if heads == addends:
|
||||
good(f"RBAC SPEC §5 · (b) {len(heads)} comptes de regroupement == "
|
||||
f"termes de la ligne d'auto-contrôle ({'+'.join(map(str, addends))})")
|
||||
else:
|
||||
bad(f"RBAC SPEC §5 · (b) comptes de regroupement {heads} ≠ termes de "
|
||||
f"la ligne {addends} (ordre/valeur) → aligner titres et somme")
|
||||
# (c) arithmétique vraie
|
||||
if sum(addends) == rhs:
|
||||
good(f"RBAC SPEC §5 · (c) Σ termes {'+'.join(map(str, addends))} = "
|
||||
f"{rhs} (arithmétique exacte)")
|
||||
else:
|
||||
bad(f"RBAC SPEC §5 · (c) la ligne écrit « = {rhs} » MAIS Σ termes = "
|
||||
f"{sum(addends)} → corriger la somme")
|
||||
# (d) membre droit == |rôles| du contrat
|
||||
if rhs == N5:
|
||||
good(f"RBAC SPEC §5 · (d) membre droit {rhs} == |rôles| "
|
||||
f"rbac_50_roles.json ({N5})")
|
||||
else:
|
||||
bad(f"RBAC SPEC §5 · (d) la ligne totalise {rhs} MAIS le contrat "
|
||||
f"compte {N5} rôles → SPEC périmée")
|
||||
|
||||
# 2) apply_plan — ligne « Génération réelle » agrégeant les 3 volets ------------
|
||||
AP_RD = f"{D}/rbac/apply_plan/README.md"
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user