# Coder avec l'IA : le guide complet, du premier prompt à la production

Un agent de code (Claude Code, Codex, Antigravity, GitHub Copilot, Cursor…) peut écrire en dix minutes ce qui te prenait une journée. Il peut aussi, en dix minutes, casser ce qui marchait, inventer une bibliothèque et te laisser un projet que plus personne ne comprend. La différence ne vient pas de l'outil : elle vient de ta méthode.

Ce guide décrit cette méthode, du premier prompt jusqu'à la mise en production. Il vaut pour tous les outils : les noms de fichiers et de commandes changent, les principes restent.

**Pour qui ?**

- **Débutant** : lis les sections 1 à 4, 7, 9 et 10. Tu apprendras à garder la main et à comprendre ce que l'IA produit.
- **Intermédiaire** : ajoute les sections 5, 6, 8 et 11. Tu passeras de « l'IA m'aide » à « je pilote un agent sur un vrai projet ».
- **Professionnel** : les sections 8, 12, 13, 14 et 15 te donnent le cadre pour livrer en production avec un agent autonome, tester ton application comme un attaquant, sans perdre en qualité.

Tout au long du guide, on suit un même exemple : **AgriScan**, une app web qui diagnostique une maladie du maïs à partir d'une photo, pour les petits producteurs au Togo.

## 1. Les 10 règles d'or

L'IA est un coéquipier très rapide qui n'a aucune mémoire de ton projet et aucune responsabilité sur le résultat. Toi, tu as les deux.

1. **Tu es le chef de projet, l'IA exécute.** Tu décides quoi construire, pour qui et dans quel ordre. L'IA propose et produit.
2. **Le contexte vit dans des fichiers, pas dans ta tête.** Ce que l'agent doit savoir à chaque session (stack, commandes, règles, design) s'écrit une fois dans le dépôt (sections 2 à 5).
3. **Cadre avant de coder.** Un problème flou donne un code flou. Une page qui dit quoi, pour qui et ce qui est hors périmètre économise des heures (section 3).
4. **Découpe en jalons, livre un MVP testable d'abord.** On n'ajoute pas l'étage 3 tant que le rez-de-chaussée ne tient pas debout (section 6).
5. **Plan, puis code.** Pour toute tâche de plus de quelques lignes, demande un plan, valide-le, puis laisse coder (section 7).
6. **Petits pas, petits commits.** Une tâche = un commit qui marche. Tu peux toujours revenir au dernier état vert.
7. **Vérifie tout ce qui compte.** Lance, teste, lis le diff. Un code qui a l'air juste n'est pas un code qui marche. Ne fusionne jamais une ligne que tu ne saurais pas expliquer.
8. **L'autonomie de l'agent se mérite.** Plus tes tests et tes garde-fous sont solides, plus tu peux laisser l'agent travailler seul (section 8).
9. **Reste capable de déboguer sans l'IA.** Quand l'agent tourne en rond, c'est toi qui dois reprendre la main (section 10).
10. **Protège tes secrets et cite tes outils.** Jamais de clé, de mot de passe ou de donnée personnelle dans un prompt ou un commit. Et dis dans ton README quels outils IA tu as utilisés.

## 2. Les outils et où chacun lit ses instructions

Tous les agents de code fonctionnent de la même façon : au début de chaque session, ils lisent un ou plusieurs fichiers Markdown du dépôt pour savoir comment travailler. Seul le nom du fichier change.

| Outil | Fichier d'instructions du projet | À savoir |
| --- | --- | --- |
| Claude Code | `CLAUDE.md` à la racine (et dans les sous-dossiers) | `/init` en génère un premier jet. Un `CLAUDE.md` peut importer un autre fichier avec `@AGENTS.md`. |
| OpenAI Codex | `AGENTS.md` | Lu automatiquement au début de chaque session. Réglages dans `.codex/config.toml`. |
| Google Antigravity | `GEMINI.md` ou `AGENTS.md` à la racine, règles dans `.agents/rules/` | Chaque fichier de règles est limité à 12 000 caractères. |
| GitHub Copilot | `.github/copilot-instructions.md`, `.github/instructions/*.instructions.md`, `AGENTS.md` | Le fichier `AGENTS.md` le plus proche du code modifié l'emporte. |
| Cursor et d'autres | Leur propre dossier de règles, et souvent `AGENTS.md` | Vérifie la documentation de ton outil. |

