Audit Financier — Rapport CFO Personnel
Transformez un dossier de fichiers de relevés bruts en un Rapport CFO Personnel : données vérifiées et une couche narrative qui répond à Que s'est-il passé ? Pourquoi ? Que dois-je faire ensuite ?
Priorité à la précision : les montants sont lus textuellement et rapprochés du solde courant — rien n'est inventé.
Indépendant de la banque. Fonctionne avec n'importe quelle banque ou export de compte, à partir d'une liste de transactions. Les colonnes, les lignes d'en-tête et l'ordre des dates (DMY/MDY/YMD) sont détectés automatiquement par fichier ; le nettoyeur de contrepartie est indépendant du type de rail (UPI, POS, ACH, SEPA, carte, virement, …). Rien n'est codé en dur pour une banque spécifique — vous confirmez la correspondance détectée automatiquement et ajustez les mots-clés de catégorie.
Pipeline (5 étapes)
ingérer -> analyser -> catégoriser (boucle jusqu'à >=99%) -> analyser_finance -> rapport (servir + rechargement à chaud)
Les scripts se trouvent dans cette compétence. Exécutez-les sur le dossier d'audit (le dossier contenant les fichiers de relevés). Définissez d'abord deux variables :
SKILL="<chemin absolu vers ce dossier de compétence>" # le dossier contenant ce SKILL.md
ROOT="<chemin absolu du dossier d'audit>" # où se trouvent les fichiers de relevés
Confidentialité — ne jamais envoyer de données réelles
Tous les fichiers de relevés, soldes, narrations et sorties générées restent locaux
dans ROOT/. Le dépôt de la compétence ne contient que des modèles, une configuration
d'exemple et des fixtures factices (assets/fixtures/sample_analysis.json).
Ignoré par Git (ne jamais pousser) : output/ (y compris report.html, analysis.json,
audit.db), fichiers de relevés, et config/mapping.json / overrides en direct.
Étiquettes optionnelles dans config/mapping.json : account_label ou account_last4 pour
le pied de page de la barre latérale (par défaut "Compte principal"). Nom commercial dans
config/business.json → display_name (par défaut "Entreprise").
Supposons que les fichiers de relevés soient déjà téléchargés dans ROOT
(PDF / XLSX / XLS / CSV / TXT).
Choisissez l'environnement d'exécution (l'utilisateur préfère Node.js) :
- Utiliser Node lorsque
nodeest disponible ET qu'aucune entrée n'est un PDF. - Utiliser Python lorsqu'une entrée est un PDF (le chemin Node ne peut pas analyser les PDF) ou que
nodeest indisponible.
Détecter et installer les dépendances :
# Chemin Node (préféré)
command -v node && node --version # nécessite Node >= 22 pour sqlite intégré
( cd "$ROOT" && npm install xlsx ) # UNIQUEMENT pour .xls/.xlsx ; CSV/TXT ne nécessitent rien
# Chemin Python (fallback / requis pour PDF)
python3 --version
pip install openpyxl "xlrd==2.0.1" pdfplumber pandas # + pandas pour l'étape d'analyse financière
Définissez comment vous invoquez une étape ($ETAPE = ingérer|analyser|catégoriser|analyser_finance|rapport) :
# Node : node "$SKILL/scripts/node/$ETAPE.mjs" --root "$ROOT" [args]
# Python : python3 "$SKILL/scripts/python/$ETAPE.py" --root "$ROOT" [args]
Étape 1 — Ingérer & détecter
node "$SKILL/scripts/node/ingest.mjs" --root "$ROOT" # ou python3 .../ingest.py --root "$ROOT"
Ceci prévisualise chaque fichier et écrit config/mapping.json avec une ligne d'en-tête
détectée automatiquement, les rôles des colonnes et un date_format explicite. Lisez la
prévisualisation et vérifiez mapping.json — les banques diffèrent. Si une entrée a un
_date_note, l'ordre des dates était ambigu (par ex. 03/04/2024) ; confirmez date_format
auprès de l'utilisateur. Chaque entrée de fichier nécessite : header_row, data_start_row,
date_format (un motif strptime comme %d/%m/%Y, ou auto), columns (rôle → index
basé sur 0), et amount_mode :
debit_credit— colonnes séparées pour retrait + dépôt (le plus courant)signed— une colonneamountdont le signe indique la directionamount_type— une colonneamountplus une colonnetypecontenant DR/CR
Corrigez tout index incorrect avant l'analyse.
Étape 2 — Analyser, normaliser, dédupliquer, valider
node "$SKILL/scripts/node/parse.mjs" --root "$ROOT" # ou .../parse.py
Écrit output/audit.db (SQLite). La répartition débit/crédit est dérivée du
montant signé de sorte qu'elle corresponde toujours à la chaîne de solde (en gérant
correctement les remboursements codés comme des retraits négatifs). Exigez que la
vérification d'intégrité soit RÉUSSIE (ou n/a quand il n'y a pas de colonne de solde).
Si elle ÉCHOUE :
- Revérifiez les colonnes de
mapping.json/data_start_row/date_format. - Relisez la prévisualisation de l'ingestion (relancez l'ingestion si nécessaire) ; confirmez que vous n'avez pas inclus de lignes d'en-tête/pied de page.
chain_issues > 0par fichier pointe vers les lignes exactes qui ont été mal analysées.
Ne passez pas à la catégorisation tant que l'analyse n'est pas réconciliée.
Étape 3 — Catégoriser (boucler jusqu'à >= 99 % par valeur)
cp "$SKILL/config/categories.example.json" "$ROOT/config/categories.json" # première exécution uniquement
# Pour un compte professionnel / freelance, aussi :
cp "$SKILL/config/business.example.json" "$ROOT/config/business.json" # puis éditez-le
node "$SKILL/scripts/node/categorize.mjs" --root "$ROOT" # ou .../categorize.py
Priorité des règles : overrides.json > business.json > categories.json ; la
priorité la plus élevée gagne. La catégorisation est priorité au script ; atteignez
99 % comme ceci :
- Exécutez categorize. Lisez le résumé de couverture et
output/uncategorized.csv(regroupés par commerçant, plus grande valeur en premier). - Pour les commerçants dont l'identité est évidente d'après la narration, ajoutez
vous-même des règles dans
config/overrides.json(voir format ci-dessous) — pas besoin de demander. - Pour les commerçants ambigus (pas clair qui/quoi, ou personnel vs professionnel pas clair), posez à l'utilisateur une question concise, puis ajoutez la règle.
- Réexécutez categorize. Répétez jusqu'à ce que la couverture en valeur ≥ 99 %.
Format de config/overrides.json :
{ "rules": [
{ "keywords": ["ACME", "ACME CORP"], "primary": "Revenus", "sub": "Honoraires ACME", "when": "credit" },
{ "keywords": ["GROSLOYER"], "primary": "Logement", "sub": "Loyer", "is_business": 0 }
] }
Visez à ce que chaque transaction porte une primary_cat et un sub_cat. La
contrepartie P2P factuelle de repli étiquette les transferts mais est comptée comme
"à revoir" — convertissez les plus importantes en règles réelles.
Étape 4 — Analyser financièrement (construire output/analysis.json)
python3 "$SKILL/scripts/python/analyze.py" --root "$ROOT"
Calcule les tranches d'exercice financier, les rapports par catégorie, la narration CFO,
le moteur de revenus, le résumé de la brûlure, les zones problématiques et le bilan
professionnel à partir de output/audit.db. Écrit output/analysis.json (et
facultativement findings.md localement — ne jamais envoyer).
Nécessite pandas. Ajustez config/business.json → display_name pour l'étiquette
de la section professionnelle (par défaut "Entreprise").
Étape 5 — Générer le rapport (servir + rechargement à chaud + ouverture automatique)
python3 "$SKILL/scripts/python/report.py" --root "$ROOT" --serve
Construit output/report.html à partir de analysis.json + lignes du grand livre
intégrées en ligne. Avec --serve, ouvre http://127.0.0.1:8765/ et recharge à chaud
lorsque la base de données / la configuration change (relance analyse + réaffichage).
Utilisez --refresh-analysis pour forcer une nouvelle analyse lors d'une construction
unique.
Interface du rapport (output/report.html) — Tableau de bord hybride Money.Audit
Coque : cadre d'application arrondi, barre latérale légère avec liste des exercices
- navigation par sections (scroll-spy), colonne principale pleine largeur. Titre : Ce qui compte pour votre argent.
Apparence : police sérif Fraunces + police UI Spline Sans ; coque crème
chaude (#f7f6f3), accent doré. Pas de SaaS gris générique.
Sections (barre latérale) : Aperçu, Moteur de revenus, Brûlure mensuelle, Zones problématiques, Bilan professionnel, Trésorerie & mouvements, Plan d'action, Toutes catégories, Grand livre (recherche + filtres).
Données intégrées : const ANALYSIS = … et const LEDGER = … — pas de récupération
externe. Le pied de page de la barre latérale affiche account_label provenant de la
correspondance (ne jamais coder en dur les numéros de compte dans le modèle).
Animation : emil-design-eng — :active scale(0.98), transitions de largeur de
barre, compatible avec mouvement réduit. Guide de style :
references/ui_style_guide.md.
Modèle : assets/report_template.html. Fixture factice pour la documentation :
assets/fixtures/sample_analysis.json.
Lorsque vous modifiez l'interface du rapport : éditez le modèle + le guide de style ;
ne jamais envoyer output/report.html réel. Régénérez localement via analyze → report.
Contenu du rapport
- Aperçu — score de santé, indicateurs, trois citations du CFO.
- Revenus / brûlure / problèmes — sections prioritaires sur les décisions avec possibilité d'explorer les catégories.
- Revue professionnelle — lorsque
config/business.jsonest présent. - Grand livre — preuves de transactions consultables (les 350 premières correspondances affichées).
Indicateurs : --port N, --no-open, --refresh-analysis. Sans --serve, écrit
output/report.html une fois (exécute d'abord l'analyse si analysis.json manque).
Méthodologie : references/financial_frameworks.md.
Remarque : L'interface hybride Money.Audit utilise le chemin Python d'analyse +
rapport. Le report.mjs de Node affiche encore le modèle CFO hérité pour les audits
simples sans analyse.
Disposition produite dans le dossier d'audit
ROOT/
├── <fichiers de relevés> # entrée (PDF/XLSX/XLS/CSV/TXT)
├── config/
│ ├── mapping.json # correspondance des colonnes (vérifier après ingestion)
│ ├── categories.json # règles de catégorie (à partir de l'exemple)
│ ├── business.json # facultatif : revenus/paye/infrastructure professionnels
│ └── overrides.json # vos étiquettes ajoutées pendant la boucle
└── output/
├── audit.db # source de vérité SQLite
├── analysis.json # étape d'analyse (local uniquement — données personnelles)
├── uncategorized.csv # file d'attente de révision (régénérée à chaque exécution de catégorisation)
└── report.html # tableau de bord Money.Audit (local uniquement — données personnelles)
La compétence n'écrit que ce qui est nécessaire : configuration modifiable, la base de
données SQLite qui transporte l'état entre les étapes, la file d'attente de révision et le
rapport final. Les vidages intermédiaires (la prévisualisation de l'ingestion, le JSON du
rapport) sont imprimés/intégrés, pas écrits comme fichiers supplémentaires. mapping.json
et audit.db doivent persister sur le disque car chaque étape s'exécute comme un processus
séparé.
Remarques
- Les mêmes
mapping.json/config/ schéma SQLite fonctionnent avec les deux environnements d'exécution ; vous pouvez changer d'environnement en cours d'audit. - Gardez les fichiers de relevés bruts hors du contrôle de version (ils contiennent des données personnelles).
- Pour le schéma complet, les calculs de validation et la référence de configuration, voir reference.md.
- Pour les cadres d'analyse (taux d'épargne, 50/30/20, benchmarks, logique de recommandation), voir references/financial_frameworks.md.
Demandes courantes traitées par cette compétence
- « Auditer / catégoriser mes relevés bancaires et faire un rapport » — pipeline complet.
- « Quel est mon rapport CFO personnel pour l'exercice 2024-25 ? » — utiliser le sélecteur de période après le rapport.
- « Quel est mon taux d'épargne et comment l'améliorer ? » — résumé exécutif + plan d'action.
- « Où est-ce que je dépense trop ? » — intelligence des dépenses + contrefactuels.
- « Que devrais-je arrêter/commencer/continuer ? » — section plan d'action.
- « Demander à mon CFO concernant la trésorerie / la dette / les investissements » — utiliser les invites Demander à votre CFO avec votre agent.
- « Améliorer l'interface du rapport / la rendre en pleine largeur / corriger la mise en
page » — éditer
assets/report_template.htmlselon references/ui_style_guide.md ; régénérer localement avec analyze → report. Ne jamais envoyeroutput/report.html.