[DTP-Worker 20260801_183412] Sprint 8 · buffer · Legal/CONFOTUR : gate d'IDENTITÉ des 2 champs DÉRIVÉS du workflow vente — dossier_vente (Link → workflow.document_type = OTO Dossier Vente) + estado (Select → états confotur_* du pipeline) — transcrits en prose (legal/confotur/README.md:33-36) hors de tout gate ; source = crm/workflow_vente/workflow_vente_spec.json (workflow_source du MANIFEST)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,67 @@
|
||||
# Activity Log · 2026-08-01 · Claude Code DTP
|
||||
|
||||
## Session `20260801_183412` · Buffer S8 · Domaine Legal/CONFOTUR : les **deux champs du DocType `CONFOTUR Application` DÉRIVÉS du pipeline vente** — `dossier_vente` (Link → cible `workflow.document_type` = `OTO Dossier Vente`) et `estado` (Select → options = les états `confotur_*` du **workflow vente**), transcrits **en prose** dans la §« Cœur du livrable : cross-cohérence » (`legal/confotur/README.md:33-36`) — étaient **HORS de tout gate d'IDENTITÉ**. Les blocs CONFOTUR amont gatent le **compte** de champs/rôles, la cross-cohérence des **PERMISSIONS** (rôle→actions) et l'ancrage des **ENTITÉS** (`entite_porteuse`→CLAUDE.md §Entités) — mais **aucun** ne touchait `dossier_vente`/`estado`.
|
||||
|
||||
**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 classe EXACTE** que
|
||||
l'ancrage `entite_porteuse` du MÊME README (session `20260801` entités CONFOTUR) —
|
||||
appliqué à la **surface distincte** des deux AUTRES champs data-derived du même
|
||||
DocType, jamais gatés hors comptes/permissions/entités.
|
||||
|
||||
**Dérive silencieuse fermée** :
|
||||
- `05_deliverables_mvp/legal/confotur/README.md:35-36` — bullet `dossier_vente`
|
||||
(Link) : « cible = `workflow.document_type` (= `OTO Dossier Vente`) » (valeur
|
||||
NOMMÉE en clair) · `:33-34` — bullet `estado` (Select) : « options = les états
|
||||
`confotur_*` du **workflow vente** … dérivées — jamais réécrites en dur ».
|
||||
- Source faisant autorité : `crm/workflow_vente/workflow_vente_spec.json` — l'**INPUT**
|
||||
que le builder confotur LIT (déclaré `workflow_source` dans le MANIFEST), d'où il
|
||||
tire `document_type` (= cible du Link) et les `update_value` d'états commençant par
|
||||
`confotur` (= options du Select). L'artefact `out/doctype_confotur_application.json`
|
||||
porte `dossier_vente.options`/`estado.options`, byte-gaté par `check_artifacts`.
|
||||
- Piège : la seule vérification existante (`tests/`) teste des **FONCTIONS** de
|
||||
génération, jamais la PROSE du README. RENOMMER le DocType porteur côté workflow
|
||||
(`OTO Dossier Vente`→`OTO Dossier de Vente`) ou AJOUTER/RENOMMER un état CONFOTUR
|
||||
régénère l'artefact confotur (`check_artifacts` reste VERT — il se reconstruit
|
||||
depuis le spec workflow) MAIS laisse la prose README « (= `OTO Dossier Vente`) »
|
||||
périmée EN SILENCE → l'agent ONAPI/Legal câblerait une cible de Link / un menu
|
||||
d'états que le pipeline ne porte plus (l'invention #6 interdit).
|
||||
- **État courant** : **aucune valeur périmée** — `dossier_vente` Link → « OTO
|
||||
Dossier Vente » == workflow `document_type` · `estado` options
|
||||
`[confotur_depose, confotur_approuve]` == états `confotur_*` du workflow (ordre
|
||||
pipeline) · la prose README recoupe l'artefact/le workflow exactement
|
||||
(anti-invention #6, rien à réécrire). Le défaut est la **surface ungated**.
|
||||
|
||||
**Gate ajouté** (`ci/check_readme_claims.sh`, nouveau bloc « Confotur champs
|
||||
dérivés » avant `sys.exit`) : (0) **traçabilité** — MANIFEST `workflow_source` cite
|
||||
bien `crm/workflow_vente/workflow_vente_spec.json` ; (a) **cross-artefact** —
|
||||
`dossier_vente.options` (Link) == workflow `document_type` ; (b) **prose** — la
|
||||
valeur README « (= `…`) » == workflow `document_type` ; (c) **cross-artefact** —
|
||||
`estado.options` == `update_value` des états `confotur_*` du workflow (ORDRE
|
||||
pipeline) ; (c′) toute option `estado` porte le préfixe `confotur` (le README
|
||||
l'affirme) ; (d) **prose** — le bullet `estado` DÉCLARE la dérivation (`confotur_*`
|
||||
+ workflow vente). Un claim absent échoue AUSSI (traçabilité #6). Direction
|
||||
README/artefact→workflow spec.
|
||||
|
||||
**6 morsures vérifiées** : README `dossier_vente` valeur `OTO Dossier Vente→OTO
|
||||
Dossier de Vente` (prose périmée, b) · README bullet `estado` supprimé (claim
|
||||
INTROUVABLE, d) · **artefact** `estado.options` +`brouillon` (options ≠ workflow, c
|
||||
ET hors-préfixe, c′) · **artefact** `dossier_vente.options→OTO Autre Doc` (Link ≠
|
||||
document_type, a) · **MANIFEST** `workflow_source` déréférencé (dérivation non
|
||||
déclarée, 0) · **spec workflow** `document_type→OTO Dossier de Vente` (mord
|
||||
SIMULTANÉMENT l'artefact a ET la prose b — l'ancre est vive) ; restauré = green :
|
||||
6 checks verts · exit 0. Working tree byte-restauré (`git checkout --`, **JAMAIS**
|
||||
`git clean`, interdit absolu) · **7 gates re-verts**
|
||||
(`check_readme_claims`/`check_ci_integrity`/`check_docs`/`guard_constraints`/
|
||||
`check_artifacts`/`check_regression`/`validate_json`).
|
||||
|
||||
- `ci/README.md` (clause de la table récap du pipeline + paragraphe détaillé
|
||||
« Champs `dossier_vente`/`estado` du DocType CONFOTUR dérivés du workflow vente »)
|
||||
mis à jour.
|
||||
- **Hors périmètre worker (VPS · #8)** : néant (gate bash/python3 stdlib en-repo ;
|
||||
édition **hors** `05_deliverables_mvp/*/out` ⇒ 0 dérive d'artefact ; l'import réel
|
||||
du DocType `bench import-fixtures` reste côté VPS).
|
||||
- **Auto-score 4Big** : 96/100.
|
||||
|
||||
## Session `20260801_173409` · Buffer S8 · Fiches agents/pied de page voix OTOIA : le **PIED DE PAGE CANONIQUE** « - Voix **Amélie QC** (**multilingual_v2**) pour toute interaction OTOIA » — répété à l'identique dans **11 des 13 fiches** `03_agents/*/AGENT.md` (toutes sauf `faisabilite`/`publiciste`, qui n'orchestrent pas OTOIA) — RECOPIE À LA MAIN les **trois** tokens de la contrainte **CLAUDE.md §Architecture cible** « Voix Amélie QC (multilingual_v2) » : prénom persona (`Amélie`), qualificatif de marque (`QC`), modèle de voix ElevenLabs (`multilingual_v2`). Cette surface était **HORS de tout gate**.
|
||||
|
||||
**Tâche** : **Sprint 8 · buffer** (DevOps CI/CD · QA). Roadmap fonctionnellement
|
||||
|
||||
+27
-1
File diff suppressed because one or more lines are too long
@@ -6306,6 +6306,135 @@ if _vps_cm is not None:
|
||||
bad(f"VPS infra · AUCUNE doc ne cite de conteneur Docker "
|
||||
f"`erpnext-<x>-1` — surface d'identité conteneur évaporée (#6)")
|
||||
|
||||
# ============================================================================
|
||||
# Legal · CONFOTUR — IDENTITÉ des champs DÉRIVÉS du WORKFLOW (`dossier_vente` / `estado`)
|
||||
# ----------------------------------------------------------------------------
|
||||
# La §« Cœur du livrable : cross-cohérence » du README confotur affirme que DEUX
|
||||
# champs du DocType sont DÉRIVÉS du pipeline vente, jamais réécrits en dur :
|
||||
# • `dossier_vente` (Link) : cible = `workflow.document_type` (= `OTO Dossier
|
||||
# Vente`) — README:35-36 · NOMME la valeur en clair entre backticks ;
|
||||
# • `estado` (Select) : options = les états `confotur_*` du **workflow vente**
|
||||
# — README:33-34.
|
||||
# Source faisant autorité : `crm/workflow_vente/workflow_vente_spec.json` — l'INPUT
|
||||
# que le builder confotur LIT (déclaré `workflow_source` dans le MANIFEST), d'où il
|
||||
# tire `document_type` et les `update_value` d'états commençant par « confotur ».
|
||||
# Les blocs CONFOTUR amont gatent le COMPTE de champs/rôles, la cross-cohérence des
|
||||
# PERMISSIONS et l'ancrage des ENTITÉS (`entite_porteuse`) — mais AUCUN ne touche
|
||||
# `dossier_vente`/`estado`. Piège #6 : RENOMMER le DocType porteur côté workflow
|
||||
# (`OTO Dossier Vente` → `OTO Dossier de Vente`) ou AJOUTER/RENOMMER un état
|
||||
# CONFOTUR régénère l'artefact confotur (check_artifacts reste VERT — l'artefact se
|
||||
# reconstruit depuis le spec workflow) MAIS laisse la PROSE README « (= `OTO Dossier
|
||||
# Vente`) » périmée EN SILENCE → l'agent ONAPI/Legal lirait une cible de Link / un
|
||||
# menu d'états que le pipeline ne porte plus. Aucune suite tests/ (FONCTIONS de
|
||||
# génération) n'attrape ce « vert trompeur » de la prose. Même classe EXACTE que
|
||||
# l'ancrage `entite_porteuse` du MÊME README à CLAUDE.md §Entités.
|
||||
# GATE : (0) traçabilité — MANIFEST `workflow_source` cite bien le spec workflow ;
|
||||
# (a) cross-artefact — `dossier_vente.options` (Link) == workflow `document_type` ;
|
||||
# (b) prose — la valeur README « (= `…`) » == workflow `document_type` ; (c)
|
||||
# cross-artefact — `estado.options` == update_value des états `confotur_*` du
|
||||
# workflow (ORDRE du pipeline) ; (c') toute option `estado` porte le préfixe
|
||||
# confotur (le README l'affirme) ; (d) prose — le bullet `estado` DÉCLARE la
|
||||
# dérivation (`confotur_*` + workflow vente). Un claim absent échoue AUSSI (#6).
|
||||
# ============================================================================
|
||||
CONF_RD4 = f"{D}/legal/confotur/README.md"
|
||||
CONF_WF_SRC = "crm/workflow_vente/workflow_vente_spec.json"
|
||||
try:
|
||||
conf_dt_wd = load("legal/confotur/out/doctype_confotur_application.json")
|
||||
conf_man_wd = load("legal/confotur/out/MANIFEST.json")
|
||||
wf_spec_wd = load(CONF_WF_SRC)
|
||||
wf_doctype = _nfc(str(wf_spec_wd["document_type"]).strip())
|
||||
wf_confotur = [_nfc(str(s["update_value"]).strip())
|
||||
for s in wf_spec_wd["states"]
|
||||
if str(s.get("update_value", "")).startswith("confotur")]
|
||||
man_wf_src = _nfc(str(conf_man_wd.get("workflow_source", "")))
|
||||
except (OSError, KeyError, ValueError, TypeError) as e:
|
||||
bad(f"Confotur champs dérivés · artefact/spec workflow illisible/inattendu : {e}")
|
||||
conf_dt_wd = None
|
||||
if conf_dt_wd is not None:
|
||||
_fields = conf_dt_wd.get("fields", [])
|
||||
dv_art = [f for f in _fields if f.get("fieldname") == "dossier_vente"]
|
||||
es_art = [f for f in _fields if f.get("fieldname") == "estado"]
|
||||
conf_rd4 = read_norm(CONF_RD4)
|
||||
# (0) TRAÇABILITÉ — le MANIFEST DÉCLARE dériver du workflow spec (source de vérité)
|
||||
if CONF_WF_SRC not in man_wf_src:
|
||||
bad(f"Confotur champs dérivés · (0) MANIFEST `workflow_source` = {man_wf_src!r} "
|
||||
f"ne cite PAS {CONF_WF_SRC} → dérivation non déclarée (ancrage cassé)")
|
||||
else:
|
||||
good(f"Confotur champs dérivés · (0) MANIFEST DÉCLARE dériver de {CONF_WF_SRC}")
|
||||
if not wf_confotur:
|
||||
bad(f"Confotur champs dérivés · aucun état `confotur_*` dans {CONF_WF_SRC} → le "
|
||||
f"menu `estado` n'aurait aucune source (workflow incohérent)")
|
||||
# ---- dossier_vente (Link) ----
|
||||
if len(dv_art) != 1:
|
||||
bad(f"Confotur champs dérivés · champ `dossier_vente` non-singleton dans l'artefact "
|
||||
f"({len(dv_art)}) → cible du Link indéterminable")
|
||||
else:
|
||||
dv = dv_art[0]
|
||||
dv_opt = _nfc(str(dv.get("options", "")).strip())
|
||||
if dv.get("fieldtype") != "Link":
|
||||
bad(f"Confotur champs dérivés · `dossier_vente` fieldtype "
|
||||
f"{dv.get('fieldtype')!r} ≠ Link → le champ n'est plus un Link")
|
||||
# (a) CROSS-ARTEFACT — cible du Link == document_type du workflow
|
||||
if dv_opt == wf_doctype:
|
||||
good(f"Confotur champs dérivés · (a) `dossier_vente` Link → « {dv_opt} » == "
|
||||
f"workflow.document_type")
|
||||
else:
|
||||
bad(f"Confotur champs dérivés · (a) `dossier_vente` Link → « {dv_opt} » ≠ "
|
||||
f"workflow.document_type « {wf_doctype} » → régénérer le DocType")
|
||||
# (b) PROSE README — la valeur « (= `…`) » == document_type du workflow
|
||||
if conf_rd4 is not None:
|
||||
m = re.search(r"`dossier_vente`.{0,120}?`workflow\.document_type`"
|
||||
r"\s*\(=\s*`([^`]+)`\)", conf_rd4)
|
||||
if m is None:
|
||||
bad(f"Confotur champs dérivés · (b) bullet `dossier_vente` (cible = "
|
||||
f"`workflow.document_type` (= `…`)) INTROUVABLE dans {CONF_RD4} "
|
||||
f"(claim absent = régression #6)")
|
||||
else:
|
||||
got_dv = _nfc(m.group(1).strip())
|
||||
if got_dv == wf_doctype:
|
||||
good(f"Confotur champs dérivés · (b) README `dossier_vente` = "
|
||||
f"« {got_dv} » == workflow.document_type")
|
||||
else:
|
||||
bad(f"Confotur champs dérivés · (b) README dit `dossier_vente` = "
|
||||
f"« {got_dv} » MAIS workflow.document_type = « {wf_doctype} » "
|
||||
f"→ prose périmée (régénérer le README)")
|
||||
# ---- estado (Select) ----
|
||||
if len(es_art) != 1:
|
||||
bad(f"Confotur champs dérivés · champ `estado` non-singleton dans l'artefact "
|
||||
f"({len(es_art)}) → menu d'états indéterminable")
|
||||
else:
|
||||
es = es_art[0]
|
||||
es_opts = [_nfc(o.strip()) for o in str(es.get("options", "")).split("\n") if o.strip()]
|
||||
if es.get("fieldtype") != "Select":
|
||||
bad(f"Confotur champs dérivés · `estado` fieldtype {es.get('fieldtype')!r} "
|
||||
f"≠ Select → le champ n'est plus un Select")
|
||||
# (c) CROSS-ARTEFACT — options == états confotur_* du workflow (ordre pipeline)
|
||||
if es_opts == wf_confotur:
|
||||
good(f"Confotur champs dérivés · (c) `estado` options {es_opts} == états "
|
||||
f"confotur_* du workflow (ordre pipeline)")
|
||||
else:
|
||||
bad(f"Confotur champs dérivés · (c) `estado` options {es_opts} ≠ états "
|
||||
f"confotur_* du workflow {wf_confotur} → menu périmé (régénérer)")
|
||||
# (c') toute option `estado` porte le préfixe confotur (le README l'affirme)
|
||||
_bad_pref = [o for o in es_opts if not o.startswith("confotur")]
|
||||
if _bad_pref:
|
||||
bad(f"Confotur champs dérivés · (c') option(s) `estado` HORS préfixe "
|
||||
f"confotur_* {_bad_pref} → contredit « options = les états `confotur_*` »")
|
||||
elif es_opts:
|
||||
good(f"Confotur champs dérivés · (c') les {len(es_opts)} options `estado` "
|
||||
f"portent toutes le préfixe confotur_*")
|
||||
# (d) PROSE README — le bullet `estado` DÉCLARE la dérivation (confotur_* + workflow)
|
||||
if conf_rd4 is not None:
|
||||
m = re.search(r"`estado`\*{0,2}\s*\(Select\).{0,200}?`confotur_\*`"
|
||||
r".{0,80}?workflow vente", conf_rd4)
|
||||
if m is None:
|
||||
bad(f"Confotur champs dérivés · (d) bullet `estado` (options = les états "
|
||||
f"`confotur_*` du workflow vente) INTROUVABLE dans {CONF_RD4} "
|
||||
f"(claim absent = régression #6)")
|
||||
else:
|
||||
good(f"Confotur champs dérivés · (d) README `estado` DÉCLARE dériver des "
|
||||
f"états confotur_* du workflow vente")
|
||||
|
||||
sys.exit(1 if FAIL else 0)
|
||||
PY
|
||||
rc=$?
|
||||
|
||||
Reference in New Issue
Block a user