**Le conseil qui t'évite de tout dupliquer :** fais de `AGENTS.md` ta source de vérité (c'est un [format ouvert](https://agents.md) lu par la plupart des agents), et pour les outils qui veulent leur propre fichier, fais-le pointer dessus. Par exemple, un `CLAUDE.md` d'une ligne :

```markdown
@AGENTS.md
```

Ainsi, changer d'outil (ou en utiliser deux dans la même équipe) ne change rien à tes règles. C'est ce qui rend ce guide valable dans dix ans : les outils passent, tes fichiers restent.

## 3. Cadrer avant de coder

La plupart des projets ratés avec l'IA ne le sont pas à cause du code, mais parce que personne n'a écrit ce qu'on construisait. L'IA comble alors les trous avec des suppositions, et chaque supposition est un bug potentiel.

Avant la première ligne de code, écris un `docs/PRODUCT.md` d'une page :

```markdown
# AgriScan

## Le problème
Les petits producteurs de maïs au Togo détectent les maladies trop tard,
faute d'agronome disponible.

## Pour qui
Producteurs avec un smartphone Android d'entrée de gamme, connexion 3G instable,
qui lisent le français simple.

## Ce que fait le MVP
1. Le producteur prend une photo d'une feuille.
2. L'app renvoie : maladie probable, niveau de confiance, un conseil d'action.

## Critères de réussite
- Réponse en moins de 10 secondes en 3G.
- Une photo qui n'est pas une feuille de maïs est refusée poliment.

## Hors périmètre (pour l'instant)
- Comptes utilisateurs, historique, paiement, application mobile native.
```

La section **Hors périmètre** est la plus importante pour travailler avec un agent : elle l'empêche d'ajouter une base de données ou un système de connexion « parce que c'est mieux ».

Tu peux faire ce cadrage avec l'IA, en lui demandant de te poser des questions plutôt que de répondre :

```text
Je veux construire une app qui aide les producteurs de maïs à détecter les maladies.
Avant de proposer quoi que ce soit, pose-moi les 8 questions les plus importantes
pour cadrer le MVP (utilisateurs, contraintes, critères de réussite, hors périmètre).
Ensuite, rédige docs/PRODUCT.md à partir de mes réponses.
```

## 4. Les fichiers de contexte

Voici le kit complet. Pour un hack de 2 heures, `README.md` et `AGENTS.md` suffisent. Pour un vrai produit, ajoute les autres au fil de l'eau.

| Fichier | Ce qu'il contient | Quand le créer |
| --- | --- | --- |
| `README.md` | Ce que fait le projet, comment le lancer | Toujours |
| `AGENTS.md` | Les instructions pour l'agent : stack, commandes, règles, format du compte rendu | Toujours |
| `docs/PRODUCT.md` | Le problème, les utilisateurs, le MVP, le hors périmètre (section 3) | Avant de coder |
| `docs/ARCHITECTURE.md` | Comment le code est organisé et pourquoi | Dès qu'il y a plus de 3 fichiers |
| `docs/DESIGN.md` | Le système visuel : couleurs, typo, boutons, composition (section 5) | Dès qu'il y a une interface |
| `STYLE_GUIDE.md` | Les conventions de code | Dès que vous êtes deux |
| `docs/ROADMAP.md` | Les jalons et leur état (section 6) | Avant de coder |
| `docs/PROGRESS.md` | Le journal des sessions de l'agent (section 8) | Dès la première session autonome |
| `docs/decisions/` | Une note courte par décision importante (ADR) | Quand une décision engage le projet |

### AGENTS.md : le fichier le plus important

Garde-le court (une à deux pages) : l'agent le relit à chaque session, et un fichier trop long dilue ce qui compte. Mets-y ce que l'agent ne peut pas deviner en lisant le code, et renvoie vers les autres fichiers pour le détail.

```markdown
# AGENTS.md

## Le projet
AgriScan : diagnostic des maladies du maïs à partir d'une photo, pour les petits
producteurs au Togo. Textes visibles en français simple.
Avant de travailler, lis docs/PRODUCT.md, docs/ROADMAP.md et la fin de docs/PROGRESS.md.

## Stack
- Python 3.12, FastAPI, Jinja2, CSS sans framework (voir docs/DESIGN.md)
- Modèle : Gemma 4 via l'API Gemini (SDK google-genai)
- Gestion des dépendances : uv

## Commandes
- Installer : uv sync
- Lancer : uv run fastapi dev app/main.py
- Tester : uv run pytest
- Vérifier le style : uv run ruff check . && uv run ruff format --check .

## Structure
- app/main.py : routes ; app/gemma.py : seul endroit qui appelle le modèle
- app/prompts.py : tous les prompts ; app/static/css/ : styles (voir docs/DESIGN.md)
- tests/ : un fichier de test par module

## Règles de travail
- Travaille uniquement sur le jalon en cours de docs/ROADMAP.md.
- Pour toute tâche de plus de 30 lignes, propose un plan avant de coder.
- Chaque nouvelle fonction a un test. Lance les tests et le linter avant de dire « terminé ».
- N'ajoute aucune dépendance sans le demander et sans expliquer pourquoi.
- Ne modifie pas les fichiers hors de app/, tests/ et docs/ sans demander.
- Si tu bloques deux fois sur la même erreur, arrête-toi et explique ce que tu as essayé.

## Sécurité
- Les secrets viennent des variables d'environnement (.env, jamais commité).
- Ne lis pas, n'affiche pas et ne modifie pas .env.
- Aucune commande qui touche la production, la base de données partagée ou git push --force.

## Compte rendu de fin de tâche
À la fin de chaque tâche, réponds avec ce format, puis ajoute-le en tête de docs/PROGRESS.md :
- Fait : ce qui a changé, en 3 lignes max
- Fichiers : la liste des fichiers modifiés
- Vérifié : les commandes lancées et leur résultat
- Pour tester toi-même : les étapes exactes
- Décisions : les choix que tu as faits et pourquoi
- Reste à faire / risques : ce qui n'est pas fini ou pas sûr
- Prochaine étape proposée
```

### STYLE_GUIDE.md

Il garde le code homogène, même quand quatre personnes et deux agents codent en parallèle.

```markdown
# Guide de style

## Python
- ruff format, lignes de 100 caractères max ; ruff check sans erreur
- Noms en anglais, snake_case ; typage obligatoire sur les fonctions publiques
- Une fonction = une responsabilité ; si elle dépasse 40 lignes, découpe-la
- Pas de print() dans le code livré : utilise logging

## Erreurs
- Message pour l'utilisateur : ce qui s'est passé et quoi faire, en français simple
- Message dans les logs : le détail technique, jamais de donnée personnelle

## Git
- Conventional Commits : feat:, fix:, docs:, test:, refactor:, chore:
- Une branche par tâche : feat/nom-court ; Pull Requests petites (moins de 400 lignes)
```

### ARCHITECTURE.md

Il explique comment le projet est construit et pourquoi. L'agent s'en sert pour intégrer son code au lieu de tout réinventer.

```markdown
# Architecture

## Flux principal
Photo -> POST /diagnostic (FastAPI) -> gemma.analyser_image() -> Gemma 4 -> JSON -> page résultat

## Décisions
- Tous les appels au modèle passent par app/gemma.py : on peut changer de modèle
  sans toucher au reste.
- Les prompts vivent dans app/prompts.py, versionnés comme du code.
- Si le modèle ne répond pas, l'utilisateur voit un message d'attente, jamais une erreur brute.

## Ce qu'on ne fait pas (et pourquoi)
- Pas de base de données au MVP : rien à stocker tant qu'il n'y a pas d'historique.
```

### README.md

C'est la vitrine. Il doit permettre à un inconnu de comprendre le projet en 30 secondes et de le lancer en 5 minutes : le problème, la solution en une phrase, l'installation, le lancement, les tests, le modèle utilisé et sa licence, les outils IA utilisés pour coder, l'équipe, la licence du projet.

## 5. DESIGN.md et l'architecture CSS

Sans règles visuelles, un agent invente un nouveau vert, une nouvelle taille de bouton et un nouvel espacement à chaque écran. Au bout d'une semaine, l'interface ressemble à un patchwork. `docs/DESIGN.md` règle ça : il décrit ton système visuel une fois, et l'agent l'applique partout.

### Ce que contient un bon DESIGN.md

1. **Les principes** : le ton visuel en deux ou trois phrases.
2. **Les tokens** : couleurs, typographie, espacements, rayons, ombres. Chacun a un nom et un rôle.
3. **Les composants** : boutons, champs, cartes, alertes, avec leurs variantes et leurs états.
4. **Les règles de composition** : comment placer et juxtaposer les éléments.
5. **L'accessibilité** et le responsive.
6. **Les règles pour l'agent** : ce qu'il ne doit jamais faire.

```markdown
# Design

## Principes
Simple, lisible au soleil, utilisable d'une main sur un petit écran Android.
Une action principale par écran. Le vert dit « agir », le rouge dit « danger », rien d'autre.

## Couleurs (rôles, pas des teintes)
| Token              | Clair    | Sombre   | Usage                                 |
| --color-primary    | #1F7A3D  | #4CB86E  | Action principale, liens              |
| --color-on-primary | #FFFFFF  | #0B1F12  | Texte sur fond primary                |
| --color-surface    | #FAFAF7  | #121513  | Fond de page                          |
| --color-surface-2  | #FFFFFF  | #1C211E  | Cartes, champs                        |
| --color-text       | #1B1F1D  | #E8ECE9  | Texte principal                       |
| --color-muted      | #5B635E  | #A3ACA6  | Texte secondaire                      |
| --color-border     | #D9DDD8  | #2E3530  | Bordures                              |
| --color-danger     | #B42318  | #F97066  | Erreurs, suppression                  |
| --color-on-danger  | #FFFFFF  | #2A0A07  | Texte sur fond danger                 |
| --color-warning    | #B54708  | #FDB022  | Confiance faible                      |

## Typographie
Police système. Échelle : 14 / 16 (corps) / 20 / 24 / 32 px. Interligne 1.5 pour le corps.

## Espacements
Échelle de 4 px : 4, 8, 12, 16, 24, 32, 48. Aucune autre valeur.

## Rayons et ombres
Rayons : 6 px (champs, boutons), 12 px (cartes). Une seule ombre, pour les cartes.

## Boutons
- Variantes : primary (fond vert), secondary (bordure, fond transparent), ghost (texte seul),
  danger (fond rouge, uniquement pour une action destructive).
- Tailles : md (44 px de haut, par défaut), sm (36 px, dans les tableaux uniquement).
- États obligatoires : hover, focus visible, disabled, loading (spinner + texte conservé).
- Texte : un verbe d'action (« Analyser la photo »), jamais « OK » ou « Valider » seul.

## Composition
- Un seul bouton primary visible par écran ou par boîte de dialogue.
- Groupe de boutons : secondary à gauche, primary à droite, 8 px d'écart.
  Sur mobile (< 480 px) : empilés, pleine largeur, primary en haut.
- Un bouton danger n'est jamais collé au bouton primary : 24 px d'écart minimum.
- Formulaires : label au-dessus du champ, message d'erreur sous le champ, en danger.
- Contenu centré, largeur max 640 px ; marges latérales 16 px sur mobile.

## Accessibilité
- Contraste minimum 4.5:1 pour le texte. Zone tactile minimum 44 x 44 px.
- Le focus clavier est toujours visible. Une couleur ne porte jamais seule une information.

## Règles pour l'agent
- N'écris jamais une couleur, une taille ou un espacement en dur : utilise var(--...).
- Réutilise les classes de composants existantes avant d'en créer une nouvelle.
- Un nouveau composant ou token s'ajoute d'abord ici, puis dans le CSS.
```

### L'architecture CSS

Le DESIGN.md dit *quoi*, l'architecture CSS dit *où*. Range tes styles en couches, du plus général au plus spécifique. La règle CSS `@layer` fixe l'ordre de priorité, et tu ne te bats plus jamais contre la spécificité.

```text
app/static/css/
  main.css            point d'entrée : déclare les couches et importe le reste
  tokens.css          variables : couleurs, typo, espacements (le DESIGN.md en code)
  reset.css           remise à zéro des styles du navigateur
  base.css            styles des balises : body, h1, a, input
  layout.css          structure des pages : conteneur, grilles, piles
  components/
    button.css        un fichier par composant
    card.css
    form.css
  utilities.css       petites classes d'appoint : .visually-hidden, .mt-16
```

```css
/* main.css */
@layer reset, tokens, base, layout, components, utilities;

@import url("reset.css") layer(reset);
@import url("tokens.css") layer(tokens);
@import url("base.css") layer(base);
@import url("layout.css") layer(layout);
@import url("components/button.css") layer(components);
@import url("components/card.css") layer(components);
@import url("components/form.css") layer(components);
@import url("utilities.css") layer(utilities);
```

```css
/* tokens.css */
:root {
  --color-primary: #1f7a3d;
  --color-on-primary: #ffffff;
  --color-surface: #fafaf7;
  --color-surface-2: #ffffff;
  --color-text: #1b1f1d;
  --color-muted: #5b635e;
  --color-border: #d9ddd8;
  --color-danger: #b42318;
  --color-on-danger: #ffffff;

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;  --space-4: 16px;
  --space-6: 24px; --space-8: 32px; --space-12: 48px;

  --radius-sm: 6px;
  --radius-md: 12px;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-primary: #4cb86e;
    --color-on-primary: #0b1f12;
    --color-surface: #121513;
    --color-surface-2: #1c211e;
    --color-text: #e8ece9;
    --color-muted: #a3aca6;
    --color-border: #2e3530;
    --color-danger: #f97066;
    --color-on-danger: #2a0a07;
  }
}
```

```css
/* components/button.css */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: 600 16px/1 var(--font-body);
  cursor: pointer;
}
.btn:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn--primary { background: var(--color-primary); color: var(--color-on-primary); }
.btn--secondary { background: transparent; color: var(--color-text); border-color: var(--color-border); }
.btn--danger { background: var(--color-danger); color: var(--color-on-danger); }

/* Composition : secondary à gauche, primary à droite ; empilés sur mobile */
.btn-group { display: flex; justify-content: flex-end; gap: var(--space-2); }
@media (max-width: 480px) {
  .btn-group { flex-direction: column-reverse; }
  .btn-group .btn { width: 100%; }
}
```

Remarque que le mode sombre ne touche qu'aux tokens : aucun composant ne change. C'est tout l'intérêt de nommer les couleurs par rôle (`--color-primary`) plutôt que par teinte (`--green-700`).

Tu utilises Tailwind ou un autre framework ? Le principe ne change pas : les mêmes tokens vont dans la configuration du thème, et le DESIGN.md interdit les valeurs arbitraires.

### Générer ton système de design avec l'IA

Tu n'as pas à tout écrire à la main. Donne à l'agent ta marque et tes contraintes, et demande-lui le DESIGN.md *et* le code, puis une page de démonstration pour vérifier d'un coup d'œil :

```text
Crée le système de design d'AgriScan.
Marque : vert #1F7A3D, ton sérieux et rassurant, public de producteurs sur des
smartphones Android d'entrée de gamme, souvent en plein soleil.
1. Rédige docs/DESIGN.md avec : principes, tokens (couleurs par rôle en clair et sombre,
   typo, espacements sur une échelle de 4 px, rayons), boutons (variantes, tailles, états),
   champs de formulaire, cartes, alertes, règles de composition, accessibilité (WCAG AA).
2. Implémente-le dans app/static/css/ avec l'architecture en couches @layer
   (reset, tokens, base, layout, components, utilities), un fichier par composant.
3. Crée une page /styleguide qui affiche chaque token et chaque composant dans tous
   ses états, en clair et en sombre.
4. Vérifie les contrastes de chaque paire texte/fond et donne-moi le tableau des ratios.
Pas de framework CSS, pas de police externe.
```

La page `/styleguide` devient ton banc d'essai : chaque fois que l'agent touche au CSS, tu l'ouvres et tu vois immédiatement si quelque chose a bougé.

## 6. Découper en jalons : un MVP testable d'abord

Le piège classique avec un agent : lui demander « construis l'application ». Il produit 3 000 lignes, la moitié ne marche pas, et tu ne sais pas par où commencer. La parade : découper le projet en **jalons** (milestones), chacun livrant quelque chose qu'un humain peut tester.

### Tranches verticales, pas couches horizontales

Un jalon n'est pas « toute la base de données » puis « toute l'API » puis « toute l'interface ». C'est une **tranche verticale** : un peu d'interface, un peu d'API, un peu de modèle, mais un parcours complet qui marche de bout en bout. Le premier jalon utile s'appelle le **MVP** : la plus petite version qui résout vraiment le problème.

### Le fichier ROADMAP.md

```markdown
# Roadmap

## M0 · Squelette (terminé, v0.0.1)
Objectif : un projet qui se lance et se teste.
- [x] Repo, LICENSE, README, AGENTS.md
- [x] Page d'accueil servie par FastAPI, un test qui passe, CI qui lance les tests

## M1 · MVP : une photo, un diagnostic (en cours)
Objectif : un producteur envoie une photo et lit un diagnostic utile.
- [ ] Formulaire d'envoi de photo (mobile d'abord)
- [ ] Route POST /diagnostic qui appelle Gemma 4
- [ ] Page résultat : maladie, confiance, conseil
- [ ] Refus poli d'une photo qui n'est pas une feuille de maïs
Critères d'acceptation :
- Testé par une vraie personne sur un vrai téléphone avec 5 photos différentes
- Tests et linter verts ; réponse en moins de 10 s
Hors périmètre : comptes, historique, hors ligne

## M2 · Robustesse
- Compression de la photo côté navigateur, délai d'attente, messages d'erreur clairs

## M3 · Historique des diagnostics
- Comptes simples, base de données, liste des diagnostics passés

## M4 · Production
- Docker, déploiement continu, monitoring, sauvegardes (voir section 12)
```

### Les règles du jeu

1. **Un seul jalon à la fois.** L'agent travaille sur le jalon « en cours » et rien d'autre (c'est écrit dans AGENTS.md).
2. **Chaque jalon a ses critères d'acceptation.** « C'est fini » veut dire : les critères sont remplis, pas « l'agent a dit terminé ».
3. **Un humain teste avant de passer au suivant.** Lance l'app, fais le parcours, essaie de la casser. Puis marque le jalon avec un tag git (`git tag v0.1.0`).
4. **Après chaque jalon, on décide.** Continuer comme prévu, modifier les jalons suivants, en ajouter, ou en supprimer. Ce que tu apprends en testant le MVP vaut plus que ton plan de départ.
5. **Une nouvelle idée va dans ROADMAP.md, pas dans le jalon en cours.** C'est ce qui protège ton MVP de l'étalement.

### Faire découper le projet par l'IA

```text
Lis docs/PRODUCT.md. Découpe le projet en jalons livrables, sous forme de tranches
verticales. Le M1 doit être le plus petit MVP qu'un vrai utilisateur peut tester.
Pour chaque jalon : objectif en une phrase, tâches (moins d'une demi-journée chacune),
critères d'acceptation vérifiables, hors périmètre. Écris le résultat dans
docs/ROADMAP.md. Ne code rien.
```

Relis le résultat avec un œil critique : l'IA a tendance à mettre trop de choses dans le MVP. Coupe sans hésiter.

## 7. La boucle de travail : explorer, planifier, coder, vérifier, commiter

Chaque tâche du jalon suit la même boucle. Elle prend quelques minutes de plus que « vas-y, code », et en fait gagner des heures.

| Étape | Ce que tu demandes | Ce que tu vérifies |
| --- | --- | --- |
| 1. Explorer | « Lis les fichiers concernés par cette tâche et explique-moi comment ça marche aujourd'hui. Ne modifie rien. » | L'agent a compris le code existant |
| 2. Planifier | « Propose un plan : fichiers à modifier, étapes, tests à ajouter, risques. » | Le plan respecte le jalon, l'architecture et le hors périmètre |
| 3. Coder | « Applique le plan. » | Rien pendant qu'il code, sauf s'il s'écarte du plan |
| 4. Vérifier | « Lance les tests et le linter, corrige jusqu'au vert. » | Tu relis le diff, tu lances l'app, tu fais le parcours toi-même |
| 5. Commiter | « Fais un commit au format Conventional Commits. » | Le message décrit vraiment le changement |
| 6. Rendre compte | Le compte rendu défini dans AGENTS.md (section 8) | Il correspond à ce que tu as vu |

La plupart des outils ont un mode dédié à l'étape 2. Dans Claude Code, le **plan mode** (Shift+Tab, ou un prompt qui commence par `/plan`) laisse l'agent lire et proposer, mais bloque les modifications tant que tu n'as pas approuvé le plan. Antigravity propose un mode de planification qui produit un plan d'implémentation que tu peux annoter. Avec les autres outils, il suffit de l'écrire : « propose un plan, ne code rien ».

### Gérer le contexte

Un agent a une mémoire de travail limitée. Plus une session s'allonge, plus il oublie le début et plus il se trompe.

- **Une tâche = une session.** Terminée et commitée ? Ouvre une nouvelle session (ou vide le contexte, par exemple `/clear` dans Claude Code).
- **Les fichiers sont la mémoire.** Ce qui doit survivre d'une session à l'autre va dans AGENTS.md, ROADMAP.md ou PROGRESS.md, pas dans la conversation.
- **Montre, ne raconte pas.** Indique les fichiers précis (`app/gemma.py`, `tests/test_main.py`) plutôt que « le code du modèle ».

### Git est ton filet de sécurité

Avant de laisser un agent modifier quoi que ce soit, ton arbre de travail doit être propre (`git status` vide). Si le résultat ne te plaît pas, `git restore .` et `git clean -fd` te ramènent au dernier commit, sans discussion. Certains outils ont aussi leurs propres points de retour, mais git marche partout et pour toujours.

Pour faire travailler plusieurs agents en parallèle sans qu'ils se marchent dessus, donne à chacun sa propre copie du dépôt avec `git worktree` :

```bash
git worktree add ../agriscan-m2-compression -b feat/compression
git worktree add ../agriscan-m2-erreurs -b feat/messages-erreur
```

## 8. Le mode autonome et le compte rendu de fin de tâche

Quand ton projet a des tests, un AGENTS.md clair et un jalon bien défini, tu peux laisser l'agent travailler seul pendant 20 minutes ou deux heures, et ne revenir que pour lire son compte rendu. C'est là que le gain de temps devient énorme, et c'est aussi là que les dégâts peuvent l'être.

### Quand l'activer

| Feu vert | Feu rouge |
| --- | --- |
| Tâche définie avec des critères d'acceptation | « Améliore l'app » |
| Tests automatiques qui couvrent le parcours principal | Aucun test |
| Branche dédiée, arbre git propre | Travail non commité en cours |
| Aucun accès à la production ni aux vraies données | Clés de production dans l'environnement |

### Comment l'activer selon l'outil

- **Claude Code** : les modes de permission se changent avec Shift+Tab ou au lancement (`claude --permission-mode auto`). En mode **auto**, un second modèle examine chaque action à ta place et bloque les actions risquées. **acceptEdits** accepte les modifications de fichiers mais te demande pour le reste. **bypassPermissions** ne vérifie plus rien : à réserver à un conteneur ou une machine virtuelle isolée.
- **OpenAI Codex** : deux réglages se combinent. Le *sandbox* limite ce que l'agent peut toucher (`workspace-write` par défaut : il écrit seulement dans ton projet). La *politique d'approbation* dit quand il te demande (`on-request` par défaut, `never` pour un travail sans interruption). `danger-full-access` est réservé aux environnements isolés.
- **Google Antigravity** : le réglage d'exécution des commandes du terminal passe de « Request Review » (tu valides, sauf liste autorisée) à « Always Proceed » (tout s'exécute, sauf liste interdite).
- **GitHub Copilot** : le mode agent dans l'éditeur, ou l'agent de code sur GitHub, qui travaille sur une branche et te rend une Pull Request à relire.

Les noms changeront ; la question à te poser reste la même : *qu'est-ce que l'agent peut faire sans moi, et qu'est-ce qui l'en empêche ?*

### Les garde-fous

L'autonomie ne remplace pas les règles, elle les rend indispensables. Interdis explicitement ce qui ne doit jamais arriver. Dans Claude Code, par exemple, dans `.claude/settings.json` :

```json
{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Bash(git push --force *)",
      "Bash(rm -rf *)"
    ]
  }
}
```

Et quel que soit l'outil :

- **Une branche ou un worktree par mission**, jamais directement sur `main`.
- **Tests et linter verts obligatoires** avant que l'agent dise « terminé » (c'est dans AGENTS.md).
- **Aucun secret de production** dans l'environnement de l'agent : des clés de test, avec un quota limité.
- **Une limite claire** : « si tu bloques deux fois sur la même erreur, arrête-toi et explique ».

