dataroom-prep — Skill de préparation de dataroom M&A
Quand utiliser ce skill
Déclencher quand l'utilisateur demande de :
- Trier / organiser / structurer des documents en vrac en dataroom DD
- Préparer une dataroom M&A pré-upload VDR (Ansarada, Datasite, Drooms, etc.)
- Renommer en masse des documents avec convention
Project X - Intitulé du document - yyyymmdd
- Détecter et archiver les doublons / versions obsolètes d'un dossier
- Générer une checklist des documents à demander client
Confidentialité & zéro exfiltration (RÈGLE ABSOLUE)
🔒 Les documents et leur contenu ne quittent JAMAIS le PC de l'utilisateur. Toute la
persistance se fait en local (workdir + dossier destination) ; rien n'est envoyé vers un
serveur externe.
Règles non négociables :
- Traitement local par défaut. Extraction, classification, dedup, build, Excel mapping et
le Top 50 des documents manquants sont 100% hors-ligne (scripts Python, listes DD locales
dans
data_sources/). Aucun appel réseau n'est requis pour produire une dataroom complète.
- Ne JAMAIS envoyer de contenu de document — ni un fichier, ni un snippet
extracted.json,
ni un titre/chemin issu des documents — vers un outil externe : pas de Firecrawl, pas de
data.gouv, pas de WebSearch/WebFetch, pas de MCP tiers, pas d'upload. Ces données restent
strictement dans la session et sur le disque local.
- Aucune donnée client dans la mémoire persistante. Ne rien écrire dans
MEMORY.md ni dans
les fichiers memory/ qui contienne un nom de société cible, un chiffre, un titre de
document ou tout élément du mandat. La mémoire ne sert qu'aux notes de process génériques.
- Seule exception réseau = Étape 8 (checklist enrichie), strictement opt-in. Cette étape
appelle
firecrawl_scrape sur le site web public de la société + des sources juridiques
(data.gouv / Légifrance / Fedlex). Elle n'envoie QUE l'URL publique et des requêtes
secteur/droit — jamais le contenu des documents. Avant de la lancer, prévenir
l'utilisateur : « cette étape contacte des serveurs externes (le site public de la société +
sources légales) ; veux-tu la lancer ou rester 100% hors-ligne ? ». Si l'utilisateur veut le
zéro-réseau total, sauter l'Étape 8 et se contenter du Top 50 local (étape 5bis), qui
couvre déjà la liste des documents à demander sans aucune connexion.
- Nettoyage des résidus. Écrire les fichiers de travail (
extracted.json,
decisions.json) dans un workdir temporaire isolé, jamais dans scripts/. Ne pas
laisser traîner de fichier contenant des titres/snippets de documents client dans le dossier
du skill après le run.
Pipeline complet (8 étapes)
Étape 1 — Questions obligatoires (TOUT poser au début, en une seule passe)
⚠️ RÈGLE DE FLUX : poser TOUTES les questions au tout début, avant de lancer le moindre
script. L'objectif est de pouvoir enchaîner l'intégralité du pipeline (extraction →
classification → dedup → build → Excel → checklist enrichie) sans interruption ni nouvelle
question. Ne PAS découper en « Phase 1 » / « Phase 2 ». La décision sur la checklist
enrichie (et ses sous-questions) est demandée ICI, en amont, pas après le build.
Utiliser AskUserQuestion pour poser dans cet ordre (regrouper en quelques écrans de
questions multiples ; idéalement tout collecter avant la première action) :
- "Où sont tes documents source ?" — un chemin (dossier ou ZIP). Question obligatoire,
toujours posée explicitement si le chemin n'a pas déjà été donné dans le prompt.
- "Où veux-tu créer la dataroom organisée ?" — chemin destination. Question obligatoire,
toujours posée explicitement si le chemin n'a pas déjà été donné dans le prompt. Proposer
par défaut un sous-dossier à côté de la source (ex.
<dossier parent source>/<Project name>).
- "Nom du projet ?" — utilisé pour préfixer les fichiers (ex: "Project Medicaps")
- "Dans quelle langue veux-tu la structure de dossiers ?" — FR / EN / DE / IT / ES
- "Dans quelle langue veux-tu le fichier Excel mapping ?" — FR / EN / DE / IT / ES
"Quels noms anonymiser ?" — NE JAMAIS POSER cette question. L'anonymisation est
TOUJOURS active par défaut, sans confirmation (« bien sûr que oui »). Le nom réel de la
société cible + ses marques/filiales/entités liées sont détectés automatiquement par
Claude depuis le contenu des documents extraits, puis passés à --scrub de façon
strictement interne. Ces noms ne doivent JAMAIS être écrits, affichés, ni dans une question,
ni dans le chat, ni dans le raisonnement (cf. RÈGLE ABSOLUE plus bas).
- "Provenance de la documentation (pays) ?" — France (FR) / Suisse (CH). Choisit la liste DD
de référence pour le Top 50 des documents manquants (cf. étape 5bis).
- "Secteur d'activité ?" — onglet de la liste DD : BTP / Industrie / Services & Conseil /
Tech / Distribution / Santé / Immobilier / Hôtellerie-Restauration / Transport & Logistique /
Agroalimentaire.
- "Veux-tu aussi la checklist enrichie des documents à demander au client ?" — Oui / Non.
Posée ici, dès le début (et non après le build). Si Oui, enchaîner immédiatement dans
la même passe de questions les sous-questions de la checklist enrichie :
- Localisation de la société : France / Suisse / Belgique / Luxembourg / autre
- Site web de la société : URL (sera scrapée pour détecter secteur, taille, marchés, conformités)
- Secteur d'activité connu (optionnel — vide = détection auto via site web)
- Sources à consulter : data.gouv / Légifrance / Fedlex / OpenLaw / aucune
⚠️ PIÈGE À NE PLUS REFAIRE : ne jamais reporter Q1/Q2/Q3 (chemins + nom de projet) à plus
tard sous prétexte que AskUserQuestion exige 2 à 4 options et ne fait pas de texte libre
nativement. Ces trois questions sont des chemins/texte libre : elles DOIVENT quand même
apparaître dans le tout premier envoi de questions, pas dans un second aller-retour. Technique
à utiliser : donner 2 options factices qui couvrent les cas réels (ex. pour la destination,
"À côté de la source" vs "Autre emplacement" — l'utilisateur tape le chemin réel via
l'option "Other", toujours disponible automatiquement) plutôt que d'omettre la question du
premier lot. Un lot de questions qui ne contient QUE des choix fermés (langue, pays, secteur…)
et laisse le chemin source pour « après » est un flux raté — corriger avant d'envoyer.
Si l'utilisateur a déjà précisé tout ou partie de ces infos dans le prompt, ne pas re-demander.
Une fois toutes les réponses collectées, dérouler le pipeline complet sans poser d'autre
question.
Étape 2 — Extraction de texte
Lancer scripts/extract.py avec :
--source <path_user> — chemin source
--out <skill_workdir>/extracted.json — workdir temporaire
Le script :
- Scanne récursivement les
.pdf .docx .xlsx .pptx .doc .xls .msg
- Exclut les artefacts (code, builds,
.cache, node_modules, _files/)
- Extrait un snippet de 2-3K caractères par doc
- Sort un JSON avec
relpath, filename, parent_folder, snippet, readable
Étape 3 — Classification IA (règles + parent_folder)
Lancer scripts/classify.py avec :
--extracted extracted.json
--language <FR/EN/DE/IT/ES> — langue de la structure
--templates templates/folder_structure_<lang>.json
Le script :
- Charge le template multilingue
- Pour chaque doc, classe en (folder_N1, theme_N2, confidence) via heuristiques
parent_folder + filename + snippet
- LOW confidence → forcé en
11_Document à trier
- Génère un nouveau nom :
{Project} - {Theme} - {Subject} - {yyyymm}.{ext}
Étape 4 — Détection doublons + versions
Lancer scripts/dedup.py :
- Hash SHA-256 sur chaque fichier → groupes de doublons exacts
- Clustering par filename normalisé (retire dates, versions, suffixes) → versions
- Garde la version au score le plus élevé (final > signed > v3 > v2 > v1 > draft, et date la plus récente)
Étape 5 — Build dataroom N1/N2
Lancer scripts/build_dataroom.py :
- Crée la structure 11 dossiers N1 dans le destination user
- Sous-dossiers N2 par theme (NDA, Brevets, Bilans annuels, Commercial - Client X, etc.)
- Copie + renomme les UNIQUE dans la dataroom principale
- Archive les DOUBLON_EXACT dans
_98_Doublons exacts/
- Archive les VERSION_OBSOLETE dans
_99_Versions anciennes/{N1}/{N2}/
Étape 6 — Excel mapping multilingue
Lancer scripts/generate_mapping.py --lang <excel_lang> :
- Colonnes :
Original | Chemin source | Nouveau nom | Dossier N1 | Sous-dossier N2 | Confiance | Statut dedup | Chemin final
- Headers traduits selon
excel_lang
- Charte Hectelion : navy
#182E4E, cellules input cyan #72C7E7, police Calibri 9-11 pt
- 5 onglets : Dashboard | Mapping | Structure dataroom | Doublons & versions | (placeholder) Checklist
Étape 7 — Branchement checklist enrichie (PAS de nouvelle question)
⚠️ Ne RIEN re-demander ici. La décision (Oui/Non) et ses 4 sous-réponses (localisation,
site web, secteur connu, sources) ont déjà été collectées à l'Étape 1. Se contenter de
brancher :
- Si l'utilisateur a répondu Non à la checklist → terminer le pipeline après l'Étape 6.
- Si l'utilisateur a répondu Oui → enchaîner directement l'Étape 8 avec les réponses déjà
en main (localisation, URL site web, secteur connu, sources).
Étape 8 — Enrichissement checklist
Lancer scripts/enrich_checklist.py :
- Scrape site web via Firecrawl (
firecrawl_scrape) → texte de la page d'accueil + about + produits/services
- Analyse contextuelle : utiliser Claude (via prompt structuré) pour identifier :
- Secteur précis (MedTech, SaaS, immobilier, retail, etc.)
- Présence internationale (filiales, exports)
- Effectif estimé
- Conformités requises (CE, FDA, ISO, RGPD, HIPAA, etc.)
- Cross-référence avec sources :
- Si France → consulter Légifrance + data.gouv (obligations sectorielles)
- Si Suisse → consulter Fedlex (admin.ch) + obligations OFEN/FINMA
- Génère un Excel "Project X - Liste documents à demander.xlsx" avec 4 colonnes :
- Catégorie (par dossier N1/N2)
- Document/Information demandé
- Pourquoi (référence légale ou contextuelle)
- Statut (✓ déjà présent / ⚠ partiel / ✗ à demander)
Le tout sauvegardé au chemin destination user.
Templates de structure de dossiers multilingues
Chaque langue a son fichier templates/folder_structure_<lang>.json avec :
- Noms des 11 dossiers N1
- Mapping des themes N2 fréquents (Bilans annuels, NDA, Brevets, KBIS, etc.)
Langues supportées : FR, EN, DE, IT, ES.
Pour autre langue : utiliser Claude pour traduire les noms à la volée.
Sources de données externes
| Source |
Langue |
Type |
Statut |
Firecrawl (firecrawl_scrape) |
toutes |
Scraping site web |
Actif |
data.gouv (mcp__datagouv__*) |
FR |
Datasets publics français |
Actif |
| Légifrance (API publique gratuite) |
FR |
Lois, codes, jurisprudence |
À implémenter (V2) |
| Fedlex (Suisse) |
DE/FR/IT |
Droit fédéral suisse |
À implémenter (V2) |
| OpenLaw |
FR |
Jurisprudence ouverte |
À implémenter (V2) |
Pour V1, focus sur Firecrawl + data.gouv. Les autres en V2.
Livrables finaux
À la fin du pipeline complet, l'utilisateur trouve dans son dossier destination :
<destination>/
├── <Project name>/ ← dataroom organisée
│ ├── 01_<Informations générales>/ (langue choisie)
│ ├── 02_<Finance>/
│ │ ├── <Bilans annuels>/
│ │ ├── <Facturation commerciale>/
│ │ └── ...
│ ├── 03_<Légal>/
│ │ ├── <NDA & confidentialité>/
│ │ ├── <Brevets>/
│ │ └── ...
│ ├── ... (11 dossiers N1)
│ ├── _98_<Doublons exacts>/
│ ├── _99_<Versions anciennes>/
│ ├── _Rapport DataPrep.xlsx ← mapping + structure + dedup
│ └── _Liste documents à demander.xlsx ← si Phase 2 activée
└── <Project name>.zip ← ZIP livrable
Conventions de renommage
Pattern obligatoire : {Project} - {Intitulé réel du document} - {yyyymmdd}.{ext}
⚠️ RÈGLE ABSOLUE — ANONYMISATION (toujours active, jamais négociée). Le nom réel de la
société cible, de ses marques, filiales et entités liées ne doit JAMAIS apparaître nulle
part — y compris :
- dans les noms de fichiers, sous-dossiers, Excel (y compris colonne « Nom original ») et titres ;
- dans tes messages de chat à l'utilisateur ;
- dans tes questions (
AskUserQuestion ou autres) ;
- dans ton raisonnement / réflexion visible, y compris pendant l'étape où tu cherches à
identifier ce nom pour le scrubber.
Seul le nom de PROJET est visible, partout (ex. « la société cible », « Project X »).
Ne jamais demander si l'on doit anonymiser : la réponse est toujours oui, implicitement.
Lors du titrage IA, décrire le document de façon générique (ex. « entité holding » et non le
vrai nom).
Détection automatique + filet technique : Claude identifie lui-même les noms réels depuis
le contenu extrait (sans jamais les afficher), puis les passe à --scrub de run_pipeline.py,
qui retire automatiquement toute occurrence (insensible casse, limites de mots) des noms
interdits dans les fichiers/dossiers/Excel générés. Pour éviter que le nom réel transparaisse
même dans une commande shell affichée, écrire la liste de scrub dans un fichier local non
commenté (--scrub-file <chemin>) plutôt que de l'inliner dans --scrub "..." lorsque c'est
possible.
Quatre règles strictes (édictées par l'utilisateur) :
- Ne JAMAIS reprendre le vieux nom de fichier brut. L'intitulé doit être un titre
propre déduit du contenu du document (lu via extraction / OCR), pas le nom d'origine.
❌
... - PV AG fin rem 08 VD - 2024.pdf ❌ ... - StatutsMai2020 - undated.pdf
✅ ... - Procès-verbal AGO cessation rémunération du Président - 20240830.pdf
- Ne JAMAIS répéter le nom du dossier / thème dans le nom de fichier : l'arborescence
porte déjà le thème. ❌
... - Marketing & commercial - Plan marketing ...
✅ ... - Plan marketing 2021-2022.docx
- Date au format
yyyymmdd (ou yyyymm / yyyy si le jour/mois est inconnu, ou rien
si le document n'a pas de date pertinente).
- L'intitulé doit rester COURT et descriptif — l'essentiel du document en quelques mots
(viser ~3 à 7 mots, pas de phrase entière ni de sous-clauses). Garder le type de document +
l'élément qui le distingue des autres du même type, rien de plus.
❌
... - Procès-verbal de l'Assemblée Générale Ordinaire Annuelle statuant sur l'approbation des comptes de l'exercice clos le 31 décembre 2020 - 20210630.pdf
✅ ... - PV AGO approbation des comptes 2020 - 20210630.pdf
Format final à retenir : Nom [Projet] + Nom du document (court, descriptif) + yyyymmdd.
Exemples :
Project Hectelion - Extrait Kbis - 20250506.pdf
Project Hectelion - Term Sheet signé - 20220428.pdf
Project Hectelion - Comptes annuels - attestation de conformité - 20201231.pdf
Project Hectelion - Table de capitalisation.xlsx (sans date)
Pour les documents en 11_Document à trier (confiance LOW), garder le nom original sans renommage.
Mécanisme de titrage par contenu (lecture + OCR)
Le titre propre ne peut pas être deviné depuis le nom de fichier : il faut comprendre le
contenu. Le pipeline procède donc en deux temps :
- Extraction enrichie (
run_pipeline.py) :
- PDF lus via PyMuPDF (couche texte native, bien plus fiable que pypdf).
- PDF scannés (sans couche texte) → fallback OCR via
pytesseract + Pillow
(rendu image puis OCR fra+eng). Avant toute extraction réelle (mode --source),
le pipeline vérifie automatiquement que pytesseract/Pillow/le binaire tesseract
sont présents et, sinon, tente de les installer tout seul (pip install pytesseract pillow + winget install UB-Mannheim.TesseractOCR sur Windows, brew install tesseract sur macOS, apt-get install tesseract-ocr sur Linux) — silencieux et non
bloquant : si l'installation échoue (pas d'admin, pas de gestionnaire de paquets, pas
de réseau), le doc est marqué SCANNED_NO_OCR et l'extraction reste gracieuse (pas de
crash). Ne jamais sauter cette vérification ni la rendre optionnelle : l'objectif est
qu'un maximum de PDF scannés soient lus, à chaque lancement du skill, sans intervention
manuelle.
- Word (
python-docx) et Excel (openpyxl) lus nativement.
- Décisions IA : après extraction, Claude lit les snippets (et, pour les PDF scannés
non couverts par tesseract, rasterise la page en PNG via PyMuPDF puis la lit comme
image — OCR visuel) et produit un fichier
decisions.json :{ "<relpath>": { "n1": "03", "n2": "PV Assemblées",
"title": "Procès-verbal AGO ...", "date": "20240830",
"confidence": "HIGH" } }
Le pipeline est relancé avec --decisions-json : ces titres/classements surchargent
les heuristiques. Le champ date fourni (même vide) est respecté littéralement.
Flux recommandé :
python run_pipeline.py --source ... --extract-only extracted.json # 1. extraire
# 2. Claude lit extracted.json (+ OCR visuel des PDF scannés) -> decisions.json
python run_pipeline.py --source ... --decisions-json decisions.json --make-zip # 3. build
Dépendances : pymupdf (requis pour l'extraction enrichie + le rendu OCR visuel) ;
pytesseract + Pillow + binaire tesseract pour l'OCR automatique en lot — auto-installés
par le pipeline lui-même à chaque lancement s'ils manquent (voir ci-dessus), donc à ne plus
jamais demander à l'utilisateur d'installer manuellement en amont.
Documents manquants — Top 50 par catégorie (étape 5bis)
Après le tri, le rapport Excel gagne un onglet « Documents à demander » : le Top 50 des
documents importants MANQUANTS, groupés par catégorie et triés par priorité.
Source : les listes DD de référence Hectelion (issues du SaaS VDR prep), une par pays, avec un
onglet par secteur (~344 exigences chacune, colonne Priorité Haute/Moyenne/Basse) :
data_sources/Hectelion - Listes DD - FRANCE.xlsx
data_sources/Hectelion - Listes DD - SUISSE.xlsx
Mécanique (run_pipeline.py --country FR|CH --sector <onglet>) :
- Charge la liste DD du pays + secteur choisis.
- Marque chaque exigence présent/manquant par recouvrement de tokens avec les documents
réellement classés dans la dataroom (statut « présents (estimés) » — à revérifier).
- Écrit l'onglet, colonnes
Catégorie | Réf. | Document à demander | Priorité | Période | Base légale.
Répartition PROPORTIONNELLE obligatoire : les 50 slots sont distribués entre catégories
(apportionnement au plus fort reste, pondéré par le nb de manquants de chaque section, min 1
par catégorie représentée), au lieu de tout concentrer sur les grosses sections (Finance).
Ex. ~10 Finance, ~7 Juridique, ~6 RH, ~5 Fiscal, ~3 Opérations… À l'intérieur de chaque
catégorie, priorité Haute d'abord. Objectif : une demande client équilibrée couvrant tous les
volets de la DD.
C'est la version template-driven de la checklist Phase 2 (plus fiable que le scraping) :
le pays oriente les obligations légales, le secteur la liste métier.
Charte graphique des livrables Excel
Toujours appliquer la charte Hectelion (skill hectelion-brand auto-chargé) :
- Headers : fond
#182E4E, texte blanc, Calibri 11 pt Bold
- Cellules input : fond cyan
#72C7E7
- Cellules données : Calibri 9-11 pt, blanc
- Titres éditoriaux d'onglet : Cardo 25 pt / 18 pt
- Statut dedup : MINT vert / WARNING orange / ALERT rouge
Anti-patterns à éviter
- ❌ Inventer une classification quand le document est illisible → forcer
11_Document à trier
- ❌ Renommer un doc qui va en 11_À trier → garder son nom original
- ❌ Ignorer les doublons exacts → toujours les détecter et archiver séparément
- ❌ Mettre tous les docs en racine d'un dossier N1 → toujours créer la structure N2
- ❌ Hardcoder la langue FR → respecter le choix utilisateur
Exemple d'invocation
User: /dataroom-prep
Claude: [Pose TOUTES les questions au début via AskUserQuestion :
Q1 source, Q2 destination, Q3 nom projet, Q4 langue structure,
Q5 langue Excel, Q7 pays, Q8 secteur, Q9 checklist enrichie Oui/Non
(+ si Oui : localisation, site web, secteur connu, sources)]
User: [répond à tout]
Claude: [déroule TOUT le pipeline sans interruption :
extraction → classification → dedup → build dataroom + Excel
→ si checklist=Oui : enrich_checklist.py → scrape + analyse + Excel checklist]
Claude: [livre dataroom + Excel(s) + ZIP]
Pour usage automatisé/scriptable, voir scripts/run_pipeline.py qui orchestre les 8 étapes.
1---2name: dataroom-prep3description: Trie et structure des documents en vrac en dataroom M&A-ready (11 dossiers + sous-dossiers multilingues), avec classification IA, détection des doublons exacts (SHA-256), détection des versions obsolètes, et checklist contextuelle enrichie via scraping site web + sources juridiques/fiscales/comptables (Légifrance, data.gouv, Fedlex). Multilingue FR/EN/DE/IT/ES. Utiliser quand l'utilisateur dit "structure cette dataroom", "trie ces documents", "prépare cette dataroom DD", "/dataroom-prep", ou demande de transformer un dossier en vrac en dataroom M&A.4---56# dataroom-prep — Skill de préparation de dataroom M&A78## Quand utiliser ce skill910Déclencher quand l'utilisateur demande de :11- Trier / organiser / structurer des documents en vrac en dataroom DD12- Préparer une dataroom M&A pré-upload VDR (Ansarada, Datasite, Drooms, etc.)13- Renommer en masse des documents avec convention `Project X - Intitulé du document - yyyymmdd`14- Détecter et archiver les doublons / versions obsolètes d'un dossier15- Générer une checklist des documents à demander client1617## Confidentialité & zéro exfiltration (RÈGLE ABSOLUE)1819> 🔒 **Les documents et leur contenu ne quittent JAMAIS le PC de l'utilisateur.** Toute la20> persistance se fait en local (workdir + dossier destination) ; **rien n'est envoyé vers un21> serveur externe.**2223Règles non négociables :24251. **Traitement local par défaut.** Extraction, classification, dedup, build, Excel mapping et26 le Top 50 des documents manquants sont **100% hors-ligne** (scripts Python, listes DD locales27 dans `data_sources/`). Aucun appel réseau n'est requis pour produire une dataroom complète.282. **Ne JAMAIS envoyer de contenu de document — ni un fichier, ni un snippet `extracted.json`,29 ni un titre/chemin issu des documents — vers un outil externe** : pas de Firecrawl, pas de30 data.gouv, pas de WebSearch/WebFetch, pas de MCP tiers, pas d'upload. Ces données restent31 strictement dans la session et sur le disque local.323. **Aucune donnée client dans la mémoire persistante.** Ne rien écrire dans `MEMORY.md` ni dans33 les fichiers `memory/` qui contienne un nom de société cible, un chiffre, un titre de34 document ou tout élément du mandat. La mémoire ne sert qu'aux notes de process génériques.354. **Seule exception réseau = Étape 8 (checklist enrichie), strictement opt-in.** Cette étape36 appelle `firecrawl_scrape` sur le **site web public** de la société + des sources juridiques37 (data.gouv / Légifrance / Fedlex). Elle n'envoie QUE l'URL publique et des requêtes38 secteur/droit — **jamais** le contenu des documents. Avant de la lancer, prévenir39 l'utilisateur : « cette étape contacte des serveurs externes (le site public de la société +40 sources légales) ; veux-tu la lancer ou rester 100% hors-ligne ? ». Si l'utilisateur veut le41 zéro-réseau total, **sauter l'Étape 8** et se contenter du Top 50 local (étape 5bis), qui42 couvre déjà la liste des documents à demander sans aucune connexion.435. **Nettoyage des résidus.** Écrire les fichiers de travail (`extracted.json`,44 `decisions.json`) dans un **workdir temporaire isolé**, jamais dans `scripts/`. Ne pas45 laisser traîner de fichier contenant des titres/snippets de documents client dans le dossier46 du skill après le run.4748## Pipeline complet (8 étapes)4950### Étape 1 — Questions obligatoires (TOUT poser au début, en une seule passe)5152> ⚠️ **RÈGLE DE FLUX : poser TOUTES les questions au tout début, avant de lancer le moindre53> script.** L'objectif est de pouvoir enchaîner l'intégralité du pipeline (extraction →54> classification → dedup → build → Excel → checklist enrichie) sans interruption ni nouvelle55> question. **Ne PAS découper en « Phase 1 » / « Phase 2 ».** La décision sur la checklist56> enrichie (et ses sous-questions) est demandée ICI, en amont, pas après le build.5758**Utiliser `AskUserQuestion`** pour poser dans cet ordre (regrouper en quelques écrans de59questions multiples ; idéalement tout collecter avant la première action) :60611. **"Où sont tes documents source ?"** — un chemin (dossier ou ZIP). **Question obligatoire,62 toujours posée explicitement** si le chemin n'a pas déjà été donné dans le prompt.632. **"Où veux-tu créer la dataroom organisée ?"** — chemin destination. **Question obligatoire,64 toujours posée explicitement** si le chemin n'a pas déjà été donné dans le prompt. Proposer65 par défaut un sous-dossier à côté de la source (ex. `<dossier parent source>/<Project name>`).663. **"Nom du projet ?"** — utilisé pour préfixer les fichiers (ex: "Project Medicaps")674. **"Dans quelle langue veux-tu la structure de dossiers ?"** — FR / EN / DE / IT / ES685. **"Dans quelle langue veux-tu le fichier Excel mapping ?"** — FR / EN / DE / IT / ES696. ~~"Quels noms anonymiser ?"~~ — **NE JAMAIS POSER cette question.** L'anonymisation est70 TOUJOURS active par défaut, sans confirmation (« bien sûr que oui »). Le nom réel de la71 société cible + ses marques/filiales/entités liées sont **détectés automatiquement par72 Claude** depuis le contenu des documents extraits, puis passés à `--scrub` de façon73 strictement interne. Ces noms ne doivent JAMAIS être écrits, affichés, ni dans une question,74 ni dans le chat, ni dans le raisonnement (cf. RÈGLE ABSOLUE plus bas).757. **"Provenance de la documentation (pays) ?"** — France (FR) / Suisse (CH). Choisit la liste DD76 de référence pour le **Top 50 des documents manquants** (cf. étape 5bis).778. **"Secteur d'activité ?"** — onglet de la liste DD : BTP / Industrie / Services & Conseil /78 Tech / Distribution / Santé / Immobilier / Hôtellerie-Restauration / Transport & Logistique /79 Agroalimentaire.809. **"Veux-tu aussi la checklist enrichie des documents à demander au client ?"** — Oui / Non.81 **Posée ici, dès le début** (et non après le build). Si **Oui**, enchaîner immédiatement dans82 la même passe de questions les sous-questions de la checklist enrichie :83 - **Localisation de la société** : France / Suisse / Belgique / Luxembourg / autre84 - **Site web de la société** : URL (sera scrapée pour détecter secteur, taille, marchés, conformités)85 - **Secteur d'activité connu** (optionnel — vide = détection auto via site web)86 - **Sources à consulter** : data.gouv / Légifrance / Fedlex / OpenLaw / aucune8788> ⚠️ **PIÈGE À NE PLUS REFAIRE : ne jamais reporter Q1/Q2/Q3 (chemins + nom de projet) à plus89> tard sous prétexte que `AskUserQuestion` exige 2 à 4 options et ne fait pas de texte libre90> nativement.** Ces trois questions sont des chemins/texte libre : elles DOIVENT quand même91> apparaître dans le tout premier envoi de questions, pas dans un second aller-retour. Technique92> à utiliser : donner 2 options factices qui couvrent les cas réels (ex. pour la destination,93> `"À côté de la source"` vs `"Autre emplacement"` — l'utilisateur tape le chemin réel via94> l'option "Other", toujours disponible automatiquement) plutôt que d'omettre la question du95> premier lot. Un lot de questions qui ne contient QUE des choix fermés (langue, pays, secteur…)96> et laisse le chemin source pour « après » est un flux raté — corriger avant d'envoyer.9798Si l'utilisateur a déjà précisé tout ou partie de ces infos dans le prompt, ne pas re-demander.99**Une fois toutes les réponses collectées, dérouler le pipeline complet sans poser d'autre100question.**101102### Étape 2 — Extraction de texte103104Lancer `scripts/extract.py` avec :105- `--source <path_user>` — chemin source106- `--out <skill_workdir>/extracted.json` — workdir temporaire107108Le script :109- Scanne récursivement les `.pdf .docx .xlsx .pptx .doc .xls .msg`110- Exclut les artefacts (code, builds, `.cache`, `node_modules`, `_files/`)111- Extrait un snippet de 2-3K caractères par doc112- Sort un JSON avec `relpath`, `filename`, `parent_folder`, `snippet`, `readable`113114### Étape 3 — Classification IA (règles + parent_folder)115116Lancer `scripts/classify.py` avec :117- `--extracted extracted.json`118- `--language <FR/EN/DE/IT/ES>` — langue de la structure119- `--templates templates/folder_structure_<lang>.json`120121Le script :122- Charge le template multilingue123- Pour chaque doc, classe en (folder_N1, theme_N2, confidence) via heuristiques `parent_folder` + `filename` + `snippet`124- LOW confidence → forcé en `11_Document à trier`125- Génère un nouveau nom : `{Project} - {Theme} - {Subject} - {yyyymm}.{ext}`126127### Étape 4 — Détection doublons + versions128129Lancer `scripts/dedup.py` :130- Hash SHA-256 sur chaque fichier → groupes de doublons exacts131- Clustering par filename normalisé (retire dates, versions, suffixes) → versions132- Garde la version au score le plus élevé (final > signed > v3 > v2 > v1 > draft, et date la plus récente)133134### Étape 5 — Build dataroom N1/N2135136Lancer `scripts/build_dataroom.py` :137- Crée la structure 11 dossiers N1 dans le destination user138- Sous-dossiers N2 par theme (NDA, Brevets, Bilans annuels, Commercial - Client X, etc.)139- Copie + renomme les UNIQUE dans la dataroom principale140- Archive les DOUBLON_EXACT dans `_98_Doublons exacts/`141- Archive les VERSION_OBSOLETE dans `_99_Versions anciennes/{N1}/{N2}/`142143### Étape 6 — Excel mapping multilingue144145Lancer `scripts/generate_mapping.py --lang <excel_lang>` :146- Colonnes : `Original | Chemin source | Nouveau nom | Dossier N1 | Sous-dossier N2 | Confiance | Statut dedup | Chemin final`147- Headers traduits selon `excel_lang`148- Charte Hectelion : navy `#182E4E`, cellules input cyan `#72C7E7`, police Calibri 9-11 pt149- 5 onglets : Dashboard | Mapping | Structure dataroom | Doublons & versions | (placeholder) Checklist150151### Étape 7 — Branchement checklist enrichie (PAS de nouvelle question)152153> ⚠️ **Ne RIEN re-demander ici.** La décision (Oui/Non) et ses 4 sous-réponses (localisation,154> site web, secteur connu, sources) ont déjà été collectées à l'**Étape 1**. Se contenter de155> brancher :156> - Si l'utilisateur a répondu **Non** à la checklist → terminer le pipeline après l'Étape 6.157> - Si l'utilisateur a répondu **Oui** → enchaîner directement l'Étape 8 avec les réponses déjà158> en main (localisation, URL site web, secteur connu, sources).159160### Étape 8 — Enrichissement checklist161162Lancer `scripts/enrich_checklist.py` :1631641. **Scrape site web** via Firecrawl (`firecrawl_scrape`) → texte de la page d'accueil + about + produits/services1652. **Analyse contextuelle** : utiliser Claude (via prompt structuré) pour identifier :166 - Secteur précis (MedTech, SaaS, immobilier, retail, etc.)167 - Présence internationale (filiales, exports)168 - Effectif estimé169 - Conformités requises (CE, FDA, ISO, RGPD, HIPAA, etc.)1703. **Cross-référence avec sources** :171 - Si France → consulter Légifrance + data.gouv (obligations sectorielles)172 - Si Suisse → consulter Fedlex (admin.ch) + obligations OFEN/FINMA1734. **Génère un Excel "Project X - Liste documents à demander.xlsx"** avec 4 colonnes :174 - Catégorie (par dossier N1/N2)175 - Document/Information demandé176 - Pourquoi (référence légale ou contextuelle)177 - Statut (✓ déjà présent / ⚠ partiel / ✗ à demander)178179Le tout sauvegardé au chemin destination user.180181## Templates de structure de dossiers multilingues182183Chaque langue a son fichier `templates/folder_structure_<lang>.json` avec :184- Noms des 11 dossiers N1185- Mapping des themes N2 fréquents (Bilans annuels, NDA, Brevets, KBIS, etc.)186187Langues supportées : FR, EN, DE, IT, ES.188Pour autre langue : utiliser Claude pour traduire les noms à la volée.189190## Sources de données externes191192| Source | Langue | Type | Statut |193|---|---|---|---|194| Firecrawl (`firecrawl_scrape`) | toutes | Scraping site web | Actif |195| data.gouv (`mcp__datagouv__*`) | FR | Datasets publics français | Actif |196| Légifrance (API publique gratuite) | FR | Lois, codes, jurisprudence | À implémenter (V2) |197| Fedlex (Suisse) | DE/FR/IT | Droit fédéral suisse | À implémenter (V2) |198| OpenLaw | FR | Jurisprudence ouverte | À implémenter (V2) |199200Pour V1, focus sur Firecrawl + data.gouv. Les autres en V2.201202## Livrables finaux203204À la fin du pipeline complet, l'utilisateur trouve dans son dossier destination :205206```207<destination>/208├── <Project name>/ ← dataroom organisée209│ ├── 01_<Informations générales>/ (langue choisie)210│ ├── 02_<Finance>/211│ │ ├── <Bilans annuels>/212│ │ ├── <Facturation commerciale>/213│ │ └── ...214│ ├── 03_<Légal>/215│ │ ├── <NDA & confidentialité>/216│ │ ├── <Brevets>/217│ │ └── ...218│ ├── ... (11 dossiers N1)219│ ├── _98_<Doublons exacts>/220│ ├── _99_<Versions anciennes>/221│ ├── _Rapport DataPrep.xlsx ← mapping + structure + dedup222│ └── _Liste documents à demander.xlsx ← si Phase 2 activée223└── <Project name>.zip ← ZIP livrable224```225226## Conventions de renommage227228Pattern obligatoire : **`{Project} - {Intitulé réel du document} - {yyyymmdd}.{ext}`**229230> ⚠️ **RÈGLE ABSOLUE — ANONYMISATION (toujours active, jamais négociée).** Le **nom réel de la231> société cible, de ses marques, filiales et entités liées ne doit JAMAIS apparaître** nulle232> part — y compris :233> - dans les noms de fichiers, sous-dossiers, Excel (y compris colonne « Nom original ») et titres ;234> - **dans tes messages de chat à l'utilisateur** ;235> - **dans tes questions** (`AskUserQuestion` ou autres) ;236> - **dans ton raisonnement / réflexion visible**, y compris pendant l'étape où tu cherches à237> identifier ce nom pour le scrubber.238>239> **Seul le nom de PROJET est visible, partout** (ex. « la société cible », « Project X »).240> **Ne jamais demander si l'on doit anonymiser** : la réponse est toujours oui, implicitement.241> Lors du titrage IA, décrire le document de façon générique (ex. « entité holding » et non le242> vrai nom).243>244> **Détection automatique + filet technique :** Claude identifie lui-même les noms réels depuis245> le contenu extrait (sans jamais les afficher), puis les passe à `--scrub` de `run_pipeline.py`,246> qui retire automatiquement toute occurrence (insensible casse, limites de mots) des noms247> interdits dans les fichiers/dossiers/Excel générés. Pour éviter que le nom réel transparaisse248> même dans une commande shell affichée, écrire la liste de scrub dans un fichier local non249> commenté (`--scrub-file <chemin>`) plutôt que de l'inliner dans `--scrub "..."` lorsque c'est250> possible.251252Quatre règles strictes (édictées par l'utilisateur) :2532541. **Ne JAMAIS reprendre le vieux nom de fichier brut.** L'intitulé doit être un titre255 propre déduit du *contenu* du document (lu via extraction / OCR), pas le nom d'origine.256 ❌ `... - PV AG fin rem 08 VD - 2024.pdf` ❌ `... - StatutsMai2020 - undated.pdf`257 ✅ `... - Procès-verbal AGO cessation rémunération du Président - 20240830.pdf`2582. **Ne JAMAIS répéter le nom du dossier / thème dans le nom de fichier** : l'arborescence259 porte déjà le thème. ❌ `... - Marketing & commercial - Plan marketing ...`260 ✅ `... - Plan marketing 2021-2022.docx`2613. **Date au format `yyyymmdd`** (ou `yyyymm` / `yyyy` si le jour/mois est inconnu, ou rien262 si le document n'a pas de date pertinente).2634. **L'intitulé doit rester COURT et descriptif** — l'essentiel du document en quelques mots264 (viser ~3 à 7 mots, pas de phrase entière ni de sous-clauses). Garder le type de document +265 l'élément qui le distingue des autres du même type, rien de plus.266 ❌ `... - Procès-verbal de l'Assemblée Générale Ordinaire Annuelle statuant sur l'approbation des comptes de l'exercice clos le 31 décembre 2020 - 20210630.pdf`267 ✅ `... - PV AGO approbation des comptes 2020 - 20210630.pdf`268269Format final à retenir : **Nom [Projet] + Nom du document (court, descriptif) + yyyymmdd**.270271Exemples :272- `Project Hectelion - Extrait Kbis - 20250506.pdf`273- `Project Hectelion - Term Sheet signé - 20220428.pdf`274- `Project Hectelion - Comptes annuels - attestation de conformité - 20201231.pdf`275- `Project Hectelion - Table de capitalisation.xlsx` (sans date)276277Pour les documents en `11_Document à trier` (confiance LOW), garder le nom original sans renommage.278279### Mécanisme de titrage par contenu (lecture + OCR)280281Le titre propre ne peut pas être deviné depuis le nom de fichier : il faut **comprendre le282contenu**. Le pipeline procède donc en deux temps :2832841. **Extraction enrichie** (`run_pipeline.py`) :285 - PDF lus via **PyMuPDF** (couche texte native, bien plus fiable que pypdf).286 - PDF **scannés** (sans couche texte) → **fallback OCR** via `pytesseract` + Pillow287 (rendu image puis OCR `fra+eng`). **Avant toute extraction réelle (mode `--source`),288 le pipeline vérifie automatiquement que `pytesseract`/Pillow/le binaire `tesseract`289 sont présents et, sinon, tente de les installer tout seul** (`pip install pytesseract290 pillow` + `winget install UB-Mannheim.TesseractOCR` sur Windows, `brew install291 tesseract` sur macOS, `apt-get install tesseract-ocr` sur Linux) — silencieux et non292 bloquant : si l'installation échoue (pas d'admin, pas de gestionnaire de paquets, pas293 de réseau), le doc est marqué `SCANNED_NO_OCR` et l'extraction reste gracieuse (pas de294 crash). Ne jamais sauter cette vérification ni la rendre optionnelle : l'objectif est295 qu'un maximum de PDF scannés soient lus, à chaque lancement du skill, sans intervention296 manuelle.297 - Word (`python-docx`) et Excel (`openpyxl`) lus nativement.2982. **Décisions IA** : après extraction, Claude lit les snippets (et, pour les PDF scannés299 non couverts par tesseract, **rasterise la page en PNG via PyMuPDF puis la lit comme300 image** — OCR visuel) et produit un fichier `decisions.json` :301 ```json302 { "<relpath>": { "n1": "03", "n2": "PV Assemblées",303 "title": "Procès-verbal AGO ...", "date": "20240830",304 "confidence": "HIGH" } }305 ```306 Le pipeline est relancé avec `--decisions-json` : ces titres/classements **surchargent**307 les heuristiques. Le champ `date` fourni (même vide) est respecté littéralement.308309Flux recommandé :310```311python run_pipeline.py --source ... --extract-only extracted.json # 1. extraire312# 2. Claude lit extracted.json (+ OCR visuel des PDF scannés) -> decisions.json313python run_pipeline.py --source ... --decisions-json decisions.json --make-zip # 3. build314```315316**Dépendances** : `pymupdf` (requis pour l'extraction enrichie + le rendu OCR visuel) ;317`pytesseract` + `Pillow` + binaire `tesseract` pour l'OCR automatique en lot — **auto-installés318par le pipeline lui-même à chaque lancement s'ils manquent** (voir ci-dessus), donc à ne plus319jamais demander à l'utilisateur d'installer manuellement en amont.320321## Documents manquants — Top 50 par catégorie (étape 5bis)322323Après le tri, le rapport Excel gagne un onglet **« Documents à demander »** : le **Top 50 des324documents importants MANQUANTS**, groupés par catégorie et triés par priorité.325326Source : les listes DD de référence Hectelion (issues du SaaS VDR prep), une par pays, avec un327onglet par secteur (~344 exigences chacune, colonne `Priorité` Haute/Moyenne/Basse) :328- `data_sources/Hectelion - Listes DD - FRANCE.xlsx`329- `data_sources/Hectelion - Listes DD - SUISSE.xlsx`330331Mécanique (`run_pipeline.py --country FR|CH --sector <onglet>`) :3321. Charge la liste DD du pays + secteur choisis.3332. Marque chaque exigence **présent/manquant** par recouvrement de tokens avec les documents334 réellement classés dans la dataroom (statut « présents (estimés) » — à revérifier).3353. Écrit l'onglet, colonnes `Catégorie | Réf. | Document à demander | Priorité | Période | Base légale`.336337**Répartition PROPORTIONNELLE obligatoire** : les 50 slots sont distribués entre catégories338(apportionnement au plus fort reste, pondéré par le nb de manquants de chaque section, **min 1339par catégorie représentée**), au lieu de tout concentrer sur les grosses sections (Finance).340Ex. ~10 Finance, ~7 Juridique, ~6 RH, ~5 Fiscal, ~3 Opérations… À l'intérieur de chaque341catégorie, priorité Haute d'abord. Objectif : une demande client équilibrée couvrant tous les342volets de la DD.343344C'est la version **template-driven** de la checklist Phase 2 (plus fiable que le scraping) :345le pays oriente les obligations légales, le secteur la liste métier.346347## Charte graphique des livrables Excel348349Toujours appliquer la charte Hectelion (skill `hectelion-brand` auto-chargé) :350- Headers : fond `#182E4E`, texte blanc, Calibri 11 pt Bold351- Cellules input : fond cyan `#72C7E7`352- Cellules données : Calibri 9-11 pt, blanc353- Titres éditoriaux d'onglet : Cardo 25 pt / 18 pt354- Statut dedup : MINT vert / WARNING orange / ALERT rouge355356## Anti-patterns à éviter357358- ❌ **Inventer une classification** quand le document est illisible → forcer `11_Document à trier`359- ❌ **Renommer un doc qui va en 11_À trier** → garder son nom original360- ❌ **Ignorer les doublons exacts** → toujours les détecter et archiver séparément361- ❌ **Mettre tous les docs en racine d'un dossier N1** → toujours créer la structure N2362- ❌ **Hardcoder la langue FR** → respecter le choix utilisateur363364## Exemple d'invocation365366```367User: /dataroom-prep368Claude: [Pose TOUTES les questions au début via AskUserQuestion :369 Q1 source, Q2 destination, Q3 nom projet, Q4 langue structure,370 Q5 langue Excel, Q7 pays, Q8 secteur, Q9 checklist enrichie Oui/Non371 (+ si Oui : localisation, site web, secteur connu, sources)]372User: [répond à tout]373Claude: [déroule TOUT le pipeline sans interruption :374 extraction → classification → dedup → build dataroom + Excel375 → si checklist=Oui : enrich_checklist.py → scrape + analyse + Excel checklist]376Claude: [livre dataroom + Excel(s) + ZIP]377```378379Pour usage automatisé/scriptable, voir `scripts/run_pipeline.py` qui orchestre les 8 étapes.