[DTP-Worker] Sprint 8 · buffer L75 · Domaine Mobile (2e surface) : la ligne récap du README de l'app Expo ÉNUMÉRAIT À LA MAIN ses 5 onglets « (Ventes/Construction/Achat/Compta/Direction) » sans AUCUN gate d'IDENTITÉ. Le bloc mobile existant recompute le QUADRUPLET de la ligne (onglets · rôles couverts · langues · identifiants a_confirmer) depuis MANIFEST.counts, MAIS son patron du compte matche la parenthèse par \([^)]*\) et en IGNORE le contenu — surface data-derived distincte du MÊME README, même ligne. Cette liste dérive de mobile/app_config/out/role_navigation.json (byte-gaté par check_artifacts) : un onglet par portail métier du contrat RBAC (bijection 1 onglet ⇔ 1 portail, plateforme exclu), chaque entrée = son label « OTO <Nom> » ; nom court énuméré = label sans le préfixe « OTO ». Le bloc mobile ne gate QUE le COMPTE (« 5 onglets ») : un ÉCHANGE (Ventes→Marketing) laisse le compte à 5 — le compteur reste AVEUGLE — pendant que l'artefact dit autre chose ; un RETRAIT (Compta absent) fait tomber l'énumération à 4 tandis que « 5 onglets » reste juste ; un RÉORDRE passe aussi — « vert trompeur » qu'aucune suite tests/ (qui teste des FONCTIONS, pas la prose) n'attrape → nouveau bloc dans check_readme_claims recomputant la LISTE ORDONNÉE des noms courts depuis role_navigation (zéro duplication de la navigation du générateur #6) et exigeant que la parenthèse l'énumère EXACTEMENT. Contrôle par ENSEMBLE (absent ET en trop mordus via set-diff), puis ORDRE. Même patron que l'énumération des confirmations DevOps, la carte de renormalisation par archétype 4Big ou la table « Verdict courant » de l'audit 5D. Cohérence croisée en bonus : len(role_navigation) == MANIFEST.counts.onglets == MANIFEST.counts.portails (la bijection du générateur) — mord un compteur du manifeste désynchronisé de sa navigation. Un claim absent échoue AUSSI (4 morsures vérifiées : échange Ventes→Marketing capté là où le compte reste 5 · retrait Compta capté là où « 5 onglets » reste juste · réordre capté « même ensemble, ordre ≠ » · énumération supprimée = INTROUVABLE ; restauré = green : Ventes/Construction/Achat/Compta/Direction == role_navigation · bijection 5==onglets==portails). État courant : aucun onglet périmé (anti-invention #6, rien à réécrire) — le défaut est la surface ungated. ci/README.md (table + détail) mis à jour · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -886,6 +886,68 @@ if mob_exp is not None:
|
||||
bad(f"Mobile · {MOB_RD} — dit {'/'.join(m.groups())} MAIS MANIFEST dit "
|
||||
f"{'/'.join(mob_exp)} ({mob_src}) → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Mobile (2e surface) · ÉNUMÉRATION des onglets de l'app Expo — même README, même
|
||||
# ligne récap « **5 onglets** (Ventes/Construction/Achat/Compta/Direction) ».
|
||||
# ----------------------------------------------------------------------------
|
||||
# Le bloc mobile ci-dessus recompute le COMPTE d'onglets (« 5 ») mais son patron
|
||||
# ne mord QUE le nombre : la parenthèse qui ÉNUMÈRE les 5 portails est matchée par
|
||||
# `\([^)]*\)` et son CONTENU est IGNORÉ. Or cette liste est DATA-DERIVED : le
|
||||
# générateur app_config émet out/role_navigation.json (byte-gaté par
|
||||
# check_artifacts ⇒ artefact faisant autorité) = un onglet par portail métier du
|
||||
# contrat RBAC (bijection 1 onglet ⇔ 1 portail · `plateforme` exclu), chaque
|
||||
# entrée portant `portail` (id) + `label` (« OTO <Nom> »). Le nom court énuméré au
|
||||
# README = le label sans le préfixe « OTO ». Un ÉCHANGE (Ventes→Marketing), un
|
||||
# RETRAIT (Compta absent — l'énumération tombe à 4 tandis que « **5 onglets** »
|
||||
# reste juste) ou un RÉORDRE ferait dériver la prose EN SILENCE pendant que
|
||||
# l'artefact dit autre chose : « vert trompeur » aveugle au seul compte, qu'aucune
|
||||
# suite tests/ (qui teste des FONCTIONS, pas la prose) n'attrape — même patron que
|
||||
# l'énumération des confirmations DevOps, la carte de renormalisation par archétype
|
||||
# 4Big ou la table « Verdict courant » de l'audit 5D. On RECOMPUTE ici la LISTE
|
||||
# ORDONNÉE des noms courts depuis role_navigation.json (zéro duplication de la
|
||||
# navigation du générateur) et on exige que la parenthèse l'énumère EXACTEMENT
|
||||
# (absent ET en trop mordus, puis ordre). Cohérence croisée en bonus :
|
||||
# len(role_navigation) == MANIFEST.counts.onglets == MANIFEST.counts.portails (la
|
||||
# bijection du générateur) — mord un compteur du manifeste désynchronisé de sa
|
||||
# propre liste de navigation.
|
||||
# ============================================================================
|
||||
try:
|
||||
mob_nav = load("mobile/app_config/out/role_navigation.json")
|
||||
# nom court = label « OTO <Nom> » sans le préfixe « OTO » (ce que le doc copie)
|
||||
mob_names = [re.sub(r"^OTO\s+", "", e["label"]).strip() for e in mob_nav]
|
||||
mob_names_c = load("mobile/app_config/out/MANIFEST.json")["counts"]
|
||||
except (OSError, KeyError, ValueError, TypeError) as e:
|
||||
bad(f"Mobile · role_navigation/MANIFEST illisible/inattendu : {e}"); mob_names = None
|
||||
if mob_names is not None:
|
||||
# bijection : la liste de navigation == compteurs onglets ET portails du manifeste
|
||||
n_nav = len(mob_nav)
|
||||
if not (n_nav == mob_names_c.get("onglets") == mob_names_c.get("portails")):
|
||||
bad(f"Mobile · bijection rompue : |role_navigation|={n_nav} MAIS "
|
||||
f"MANIFEST onglets={mob_names_c.get('onglets')} "
|
||||
f"portails={mob_names_c.get('portails')} → régénérer l'artefact")
|
||||
else:
|
||||
good(f"Mobile · bijection onglet⇔portail : {n_nav} == onglets == portails")
|
||||
# énumération de la parenthèse : capturer le contenu entre ( ) qui suit « N onglets »
|
||||
mob_enum_pat = r"\*\*\d+ onglets\*\* \(([^)]*)\)"
|
||||
mob_txt2 = read_norm(MOB_RD)
|
||||
if mob_txt2 is not None:
|
||||
me = re.search(mob_enum_pat, mob_txt2)
|
||||
if me is None:
|
||||
bad(f"Mobile · {MOB_RD} — énumération des onglets INTROUVABLE "
|
||||
f"(attendu {'/'.join(mob_names)})")
|
||||
else:
|
||||
got = [s.strip() for s in me.group(1).split("/") if s.strip()]
|
||||
if got == mob_names:
|
||||
good(f"Mobile · {MOB_RD} — énumération onglets {'/'.join(got)} "
|
||||
f"== role_navigation")
|
||||
else:
|
||||
miss = [x for x in mob_names if x not in got]
|
||||
extra = [x for x in got if x not in mob_names]
|
||||
detail = (f" · absents={miss}" if miss else "") + \
|
||||
(f" · en trop={extra}" if extra else "") or " · même ensemble, ordre ≠"
|
||||
bad(f"Mobile · {MOB_RD} — énumère {got} MAIS role_navigation dit "
|
||||
f"{mob_names}{detail} → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# Legal · DocType CONFOTUR Application (champs / sections / rôles / évènements de
|
||||
# dépôt) — même classe de « vert trompeur », transcrit À LA MAIN dans DEUX docs.
|
||||
|
||||
Reference in New Issue
Block a user