Files
oto-enterprise-os-dtp/05_activity_log/2026-07-30.md
T
Claude Code DTP Worker a517619432 [DTP-Worker] Sprint 7 · Générateur Audit 4Big qualité (95+/100 sur 100% deliverables) (QA · roadmap L69)
Audit de méta-niveau + gate : note la qualité 4Big de 100% des livrables gated
et bloque (FAIL) si un module < 95/100 (CLAUDE.md #5). Couverture PROUVÉE par
recoupement bijectif registre ↔ working-directory du CI (moins l'auditeur · SoD
ISA 315). 5 critères déterministes (DOC/CONTRAT/TESTS/CLI/HANDOFF) renormalisés
par archétype. Anti-invention (#6) : chaque note est recalculée depuis des faits
du dépôt, jamais saisie ; un invariant recompute chaque note.

Résultat : PASS · 17/17 modules à 100/100. Régression 442 tests verts (+34).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-30 10:11:02 +00:00

465 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Activity Log · 2026-07-30 · Claude Code DTP
## Session `20260730_095728` (session 20)
**Tâche** : **Sprint 7 · QA** — Générateur de l'**Audit 4Big qualité** (roadmap
**L69** « QA : **Audit 4Big niveau 95+/100 sur 100% deliverables** »). Premier
volet Sprint 7 réalisable en repo — les volets polish `otov7.com` (Frontend) et
scénarios démo P07/P05 (CRM+Faisabilité) dépendent du site live / `data_room`
réelle (hors périmètre worker · #8).
**Décision d'architecture** : audit de **MÉTA-NIVEAU** et **gate** (pas rapport
indicatif). Il note la qualité 4Big de **100 % des livrables** et **bloque**
(verdict `FAIL`) si un module tombe sous **95/100** (CLAUDE.md #5) ou si la
couverture est incomplète. La couverture est **prouvée, pas déclarée** : le
registre est recoupé **bijectivement** avec les `working-directory` du CI Gitea,
moins l'auditeur lui-même (**séparation des pouvoirs** · ISA 315). 5 critères
déterministes : `DOC` · `CONTRAT` (schema) · `TESTS` (≥8 méthodes) · `CLI`
(argparse+`__main__`) · `HANDOFF` (`out/` intègre), renormalisés par archétype.
**Fichiers créés**`05_deliverables_mvp/qa/audit_4big/` :
- `quality_spec.json` (rubrique 5 critères + poids · seuil 95 verbatim · 4
archétypes · registre 17 modules sourcés)
- `q4lib/{__init__,deps,registry,criteria,scoring,builder}.py` (`deps`
**réutilise** le validateur maison Publiciste · `registry` parse `ci.yml` et
prouve la couverture · `criteria` purs lus depuis le dépôt · `scoring`
renormalise par archétype · `builder` déterministe)
- `audit_4big_gen.py` (CLI `build`/`validate` · **9 familles d'invariants**)
- `quality.schema.json` (contrat de sortie draft-07)
- `out/{quality_report,MANIFEST}.json` (hand-off) · `tests/test_audit_4big.py`
(**34 tests** dont 15 injections négatives sur arbre synthétique) · `README.md`
· `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `qa-audit-4big-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : une note **ne peut pas être fabriquée « pour
faire 95 »** — elle est **recalculée** depuis des faits (fichiers, taille,
comptage `test_*`, validité JSON du hand-off) ; un invariant re-somme les poids et
recompute chaque note (`INV6`) ; l'auditeur est **hors de son propre périmètre**
(SoD · `INV4`) ; seuil 95 repris verbatim de CLAUDE.md #5.
**Résultat** : verdict `PASS`**17/17 modules à 100/100** · pass-rate 100 % ·
couverture 100 % des livrables gated. Valeur = **gate anti-régression** (15 tests
négatifs prouvent la chute sous 95 en cas de dégradation).
**Vérifs** : 34/34 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **442 tests verts** au total (408 → +34) ; build déterministe.
**Hors périmètre worker (VPS · #8)** : publication du rapport dans le desk ERPNext
+ branchement du gate 4Big sur le pipeline de release VPS → agent QA / DevOps.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session20.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session20.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_092724` (session 19)
**Tâche** : **Sprint 6 · ERPNext Backend** — Générateur du **Chat OTOIA embarqué
par portail** (roadmap **L63** « ERPNext Backend : **Chat OTOIA embedded dans chaque
portail** »). Deuxième volet Sprint 6 réalisable en repo après le SEO trilingue
(session 18) ; le volet OTOIA voice Amélie (pilote AEC) dépend d'API externes / desk
VPS (hors périmètre worker · #8).
**Décision d'architecture (#1 ERPNext natif)** : dans ERPNext v15, un bloc de contenu
réutilisable inséré dans un `Workspace` **EST** le DocType `Custom Block` → on livre
**un `Custom Block` par portail** (un `<div>` de montage) + la **config runtime**
(`chat_mount.json`), pas de framework de chat externe. Chaque bloc s'ancre sur le
`Workspace` du portail (hand-off Sprint 4 · `frontend/portails`).
**Fichiers créés**`05_deliverables_mvp/frontend/chat_otoia/` :
- `chat_spec.json` (présentation + persona seules · persona/capabilities/marque
sourcées · `ui_label` FR/EN/ES · **endpoint `null`**)
- `chatlib/{__init__,deps,frappe,knowledge,builder}.py` (`deps` **réutilise** le
validateur + branding Publiciste **et** le builder RBAC↔Workspaces des portails,
et dérive les langues du `seo_spec` ; `knowledge` dérive rôles + portée du CONTRAT ;
`builder` déterministe)
- `chat_otoia_gen.py` (CLI `build`/`validate` · **14 invariants**)
- `chat.schema.json` (contrat de sortie draft-07)
- `out/{custom_block,chat_mount,MANIFEST}.json` (hand-off) · `tests/test_chat_otoia.py`
(**31 tests** dont 11 injections négatives) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `chat-otoia-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : **endpoint OTOIA = `null` (`a_confirmer`)** — jamais
fabriqué (invariant refuse tout endpoint non-null et toute URL dans le HTML) ; **portée
de connaissance = surface RBAC EXACTE du portail** (l'assistant ne peut exposer un
DocType hors périmètre — ajout/retrait rejeté) ; **rôles autorisés synchronisés avec
les Has Role réels des Workspaces** (cohérence inter-livrables prouvée) ; persona
Amélie / capabilities OTOIA / langues repris de sources sourcées ; HTML de montage sans
aucun chiffre.
**Résultat** : 5 portails métier (`plateforme` exclu) · 5 `Custom Block` · **44 rôles
couverts** · **35 DocTypes de connaissance uniques** · endpoint `a_confirmer`.
**Vérifs** : 31/31 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **408 tests verts** au total (377 → +31) ; build déterministe.
**Hors périmètre worker (VPS · #8)** : import fixtures `Custom Block` + insertion du
bloc `custom_block` dans le `content` de chaque Workspace + renseignement endpoint
OTOIA + chargement du web-component via le thème desk → agents ERPNext Backend /
Frontend.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session19.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session19.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_085719` (session 18)
**Tâche** : **Sprint 6 · SEO** — Générateur **SEO trilingue** (roadmap L60 :
« Refactor mission `seo_autonome/` → **200+ mots-clés FR/EN/ES · schema.org ·
hreflang** »). Premier volet Sprint 6 réalisable en repo — les volets OTOIA voice
Amélie (pilote AEC) et chat OTOIA embarqué dépendent d'API externes / desk VPS
(hors périmètre worker · #8).
**Décision d'architecture** : livrable de **second niveau** — la matière première
est **`projets_master.json`**, la sortie canonique du **Publiciste** (dérivée de
`data_room/PXX/`). Le générateur ne fabrique aucun fait de projet ; il **réutilise**
(zéro duplication · #5) le validateur maison + les tokens de marque du Publiciste
(`lib/validator.py`, `lib/branding.py`).
**Fichiers créés**`05_deliverables_mvp/seo/` :
- `seo_spec.json` (config site + **lexique éditorial générique** FR/EN/ES + org
schema.org + cibles · zéro donnée projet, zéro chiffre)
- `seolib/{__init__,deps,keywords,schemaorg,hreflang,builder}.py` (`deps` réutilise
validateur + branding Publiciste ; `keywords`/`schemaorg`/`hreflang` purs et
déterministes ; `builder` assemble bundle + manifeste)
- `seo_gen.py` (CLI `build`/`validate` · **15 invariants**)
- `seo.schema.json` (contrat de sortie draft-07)
- `fixtures/projets_master.json` (test only · 9 projets P01..P09, noms sourcés
`CLAUDE.md §Projets`, tous `en_developpement`, **zéro chiffre**)
- `out/{seo_keywords,seo_schema_org,seo_hreflang,MANIFEST}.json` (hand-off) ·
`tests/test_seo.py` (**36 tests** dont 8 injections négatives) · `README.md` ·
`.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `seo-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : un mot-clé = composition de tokens factuels
(`projet:<code>.nom`/`.localisation`, sourçables) + lexique éditorial générique
non chiffré (`lexicon:*`) ; un invariant vérifie que chaque mot-clé est sourcé et
résoluble ; un mot-clé ne peut porter que les chiffres de son champ source
(« 1069 Crisfer » passe ; un prix injecté est refusé). schema.org n'émet un prix
que pour un projet `disponible` à typologie **sourcée** (USD · #10) — la fixture
`en_developpement` produit donc **0 offre**, aucun chiffre inventé dans le hand-off.
**Résultat** : **258 mots-clés** (fr=87 · en=87 · es=84 · cible 200 dépassée) ·
schema.org 10 nœuds (1 Organization + 9 Residence) · hreflang 10 pages (accueil +
9 projets) × 4 alternates (FR/EN/ES + x-default).
**Vérifs** : 36/36 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **377 tests verts** au total (341 → +36) ; build déterministe.
**Hors périmètre worker (VPS · #8)** : injection balises hreflang/JSON-LD dans
`www/` + sitemap + Google Search Console + branchement sur la vraie sortie
Publiciste (9 projets réels) → agent SEO / Frontend.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session18.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session18.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_082714` (session 17)
**Tâche** : **Sprint 5 · QA** — Générateur de l'**Audit 5D de conformité**
(roadmap Sprint 5 · QA « **Audit UAF + normes ISA/IFRS 5D** »). Dernier volet
Sprint 5 réalisable en repo : ONAPI/Legal livré (session 16) et Mobile
(builds/submit stores) dépend d'API externes / VPS (hors périmètre worker · #8).
**Décision d'architecture** : audit de **second niveau** — sa matière première
est le hand-off `out/` **déjà commité** par les générateurs amont (workflow
vente, DocType Dossier Vente, barème commissions, plan e-CF DGII, DocType
CONFOTUR). Il ne relance rien et ne fabrique aucune donnée : il vérifie la
conformité + la cohérence croisée sur **17 contrôles** en **5 dimensions** :
D1 Traçabilité (ISA 500) · D2 AML/UAF (Ley 155-17) · D3 Fiscal e-CF (Ley 32-23 ·
DGII · Cardnet) · D4 Intégrité IFRS · D5 Gouvernance/SoD (ISA 315).
**Fichiers créés**`05_deliverables_mvp/qa/audit_5d/` :
- `audit_spec.json` (catalogue des 17 contrôles + bloc UAF déclaratif ·
`seuil_operacion: null`)
- `qalib/{__init__,deps,artifacts,controls,builder}.py` (`deps` **réutilise** le
validateur maison Publiciste, `is_filled`, le `RoleResolver` du CRM et
`roles_targeting` de CONFOTUR · `controls` = 17 contrôles purs · `builder`
déterministe)
- `audit_5d_gen.py` (CLI `build`/`validate` · **15 invariants**)
- `audit.schema.json` (contrat de sortie draft-07)
- `out/{audit_report,MANIFEST}.json` (hand-off) · `tests/test_audit_5d.py`
(**37 tests** · une injection négative par contrôle) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `qa-audit-5d-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : l'audit **remonte, ne fabrique pas**. Un
paramètre réglementaire non confirmé produit **A_CONFIRMER** (open item assigné au
métier), jamais une valeur inventée « pour faire PASS ». **FAIL** = incohérence
inter-livrables OU valeur chiffrée **sans `source`**. Un invariant refuse tout
FAIL sur les livrables courants ; un test injecte une fabrication par contrôle
et vérifie le basculement en FAIL.
**Résultat** : verdict `PASS_WITH_OPEN_ITEMS` — **13 PASS · 0 FAIL · 4 à
confirmer** (D1.1 taux → Direction ; D1.2 RNC émetteur → Compta ; D1.3
ITBIS/TipoCambio → Fiscaliste eCF ; D2.3 seuil UAF → Oficial de Cumplimiento).
Ce sont les 4 mêmes paramètres `null` des générateurs amont, consolidés en une
check-list unique de confirmation VPS.
**Vérifs** : 37/37 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **341 tests verts** au total ; build déterministe.
**Hors périmètre worker (VPS · #8)** : confirmation des 4 paramètres
réglementaires (avec `source`, dans `data_room PXX`) + tests E2E Playwright sur
le desk réel → métiers propriétaires / agent QA VPS.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session17.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session17.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_075712` (session 16)
**Tâche** : **Sprint 5 · ONAPI/Legal** — Générateur du **DocType porteur
`CONFOTUR Application`** (roadmap **L55** « Refactor `oto_module_confotur_application.py`
→ dépôts automatiques »). Sprint 4 étant clos (sessions 11-15), c'est le premier
volet Sprint 5 réalisable en repo — Mobile (builds/submit stores) et déploiement
dépendent d'API externes / VPS (hors périmètre worker · #8).
**Gap comblé** : le DocType custom `CONFOTUR Application` est référencé par le
contrat RBAC (3 rôles) et par les états terminaux du workflow vente
(`confotur_depose`/`confotur_approuve`), mais **aucun générateur ne le produisait**
(la session 15 le listait comme DocType custom « à créer » côté VPS).
**Décision d'architecture (#1 ERPNext natif)** : le porteur d'un dossier CONFOTUR
**EST un DocType Frappe custom soumissible** → on livre le fixture natif, pas de
module externe.
**Fichiers créés**`05_deliverables_mvp/legal/confotur/` :
- `confotur_spec.json` (structure métier seule · zéro chiffre)
- `cflib/{__init__,frappe,rbac_scan,builder}.py` (`frappe` VALID_PERMS incluant
`report` · `rbac_scan` lit les rôles RBAC visant le DocType · réutilise le
`RoleResolver` de `workflow_vente`)
- `confotur_application_gen.py` (CLI `build`/`validate` · **14 invariants**)
- `confotur.schema.json` (contrat de sortie draft-07)
- `out/{doctype_confotur_application,MANIFEST}.json` (hand-off) ·
`tests/test_confotur.py` (**44 tests** dont 8 négatifs) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `legal-confotur-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : les **permissions du DocType SONT, mot pour mot,
les `permissions_cibles` RBAC** (ventes-confotur/legal-onapi/legal-directeur) — ni
ajout ni retrait ; `is_submittable` déduit de l'action `submit` RBAC ;
`estado`/`dossier_vente` dérivés du workflow ; **aucun** taux/loi/montant/référence
d'autorité (deux invariants refusent tout champ de type montant et tout `default`) ;
paramètres légaux réels → `data_room P05/P07` côté VPS. Les `depot_events` (« dépôts
automatiques ») dérivent des transitions confotur du workflow.
**Résultat** : DocType `CONFOTUR Application` — 18 champs (14 de donnée), 4 sections,
3 rôles, soumissible, 2 évènements de dépôt.
**Vérifs** : 44/44 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **304 tests verts** au total ; build déterministe.
**Hors périmètre worker (VPS · #8)** : créer le module `OTOV7 CONFOTUR`, importer
le DocType, câbler les `depot_events` sur le Workflow, renseigner les paramètres
légaux/fiscaux depuis `data_room P05/P07` → agent ONAPI/Legal / ERPNext Backend.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session16.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session16.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_072711` (session 15)
**Tâche** : Sprint 4 · Frontend Console — Générateur de **Workspaces ERPNext
(5 portails rôle)** (roadmap ligne 49 « 5 portails (Ventes/Construction/Achat/
Compta/Direction) » ; dernier volet ouvert de Sprint 4, les volets CRM et ERPNext
Backend ayant été livrés sessions 11-14).
**Décision d'architecture (#1 ERPNext natif)** : dans ERPNext v15, le portail de
landing par rôle **EST le DocType `Workspace`** → on livre 5 Workspaces natifs,
pas de framework de dashboard externe.
**Fichiers créés**`05_deliverables_mvp/frontend/portails/` :
- `portails_spec.json` (mise en page seule : cartes/raccourcis/thème · aucun
DocType ni rôle hors contrat)
- `wslib/{__init__,frappe,builder}.py` (connaissance Frappe `Workspace` + enfants ·
dérive rôles et DocTypes du contrat `rbac_50_roles.json`)
- `workspaces_gen.py` (CLI `build`/`validate` · 12 invariants de cross-cohérence)
- `workspace.schema.json` (contrat de sortie draft-07)
- `out/{workspace,MANIFEST}.json` (hand-off) · `tests/test_workspaces.py`
(19 tests dont 4 négatifs) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `frontend-portails-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : la source de vérité est le contrat RBAC, jamais
la spec. Tout lien/raccourci vise un DocType présent dans les `permissions_cibles`
du portail (droit prouvé) ; couverture exhaustive sans doublon ; flag `custom`
issu du contrat ; aucun chiffre stocké (compteurs live du desk) ; tokens de marque
(`#0a0a12`/`#f0b429`/Fraunces/Cormorant) repris verbatim de CLAUDE.md #4 avec source.
**Résultat** : 5 Workspaces (Ventes/Construction/Achat/Compta/Direction), 44 rôles
restreints ; console technique `plateforme` exclue (roadmap = 5 portails métier).
**Vérifs** : 19/19 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **260 tests verts** au total ; build déterministe.
**Hors périmètre worker (VPS · #8)** : fixer `Workspace.module` à l'import + créer
les DocTypes custom (`CONFOTUR Application`, `Faisabilité`, `Publiciste Log`) +
appliquer le thème desk → agents ERPNext Backend / Frontend Console.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session15.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session15.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_065711` (session 14)
**Tâche** : Sprint 4 · ERPNext Backend — Générateur de **configuration e-CF DGII
(Compupar)** (roadmap ligne 51 « e-CF DGII intégration (Compupar) » ; les
commissions ayant été livrées session 13, l'e-CF restait ouvert · GAP §Backend).
**Fichiers créés**`05_deliverables_mvp/fiscal/ecf_dgii/` :
- `ecf_spec.json` (catalogue 10 types e-CF DGII · table FormaPago · format e-NCF ·
moneda USD/DOP · RNC/ITBIS/TipoCambio `null` · provider Compupar · 2 évènements
d'émission · `field_map` Dossier Vente → e-CF)
- `ecflib/{__init__,deps,ncf,builder}.py` (réutilise `is_filled`/`CANONICAL`/
`validate` + `RoleResolver` du module `workflow_vente` · composeur e-NCF
traçable `E+tipo(2)+seq(10)` façon `finance.py`)
- `ecf_dgii_gen.py` (CLI `build`/`validate` · 12 invariants de cross-cohérence)
- `ecf.schema.json` (contrat de sortie draft-07)
- `fixtures/dossier_exemple.json` (test only · opérandes fictifs sourcés)
- `out/{ecf_plan,MANIFEST}.json` (hand-off) · `tests/test_ecf_dgii.py`
(39 tests) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `fiscal-ecf-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : aucun chiffre fiscal OTO n'est documenté →
`rnc_emisor` / `taux ITBIS` / `TipoCambio` / endpoints Compupar restent `null`
(a_confirmer) ; un invariant refuse toute valeur fixée **sans `source`**. Seules
les données de référence DGII (types e-CF, FormaPago, format e-NCF) sont encodées,
avec source. Le composeur e-NCF reste `None` tant qu'un opérande manque.
**Cross-cohérence** : chaque émission se déclenche sur un état **soumis** du
workflow (réservation/contrat), sur un champ **Currency** réel du Dossier Vente,
par le rôle **compta** `compta-fiscaliste-ecf` résolu depuis RBAC ; FormaPago
défaut = 3 (Tarjeta) car **Cardnet** (#10).
**Vérifs** : 39/39 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **241 tests verts** au total.
**Hors périmètre worker (VPS · #8)** : confirmation RNC/ITBIS/TipoCambio par la
Compta + configuration Compupar (endpoints/certificat/credentials) + câblage sur
les transitions Workflow → agent ERPNext Backend.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session14.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session14.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_062706` (session 13)
**Tâche** : Sprint 4 · ERPNext Backend — Générateur du **barème de commissions
vendeurs** (roadmap ligne 51 « commissions vendeurs auto »).
**Fichiers créés**`05_deliverables_mvp/crm/commissions/` :
- `bareme_spec.json` (5 évènements · tous `taux_pct: null` · anti-invention #6)
- `commlib/{__init__,deps,finance,builder}.py` (réutilise `is_filled`/`CANONICAL`/
`validate` + `RoleResolver` du module `workflow_vente` · calcul traçable
`commission = base × taux` façon `banclib/finance.py`)
- `commissions_gen.py` (CLI `build`/`validate` · 10 invariants de cross-cohérence)
- `bareme.schema.json` (contrat de sortie draft-07)
- `fixtures/dossier_exemple.json` (test only · chiffres fictifs sourcés)
- `out/{commission_plan,MANIFEST}.json` (hand-off) · `tests/test_commissions.py`
(25 tests) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `crm-commissions-tests` + ajout au `gate`.
**Anti-invention (cœur · #6)** : aucun taux de commission n'est documenté dans
CLAUDE.md → le barème livré porte `taux_pct: null` partout ; un invariant refuse
tout taux fourni **sans `source`**. Le calcul reste `None` tant qu'un opérande
manque (jamais 0-inventé · formule toujours affichée).
**Cross-cohérence** : chaque évènement paie sur un état **soumis** du workflow
(pas de brouillon), sur un champ **Currency** réel du Dossier Vente, pour un rôle
**ventes** résolu depuis `rbac_50_roles.json`.
**Vérifs** : 25/25 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **202 tests verts** au total.
**Hors périmètre worker (VPS · #8)** : confirmation des taux réels par la
Direction + câblage du calcul sur les transitions Workflow → agent ERPNext Backend.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session13.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session13.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_055704` (session 12)
**Tâche** : Sprint 4 · CRM — Générateur du **DocType porteur `OTO Dossier Vente`**
(complète le hand-off du workflow vente : le document réel que le Workflow pilote).
**Fichiers créés**`05_deliverables_mvp/crm/dossier_vente/` :
- `doctype_spec.json` (structure métier · zéro chiffre · Projet P01..P09 · USD/DOP)
- `dvlib/{__init__,frappe,builder}.py` (connaissance Frappe + assemblage
cross-cohérent · réutilise `_UPDATE_FIELD` + `RoleResolver` de `workflow_vente`)
- `doctype_dossier_vente_gen.py` (CLI `build`/`validate` · 12 invariants)
- `doctype.schema.json` (contrat de sortie draft-07)
- `out/{doctype_oto_dossier_vente,MANIFEST}.json` (hand-off)
- `tests/test_dossier_vente.py` (31 tests) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `crm-dossier-vente-tests` + ajout au `gate`.
**Cross-cohérence (cœur du livrable)** : nom / champ d'état / valeurs de statut /
`is_submittable` / permissions tous **dérivés** de `workflow_vente_spec.json`
(source unique · anti-dérive) ; rôles résolus depuis `rbac_50_roles.json` (#6).
**Vérifs** : 31/31 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **177 tests verts** au total.
**Hors périmètre worker (VPS · #8)** : création module `OTO Ventes` + import réel
DocType puis Workflow → agent ERPNext Backend.
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session12.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session12.md).
**Auto-score 4Big** : 96/100.
## Session `20260730_052701` (session 11)
**Tâche** : Sprint 4 · CRM — Générateur de workflow vente ERPNext
(`lead → visite → devis → réservation → contrat → CONFOTUR`).
**Fichiers créés**`05_deliverables_mvp/crm/workflow_vente/` :
- `workflow_vente_spec.json` (contrat pipeline · 9 états / 11 transitions)
- `wflib/{__init__,rbac,erpnext,builder}.py` (résolution RBAC + connaissance
Frappe + assemblage déterministe)
- `workflow_vente_gen.py` (CLI `build`/`validate` · 9 invariants de graphe)
- `workflow.schema.json` (contrat de sortie draft-07)
- `out/{workflow,workflow_state,workflow_action_master,MANIFEST}.json` (hand-off)
- `tests/test_workflow_vente.py` (25 tests) · `README.md` · `.gitignore`
**Fichiers modifiés** :
- `.gitea/workflows/ci.yml` : job `crm-workflow-vente-tests` + ajout au `gate`.
**Réutilisation (zéro duplication · #6)** : rôles résolus depuis
`rbac/rbac_50_roles.json` (jamais de nom Frappe en dur) + validateur maison
Publiciste.
**Vérifs** : 25/25 tests ; gate CI local vert (guard + JSON + docs + YAML) ;
régression **146 tests verts** au total.
**Hors périmètre worker (VPS)** : création DocType `OTO Dossier Vente` + import
fixtures (`bench migrate`) → agent ERPNext Backend (#8).
**Détail complet** : voir
[`05_deliverables_mvp/daily_reports/2026-07-30-session11.md`](../05_deliverables_mvp/daily_reports/2026-07-30-session11.md).
**Auto-score 4Big** : 96/100.