### Lancer une mission autonome

```text
Mission : jalon M1 de docs/ROADMAP.md, tâche « Page résultat ».
Travaille en autonomie sur la branche feat/page-resultat.
Critères de fin :
- La page affiche maladie, confiance et conseil, selon docs/DESIGN.md
- Une confiance « faible » s'affiche avec le style warning
- uv run pytest et uv run ruff check . passent
Avance par petits commits. Ne touche pas aux fichiers hors de app/ et tests/.
Si tu bloques deux fois sur la même erreur, arrête-toi.
Termine par le compte rendu défini dans AGENTS.md.
```

### Le compte rendu de fin de tâche

C'est ce qui te permet de reprendre la main en deux minutes. Exige-le à chaque fois, dans le même format (il est défini dans l'AGENTS.md de la section 4). Exemple de ce que tu dois recevoir :

```markdown
## 2026-10-24 · M1 · Page résultat
- Fait : page /resultat affichant le diagnostic ; carte warning si confiance faible.
- Fichiers : app/main.py, app/templates/resultat.html, app/static/css/components/card.css,
  tests/test_resultat.py
- Vérifié : uv run pytest (12 réussis) ; uv run ruff check . (0 erreur)
- Pour tester toi-même : uv run fastapi dev app/main.py, ouvre /, envoie tests/data/rouille.jpg
- Décisions : ajout de la variante .card--warning dans DESIGN.md et card.css
- Reste à faire / risques : le texte du conseil déborde sur les écrans de 320 px
- Prochaine étape proposée : refus poli des photos non valides (dernière tâche de M1)
```

