[DTP-Worker] Sprint 8 · buffer · Fiscal/ecf_dgii (2e surface) : la CROSS-COHÉRENCE e-CF ↔ workflow ↔ DocType ↔ RBAC — le CŒUR du livrable — énumérait EN PROSE trois données data-derived (états qui ÉMETTENT un e-CF · champs Currency de base · FormaPago défaut ancrée sur CLAUDE.md #10/Cardnet) sans AUCUN gate d'IDENTITÉ. Le bloc e-NCF existant ne gate QUE le FORMAT de l'identifiant (E+tipo(2)+seq(10)=13) — jamais ces trois ensembles/valeur. Ils sont DATA-DERIVED de out/ecf_plan.json (byte-gaté par check_artifacts) : README:48 « seulement réservation et contrat » = {emission_events[].update_value} · README:50 « (montant_reservation, montant_contrat) » = {emission_events[].base_field} · README:59 « FormaPago défaut = 3 (Tarjeta) … via Cardnet (#10) » = forma_pago_defaut (ancré sur CLAUDE.md #10 : Cardnet = carte, pas Stripe). PIÈGE : check_artifacts ne prouve QUE ecf_plan==build (byte-for-byte) et le bloc racine ne gate QUE le compte de tests e-CF (« 39 ») → AJOUTER un évènement d'émission (facturer un devis) · en RETIRER un · RENOMMER un base_field · CHANGER forma_pago_defaut (Cardnet abandonné → code 2 Transfert) laissait la prose périmée pendant que l'artefact dit autre chose → l'agent ERPNext Backend câblerait le mauvais évènement / la mauvaise FormaPago (le risque même que la cross-cohérence veut prévenir) — « vert trompeur » qu'aucune suite tests/ (qui teste des FONCTIONS ncf/résolution, pas la prose) n'attrape. Même patron EXACT que la cross-cohérence CRM/Commissions déjà gatée (base_field + états soumis). Nouveau bloc « Fiscal cross-cohérence » dans ci/check_readme_claims.sh (après le bloc e-NCF) : (1) états émetteurs recomputés de emission_events[].update_value, prose exigée EXACTE (set-diff · accents NFKD) ; (2) champs de base recomputés de emission_events[].base_field, prose EXACTE ; (3) FormaPago défaut = forma_pago_defaut.code + libellé (⊆ catalogue) + ancrage Cardnet à proximité. Cohérences croisées en bonus (mordent un plan INTERNEMENT incohérent) : forma_pago_defaut.code ∈ catalogue formas_pago · libellé prose ⊆ libellé catalogue du code · ensembles NON VIDES. Un claim absent échoue AUSSI. 7 morsures vérifiées : prose retire contrat des émetteurs (absents=[contrat]) · prose renomme montant_contrat→montant_final (absents + en trop) · prose FormaPago 3→2 (drift artefact) · artefact forma_pago_defaut.code 3→2 (prose périmée) · artefact ajoute l'évènement devis (états ET base_field mordus · absents=[devis]) · FormaPago prose supprimée (INTROUVABLE) · artefact code→99 hors catalogue (incohérence interne) ; restauré = green : émetteurs [contrat,reservation] · base [montant_contrat,montant_reservation] · FormaPago 3 (Tarjeta) ancré Cardnet · 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 e-CF DGII ») mis à jour · working tree byte-restauré (git clean) · 7 gates re-verts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,53 @@
|
||||
# Activity Log · 2026-07-31 · Claude Code DTP
|
||||
|
||||
## Session `20260731_203134` · Buffer S8 · Domaine Fiscal/ecf_dgii (2e surface) : la **CROSS-COHÉRENCE e-CF ↔ workflow ↔ DocType ↔ RBAC** — le CŒUR du livrable — énumère EN PROSE trois données data-derived (états qui émettent un e-CF, champs Currency de base, **FormaPago défaut** ancrée sur CLAUDE.md #10/Cardnet) **sans aucun gate d'IDENTITÉ**. Le bloc e-NCF existant ne gate QUE le FORMAT de l'identifiant.
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||||
close ; poursuite de la série anti-dérive (CLAUDE.md #6). Même patron EXACT que la
|
||||
cross-cohérence CRM/Commissions déjà gatée (base_field + états soumis) — appliqué à
|
||||
la 2e surface data-derived du README `fiscal/ecf_dgii`, jamais gatée.
|
||||
|
||||
**Dérive silencieuse fermée** :
|
||||
- Source faisant autorité : `05_deliverables_mvp/fiscal/ecf_dgii/out/ecf_plan.json`
|
||||
(byte-gaté par `check_artifacts`). Trois claims du README étaient recopiés à la
|
||||
main sans recompute : README:48 « seulement **réservation et contrat** » =
|
||||
`{emission_events[].update_value}` · README:50 « (`montant_reservation`,
|
||||
`montant_contrat`) » = `{emission_events[].base_field}` · README:59 « **FormaPago
|
||||
défaut = 3 (Tarjeta)** … via **Cardnet** (#10) » = `forma_pago_defaut` (ancrée sur
|
||||
CLAUDE.md #10 — Cardnet = paiement carte, pas Stripe).
|
||||
- Piège : `check_artifacts` ne prouve QUE `ecf_plan == build` (byte-for-byte) et le
|
||||
bloc racine ne gate QUE le compte de tests e-CF (« 39 ») ; AJOUTER un évènement
|
||||
d'émission (facturer un devis), en RETIRER un, RENOMMER un `base_field` ou CHANGER
|
||||
`forma_pago_defaut` (Cardnet abandonné → code 2 Transfert) laissait la prose périmée
|
||||
pendant que l'artefact dit autre chose → l'agent ERPNext Backend câblerait le
|
||||
mauvais évènement / la mauvaise FormaPago (le risque même que la cross-cohérence
|
||||
veut prévenir). Aucune suite `tests/` (qui teste les FONCTIONS `ncf`/résolution,
|
||||
pas la prose) n'attrape ce « vert trompeur ».
|
||||
|
||||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « Fiscal cross-cohérence »
|
||||
après le bloc e-NCF) : (1) états émetteurs recomputés de `emission_events[].update_value`,
|
||||
prose exigée EXACTE (set-diff · accents normalisés NFKD) ; (2) champs de base recomputés
|
||||
de `emission_events[].base_field`, prose exigée EXACTE ; (3) FormaPago défaut =
|
||||
`forma_pago_defaut.code` + libellé (⊆ catalogue) + ancrage Cardnet exigé à proximité.
|
||||
Cohérences croisées en bonus (mordent un plan INTERNEMENT incohérent) :
|
||||
`forma_pago_defaut.code` ∈ catalogue `formas_pago` · libellé prose ⊆ libellé catalogue ·
|
||||
ensembles non vides. Un claim absent échoue AUSSI (traçabilité).
|
||||
|
||||
**7 morsures vérifiées** : prose retire `contrat` des émetteurs (absents=[contrat]) ·
|
||||
prose renomme `montant_contrat→montant_final` (absents + en trop) · prose FormaPago
|
||||
`3→2` (drift artefact) · artefact `forma_pago_defaut.code 3→2` (prose périmée) ·
|
||||
artefact ajoute l'évènement `devis` (états ET base_field mordus, absents=[devis]) ·
|
||||
FormaPago prose supprimée (INTROUVABLE) · artefact `code→99` hors catalogue
|
||||
(incohérence interne) ; restauré = green : émetteurs [contrat,reservation] · base
|
||||
[montant_contrat,montant_reservation] · FormaPago 3 (Tarjeta) ancré Cardnet · exit 0.
|
||||
Working tree byte-restauré (git clean) · **7 gates re-verts**.
|
||||
|
||||
- É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 e-CF
|
||||
DGII ») mis à jour.
|
||||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo).
|
||||
- **Auto-score 4Big** : 96/100.
|
||||
|
||||
## Session `20260731_200130` · Buffer S8 · Domaine Faisabilité/generator : les **paramètres canoniques** du générateur 4 volets (« `3 %` édition · `8.5 %` marketing · `52 %` point d'équilibre · `USD+DOP` · `Cardnet` · `Letter US` ») — la garantie anti-invention (#6) du module, imposée à CHAQUE faisabilité — étaient **RECOPIÉS** dans `genlib/model.py::CANONICAL` (dict émis dans chaque rendu, **hors `out/`** donc invisible à check_artifacts) **et** dans la prose README:28, **sans aucun ancrage** à leur source faisant autorité : les contraintes NON-NÉGOCIABLES **#9/#10 de CLAUDE.md**.
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||||
|
||||
+28
-1
File diff suppressed because one or more lines are too long
@@ -1675,6 +1675,112 @@ if encf is not None:
|
||||
re.search(r"`([A-Z])\s*\+\s*tipoeCF\((\d+)\)\s*\+\s*"
|
||||
r"secuencia\((\d+)\)`", ecf_fi), False)
|
||||
|
||||
# ============================================================================
|
||||
# Fiscal · e-CF DGII (2e surface du MÊME README) · la CROSS-COHÉRENCE
|
||||
# (« le cœur du livrable ») — ENSEMBLES/valeur data-derived transcrits À LA MAIN
|
||||
# sans AUCUN gate d'IDENTITÉ. Le bloc e-NCF ci-dessus ne gate QUE le FORMAT de
|
||||
# l'identifiant ; la section « Cross-cohérence e-CF ↔ workflow ↔ DocType ↔ RBAC »
|
||||
# ÉNUMÈRE trois données dérivées de out/ecf_plan.json (byte-gaté par
|
||||
# check_artifacts ⇒ faisant autorité) :
|
||||
# • README:48 « seulement réservation et contrat » — l'ensemble des états qui
|
||||
# ÉMETTENT un e-CF = {emission_events[].update_value}.
|
||||
# • README:50 « (`montant_reservation`, `montant_contrat`) » — l'ensemble des
|
||||
# champs Currency de base = {emission_events[].base_field}.
|
||||
# • README:59 « FormaPago défaut = 3 (Tarjeta) … via Cardnet (#10) » — le code +
|
||||
# libellé de forma_pago_defaut, ANCRÉ sur CLAUDE.md #10 (Cardnet = carte).
|
||||
# Aucun gate ne comparait ces valeurs à l'artefact : AJOUTER un évènement
|
||||
# d'émission (facturer un devis) · en RETIRER un · RENOMMER un base_field ·
|
||||
# CHANGER forma_pago_defaut (Cardnet abandonné → code 2 Transfert) ferait dériver
|
||||
# la prose en silence pendant que l'ecf_plan byte-gaté dit autre chose — l'agent
|
||||
# ERPNext Backend câblerait le mauvais évènement / la mauvaise FormaPago (le risque
|
||||
# même que la cross-cohérence veut prévenir) — « vert trompeur » qu'aucune suite
|
||||
# tests/ (qui teste des FONCTIONS ncf/résolution, pas la prose) n'attrape. Même
|
||||
# patron EXACT que la cross-cohérence CRM/Commissions (base_field + états soumis).
|
||||
# On RECOMPUTE chaque ensemble/valeur depuis l'artefact (zéro duplication du
|
||||
# contrat du générateur #6) et on exige que la prose l'encode EXACTEMENT (absent ET
|
||||
# en trop via set-diff · accents/casse normalisés). Cohérences croisées en bonus
|
||||
# (mordent un plan INTERNEMENT incohérent) : forma_pago_defaut.code ∈ catalogue
|
||||
# formas_pago · libellé prose ⊆ libellé catalogue du code · ensembles NON VIDES.
|
||||
# Un claim absent échoue AUSSI (traçabilité).
|
||||
# ============================================================================
|
||||
ECF_RD2 = f"{D}/fiscal/ecf_dgii/README.md"
|
||||
def _ecf_acc(s):
|
||||
return "".join(c for c in unicodedata.normalize("NFKD", s)
|
||||
if unicodedata.category(c) != "Mn").lower()
|
||||
try:
|
||||
ecfp = load("fiscal/ecf_dgii/out/ecf_plan.json")
|
||||
ecf_ev = ecfp["emission_events"]
|
||||
ecf_uv = {_ecf_acc(e["update_value"]) for e in ecf_ev}
|
||||
ecf_bf = {e["base_field"] for e in ecf_ev}
|
||||
ecf_fpd = ecfp["forma_pago_defaut"]
|
||||
ecf_fp_code = str(ecf_fpd["code"])
|
||||
ecf_fp_cat = {str(f["code"]): f["label"] for f in ecfp["formas_pago"]}
|
||||
except (OSError, KeyError, ValueError, TypeError) as e:
|
||||
bad(f"Fiscal cross-cohérence · artefact ecf_plan illisible/inattendu : {e}"); ecf_ev = None
|
||||
if ecf_ev is not None:
|
||||
# bonus : plan INTERNEMENT cohérent (ensembles non vides · défaut ∈ catalogue)
|
||||
if not ecf_uv or not ecf_bf:
|
||||
bad("Fiscal cross-cohérence · aucun évènement d'émission (plan vide) → vérifier le plan")
|
||||
elif ecf_fp_code not in ecf_fp_cat:
|
||||
bad(f"Fiscal cross-cohérence · forma_pago_defaut.code={ecf_fp_code} ABSENT du "
|
||||
f"catalogue formas_pago {sorted(ecf_fp_cat)} → plan incohérent")
|
||||
else:
|
||||
good(f"Fiscal cross-cohérence · forma_pago_defaut {ecf_fp_code} "
|
||||
f"({ecf_fp_cat[ecf_fp_code]}) ∈ catalogue formas_pago · émission {sorted(ecf_uv)} non vide")
|
||||
ecf_rd2 = read_norm(ECF_RD2)
|
||||
if ecf_rd2 is not None:
|
||||
# 1) README:48 — états émetteurs « seulement réservation et contrat »
|
||||
me = re.search(r"seulement\s+([^.]+)\.", ecf_rd2)
|
||||
if me is None:
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — énumération des états émetteurs "
|
||||
f"INTROUVABLE (attendu {sorted(ecf_uv)})")
|
||||
else:
|
||||
es = {_ecf_acc(t.strip()) for t in re.split(r"\bet\b|[,/]", me.group(1)) if t.strip()}
|
||||
if es == ecf_uv:
|
||||
good(f"Fiscal cross-cohérence · {ECF_RD2} — états émetteurs {sorted(es)} == "
|
||||
f"ecf_plan.emission_events[].update_value")
|
||||
else:
|
||||
miss = sorted(ecf_uv - es); extra = sorted(es - ecf_uv)
|
||||
detail = (f" · absents={miss}" if miss else "") + (f" · en trop={extra}" if extra else "")
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — énumère {sorted(es)} MAIS plan "
|
||||
f"{sorted(ecf_uv)}{detail} → régénérer le README")
|
||||
# 2) README:50 — champs de base « (`montant_reservation`, `montant_contrat`) »
|
||||
mf = re.search(r"Currency réel\*\* du DocType Dossier Vente\s*\(([^)]*)\)", ecf_rd2)
|
||||
if mf is None:
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — énumération des champs de base "
|
||||
f"INTROUVABLE (attendu {sorted(ecf_bf)})")
|
||||
else:
|
||||
bs = set(re.findall(r"`([a-z_]+)`", mf.group(1)))
|
||||
if bs == ecf_bf:
|
||||
good(f"Fiscal cross-cohérence · {ECF_RD2} — champs de base {sorted(bs)} == "
|
||||
f"ecf_plan.emission_events[].base_field")
|
||||
else:
|
||||
miss = sorted(ecf_bf - bs); extra = sorted(bs - ecf_bf)
|
||||
detail = (f" · absents={miss}" if miss else "") + (f" · en trop={extra}" if extra else "")
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — énumère {sorted(bs)} MAIS plan "
|
||||
f"{sorted(ecf_bf)}{detail} → régénérer le README")
|
||||
# 3) README:59 — FormaPago défaut « = 3 (Tarjeta) … via Cardnet (#10) »
|
||||
mp = re.search(r"FormaPago défaut\s*=\s*(\d+)\s*\(([^)]*)\)", ecf_rd2)
|
||||
if mp is None:
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — FormaPago défaut INTROUVABLE "
|
||||
f"(attendu code {ecf_fp_code} · {ecf_fp_cat.get(ecf_fp_code,'?')})")
|
||||
else:
|
||||
got_code = mp.group(1); got_lbl = _ecf_acc(mp.group(2).strip())
|
||||
cat_lbl = _ecf_acc(ecf_fp_cat.get(ecf_fp_code, ""))
|
||||
has_cardnet = "cardnet" in _ecf_acc(ecf_rd2[mp.start():mp.start() + 160])
|
||||
if got_code == ecf_fp_code and got_lbl and got_lbl in cat_lbl and has_cardnet:
|
||||
good(f"Fiscal cross-cohérence · {ECF_RD2} — FormaPago défaut {got_code} "
|
||||
f"({mp.group(2).strip()}) == forma_pago_defaut · ancré Cardnet (#10)")
|
||||
elif got_code != ecf_fp_code:
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — FormaPago défaut = {got_code} MAIS "
|
||||
f"forma_pago_defaut.code = {ecf_fp_code} → régénérer le README")
|
||||
elif not (got_lbl and got_lbl in cat_lbl):
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — libellé FormaPago {mp.group(2).strip()!r} "
|
||||
f"≠ catalogue code {ecf_fp_code} ({ecf_fp_cat.get(ecf_fp_code)!r}) → régénérer")
|
||||
else:
|
||||
bad(f"Fiscal cross-cohérence · {ECF_RD2} — FormaPago défaut sans ancrage "
|
||||
f"Cardnet (#10) à proximité → régénérer le README")
|
||||
|
||||
# ============================================================================
|
||||
# CRM/Commissions · barème vendeurs — la CROSS-COHÉRENCE (« cœur du livrable »)
|
||||
# transcrite À LA MAIN dans le README sans AUCUN gate d'IDENTITÉ.
|
||||
|
||||
Reference in New Issue
Block a user