---
read_when:
    - Exécuter les tests localement ou en CI
    - Ajout de tests de régression pour les bogues de modèle/fournisseur
    - Débogage du comportement du Gateway et de l’agent
summary: 'Kit de test : suites unitaires, e2e et en conditions réelles, runners Docker et ce que couvre chaque test'
title: Tests
x-i18n:
    generated_at: "2026-05-11T20:41:07Z"
    model: gpt-5.5
    provider: openai
    source_hash: cfc73e8b86188dbc58a92f36a90b9fb4d59ac4cce2c60e0bd81aca662a524561
    source_path: help/testing.md
    workflow: 16
---

OpenClaw dispose de trois suites Vitest (unitaires/intégration, e2e, live) et d’un petit ensemble
d’exécuteurs Docker. Ce document est un guide « comment nous testons » :

- Ce que couvre chaque suite (et ce qu’elle ne couvre délibérément _pas_).
- Quelles commandes exécuter pour les workflows courants (local, pré-push, débogage).
- Comment les tests live découvrent les identifiants et sélectionnent les modèles/fournisseurs.
- Comment ajouter des régressions pour les problèmes réels de modèles/fournisseurs.

<Note>
**La pile QA (qa-lab, qa-channel, voies de transport live)** est documentée séparément :

- [Vue d’ensemble QA](/fr/concepts/qa-e2e-automation) - architecture, surface de commandes, création de scénarios.
- [QA matricielle](/fr/concepts/qa-matrix) - référence pour `pnpm openclaw qa matrix`.
- [Canal QA](/fr/channels/qa-channel) - le plugin de transport synthétique utilisé par les scénarios adossés au dépôt.