Ce compte rendu s'ajoute en tête de `docs/PROGRESS.md`. Ce fichier devient le journal de bord du projet : n'importe qui (toi dans six mois, un nouveau membre, un nouvel agent) sait où en est le projet en lisant ses premières lignes.

**Ne crois pas le compte rendu sur parole.** Relance toi-même les tests, lis le diff (`git diff main...feat/page-resultat`), fais le parcours décrit dans « Pour tester toi-même ». Un agent peut annoncer « 12 tests réussis » alors qu'il en a désactivé deux.

## 9. Le prompting : parler à l'agent

Avec de bons fichiers de contexte, tes prompts deviennent courts. Ils doivent quand même répondre à quatre questions : **le contexte** (où on est), **la tâche** (quoi faire), **le format** (quoi rendre), **les limites** (quoi ne pas faire).

### Avant / après

```text
Fais-moi une API pour analyser des photos.
```

```text
Contexte : jalon M1 (voir docs/ROADMAP.md), projet FastAPI décrit dans AGENTS.md.
Tâche : ajoute la route POST /diagnostic qui reçoit une image (UploadFile),
appelle gemma.analyser_image() et renvoie le résultat en JSON.
Format : le code de la route, puis un test pytest qui simule l'appel au modèle.
Limites : pas d'appel direct au modèle dans la route ; refuse les fichiers de plus
de 5 Mo (413) et les formats autres que JPEG/PNG (415). Aucune nouvelle dépendance.
```

Le second prompt laisse beaucoup moins de place aux suppositions, donc beaucoup moins de corrections.

### Les habitudes qui font la différence

1. **Donne la matière brute.** Une erreur ? Colle le log *complet* et le fichier de configuration concerné, pas ton résumé. Une règle à respecter ? Donne le lien ou le texte du document de référence.
2. **Donne un exemple.** Une entrée et la sortie attendue valent mieux qu'un paragraphe d'explications.
3. **Plan d'abord.** « Propose un plan, ne code rien » pour tout ce qui dépasse quelques lignes.
4. **Impose le format.** JSON, tableau, un seul fichier, « uniquement le diff » : dis-le.
5. **Itère précisément.** « Garde tout, mais déplace la validation dans une fonction à part » plutôt qu'un nouveau prompt de zéro.
6. **Fais-le se relire.** « Quels cas limites ce code ne gère-t-il pas ? », « Vérifie tout contre la documentation officielle ».
7. **Demande des choix, pas une réponse.** « Donne-moi 3 approches avec leurs compromis » avant une décision d'architecture.
8. **Fais-toi expliquer.** « Explique ce code ligne par ligne comme à un débutant » : c'est comme ça qu'on progresse au lieu de dépendre.

