[{"data":1,"prerenderedAt":46},["ShallowReactive",2],{"doc:fr:testing":3},{"title":4,"lede":5,"html":6,"headings":7},"Tester et valider un ticket","Quand un agent a fini, son ticket attend dans « À tester ». « ▶ Tester » lance sa fonctionnalité sur des ports à part, après t’avoir montré ce qui va tourner. « Valider » livre le travail, « Renvoyer » le rend à l’agent avec tes remarques.","\u003Cp>\u003Cimg src=\"\u002Fimages\u002Ftest.jpg\" alt=\"Le test d’un ticket : la fenêtre « Tester DEM-6 » montre la préparation terminée et les deux processus prêts\" width=\"1920\" height=\"960\" loading=\"lazy\" decoding=\"async\">\u003C\u002Fp>\n\u003Ch2 id=\"quand-un-ticket-arrive-dans-a-tester\">Quand un ticket arrive dans « À tester »\u003C\u002Fh2>\n\u003Cp>Un ticket passe dans « À tester » quand tous ses critères sont atteints, ou quand l’agent a épuisé ses boucles (la carte porte alors « Objectif partiel »). Tu es prévenu (« prêt à tester »), et le badge de « Kanban » compte un ticket de plus.\u003C\u002Fp>\n\u003Cp>La carte montre « Ce qui a été fait », les critères avec la note de l’agent au survol, le coût du ticket et « 3\u002F3 critères ». Dessous : « ▶ Tester » quand l’agent a de quoi lancer son travail, le bouton de validation, et « Renvoyer ».\u003C\u002Fp>\n\u003Cp>Pour regarder le travail avant de décider, ouvre l’agent (un clic sur la carte) : sa conversation, ses fichiers modifiés et leurs diffs se lisent comme ceux de n’importe quel agent (voir \u003Ca href=\"\u002Fdocs\u002Fgit\u002F\">Git\u003C\u002Fa> et \u003Ca href=\"\u002Fdocs\u002Feditor\u002F\">L’éditeur\u003C\u002Fa>).\u003C\u002Fp>\n\u003Cp>« Valider » et « Renvoyer » sont refusés tant que l’agent travaille encore : attends la fin de son tour.\u003C\u002Fp>\n\u003Ch2 id=\"tester-avec-tester\">Tester avec « ▶ Tester »\u003C\u002Fh2>\n\u003Ch3 id=\"ou-est-le-bouton\">Où est le bouton\u003C\u002Fh3>\n\u003Cp>Le bouton « ▶ Tester » est sur la carte « À tester », dans l’en-tête de la conversation de l’agent et dans la partie « Lancement de test » du bilan des critères. Il apparaît quand l’agent a donné sa recette de lancement (voir plus bas), ou quand \u003Ca href=\"#avec-isola\">isola\u003C\u002Fa> lance les services du worktree. Il n’y est pas pour un agent archivé, un agent sans worktree, ni pendant que le ticket est en cours de validation : l’app refuse alors tout lancement de test (« Validation en cours : le lancement de test attendra sa fin. »).\u003C\u002Fp>\n\u003Cp>Le protocole de l’agent lui demande de donner sa recette au plus tard quand tous les critères sont atteints. Si elle manque, l’en-tête de sa conversation propose « Préparer le lancement » : l’agent est invité à dire comment lancer son worktree, sur ses ports.\u003C\u002Fp>\n\u003Ch3 id=\"la-recette-ecrite-par-l-agent\">La recette écrite par l’agent\u003C\u002Fh3>\n\u003Cp>Une recette dit comment lancer le travail de l’agent dans son worktree :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>des étapes de « Préparation » : des commandes lancées l’une après l’autre, chacune dans un dossier du worktree (\u003Ccode>npm install\u003C\u002Fcode>) ;\u003C\u002Fli>\n\u003Cli>des processus : un nom, une commande, un dossier, des variables d’environnement et l’adresse qui répond quand le processus est prêt (un serveur de développement) ;\u003C\u002Fli>\n\u003Cli>l’adresse à ouvrir dans le navigateur, celle qui montre directement la fonctionnalité (la page, l’écran, l’état à tester).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>C’est l’agent qui l’écrit, et elle tourne dans ton shell, hors du mode de permission de Claude Code. Escouade te la montre donc avant de la lancer. À la première fois, et chaque fois que la recette change (une commande, une variable, un dossier ou l’adresse), la fenêtre « Tester DEM-6 » affiche :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>« Ces commandes ont été écrites par dem-6-limiter-les-tentatives. Elles tournent dans ton shell, hors du mode de permission de Claude Code. » ;\u003C\u002Fli>\n\u003Cli>« Préparation » : chaque commande et son « Dossier » (« la racine du worktree » quand il est vide) ;\u003C\u002Fli>\n\u003Cli>« Lancement » : chaque processus, sa commande, son « Dossier », ses « Variable » et son « Adresse » ;\u003C\u002Fli>\n\u003Cli>« Ouverture » : l’adresse qui s’ouvrira dans le navigateur.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Rien ne tourne avant que tu cliques sur « Lancer » ; « Annuler » ferme la fenêtre. Les caractères qui cacheraient une partie d’une commande (retour chariot, espace de largeur nulle, marque de direction…) sont écrits en toutes lettres (\u003Ccode class=\"key\">⟨U+200B⟩\u003C\u002Fcode>), et les longues suites d’espaces ou de lignes vides sont comptées (« ⟨24 espaces⟩ »).\u003C\u002Fp>\n\u003Cp>Si l’agent envoie une autre recette pendant que tu lis, la fenêtre le dit (« La recette vient de changer : relis-la avant de lancer. ») et « Lancer » reste fermé une seconde, pour qu’un clic visé sur l’ancienne ne valide pas la nouvelle. L’approbation est gardée avec l’agent : une recette que tu as approuvée et qui n’a pas changé se lance directement la fois suivante. Et Escouade refuse de lancer une étape d’une recette que tu n’as pas approuvée.\u003C\u002Fp>\n\u003Ch3 id=\"les-ports-reserves\">Les ports réservés\u003C\u002Fh3>\n\u003Cp>Chaque agent de ticket reçoit un bloc de 10 ports à lui, à partir de 4100 : 4100 à 4109, puis 4110 à 4119… Le bloc est le premier qu’aucun agent n’occupe et dont tous les ports sont libres sur ta machine. Ainsi, les serveurs de plusieurs tickets tournent côte à côte sans se gêner, ni gêner ton propre serveur de développement.\u003C\u002Fp>\n\u003Cp>L’agent connaît son bloc. Il doit s’en servir sans l’écrire dans des fichiers versionnés (en arguments ou en variables d’environnement). Les commandes d’un test, celles des tests de validation et celles de préparation du worktree reçoivent \u003Ccode class=\"key\">ESCOUADE_PORT_BASE\u003C\u002Fcode> (le premier port) et \u003Ccode class=\"key\">ESCOUADE_PORT_END\u003C\u002Fcode> (le dernier).\u003C\u002Fp>\n\u003Ch3 id=\"pendant-le-test\">Pendant le test\u003C\u002Fh3>\n\u003Cp>La fenêtre liste les étapes, chacune avec son état (✓ prêt, … en cours, ✕ en échec, ■ arrêté, – non attendu) :\u003C\u002Fp>\n\u003Col>\n\u003Cli>Les étapes de préparation tournent l’une après l’autre. Elles ne tournent qu’une fois par recette : tant qu’elle ne change pas et qu’Escouade reste ouverte, un nouveau test les saute. Une étape en échec arrête le test (« Préparation en échec (code 1) »).\u003C\u002Fli>\n\u003Cli>Chaque processus démarre dans son propre terminal, en lecture seule. Ils apparaissent dans la section « Lancement » de la barre latérale, avec leurs logs (voir \u003Ca href=\"\u002Fdocs\u002Flaunch\u002F\">Les commandes de lancement\u003C\u002Fa>).\u003C\u002Fli>\n\u003Cli>Pour chaque processus qui a une adresse, Escouade attend qu’elle réponde (n’importe quelle réponse HTTP compte, même une 404), pendant 3 minutes au plus : « en attente de localhost:4101… », puis « prêt · 2,4 s » ou « Pas de réponse de \u003Ca href=\"http:\u002F\u002Flocalhost:4101\" rel=\"noopener\">http:\u002F\u002Flocalhost:4101\u003C\u002Fa> après 3 min ».\u003C\u002Fli>\n\u003Cli>Le navigateur s’ouvre sur l’adresse à ouvrir, à défaut sur celle du premier processus (« Ouvert dans le navigateur : … »).\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Quand le test est prêt, la fenêtre propose « Rouvrir » (le navigateur), « Voir les logs », « Tout arrêter » et « Fermer ». Une ligne en échec a son « Voir le log ». Un processus qui s’arrête pendant que le test est prêt met fin au test (« web s’est arrêté »).\u003C\u002Fp>\n\u003Cp>Tant que les serveurs tournent, la carte du ticket affiche « ■ Arrêter », qui les arrête, et « Ouvrir », qui rouvre l’adresse. Les serveurs s’arrêtent aussi d’eux-mêmes quand le ticket est validé, quand son agent est archivé ou supprimé et quand le projet est fermé.\u003C\u002Fp>\n\u003Ch3 id=\"avec-isola\">Avec isola\u003C\u002Fh3>\n\u003Cp>Quand \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcyucelen\u002Fisola\" rel=\"noopener\">isola\u003C\u002Fa> est installé et que le worktree a un \u003Ccode class=\"key\">.isola.toml\u003C\u002Fcode>, isola lance les services du worktree sur ses propres ports et adresses. L’agent ne reçoit alors pas de bloc de ports, et il n’a pas de recette à écrire : il donne seulement l’adresse qui montre la fonctionnalité.\u003C\u002Fp>\n\u003Cp>« ▶ Tester » montre alors le \u003Ccode class=\"key\">.isola.toml\u003C\u002Fcode> sous « Configuration isola (.isola.toml) » (isola lance les commandes de ce fichier dans ton shell, hors du mode de permission de Claude Code, et l’agent peut l’avoir écrit ou modifié) et l’adresse qui s’ouvrira. Comme pour une recette, rien ne tourne avant « Lancer » et un fichier modifié est montré de nouveau. Le test lance \u003Ccode>isola up\u003C\u002Fcode>, attend que chaque service réponde, puis ouvre l’adresse. « Tout arrêter » lance \u003Ccode>isola down\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"valider-un-ticket\">Valider un ticket\u003C\u002Fh2>\n\u003Cp>Le bouton de la carte porte le nom de ce que la validation fait. Cela se règle dans le premier groupe de Réglages › Kanban, « Quand je valide un ticket « À tester » » ; le bouton « Après validation : … » de l’en-tête y mène (voir \u003Ca href=\"\u002Fdocs\u002Fsettings-board\u002F\">Réglages du Kanban\u003C\u002Fa>).\u003C\u002Fp>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Choix du réglage\u003C\u002Fth>\n\u003Cth>Bouton\u003C\u002Fth>\n\u003Cth>Ce qui se passe\u003C\u002Fth>\n\u003Cth>La carte « Terminé » dit\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>« Merger dans une branche »\u003C\u002Ftd>\n\u003Ctd>« Valider et merger »\u003C\u002Ftd>\n\u003Ctd>Ce qui reste dans le worktree est commité, puis mergé dans la branche cible avec la stratégie choisie : « Merge commit », « Squash » ou « Rebase ».\u003C\u002Ftd>\n\u003Ctd>« ⤵ Mergé dans main · squash »\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>« Ouvrir une pull request »\u003C\u002Ftd>\n\u003Ctd>« Valider + PR »\u003C\u002Ftd>\n\u003Ctd>Commit, push de la branche du ticket (\u003Ccode class=\"key\">ticket\u002F&lt;clé&gt;\u003C\u002Fcode>), puis une pull request vers la branche cible, en brouillon si « PR en brouillon » est activé.\u003C\u002Ftd>\n\u003Ctd>« ⇡ PR #41 → main »\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>« Pousser la branche du ticket »\u003C\u002Ftd>\n\u003Ctd>« Valider et pousser »\u003C\u002Ftd>\n\u003Ctd>Commit et push de la branche du ticket, sans merge ni PR.\u003C\u002Ftd>\n\u003Ctd>« ⇡ Poussé sur ticket\u002Fdem-3 »\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>« Laisser en l’état »\u003C\u002Ftd>\n\u003Ctd>« Valider »\u003C\u002Ftd>\n\u003Ctd>Rien n’est commité : les modifications restent dans le worktree, et l’agent aussi.\u003C\u002Ftd>\n\u003Ctd>« ◇ Laissé dans le worktree »\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>Un ticket « À tester » se valide même s’il est en « Objectif partiel ».\u003C\u002Fp>\n\u003Cp>Une fois le ticket validé (sauf avec « Laisser en l’état »), son agent est archivé. Si « Supprimer le worktree une fois validé » est activé (par défaut), le worktree est supprimé après les commandes de démontage du projet. La branche du ticket part avec lui après un merge, ou quand le ticket n’apportait aucun changement ; elle reste quand elle a été poussée ou proposée en PR. Une branche existante que le ticket avait reprise n’est jamais supprimée. Le ticket passe dans « Terminé », avec son issue, son coût et son nombre de boucles. Un ticket importé met son statut à jour et peut laisser un commentaire (voir \u003Ca href=\"\u002Fdocs\u002Fintegrations\u002F\">Jira, Trello, GitHub et Linear\u003C\u002Fa>).\u003C\u002Fp>\n\u003Cp>Si la branche du ticket n’apporte aucun changement, le ticket est terminé quand même : « ∅ Aucune modification ».\u003C\u002Fp>\n\u003Ch3 id=\"les-etapes-d-une-validation\">Les étapes d’une validation\u003C\u002Fh3>\n\u003Cp>La carte affiche l’étape en cours : « Validation… », puis, selon les réglages, « Tests… », « Commit… » et « Merge… » ou « Push… ».\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Tests.\u003C\u002Fstrong> Avec « Relancer les tests avant » activé et une « Commande de tests » renseignée, la commande tourne dans le worktree du ticket, avec les variables de ports, pendant 20 minutes au plus. Les serveurs d’un test éventuel sont arrêtés avant. Si un test échoue, la validation s’arrête : le ticket retourne « En cours » chez son agent, qui reçoit la fin de la sortie des tests (« Les tests (\u003Ccode>npm test\u003C\u002Fcode>) échouent : … ») et recommence à la boucle 1. Il revient dans « À tester » quand il a fini.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Commit.\u003C\u002Fstrong> Tout ce qui reste dans le worktree est commité, sauf les fichiers copiés du projet (\u003Ccode class=\"key\">.env\u003C\u002Fcode>…), qui ne le sont jamais : si la branche en porte un, la validation s’arrête et le dit. Le message est écrit par Haiku au format Conventional Commits, avec la clé en fin de ligne (\u003Ccode>feat: limiter les tentatives de connexion [DEM-6]\u003C\u002Fcode>), dans la « Langue des textes rédigés par Claude ». S’il ne donne rien d’utilisable, le message est \u003Ccode>feat: &lt;titre&gt; [&lt;clé&gt;]\u003C\u002Fcode>. Avec « Message de commit généré » éteint, c’est \u003Ccode>DEM-6 Limiter les tentatives de connexion\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Merge ou push.\u003C\u002Fstrong> Le merge se fait dans le dossier du projet quand la branche cible y est extraite (il est refusé si des fichiers suivis y ont des modifications non commitées), dans un worktree temporaire sinon, et il est refusé quand la branche cible est extraite dans le worktree d’un agent. Deux validations dans le même dépôt se font l’une après l’autre. Pour une pull request, Escouade utilise la CLI \u003Ccode class=\"key\">gh\u003C\u002Fcode> de GitHub : le titre est le message de commit, la description reprend celle du ticket, « Ce qui a été fait » et les critères en liste à cocher. Sans \u003Ccode class=\"key\">gh\u003C\u002Fcode>, ou s’il échoue, la page GitHub de comparaison s’ouvre dans le navigateur, déjà remplie, et la carte dit « ⇡ ticket\u002Fdem-6 poussée · PR à finaliser ». Avec un autre hébergeur que GitHub, la branche est poussée et la carte dit « ⇡ ticket\u002Fdem-6 poussée · PR à ouvrir sur ton hébergeur ».\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Quand le merge supprime le worktree et que des fichiers de l’agent sont ouverts dans l’éditeur avec des modifications non enregistrées, Escouade demande d’abord « Valider DEM-6 ? », en disant ce qui serait perdu.\u003C\u002Fp>\n\u003Ch3 id=\"les-conflits\">Les conflits\u003C\u002Fh3>\n\u003Cp>Quand le merge rencontre un conflit, il est annulé : rien n’est à moitié mergé. Le réglage « En cas de conflit » décide de la suite.\u003C\u002Fp>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Réglage\u003C\u002Fth>\n\u003Cth>Ce qui se passe\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>« Me demander » (par défaut)\u003C\u002Ftd>\n\u003Ctd>La carte se bloque sur « Conflit avec main » et propose « L’agent résout » et « Annuler ».\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>« L’agent résout »\u003C\u002Ftd>\n\u003Ctd>L’agent prend le conflit en charge tout de suite.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>« Annuler »\u003C\u002Ftd>\n\u003Ctd>La carte se bloque en nommant les fichiers (« Conflit avec main sur : a.ts, b.ts »), et propose « Réessayer ».\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>« L’agent résout » fusionne la branche cible dans la branche du ticket (ou, avec la stratégie « Rebase », demande à l’agent de rebaser), laisse les conflits dans le worktree et renvoie le ticket « En cours », à la boucle 1, avec l’agent prévenu. « Annuler » sur la carte enlève le blocage : le ticket reste « À tester ».\u003C\u002Fp>\n\u003Ch3 id=\"quand-une-etape-echoue\">Quand une étape échoue\u003C\u002Fh3>\n\u003Cp>Une étape en échec (une branche cible introuvable, un conflit non résolu dans le worktree, un push refusé…) laisse le ticket « À tester », bloqué avec la première ligne de l’erreur, et tu es prévenu (« bloqué »). Le bouton de validation devient « Réessayer » : il relance la validation.\u003C\u002Fp>\n\u003Ch2 id=\"renvoyer-un-ticket-a-son-agent\">Renvoyer un ticket à son agent\u003C\u002Fh2>\n\u003Cp>« Renvoyer » ouvre un champ « Ce qui ne va pas ». Décris le problème (le bouton « Renvoyer » reste grisé tant que le champ est vide ; \u003Ccode class=\"key\">Échap\u003C\u002Fcode> ou « Annuler » abandonnent).\u003C\u002Fp>\n\u003Cp>Le ticket retourne « En cours », avec le même agent et le même worktree, à la boucle 1. L’agent reçoit « Retour de test sur DEM-6 : \u003Ccode>&lt;ton texte&gt;\u003C\u002Fcode>. Corrige, revérifie tous les critères, puis termine par le bilan. » Il boucle de nouveau jusqu’à atteindre les critères ou épuiser ses boucles, puis le ticket revient dans « À tester ». Toutes les boucles comptent dans le total affiché sur la carte « Terminé ».\u003C\u002Fp>\n\u003Cp>Pour la façon dont l’agent boucle sur un ticket, voir \u003Ca href=\"\u002Fdocs\u002Fautopilot\u002F#la-boucle\">Le pilote auto\u003C\u002Fa>.\u003C\u002Fp>\n",[8,12,15,19,22,25,28,31,34,37,40,43],{"id":9,"text":10,"depth":11},"quand-un-ticket-arrive-dans-a-tester","Quand un ticket arrive dans « À tester »",2,{"id":13,"text":14,"depth":11},"tester-avec-tester","Tester avec « ▶ Tester »",{"id":16,"text":17,"depth":18},"ou-est-le-bouton","Où est le bouton",3,{"id":20,"text":21,"depth":18},"la-recette-ecrite-par-l-agent","La recette écrite par l’agent",{"id":23,"text":24,"depth":18},"les-ports-reserves","Les ports réservés",{"id":26,"text":27,"depth":18},"pendant-le-test","Pendant le test",{"id":29,"text":30,"depth":18},"avec-isola","Avec isola",{"id":32,"text":33,"depth":11},"valider-un-ticket","Valider un ticket",{"id":35,"text":36,"depth":18},"les-etapes-d-une-validation","Les étapes d’une validation",{"id":38,"text":39,"depth":18},"les-conflits","Les conflits",{"id":41,"text":42,"depth":18},"quand-une-etape-echoue","Quand une étape échoue",{"id":44,"text":45,"depth":11},"renvoyer-un-ticket-a-son-agent","Renvoyer un ticket à son agent",1791926754946]