[DTP-Worker 20260802_070524] Sprint 8 · buffer · Mobile app_config : gate d'IDENTITÉ du COMPTE D'INVARIANTS de _validate_bundle (8ᵉ instance de la classe ledger)
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>
This commit is contained in:
@@ -8523,6 +8523,129 @@ if cmi_src is not None:
|
||||
bad(f"Commissions invariants · {CMI_RD} — énumération prose {cmi_enum} "
|
||||
f"≠ 1..{cmi_ninv} (item sauté/dupliqué) → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Mobile · app_config · IDENTITÉ du COMPTE D'INVARIANTS de `_validate_bundle` —
|
||||
# 8ᵉ instance de la classe « ledger d'invariants » (après Chat OTOIA · SEO ·
|
||||
# Fiscal e-CF · Legal CONFOTUR · CRM Dossier Vente · QA Audit 5D · CRM
|
||||
# Commissions), appliquée au générateur de la config app mobile (roadmap Sprint 5
|
||||
# l.56-57 « Rebuild Expo 54 + submit »).
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le générateur app_config_gen.py applique un COMPTE d'invariants de cohérence
|
||||
# (onglets=portails RBAC · rôles=surface exacte · marque #4 · devises #10 · Expo
|
||||
# SDK · anti-invention a_confirmer · déterminisme…) dont la source d'autorité
|
||||
# n'est PAS un artefact JSON (invisible à check_artifacts qui byte-gate les
|
||||
# out/*.json) mais le LEDGER NUMÉROTÉ de `_validate_bundle` : les marqueurs
|
||||
# `# Invariant N ·` (1..12) qui ouvrent chaque contrôle. Le nombre « 12 » est
|
||||
# transcrit À LA MAIN à QUATRE endroits qu'AUCUN gate ne couvrait : UNE chaîne du
|
||||
# .py (message de succès CLI « … schéma + 12 invariants verts »), DEUX du README
|
||||
# (bloc de commande « schéma + 12 invariants », prose de récap « Schéma + 12
|
||||
# invariants verts » — le « 12 » et le mot séparés par un saut de ligne) + UNE du
|
||||
# fichier de tests (docstring « … + les 12 invariants du CLI »). Ajouter un
|
||||
# contrôle `# Invariant 13 ·` à `_validate_bundle` sans toucher ces chaînes ⇒ le
|
||||
# README, le self-report CLI ET la docstring de test mentent en silence pendant
|
||||
# que la CI applique 13 contrôles — « vert trompeur » (#6) que ni les suites
|
||||
# tests/ (qui EXÉCUTENT la validation mais ne comptent jamais la prose) ni le
|
||||
# byte-gate d'artefact (aveugle au .py source) n'attrapent.
|
||||
# PARTICULARITÉS vs les 7 blocs précédents :
|
||||
# · le REGISTRE-source utilise le style `# Invariant N ·` (le mot « Invariant »
|
||||
# précède le numéro) — les blocs Chat OTOIA/SEO/Fiscal/CONFOTUR/Dossier/Audit
|
||||
# 5D/Commissions ancrés sur le style nu `# N ·` NE le voient PAS ; on ancre
|
||||
# donc sur `#\s*Invariant\s+(\d+)…` ;
|
||||
# · la fonction s'appelle `_validate_bundle` (pas `_validate`) — l'ancre `def
|
||||
# _validate\b` des autres blocs ne matche pas (`\b` échoue avant `_bundle`) ;
|
||||
# · ledger PROPRE 1..N compté À PART du schéma (phrasé « schéma + N invariants »)
|
||||
# — pas de schéma-#1 non marqué, pas de split a/b ; on garde le filet doublon
|
||||
# nu ;
|
||||
# · ce README n'a NI titre « ## Les N invariants » NI énumération numérotée du
|
||||
# ledger → on gate (a)(b)(b')(d), en AJOUTANT la surface fichier-de-tests (b')
|
||||
# absente des blocs précédents (leurs tests ne portaient pas le chiffre).
|
||||
# On RECOMPUTE le ledger depuis le SEUL registre-source (les `# Invariant N ·` de
|
||||
# `_validate_bundle`) et on exige : (a) ledger CONTIGU 1..N (lacune OU doublon nu
|
||||
# = vrai défaut de registre, mordu) ; (b) TOUTE mention « N invariants » du .py ==
|
||||
# |ledger| ; (b') TOUTE mention « N invariants » du fichier de tests == |ledger| ;
|
||||
# (d) TOUTE mention « N invariants » du README == |ledger|. Mention ou registre
|
||||
# absent = échec (disparition d'un chiffre = régression de traçabilité #6).
|
||||
# ============================================================================
|
||||
MBI_GEN = f"{D}/mobile/app_config/app_config_gen.py"
|
||||
MBI_RD = f"{D}/mobile/app_config/README.md"
|
||||
MBI_TS = f"{D}/mobile/app_config/tests/test_mobile_app_config.py"
|
||||
try:
|
||||
mbi_src = open(MBI_GEN, encoding="utf-8").read()
|
||||
except OSError as e:
|
||||
bad(f"Mobile invariants · générateur {MBI_GEN} illisible : {e}"); mbi_src = None
|
||||
if mbi_src is not None:
|
||||
_mfn = re.search(r"def _validate_bundle\b", mbi_src)
|
||||
if _mfn is None:
|
||||
bad(f"Mobile invariants · fonction `_validate_bundle` INTROUVABLE dans {MBI_GEN} "
|
||||
"(registre-source du ledger absent → impossible de re-dériver)")
|
||||
else:
|
||||
_bs = _mfn.end()
|
||||
_mn = re.search(r"\ndef ", mbi_src[_bs:])
|
||||
_body = mbi_src[_bs: _bs + _mn.start()] if _mn else mbi_src[_bs:]
|
||||
_pairs = re.findall(r"#\s*Invariant\s+(\d+)([a-z]?)\s*·", _body)
|
||||
_dup_bare = sorted({n for n in {p[0] for p in _pairs}
|
||||
if [s for num, s in _pairs if num == n and s == ""]
|
||||
and sum(1 for num, _ in _pairs if num == n) > 1})
|
||||
_top = sorted({int(n) for n, _ in _pairs})
|
||||
if not _top:
|
||||
bad(f"Mobile invariants · aucun marqueur `# Invariant N ·` dans `_validate_bundle` "
|
||||
f"de {MBI_GEN} (ledger vide → impossible de re-dériver)")
|
||||
elif _dup_bare:
|
||||
bad(f"Mobile invariants · marqueur(s) `# Invariant N ·` dupliqué(s) sans suffixe "
|
||||
f"a/b dans `_validate_bundle` : {_dup_bare} — vrai doublon de registre")
|
||||
else:
|
||||
mbi_ninv = len(_top)
|
||||
if _top != list(range(1, mbi_ninv + 1)):
|
||||
bad(f"Mobile invariants · ledger `_validate_bundle` NON contigu : {_top} "
|
||||
f"(attendu 1..{mbi_ninv}) — lacune/doublon dans les marqueurs `# Invariant N ·`")
|
||||
else:
|
||||
good(f"Mobile invariants · ledger `_validate_bundle` contigu 1..{mbi_ninv} "
|
||||
f"({mbi_ninv} marqueurs `# Invariant N ·` · schéma compté à part)")
|
||||
# (b) self-report(s) du .py « N invariants ».
|
||||
mbi_py_rep = sorted({int(x) for x in re.findall(r"(\d+)\s+invariants", mbi_src)})
|
||||
if not mbi_py_rep:
|
||||
bad(f"Mobile invariants · aucune mention « N invariants » dans {MBI_GEN} "
|
||||
f"(self-report absent → attendu {mbi_ninv})")
|
||||
elif mbi_py_rep == [mbi_ninv]:
|
||||
good(f"Mobile invariants · {MBI_GEN} — self-report(s) {mbi_py_rep} "
|
||||
f"== ledger ({mbi_ninv})")
|
||||
else:
|
||||
bad(f"Mobile invariants · {MBI_GEN} — self-report(s) « N invariants » "
|
||||
f"{mbi_py_rep} MAIS ledger en compte {mbi_ninv} "
|
||||
"(une chaîne du générateur désynchronisée du registre)")
|
||||
# (b') self-report du fichier de tests « N invariants » (docstring).
|
||||
try:
|
||||
mbi_ts_raw = open(MBI_TS, encoding="utf-8").read()
|
||||
except OSError as e:
|
||||
bad(f"Mobile invariants · {MBI_TS} illisible : {e}"); mbi_ts_raw = None
|
||||
if mbi_ts_raw is not None:
|
||||
mbi_ts_rep = sorted({int(x) for x in re.findall(r"(\d+)\s+invariants", mbi_ts_raw)})
|
||||
if not mbi_ts_rep:
|
||||
bad(f"Mobile invariants · aucune mention « N invariants » dans {MBI_TS} "
|
||||
f"(self-report tests absent → attendu {mbi_ninv})")
|
||||
elif mbi_ts_rep == [mbi_ninv]:
|
||||
good(f"Mobile invariants · {MBI_TS} — docstring {mbi_ts_rep} "
|
||||
f"== ledger ({mbi_ninv})")
|
||||
else:
|
||||
bad(f"Mobile invariants · {MBI_TS} — docstring « N invariants » "
|
||||
f"{mbi_ts_rep} MAIS ledger en compte {mbi_ninv} → régénérer la docstring")
|
||||
# (d) toute mention « N invariants » du README == ledger.
|
||||
try:
|
||||
mbi_rd_raw = open(MBI_RD, encoding="utf-8").read()
|
||||
except OSError as e:
|
||||
bad(f"Mobile invariants · {MBI_RD} illisible : {e}"); mbi_rd_raw = None
|
||||
if mbi_rd_raw is not None:
|
||||
mbi_rd_rep = sorted({int(x) for x in re.findall(r"(\d+)\s+invariants", mbi_rd_raw)})
|
||||
if not mbi_rd_rep:
|
||||
bad(f"Mobile invariants · aucune mention « N invariants » dans {MBI_RD} "
|
||||
f"(self-report README absent → attendu {mbi_ninv})")
|
||||
elif mbi_rd_rep == [mbi_ninv]:
|
||||
good(f"Mobile invariants · {MBI_RD} — mention(s) {mbi_rd_rep} "
|
||||
f"== ledger (aucune dérive)")
|
||||
else:
|
||||
bad(f"Mobile invariants · {MBI_RD} — mention(s) « N invariants » "
|
||||
f"{mbi_rd_rep} MAIS ledger en compte {mbi_ninv} → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Traçabilité roadmap · le `roadmap_ref` VERBATIM des artefacts — la CITATION
|
||||
# (n° de ligne + « libellé bullet ») ANCRÉE sur la ligne RÉELLE de la roadmap,
|
||||
|
||||
Reference in New Issue
Block a user