### Bibliothèque de prompts

Garde ces modèles dans un fichier `docs/PROMPTS.md` (ou en commandes personnalisées, si ton outil le permet) et réutilise-les.

```text
# Revue de code
Relis le diff de la branche courante par rapport à main comme un développeur senior exigeant.
Cherche : bugs, cas limites non gérés, failles de sécurité, écarts avec AGENTS.md et
DESIGN.md, code mort, tests manquants. Classe par gravité. Ne modifie rien.

# Tests d'abord
Écris les tests de la fonctionnalité X d'après les critères d'acceptation de ROADMAP.md.
Lance-les : ils doivent échouer. Ne code pas encore la fonctionnalité.

# Refactor sans risque
Refactorise app/main.py pour séparer validation et logique métier. Le comportement ne
doit pas changer : les tests existants doivent passer sans être modifiés.

# Comprendre un code existant
Explique-moi comment fonctionne ce projet : point d'entrée, flux principal, où sont les
dépendances externes. Fais un schéma en texte. Ne modifie rien.

# Mettre à jour la doc
Compare README.md, AGENTS.md et ARCHITECTURE.md avec le code actuel. Liste ce qui est
faux ou manquant, puis corrige les fichiers.
```

### Les prompts à l'intérieur de ton application

Quand ton application appelle un modèle (comme Gemma dans AgriScan), le prompt fait partie du code :

- Range tous les prompts dans un seul fichier (`app/prompts.py`), versionné.
- Sépare les instructions fixes (rôle, format) des données de l'utilisateur, et traite ces données comme des données, jamais comme des ordres.
- Demande une sortie structurée (JSON) et valide-la dans ton code.
- Garde un petit jeu de cas de test (5 à 10 photos ou textes) et rejoue-le à chaque modification du prompt.

```python
DIAGNOSTIC_PROMPT = """Tu es un agronome qui aide des petits producteurs au Togo.
Regarde la photo de la feuille de maïs.
Réponds uniquement en JSON avec les clés :
- "maladie" : le nom probable, ou "inconnue"
- "confiance" : "faible", "moyenne" ou "forte"
- "conseil" : une action simple, en une phrase, en français
Si la photo n'est pas une feuille de maïs, mets "maladie": "photo non valide"."""
```

## 10. Quand ça casse : déboguer toi-même, puis bien demander

Un jour, l'agent va tourner en rond : il corrige, ça casse ailleurs, il corrige encore, et chaque tentative empire les choses. Ce jour-là, la compétence qui compte, c'est la tienne. Tu peux toujours redemander à l'IA, mais tu dois aussi savoir t'en passer.

### La méthode en 7 étapes

1. **Lis l'erreur, en entier.** En Python, la dernière ligne du traceback dit *quoi* ; remonte ensuite jusqu'à la première ligne qui pointe vers *ton* fichier : c'est souvent là que ça se passe.
2. **Reproduis.** Note la commande exacte qui provoque l'erreur. Un bug que tu ne reproduis pas, tu ne peux pas savoir si tu l'as corrigé.
3. **Demande-toi ce qui a changé.** `git status`, `git diff`, `git log --oneline -5`. Neuf fois sur dix, le bug est dans le dernier changement. `git stash` te permet de vérifier en un instant si ça marchait sans lui.
4. **Isole.** Réduis le problème à sa plus petite forme. Ajoute un `print()` ou un `logging.debug()` avant la ligne qui casse, ou mets un `breakpoint()` pour inspecter les variables dans le débogueur. Côté interface, ouvre les outils du navigateur (F12) : onglet Console pour les erreurs JavaScript, onglet Réseau pour voir la requête et la réponse exactes.
5. **Une hypothèse, un changement.** « Je pense que la photo arrive vide » → tu vérifies → tu corriges. Ne change jamais trois choses à la fois.
6. **Lis la source officielle.** Documentation de la version que tu utilises, notes de version, issues GitHub du projet. Beaucoup de bugs viennent d'une API qui a changé entre deux versions.
7. **Reviens au vert.** Si tu es perdu : `git restore .` et tu repars du dernier commit qui marchait. Si tu ne sais pas quel commit a tout cassé, `git bisect` le trouve pour toi par dichotomie.

### Les erreurs que tu croiseras le plus

| Symptôme | Cause la plus fréquente | Premier réflexe |
| --- | --- | --- |
| `ModuleNotFoundError` | Mauvais environnement virtuel ou mauvais dossier | `which python`, lance depuis la racine, `uv sync` |
| `Address already in use` | Un autre serveur occupe le port | `lsof -i :8000` puis arrête le processus |
| `401` / `403` | Clé d'API absente, expirée ou mal chargée | Affiche si la variable existe (jamais sa valeur) |
| `404` sur une route | Mauvais chemin ou méthode (GET au lieu de POST) | Ouvre `/docs` (FastAPI) ou liste les routes |
| `422` (FastAPI) | Le corps de la requête ne correspond pas au schéma | Lis le détail JSON de la réponse : il dit quel champ |
| Erreur CORS dans le navigateur | Le front et l'API ne sont pas sur la même origine | Configure le middleware CORS côté API |
| Échec d'installation ou de build | Conflit de versions, mauvaise configuration du projet | Lis la première erreur du log, pas la dernière |
| « Ça marche chez moi » | Variable d'environnement ou version différente | Compare `.env.example`, versions, lockfile |

**Exemple vécu.** Un `uv sync` échoue avec une longue erreur de build. En lisant le log en entier avec le `pyproject.toml` à côté, on comprend que uv essaie d'empaqueter le projet comme une bibliothèque installable, alors que c'est une application. La correction tient en deux lignes dans `pyproject.toml` :

```toml
[tool.uv]
package = false
```

Le réflexe gagnant n'était pas de demander « corrige », mais de fournir le log complet *et* le fichier de configuration, et de comprendre la cause avant d'appliquer le correctif.

### La règle des deux essais

Si l'IA a proposé deux correctifs pour la même erreur et qu'aucun ne marche, **arrête de prompter**. Reviens au dernier commit vert, applique la méthode ci-dessus pendant 15 minutes, et ne reviens vers l'IA qu'avec ce que tu as appris. Un agent qui boucle accumule des correctifs inutiles qui deviennent eux-mêmes des bugs.

### Bien demander de l'aide à l'IA

Quand tu reviens vers l'agent, donne-lui un vrai rapport de bug :

```text
Bug : POST /diagnostic renvoie 500 avec une photo PNG, marche avec un JPEG.
Commande : curl -F "photo=@tests/data/feuille.png" localhost:8000/diagnostic
Erreur complète : (colle tout le traceback)
Attendu : un JSON de diagnostic, comme pour le JPEG.
Depuis quand : le commit a3f9c21 (compression des images).
Déjà vérifié : le fichier arrive bien (taille correcte dans les logs).
Versions : Python 3.12, google-genai (voir uv.lock).
Explique d'abord la cause probable, puis propose le correctif le plus petit possible.
Ne modifie pas les tests pour les faire passer.
```

La dernière ligne est importante : un agent pressé « corrige » parfois un test en le supprimant ou en changeant la valeur attendue.

### Entraîne ton autonomie

- Une fois par semaine, corrige un bug **sans IA**, du début à la fin.
- Quand l'IA corrige un bug, demande-lui : « Explique la cause et comment j'aurais pu la trouver seul. »
- Tiens un fichier `docs/BUGS.md` : symptôme, cause, correctif. Au bout de trois mois, c'est ta meilleure documentation.

## 11. Qualité et sécurité

Un agent produit du code à la vitesse d'une équipe entière. Sans contrôles automatiques, il produit aussi des bugs à la vitesse d'une équipe entière. Ces outils sont ce qui te permet de lui faire confiance.

### Les tests

- **Tests unitaires** pour la logique (une fonction, un cas). Rapides, nombreux.
- **Tests d'intégration** pour les routes et les échanges entre modules, avec les services externes simulés (comme le modèle dans l'atelier Gemma).
- **Tests de bout en bout** pour le parcours principal dans un vrai navigateur (Playwright, par exemple). Peu nombreux, mais ce sont eux qui prouvent que le MVP marche.