Cette page couvre l’exécution des suites de tests régulières et des exécuteurs Docker/Parallels. La section des exécuteurs propres à QA ci-dessous ([Exécuteurs propres à QA](#qa-specific-runners)) liste les invocations `qa` concrètes et renvoie aux références ci-dessus.
</Note>

## Démarrage rapide

La plupart du temps :

- Barrière complète (attendue avant push) : `pnpm build && pnpm check && pnpm check:test-types && pnpm test`
- Exécution plus rapide de toute la suite locale sur une machine confortable : `pnpm test:max`
- Boucle de surveillance Vitest directe : `pnpm test:watch`
- Le ciblage direct de fichiers route désormais aussi les chemins d’extensions/canaux : `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`
- Préférez d’abord les exécutions ciblées lorsque vous itérez sur un seul échec.
- Site QA adossé à Docker : `pnpm qa:lab:up`
- Voie QA adossée à une VM Linux : `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline`

Lorsque vous touchez aux tests ou voulez davantage de confiance :

- Barrière de couverture : `pnpm test:coverage`
- Suite E2E : `pnpm test:e2e`

Lors du débogage de vrais fournisseurs/modèles (nécessite de vrais identifiants) :

- Suite live (modèles + sondes d’outils/images du Gateway) : `pnpm test:live`
- Cibler silencieusement un fichier live : `pnpm test:live -- src/agents/models.profiles.live.test.ts`
- Rapports de performances d’exécution : déclenchez `OpenClaw Performance` avec
  `live_gpt54=true` pour un vrai tour d’agent `openai/gpt-5.4` ou
  `deep_profile=true` pour des artefacts CPU/tas/trace Kova. Les exécutions planifiées quotidiennes
  publient des artefacts des voies fournisseur simulé, profil profond et GPT 5.4 vers
  `openclaw/clawgrit-reports` lorsque `CLAWGRIT_REPORTS_TOKEN` est configuré. Le
  rapport fournisseur simulé inclut aussi les chiffres de démarrage du Gateway au niveau source, mémoire,
  pression des plugins, boucle de salutation répétée avec faux modèle et démarrage CLI.
- Balayage live des modèles Docker : `pnpm test:docker:live-models`
  - Chaque modèle sélectionné exécute désormais un tour texte plus une petite sonde de type lecture de fichier.
    Les modèles dont les métadonnées annoncent une entrée `image` exécutent aussi un petit tour image.
    Désactivez les sondes supplémentaires avec `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` ou
    `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` lors de l’isolation des échecs de fournisseur.
  - Couverture CI : les workflows quotidiens `OpenClaw Scheduled Live And E2E Checks` et manuels
    `OpenClaw Release Checks` appellent tous deux le workflow live/E2E réutilisable avec
    `include_live_suites: true`, ce qui inclut des jobs distincts de matrice live Docker
    par fragments de fournisseur.
  - Pour des relances CI ciblées, déclenchez `OpenClaw Live And E2E Checks (Reusable)`
    avec `include_live_suites: true` et `live_models_only: true`.
  - Ajoutez les nouveaux secrets fournisseur à fort signal dans `scripts/ci-hydrate-live-auth.sh`
    ainsi que `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` et ses
    appelants planifiés/release.
- Smoke test de discussion liée Codex natif : `pnpm test:docker:live-codex-bind`
  - Exécute une voie live Docker contre le chemin serveur d’application Codex, lie un DM Slack synthétique
    avec `/codex bind`, exerce `/codex fast` et
    `/codex permissions`, puis vérifie qu’une réponse simple et une pièce jointe image
    passent par la liaison native du plugin au lieu d’ACP.
- Smoke test du harnais serveur d’application Codex : `pnpm test:docker:live-codex-harness`
  - Exécute des tours d’agent Gateway via le harnais serveur d’application Codex détenu par le plugin,
    vérifie `/codex status` et `/codex models`, et exerce par défaut les sondes image,
    MCP Cron, sous-agent et Guardian. Désactivez la sonde sous-agent avec
    `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` lors de l’isolation d’autres échecs du serveur d’application Codex. Pour une vérification ciblée du sous-agent, désactivez les autres sondes :
    `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`.
    Cela quitte après la sonde sous-agent sauf si
    `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0` est défini.
- Smoke test d’installation Codex à la demande : `pnpm test:docker:codex-on-demand`
  - Installe le tarball OpenClaw empaqueté dans Docker, exécute l’onboarding par clé API OpenAI,
    et vérifie que le plugin Codex ainsi que la dépendance `@openai/codex`
    ont été téléchargés à la demande dans la racine npm gérée.
- Smoke test live de dépendance d’outil de plugin : `pnpm test:docker:live-plugin-tool`
  - Empaquète un plugin fixture avec une vraie dépendance `slugify`, l’installe via
    `npm-pack:`, vérifie la dépendance sous la racine npm gérée, puis demande à un
    modèle OpenAI live d’appeler l’outil du plugin et de renvoyer le slug masqué.
- Smoke test de commande de secours Crestodian : `pnpm test:live:crestodian-rescue-channel`
  - Vérification opt-in renforcée de la surface de commande de secours du canal de messages.
    Elle exerce `/crestodian status`, met en file d’attente un changement persistant de modèle,
    répond `/crestodian yes`, et vérifie le chemin d’écriture audit/config.
- Smoke test Docker du planificateur Crestodian : `pnpm test:docker:crestodian-planner`
  - Exécute Crestodian dans un conteneur sans configuration avec un faux CLI Claude sur `PATH`
    et vérifie que le repli du planificateur flou se traduit par une écriture de configuration typée auditée.
- Smoke test Docker de première exécution Crestodian : `pnpm test:docker:crestodian-first-run`
  - Démarre depuis un répertoire d’état OpenClaw vide, route `openclaw` nu vers
    Crestodian, applique des écritures setup/modèle/agent/plugin Discord + SecretRef,
    valide la configuration et vérifie les entrées d’audit. Le même chemin de configuration Ring 0 est
    aussi couvert dans QA Lab par
    `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup`.
- Smoke test de coût Moonshot/Kimi : avec `MOONSHOT_API_KEY` défini, exécutez
  `openclaw models list --provider moonshot --json`, puis exécutez un
  `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`
  isolé contre `moonshot/kimi-k2.6`. Vérifiez que le JSON indique Moonshot/K2.6 et que la
  transcription de l’assistant stocke `usage.cost` normalisé.

<Tip>
Lorsque vous n’avez besoin que d’un seul cas en échec, préférez restreindre les tests live via les variables d’environnement de liste d’autorisation décrites ci-dessous.
</Tip>

## Exécuteurs propres à QA

Ces commandes complètent les suites de tests principales lorsque vous avez besoin du réalisme de QA-lab :

La CI exécute QA Lab dans des workflows dédiés. La parité agentique est imbriquée sous
`QA-Lab - All Lanes` et la validation de release, pas dans un workflow PR autonome.
La validation large doit utiliser `Full Release Validation` avec
`rerun_group=qa-parity` ou le groupe QA des vérifications de release. Les vérifications
de release stables/par défaut gardent le soak live/Docker exhaustif derrière `run_release_soak=true` ; le
profil `full` force le soak. `QA-Lab - All Lanes`
s’exécute chaque nuit sur `main` et depuis un déclenchement manuel avec la voie de parité simulée, la voie Matrix live, la voie Telegram live gérée par Convex et la voie Discord live gérée par Convex comme jobs parallèles. Les vérifications QA planifiées et de release passent explicitement
Matrix `--profile fast`, tandis que le CLI Matrix et l’entrée de workflow manuelle
restent par défaut sur `all` ; le déclenchement manuel peut fragmenter `all` en jobs `transport`,
`media`, `e2ee-smoke`, `e2ee-deep` et `e2ee-cli`. `OpenClaw Release
Checks` exécute la parité ainsi que les voies rapides Matrix et Telegram avant l’approbation de release, en utilisant `mock-openai/gpt-5.5` pour les vérifications de transport de release afin qu’elles restent
déterministes et évitent le démarrage normal du plugin fournisseur. Ces Gateways de transport live
désactivent la recherche mémoire ; le comportement mémoire reste couvert par les suites de parité QA.

Les fragments live media de release complète utilisent
`ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`, qui dispose déjà de
`ffmpeg` et `ffprobe`. Les fragments live Docker modèle/backend utilisent l’image partagée
`ghcr.io/openclaw/openclaw-live-test:<sha>` construite une fois par commit sélectionné,
puis la récupèrent avec `OPENCLAW_SKIP_DOCKER_BUILD=1` au lieu de reconstruire
dans chaque fragment.

- `pnpm openclaw qa suite`
  - Exécute les scénarios QA adossés au dépôt directement sur l’hôte.
  - Exécute plusieurs scénarios sélectionnés en parallèle par défaut avec des
    workers Gateway isolés. `qa-channel` utilise par défaut une concurrence de 4
    (limitée par le nombre de scénarios sélectionnés). Utilisez `--concurrency <count>`
    pour ajuster le nombre de workers, ou `--concurrency 1` pour l’ancien lane série.
  - Se termine avec un code non nul si un scénario échoue. Utilisez `--allow-failures`
    lorsque vous voulez des artefacts sans code de sortie en échec.
  - Prend en charge les modes fournisseur `live-frontier`, `mock-openai` et `aimock`.
    `aimock` démarre un serveur fournisseur local adossé à AIMock pour une
    couverture expérimentale des fixtures et des mocks de protocole sans remplacer
    le lane `mock-openai` sensible aux scénarios.
- `pnpm test:plugins:kitchen-sink-live`
  - Exécute le gauntlet live du plugin OpenAI Kitchen Sink via QA Lab. Il
    installe le package externe Kitchen Sink, vérifie l’inventaire de surface du
    SDK de plugin, sonde `/healthz` et `/readyz`, enregistre les preuves CPU/RSS
    du Gateway, exécute un tour OpenAI live et vérifie les diagnostics
    adversariaux. Nécessite une authentification OpenAI live telle que
    `OPENAI_API_KEY`. Dans les sessions Testbox hydratées, il source
    automatiquement le profil live-auth Testbox lorsque l’assistant
    `openclaw-testbox-env` est présent.
- `pnpm test:gateway:cpu-scenarios`
  - Exécute le banc de démarrage du Gateway ainsi qu’un petit pack de scénarios
    QA Lab mock (`channel-chat-baseline`, `memory-failure-fallback`,
    `gateway-restart-inflight-run`) et écrit un résumé combiné des observations
    CPU sous `.artifacts/gateway-cpu-scenarios/`.
  - Signale par défaut uniquement les observations de CPU élevé soutenu
    (`--cpu-core-warn` plus `--hot-wall-warn-ms`), afin que les courts pics de
    démarrage soient enregistrés comme métriques sans ressembler à la régression
    de Gateway bloqué pendant plusieurs minutes.
  - Utilise les artefacts `dist` construits ; exécutez d’abord une build lorsque
    le checkout ne contient pas déjà une sortie runtime fraîche.
- `pnpm openclaw qa suite --runner multipass`
  - Exécute la même suite QA dans une VM Linux Multipass jetable.
  - Conserve le même comportement de sélection de scénarios que `qa suite` sur l’hôte.
  - Réutilise les mêmes indicateurs de sélection fournisseur/modèle que `qa suite`.
  - Les exécutions live transmettent les entrées d’authentification QA prises en
    charge qui sont pratiques pour l’invité : clés fournisseur basées sur l’env,
    chemin de configuration du fournisseur live QA et `CODEX_HOME` lorsqu’il est présent.
  - Les répertoires de sortie doivent rester sous la racine du dépôt afin que
    l’invité puisse réécrire via l’espace de travail monté.
  - Écrit le rapport QA et le résumé normaux, plus les journaux Multipass sous
    `.artifacts/qa-e2e/...`.
- `pnpm qa:lab:up`
  - Démarre le site QA adossé à Docker pour le travail QA de type opérateur.
- `pnpm test:docker:npm-onboard-channel-agent`
  - Construit une tarball npm depuis le checkout actuel, l’installe globalement
    dans Docker, exécute l’onboarding non interactif avec clé API OpenAI,
    configure Telegram par défaut, vérifie que le runtime du plugin packagé se
    charge sans réparation de dépendances au démarrage, exécute doctor, puis
    exécute un tour d’agent local contre un endpoint OpenAI mocké.
  - Utilisez `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` pour exécuter le même lane
    d’installation packagée avec Discord.
- `pnpm test:docker:session-runtime-context`
  - Exécute un smoke Docker déterministe d’application construite pour les
    transcriptions de contexte runtime embarqué. Il vérifie que le contexte
    runtime OpenClaw masqué est persisté comme message personnalisé non affiché
    au lieu de fuiter dans le tour utilisateur visible, puis amorce une session
    JSONL cassée affectée et vérifie que `openclaw doctor --fix` la réécrit vers
    la branche active avec une sauvegarde.
- `pnpm test:docker:npm-telegram-live`
  - Installe un package candidat OpenClaw dans Docker, exécute l’onboarding du
    package installé, configure Telegram via la CLI installée, puis réutilise le
    lane QA Telegram live avec ce package installé comme Gateway SUT.
  - Le wrapper monte uniquement la source du harness `qa-lab` depuis le checkout ;
    le package installé possède `dist`, `openclaw/plugin-sdk` et le runtime de
    plugins groupés afin que le lane ne mélange pas les plugins du checkout
    actuel dans le package testé.
  - Utilise par défaut `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta` ; définissez
    `OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` ou
    `OPENCLAW_CURRENT_PACKAGE_TGZ` pour tester une tarball locale résolue au lieu
    d’installer depuis le registre.
  - Utilise les mêmes identifiants env Telegram ou la même source d’identifiants
    Convex que `pnpm openclaw qa telegram`. Pour l’automatisation CI/release,
    définissez `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex` ainsi que
    `OPENCLAW_QA_CONVEX_SITE_URL` et le secret de rôle. Si
    `OPENCLAW_QA_CONVEX_SITE_URL` et un secret de rôle Convex sont présents en CI,
    le wrapper Docker sélectionne automatiquement Convex.
  - Le wrapper valide l’env d’identifiants Telegram ou Convex sur l’hôte avant
    le travail de build/installation Docker. Définissez
    `OPENCLAW_NPM_TELEGRAM_SKIP_CREDENTIAL_PREFLIGHT=1` uniquement lorsque vous
    déboguez délibérément la configuration préalable aux identifiants.
  - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` remplace le
    `OPENCLAW_QA_CREDENTIAL_ROLE` partagé uniquement pour ce lane.
  - GitHub Actions expose ce lane comme workflow mainteneur manuel
    `NPM Telegram Beta E2E`. Il ne s’exécute pas lors d’un merge. Le workflow
    utilise l’environnement `qa-live-shared` et les baux d’identifiants CI Convex.
- GitHub Actions expose également `Package Acceptance` pour la preuve produit en
  exécution annexe contre un package candidat. Il accepte une ref approuvée, une
  spec npm publiée, une URL de tarball HTTPS avec SHA-256, ou un artefact tarball
  d’une autre exécution, téléverse le `openclaw-current.tgz` normalisé comme
  `package-under-test`, puis exécute le planificateur Docker E2E existant avec
  les profils de lane smoke, package, product, full ou custom. Définissez
  `telegram_mode=mock-openai` ou `live-frontier` pour exécuter le workflow QA
  Telegram contre le même artefact `package-under-test`.
  - Preuve produit de la dernière bêta :

```bash
gh workflow run package-acceptance.yml --ref main \
  -f source=npm \
  -f package_spec=openclaw@beta \
  -f suite_profile=product \
  -f telegram_mode=mock-openai
```

- La preuve par URL de tarball exacte nécessite un digest :

```bash
gh workflow run package-acceptance.yml --ref main \
  -f source=url \
  -f package_url=https://registry.npmjs.org/openclaw/-/openclaw-VERSION.tgz \
  -f package_sha256=<sha256> \
  -f suite_profile=package
```

- La preuve par artefact télécharge un artefact tarball depuis une autre exécution Actions :

```bash
gh workflow run package-acceptance.yml --ref main \
  -f source=artifact \
  -f artifact_run_id=<run-id> \
  -f artifact_name=<artifact-name> \
  -f suite_profile=smoke
```

- `pnpm test:docker:plugins`
  - Pack et installe la build OpenClaw actuelle dans Docker, démarre le Gateway
    avec OpenAI configuré, puis active les canaux/plugins groupés via des
    modifications de configuration.
  - Vérifie que la découverte de configuration laisse absents les plugins
    téléchargeables non configurés, que la première réparation doctor configurée
    installe explicitement chaque plugin téléchargeable manquant et qu’un second
    redémarrage n’exécute pas de réparation de dépendances masquée.
  - Installe également une baseline npm plus ancienne connue, active Telegram
    avant d’exécuter `openclaw update --tag <candidate>`, puis vérifie que le
    doctor post-update du candidat nettoie les débris de dépendances de plugin
    héritées sans réparation postinstall côté harness.
- `pnpm test:parallels:npm-update`
  - Exécute le smoke natif de mise à jour d’installation packagée sur des
    invités Parallels. Chaque plateforme sélectionnée installe d’abord le
    package de baseline demandé, puis exécute la commande `openclaw update`
    installée dans le même invité et vérifie la version installée, le statut de
    mise à jour, la disponibilité du Gateway et un tour d’agent local.
  - Utilisez `--platform macos`, `--platform windows` ou `--platform linux` lors
    de l’itération sur un seul invité. Utilisez `--json` pour le chemin de
    l’artefact de résumé et le statut par lane.
  - Le lane OpenAI utilise `openai/gpt-5.5` par défaut pour la preuve de tour
    d’agent live. Passez `--model <provider/model>` ou définissez
    `OPENCLAW_PARALLELS_OPENAI_MODEL` lorsque vous validez délibérément un autre
    modèle OpenAI.
  - Encadrez les longues exécutions locales avec un timeout hôte afin que les
    blocages de transport Parallels ne consomment pas le reste de la fenêtre de test :

    ```bash
    timeout --foreground 150m pnpm test:parallels:npm-update -- --json
    timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json
    ```

  - Le script écrit les journaux de lane imbriqués sous `/tmp/openclaw-parallels-npm-update.*`.
    Inspectez `windows-update.log`, `macos-update.log` ou `linux-update.log`
    avant de supposer que le wrapper externe est bloqué.
  - La mise à jour Windows peut passer 10 à 15 minutes dans le doctor post-update
    et le travail de mise à jour de package sur un invité froid ; cela reste
    sain lorsque le journal de debug npm imbriqué progresse.
  - N’exécutez pas ce wrapper agrégé en parallèle avec des lanes smoke
    Parallels individuels macOS, Windows ou Linux. Ils partagent l’état des VM et
    peuvent entrer en collision lors de la restauration de snapshot, du service
    de package ou de l’état du Gateway invité.
  - La preuve post-update exécute la surface normale des plugins groupés parce
    que les façades de capacité telles que la parole, la génération d’images et
    la compréhension média sont chargées via les API runtime groupées même
    lorsque le tour d’agent lui-même ne vérifie qu’une simple réponse textuelle.

- `pnpm openclaw qa aimock`
  - Démarre uniquement le serveur fournisseur AIMock local pour des tests smoke
    directs du protocole.
- `pnpm openclaw qa matrix`
  - Exécute le lane QA live Matrix contre un homeserver Tuwunel jetable adossé à Docker. Checkout source uniquement - les installations packagées ne livrent pas `qa-lab`.
  - CLI complète, catalogue de profils/scénarios, variables env et disposition des artefacts : [QA Matrix](/fr/concepts/qa-matrix).
- `pnpm openclaw qa telegram`
  - Exécute le lane QA live Telegram contre un vrai groupe privé avec les tokens du bot driver et du bot SUT issus de l’env.
  - Nécessite `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` et `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. L’id du groupe doit être l’id numérique du chat Telegram.
  - Prend en charge `--credential-source convex` pour des identifiants mutualisés partagés. Utilisez le mode env par défaut, ou définissez `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` pour opter pour les baux mutualisés.
  - Les valeurs par défaut couvrent canary, gating par mention, adressage de commandes, `/status`, réponses mentionnées bot-à-bot et réponses de commandes natives du core. Les valeurs par défaut `mock-openai` couvrent également les régressions déterministes de chaîne de réponses et de streaming du message final Telegram. Utilisez `--list-scenarios` pour les sondes optionnelles telles que `session_status`.
  - Se termine avec un code non nul si un scénario échoue. Utilisez `--allow-failures`
    lorsque vous voulez des artefacts sans code de sortie en échec.
  - Nécessite deux bots distincts dans le même groupe privé, avec le bot SUT exposant un nom d’utilisateur Telegram.
  - Pour une observation bot-à-bot stable, activez Bot-to-Bot Communication Mode dans `@BotFather` pour les deux bots et assurez-vous que le bot driver peut observer le trafic de bots du groupe.
  - Écrit un rapport QA Telegram, un résumé et un artefact de messages observés sous `.artifacts/qa-e2e/...`. Les scénarios de réponse incluent le RTT depuis la demande d’envoi du driver jusqu’à la réponse SUT observée.

`Mantis Telegram Live` est le wrapper de preuve PR autour de ce lane. Il exécute
la ref candidate avec des identifiants Telegram loués via Convex, rend la
transcription expurgée des messages observés dans un navigateur de bureau
Crabbox, enregistre une preuve MP4, génère un GIF découpé selon le mouvement,
téléverse le bundle d’artefacts et publie une preuve PR inline via la Mantis
GitHub App lorsque `pr_number` est défini. Les mainteneurs peuvent le démarrer
depuis l’interface Actions via `Mantis Scenario` (`scenario_id:
telegram-live`) ou directement depuis un commentaire de pull request :

```text
@Mantis telegram
@Mantis telegram scenario=telegram-status-command
@Mantis telegram scenarios=telegram-status-command,telegram-mentioned-message-reply
```

`Mantis Telegram Desktop Proof` est le wrapper agentique natif Telegram Desktop
avant/après pour la preuve visuelle de PR. Démarrez-le depuis l’interface
Actions avec des `instructions` libres, via `Mantis Scenario` (`scenario_id:
telegram-desktop-proof`), ou depuis un commentaire de PR :

```text
@Mantis telegram desktop proof
```

L’agent Mantis lit la PR, décide quel comportement visible dans Telegram prouve le
changement, exécute la voie de preuve Crabbox Telegram Desktop avec utilisateur réel sur les refs de base et candidates, itère jusqu’à ce que les GIFs natifs soient utiles, écrit un manifeste
`motionPreview` appairé, et publie le même tableau GIF à 2 colonnes via la
Mantis GitHub App lorsque `pr_number` est défini.

- `pnpm openclaw qa mantis telegram-desktop-builder`
  - Loue ou réutilise un bureau Linux Crabbox, installe Telegram Desktop natif, configure OpenClaw avec un jeton de bot SUT Telegram loué, démarre le Gateway, et enregistre des preuves par capture d’écran/MP4 depuis le bureau VNC visible.
  - Utilise par défaut `--credential-source convex` afin que les workflows n’aient besoin que du secret du courtier Convex. Utilisez `--credential-source env` avec les mêmes variables `OPENCLAW_QA_TELEGRAM_*` que `pnpm openclaw qa telegram`.
  - Telegram Desktop nécessite toujours une connexion/un profil utilisateur. Le jeton de bot configure uniquement OpenClaw. Utilisez `--telegram-profile-archive-env <name>` pour une archive de profil `.tgz` en base64, ou utilisez `--keep-lease` et connectez-vous manuellement une fois via VNC.
  - Écrit `mantis-telegram-desktop-builder-report.md`, `mantis-telegram-desktop-builder-summary.json`, `telegram-desktop-builder.png` et `telegram-desktop-builder.mp4` dans le répertoire de sortie.

Les voies de transport en direct partagent un contrat standard unique afin que les nouveaux transports ne divergent pas ; la matrice de couverture par voie se trouve dans [Aperçu de la QA → Couverture des transports en direct](/fr/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` est la suite synthétique large et ne fait pas partie de cette matrice.

### Identifiants Telegram partagés via Convex (v1)

Lorsque `--credential-source convex` (ou `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`) est activé pour
la QA de transport en direct, le labo QA acquiert un bail exclusif depuis un pool adossé à Convex, envoie des heartbeats pour ce
bail pendant l’exécution de la voie, puis libère le bail à l’arrêt. Le nom de la section est antérieur
à la prise en charge de Discord, Slack et WhatsApp ; le contrat de bail est partagé entre les types.

Échafaudage de référence du projet Convex :

- `qa/convex-credential-broker/`

Variables d’environnement requises :

- `OPENCLAW_QA_CONVEX_SITE_URL` (par exemple `https://your-deployment.convex.site`)
- Un secret pour le rôle sélectionné :
  - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` pour `maintainer`
  - `OPENCLAW_QA_CONVEX_SECRET_CI` pour `ci`
- Sélection du rôle d’identifiants :
  - CLI : `--credential-role maintainer|ci`
  - Valeur par défaut via l’environnement : `OPENCLAW_QA_CREDENTIAL_ROLE` (par défaut `ci` en CI, sinon `maintainer`)

Variables d’environnement facultatives :

- `OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS` (par défaut `1200000`)
- `OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS` (par défaut `30000`)
- `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS` (par défaut `90000`)
- `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS` (par défaut `15000`)
- `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX` (par défaut `/qa-credentials/v1`)
- `OPENCLAW_QA_CREDENTIAL_OWNER_ID` (identifiant de trace facultatif)
- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` autorise les URL Convex `http://` en local loopback pour le développement local uniquement.

`OPENCLAW_QA_CONVEX_SITE_URL` doit utiliser `https://` en fonctionnement normal.

Les commandes d’administration des mainteneurs (ajout/suppression/liste du pool) exigent spécifiquement
`OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`.

Aides CLI pour les mainteneurs :

```bash
pnpm openclaw qa credentials doctor
pnpm openclaw qa credentials add --kind telegram --payload-file qa/telegram-credential.json
pnpm openclaw qa credentials list --kind telegram
pnpm openclaw qa credentials remove --credential-id <credential-id>
```

Utilisez `doctor` avant les exécutions en direct pour vérifier l’URL du site Convex, les secrets du courtier,
le préfixe d’endpoint, le délai d’expiration HTTP et l’accessibilité admin/liste sans afficher
les valeurs secrètes. Utilisez `--json` pour une sortie exploitable par machine dans les scripts et les utilitaires
CI.

Contrat d’endpoint par défaut (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`) :

- `POST /acquire`
  - Requête : `{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }`
  - Succès : `{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? }`
  - Épuisé/retentable : `{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }`
- `POST /payload-chunk`
  - Requête : `{ kind, ownerId, actorRole, credentialId, leaseToken, index }`
  - Succès : `{ status: "ok", index, data }`
- `POST /heartbeat`
  - Requête : `{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs }`
  - Succès : `{ status: "ok" }` (ou `2xx` vide)
- `POST /release`
  - Requête : `{ kind, ownerId, actorRole, credentialId, leaseToken }`
  - Succès : `{ status: "ok" }` (ou `2xx` vide)
- `POST /admin/add` (secret mainteneur uniquement)
  - Requête : `{ kind, actorId, payload, note?, status? }`
  - Succès : `{ status: "ok", credential }`
- `POST /admin/remove` (secret mainteneur uniquement)
  - Requête : `{ credentialId, actorId }`
  - Succès : `{ status: "ok", changed, credential }`
  - Garde de bail actif : `{ status: "error", code: "LEASE_ACTIVE", ... }`
- `POST /admin/list` (secret mainteneur uniquement)
  - Requête : `{ kind?, status?, includePayload?, limit? }`
  - Succès : `{ status: "ok", credentials, count }`

Forme du payload pour le type Telegram :

- `{ groupId: string, driverToken: string, sutToken: string }`
- `groupId` doit être une chaîne d’identifiant numérique de chat Telegram.
- `admin/add` valide cette forme pour `kind: "telegram"` et rejette les payloads mal formés.

Forme du payload pour le type utilisateur réel Telegram :

- `{ groupId: string, sutToken: string, testerUserId: string, testerUsername: string, telegramApiId: string, telegramApiHash: string, tdlibDatabaseEncryptionKey: string, tdlibArchiveBase64: string, tdlibArchiveSha256: string, desktopTdataArchiveBase64: string, desktopTdataArchiveSha256: string }`
- `groupId`, `testerUserId` et `telegramApiId` doivent être des chaînes numériques.
- `tdlibArchiveSha256` et `desktopTdataArchiveSha256` doivent être des chaînes hexadécimales SHA-256.
- `kind: "telegram-user"` représente un compte jetable Telegram. Traitez le bail comme couvrant tout le compte : le pilote CLI TDLib et le témoin visuel Telegram Desktop sont restaurés à partir du même payload, et une seule tâche doit détenir le bail à la fois.

Restauration du bail utilisateur réel Telegram :

```bash
tmp=$(mktemp -d /tmp/openclaw-telegram-user.XXXXXX)
node --import tsx scripts/e2e/telegram-user-credential.ts lease-restore \
  --user-driver-dir "$tmp/user-driver" \
  --desktop-workdir "$tmp/desktop" \
  --lease-file "$tmp/lease.json"
TELEGRAM_USER_DRIVER_STATE_DIR="$tmp/user-driver" \
  uv run ~/.codex/skills/custom/telegram-e2e-bot-to-bot/scripts/user-driver.py status --json
node --import tsx scripts/e2e/telegram-user-credential.ts release --lease-file "$tmp/lease.json"
```

Utilisez le profil Desktop restauré avec `Telegram -workdir "$tmp/desktop"` lorsqu’un enregistrement visuel est nécessaire. Dans les environnements opérateur locaux, `scripts/e2e/telegram-user-credential.ts` lit `~/.codex/skills/custom/telegram-e2e-bot-to-bot/convex.local.env` par défaut si les variables d’environnement du processus sont absentes.

Session Crabbox pilotée par agent :

```bash
pnpm qa:telegram-user:crabbox -- start \
  --tdlib-url http://artifacts.openclaw.ai/tdlib-v1.8.0-linux-x64.tgz \
  --output-dir .artifacts/qa-e2e/telegram-user-crabbox/pr-review
pnpm qa:telegram-user:crabbox -- send \
  --session .artifacts/qa-e2e/telegram-user-crabbox/pr-review/session.json \
  --text /status
pnpm qa:telegram-user:crabbox -- finish \
  --session .artifacts/qa-e2e/telegram-user-crabbox/pr-review/session.json
```

`start` loue l’identifiant `telegram-user`, restaure le même compte dans
TDLib et Telegram Desktop sur un bureau Linux Crabbox, démarre un Gateway SUT
mock local depuis le checkout courant, ouvre le chat Telegram visible, lance
l’enregistrement du bureau et écrit un `session.json` privé. Tant que la session est
active, un agent peut continuer à tester jusqu’à être satisfait :

- `send --session <file> --text <message>` envoie via l’utilisateur réel TDLib et attend la réponse du SUT.
- `run --session <file> -- <remote command>` exécute une commande arbitraire sur la Crabbox et enregistre sa sortie, par exemple `bash -lc 'source /tmp/openclaw-telegram-user-crabbox/env.sh && python3 /tmp/openclaw-telegram-user-crabbox/user-driver.py transcript --limit 20 --json'`.
- `screenshot --session <file>` capture le bureau visible courant.
- `status --session <file>` affiche le bail et la commande WebVNC.
- `finish --session <file>` arrête l’enregistreur, capture les artefacts de capture d’écran/vidéo/motion-trim, libère l’identifiant Convex, arrête les processus SUT locaux et arrête le bail Crabbox sauf si `--keep-box` est passé.
- `publish --session <file> --pr <number>` publie par défaut un commentaire de PR contenant uniquement des GIFs. Passez `--full-artifacts` seulement lorsque des journaux ou des artefacts JSON sont intentionnellement nécessaires.

Pour des repros visuelles déterministes, passez `--mock-response-file <path>` à `start`
ou au raccourci en une commande `probe`. Le runner utilise par défaut une classe
Crabbox standard, un enregistrement à 24 fps, des aperçus GIF de mouvement à 24 fps et une largeur de GIF
de 1920 px. Remplacez avec `--class`, `--record-fps`, `--preview-fps` et
`--preview-width` seulement lorsque la preuve nécessite des paramètres de capture différents.

Preuve Crabbox en une commande :

```bash
pnpm qa:telegram-user:crabbox -- --text /status
```

La commande `probe` par défaut est un raccourci pour un cycle start/send/finish unique. Utilisez-la pour un smoke `/status` rapide. Utilisez les commandes de session pour la revue de PR,
le travail de reproduction de bogues, ou tout cas où l’agent a besoin de plusieurs minutes
d’expérimentation arbitraire avant de décider que la preuve est complète. Utilisez `--id <cbx_...>` pour
réutiliser un bail de bureau chaud, `--keep-box` pour garder VNC ouvert après finish,
`--desktop-chat-title <name>` pour choisir le chat visible, et `--tdlib-url <tgz>`
lorsque vous utilisez une archive Linux `libtdjson.so` précuite au lieu de compiler TDLib sur
une nouvelle machine. Le runner vérifie `--tdlib-url` avec `--tdlib-sha256 <hex>` ou,
par défaut, un fichier frère `<url>.sha256`.

Payloads multicanaux validés par le courtier :

- Discord : `{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string, voiceChannelId?: string }`
- WhatsApp : `{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string }`

Les voies Slack peuvent aussi louer depuis le pool, mais la validation des payloads Slack se trouve actuellement
dans le runner QA Slack plutôt que dans le courtier. Utilisez
`{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }`
pour les lignes Slack.

### Ajouter un canal à la QA

L’architecture et les noms d’aides de scénario pour les nouveaux adaptateurs de canal se trouvent dans [Aperçu de la QA → Ajouter un canal](/fr/concepts/qa-e2e-automation#adding-a-channel). Le minimum requis : implémenter le runner de transport sur le seam hôte partagé `qa-lab`, déclarer `qaRunners` dans le manifeste du plugin, le monter en tant que `openclaw qa <runner>` et écrire les scénarios sous `qa/scenarios/`.

## Suites de tests (ce qui s’exécute où)

Considérez les suites comme un « réalisme croissant » (et un coût/une instabilité croissants) :

### Unitaires / intégration (par défaut)

- Commande : `pnpm test`
- Configuration : les exécutions non ciblées utilisent l’ensemble d’éclats `vitest.full-*.config.ts` et peuvent étendre les éclats multiprojets en configurations par projet pour la planification parallèle
- Fichiers : inventaires core/unit sous `src/**/*.test.ts`, `packages/**/*.test.ts` et `test/**/*.test.ts` ; les tests unitaires d’UI s’exécutent dans l’éclat dédié `unit-ui`
- Portée :
  - Tests purement unitaires
  - Tests d’intégration in-process (authentification du Gateway, routage, outillage, parsing, configuration)
  - Régressions déterministes pour les bogues connus
- Attentes :
  - S’exécute en CI
  - Aucune vraie clé requise
  - Doit être rapide et stable
  - Les tests du résolveur et du chargeur de surface publique doivent prouver le comportement de fallback large de `api.js` et
    `runtime-api.js` avec de minuscules fixtures de plugin générées, et non
    de vraies API sources de plugins groupés. Les chargements d’API de plugins réels relèvent
    des suites de contrat/intégration détenues par les plugins.

Politique des dépendances natives :

- Les installations de test par défaut ignorent les builds natifs opus Discord facultatifs. La réception vocale Discord utilise le décodeur pur JS `opusscript`, et `@discordjs/opus` reste désactivé dans `allowBuilds` afin que les tests locaux et les voies Testbox ne compilent pas l’addon natif.
- Utilisez une voie Discord voix dédiée aux performances ou au direct si vous devez intentionnellement comparer un build opus natif. Ne définissez pas `@discordjs/opus` sur `true` dans le `allowBuilds` par défaut ; cela force des boucles d’installation/test sans rapport à compiler du code natif.

<AccordionGroup>
  <Accordion title="Projects, shards, and scoped lanes">

    - `pnpm test` sans cible exécute douze configurations de fragments plus petites (`core-unit-fast`, `core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) au lieu d’un unique énorme processus natif de projet racine. Cela réduit le RSS de pointe sur les machines chargées et évite que le travail auto-reply/extensions n’affame des suites sans rapport.
    - `pnpm test --watch` utilise toujours le graphe de projet racine natif `vitest.config.ts`, car une boucle de surveillance multi-fragments n’est pas pratique.
    - `pnpm test`, `pnpm test:watch` et `pnpm test:perf:imports` acheminent d’abord les cibles explicites de fichiers/répertoires par des voies à portée limitée, donc `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` évite de payer le coût complet de démarrage du projet racine.
    - `pnpm test:changed` étend par défaut les chemins git modifiés en voies à portée limitée peu coûteuses : modifications directes de tests, fichiers frères `*.test.ts`, mappages source explicites et dépendants du graphe d’import local. Les modifications de config/setup/package ne déclenchent pas d’exécution large des tests, sauf si vous utilisez explicitement `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`.
    - `pnpm check:changed` est la barrière normale de vérification locale intelligente pour les travaux étroits. Elle classe le diff en core, tests core, extensions, tests d’extension, apps, docs, métadonnées de release, outillage Docker live et outillage, puis exécute les commandes correspondantes de typecheck, lint et garde. Elle n’exécute pas les tests Vitest ; appelez `pnpm test:changed` ou un `pnpm test <target>` explicite pour la preuve de test. Les changements de version limités aux métadonnées de release exécutent des vérifications ciblées de version/config/dépendances racine, avec une garde qui rejette les changements de package en dehors du champ de version de premier niveau.
    - Les modifications du harnais Docker ACP live exécutent des vérifications ciblées : syntaxe shell pour les scripts d’auth Docker live et dry-run du planificateur Docker live. Les changements de `package.json` sont inclus uniquement lorsque le diff est limité à `scripts["test:docker:live-*"]` ; les modifications de dépendances, exports, version et autres surfaces de package utilisent toujours les gardes plus larges.
    - Les tests unitaires légers en imports provenant des agents, commandes, plugins, helpers auto-reply, `plugin-sdk` et zones utilitaires pures similaires passent par la voie `unit-fast`, qui ignore `test/setup-openclaw-runtime.ts` ; les fichiers avec état ou lourds côté runtime restent sur les voies existantes.
    - Certains fichiers source helpers `plugin-sdk` et `commands` sélectionnés associent aussi les exécutions en mode changé à des tests frères explicites dans ces voies légères, afin que les modifications de helpers évitent de relancer toute la suite lourde de ce répertoire.
    - `auto-reply` dispose de compartiments dédiés pour les helpers core de premier niveau, les tests d’intégration `reply.*` de premier niveau et le sous-arbre `src/auto-reply/reply/**`. La CI divise en outre le sous-arbre reply en fragments agent-runner, dispatch et commands/state-routing afin qu’un compartiment lourd en imports ne possède pas toute la traîne Node.
    - La CI normale PR/main ignore intentionnellement le balayage par lot des extensions et le fragment `agentic-plugins` réservé aux releases. La Validation de Release complète déclenche le workflow enfant séparé `Plugin Prerelease` pour ces suites lourdes en plugins/extensions sur les release candidates.

  </Accordion>

  <Accordion title="Embedded runner coverage">

    - Lorsque vous modifiez les entrées de découverte des outils de messages ou le contexte runtime de compaction, conservez les deux niveaux de couverture.
    - Ajoutez des régressions de helpers ciblées pour les frontières pures de routage et de normalisation.
    - Gardez les suites d’intégration du runner intégré en bon état :
      `src/agents/pi-embedded-runner/compact.hooks.test.ts`,
      `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts` et
      `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`.
    - Ces suites vérifient que les ids à portée limitée et le comportement de Compaction transitent toujours par les vrais chemins `run.ts` / `compact.ts` ; les tests limités aux helpers ne remplacent pas suffisamment ces chemins d’intégration.

  </Accordion>

  <Accordion title="Vitest pool and isolation defaults">

    - La configuration Vitest de base utilise `threads` par défaut.
    - La configuration Vitest partagée fixe `isolate: false` et utilise le runner non isolé dans les projets racine, e2e et configurations live.
    - La voie UI racine conserve sa configuration `jsdom` et son optimiseur, mais s’exécute elle aussi sur le runner partagé non isolé.
    - Chaque fragment `pnpm test` hérite des mêmes valeurs par défaut `threads` + `isolate: false` depuis la configuration Vitest partagée.
    - `scripts/run-vitest.mjs` ajoute par défaut `--no-maglev` aux processus Node enfants de Vitest afin de réduire le renouvellement de compilation V8 pendant les grosses exécutions locales. Définissez `OPENCLAW_VITEST_ENABLE_MAGLEV=1` pour comparer au comportement V8 standard.

  </Accordion>

  <Accordion title="Fast local iteration">

    - `pnpm changed:lanes` montre quelles voies architecturales un diff déclenche.
    - Le hook pre-commit ne fait que du formatage. Il restage les fichiers formatés et n’exécute pas lint, typecheck ni tests.
    - Exécutez explicitement `pnpm check:changed` avant le handoff ou le push lorsque vous avez besoin de la barrière de vérification locale intelligente.
    - `pnpm test:changed` passe par défaut par des voies à portée limitée peu coûteuses. Utilisez `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` uniquement lorsque l’agent décide qu’une modification de harnais, config, package ou contrat nécessite réellement une couverture Vitest plus large.
    - `pnpm test:max` et `pnpm test:changed:max` conservent le même comportement de routage, simplement avec un plafond de workers plus élevé.
    - L’auto-scaling local des workers est intentionnellement conservateur et réduit la charge lorsque la moyenne de charge de l’hôte est déjà élevée, de sorte que plusieurs exécutions Vitest concurrentes causent moins de dégâts par défaut.
    - La configuration Vitest de base marque les projets/fichiers de configuration comme `forceRerunTriggers` afin que les réexécutions en mode changé restent correctes lorsque le câblage des tests change.
    - La configuration garde `OPENCLAW_VITEST_FS_MODULE_CACHE` activé sur les hôtes pris en charge ; définissez `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path` si vous voulez un emplacement de cache explicite pour le profilage direct.

  </Accordion>

  <Accordion title="Perf debugging">

    - `pnpm test:perf:imports` active le rapport des durées d’import Vitest ainsi que la sortie de ventilation des imports.
    - `pnpm test:perf:imports:changed` limite la même vue de profilage aux fichiers modifiés depuis `origin/main`.
    - Les données de timing des fragments sont écrites dans `.artifacts/vitest-shard-timings.json`. Les exécutions de configuration complète utilisent le chemin de configuration comme clé ; les fragments CI à motif d’inclusion ajoutent le nom du fragment afin que les fragments filtrés puissent être suivis séparément.
    - Lorsqu’un test chaud passe encore la majeure partie de son temps dans les imports de démarrage, gardez les dépendances lourdes derrière une frontière locale étroite `*.runtime.ts` et mockez directement cette frontière au lieu de deep-importer des helpers runtime uniquement pour les faire passer par `vi.mock(...)`.
    - `pnpm test:perf:changed:bench -- --ref <git-ref>` compare le `test:changed` routé au chemin natif du projet racine pour ce diff committé et affiche le temps réel ainsi que le RSS maximal macOS.
    - `pnpm test:perf:changed:bench -- --worktree` benchmarke l’arbre de travail sale courant en routant la liste des fichiers modifiés via `scripts/test-projects.mjs` et la configuration Vitest racine.
    - `pnpm test:perf:profile:main` écrit un profil CPU du thread principal pour les surcoûts de démarrage et de transformation Vitest/Vite.
    - `pnpm test:perf:profile:runner` écrit des profils CPU+heap du runner pour la suite unitaire avec le parallélisme de fichiers désactivé.

  </Accordion>
</AccordionGroup>

### Stabilité (gateway)

- Commande : `pnpm test:stability:gateway`
- Config : `vitest.gateway.config.ts`, forcée à un worker
- Portée :
  - Démarre un vrai Gateway loopback avec les diagnostics activés par défaut
  - Fait passer une agitation synthétique de messages Gateway, de mémoire et de grandes charges utiles par le chemin d’événements de diagnostic
  - Interroge `diagnostics.stability` via le RPC WS du Gateway
  - Couvre les helpers de persistance du bundle de stabilité de diagnostic
  - Vérifie que l’enregistreur reste borné, que les échantillons RSS synthétiques restent sous le budget de pression et que les profondeurs de file par session reviennent à zéro
- Attentes :
  - Compatible CI et sans clé
  - Voie étroite pour le suivi des régressions de stabilité, pas un substitut à la suite Gateway complète

### E2E (smoke gateway)

- Commande : `pnpm test:e2e`
- Config : `vitest.e2e.config.ts`
- Fichiers : `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` et tests E2E de plugins groupés sous `extensions/`
- Valeurs runtime par défaut :
  - Utilise les `threads` Vitest avec `isolate: false`, comme le reste du dépôt.
  - Utilise des workers adaptatifs (CI : jusqu’à 2, local : 1 par défaut).
  - S’exécute en mode silencieux par défaut pour réduire le surcoût des E/S console.
- Surcharges utiles :
  - `OPENCLAW_E2E_WORKERS=<n>` pour forcer le nombre de workers (plafonné à 16).
  - `OPENCLAW_E2E_VERBOSE=1` pour réactiver la sortie console verbeuse.
- Portée :
  - Comportement Gateway end-to-end multi-instance
  - Surfaces WebSocket/HTTP, appairage de nœuds et réseau plus lourd
- Attentes :
  - S’exécute en CI (lorsque c’est activé dans le pipeline)
  - Aucune clé réelle requise
  - Plus de pièces mobiles que les tests unitaires (peut être plus lent)

### E2E : smoke du backend OpenShell

- Commande : `pnpm test:e2e:openshell`
- Fichier : `extensions/openshell/src/backend.e2e.test.ts`
- Portée :
  - Démarre un Gateway OpenShell isolé sur l’hôte via Docker
  - Crée une sandbox à partir d’un Dockerfile local temporaire
  - Exerce le backend OpenShell d’OpenClaw via de vrais `sandbox ssh-config` + exécution SSH
  - Vérifie le comportement de système de fichiers canonique distant via le pont fs de la sandbox
- Attentes :
  - Opt-in uniquement ; ne fait pas partie de l’exécution `pnpm test:e2e` par défaut
  - Nécessite une CLI `openshell` locale ainsi qu’un démon Docker fonctionnel
  - Utilise des `HOME` / `XDG_CONFIG_HOME` isolés, puis détruit le Gateway de test et la sandbox
- Surcharges utiles :
  - `OPENCLAW_E2E_OPENSHELL=1` pour activer le test lors de l’exécution manuelle de la suite e2e plus large
  - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` pour pointer vers un binaire CLI non par défaut ou un script wrapper

### Live (fournisseurs réels + modèles réels)

- Commande : `pnpm test:live`
- Configuration : `vitest.live.config.ts`
- Fichiers : `src/**/*.live.test.ts`, `test/**/*.live.test.ts`, et tests live des plugins intégrés sous `extensions/`
- Valeur par défaut : **activé** par `pnpm test:live` (définit `OPENCLAW_LIVE_TEST=1`)
- Périmètre :
  - « Ce fournisseur/modèle fonctionne-t-il réellement _aujourd’hui_ avec de vrais identifiants ? »
  - Détecter les changements de format des fournisseurs, les particularités d’appel d’outils, les problèmes d’authentification et le comportement des limites de débit
- Attentes :
  - Non stable en CI par conception (vrais réseaux, vraies politiques de fournisseurs, quotas, pannes)
  - Coûte de l’argent / utilise les limites de débit
  - Préférer l’exécution de sous-ensembles restreints plutôt que « tout »
- Les exécutions live chargent `~/.profile` pour récupérer les clés API manquantes.
- Par défaut, les exécutions live isolent toujours `HOME` et copient la configuration/le matériel d’authentification dans un répertoire personnel de test temporaire afin que les fixtures unitaires ne puissent pas modifier votre vrai `~/.openclaw`.
- Définissez `OPENCLAW_LIVE_USE_REAL_HOME=1` uniquement lorsque vous avez intentionnellement besoin que les tests live utilisent votre vrai répertoire personnel.
- `pnpm test:live` utilise désormais par défaut un mode plus silencieux : il conserve la sortie de progression `[live] ...`, mais supprime l’avis supplémentaire `~/.profile` et met en sourdine les journaux d’amorçage du Gateway/le bruit Bonjour. Définissez `OPENCLAW_LIVE_TEST_QUIET=0` si vous voulez retrouver les journaux de démarrage complets.
- Rotation des clés API (spécifique au fournisseur) : définissez `*_API_KEYS` au format virgule/point-virgule ou `*_API_KEY_1`, `*_API_KEY_2` (par exemple `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) ou une substitution par live via `OPENCLAW_LIVE_*_KEY` ; les tests réessaient sur les réponses de limite de débit.
- Sortie de progression/Heartbeat :
  - Les suites live émettent désormais des lignes de progression vers stderr afin que les longs appels fournisseur soient visiblement actifs même lorsque la capture de console Vitest est silencieuse.
  - `vitest.live.config.ts` désactive l’interception de console de Vitest afin que les lignes de progression du fournisseur/Gateway soient diffusées immédiatement pendant les exécutions live.
  - Ajustez les Heartbeat de modèle direct avec `OPENCLAW_LIVE_HEARTBEAT_MS`.
  - Ajustez les Heartbeat Gateway/sonde avec `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`.

## Quelle suite dois-je exécuter ?

Utilisez ce tableau de décision :

- Modification de logique/tests : exécutez `pnpm test` (et `pnpm test:coverage` si vous avez beaucoup changé)
- Modification du réseau Gateway / protocole WS / appairage : ajoutez `pnpm test:e2e`
- Débogage de « mon bot est en panne » / échecs spécifiques à un fournisseur / appel d’outils : exécutez un `pnpm test:live` restreint

## Tests live (qui touchent au réseau)

Pour la matrice des modèles live, les smokes du backend CLI, les smokes ACP, le
harnais de serveur d’app Codex et tous les tests live des fournisseurs média
(Deepgram, BytePlus, ComfyUI, image, musique, vidéo, harnais média) — ainsi que
la gestion des identifiants pour les exécutions live — consultez
[Tester les suites live](/fr/help/testing-live). Pour la liste de contrôle dédiée à
la mise à jour et à la validation des plugins, consultez
[Tester les mises à jour et les plugins](/fr/help/testing-updates-plugins).

## Exécuteurs Docker (vérifications facultatives « fonctionne sous Linux »)

Ces exécuteurs Docker se répartissent en deux catégories :

- Exécuteurs de modèles live : `test:docker:live-models` et `test:docker:live-gateway` exécutent uniquement leur fichier live correspondant de clés de profil dans l’image Docker du dépôt (`src/agents/models.profiles.live.test.ts` et `src/gateway/gateway-models.profiles.live.test.ts`), en montant votre répertoire de configuration local et l’espace de travail (et en chargeant `~/.profile` s’il est monté). Les points d’entrée locaux correspondants sont `test:live:models-profiles` et `test:live:gateway-profiles`.
- Les exécuteurs Docker live utilisent par défaut un plafond de smoke plus réduit afin qu’un balayage Docker complet reste praticable :
  `test:docker:live-models` utilise par défaut `OPENCLAW_LIVE_MAX_MODELS=12`, et
  `test:docker:live-gateway` utilise par défaut `OPENCLAW_LIVE_GATEWAY_SMOKE=1`,
  `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`,
  `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`, et
  `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`. Remplacez ces variables d’environnement lorsque vous
  voulez explicitement l’analyse exhaustive plus large.
- `test:docker:all` construit l’image Docker live une fois via `test:docker:live-build`, empaquette OpenClaw une fois sous forme de tarball npm via `scripts/package-openclaw-for-docker.mjs`, puis construit/réutilise deux images `scripts/e2e/Dockerfile`. L’image nue est seulement l’exécuteur Node/Git pour les voies d’installation/mise à jour/dépendance de Plugin ; ces voies montent le tarball préconstruit. L’image fonctionnelle installe le même tarball dans `/app` pour les voies de fonctionnalité de l’app construite. Les définitions de voies Docker se trouvent dans `scripts/lib/docker-e2e-scenarios.mjs` ; la logique du planificateur se trouve dans `scripts/lib/docker-e2e-plan.mjs` ; `scripts/test-docker-all.mjs` exécute le plan sélectionné. L’agrégat utilise un planificateur local pondéré : `OPENCLAW_DOCKER_ALL_PARALLELISM` contrôle les emplacements de processus, tandis que les plafonds de ressources empêchent les voies live lourdes, d’installation npm et multiservices de toutes démarrer en même temps. Si une seule voie est plus lourde que les plafonds actifs, le planificateur peut quand même la démarrer lorsque le pool est vide, puis la garde seule en cours d’exécution jusqu’à ce que la capacité soit de nouveau disponible. Les valeurs par défaut sont 10 emplacements, `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10`, et `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7` ; ajustez `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` ou `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT` uniquement lorsque l’hôte Docker dispose de plus de marge. L’exécuteur effectue par défaut un prévol Docker, supprime les conteneurs E2E OpenClaw obsolètes, affiche l’état toutes les 30 secondes, stocke les durées des voies réussies dans `.artifacts/docker-tests/lane-timings.json` et utilise ces durées pour démarrer les voies plus longues en premier lors des exécutions ultérieures. Utilisez `OPENCLAW_DOCKER_ALL_DRY_RUN=1` pour afficher le manifeste pondéré des voies sans construire ni exécuter Docker, ou `node scripts/test-docker-all.mjs --plan-json` pour afficher le plan CI des voies sélectionnées, des besoins en paquet/image et des identifiants.
- `Package Acceptance` est la barrière de paquet native GitHub pour « ce tarball installable fonctionne-t-il comme un produit ? » Elle résout un paquet candidat depuis `source=npm`, `source=ref`, `source=url` ou `source=artifact`, le téléverse sous le nom `package-under-test`, puis exécute les voies Docker E2E réutilisables contre ce tarball exact au lieu de réempaqueter la référence sélectionnée. Les profils sont ordonnés par largeur : `smoke`, `package`, `product` et `full`. Consultez [Tester les mises à jour et les plugins](/fr/help/testing-updates-plugins) pour le contrat de paquet/mise à jour/Plugin, la matrice des survivants de mise à niveau publiée, les valeurs par défaut de publication et le triage des échecs.
- Les vérifications de construction et de publication exécutent `scripts/check-cli-bootstrap-imports.mjs` après tsdown. La garde parcourt le graphe statique construit depuis `dist/entry.js` et `dist/cli/run-main.js` et échoue si le démarrage avant répartition importe des dépendances de paquet comme Commander, l’interface de prompt, undici ou la journalisation avant la répartition de commande ; elle maintient aussi le fragment d’exécution Gateway intégré sous le budget et rejette les imports statiques de chemins Gateway froids connus. Le smoke de CLI empaquetée couvre également l’aide racine, l’aide d’onboarding, l’aide de doctor, le statut, le schéma de configuration et une commande de liste de modèles.
- La compatibilité héritée de Package Acceptance est plafonnée à `2026.4.25` (`2026.4.25-beta.*` inclus). Jusqu’à cette limite, le harnais tolère uniquement les lacunes de métadonnées des paquets publiés : entrées d’inventaire QA privées omises, `gateway install --wrapper` manquant, fichiers de patch manquants dans la fixture git dérivée du tarball, `update.channel` persisté manquant, emplacements hérités des enregistrements d’installation de plugins, persistance manquante des enregistrements d’installation de marketplace, et migration des métadonnées de configuration pendant `plugins update`. Pour les paquets après `2026.4.25`, ces chemins sont des échecs stricts.
- Exécuteurs de smoke de conteneur : `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:skill-install`, `test:docker:update-channel-switch`, `test:docker:upgrade-survivor`, `test:docker:published-upgrade-survivor`, `test:docker:session-runtime-context`, `test:docker:agents-delete-shared-workspace`, `test:docker:gateway-network`, `test:docker:browser-cdp-snapshot`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update`, `test:docker:plugin-lifecycle-matrix` et `test:docker:config-reload` démarrent un ou plusieurs vrais conteneurs et vérifient des chemins d’intégration de plus haut niveau.

Les exécuteurs Docker de modèles live montent aussi uniquement les répertoires personnels d’authentification CLI nécessaires (ou tous ceux pris en charge lorsque l’exécution n’est pas restreinte), puis les copient dans le répertoire personnel du conteneur avant l’exécution afin que l’OAuth de CLI externe puisse actualiser les jetons sans modifier le magasin d’authentification de l’hôte :

- Modèles directs : `pnpm test:docker:live-models` (script : `scripts/test-live-models-docker.sh`)
- Smoke ACP bind : `pnpm test:docker:live-acp-bind` (script : `scripts/test-live-acp-bind-docker.sh` ; couvre Claude, Codex et Gemini par défaut, avec une couverture stricte de Droid/OpenCode via `pnpm test:docker:live-acp-bind:droid` et `pnpm test:docker:live-acp-bind:opencode`)
- Smoke du backend CLI : `pnpm test:docker:live-cli-backend` (script : `scripts/test-live-cli-backend-docker.sh`)
- Smoke du harness app-server Codex : `pnpm test:docker:live-codex-harness` (script : `scripts/test-live-codex-harness-docker.sh`)
- Gateway + agent de développement : `pnpm test:docker:live-gateway` (script : `scripts/test-live-gateway-models-docker.sh`)
- Smoke d’observabilité : `pnpm qa:otel:smoke` est une voie privée de vérification QA sur une extraction des sources. Elle ne fait volontairement pas partie des voies Docker de publication du package, car l’archive tar npm omet QA Lab.
- Smoke live Open WebUI : `pnpm test:docker:openwebui` (script : `scripts/e2e/openwebui-docker.sh`)
- Assistant d’onboarding (TTY, échafaudage complet) : `pnpm test:docker:onboard` (script : `scripts/e2e/onboard-docker.sh`)
- Smoke d’onboarding/canal/agent de l’archive tar npm : `pnpm test:docker:npm-onboard-channel-agent` installe globalement dans Docker l’archive tar OpenClaw empaquetée, configure OpenAI via un onboarding avec référence d’environnement ainsi que Telegram par défaut, exécute doctor, puis exécute un tour d’agent OpenAI simulé. Réutilisez une archive tar préconstruite avec `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, ignorez la reconstruction hôte avec `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0`, ou changez de canal avec `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` ou `OPENCLAW_NPM_ONBOARD_CHANNEL=slack`.
- Smoke d’installation de Skill : `pnpm test:docker:skill-install` installe globalement dans Docker l’archive tar OpenClaw empaquetée, désactive dans la configuration les installations d’archives téléversées, résout depuis la recherche le slug live actuel de Skill ClawHub, l’installe avec `openclaw skills install`, puis vérifie la Skill installée ainsi que les métadonnées d’origine/verrou `.clawhub`.
- Smoke de changement de canal de mise à jour : `pnpm test:docker:update-channel-switch` installe globalement dans Docker l’archive tar OpenClaw empaquetée, bascule du package `stable` vers git `dev`, vérifie le canal persistant et le fonctionnement du Plugin après mise à jour, puis rebascule vers le package `stable` et vérifie l’état de mise à jour.
- Smoke de survie à la mise à niveau : `pnpm test:docker:upgrade-survivor` installe l’archive tar OpenClaw empaquetée par-dessus un fixture d’ancien utilisateur sale avec agents, configuration de canal, listes d’autorisation de Plugins, état obsolète des dépendances de Plugin et fichiers d’espace de travail/session existants. Il exécute la mise à jour du package plus doctor en mode non interactif sans fournisseur live ni clés de canal, puis démarre une Gateway loopback et vérifie la préservation de la configuration/de l’état ainsi que les budgets de démarrage/état.
- Smoke publié de survie à la mise à niveau : `pnpm test:docker:published-upgrade-survivor` installe `openclaw@latest` par défaut, initialise des fichiers réalistes d’utilisateur existant, configure cette référence avec une recette de commande intégrée, valide la configuration obtenue, met à jour cette installation publiée vers l’archive tar candidate, exécute doctor en mode non interactif, écrit `.artifacts/upgrade-survivor/summary.json`, puis démarre une Gateway loopback et vérifie les intentions configurées, la préservation de l’état, le démarrage, `/healthz`, `/readyz` et les budgets d’état RPC. Remplacez une référence avec `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC`, demandez au planificateur agrégé d’étendre des références locales exactes avec `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS` comme `openclaw@2026.5.2 openclaw@2026.4.23 openclaw@2026.4.15`, et étendez les fixtures en forme d’issues avec `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` comme `reported-issues` ; l’ensemble reported-issues inclut `configured-plugin-installs` pour la réparation automatique de l’installation de Plugins OpenClaw externes. Package Acceptance les expose sous `published_upgrade_survivor_baseline`, `published_upgrade_survivor_baselines` et `published_upgrade_survivor_scenarios`, résout des jetons de référence méta comme `last-stable-4` ou `all-since-2026.4.23`, et Full Release Validation étend la porte de package release-soak à `last-stable-4 2026.4.23 2026.5.2 2026.4.15` plus `reported-issues`.
- Smoke du contexte d’exécution de session : `pnpm test:docker:session-runtime-context` vérifie la persistance du transcript de contexte d’exécution masqué ainsi que la réparation par doctor des branches affectées de réécriture de prompt dupliquées.
- Smoke d’installation globale Bun : `bash scripts/e2e/bun-global-install-smoke.sh` empaquette l’arborescence actuelle, l’installe avec `bun install -g` dans un répertoire personnel isolé, et vérifie que `openclaw infer image providers --json` renvoie les fournisseurs d’images groupés au lieu de rester bloqué. Réutilisez une archive tar préconstruite avec `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, ignorez la construction hôte avec `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0`, ou copiez `dist/` depuis une image Docker construite avec `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local`.
- Smoke Docker de l’installateur : `bash scripts/test-install-sh-docker.sh` partage un même cache npm entre ses conteneurs root, update et direct-npm. Le smoke de mise à jour utilise par défaut npm `latest` comme référence stable avant la mise à niveau vers l’archive tar candidate. Remplacez avec `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` localement, ou avec l’entrée `update_baseline_version` du workflow Install Smoke sur GitHub. Les vérifications d’installateur non-root conservent un cache npm isolé afin que les entrées de cache appartenant à root ne masquent pas le comportement d’installation local à l’utilisateur. Définissez `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` pour réutiliser le cache root/update/direct-npm lors des réexécutions locales.
- Install Smoke CI ignore la mise à jour globale direct-npm dupliquée avec `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` ; exécutez le script localement sans cette variable d’environnement lorsque la couverture directe de `npm install -g` est nécessaire.
- Smoke CLI de suppression d’espace de travail partagé par les agents : `pnpm test:docker:agents-delete-shared-workspace` (script : `scripts/e2e/agents-delete-shared-workspace-docker.sh`) construit par défaut l’image Dockerfile racine, initialise deux agents avec un espace de travail dans un home de conteneur isolé, exécute `agents delete --json`, puis vérifie un JSON valide ainsi que le comportement de conservation de l’espace de travail. Réutilisez l’image install-smoke avec `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1`.
- Réseau Gateway (deux conteneurs, authentification WS + santé) : `pnpm test:docker:gateway-network` (script : `scripts/e2e/gateway-network-docker.sh`)
- Smoke d’instantané CDP du navigateur : `pnpm test:docker:browser-cdp-snapshot` (script : `scripts/e2e/browser-cdp-snapshot-docker.sh`) construit l’image E2E source plus une couche Chromium, démarre Chromium avec CDP brut, exécute `browser doctor --deep`, puis vérifie que les instantanés de rôles CDP couvrent les URL de liens, les éléments cliquables promus par le curseur, les références iframe et les métadonnées de frame.
- Régression OpenAI Responses web_search avec raisonnement minimal : `pnpm test:docker:openai-web-search-minimal` (script : `scripts/e2e/openai-web-search-minimal-docker.sh`) exécute un serveur OpenAI simulé via Gateway, vérifie que `web_search` élève `reasoning.effort` de `minimal` à `low`, puis force le rejet du schéma fournisseur et vérifie que le détail brut apparaît dans les journaux Gateway.
- Pont de canal MCP (Gateway initialisée + pont stdio + smoke de trame de notification Claude brute) : `pnpm test:docker:mcp-channels` (script : `scripts/e2e/mcp-channels-docker.sh`)
- Outils MCP du bundle Pi (serveur MCP stdio réel + smoke allow/deny du profil Pi intégré) : `pnpm test:docker:pi-bundle-mcp-tools` (script : `scripts/e2e/pi-bundle-mcp-tools-docker.sh`)
- Nettoyage MCP Cron/sous-agent (Gateway réelle + arrêt de l’enfant MCP stdio après exécutions isolées de cron et de sous-agent ponctuel) : `pnpm test:docker:cron-mcp-cleanup` (script : `scripts/e2e/cron-mcp-cleanup-docker.sh`)
- Plugins (smoke d’installation/mise à jour pour chemin local, `file:`, registre npm avec dépendances hissées, refs git mouvantes, ClawHub kitchen-sink, mises à jour de marketplace et activation/inspection du bundle Claude) : `pnpm test:docker:plugins` (script : `scripts/e2e/plugins-docker.sh`)
  Définissez `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` pour ignorer le bloc ClawHub, ou remplacez la paire package/runtime kitchen-sink par défaut avec `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` et `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID`. Sans `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL`, le test utilise un serveur fixture ClawHub local hermétique.
- Smoke de mise à jour de Plugin inchangée : `pnpm test:docker:plugin-update` (script : `scripts/e2e/plugin-update-unchanged-docker.sh`)
- Smoke de matrice de cycle de vie de Plugin : `pnpm test:docker:plugin-lifecycle-matrix` installe l’archive tar OpenClaw empaquetée dans un conteneur nu, installe un Plugin npm, active/désactive, le met à niveau et le rétrograde via un registre npm local, supprime le code installé, puis vérifie que la désinstallation retire toujours l’état obsolète tout en journalisant les métriques RSS/CPU pour chaque phase du cycle de vie.
- Smoke des métadonnées de rechargement de configuration : `pnpm test:docker:config-reload` (script : `scripts/e2e/config-reload-source-docker.sh`)
- Plugins : `pnpm test:docker:plugins` couvre le smoke d’installation/mise à jour pour chemin local, `file:`, registre npm avec dépendances hissées, refs git mouvantes, fixtures ClawHub, mises à jour de marketplace et activation/inspection du bundle Claude. `pnpm test:docker:plugin-update` couvre le comportement de mise à jour inchangée pour les Plugins installés. `pnpm test:docker:plugin-lifecycle-matrix` couvre l’installation, l’activation, la désactivation, la mise à niveau, la rétrogradation et la désinstallation avec code manquant d’un Plugin npm avec suivi des ressources.

Pour préconstruire et réutiliser manuellement l’image fonctionnelle partagée :

```bash
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-build
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels
```

Les remplacements d’image propres à une suite, comme `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`, restent prioritaires lorsqu’ils sont définis. Lorsque `OPENCLAW_SKIP_DOCKER_BUILD=1` pointe vers une image partagée distante, les scripts la récupèrent si elle n’est pas déjà locale. Les tests Docker QR et installateur conservent leurs propres Dockerfiles, car ils valident le comportement de package/d’installation plutôt que l’exécution de l’application construite partagée.

Les runners Docker à modèle live montent également le checkout actuel en lecture seule et
le préparent dans un répertoire de travail temporaire à l’intérieur du conteneur. Cela garde l’image
runtime légère tout en exécutant Vitest sur votre source/configuration locale exacte.
L’étape de préparation ignore les gros caches locaux uniquement et les sorties de build d’app telles que
`.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, ainsi que les répertoires de sortie `.build` locaux à l’app ou
Gradle, afin que les exécutions live Docker ne passent pas des minutes à copier des artefacts
spécifiques à la machine.
Ils définissent aussi `OPENCLAW_SKIP_CHANNELS=1` afin que les sondes live du Gateway ne démarrent pas
de vrais workers de canaux Telegram/Discord/etc. dans le conteneur.
`test:docker:live-models` exécute toujours `pnpm test:live`, donc transmettez aussi
`OPENCLAW_LIVE_GATEWAY_*` quand vous devez restreindre ou exclure la couverture live du Gateway
de cette lane Docker.
`test:docker:openwebui` est un smoke de compatibilité de plus haut niveau : il démarre un
conteneur Gateway OpenClaw avec les endpoints HTTP compatibles OpenAI activés,
démarre un conteneur Open WebUI épinglé contre ce Gateway, se connecte via
Open WebUI, vérifie que `/api/models` expose `openclaw/default`, puis envoie une
vraie requête de chat via le proxy `/api/chat/completions` d’Open WebUI.
Définissez `OPENWEBUI_SMOKE_MODE=models` pour les contrôles CI du chemin de release qui doivent s’arrêter
après la connexion à Open WebUI et la découverte des modèles, sans attendre une complétion
de modèle live.
La première exécution peut être sensiblement plus lente, car Docker peut devoir tirer l’image
Open WebUI et Open WebUI peut devoir terminer sa propre configuration de démarrage à froid.
Cette lane attend une clé de modèle live utilisable, et `OPENCLAW_PROFILE_FILE`
(`~/.profile` par défaut) est le moyen principal de la fournir dans les exécutions Dockerisées.
Les exécutions réussies affichent une petite charge utile JSON comme `{ "ok": true, "model":
"openclaw/default", ... }`.
`test:docker:mcp-channels` est volontairement déterministe et ne nécessite pas de
vrai compte Telegram, Discord ou iMessage. Il démarre un conteneur Gateway prérempli,
démarre un second conteneur qui lance `openclaw mcp serve`, puis vérifie la
découverte de conversations routées, la lecture de transcriptions, les métadonnées de pièces jointes,
le comportement de la file d’événements live, le routage des envois sortants et les notifications de canal +
permission de style Claude via le vrai pont MCP stdio. La vérification des notifications
inspecte directement les trames MCP stdio brutes afin que le smoke valide ce que le
pont émet réellement, pas seulement ce qu’un SDK client spécifique expose par hasard.
`test:docker:pi-bundle-mcp-tools` est déterministe et ne nécessite pas de clé de modèle live.
Il construit l’image Docker du dépôt, démarre un vrai serveur de sonde MCP stdio
dans le conteneur, matérialise ce serveur via le runtime MCP du bundle Pi embarqué,
exécute l’outil, puis vérifie que `coding` et `messaging` conservent les outils
`bundle-mcp` tandis que `minimal` et `tools.deny: ["bundle-mcp"]` les filtrent.
`test:docker:cron-mcp-cleanup` est déterministe et ne nécessite pas de clé de modèle live.
Il démarre un Gateway prérempli avec un vrai serveur de sonde MCP stdio, exécute un
tour Cron isolé et un tour enfant ponctuel `/subagents spawn`, puis vérifie
que le processus enfant MCP se termine après chaque exécution.

Smoke manuel de thread ACP en langage naturel (pas CI) :

- `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...`
- Conservez ce script pour les workflows de régression/débogage. Il pourra être de nouveau nécessaire pour la validation du routage de thread ACP, donc ne le supprimez pas.

Variables d’environnement utiles :

- `OPENCLAW_CONFIG_DIR=...` (par défaut : `~/.openclaw`) monté sur `/home/node/.openclaw`
- `OPENCLAW_WORKSPACE_DIR=...` (par défaut : `~/.openclaw/workspace`) monté sur `/home/node/.openclaw/workspace`
- `OPENCLAW_PROFILE_FILE=...` (par défaut : `~/.profile`) monté sur `/home/node/.profile` et sourcé avant l’exécution des tests
- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` pour vérifier uniquement les variables d’environnement sourcées depuis `OPENCLAW_PROFILE_FILE`, avec des répertoires temporaires de configuration/workspace et sans montages d’authentification CLI externes
- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (par défaut : `~/.cache/openclaw/docker-cli-tools`) monté sur `/home/node/.npm-global` pour les installations CLI mises en cache dans Docker
- Les répertoires/fichiers d’authentification CLI externes sous `$HOME` sont montés en lecture seule sous `/host-auth...`, puis copiés dans `/home/node/...` avant le démarrage des tests
  - Répertoires par défaut : `.minimax`
  - Fichiers par défaut : `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json`
  - Les exécutions restreintes à des fournisseurs montent uniquement les répertoires/fichiers nécessaires déduits de `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS`
  - Remplacez manuellement avec `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none` ou une liste séparée par des virgules comme `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex`
- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` pour restreindre l’exécution
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` pour filtrer les fournisseurs dans le conteneur
- `OPENCLAW_SKIP_DOCKER_BUILD=1` pour réutiliser une image `openclaw:local-live` existante lors des réexécutions qui ne nécessitent pas de reconstruction
- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` pour s’assurer que les identifiants proviennent du magasin de profils (pas de l’environnement)
- `OPENCLAW_OPENWEBUI_MODEL=...` pour choisir le modèle exposé par le Gateway pour le smoke Open WebUI
- `OPENCLAW_OPENWEBUI_PROMPT=...` pour remplacer le prompt de vérification par nonce utilisé par le smoke Open WebUI
- `OPENWEBUI_IMAGE=...` pour remplacer le tag d’image Open WebUI épinglé

## Vérification de cohérence des docs

Exécutez les contrôles de docs après les modifications de documentation : `pnpm check:docs`.
Exécutez la validation complète des ancres Mintlify quand vous avez aussi besoin de contrôles des titres dans la page : `pnpm docs:check-links:anchors`.

## Régression hors ligne (compatible CI)

Il s’agit de régressions de « vrai pipeline » sans vrais fournisseurs :

- Appel d’outils du Gateway (OpenAI simulé, vrai Gateway + boucle d’agent) : `src/gateway/gateway.test.ts` (cas : "runs a mock OpenAI tool call end-to-end via gateway agent loop")
- Assistant de configuration du Gateway (WS `wizard.start`/`wizard.next`, écrit la configuration + auth appliquée) : `src/gateway/gateway.test.ts` (cas : "runs wizard over ws and writes auth token config")

## Évaluations de fiabilité de l’agent (skills)

Nous avons déjà quelques tests compatibles CI qui se comportent comme des « évaluations de fiabilité d’agent » :

- Appel d’outils simulé via le vrai Gateway + boucle d’agent (`src/gateway/gateway.test.ts`).
- Flux d’assistant de configuration de bout en bout qui valident le câblage de session et les effets de configuration (`src/gateway/gateway.test.ts`).

Ce qui manque encore pour les Skills (voir [Skills](/fr/tools/skills)) :

- **Prise de décision :** quand les skills sont listées dans le prompt, l’agent choisit-il la bonne skill (ou évite-t-il celles qui ne sont pas pertinentes) ?
- **Conformité :** l’agent lit-il `SKILL.md` avant utilisation et suit-il les étapes/arguments requis ?
- **Contrats de workflow :** scénarios multi-tours qui vérifient l’ordre des outils, la conservation de l’historique de session et les limites du bac à sable.

Les futures évaluations doivent rester déterministes en priorité :

- Un runner de scénarios utilisant des fournisseurs simulés pour vérifier les appels d’outils + leur ordre, les lectures de fichiers de skill et le câblage de session.
- Une petite suite de scénarios centrés sur les skills (utiliser ou éviter, garde-fous, injection de prompt).
- Des évaluations live optionnelles (opt-in, conditionnées par l’environnement) uniquement après la mise en place de la suite compatible CI.

## Tests de contrat (forme des plugins et des canaux)

Les tests de contrat vérifient que chaque plugin et canal enregistré respecte son
contrat d’interface. Ils itèrent sur tous les plugins découverts et exécutent une suite de
vérifications de forme et de comportement. La lane unitaire `pnpm test` par défaut
ignore volontairement ces fichiers partagés de seam et de smoke ; exécutez explicitement
les commandes de contrat quand vous touchez des surfaces partagées de canal ou de fournisseur.

### Commandes

- Tous les contrats : `pnpm test:contracts`
- Contrats de canaux uniquement : `pnpm test:contracts:channels`
- Contrats de fournisseurs uniquement : `pnpm test:contracts:plugins`

### Contrats de canaux

Situés dans `src/channels/plugins/contracts/*.contract.test.ts` :

- **plugin** - Forme de base du plugin (id, nom, capacités)
- **setup** - Contrat de l’assistant de configuration
- **session-binding** - Comportement de liaison de session
- **outbound-payload** - Structure de la charge utile des messages
- **inbound** - Gestion des messages entrants
- **actions** - Gestionnaires d’actions de canal
- **threading** - Gestion des ID de thread
- **directory** - API d’annuaire/roster
- **group-policy** - Application de la politique de groupe

### Contrats d’état des fournisseurs

Situés dans `src/plugins/contracts/*.contract.test.ts`.

- **status** - Sondes d’état de canal
- **registry** - Forme du registre de plugins

### Contrats de fournisseurs

Situés dans `src/plugins/contracts/*.contract.test.ts` :

- **auth** - Contrat du flux d’authentification
- **auth-choice** - Choix/sélection d’authentification
- **catalog** - API de catalogue de modèles
- **discovery** - Découverte de plugins
- **loader** - Chargement de plugins
- **runtime** - Runtime de fournisseur
- **shape** - Forme/interface de plugin
- **wizard** - Assistant de configuration

### Quand exécuter

- Après avoir modifié les exports ou sous-chemins de plugin-sdk
- Après avoir ajouté ou modifié un plugin de canal ou de fournisseur
- Après avoir refactorisé l’enregistrement ou la découverte de plugins

Les tests de contrat s’exécutent en CI et ne nécessitent pas de vraies clés d’API.

## Ajouter des régressions (conseils)

Quand vous corrigez un problème de fournisseur/modèle découvert en live :

- Ajoutez une régression compatible CI si possible (fournisseur simulé/stub, ou capture de la transformation exacte de la forme de requête)
- Si c’est intrinsèquement live-only (limites de débit, politiques d’authentification), gardez le test live restreint et opt-in via des variables d’environnement
- Préférez cibler la plus petite couche qui détecte le bug :
  - bug de conversion/rejeu de requête fournisseur → test direct des modèles
  - bug de pipeline session/historique/outils du Gateway → smoke live Gateway ou test Gateway simulé compatible CI
- Garde-fou de traversée SecretRef :
  - `src/secrets/exec-secret-ref-id-parity.test.ts` dérive une cible échantillonnée par classe SecretRef à partir des métadonnées du registre (`listSecretTargetRegistryEntries()`), puis vérifie que les ids exec à segment de traversée sont rejetés.
  - Si vous ajoutez une nouvelle famille de cibles SecretRef `includeInPlan` dans `src/secrets/target-registry-data.ts`, mettez à jour `classifyTargetClass` dans ce test. Le test échoue volontairement sur les ids de cible non classifiés afin que les nouvelles classes ne puissent pas être ignorées silencieusement.

## Connexe

- [Tests live](/fr/help/testing-live)
- [Tests des mises à jour et plugins](/fr/help/testing-updates-plugins)
- [CI](/fr/ci)
