Avant la réponse, prends cinq secondes pour imaginer ce qui va se passer.
COURS INTERACTIF · VERSION 0.1.0
Comprendre Eligibou,
une dépense à la fois.
On commence par le tout début : ce qu’est un programme, un langage, une fonction, une bibliothèque, un fichier et une donnée. Ensuite seulement, tu suivras une dépense depuis Excel jusqu’à sa revue humaine et son export.
Le contrat du cours — aucune connaissance informatique n’est supposée. On part des mots, on écrit quelques lignes, puis on regarde comment Eligibou assemble ses pièces.
APPRENDRE SANS SE NOYER
Une méthode qui te fait pratiquer, pas réciter
Un novice ne doit pas tout retenir d’un coup. Ici, chaque idée revient plusieurs fois : d’abord avec une image, ensuite avec un exemple, puis avec une action que tu fais toi-même.
Lis une explication courte liée à un exemple concret, pas une définition isolée.
Change une valeur, clique, exécute une ligne de code ou choisis une réponse.
Dis avec tes mots ce que tu viens de voir. C’est le meilleur test de compréhension.
Les mêmes idées réapparaissent plus loin, dans le vrai code d’Eligibou.
Savoir raconter le trajet d’une dépense, du fichier à la décision humaine.
Distinguer un langage, un outil, un format de fichier, une bibliothèque et une boîte de code.
Repérer une variable, une fonction, une condition et le rôle d’un fichier sans comprendre chaque caractère.
Modifier un mini-programme, lancer un test et savoir où chercher quand quelque chose ne marche pas.
Quand sais-tu vraiment que tu as compris ?
Choisis la réponse la plus utile. Elle guide tout le cours.
Tu n’as pas besoin de comprendre une ligne entière immédiatement. Dans ce cours, comprendre le rôle d’une ligne est déjà une vraie victoire. Les détails viendront après.
LE MODÈLE MENTAL QUI DÉBLOQUE TOUT
Une application reçoit, transforme, montre et mémorise
Un ordinateur ne “devine” rien : il suit une recette. Pour comprendre n’importe quelle app, retrouve toujours ce qui entre, ce qui décide, ce qui sort et ce qui reste enregistré.
Entrée : le fichier Excel
Une personne choisit un fichier de dépenses. C’est une entrée : quelque chose arrive dans l’application depuis l’extérieur.
Question à se poser : “Qu’est-ce que l’utilisateur donne au programme ?”
Un clic, un fichier, une phrase, un nombre.
Une fonction, une condition ou une règle écrite.
Un texte, une décision, un écran ou un fichier.
Une ligne, un lot, une préférence ou une trace.
Une petite app reçoit 12 €, vérifie si le montant est positif puis affiche “dépense enregistrée”.
Quel est le bon résumé ?
LE DICTIONNAIRE AVANT LE CODE
Les mots de base, avec des exemples
Avant de parler d’Eligibou, on apprend à reconnaître les objets d’un programme. Clique sur un mot : tu verras sa traduction et un mini-exemple.
Programme
une recette d’instructionsUn programme est une liste d’instructions que l’ordinateur exécute dans un ordre. Comme une recette : prendre les ingrédients, mélanger, puis servir.
1. prendre un nom
2. afficher « Bonjour »À chaque nouveau mot, demande-toi : “Est-ce un langage ? Un fichier ? Une bibliothèque ? Une action ? Une donnée ?” Cette question suffit pour ne pas se perdre.
LES MOTS QUI SE RESSEMBLENT SANS ÊTRE LA MÊME CHOSE
Évite les confusions les plus fréquentes
C’est normal de confondre les mots au début : ils arrivent souvent ensemble. Le bon réflexe est de demander : “Est-ce une façon d’écrire ? un outil ? un fichier ? ou une boîte du projet ?”
Un langage
Une façon d’écrire des instructions.
Rust, TypeScript, JavaScriptUne bibliothèque
Des outils de code déjà construits que l’on réutilise.
React, SQLxUn outil
Un programme qui aide à construire, lancer ou emballer l’app.
Tauri, pnpm, CargoUn format
Une manière de ranger de l’information dans un fichier.
JSON, YAML, XLSXUne crate
Une boîte de code Rust dans le projet.
fctva-import, fctva-exportUn fichier
Un document enregistré sur le PC, qui peut contenir du code ou des données.
App.tsx, core.yaml“Rust est un outil.”
Non : Rust est un langage. Cargo est l’outil qui aide Rust à organiser et lancer le projet.
“JSON est du code.”
Pas forcément : JSON est surtout une façon de décrire une fiche de données sous forme de texte.
“Une crate est une app.”
Non : c’est une partie de l’app, rangée avec un métier précis.
Rust est…
Réponds avant de regarder le reste du cours.
FAIS UNE HYPOTHÈSE AVANT LA RÉPONSE
Prédire est plus utile que relire
Avant d’exécuter un programme, essaie de prévoir son résultat. Même une mauvaise hypothèse est utile : elle rend l’explication qui suit beaucoup plus mémorable.
Que va afficher le programme ?
const montant = 12;
if (montant > 0) {
print("dépense");
}Indice : une condition pose une question. Ici, 12 est-il plus grand que 0 ?
Et si le montant vaut -4 ?
if (montant > 0) {
print("dépense");
} else {
print("à contrôler");
}Indice : else signifie “dans les autres cas”.
Dans la situation A, quel texte apparaît ?
Ne lance rien : raisonne d’abord avec la question posée par if.
Sans regarder les définitions : raconte à voix haute la différence entre une variable et une condition. Une phrase suffit.
ATELIER · TU ÉCRIS, L’ORDINATEUR RÉPOND
Ton premier mini-programme
Pour voir immédiatement le lien entre une instruction et un résultat, écris quelques lignes de JavaScript dans le cadre ci-dessous. JavaScript est utilisé ici uniquement parce que ton navigateur sait l’exécuter directement ; Eligibou, lui, utilise aussi Rust.
Clique sur « Exécuter » pour voir le résultat.
Ce qui s’est passé : le navigateur a lu les lignes une par une. const a rangé une valeur dans une boîte, function a défini une action et if a posé une question.
Change le prénom
Remplace “Mina” par ton prénom et exécute.
Change le nombre
Mets 1 : la phrase de la condition disparaît.
Ajoute une ligne
Écris print("Je programme !").
Ce petit atelier ne prétend pas que JavaScript est le langage d’Eligibou. Il montre simplement les idées communes à tous les langages : données, fonctions, conditions et résultats. Ensuite, on verra comment Rust utilise les mêmes idées avec une autre écriture.
UNE APP, C’EST UNE IDÉE QUI DEVIENT UNE ACTION
Construis une mini-app avant de regarder la vraie
Avant les grands mots, fabrique une version miniature d’Eligibou. Elle ne connaît que trois règles simples, mais elle possède déjà un écran, des données, une décision et un résultat.
L’étiqueteuse de dépenses
Choisis une description, un montant et une règle. Prédis le résultat, puis clique sur le bouton.
Dépense à regarder
PRÊTRenseigne la fiche et lance l’exemple. La décision affichée ne vaut pas une décision FCTVA réelle : elle sert uniquement à apprendre.
Des champs où une personne écrit ou choisit.
La description, le montant et la règle choisie.
Une petite recette qui compare ces données.
Un texte clair affiché à la personne.
Lis le code comme une histoire : on reçoit une description et un montant, on pose une question, puis on renvoie une étiquette.
function etiqueter(description, montant) {
if (montant > 0 && description.includes("travaux")) {
return "bon signal : à vérifier";
}
return "il faut plus d’informations";
}Dans cette mini-app, où se trouve la décision ?
Repère la partie qui pose une question et choisit une réponse.
LES OUTILS, EXPLIQUÉS
La stack : les outils de l’application
“Stack” veut simplement dire “ensemble d’outils utilisés ensemble”. Maintenant que les mots de base sont posés, on peut regarder l’équipe d’Eligibou.
INSPECTEUR DE COUCHE
L’écran que voit l’utilisateur
React construit les composants visuels : boutons, tableaux, tiroirs de revue et indicateurs de progression. TypeScript ajoute des garde-fous sur les données qui circulent dans l’interface.
Quand tu cliques, React prépare un appel vers le cœur Rust via client.ts.
TypeScript est le langage de la partie écran. TSX est une écriture qui permet de mettre des balises d’écran dans ce code.
apps/desktop/src/Rust est un langage de programmation. Ici, il écrit le travail de fond : lire, vérifier, mémoriser, analyser et exporter.
crates/ · src-tauri/Ce sont deux façons d’écrire du texte lisible. YAML porte les réglages ; Markdown porte les explications métier.
rules/ · local/SQL pose des questions aux tableaux SQLite. JSON décrit une fiche dans un texte que plusieurs programmes peuvent relire.
fctva-storage/ · types.tsEligibou n’est pas “une app IA”. C’est une application locale : React fabrique l’écran, Rust fait le travail de fond, SQLite garde les informations et l’IA n’est qu’un moteur que l’on peut remplacer.
Qui doit lire un fichier Excel ?
Choisis la boîte de code qui transforme les cellules du classeur en fiches compréhensibles par le reste de l’application.
UN CHOIX D’ORGANISATION, PAS UNE COLLECTION DE MOTS
Pourquoi Eligibou ne met pas tout dans un seul fichier
Séparer les responsabilités ne veut pas dire “faire compliqué”. Cela veut dire donner un travail clair à chaque partie, comme dans une cuisine : une personne prépare, une autre cuit, une autre vérifie.
L’écran
Il montre des boutons, des listes et des résultats. Son travail est de rendre les choses utilisables.
React + TypeScriptLe travail de fond
Il lit les fichiers, vérifie les données, applique les règles et fabrique les exports.
Rust + cratesLa mémoire
Elle garde les lots et les décisions pour les retrouver plus tard, même après fermeture.
SQLiteLes consignes
Elles vivent dans des textes lisibles afin de pouvoir être relues et changées sans chercher partout.
YAML + MarkdownTu veux modifier une consigne FCTVA lisible par une personne métier.
Où cherches-tu d’abord ?
LIRE DU CODE SANS TOUT DÉCHIFFRER
Lis une ligne comme une phrase
Ne lis pas le code caractère par caractère. Cherche d’abord les mots qui donnent le rôle : une valeur, une action, une question, un résultat. Clique sur chaque ligne de l’exemple.
Une valeur avec un nom
const montant = 120 crée une boîte appelée montant et y range le nombre 120. Le programme peut réutiliser ce nombre plus bas.
La même idée dans deux écritures
JavaScript et Rust ne s’écrivent pas pareil. Pourtant les deux lignes rangent la même information sous le nom montant.
JavaScript : const montant = 120;
Rust : let montant = 120;Quelle ligne renvoie un résultat vers l’endroit qui a appelé la fonction ?
LE PLAN DE L’APPLICATION
Une ligne, plusieurs relais
Une architecture est le plan d’un programme : quelles sont ses grandes pièces, et comment une information passe de l’une à l’autre ? Clique sur une étape pour voir la traduction simple.
Le fichier ne bouge pas
L’utilisateur choisit un fichier. Eligibou le lit comme une suite de petits nombres, sans toucher à l’original, et calcule une signature pour reconnaître son contenu.
L’écran dit au programme : “fais cette action”. Par exemple invoke('import_file') signifie “importe ce fichier”.
Le programme dit à l’écran : “voici où j’en suis”. React écoute cette nouvelle pour afficher la progression.
Le fichier devient une fiche, puis une proposition, puis une relecture.
L’écran montre une suggestion ; l’agent confirme ou corrige.
Les lots, alertes, propositions et décisions restent consultables.
LIRE LES FICHIERS
Le plan des pièces
Le “dépôt” est simplement le dossier complet du projet. On ne mémorise pas chaque fichier : on apprend à reconnaître les boîtes et le métier de chacune.
FCTVApp/
├─ apps/desktop/
│ ├─ src/App.tsx
│ ├─ src/client.ts
│ ├─ src/types.ts
│ └─ src-tauri/src/lib.rs
├─ crates/
│ ├─ fctva-domain/
│ ├─ fctva-import/
│ ├─ fctva-rules/
│ ├─ fctva-ai/
│ ├─ fctva-analysis/
│ ├─ fctva-storage/
│ ├─ fctva-export/
│ └─ fctva-observability/
├─ rules/active/core.yaml
├─ local/
├─ Cargo.toml
├─ package.json
└─ README.md apps/desktop/src/App.tsx
Le composant racine de l’interface. Il garde l’écran courant, le lot actif, les lignes, le filtre, la configuration d’analyse et les écouteurs d’événements.
Regarde le bouton et trouve le call() qui part de App.tsx.
Dans client.ts, repère invoke et le nom exact de la commande.
Dans src-tauri/src/lib.rs, retrouve #[tauri::command] puis le service appelé.
// React / TypeScript
await call<ImportStats>('import_file', { fileName, bytes })
// Rust / Tauri
#[tauri::command]
async fn import_file(...) -> Result<ImportStats, AppError> {
let parsed = parse_workbook(...)?;
state.store.insert_batch(...).await?;
Ok(parsed.stats)
}Tu veux changer le texte d’un bouton
Quel fichier ou ensemble de fichiers regardes-tu en premier ?
LES INFORMATIONS PRENNENT FORME
De la cellule à la dépense
Une donnée, c’est une information. Le programme la transforme progressivement en une fiche claire, tout en conservant la valeur d’origine pour pouvoir vérifier.
Ligne brute
La ligne telle qu’elle arrive du fichier : des noms de colonnes et des valeurs parfois étranges.
RowData · nom interneFiche de dépense
Une fiche rangée avec montant, mandat, fournisseur, dates et alertes.
ExpenseRecord · nom RustProposition
Une réponse expliquée, avec les règles utilisées, l’incertitude et les manques.
AnalysisResult · résultatTrace de relecture
La décision finale de la personne qui a relu la ligne.
ReviewRecord · décisionpub struct ExpenseRecord {
id: Uuid,
raw: RowData, // original conservé
amount: Option<Decimal>,
mandate_number: Option<String>,
warnings: Vec<String>,
excluded_from_ai: bool,
}Option veut dire “peut-être absent”. Uuid est un identifiant unique, Decimal un nombre précis et Vec une liste. Le logiciel décrit donc clairement ce qu’il peut recevoir.
SQLite est une petite base de données dans un fichier : fctva-assist.sqlite3. Elle garde les tableaux même après fermeture de l’application.
Le petit travail invisible qui évite les gros problèmes
Avant l’analyse, le code lit le fichier, détecte la feuille, reconnaît des variantes de colonnes, convertit les montants et signale les incohérences.
Types de fichiers
.xls, .xlsx, .xlsm, .csv
Signature
empreinte SHA-256 du fichier source
Doublons
clé mandat / compte / montant / description
Dates
date dans la cellule ou le libellé
Une colonne s’appelle “Total TTC”
Quel champ métier le mapping automatique doit-il remplir ?
PLUSIEURS FAÇONS DE RÉFLÉCHIR
Règles d’abord, moteur ensuite, humain toujours
Une analyse “hybride” mélange plusieurs outils : des consignes écrites, un moteur qui propose une réponse et une personne qui vérifie. Le mot provider désigne simplement l’adaptateur vers ce moteur.
RuleSet.evaluate · signaux + anomaliesAnalysisInput · dépense + contexteprovider · Mock / Codex / HTTPvalidate_result · garde-fousReviewRecord · décision humaineMock : le faux moteur qui permet d’apprendre sans réseau
Le Mock applique une logique de démonstration et renvoie une structure d’analyse. Il permet de tester l’interface et le stockage sans envoyer une dépense nulle part.
analyze(input) → AnalysisResultLe texte d’une cellule est une donnée à lire, pas une instruction. Une phrase dans une dépense ne peut jamais commander le programme.
La vérification finale peut corriger une proposition trop incertaine : validate_result est le nom interne de ce contrôle.
Si la réponse structurée en JSON est incomplète, le programme peut demander une seule correction. Il ne recommence pas indéfiniment.
Fais parler le moteur d’exemple
Ce mini-jeu simplifie volontairement la fonction interne qui imite une analyse. Il ne remplace pas la méthodologie FCTVA : il montre comment des signaux modifient une proposition.
Le mot “investissement” et une description de travaux donnent un signal favorable.
Un contrat est une promesse : chaque moteur doit savoir recevoir une fiche et renvoyer une analyse, même s’il travaille différemment à l’intérieur.
#[async_trait]
pub trait AiAnalysisProvider {
fn kind(&self) -> AnalysisProviderKind;
async fn analyze(&self, input: AnalysisInput)
-> Result<AnalysisResult, ProviderError>;
}DE L’ÉCRAN AU PROGRAMME
Tauri fait le pont
“Desktop” veut dire une application qui s’ouvre comme une vraie fenêtre sur le PC. React dessine cette fenêtre, Rust travaille derrière, et Tauri fait passer les messages entre les deux.
Un bouton dans App.tsx demande : “analyse ce lot”. Le nom interne est analyze_batch.
client.ts est le traducteur. Tauri transmet la demande à la fonction Rust autorisée.
Le résultat revient sous forme de données structurées ; des messages de progression préviennent l’écran.
Les noms du code sont techniques, mais l’idée tient en une phrase : l’écran demande une action, puis reçoit le résultat.
// client.ts
export async function call<T>(command: string, args?: Record<string, unknown>) {
return isTauri() ? invoke<T>(command, args) : demo<T>(command, args)
}
// src-tauri/src/lib.rs
#[tauri::command]
async fn dashboard(state: State<'_, AppState>, batch_id: Uuid)
-> Result<DashboardSummary, AppError> {
Ok(state.store.dashboard(batch_id).await?)
}Le bouton “Analyser le lot” ne répond plus
Quel chemin suis-tu pour chercher la panne ?
client.ts détecte l’absence de Tauri et utilise un petit mode de démonstration. C’est pourquoi l’interface peut être prévisualisée sans lancer le programme Windows complet.
FAIRE CONFIANCE À UNE MODIFICATION
Tester, c’est poser une question précise au programme
Un test ne dit pas “tout est parfait”. Il vérifie une petite promesse. Par exemple : “si je donne ce fichier, les montants sont-ils bien lus ?” C’est ce qui permet de modifier le code sans jouer à la loterie.
Préparer
Choisir une entrée connue : une ligne, un fichier ou une situation miniature.
montant = -4Agir
Demander au programme de faire exactement une chose.
analyser(montant)Comparer
Vérifier que le résultat est celui attendu.
résultat = “à contrôler”“Le fichier original ne doit pas être modifié.”
Le test garde une copie du fichier, lance la lecture, puis vérifie que la copie et l’original sont identiques. S’ils diffèrent, le test alerte avant qu’une personne n’utilise la version Windows.
Quel est le meilleur test pour une règle disant “un montant négatif doit demander un contrôle” ?
UN BUG EST UNE PISTE, PAS UN ÉCHEC
Déboguer : réduire le problème avant de le corriger
Quand un bouton ne répond plus, ne change pas dix choses au hasard. Suis le trajet de l’information et vérifie une étape après l’autre. C’est plus lent pendant une minute, mais beaucoup plus rapide au total.
Refaire exactement l’action qui pose problème.
Regarder le message, le résultat ou l’étape où cela s’arrête.
Tester un petit exemple : une seule ligne au lieu d’un gros fichier.
Faire une correction, puis relancer le même test.
“Analyser le lot” ne fait rien
Le trajet attendu est : bouton dans App.tsx → traducteur client.ts → commande Rust → service d’analyse.
Le premier objectif n’est pas de réparer : c’est de trouver où le message s’arrête.
Vérifie le clic
Le bouton réagit-il visuellement ?
Vérifie la demande
Le traducteur reçoit-il “analyser le lot” ?
Vérifie le travail
La partie Rust démarre-t-elle l’analyse ?
Un bouton ne répond plus. Quelle action fais-tu en premier ?
LA BOUCLE SE FERME
Relire, exporter, livrer
Une application métier n’est terminée que quand on peut relire, corriger, retrouver et livrer le résultat à quelqu’un d’autre.
L’humain confirme
Le tiroir de ligne affiche les données source, les anomalies, la proposition, le motif, l’incertitude et les pièces manquantes.
review_case → ReviewRecordnom interne : enregistrer la relectureUn fichier Excel traçable
fctva-export crée plusieurs feuilles au lieu d’écraser le fichier d’entrée. XLSX est simplement le format moderne d’Excel.
Voir ce qui s’est passé
Le programme écrit des messages de suivi : import commencé, étape terminée, erreur rencontrée. Les événements JSON gardent une forme que les outils peuvent relire, tandis que le Journal IA conserve la demande, la réponse, la durée et l’éventuelle correction.
Assembler la fenêtre
Tauri rassemble l’écran construit et le programme Rust dans un installeur Windows. Les fichiers de configuration disent comment fabriquer cette fenêtre et quelles ressources joindre.
tauri.conf.jsontauri.windows.conf.jsonscripts/prepare-codex-windows.mjstooling/codex-cli-manifest.jsonLes commandes à essayer soi-même
Ouvre PowerShell dans le dépôt FCTVApp. Fais-les dans l’ordre et lis le résultat de chaque commande.
pnpm installpnpm buildcargo test --workspacepnpm devpnpm --dir apps/desktop tauri buildÀ quoi sert chaque commande ? pnpm installe et lance la partie écran, cargo construit et teste Rust, et Tauri assemble les deux dans une application Windows.
AVANT D’ÉCRIRE UNE COMMANDE
Windows sans peur : une commande est une phrase courte
PowerShell est une fenêtre où l’on donne une instruction écrite au PC. Ce n’est pas une formule magique : chaque commande dit soit “va ici”, “montre-moi ceci”, “installe”, “teste” ou “lance”.
cd : changer de dossier
Cette commande dit à PowerShell : “à partir de maintenant, travaille dans ce dossier”. C’est comme ouvrir un tiroir avant de chercher un document dedans.
cd .\FCTVAppQuestion à se poser : “Dans quel dossier suis-je avant de lancer la suite ?”
Le réflexe débutant : après chaque commande, lis les deux ou trois dernières lignes. Si tu ne comprends pas, ne passe pas à l’étape suivante ; copie le message et cherche ce qu’il veut dire.
Tu veux voir les fichiers présents dans le dossier où tu te trouves.
TRANSFÈRE CE QUE TU AS APPRIS
Imagine ton propre petit programme
Le meilleur moyen de vérifier que les notions tiennent est de les utiliser pour une autre idée. Tu ne vas pas créer un énorme produit : seulement une app qui reçoit quelque chose, applique une règle et affiche un résultat.
Décris une idée en une minute
Mon étiqueteuse de tâches
- Entrée : une tâche et sa priorité
- Règle : la priorité est-elle urgente ?
- Sortie : un message “à faire aujourd’hui” ou “à planifier”
- Première version : une page, un bouton, un résultat.
Ce plan suffit pour commencer. Tu ajouteras une mémoire, un second écran ou des règles seulement après avoir fait marcher la première version.
Évite “gérer toute ma vie”. Commence par “étiqueter une tâche”.
Un champ, un bouton et un résultat sont déjà une application.
Écris le “si… alors…” en français avant de le coder.
Invente un exemple qui doit produire un résultat clair.
Quel premier projet est le plus adapté à un débutant ?
Explique ton mini-projet à quelqu’un en utilisant les quatre mots : entrée, règle, résultat, mémoire. S’il comprend le principe, tu as déjà une base solide.
Quel composant intervient ?
Réponds aux quatre questions, puis demande ton score.
“Eligibou est une application qui s’ouvre dans une fenêtre. React dessine l’écran, Rust fait le travail de fond, SQLite garde les informations, puis une personne vérifie avant l’export Excel.”
Clique sur un mot pour sa traduction en langage simple.
Ton atelier est prêt
Valide les étapes et le défi final pour afficher ton badge de compréhension.