La technique la plus efficace avec un agent : **les tests d'abord**. Fais écrire les tests à partir des critères d'acceptation, vérifie qu'ils échouent, *puis* fais coder. L'agent a alors une cible objective, et toi un moyen de vérifier qu'il l'a atteinte.

### Le contrôle automatique à chaque commit

- **Formatage et lint** : ruff pour Python, ESLint et Prettier pour JavaScript.
- **Typage** : mypy ou pyright pour Python, TypeScript côté front.
- **Hooks pre-commit** : le framework `pre-commit` lance ces outils avant chaque commit, pour toi comme pour l'agent.

```yaml
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9
    hooks:
      - id: ruff
      - id: ruff-format
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.21.2
    hooks:
      - id: gitleaks
```

Prends les dernières versions indiquées dans la documentation de chaque outil ; `pre-commit autoupdate` les met à jour pour toi.

### Les secrets

- Les secrets vont dans `.env`, qui est dans `.gitignore`. Un `.env.example` (sans valeurs) documente les variables attendues.
- `gitleaks` (ci-dessus) bloque un commit qui contient une clé.
- Une clé poussée sur GitHub, même une minute, est une clé volée : **révoque-la immédiatement**, puis nettoie l'historique.

### Les dépendances

- Une IA peut suggérer un paquet qui n'existe pas, ou dont le nom ressemble à un vrai. Avant d'installer un paquet inconnu, vérifie sa page officielle, son dépôt, son nombre de téléchargements et sa date de dernière mise à jour.
- Versionne ton lockfile (`uv.lock`, `package-lock.json`) pour que tout le monde installe exactement les mêmes versions.
- Active Dependabot (ou Renovate) pour être prévenu des failles et des mises à jour.

### La sécurité du code généré

