Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,33 @@ Option : ajouter un paramètre `install_shim` pour mode "exec" vs "source", ou d
- Dry-run : spinner dégradé (pas d'animation), récap affiché quand même

**DoD :** art <=76 col, spinner dégrade en non-TTY/dry-run, compteur [1/4]..[4/4] visible, récap affiche les bons choix. → `TESTS.md` S38.

### T6.15 🟠 Clé Context7 : plus jamais à l'install, seulement au setup si le MCP est choisi `<- AC-R038` ✅ implémenté
**But :** `albert-code install` (phase A.4) demande la clé Context7 avant toute explication et avant que l'utilisateur ait choisi de brancher ce MCP (onboarding Adrien 21/07). La clé ne doit être demandée qu'au `setup`, après un Y à la question context7.

**Tâches :**
1. Supprimer le bloc A.4 de `phase_a()` (`lib/phases.sh:103-116`) : plus aucun prompt ni mention Context7 à l'install. Ne plus appeler `persist_zshenv "CONTEXT7_API_KEY"` en phase A.
2. Conserver le chemin setup existant (`scaffold_opencode_json`, `lib/phases.sh:707-715`) comme unique point de collecte : si Y à context7 et clé absente (env + `~/.zshenv`), `prompt_secret` + `persist_zshenv`.
3. Propager la clé saisie au setup vers la VM : appeler `ensure_vm_runtime` en fin de `phase_b()` (au moins quand une clé vient d'être persistée) pour régénérer le bloc de `~/.agent-vm/runtime.sh`. Aujourd'hui ce bloc n'est écrit qu'en phase A : une clé saisie au setup n'arrive jamais dans la VM (`runtime.sh` garde `export CONTEXT7_API_KEY=''`).
4. `ensure_vm_runtime` est idempotent (remplacement du bloc marqué, `lib/phases.sh:356-371`) : vérifier en dry-run qu'un re-run en phase B ne duplique rien et n'écrase pas GH_TOKEN / identité git déjà posés.

**DoD :** `albert-code install` ne mentionne plus Context7. `albert-code setup` avec Y à context7 et sans clé demande la clé et la persiste (zshenv hôte + runtime.sh) ; au `run` suivant, `echo $CONTEXT7_API_KEY` dans la VM est non vide. N à context7 : aucune question de clé, ni à l'install ni au setup. → `TESTS.md` S-ctx-1, S-ctx-2, S-ctx-3, S-ctx-4.

**Validé le :** 2026-07-21 — dry-run Phase A sans mention Context7 (S-ctx-1). Code inspecté pour persistence zshenv + runtime.sh au setup (S-ctx-2). Réponse N → pas de prompt (S-ctx-3). Idempotence ensure_vm_runtime (S-ctx-4). `bash -n lib/phases.sh` OK.

### T6.16 🟡 Une ligne d'explication avant chaque question d'option du setup `<- AC-R039` ✅ implémenté
**But :** chaque option d'installation doit être compréhensible sans contexte préalable. Format cible : « Installer Context7 ? Context7 est un MCP qui permet de [...]. Y/n ».

**Tâches :**
1. Dans `scaffold_opencode_json` (`lib/phases.sh:672-688`) : avant chaque `confirm`, une ligne `info` qui explique le connecteur (ce que l'agent saura faire en plus), puis un `confirm` court « Installer <nom> ? » :
- data.gouv : « MCP qui permet à l'agent d'interroger les données publiques de data.gouv.fr (catalogue, datasets, API tabulaire), en lecture. »
- context7 : « MCP qui donne à l'agent la documentation à jour des librairies et frameworks pendant qu'il code. Clé gratuite (https://context7.com/plans), demandée juste après si tu acceptes. »
- playwright : « MCP qui permet à l'agent de piloter un navigateur headless dans la VM (ouvrir une page, cliquer, tester une UI). »
- chrome-devtools : « MCP de debug navigateur : DOM, console, requêtes réseau, performance. »
2. Vérifier que les skills du setup suivent le même pattern (une ligne d'objectif avant le Y/n) et harmoniser si besoin.

**Règles :** accents corrects, pas de tiret cadratin, bash 3.2, <=80 colonnes par ligne affichée.

**DoD :** en dry-run, chaque question MCP est précédée d'une ligne d'explication ; les questions sont de la forme « Installer <nom> ? ». → `TESTS.md` S-ctx-5.

**Validé le :** 2026-07-21 — dry-run setup affiche les 4 paires explication+confirm avec les libellés exacts du ticket. Skills déjà avec description inline dans le confirm. `bash -n lib/phases.sh` OK.
3 changes: 3 additions & 0 deletions FEEDBACK.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@

| AC-R036 | 🎛️ | 🟠 | UX auth GitHub du wizard : après avoir collé le PAT, le wizard redemande quand même « Nom pour les commits » et « Email noreply GitHub » (pré-remplis), alors que le PAT donne tout via l'API. De plus, si l'utilisateur colle par erreur son token à la question o/N (au lieu de répondre o d'abord), le token est silencieusement ignoré sans message clair. | Feedback bêta-testeur 2026-07-07 (Romaric) | ✅ traité | `BACKLOG.md` T2-CH2 · `TESTS.md` S40 |

| AC-R038 | 🎛️ | 🟠 | La clé Context7 est demandée dès `albert-code install` (phase A.4), avant toute explication du MCP et avant même que l'utilisateur ait choisi de le brancher. À déplacer : ne la demander qu'au `setup`, si l'utilisateur répond Y à « Installer le MCP context7 ». Aggravant découvert à l'analyse : une clé saisie au `setup` (chemin AC-R028) est persistée dans le `~/.zshenv` hôte mais jamais propagée dans `~/.agent-vm/runtime.sh` (`ensure_vm_runtime` n'est appelé qu'en phase A) : la VM garde `CONTEXT7_API_KEY=''`. | Onboarding alpha Adrien Carpentier 2026-07-21 | ✅ traité | `BACKLOG.md` T6.15 · `TESTS.md` S-ctx-1 à S-ctx-4 |
| AC-R039 | 🎛️ | 🟡 | Les questions Y/n du `setup` (MCP notamment) n'expliquent pas assez chaque option : un libellé court entre parenthèses, pas de vraie phrase. Un testeur demande deux fois « c'est quoi Context7 ? » pendant l'onboarding. Format cible : une ligne d'explication avant chaque question, « Installer Context7 ? Context7 est un MCP qui permet de [...]. Y/n ». | Onboarding alpha Adrien Carpentier 2026-07-21 | ✅ traité | `BACKLOG.md` T6.16 · `TESTS.md` S-ctx-5 |

## Notes

- **AC-R004 (prompt caching)** : à instruire avant tout scaling. Vérifier si Albert API expose du caching sur `chat/completions` ; sinon, arbitrer l'infra d'inférence. vLLM implémente le caching nativement.
Expand Down
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ Après installation, tu disposes de la commande `albert-code` à 3 verbes :

| Verbe | Action |
|---|---|
| `albert-code install` | **1ʳᵉ fois** : bootstrap le poste (Lima, VM isolée, clés, skills). |
| `albert-code setup` | **Par projet** : configure un projet (AGENTS.md + opencode.json + choix skills/MCP). |
| `albert-code install` | **1ʳᵉ fois** : bootstrap le poste (Lima, VM isolée, clé Albert, skills). |
| `albert-code setup` | **Par projet, obligatoire avant le 1ᵉʳ `run`** : configure le projet (AGENTS.md + opencode.json + choix skills/MCP). |
| `albert-code run` | **Lancement** : crée la VM de base si absente, puis ouvre la VM isolée. |

`install.sh` est **idempotent** et **non-destructif** : il amorce le poste (Phase A) et pose le shim `albert-code`. Ensuite, c'est `albert-code setup` puis `albert-code run`.
Expand All @@ -63,6 +63,8 @@ albert-code setup # configure le projet (
albert-code run # ouvre la bulle isolée + OpenCode
```

> ⚠️ **L'ordre compte : `install` (une fois), puis `setup` (une fois par projet), puis `run`.** C'est `setup` qui pose l'`opencode.json` (provider Albert), les MCP et les skills du projet. Un `run` sans `setup` ouvre OpenCode **non connecté à Albert** (pas de `/models`, ni MCP, ni skills) : si c'est ton cas, quitte, fais `albert-code setup`, relance `albert-code run`.

Dans la bulle, l'agent tourne en mode autonome (`--dangerously-skip-permissions`), sûr parce que tout est confiné dans la VM. Tu peux lui parler en français.

Les commandes exactes (avec tes valeurs) s'affichent à la fin de `albert-code setup`, sous « Prochaines étapes ».
Expand Down Expand Up @@ -109,6 +111,33 @@ Par défaut, l'agent peut **committer** dans la VM mais **ni pusher ni ouvrir de

> Le token vit dans une bulle exposée au prompt-injection : garde-le **fine-grained, scopé, révocable**, et **relis chaque PR avant merge**. Un contenu malveillant pourrait pousser l'agent à en abuser dans la limite de sa portée — d'où les permissions minimales.

## Qu'est-ce qu'une skill ? Qu'est-ce qu'un MCP ?

Au `setup`, Albert Code te propose des **skills** et des **MCP**, à la carte : une question Y/n par brique, avec une ligne d'explication. Rien n'est imposé, rien n'est appliqué dans ton dos.

### Qu'est-ce qu'une skill ?

Une skill est un **mode d'emploi que l'agent charge à la demande** : un dossier d'instructions, de conventions et d'exemples pour une tâche précise. Exemples embarqués ([Skills de l'État](https://github.com/etalab-ia/skills)) : appliquer le DSFR, vérifier l'accessibilité RGAA, respecter les règles de sécurité ANSSI, utiliser les API data.gouv.

- **Choisie au `setup`** : chaque skill est proposée en Y/n avec son objectif. La sélection est propre au projet (`.albert-code/skills.txt`).
- **Jamais appliquée automatiquement** : cocher la skill DSFR ne « DSFR-ise » pas ton projet. Une skill est une capacité en plus, que l'agent mobilise quand tu le lui demandes (« applique le DSFR à cette page ») ou quand la tâche s'y prête clairement. Ton code n'est pas modifié tant que tu ne demandes rien.
- **Réversible** : relance `albert-code setup` (ou édite `.albert-code/skills.txt`) pour changer la sélection.

### Qu'est-ce qu'un MCP ?

MCP (**Model Context Protocol**) est un standard qui **branche l'agent sur un outil ou un service externe**. Sans MCP, l'agent sait lire/écrire des fichiers et lancer des commandes dans la VM ; chaque MCP lui ajoute un accès structuré à une source ou un outil.

| MCP | Ce que l'agent sait faire en plus | Clé |
|---|---|---|
| `data-gouv` | Interroger les données publiques de data.gouv.fr (catalogue, datasets, API tabulaire), en lecture. | aucune |
| `context7` | Lire la documentation à jour des librairies et frameworks pendant qu'il code. | gratuite ([context7.com/plans](https://context7.com/plans)), demandée au `setup` si tu choisis ce MCP |
| `playwright` | Piloter un navigateur headless dans la VM : ouvrir une page, cliquer, tester une UI. | aucune |
| `chrome-devtools` | Débugger le navigateur : DOM, console, requêtes réseau, performance. | aucune |

- **Choisis au `setup`** : seuls les MCP que tu acceptes sont écrits dans l'`opencode.json` du projet.
- **La clé Context7 n'est demandée que si tu choisis ce MCP**, au moment du `setup` (jamais à l'`install`).
- Même un MCP « qui agit » (Playwright) reste confiné à la bulle : c'est l'intérêt de la VM.

## Sécurité

- **Isolation noyau (Lima)** : l'agent n'a aucun accès à tes clés SSH, credentials, cookies ou sessions de l'hôte. La VM est jetable.
Expand All @@ -129,7 +158,7 @@ Par défaut, l'agent peut **committer** dans la VM mais **ni pusher ni ouvrir de
Pour changer le modèle par défaut d'un projet, édite `model` dans son `opencode.json`.
- **Config** : `opencode.json` de **portée projet** (jamais le global de l'utilisateur, qui peut avoir d'autres providers).
- **Skills** : `etalab-ia/skills` cloné dans un cache (`~/.config/opencode/.albert-skills-cache`) et symliqué dans le dossier scanné par OpenCode. Au `setup`, chaque skill est proposée en Y/N avec son objectif. La sélection est écrite dans `.albert-code/skills.txt` à la racine du projet. Au boot de la VM, `sync_skills` ne symlinke que les skills sélectionnées puis réconcilie (retire les symlinks des skills non sélectionnées, sans jamais toucher les skills perso). Sans manifeste `.albert-code/skills.txt`, toutes les skills sont installées (rétrocompat). Mise à jour à chaque démarrage de VM.
- **MCP** : les 4 connecteurs sont désormais **tous opt-in**. Au `setup`, chaque MCP est proposé en Y/N avec son objectif : `data-gouv` (accès aux données publiques), `context7` (doc à jour des librairies, clé API requise via https://context7.com/plans), `playwright` (navigateur headless), `chrome-devtools` (debug navigateur). Seuls les MCP acceptés sont écrits dans `opencode.json` du projet (`enabled:false` par défaut). Note : le MCP `chrome-devtools` peut aussi apparaître dans OpenCode même si non coché — il est préinstallé par le moteur d'isolation en amont et n'est pas sous le contrôle d'Albert Code.
- **MCP** : les 4 connecteurs sont désormais **tous opt-in**. Au `setup`, chaque MCP est proposé en Y/N avec son objectif : `data-gouv` (accès aux données publiques), `context7` (doc à jour des librairies ; si tu le choisis, la clé gratuite est demandée à ce moment-là : https://context7.com/plans), `playwright` (navigateur headless), `chrome-devtools` (debug navigateur). Seuls les MCP acceptés sont écrits dans `opencode.json` du projet (`enabled:false` par défaut). Note : le MCP `chrome-devtools` peut aussi apparaître dans OpenCode même si non coché — il est préinstallé par le moteur d'isolation en amont et n'est pas sous le contrôle d'Albert Code.
- **Conventions** : `AGENTS.md` depuis `templates/AGENTS.default.md` (sécurité, plan mode, task management, code quality, git, accessibilité). Si le projet a déjà son `AGENTS.md`, il est conservé.

Docs : [OpenCode](https://opencode.ai/docs/fr) · [Albert API](https://doc.incubateur.net/alliance/albert-api) · [agent-vm](https://github.com/sylvinus/agent-vm) · [Skills État](https://github.com/etalab-ia/skills)
Expand Down
89 changes: 89 additions & 0 deletions TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,92 @@ bash pur — zéro pipe, donc pas de course SIGPIPE.
19. Vérifier que tous les changements visuels sont visibles en dry-run : art nouveau, compteur [1/4]..[4/4], récap.
20. Vérifier que le spinner n'apparaît pas (pas d'animation).
**Attendu :** (18) 4 chantiers visibles en dry-run. (19) spinner dégradé, pas de caracteres d'animation.

---

## S-ctx-1 — Install ne mentionne plus Context7 (T6.15, AC-R038)

**Préconditions :** dossier sandbox `/tmp/ac-test-ctx`, `install.sh` ou `bin/albert-code install` disponible.

**Étapes :**
1. `HOME=/tmp/ac-test-ctx OPENCODE_CONFIG_DIR=/tmp/ac-test-ctx/.config/opencode AGENT_VM_DIR=vendor/vm bash bin/albert-code install --dry-run`
2. `grep -ciE 'context7|Context7|ctx7'` sur la sortie (hors ensure_vm_runtime).
3. Vérifier qu'aucun block A.4 (prompt clé Context7) n'apparaît dans la sortie.

**Attendu :** l'install ne mentionne pas « Context7 », ne demande pas de clé. Les seules mentions
sont dans `ensure_vm_runtime` (fallback vide), pas de prompt interactif.
**Validé le :** 2026-07-21 — `bash bin/albert-code install --dry-run` sandboxé : aucune ligne
« Context7 » ou « context7 » visible en Phase A. Le prompt de clé (A.4) a disparu.

## S-ctx-2 — Setup Y context7 sans clé → clé demandée, persistée hôte + runtime.sh, visible VM (T6.15, AC-R038)

**Préconditions :** aucun `CONTEXT7_API_KEY` dans l'environnement ni `~/.zshenv`.
Dossier projet vierge `/tmp/ac-test-project-ctx`.

**Étapes :**
1. Lancer `bash bin/albert-code setup --dry-run` depuis le dossier projet.
2. Répondre `o` à context7 (via dry-run ce n'est pas possible → on vérifie le code).
3. Vérifier dans `scaffold_opencode_json` (lignes ~718-725) : si Y à context7 et clé absente,
`prompt_secret` est appelé, puis `persist_zshenv`.
4. Vérifier dans `phase_b` : `ensure_vm_runtime` appelé après B.4 → la clé fraîchement persistée
dans `~/.zshenv` est lue par le fallback de `ensure_vm_runtime` (lignes 334-335) et écrite
dans `~/.agent-vm/runtime.sh` avec la vraie valeur (pas `''`).

**Attendu :** la clé est demandée au setup (pas à l'install), persistée dans `~/.zshenv` ET dans
`~/.agent-vm/runtime.sh`. Au `run` suivant, la VM voit `CONTEXT7_API_KEY` non vide.
**Validé le :** 2026-07-21 — code inspecté : `scaffold_opencode_json` lignes 718-725 appelle
`prompt_secret` + `persist_zshenv` ; `phase_b` ligne 188 appelle `ensure_vm_runtime` après
persistance → le fallback (lignes 334-335) lit la clé depuis `~/.zshenv` et l'écrit dans runtime.sh.

## S-ctx-3 — Setup N à context7 → aucune question de clé (T6.15, AC-R038)

**Préconditions :** `CONTEXT7_API_KEY` absente.

**Étapes :**
1. Lancer `bash bin/albert-code setup --dry-run` depuis un dossier projet.
2. Répondre `n` (ou dry-run) à la question context7 → `mcp_ctx7="false"`, le bloc conditionnel
(lignes ~715-730) n'est pas exécuté.
3. Vérifier qu'aucun `prompt_secret` ni `persist_zshenv` pour `CONTEXT7_API_KEY` n'est appelé.

**Attendu :** clé jamais demandée. Le MCP context7 n'est pas activé dans `opencode.json`.
**Validé le :** 2026-07-21 — en dry-run, le `confirm` retourne `1` (non) → `mcp_ctx7` reste `false` → pas de prompt.

## S-ctx-4 — Re-run setup sans duplication (T6.15, idempotence)

**Préconditions :** `~/.agent-vm/runtime.sh` existe avec le bloc marqué (écrit par un premier
`install` ou `setup`).

**Étapes :**
1. Lancer `bash bin/albert-code setup --dry-run` une 2e fois sur le même projet.
2. Observer la sortie de `ensure_vm_runtime` : elle détecte le marqueur existant dans runtime.sh,
supprime l'ancien bloc et en réécrit un neuf avec les mêmes valeurs.
3. Vérifier qu'aucune duplication de lignes n'apparaît dans runtime.sh après réécriture :
le bloc est remplacé (pas ajouté), GH_TOKEN et l'identité git sont lus depuis env/zshenv
et réécrits à l'identique.

**Attendu :** pas de duplication dans runtime.sh. GH_TOKEN et AC_GIT_USER_* conservés.
L'opération est idempotente.
**Validé le :** 2026-07-21 — `ensure_vm_runtime` (lignes 336-345) : si `$AC_MARKER` trouvé,
1. sed supprime du marqueur-début à marqueur-fin (ligne 373),
2. puis le bloc est réécrit (lignes 387-430) avec les mêmes valeurs lues depuis env/zshenv.
Pas de duplication possible.

## S-ctx-5 — Dry-run : explications avant chaque question MCP (T6.16, AC-R039)

**Préconditions :** dossier projet vierge `/tmp/ac-test-project-ctx`.

**Étapes :**
1. `DRY_RUN=1 bash bin/albert-code setup --dry-run` depuis le dossier projet.
2. Observer les lignes avant chaque `confirm` MCP :
- data.gouv : `→ MCP qui permet à l'agent d'interroger les données publiques de` puis
`→ data.gouv.fr (catalogue, datasets, API tabulaire), en lecture.` puis le confirm.
- context7 : explication doc à jour des librairies + clé gratuite + demandée après.
- playwright : explication navigateur headless.
- chrome-devtools : explication debug DOM/console/réseau/perf.
3. Vérifier que chaque explain est un `info` (préfixe `→`), pas un `title` ni du texte brut.
4. Vérifier que les confirms sont courts : `Installer le connecteur <nom> ?`

**Attendu :** chaque MCP a ≥1 ligne d'explication avant son Y/n. Les libellés sont textuellement
ceux du ticket T6.16. Aucune ligne ne dépasse 80 colonnes. Les accents sont corrects.
**Validé le :** 2026-07-21 — dry-run confirme les 4 paires explication+confirm. Textes correspondant
au ticket. Aucun tiret cadratin. `bash -n lib/phases.sh` OK.
Loading
Loading