- Valide toutes les entrées côté serveur (taille, type, format), jamais seulement dans le navigateur.
- Requêtes SQL paramétrées ou ORM, jamais de chaînes concaténées.
- Mots de passe hachés avec un algorithme fait pour ça (argon2, bcrypt), jamais « maison ».
- Pour une application qui utilise un modèle d'IA : le texte de l'utilisateur ou d'un document peut contenir des instructions cachées (*prompt injection*). Ne laisse jamais la réponse d'un modèle déclencher seule une action sensible (paiement, suppression, envoi d'e-mail).
- Le [Top 10 de l'OWASP](https://owasp.org/www-project-top-ten/) est la liste de référence des failles web à connaître.

### Relire le code de l'IA comme une Pull Request

Avant de fusionner, pose-toi ces questions :

- Est-ce que je comprends chaque ligne ? Sinon, je demande une explication.
- Est-ce que ça respecte AGENTS.md, ARCHITECTURE.md et DESIGN.md ?
- Y a-t-il des dépendances, des fichiers ou des fonctionnalités que je n'ai pas demandés ?
- Les tests vérifient-ils vraiment le comportement, ou juste que le code s'exécute ?
- Un test a-t-il été supprimé, désactivé ou affaibli ?

## 12. Vers la production

Un MVP qui tourne sur ton ordinateur n'est pas un produit. Passer en production, c'est rendre ton application fiable, observable et réparable par quelqu'un d'autre que toi. L'agent peut écrire presque tout ce qui suit ; c'est toi qui décides et qui appuies sur le bouton.

### La configuration par l'environnement

Le même code tourne en local, en préproduction et en production ; seules les variables d'environnement changent (clés, URL de base de données, niveau de log). C'est un des principes de la méthode [Twelve-Factor App](https://12factor.net), qui reste la meilleure introduction à la question.

### Le conteneur

```dockerfile
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:0.9.5 /uv /uvx /bin/

WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY app ./app

RUN useradd --create-home appuser
USER appuser
EXPOSE 8000
CMD ["uv", "run", "--no-sync", "fastapi", "run", "app/main.py", "--port", "8000"]
```

Fixe toujours les versions (de l'image, de uv, des dépendances via le lockfile) : un build doit donner le même résultat aujourd'hui et dans six mois. Prends la version de uv indiquée dans sa documentation Docker au moment où tu écris ton Dockerfile.

### L'intégration continue

Chaque push et chaque Pull Request lancent les mêmes vérifications, pour les humains comme pour les agents. Rien ne fusionne si la CI est rouge.

```yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv sync --frozen
      - run: uv run ruff check .
      - run: uv run ruff format --check .
      - run: uv run pytest
```

### Le déploiement

- **Simple** : une plateforme qui déploie un conteneur depuis GitHub (Render, Railway, Fly.io, Google Cloud Run, Azure Container Apps…).
- **Maîtrisé** : un serveur (VPS) avec Docker, Nginx en reverse proxy et un certificat Let's Encrypt.
- Dans les deux cas : un environnement de **préproduction** identique à la production, où tu testes avant chaque mise en ligne.
- **L'agent n'a jamais les clés de production.** Il écrit le Dockerfile, la CI et la configuration ; le déploiement passe par la CI ou par toi.

### Observer ce qui se passe

- Une route `/health` qui répond 200 quand l'application va bien.
- Des logs structurés (JSON), sans données personnelles ni secrets.
- Un outil de suivi des erreurs (Sentry, par exemple) qui te prévient avant tes utilisateurs.
- Une surveillance de disponibilité (Uptime Kuma, UptimeRobot…).
- Pour les appels à un modèle d'IA : délai d'attente, nouvelles tentatives avec attente croissante, et une alerte de budget sur ton compte.

### Les données

- Toute modification du schéma de base passe par une migration versionnée (Alembic pour SQLAlchemy, par exemple), jamais à la main.
- Des sauvegardes automatiques, et un test de restauration régulier : une sauvegarde jamais restaurée n'est pas une sauvegarde.

### Les versions

- Numérote tes versions avec [SemVer](https://semver.org) : `1.4.2` = majeure (casse la compatibilité), mineure (nouvelle fonctionnalité), correctif.
- Tiens un `CHANGELOG.md` (format [Keep a Changelog](https://keepachangelog.com)) ; l'agent peut le mettre à jour à partir des commits Conventional Commits.
- Tague chaque mise en production (`git tag v1.4.2`) pour pouvoir revenir en arrière en une commande.

### Checklist avant la mise en production

- [ ] Tests, lint et CI verts sur la branche principale
- [ ] Parcours principal testé par un humain en préproduction
- [ ] Aucune clé dans le code ni dans l'historique git ; secrets dans le gestionnaire de la plateforme
- [ ] `/health`, suivi des erreurs et surveillance de disponibilité en place
- [ ] Sauvegardes actives et restauration testée
- [ ] Procédure de retour à la version précédente écrite et testée
- [ ] CHANGELOG à jour, version taguée
- [ ] README et ARCHITECTURE.md à jour

### Quand la production casse

D'abord rétablir le service (revenir à la version précédente), ensuite comprendre. Puis écris un court compte rendu d'incident sans chercher de coupable : ce qui s'est passé, l'impact, la cause, ce qu'on change pour que ça n'arrive plus. Ajoute la leçon à AGENTS.md si elle concerne la façon de travailler de l'agent.

## 13. Tester comme un attaquant : sécurité, charge, performance

Une application construite avec l'IA a les mêmes failles qu'une autre, plus quelques-unes qui lui sont propres : l'agent écrit vite du code qui *marche*, pas forcément du code qui *résiste*. Avant d'ouvrir ton application au public, et ensuite à chaque version importante, teste-la sous quatre angles.

> **La règle absolue :** ne teste que ce qui t'appartient, ou ce que tu as l'autorisation écrite de tester. Scanner ou attaquer l'application de quelqu'un d'autre sans accord est illégal dans la plupart des pays, même « pour apprendre ». Teste en préproduction, jamais directement sur la production sans un créneau prévu et prévenu.

### Les failles typiques d'une app écrite par une IA

- **Contrôle d'accès oublié** : la route `/diagnostics/42` renvoie le diagnostic de n'importe qui, il suffit de changer le numéro.
- **Secrets en dur** dans le code ou dans le JavaScript envoyé au navigateur.
- **Configuration de développement en production** : mode debug actif, messages d'erreur détaillés, CORS ouvert à tous (`*`).
- **Aucune limite de débit** : un script peut appeler ton API (et ton modèle payant) 10 000 fois par minute.
- **Entrées non validées** côté serveur.
- **Dépendances obsolètes ou inventées.**
- **Prompt injection** : un texte ou une image contient des instructions qui détournent ton modèle.

### 1. La revue sécurité (le regard du CSO)

Avant les outils, la réflexion. C'est ce que ferait un responsable de la sécurité (CSO) en arrivant sur ton projet. Écris un `docs/SECURITY_REVIEW.md` d'une page qui répond à ces questions :

- **Quelles données** manipule l'application ? Lesquelles sont personnelles ou sensibles ? Où sont-elles stockées, combien de temps ?
- **Qui peut faire quoi ?** Liste les rôles et vérifie que chaque route contrôle le rôle, pas seulement la connexion.
- **Par où entre-t-on ?** Formulaires, API, fichiers envoyés, webhooks, prompts : chaque entrée est une porte.
- **Que se passe-t-il si…** une clé fuit, la base est copiée, le modèle répond n'importe quoi, un compte admin est volé ?
- **Comment le saurait-on ?** Logs, alertes, suivi des erreurs.
- **Qui prévenir et comment réagir ?** Un plan d'incident, même de dix lignes.

L'IA est très utile pour cette revue, à condition de lui interdire d'agir :

```text
Agis comme un auditeur de sécurité applicative. Analyse le code de ce dépôt (lecture seule,
n'exécute aucune commande réseau). Cherche les vulnérabilités de l'OWASP Top 10 et de
l'OWASP Top 10 pour les applications LLM : contrôle d'accès, injection, secrets, configuration,
dépendances, validation des entrées, limites de débit, prompt injection.
Pour chaque problème : fichier et ligne, scénario d'exploitation en une phrase, gravité
(critique, haute, moyenne, basse), correctif proposé. Classe par gravité. Ne modifie rien.
```

Puis corrige les problèmes un par un, chacun avec un test qui prouve que la faille est fermée.

### 2. Les scans automatiques

Ces outils trouvent les erreurs connues en quelques minutes. Mets les plus rapides dans ta CI.

| Ce qu'on cherche | Outil (exemples) | Commande |
| --- | --- | --- |
| Failles dans ton code Python | Bandit, Semgrep | `uvx bandit -r app` · `uvx semgrep scan --config auto` |
| Dépendances vulnérables | pip-audit, Dependabot | `uv export --no-hashes > req.txt && uvx pip-audit -r req.txt` |
| Secrets commités | gitleaks | `gitleaks detect` |
| Image Docker vulnérable | Trivy | `trivy image agriscan:latest` |
| Analyse du code sur GitHub | CodeQL (code scanning) | À activer dans les paramètres de sécurité du dépôt |
| Application en marche | OWASP ZAP (scan de base) | voir ci-dessous |
| En-têtes HTTP et TLS | Mozilla Observatory, SSL Labs | Depuis leur site, sur ton domaine |

Le scan de base d'OWASP ZAP visite ton application comme un navigateur et signale les problèmes courants (en-têtes manquants, cookies mal configurés, fuites d'information), sans attaque agressive :

```bash
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py -t https://preprod.agriscan.example
```

### 3. Le test d'intrusion (pentest)

Les scanners trouvent ce qui est connu ; un pentester trouve ce qui est propre à *ton* application : une logique métier contournable, un enchainement de petites failles. Pour un produit qui manipule de l'argent ou des données personnelles (paiement Mobile Money, santé, comptes clients), c'est indispensable avant le lancement.

- **Fais-le faire par quelqu'un d'autre** que ceux qui ont écrit le code : un collègue formé, un prestataire, ou un programme de bug bounty quand le produit grandit.
- **Cadre-le par écrit** : périmètre (domaines, routes, comptes de test), dates, ce qui est interdit (déni de service, données réelles), contacts en cas de problème.
- **Exige un rapport** avec, pour chaque faille, sa gravité, comment la reproduire et comment la corriger. Corrige, puis fais re-tester.
- **Publie un `SECURITY.md`** qui explique comment signaler une faille de manière responsable, et réponds vite à ceux qui le font.

Pour te former au hacking éthique, entraîne-toi uniquement sur des terrains prévus pour ça : des applications volontairement vulnérables comme OWASP Juice Shop, à lancer chez toi, ou des plateformes de CTF.

### 4. Les tests propres aux applications d'IA

- **Prompt injection** : envoie des entrées qui contiennent des instructions (« ignore tes consignes et… », du texte écrit dans une image). L'application doit continuer à se comporter normalement.
- **Sortie non fiable** : la réponse du modèle est validée (schéma JSON, valeurs autorisées) avant d'être affichée ou utilisée, et elle n'est jamais insérée telle quelle dans du HTML ou une requête SQL.
- **Abus de coût** : limite le nombre d'appels par utilisateur et par adresse IP, plafonne la taille des entrées, mets une alerte de budget.
- **Fuite de données** : le prompt système et les données des autres utilisateurs ne doivent jamais apparaître dans une réponse.

Ajoute ces cas à tes tests automatiques : ils doivent rester verts à chaque modification du prompt.

### 5. Les tests de charge

Combien d'utilisateurs simultanés ton application supporte-t-elle avant de ralentir, puis de tomber ? Il vaut mieux le savoir avant le passage à la radio. Locust permet d'écrire ce test en Python :

```python
# locustfile.py
from locust import HttpUser, between, task


class Producteur(HttpUser):
    wait_time = between(1, 3)

    @task
    def diagnostic(self):
        with open("tests/data/feuille.jpg", "rb") as photo:
            self.client.post("/diagnostic", files={"photo": ("feuille.jpg", photo, "image/jpeg")})
```

```bash
locust -f locustfile.py --host https://preprod.agriscan.example \
  --users 50 --spawn-rate 5 --run-time 5m --headless
```

- **Teste en préproduction**, jamais en production sans prévenir.
- **Remplace le modèle payant par une fausse réponse** pendant le test (une variable d'environnement suffit), sinon tu testes ton quota et tu paies la facture. Teste l'appel réel séparément, avec peu d'utilisateurs.
- **Regarde trois chiffres** : le temps de réponse au 95e centile (p95), le taux d'erreur, et le nombre de requêtes par seconde au moment où ça décroche.
- **Fixe-toi un objectif écrit**, par exemple « 50 utilisateurs simultanés, p95 sous 2 s hors appel au modèle, moins de 1 % d'erreurs », et refais le test à chaque version importante. k6 est une bonne alternative si tu préfères le JavaScript.

### 6. Les tests de performance

La charge mesure combien d'utilisateurs, la performance mesure à quelle vitesse pour chacun.

- **Côté navigateur** : Lighthouse (dans les outils de Chrome) mesure le temps de chargement, l'accessibilité, les bonnes pratiques et le référencement (SEO). Teste en simulant un mobile en 3G : c'est la réalité de beaucoup d'utilisateurs.
- **Côté serveur** : mesure avant d'optimiser. Un profileur comme py-spy montre où le temps est vraiment passé ; pour la base de données, `EXPLAIN` montre les requêtes qui manquent d'index.
- **Les gains les plus fréquents** : compresser les images avant l'envoi, mettre en cache ce qui ne change pas, éviter les requêtes en boucle (le problème « N+1 »), servir les fichiers statiques par Nginx ou un CDN.

### Checklist sécurité avant le lancement

- [ ] Revue sécurité écrite, problèmes critiques et hauts corrigés avec un test
- [ ] Contrôle d'accès vérifié sur chaque route (un utilisateur ne voit que ses données)
- [ ] Scans automatiques (code, dépendances, secrets, image) dans la CI, sans alerte critique
- [ ] Scan ZAP de base sans alerte haute ; en-têtes de sécurité et HTTPS en place
- [ ] Mode debug désactivé, erreurs génériques pour l'utilisateur, CORS restreint
- [ ] Limites de débit sur l'API et sur les appels au modèle, alerte de budget active
- [ ] Tests de prompt injection et de validation des sorties au vert
- [ ] Test de charge réalisé, objectif atteint et résultat noté
- [ ] Pentest réalisé si l'app manipule argent ou données personnelles
- [ ] SECURITY.md publié, plan d'incident écrit

## 14. La boîte à outils

Les outils changent vite ; les catégories, beaucoup moins. Choisis un outil par case, apprends-le bien, et ne change que pour une vraie raison.

| Besoin | Exemples d'outils | Pourquoi |
| --- | --- | --- |
| Agent de code | Claude Code, OpenAI Codex, Google Antigravity, GitHub Copilot, Cursor | Écrire, modifier, tester le code à ta place, sous ta direction |
| Modèles dans ton app | Gemma (modèle ouvert), API Claude, API Gemini, OpenAI | Les capacités d'IA de ton produit |
| Versioning et collaboration | Git, GitHub (issues, Pull Requests, Projects) | Historique, revue, retour en arrière |
| Environnement Python | uv, ruff, pytest, mypy ou pyright | Installer, formater, tester, typer |
| Front-end | Outils du navigateur (F12), Playwright, Lighthouse | Déboguer, tester le parcours, mesurer performance et accessibilité |
| Qualité et sécurité | pre-commit, gitleaks, Dependabot | Contrôles automatiques avant et après chaque commit |
| CI/CD | GitHub Actions | Les mêmes vérifications pour tout le monde, déploiement automatisé |
| Conteneurs et déploiement | Docker, Nginx, Render, Fly.io, Cloud Run, Azure | Faire tourner l'app ailleurs que chez toi |
| Observabilité | Sentry, Uptime Kuma, logs structurés | Savoir que ça casse avant tes utilisateurs |
| Documentation | Markdown dans le dépôt, MkDocs | Une doc qui vit avec le code |
| Connecter l'agent | Serveurs MCP (Model Context Protocol) | Donner à l'agent un accès contrôlé à GitHub, une documentation, une base de test |

Le [Model Context Protocol](https://modelcontextprotocol.io) mérite une mention : c'est un standard ouvert qui permet de brancher un agent sur des outils et des sources de données. Un même serveur MCP fonctionne avec plusieurs agents, ce qui fait partie de ce qui rend ce guide durable.

## 15. Progresser : de débutant à expert

L'IA ne fait pas de toi un expert. Elle multiplie ce que tu sais déjà : zéro fois cent, ça fait toujours zéro. Voici le chemin.

| Niveau | Comment tu travailles | Ce que tu dois maîtriser | Tu passes au suivant quand… |
| --- | --- | --- | --- |
| Débutant | Tu poses des questions, tu copies du code et tu le fais expliquer | Lire une erreur, git de base, les bases de ton langage | Tu sais expliquer chaque ligne de ton projet |
| Intermédiaire | Un agent dans ton dépôt, avec AGENTS.md, plan d'abord, jalons, tests | Tests, débogage, découpage en jalons | Tu livres un MVP testé sans que l'agent tourne en rond |
| Avancé | Missions autonomes avec garde-fous, CI, revue systématique, bibliothèque de prompts | Architecture, sécurité, CI/CD, production | Tes projets tiennent en production et d'autres peuvent y contribuer |
| Expert | Plusieurs agents en parallèle, automatisations, outillage sur mesure | Concevoir des systèmes, mesurer, transmettre | Ton équipe va plus vite grâce à tes règles et tes outils |

### Ce que font les experts

- **Ils personnalisent leur outil.** Commandes personnalisées pour les tâches répétitives (revue, release, mise à jour de la doc). *Hooks* : des scripts lancés automatiquement avant ou après une action de l'agent, par exemple ruff après chaque modification. Sous-agents spécialisés : un relecteur, un testeur, un rédacteur de documentation. Claude Code, Codex et les autres proposent tous une partie de ces mécanismes, sous des noms différents.
- **Ils parallélisent.** Plusieurs agents, chacun dans son worktree, sur des tâches indépendantes ; eux passent leur temps à cadrer et à relire.
- **Ils font relire le travail d'un agent par un autre.** Un agent qui n'a pas écrit le code le relit avec un regard neuf.
- **Ils améliorent leurs règles en continu.** Chaque fois qu'un agent se trompe deux fois de la même façon, la leçon va dans AGENTS.md.
- **Ils gardent les fondamentaux.** HTTP, SQL, git, la mise en page CSS, les structures de données, la lecture de code : c'est ce qui leur permet de juger ce que l'IA produit.
- **Ils lisent plus de code qu'ils n'en écrivent**, et ils en écrivent encore à la main de temps en temps.
- **Ils partagent.** Leurs AGENTS.md, leurs DESIGN.md, leurs prompts : la communauté progresse plus vite que chacun de son côté.

## 16. Spécial Hack Day : 2 heures

Pendant un hackathon, tout ce guide se compresse. Garde README.md, AGENTS.md et un mini-ROADMAP de trois lignes (le MVP, et c'est tout).

| Temps | Ce que tu fais | Ce que tu demandes à l'IA |
| --- | --- | --- |
| 0 → 15 min | Choisir le problème, créer le repo, LICENSE, README, AGENTS.md | « Propose 3 façons simples de résoudre ce problème en 2 h avec Gemma » |
| 15 → 30 min | Faire marcher un premier appel au modèle | « Écris la fonction minimale qui envoie ce prompt à Gemma et affiche la réponse » |
| 30 → 90 min | Construire le MVP, par petits commits | Une demande par fonctionnalité, chaque fois avec son test |
| 90 → 105 min | Arrêter d'ajouter, stabiliser | « Quels cas peuvent faire planter ce code ? Corrige le plus probable » |
| 105 → 120 min | README final, vidéo démo, push, soumission | « Relis ce README : manque-t-il quelque chose pour qu'un inconnu lance le projet ? » |

Dans une équipe de 4 : une personne sur le modèle et les prompts, une sur l'interface, une sur l'intégration et les tests, une sur le README, la vidéo et le pitch. Une branche par personne, des Pull Requests courtes.

Trois rappels : cite les outils IA utilisés dans le README (c'est une règle du Hack Day), ne laisse pas l'IA écrire ton pitch à ta place, et ne change pas de modèle ou de framework en cours de route.

## 17. Ressources

**Fichiers d'instructions et agents**

- [Le format AGENTS.md](https://agents.md) : le format ouvert lu par la plupart des agents de code
- [Instructions de dépôt pour GitHub Copilot](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions)
- [Claude Code : les modes de permission](https://code.claude.com/docs/en/permission-modes) (plan mode, auto mode et garde-fous)
- [Documentation d'OpenAI Codex](https://developers.openai.com/codex)
- [Google Antigravity](https://antigravity.google)
- [Model Context Protocol](https://modelcontextprotocol.io)

**Design et CSS**

- [La règle CSS @layer (MDN)](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer)
- [Contraste minimum WCAG (W3C)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)

**Qualité, sécurité, production**

- [Conventional Commits](https://www.conventionalcommits.org) · [SemVer](https://semver.org) · [Keep a Changelog](https://keepachangelog.com)
- [pre-commit](https://pre-commit.com) · [gitleaks](https://github.com/gitleaks/gitleaks) · [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [uv](https://docs.astral.sh/uv/) et [uv avec Docker](https://docs.astral.sh/uv/guides/integration/docker/)
- [The Twelve-Factor App](https://12factor.net)

**Tests de sécurité, de charge et de performance**

- [OWASP Top 10 pour les applications LLM](https://genai.owasp.org) · [OWASP ZAP](https://www.zaproxy.org) · [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/) (pour s'entraîner)
- [Bandit](https://bandit.readthedocs.io) · [Semgrep](https://semgrep.dev) · [pip-audit](https://github.com/pypa/pip-audit) · [Trivy](https://trivy.dev)
- [Locust](https://locust.io) · [k6](https://k6.io) · [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview)

**Gemma et Copilot pour le Hack Day**

- [Ressources Gemma 4 de MLH](https://mlh.link/gemma) · [Quickstart](https://mlh.link/gemma-quickstart) · [Guide débutant](https://mlh.link/gemma-beginnerguide) · [Documentation](https://mlh.link/gemma-docs)
- [Utiliser Gemma avec l'API Gemini](https://ai.google.dev/gemma/docs/core/gemma_on_gemini_api) · [Clé d'API gratuite dans Google AI Studio](https://aistudio.google.com/)
- [Copilot gratuit pour les étudiants](https://mlh.link/GitHub)

**Pour mettre ce guide en pratique**

- L'atelier pas à pas de cette série : construire AgriScan avec Gemma 4, en appliquant ce guide.

---

*Guide écrit par Python Togo pour le Hacktoberfest Hack Day Lomé x Python Togo, le 24 octobre 2026, et pensé pour durer : les outils changeront, la méthode restera. Améliore-le, partage-le, et rejoins la communauté : [pytogo.org/discord](https://pytogo.org/discord).*

