dsh-composer-plus 1.16.1 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.fr.md CHANGED
@@ -29,7 +29,7 @@ dsh plugin --profile web add dsh-composer-plus
29
29
 
30
30
  Redémarrez ensuite dsh. (La CLI ne peut pas installer dans le profil de bureau ; c’est l’app qui le gère.)
31
31
 
32
- > Le pnpm de dsh ignore les versions publiées depuis moins de 24 heures. Juste après une nouvelle version, ajoutez le numéro de version : `dsh-composer-plus@1.16.1`.
32
+ > Le pnpm de dsh ignore les versions publiées depuis moins de 24 heures. Juste après une nouvelle version, ajoutez le numéro de version : `dsh-composer-plus@1.18.0`.
33
33
 
34
34
  ## Fonctionnalités
35
35
 
@@ -47,6 +47,7 @@ Redémarrez ensuite dsh. (La CLI ne peut pas installer dans le profil de bureau
47
47
  | **Mode plan avec Shift+Tab** | <a id="feature-plantoggle"></a>`Shift+Tab` ajoute `/plan ` au début du brouillon (appuyez de nouveau pour le retirer). Si la discussion est déjà en mode plan, `Shift+Tab` quitte ce mode. | <a href="assets/features/planToggle.webp"><img src="assets/features/planToggle.webp" width="160" alt="Capture d’écran : Mode plan avec Shift+Tab"></a> |
48
48
  | **Garder le focus dans la zone de saisie** | <a id="feature-keepfocus"></a>Après l’envoi d’une commande `/` ou d’une compétence, le curseur reste dans la zone de saisie et vous pouvez taper de nouveau tout de suite. Cela fonctionne aussi pour les macros clavier qui tapent une commande et appuient sur `Enter`. dsh met la zone de saisie en lecture seule pendant qu’il résout la commande, et le navigateur retire alors le focus. Cette fonctionnalité remet le focus, sauf si un menu, une boîte de dialogue ou un autre champ l’a. | <a href="assets/features/keepFocus.webp"><img src="assets/features/keepFocus.webp" width="160" alt="Capture d’écran : Garder le focus dans la zone de saisie"></a> |
49
49
  | **Adapter la carte de question à la fenêtre** | <a id="feature-questionfit"></a>Quand l’agent vous pose une question, la question et ses réponses défilent ensemble dans la carte, et **Ignorer** et **Envoyer** restent visibles en bas. La carte utilise la hauteur de la fenêtre (moins 200 px pour l’en-tête de la conversation et une bande de la conversation) : elle grandit et rétrécit avec la fenêtre. Sans cette fonctionnalité, dsh limite la carte à 60 % de la fenêtre (520 px au plus) et seules les réponses défilent : une longue question peut pousser sa propre fin, les réponses et les boutons hors de la carte. | <a href="assets/features/questionFit.webp"><img src="assets/features/questionFit.webp" width="160" alt="Capture d’écran : Adapter la carte de question à la fenêtre"></a> |
50
+ | **Adapter l’en-tête de la conversation à la fenêtre** | <a id="feature-headerfit"></a>Dans une fenêtre étroite, les boutons de l’en-tête de la conversation de dsh (le mode, les sous-agents, les tâches en arrière-plan, Ouvrir dans, l’étiquette de branche et l’étiquette d’autorisations) ne se chevauchent plus. Le titre garde au moins 120 px ; les boutons qui ne tiennent pas passent sur une deuxième ligne à droite, et chacun reste cliquable. Quand tout tient sur une ligne (fenêtre large), l’en-tête est exactement celui de dsh. Sans cette fonction, dsh ne réduit que le titre : avec un sous-agent et des tâches en arrière-plan, ses boutons se chevauchent dans une colonne de conversation étroite. L’étiquette de branche (**Une branche par discussion**) et celle d’autorisations (**Autoriser pour cette discussion**) s’adaptent aussi à l’en-tête quand cet interrupteur est désactivé. | <a href="assets/features/headerFit.webp"><img src="assets/features/headerFit.webp" width="160" alt="Capture d’écran : Adapter l’en-tête de la conversation à la fenêtre"></a> |
50
51
  | **Continuer en un clic** | <a id="feature-continuebutton"></a>Après un tour arrêté, en échec ou interrompu, une zone de saisie vide affiche **▶**. Un clic reprend la conversation existante, sans écrire dans le champ de saisie ni ajouter de message visible à la discussion (le modèle reçoit une courte note cachée « continue là où tu t’es arrêté », car certains fournisseurs, comme Claude, refusent une requête qui se termine par une réponse de l’assistant). Les messages de la file y restent : ▶ reprend seulement la tâche arrêtée, puis la file s’exécute. Un tour terminé garde le bouton Envoyer habituel. | <a href="assets/features/continueButton.webp"><img src="assets/features/continueButton.webp" width="160" alt="Capture d’écran : Continuer en un clic"></a> |
51
52
  | **Reprendre après redémarrage** | <a id="feature-resumeafterrestart"></a>Désactivée par défaut : activez-la dans **Réglages → Composer Plus**. Si vous quittez dsh (ou s’il se ferme) pendant qu’une discussion travaille, cette discussion reprend d’elle-même quand vous rouvrez dsh, avec la même note cachée que Continuer en un clic. Si une itération d’objectif (`/goal`) était en cours, l’objectif passe à l’itération suivante (dsh suspend les objectifs à chaque démarrage jusqu’à ce que vous les repreniez). Les discussions que vous avez arrêtées, terminées ou en échec ne reprennent pas. dsh lui-même n’a pas de réglage pour cela : il marque seulement ce tour comme interrompu. | <a href="assets/features/resumeAfterRestart.webp"><img src="assets/features/resumeAfterRestart.webp" width="160" alt="Capture d’écran : Reprendre après redémarrage"></a> |
52
53
  | **Glisser-déposer dans la file** | <a id="feature-queuereorder"></a>Les messages en file d’attente reçoivent une poignée (⠿). Faites-la glisser pour réordonner, ou placez le focus sur la poignée et appuyez sur `↑` / `↓`. `Esc` annule. | <a href="assets/features/queueReorder.webp"><img src="assets/features/queueReorder.webp" width="160" alt="Capture d’écran : Glisser-déposer dans la file"></a> |
@@ -63,19 +64,25 @@ Redémarrez ensuite dsh. (La CLI ne peut pas installer dans le profil de bureau
63
64
  | **Branches dans l’arborescence des espaces de travail** | <a id="feature-branchtree"></a>Réglages → Composer Plus → **Branches dans l’arborescence des espaces de travail** (désactivé par défaut). Chaque branche qui a un dossier de worktree dans `<project>/.worktrees/` s’affiche alors comme un projet dans son projet ; choisissez **Options d’affichage** → **Arborescence des espaces de travail** de dsh pour la voir imbriquée. Une branche dont le dossier est supprimé quitte la liste, et dsh affiche ses discussions sous **Sans groupe**. Quand l’agent d’une discussion dans le dossier du projet crée une branche et passe dessus (`git switch -c`, `git checkout -b`) sans modification non validée dans le dossier, le dossier du projet revient à sa branche précédente, la branche reçoit son propre dossier et la discussion y va : une copie s’ouvre dans le projet de la branche et continue la tâche, et l’ancienne discussion est archivée. La liste est vérifiée au démarrage, toutes les 30 secondes, après chaque tour et quand vous revenez à la fenêtre. | <a href="assets/features/branchTree.webp"><img src="assets/features/branchTree.webp" width="160" alt="Capture d’écran : Branches dans l’arborescence des espaces de travail"></a> |
64
65
  | **Prédiction du message suivant** | <a id="feature-nextprediction"></a>Activée par défaut ; vous pouvez la désactiver dans **Réglages → Composer Plus**. Quand l’agent termine un tour (pas un tour arrêté ou en échec), la zone de saisie vide affiche en gris une prédiction de votre prochain message, avec l’indication **Tab pour accepter**. `Tab` place le texte dans la zone de saisie, sans l’envoyer. `Esc` la masque pour ce tour. Taper du texte la masque aussi, et un nouveau tour la remplace. Le menu **Modèle**, sous l’interrupteur, liste les modèles de dsh (la même liste que le menu des modèles de dsh). **Défaut de dsh** est sélectionné par défaut et suit le modèle par défaut de dsh. Chaque tour terminé coûte un court appel au modèle. Dans Tether, la prédiction s’affiche au-dessus de la zone de saisie vide : touchez-la pour la placer dans le champ. | <a href="assets/features/nextPrediction.webp"><img src="assets/features/nextPrediction.webp" width="160" alt="Capture d’écran : Prédiction du message suivant"></a> |
65
66
  | **Compléter pendant la saisie** | <a id="feature-typingcompletion"></a>Désactivé par défaut ; vous pouvez l’activer dans **Réglages → Composer Plus**. Pendant que vous tapez, un texte gris juste après le curseur montre comment votre message peut continuer. `Tab` l’ajoute au message, sans l’envoyer. `Esc` le masque. Il ne propose que vos propres mots suivants : jamais une réponse qui vous est adressée, ni des textes d’erreur ou des noms inventés. Si le message semble complet ou si le modèle n’est pas sûr, rien ne s’affiche. Si vous tapez les lettres suivantes du texte gris, il reste affiché, sans nouvel appel au modèle. Cette fonctionnalité a son propre menu **Modèle** sous son interrupteur. Sa première option, **Comme la prédiction du message suivant**, utilise le modèle de **Prédiction du message suivant** (c’est l’option par défaut) ; choisissez un autre modèle pour utiliser un modèle différent pour chaque fonctionnalité, par exemple un modèle plus rapide pour les complétions. Elle fait un appel au modèle à chaque pause pendant la saisie : elle consomme donc beaucoup plus de tokens que la prédiction. Choisissez un modèle rapide et peu coûteux. Elle ne s’exécute pas pour une commande slash, un message avec une pastille de fichier, ou quand le curseur n’est pas à la fin. Dans Tether, la suite s’affiche au-dessus du champ pendant la saisie : touchez-la pour l’ajouter. | <a href="assets/features/typingCompletion.webp"><img src="assets/features/typingCompletion.webp" width="160" alt="Capture d’écran : Compléter pendant la saisie"></a> |
66
- | **Améliorer le prompt** | <a id="feature-promptimprove"></a>Tapez une demande approximative, puis cliquez sur la baguette magique (**Améliorer le prompt**) à côté du menu des modèles. Un appel au modèle la réécrit en un prompt plus clair : l’objectif d’abord, de courtes étapes numérotées quand il y a plusieurs parties, et la vérification à lancer. Il lit cette discussion (sans les messages retirés par une annulation), le README, AGENTS.md et le manifeste du projet, les fichiers modifiés et les fichiers dont le nom correspond à vos mots, et garde votre langue. Il n’invente jamais de noms de fichiers. Le nouveau texte remplace votre brouillon, mais n’est pas envoyé : lisez-le, modifiez-le, puis appuyez sur `Enter`. `Cmd/Ctrl+Z` rétablit votre texte en une étape, tout comme le bouton (**Annuler l’amélioration**). Si vous tapez pendant qu’il travaille, votre nouveau texte reste. `Esc` ou un second clic annule. Il a son propre menu **Modèle** dans les Réglages (par défaut : **Comme le modèle de la discussion**). Pas pour les commandes slash ni pour un message avec une pastille de fichier. Dans Tether, la baguette est à côté du champ. | <a href="assets/features/promptImprove.webp"><img src="assets/features/promptImprove.webp" width="160" alt="Capture d’écran : Améliorer le prompt"></a> |
67
- | **Vérification de l’objectif** | <a id="feature-goalcheck"></a>Lancez un objectif avec `/goal`. Quand l’agent marque l’objectif comme terminé lors d’une itération automatique, l’objectif ne se ferme qu’après deux vérifications. D’abord, la commande de test du projet s’exécute dans le dossier de la discussion, avec le mode sandbox de la discussion. La commande est la vôtre ou celle trouvée dans `package.json`, `Makefile`, `Cargo.toml`, `go.mod` ou pytest. Quand la dernière étape de l’agent lui-même était une exécution réussie de ce test, il n’est pas relancé. Ensuite, un appel indépendant au modèle, sans outils, lit l’objectif, cette discussion, `git status` et le résultat du test. Si une vérification échoue, l’objectif reste actif et l’agent lit pourquoi, puis l’itération suivante continue. Une ligne sous la barre de l’objectif (**Vérification de l’objectif**) affiche le test et le dernier résultat. **Modifier** définit votre propre commande de test et une limite de temps ou de tokens ; au-delà de la limite, l’objectif devient bloqué. **Lancer maintenant** lance la vérification sans fermer l’objectif. Il a son propre menu **Modèle** dans les Réglages (par défaut : **Comme le modèle de la discussion**). Quand vous terminez l’objectif vous-même, rien n’est vérifié. | <a href="assets/features/goalCheck.webp"><img src="assets/features/goalCheck.webp" width="160" alt="Capture d’écran : Vérification de l’objectif"></a> |
68
- | **Mémoire du projet** | <a id="feature-projectmemory"></a>Désactivée par défaut : activez-la dans **Réglages → Composer Plus**. Chaque dossier de projet a sa propre mémoire, que les discussions suivantes de ce projet lisent, comme DS Bot en garde une par Bot. Après chaque tour terminé, un appel au modèle de la discussion lit les nouveaux messages (pas ceux annulés), garde vos préférences, décisions et faits durables sous forme de notes courtes, et modifie ou supprime les anciennes. L’agent peut aussi enregistrer, supprimer et chercher des notes lui-même (`memory_remember`, `memory_forget`, `memory_recall`). Une note peut aussi être globale : tous les projets la lisent. Une nouvelle discussion reçoit les notes dans son prompt système ; une note enregistrée plus tard apparaît à partir de la discussion suivante. Les fichiers sont en Markdown dans le dossier personnel de dsh (`storages/dsh-composer-plus/memory/`), jamais dans le dossier du projet. | <a href="assets/features/projectMemory.webp"><img src="assets/features/projectMemory.webp" width="160" alt="Capture d’écran : Mémoire du projet"></a> |
67
+ | **Améliorer le prompt** | <a id="feature-promptimprove"></a>Tapez une demande approximative, puis cliquez sur la baguette magique (**Améliorer le prompt**) à côté du menu des modèles. Un appel au modèle la réécrit en un prompt plus clair : l’objectif d’abord, de courtes étapes numérotées quand il y a plusieurs parties, et la vérification à lancer. Il lit cette discussion (sans les messages retirés par une annulation), le README, AGENTS.md et le manifeste du projet, les fichiers modifiés et les fichiers dont le nom correspond à vos mots, et garde votre langue. Il n’invente jamais de noms de fichiers. Le nouveau texte remplace votre brouillon, mais n’est pas envoyé : lisez-le, modifiez-le, puis appuyez sur `Enter`. `Cmd/Ctrl+Z` rétablit votre texte en une étape, tout comme le bouton (**Annuler l’amélioration**). Si vous tapez pendant qu’il travaille, votre nouveau texte reste. `Esc` ou un second clic annule. Il a son propre menu **Modèle** dans les Réglages (par défaut : **Comme le modèle de la discussion**). Sur un message `/goal <objective>`, il réécrit seulement l’objectif, sous forme d’une condition d’achèvement que la **Vérification de l’objectif** peut vérifier : les résultats attendus, les vérifications qui doivent réussir, la preuve à montrer dans la discussion, une partie impossible à faire marquée comme non résolue, et un arrêt quand le même blocage persiste. La commande `/goal` reste. Pas pour les autres commandes slash, un mot de contrôle de `/goal` (`clear`, `pause`, `resume`) ni un message avec une pastille de fichier. Dans Tether, la baguette est à côté du champ. | <a href="assets/features/promptImprove.webp"><img src="assets/features/promptImprove.webp" width="160" alt="Capture d’écran : Améliorer le prompt"></a> |
68
+ | **Vérification de l’objectif** | <a id="feature-goalcheck"></a>Lancez un objectif avec `/goal`. Quand l’agent marque l’objectif comme terminé lors d’une itération automatique, l’objectif ne se ferme qu’après deux vérifications. D’abord, la commande de test du projet s’exécute dans le dossier de la discussion, avec le mode sandbox de la discussion. La commande est la vôtre ou celle trouvée dans `package.json`, `Makefile`, `Cargo.toml`, `go.mod` ou pytest. Quand la dernière étape de l’agent lui-même était une exécution réussie de ce test, il n’est pas relancé. Ensuite, un appel indépendant au modèle, sans outils, lit l’objectif, cette discussion, `git status` et le résultat du test. Le modèle répond par un tableau de preuves : chaque partie de l’objectif est vérifiée, incorrecte ou non résolue, avec la preuve et la correction ; l’objectif ne se ferme que lorsque chaque partie est vérifiée. Si une vérification échoue, l’objectif reste actif et l’agent lit chaque partie ouverte avec sa preuve et sa correction, puis l’itération suivante continue. Une ligne sous la barre de l’objectif (**Vérification de l’objectif**) affiche le test, le dernier résultat et le nombre de parties vérifiées (survolez-la pour voir le tableau). **Modifier** définit votre propre commande de test et une limite de temps ou de tokens ; au-delà de la limite, l’objectif devient bloqué. La limite de tokens compte aussi les sous-agents de la discussion. **Lancer maintenant** lance la vérification sans fermer l’objectif. Il a son propre menu **Modèle** dans les Réglages (par défaut : **Comme le modèle de la discussion**). Quand vous terminez l’objectif vous-même, rien n’est vérifié. | <a href="assets/features/goalCheck.webp"><img src="assets/features/goalCheck.webp" width="160" alt="Capture d’écran : Vérification de l’objectif"></a> |
69
+ | **Continuer dans une nouvelle discussion** | <a id="feature-handoffchat"></a>Clic droit sur une discussion dans la barre latérale (ou ouvrez son menu **…**) → **Continuer dans une nouvelle discussion…**. Un seul appel au modèle de la discussion rédige une note de passation à partir de ce que montre la discussion : Tâche, Résultats, Terminé, Décisions, Problèmes ouverts et Prochaine action (les appels d’outils et leurs résultats sont les preuves ; les étapes que vous avez annulées sont exclues). La note s’ouvre dans une boîte de dialogue : lisez-la et modifiez-la. **Rédiger à nouveau** rédige une nouvelle note. **Lancer une nouvelle discussion** (ou `Cmd/Ctrl+Enter`) ouvre une nouvelle discussion dans le même projet, avec la note et un lien vers l’ancienne discussion comme premier message ; l’ancienne discussion reste telle quelle. Utilisez cette fonction quand une longue discussion est pleine ou lente, ou pour continuer demain. Rien n’est écrit dans le projet. | <a href="assets/features/handoffChat.webp"><img src="assets/features/handoffChat.webp" width="160" alt="Capture d’écran : Continuer dans une nouvelle discussion"></a> |
70
+ | **Répartition du contexte** | <a id="feature-contextbreakdown"></a>Barre latérale droite → `+` → **Contexte**. La page montre ce qui remplit maintenant le contexte du modèle de la discussion ouverte et la part de la fenêtre de contexte utilisée : le prompt système, les instructions du projet (AGENTS.md), les compétences, vos messages, les réponses de l’agent et les appels d’outils, les résultats d’outils (par outil), les résultats MCP (par serveur), les définitions des outils, le résumé de compaction et les autres notes de contexte, chacun avec ses tokens et sa part. Cliquez sur une partie pour voir ses outils ou ses serveurs. Elle lit seulement le journal de la discussion, après `/compact` et les annulations, et n’appelle aucun modèle ; elle relit le journal après chaque tour et avec **Actualiser**. Utilisez-la pour voir pourquoi une discussion est lente ou pleine, par exemple à cause d’un gros résultat d’outil MCP ou de nombreuses définitions d’outils. | <a href="assets/features/contextBreakdown.webp"><img src="assets/features/contextBreakdown.webp" width="160" alt="Capture d’écran : Répartition du contexte"></a> |
71
+ | **Étapes planifiées** | <a id="feature-plannedsteps"></a>Désactivée par défaut : activez-la dans **Réglages → Composer Plus**. L’agent reçoit l’outil `plan_next_steps` : dans le même message qu’une commande, il peut planifier les commandes suivantes avec leurs arguments exacts et une condition, par exemple « lance `npm test` quand la compilation réussit ». Quand le résultat remplit la condition, Composer Plus exécute lui-même l’étape suivante, sans nouvel appel au modèle, et une longue discussion consomme moins de jetons. L’étape apparaît dans la discussion sous forme d’une courte ligne, « Composer Plus · Planned steps: ran `test` … without a model call », suivie de son appel d’outil et de son résultat. Uniquement des étapes `bash`, `read`, `grep` et `glob` ; les approbations, le sandbox et Fichiers protégés s’appliquent à chaque étape comme d’habitude. Le modèle répond de nouveau quand une condition échoue, quand deux étapes sont prêtes en même temps, après la dernière étape et quand vous envoyez un message. L’idée vient de HarnessMM (arXiv 2610.32813). | <a href="assets/features/plannedSteps.webp"><img src="assets/features/plannedSteps.webp" width="160" alt="Capture d’écran : Étapes planifiées"></a> |
72
+ | **Fichiers protégés** | <a id="feature-protectedfiles"></a>Activée par défaut. Les outils de fichiers propres à l’agent ne peuvent ni lire ni modifier les fichiers qui correspondent à vos motifs : `read`, `read_image` et `grep` sur un fichier sont refusés pour les motifs **lecture et écriture**, et `write`, `edit` et `str_replace_editor` pour les deux types. L’agent lit pourquoi et on lui demande de vous consulter. Les motifs par défaut sont `.env*`, `*.pem` et `*.key`. Réglages → Composer Plus → **Fichiers protégés** : ajoutez un motif (par exemple `published/**` ou `config/*.yml`), cliquez sur son type pour basculer entre **lecture et écriture** et **écriture seule**, supprimez-le avec ✕, ou cliquez sur **Utiliser les valeurs par défaut**. Un motif sans `/` correspond à un nom de fichier dans n’importe quel dossier. C’est un garde-fou, pas un sandbox : une commande shell (`cat .env`), un script ou un outil MCP peut encore atteindre le fichier (voir Limites). | <a href="assets/features/protectedFiles.webp"><img src="assets/features/protectedFiles.webp" width="160" alt="Capture d’écran : Fichiers protégés"></a> |
73
+ | **Commandes bloquées** | <a id="feature-blockedcommands"></a>Activée par défaut, avec une liste vide. Les commandes shell de l’agent (`bash`, `pwsh`) ne peuvent pas exécuter une commande qui correspond à vos règles : une règle **bloquer** refuse l’appel (l’agent lit pourquoi et on lui demande de vous consulter), une règle **demander d’abord** affiche la carte d’approbation de dsh, et la commande ne s’exécute que si vous l’autorisez. Réglages → Composer Plus → **Commandes bloquées** : tapez une règle (par exemple `npm publish`, `git push --force` ou `ssh *192.168.2.19`), cliquez sur son type pour basculer entre **bloquer** et **demander d’abord**, puis cliquez sur **Ajouter** ; cliquez sur le type d’une règle pour le changer, supprimez-la avec ✕. Une règle est un nom de commande et des mots qui doivent le suivre dans cet ordre ; `*` correspond à n’importe quel texte. La vérification trouve aussi la commande après `&&`, `;`, `\|`, dans `$(…)`, `bash -c "…"` ou `eval`, et après `sudo` ou `env`. C’est un garde-fou, pas un sandbox : une variable (`$CMD`), un fichier de script ou un autre programme peut encore exécuter la commande (voir Limites). | <a href="assets/features/blockedCommands.webp"><img src="assets/features/blockedCommands.webp" width="160" alt="Capture d’écran : Commandes bloquées"></a> |
74
+ | **Tableau des tâches** | <a id="feature-taskboard"></a>Barre latérale gauche → **Tableau des tâches**. Un tableau kanban de vos projets dsh, pour vous et pour les agents : **À faire**, **En cours**, **En revue** et **Terminé** (et **En attente**, voir plus bas). Choisissez un projet ou **Tous les projets** à gauche. **Nouvelle tâche** (ou `n`) ouvre une nouvelle carte : tapez son titre et appuyez sur `Enter`. Faites glisser une carte vers une autre colonne ou entre deux cartes. Cliquez sur une carte pour voir et modifier son **Statut**, ses **Étiquettes**, **Manuelle** (les agents l’ignorent), sa description (Markdown) et ses commentaires. `/` cherche dans tous les projets, `h` affiche seulement les tâches manuelles, et le bouton d’export enregistre le tableau en Markdown ou en JSON. Les agents reçoivent des outils de tableau : dans une discussion, demandez à l’agent de « prendre la tâche suivante du tableau » ; il déplace la première carte de **À faire** vers **En cours**, commente ce qu’il a fait et la déplace vers **En revue** ; c’est vous qui la déplacez vers **Terminé**. Dans un projet qui a des tâches ouvertes, chaque discussion reçoit cette règle d’elle-même. Réglages → Composer Plus → **Tableau des tâches** contient l’interrupteur de la colonne **En attente** : les agents vous laissent ses cartes. | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="Capture d’écran : Tableau des tâches"></a> |
75
+ | **Mémoire du projet** | <a id="feature-projectmemory"></a>Désactivée par défaut : activez-la dans **Réglages → Composer Plus**. Chaque dossier de projet a sa propre mémoire, que les discussions suivantes de ce projet lisent, comme DS Bot en garde une par Bot. Après chaque tour terminé, un appel au modèle de la discussion lit les nouveaux messages (pas ceux annulés), garde vos préférences, décisions et faits durables sous forme de notes courtes, et modifie ou supprime les anciennes. L’agent peut aussi enregistrer, supprimer et chercher des notes lui-même (`memory_remember`, `memory_forget`, `memory_recall`). Une note peut aussi être globale : tous les projets la lisent. Une nouvelle discussion reçoit les notes dans son prompt système ; une note enregistrée plus tard apparaît à partir de la discussion suivante. Les fichiers sont en Markdown dans le dossier personnel de dsh (`storages/dsh-composer-plus/memory/`), jamais dans le dossier du projet. **Ouvrir la mémoire**, sur la même ligne, montre toutes les notes enregistrées, groupées par projet (et la mémoire globale), avec un filtre. Écrivez avec vos mots ce qu’il faut changer (par exemple « je suis passé de yarn à pnpm »), puis **Aperçu des modifications** : le modèle par défaut de dsh propose les modifications, et seul **Appliquer** les enregistre. Dans Tether : menu du titre de la discussion → Project memory. | <a href="assets/features/projectMemory.webp"><img src="assets/features/projectMemory.webp" width="160" alt="Capture d’écran : Mémoire du projet"></a> |
69
76
  | **Autoriser pour cette discussion** | <a id="feature-allowforchat"></a>Quand la revue automatique vous demande votre avis, la carte d’approbation propose **Autoriser pour cette discussion** : le même outil dans la même discussion est ensuite autorisé, quels que soient les arguments, jusqu’à la fin de la limite de temps (1 heure par défaut ; choisissez-la dans **Réglages → Composer Plus → Autoriser pour cette discussion**). Ensuite, l’agent demande à nouveau. Une pastille dans l’en-tête liste les autorisations avec leur heure de fin et permet de les révoquer. Les autorisations restent valables après un redémarrage. | <a href="assets/features/allowForChat.webp"><img src="assets/features/allowForChat.webp" width="160" alt="Capture d’écran : Autoriser pour cette discussion"></a> |
70
77
  | **Statut du projet** | <a id="feature-projectstatus"></a>La ligne d’un projet dans la barre latérale affiche le même indicateur en cours / en attente / terminé que ses discussions : même replié, un projet vous indique donc qu’une discussion travaille ou a besoin de vous. Une discussion qui vous attend s’affiche en premier, puis une discussion terminée que vous n’avez pas encore ouverte (le point vert, même pendant qu’une autre discussion est encore en cours), puis l’indicateur en cours. Survolez-le pour voir les détails. Dans **Arborescence des espaces de travail**, la ligne d’un dossier parent affiche aussi les discussions de chaque projet qu’il contient (par exemple chaque dossier de branche dans `.worktrees/`), même quand il est replié. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Capture d’écran : Statut du projet"></a> |
71
- | **Branche Git sur les lignes de discussion** | <a id="feature-sessionbranch"></a>Chaque ligne de discussion de la barre latérale affiche une petite pastille grise avec la branche git sur laquelle se trouvait le dossier du projet de la discussion lors de son dernier tour (par exemple `main` ou `feature/login` ; un HEAD détaché affiche son identifiant de commit court entre parenthèses). Deux discussions d’un même projet sur des branches différentes ne se ressemblent plus, et vous voyez tout de suite quand vous allez continuer une discussion sur la mauvaise branche. Survolez la pastille pour voir le nom complet. La partie hôte lit la branche (`git branch --show-current`, en lecture seule) au début et à la fin de chaque tour ; une discussion sans tour depuis que vous avez installé cette fonctionnalité, ou un dossier qui n’est pas un dépôt git, n’affiche pas de pastille. Si la ligne de projet au-dessus de la discussion porte le même nom que la branche (par exemple un dossier « Une branche par discussion »), la ligne de discussion n’affiche pas de pastille, mais « Dans une seule liste » l’affiche toujours. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="Capture d’écran : Branche Git sur les lignes de discussion"></a> |
78
+ | **Branche Git sur les lignes de discussion** | <a id="feature-sessionbranch"></a>Chaque ligne de discussion de la barre latérale affiche une petite pastille grise avec la branche git sur laquelle se trouvait le dossier du projet de la discussion lors de son dernier tour (par exemple `main` ou `feature/login` ; un HEAD détaché n’a pas de branche et n’affiche pas de pastille). Deux discussions d’un même projet sur des branches différentes ne se ressemblent plus, et vous voyez tout de suite quand vous allez continuer une discussion sur la mauvaise branche. Survolez la pastille pour voir le nom complet. La partie hôte lit la branche (`git branch --show-current`, en lecture seule) au début et à la fin de chaque tour ; une discussion sans tour depuis que vous avez installé cette fonctionnalité, ou un dossier qui n’est pas un dépôt git, n’affiche pas de pastille. Si la ligne de projet au-dessus de la discussion porte le même nom que la branche (par exemple un dossier « Une branche par discussion »), la ligne de discussion n’affiche pas de pastille, mais « Dans une seule liste » l’affiche toujours. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="Capture d’écran : Branche Git sur les lignes de discussion"></a> |
72
79
  | **Tout marquer comme lu** | <a id="feature-markprojectread"></a>Dans la barre latérale, cliquez sur le bouton **…** d’un projet → **Tout marquer comme lu**. Le point vert non lu disparaît d’un coup de toutes les discussions de ce projet ; les autres projets gardent le leur. L’élément est grisé (**Aucune discussion non lue**) quand le projet n’en a aucune. | <a href="assets/features/markProjectRead.webp"><img src="assets/features/markProjectRead.webp" width="160" alt="Capture d’écran : Tout marquer comme lu"></a> |
73
80
  | **Projets actifs en premier** | <a id="feature-activeprojectsfirst"></a>Quand une discussion commence à s’exécuter ou a besoin de vous, son projet monte en haut de la barre latérale avec l’animation de ligne de dsh (le même mouvement que si vous l’y faisiez glisser). Les projets terminés restent à leur place ; faites-les glisser où vous voulez, comme d’habitude. Les déplacements sont enregistrés dans l’ordre des projets de dsh : si vous désactivez cette fonctionnalité, l’ordre actuel reste. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Capture d’écran : Projets actifs en premier"></a> |
74
81
  | **Filtre des projets récents** | <a id="feature-recentprojects"></a>Barre latérale → options d’affichage (icône de curseurs) → **Actifs au cours des 2 dernières heures**. Tant que cette option est sélectionnée, la barre latérale n’affiche que les projets qui ont une discussion active au cours des 2 dernières heures : une discussion mise à jour pendant ce temps, une discussion en cours ou en attente, la discussion ouverte, ou une discussion terminée que vous n’avez pas encore ouverte (le point vert « terminé » de dsh), même après les 2 heures. Les projets sans une telle discussion sont masqués, y compris les projets nouveaux et vides. Dans **Arborescence des espaces de travail**, un dossier parent reste affiché tant qu’un projet qu’il contient est actif, et les discussions qui n’ont pas été actives au cours des 2 dernières heures sont aussi masquées, si bien que seules les discussions récentes sont affichées. Sélectionnez de nouveau l’option pour afficher tous les projets. Le choix est conservé sur cet appareil. | <a href="assets/features/recentProjects.webp"><img src="assets/features/recentProjects.webp" width="160" alt="Capture d’écran : Filtre des projets récents"></a> |
75
82
  | **Réduire tous les projets** | <a id="feature-collapseprojects"></a>Quand un projet est ouvert dans la barre latérale, un bouton apparaît à côté des options d’affichage (icône de curseurs). Cliquez dessus pour fermer tous les projets ouverts d’un coup, par exemple 3 projets ouverts sur 5. Le bouton disparaît de nouveau quand aucun projet n’est ouvert. | <a href="assets/features/collapseProjects.webp"><img src="assets/features/collapseProjects.webp" width="160" alt="Capture d’écran : Réduire tous les projets"></a> |
76
83
  | **Trier par état** | <a id="feature-statusorder"></a>Barre latérale → options d’affichage → **Trier par** → **Par état** (avec **Dans une seule liste**). Les discussions terminées viennent en premier (le point « terminé » de dsh, qu’un tour terminé par une erreur reçoit aussi), puis les discussions en cours ou en attente, puis celles qui ont une automatisation active (Schedule), puis les autres dans l’ordre de dsh. Quand vous ouvrez une discussion terminée, elle descend. Seul l’affichage change : sélectionnez **Ordre manuel** ou **Dernière mise à jour** pour revenir en arrière. | <a href="assets/features/statusOrder.webp"><img src="assets/features/statusOrder.webp" width="160" alt="Capture d’écran : Trier par état"></a> |
77
84
  | **Notifications en arrière-plan** | <a id="feature-notifications"></a>Quand dsh est en arrière-plan, vous recevez une notification quand un tour se termine (première ligne de la réponse) ou quand une discussion vous attend vraiment : une approbation (nom de l’outil), une réponse (la question) ou une revue de plan. Une demande doit être encore ouverte 1,5 s plus tard : les approbations données automatiquement (autorisations de la revue automatique, autres plugins) restent donc silencieuses, et une notification est retirée dès que sa demande reçoit une réponse. La pastille du Dock / de la barre des tâches compte les discussions en attente. Un clic sur la notification ouvre cette discussion. | <a href="assets/features/notifications.webp"><img src="assets/features/notifications.webp" width="160" alt="Capture d’écran : Notifications en arrière-plan"></a> |
78
- | **Ouvrir la discussion en attente en cas d’inactivité** | <a id="feature-idleswitch"></a>Quand une discussion pose une question ou attend une approbation ou une revue du plan (le point orange) et que vous n’utilisez pas dsh pendant 30 secondes, dsh ouvre cette discussion. Si plusieurs discussions attendent, celle qui attend depuis le plus longtemps s’ouvre en premier ; la suivante s’ouvre après 30 autres secondes sans utilisation. Une touche, un clic, un mouvement de souris, la molette ou un toucher relancent les 30 secondes. Du texte dans le champ qui a le focus, du texte sélectionné, ou un menu ou une boîte de dialogue ouverts empêchent aussi le changement. Tant qu’une discussion en attente est à l’écran, rien ne change. Si vous quittez une discussion en attente sans répondre, elle peut se rouvrir après les 30 secondes suivantes sans utilisation. Cela fonctionne aussi quand dsh est en arrière-plan, mais dsh ne passe pas au premier plan. | <a href="assets/features/idleSwitch.webp"><img src="assets/features/idleSwitch.webp" width="160" alt="Capture d’écran : Ouvrir la discussion en attente en cas d’inactivité"></a> |
85
+ | **Ouvrir la discussion en attente en cas d’inactivité** | <a id="feature-idleswitch"></a>Quand une discussion pose une question, attend une approbation ou une revue du plan (le point orange) ou termine un tour que vous n’avez pas encore lu (le point vert), et que vous n’utilisez pas dsh pendant 30 secondes, dsh ouvre cette discussion. Les discussions orange s’ouvrent avant les vertes. Dans chaque groupe, celle qui attend depuis le plus longtemps s’ouvre en premier ; la suivante s’ouvre après 30 autres secondes sans utilisation. Une touche, un clic, un mouvement de souris, la molette ou un toucher relancent les 30 secondes. Du texte dans le champ qui a le focus, du texte sélectionné, ou un menu ou une boîte de dialogue ouverts empêchent aussi le changement. Tant qu’une discussion en attente est à l’écran, rien ne change. Si vous quittez une discussion en attente sans répondre, elle peut se rouvrir après les 30 secondes suivantes sans utilisation. Quand une discussion verte s’ouvre, son point disparaît ; la discussion verte suivante ne s’ouvre qu’après que vous avez de nouveau utilisé dsh, puis 30 secondes sans utilisation. Cela fonctionne aussi quand dsh est en arrière-plan, mais dsh ne passe pas au premier plan. | <a href="assets/features/idleSwitch.webp"><img src="assets/features/idleSwitch.webp" width="160" alt="Capture d’écran : Ouvrir la discussion en attente en cas d’inactivité"></a> |
79
86
  | **Langue de l’application** | <a id="feature-language"></a>Réglages → Composer Plus → **Langue de l’application** passe toute l’interface de dsh en Türkçe, Español, Português (Brasil), Français, Deutsch, Русский, 日本語, 한국어, Bahasa Indonesia, Tiếng Việt ou हिन्दी (voir ci-dessous). | <a href="assets/features/language.webp"><img src="assets/features/language.webp" width="160" alt="Capture d’écran : Langue de l’application"></a> |
80
87
  | **Connexion mobile (iPhone)** | <a id="feature-mobileconnect"></a>Utilisez dsh depuis votre iPhone avec l’app [Tether](tether/), sur le même réseau Wi-Fi ou via [Tailscale](https://tailscale.com). Activez-la dans **Réglages → Composer Plus** (elle est désactivée par défaut, car elle ouvre un port réseau sur ce Mac). Cliquez ensuite sur **Connexion mobile** en bas à gauche de la barre latérale : scannez le code QR avec l’app Appareil photo de l’iPhone (touchez **Open in Tether**) ou avec **Scan code** dans Tether, touchez **Connect** et cliquez sur **Approve**. Installez d’abord Tether : sans elle, l’app Appareil photo ne peut pas ouvrir le code. Le téléphone affiche vos discussions, envoie des messages (avec des photos : le **+** de la zone de saisie → Camera, Photos ou Paste image), répond aux approbations et aux questions, et change de modèle et d’agent. Appairez autant de Mac que vous voulez : le nom du Mac, en haut à gauche de l’app, permet de passer de l’un à l’autre. Le panneau **Connexion mobile** liste les iPhone appairés avec leur dernière connexion : **Remove** en déconnecte un tout de suite. « Tailscale only » refuse le réseau local (pour un Wi-Fi partagé), et le journal d’accès montre qui a essayé de se connecter. Dans Tether, « Settings → Privacy » verrouille l’app avec Face ID. | <a href="assets/features/mobileConnect.webp"><img src="assets/features/mobileConnect.webp" width="160" alt="Capture d’écran : Connexion mobile (iPhone)"></a> |
81
88
  | **Mises à jour automatiques** | <a id="feature-autoupdate"></a>Au démarrage de dsh, le plugin vérifie la [dernière version sur GitHub](https://github.com/furkancak1r/dsh-composer-plus/releases/latest). Si elle est plus récente et déjà sur npm, il installe exactement cette version avec le gestionnaire de plugins de dsh (le même chemin que Réglages → Plugins) et vous avertit. Redémarrez dsh pour la charger. **Réglages → Composer Plus → Mises à jour de Composer Plus** affiche la version et propose **Rechercher des mises à jour** / **Mettre à jour**. Au premier démarrage de dsh avec la nouvelle version, une fenêtre **Nouveautés de Composer Plus N** affiche une fois les notes de cette version (issues de la même vérification des mises à jour, sans autre appel réseau) ; **Fermer** ou `Esc` la ferme. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="Capture d’écran : Mises à jour automatiques"></a> |
@@ -160,7 +167,12 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
160
167
  - **Compléter pendant la saisie :** désactivé tant que vous ne l’activez pas. Quand il est activé, à chaque pause pendant la saisie, la partie hôte envoie le texte déjà saisi, ainsi que vos propres messages de la discussion et les réponses texte de l’agent (sans sortie d’outil, sans contexte caché ni raisonnement), environ 3 000 caractères de discussion au plus, au modèle choisi sous **Compléter pendant la saisie** (par défaut, le modèle de **Prédiction du message suivant**). Une pause plus récente arrête la requête précédente. Rien n’est enregistré dans la discussion. L’interrupteur est dans `$DSH_HOME/storages/dsh-composer-plus/complete.json` (fichier réservé au propriétaire).
161
168
  - **Améliorer le prompt :** rien ne s’exécute tant que vous ne cliquez pas sur la baguette magique. La partie hôte envoie alors votre brouillon, vos propres messages de la discussion et les réponses texte de l’agent (sans sortie d’outil, sans contexte caché, sans raisonnement ni messages retirés par une annulation ; environ 6 000 caractères au plus, la partie la plus récente), le même résumé du projet que pour **Idées de fonctionnalités** (avec les mêmes règles de fichiers : ni `.env*` ni fichiers de clés, aucun lien symbolique hors du dossier, aucune FIFO), les chemins que `git status` liste comme modifiés et jusqu’à 30 chemins suivis ou non suivis (non ignorés) dont le nom partage des mots avec votre brouillon, au modèle choisi sous **Améliorer le prompt** (par défaut, le modèle de la discussion), en une seule requête. Aucun autre contenu de fichier que ce résumé n’est envoyé. Rien n’est écrit dans la discussion ni dans le projet : la réponse remplace seulement votre brouillon dans la zone de saisie, et vous décidez de l’envoyer ou non. Le modèle choisi est dans `$DSH_HOME/storages/dsh-composer-plus/improve.json` (fichier réservé au propriétaire).
162
169
  - **Vérification de l’objectif :** elle ne s’exécute que quand l’agent marque un `/goal` comme terminé lors d’une itération automatique (ou quand vous cliquez sur **Lancer maintenant**). La partie hôte exécute la commande de test dans le dossier de la discussion avec le mode sandbox de la discussion (comme l’outil `bash` de dsh lui-même : la même politique d’accès aux fichiers ; quand ce sandbox ne peut pas démarrer, le test ne s’exécute pas et la vérification échoue). Pour trouver la commande, elle ne lit que `package.json`, `Makefile`, `Cargo.toml`, `go.mod`, `pyproject.toml` et `pytest.ini`, comme fichiers ordinaires dans le dossier (aucun lien symbolique hors du dossier, aucune FIFO). Elle envoie ensuite l’objectif, la discussion depuis le début de l’objectif (vos messages, les réponses de l’agent, les appels d’outils coupés à 1 000 caractères et les 2 000 derniers caractères de chaque résultat d’outil ; sans raisonnement ni étapes retirées par une annulation ; environ 60 000 caractères au plus, la partie la plus récente), `git status --short` et la fin de la sortie du test au modèle choisi sous **Vérification de l’objectif** (par défaut, le modèle de la discussion), en une seule requête sans outils. La sortie des outils peut contenir ce que l’agent a lu : cette requête peut donc contenir des parties de vos fichiers, comme la discussion elle-même. Rien n’est écrit dans la discussion ni dans le projet. Votre commande de test, les limites, le dernier résultat (avec la fin de sa sortie) et le modèle choisi sont dans `$DSH_HOME/storages/dsh-composer-plus/goal-check.json` (fichier réservé au propriétaire, les 500 discussions les plus récentes).
163
- - **Mémoire du projet :** désactivée tant que vous ne l’activez pas. Quand elle est activée, après chaque tour terminé d’une discussion de premier niveau, la partie Host envoie les nouveaux messages de la discussion depuis la dernière revue (vos messages et les réponses texte de l’agent ; pas de sortie d’outils, pas de raisonnement, pas de contexte caché, pas de messages annulés ; la copie de la discussion parente dans une discussion dérivée est laissée de côté ; au plus environ 16 000 caractères) et les notes enregistrées au modèle de la discussion, en une seule requête sans outils. Les notes sont des fichiers Markdown dans `$DSH_HOME/storages/dsh-composer-plus/memory/` (fichiers réservés au propriétaire) : `projects/<id>/` pour chaque dossier de projet (`<id>` est un hash du chemin réel du dossier ; `project.json` indique le dossier), `global/`, `journal.jsonl` (chaque modification avec la ligne avant et après) et `reviewed.json` (jusqu’où chaque discussion a été lue). Rien n’est écrit dans le dossier du projet. Les notes qui ressemblent à une clé, un jeton, un mot de passe ou un numéro d’identité sont refusées. Les notes d’un projet entrent dans le prompt système de chaque nouvelle discussion de ce dossier : elles vont donc au modèle avec chaque requête de cette discussion. L’interrupteur est dans `memory.json`, au même endroit.
170
+ - **Continuer dans une nouvelle discussion :** rien ne s’exécute tant que vous ne cliquez pas. Ensuite, la partie hôte envoie la discussion (comme la Vérification de l’objectif la lit : sans raisonnement ni étapes retirées par une annulation) au modèle de la discussion elle-même et affiche la note de passation ; seul **Lancer une nouvelle discussion** crée une nouvelle discussion. Rien n’est écrit dans le projet.
171
+ - **Répartition du contexte :** la partie hôte lit seulement le journal de la discussion ; aucun appel au modèle, aucun fichier du projet.
172
+ - **Tableau des tâches :** le tableau (titres, descriptions, étiquettes et commentaires de vos tâches, chemins des dossiers de projet et leurs id courts) se trouve dans `$DSH_HOME/storages/dsh-composer-plus/board.json` (fichier réservé au propriétaire) ; l’interrupteur se trouve à côté, dans `board-switch.json`. Rien ne quitte votre machine et rien n’est écrit dans un dossier de projet. Les outils du tableau donnent aux agents ce que vous avez écrit sur le tableau : le texte d’une tâche arrive donc au modèle de la discussion quand un agent la lit. Un fichier de tableau endommagé est gardé sous le nom `board.json.broken-<time>` et le tableau repart vide.
173
+ - **Fichiers protégés :** la liste et l’interrupteur se trouvent dans `$DSH_HOME/storages/dsh-composer-plus/protected-files.json` (fichier réservé au propriétaire). La vérification lit seulement le chemin de chaque appel d’outil de fichiers (et son chemin réel), jamais le fichier.
174
+ - **Commandes bloquées :** les règles et l’interrupteur se trouvent dans `$DSH_HOME/storages/dsh-composer-plus/blocked-commands.json` (fichier réservé au propriétaire). La vérification lit seulement le texte de la commande de chaque appel `bash` et `pwsh` ; elle n’exécute rien et n’envoie rien.
175
+ - **Mémoire du projet :** désactivée tant que vous ne l’activez pas. Quand elle est activée, après chaque tour terminé d’une discussion de premier niveau, la partie Host envoie les nouveaux messages de la discussion depuis la dernière revue (vos messages et les réponses texte de l’agent ; pas de sortie d’outils, pas de raisonnement, pas de contexte caché, pas de messages annulés ; la copie de la discussion parente dans une discussion dérivée est laissée de côté ; au plus environ 16 000 caractères) et les notes enregistrées au modèle de la discussion, en une seule requête sans outils. Les notes sont des fichiers Markdown dans `$DSH_HOME/storages/dsh-composer-plus/memory/` (fichiers réservés au propriétaire) : `projects/<id>/` pour chaque dossier de projet (`<id>` est un hash du chemin réel du dossier ; `project.json` indique le dossier), `global/`, `journal.jsonl` (chaque modification avec la ligne avant et après) et `reviewed.json` (jusqu’où chaque discussion a été lue). Rien n’est écrit dans le dossier du projet. Les notes qui ressemblent à une clé, un jeton, un mot de passe ou un numéro d’identité sont refusées. Les notes d’un projet entrent dans le prompt système de chaque nouvelle discussion de ce dossier : elles vont donc au modèle avec chaque requête de cette discussion. L’interrupteur est dans `memory.json`, au même endroit. **Ouvrir la mémoire** n’envoie rien tant que vous ne cliquez pas sur **Aperçu des modifications** ; ensuite, il envoie les notes affichées et votre texte au modèle par défaut de dsh, en une seule requête sans outils. Les modifications ne sont écrites qu’avec **Appliquer**, avec `editor` dans le journal. Tether lit et modifie les notes par la même route.
164
176
  - **Sauvegarde :** rien ne quitte votre machine. Les archives vont dans `~/Desktop/dsh-backups` (fichiers réservés au propriétaire). Les secrets ne sont pas dans une archive : les fichiers d’identifiants (`.credentials.yaml`, `.env`), les fichiers de clés (`.pem`, `.key`, `.p12`, `.pfx`) et les valeurs des réglages token, secret, password et clé d’API des fichiers yml sont masqués ; leurs vraies copies restent dans `composer-plus-vault/<archive>/`, dans le même dossier (réservé au propriétaire), sur cet ordinateur uniquement. **Pour un autre ordinateur** ne copie aucun vault : saisissez de nouveau ces secrets là-bas. Vos journaux de discussion, vos réglages et le reste du dossier personnel de dsh sont dans l’archive tels quels : gardez le dossier privé, comme `$DSH_HOME` lui-même. La sauvegarde lit les fichiers avec `O_NOFOLLOW | O_NONBLOCK` ; un lien symbolique est enregistré comme lien (jamais suivi) et une FIFO ou un périphérique est ignoré. L’interrupteur et les réglages de la sauvegarde automatique sont dans `$DSH_HOME/storages/dsh-composer-plus/auto-backup.json`, l’interrupteur de la console de secours dans `rescue-console.json`, et pendant que dsh tourne, `running/host-<pid>.json` désigne chaque processus dsh (la console de secours les lit pour refuser une restauration).
165
177
  - **Console de secours :** un menu dans un terminal ; elle n’ouvre aucun port réseau. Une restauration écrit uniquement dans un nouveau dossier à côté du dossier personnel de dsh (fichiers avec `O_EXCL | O_NOFOLLOW`, liens symboliques en dernier et jamais suivis) et refuse une archive qui contient un nom dangereux (`..`, un chemin absolu), un périphérique ou une FIFO, plus d’un dossier de premier niveau ou une entrée sous un lien.
166
178
 
@@ -182,7 +194,7 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
182
194
  - **Pas de pastille de branche sur une ligne de discussion :** la discussion n’a eu aucun tour depuis que vous avez installé cette version, son dossier n’est pas un dépôt git, ou **Branche Git sur les lignes de discussion** est désactivée. Après une mise à jour, redémarrez dsh (la partie hôte enregistre la branche).
183
195
  - **Vérification de l’objectif indique que le test s’est terminé avec le code 127 ou « not found » :** dsh démarré depuis le Finder ou le Dock peut avoir un PATH plus court que votre terminal : il ne trouve donc pas `npm`, `pnpm` ou `cargo`. Démarrez dsh depuis un terminal, ou définissez votre propre commande de test avec le chemin complet sous **Vérification de l’objectif** → **Modifier**. **Lancer maintenant** affiche le résultat tout de suite.
184
196
  - **L’objectif ne se ferme pas et l’agent continue de travailler :** **Vérification de l’objectif** a trouvé un test en échec ou du travail manquant ; la ligne sous l’objectif indique pourquoi (survolez le résultat pour voir les détails). Corrigez la cause ou la commande de test, ou terminez l’objectif vous-même avec `/goal` ou la barre de l’objectif (ce n’est pas vérifié).
185
- - **L’installation échoue juste après une nouvelle version :** ajoutez la version (`dsh-composer-plus@1.16.1`) ; voir la note d’installation plus haut.
197
+ - **L’installation échoue juste après une nouvelle version :** ajoutez la version (`dsh-composer-plus@1.18.0`) ; voir la note d’installation plus haut.
186
198
  - **Sauvegarder maintenant indique « Une autre action de sauvegarde est en cours » :** une action tourne dans une autre fenêtre de dsh ou dans la console de secours (elles partagent un fichier de verrou, `.composer-plus.lock`, dans le dossier de sauvegarde). Attendez qu’elle se termine. Si aucune action ne tourne, le verrou d’un processus fermé est repris au clic suivant.
187
199
  - **La console de secours indique « dsh is running » :** quittez d’abord dsh. Si dsh est vraiment fermé, le fichier nommé dans le message reste d’un plantage : supprimez-le et réessayez.
188
200
  - **Après une restauration, dsh ne démarre pas ou un plugin manque :** les paquets de plugins d’un profil doivent être réinstallés. La console de secours le propose après une restauration ; sinon, exécutez `pnpm install` dans chaque dossier sous `$DSH_HOME/profiles/` qu’elle liste. Les secrets qui n’étaient pas dans le vault (autre ordinateur) doivent être saisis de nouveau : la console les liste.
@@ -205,6 +217,7 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
205
217
  - **Autoriser pour cette discussion** compte la limite de temps à partir du moment de l’autorisation. Une nouvelle limite de temps s’applique tout de suite aux autorisations en cours : une limite plus courte peut donc y mettre fin tout de suite. Les autorisations des versions 1.12 et antérieures n’ont pas d’heure : après la mise à jour, l’agent redemande une fois pour ces outils.
206
218
  - **Garder le focus dans la zone de saisie** ne rend le focus qu’après une commande `/` ou une compétence. Pendant que dsh résout la commande, la zone de saisie reste en lecture seule pendant quelques millisecondes : les touches tapées pendant ce temps sont perdues. Si le menu `/` de dsh est encore ouvert, `Enter` choisit la ligne en surbrillance et n’envoie pas le message.
207
219
  - **Adapter la carte de question à la fenêtre** ne modifie que la carte de question de dsh, pas la carte de revue du plan. Elle trouve la carte grâce au balisage de dsh (`data-question-key`, `data-question-scroll`) ; si une mise à jour de dsh change ce balisage, la carte s’affiche comme dsh la dessine. La hauteur de la carte suit la fenêtre, pas la conversation : dans une conversation affichée dans un panneau latéral étroit, une carte haute peut encore dépasser le haut de la conversation.
220
+ - **Adapter l’en-tête de la conversation à la fenêtre** trouve l’en-tête de la conversation de dsh par ses noms de classe générés (`_titleRow`, `_titleCluster`, `_crumbs`, `_headerActions`, `_headerUtilities`), car dsh n’offre pas de point d’accroche pour sa mise en page. Si une mise à jour de dsh les renomme, l’en-tête s’affiche comme dsh le dessine. Dans une colonne de conversation très étroite, l’en-tête peut prendre deux ou trois lignes, et la zone au-dessus des messages devient plus basse.
208
221
  - **Connexion mobile** ne fonctionne que sur macOS (elle utilise `en0`, `openssl`, `swift` et `dns-sd`). Elle utilise les ports fixes 19390 et 19391 : un seul dsh par Mac peut donc l’exécuter à la fois (chaque Mac est une entrée dans la liste des Mac du téléphone). Le téléphone ne reçoit des notifications que lorsque Tether est ouvert ou vient de passer en arrière-plan (pas de service push). Tether ne les envoie qu’après que vous avez activé « Settings → Notifications → Send notifications » dans Tether. Cette option est désactivée par défaut, et iOS demande l’autorisation quand vous l’activez. L’app iOS n’est pas encore sur l’App Store : compilez-la depuis `tether/ios` avec Xcode. « Tailscale only » demande quand même une adresse Wi-Fi ou Ethernet sur le Mac (la passerelle ne démarre qu’avec une telle adresse). Le journal d’accès est propre à chaque Mac et ne garde que les 200 tentatives les plus récentes ; une tentative répétée en moins d’une minute augmente de un le compteur de la même ligne. Le verrouillage de Tether ne masque pas les aperçus des notifications sur l’écran verrouillé de l’iPhone : désactivez-les dans les Réglages d’iOS. Les points verts de Tether suivent le Mac : une conversation que vous ouvrez dans dsh perd aussi son point sur le téléphone. Une conversation que vous ouvrez dans Tether perd son point seulement sur les téléphones. Le point de dsh sur le Mac reste jusqu’à ce que vous ouvriez la conversation sur le Mac.
209
222
  - Un lien de session fonctionne dans les discussions ; un clic dessus n’ouvre pas la discussion. Un lien créé avec **Copier le lien du message** n’ouvre son message que sur dsh 0.2.1 et versions ultérieures, et seulement depuis un message dans une discussion (dsh 0.2.0 n’a pas de règles de texte utilisateur : le lien y est copié, mais s’affiche comme texte simple). Un message qu’une annulation a retiré, ou que la compaction a enlevé de l’historique que dsh charge, ne peut pas être affiché : le lien le dit alors. Les boutons 🔗 s’attachent aux lignes de message de dsh ; si une mise à jour de dsh change ce balisage, ils ne s’affichent pas.
210
223
  - **Tout marquer comme lu** change les points non lus de dsh lui-même par une partie de dsh qui n’est pas une API publique (la liste `completionUnread` de l’état des sessions de dsh). Si une mise à jour de dsh la renomme, l’élément ne s’affiche pas. L’élément va dans le menu « … » du projet de dsh, qui n’a pas d’emplacement pour les plugins ; si dsh change ce menu, l’élément ne s’affiche pas non plus.
@@ -219,7 +232,7 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
219
232
  - **Une branche par discussion** : quand le dossier de branche d'une discussion (`<project>/.worktrees/<name>`) est supprimé, par exemple quand l'agent de la discussion retire le worktree et supprime la branche, l'étape suivante de la discussion la sort de ce dossier. Le projet du dossier de branche disparaît de la barre latérale, et la discussion apparaît sous Sans groupe et reste ouverte. Avec dsh 0.2.1 et plus, la discussion continue dans le dossier principal du projet, et le modèle reçoit une note sur le nouveau dossier. Avec dsh 0.2.0, la discussion garde le dossier supprimé : une commande y échoue jusqu'à ce que vous commenciez une nouvelle discussion. Le projet d'une branche supprimée qu'aucune discussion n'utilise disparaît aussi de la barre latérale : Composer Plus vérifie les dossiers de branche au démarrage et toutes les 30 secondes, aussi sans filtre de la barre latérale. Pendant qu'une discussion se déplace, **Nouvelle branche** dans le même dépôt répond « réessayez ». Interrupteur désactivé, l'erreur de dsh revient (« working-directory: directory does not exist »).
220
233
  - **Branches dans l’arborescence des espaces de travail** écrit dans git sans clic : quand il déplace une discussion, il remet le dossier du projet sur sa branche précédente (`git switch`) et ajoute un worktree (`git worktree add`). Il ne supprime jamais une branche, un worktree ni un fichier. dsh ne peut pas changer le dossier d’une discussion : une discussion déplacée est donc une copie (le fork propre à dsh, avec un nouvel id) et l’ancienne discussion est archivée. La copie reprend la tâche arrêtée ; un appel d’outil en cours quand la branche est apparue se termine par un refus, et l’agent le relance dans le nouveau dossier. Un objectif de l’ancienne discussion ne suit pas. Seule une discussion dont le dossier est le dossier principal du dépôt est déplacée, et seulement pour une branche qu’elle a créée et sur laquelle elle est passée pendant ce tour (`git switch -c`, `git checkout -b`) : une branche créée avec `git branch` seul, un dossier avec des modifications non validées, un worktree lié ou un sous-dossier ne déplacent rien. Seuls les worktrees placés directement dans `<project>/.worktrees/` et liés à une branche apparaissent dans l’arborescence ; un worktree détaché ou placé ailleurs n’apparaît pas. La copie ne s’ouvre d’elle-même que si sa discussion était celle qui était ouverte (le plugin le lit dans la ligne de la barre latérale de dsh) ; sinon, elle est dans le projet de la branche.
221
234
  - **Rechercher dans la discussion** ne cherche que dans ce que la page affiche : les messages et les réponses chargés (faites défiler vers le haut ou cliquez sur **Charger les précédents** pour les plus anciens), ni dans les étapes d’outil fermées, ni dans le texte replié de la sortie d’un outil. La recherche compte au plus 2 000 résultats (puis « 2000+ »). Elle utilise l’API de surlignage du navigateur (Chromium 105 et plus récent ; l’app de bureau l’a) : dans un navigateur plus ancien, le compteur et les déplacements fonctionnent sans la couleur. `Cmd+F` sur un Mac (`Ctrl+F` sous Windows et Linux) ne l’ouvre que lorsqu’une discussion est à l’écran ; ailleurs, la recherche du navigateur fonctionne comme avant. Sur un Mac, `Ctrl+F` garde son rôle macOS dans les champs de texte (le curseur avance d’un caractère).
222
- - **Ouvrir la discussion en attente en cas d’inactivité** ne connaît que ce que voit la fenêtre de dsh : le travail dans une autre app ne compte pas, donc quand dsh est en arrière-plan, elle peut ouvrir une discussion en attente au bout de 30 secondes. Elle ne fait pas passer dsh au premier plan. Lire sans toucher une touche, cliquer ni bouger la souris compte comme de l’inactivité. Elle ne regarde que les discussions avec le point orange de dsh (une question, une approbation ou une revue du plan) ; la demande d’un sous-agent s’affiche dans sa discussion parente. Tant qu’une discussion en attente est à l’écran, aucune autre ne s’ouvre ; une discussion quittée sans réponse peut se rouvrir après les 30 secondes suivantes sans utilisation. Les 30 secondes ne sont pas modifiables.
235
+ - **Ouvrir la discussion en attente en cas d’inactivité** ne connaît que ce que voit la fenêtre de dsh : le travail dans une autre app ne compte pas, donc quand dsh est en arrière-plan, elle peut ouvrir une discussion en attente au bout de 30 secondes. Elle ne fait pas passer dsh au premier plan. Lire sans toucher une touche, cliquer ni bouger la souris compte comme de l’inactivité. Elle ne regarde que les discussions avec le point orange de dsh (une question, une approbation ou une revue du plan) ou avec son point vert (un tour terminé que vous n’avez pas encore ouvert) ; la demande d’un sous-agent s’affiche dans sa discussion parente. Les discussions orange s’ouvrent d’abord. Ouvrir une discussion verte retire son point, donc les 30 secondes de la discussion verte suivante ne commencent qu’après votre prochaine touche, clic, mouvement de souris, molette ou toucher : quand vous revenez, les autres points verts sont toujours là. Tant qu’une discussion en attente est à l’écran, aucune autre ne s’ouvre ; une discussion quittée sans réponse peut se rouvrir après les 30 secondes suivantes sans utilisation. Les 30 secondes ne sont pas modifiables.
223
236
  - Une notification envoyée avant un redémarrage ne fait que ramener dsh au premier plan quand vous cliquez dessus.
224
237
  - Les projets actifs sont déplacés avec l’ordre des projets enregistré par dsh : le nouvel ordre est donc conservé après un redémarrage. Les discussions hors de tout projet (« Sans groupe ») ne peuvent pas être déplacées ; dsh les liste toujours en dernier.
225
238
  - dsh n’a pas de point d’extension dans le menu des options d’affichage de la barre latérale : l’option des projets récents est donc ajoutée au menu de dsh lui-même. Si une mise à jour de dsh change ce menu, l’option n’apparaît pas et tous les projets restent visibles. Le filtre agit sur les lignes de projet : **Dans une seule liste** n’est donc pas filtré. Dans **Arborescence des espaces de travail**, un dossier parent reste affiché tant qu’un projet qu’il contient est actif, et les lignes de discussion qui n’ont pas été actives au cours des 2 dernières heures sont masquées aussi ; dans **Espace de travail**, seules les lignes de projet sont filtrées. Le filtre lit la vue que dsh affiche dans le réglage de vue enregistré par dsh (pas une API publique) ; si une mise à jour de dsh le renomme, **Arborescence des espaces de travail** est filtrée comme **Espace de travail**. La fonction Statut du projet lit le même réglage : dans **Arborescence des espaces de travail**, la ligne d’un dossier parent compte aussi les discussions des projets qu’il contient ; si dsh renomme ce réglage, chaque ligne n’affiche que ses propres discussions. **Par état** a le même type de limite : dsh n’a pas d’emplacement pour l’ordre, donc l’élément de menu et l’ordre des lignes s’attachent au balisage du menu et de la liste de dsh.
@@ -228,10 +241,16 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
228
241
  - dsh n’a pas non plus de point d’extension qui choisit où s’ouvre **Nouvelle session**. **Espace de travail par défaut pour Nouvelle session** enveloppe une méthode de dsh qui n’est pas une API publique (`startSession` du service d’espaces de travail de dsh). Si une mise à jour de dsh la renomme, **Nouvelle session** s’ouvre là où dsh le choisit (le projet ouvert ou le plus récent). Tout appel qui ne nomme pas de projet utilise la valeur par défaut : le bouton de la barre latérale, son raccourci, le logo et aussi **Nouvelle** sur la page **Tâches d’automatisation**. dsh rouvre toujours la dernière discussion au démarrage. Le dossier général est créé et ajouté à vos projets à la première utilisation ; sous Windows ou Linux avec un dossier Documents déplacé, il peut être différent du dossier de dsh.
229
242
  - dsh n’a pas non plus de point d’extension pour une indication dans la zone de saisie : le texte de **Prédiction du message suivant** se place donc sur le texte indicatif de dsh (`[data-composer-placeholder]`). Si une mise à jour de dsh change ce balisage, aucune prédiction ne s’affiche. Tant qu’elle est activée, chaque tour terminé coûte un court appel au modèle.
230
243
  - **Compléter pendant la saisie** affiche son texte au moyen de l’indication de saisie propre à dsh (le style `--dsh-composer-hint` que dsh utilise pour l’indication d’argument d’une commande slash). Cette fonctionnalité ne s’exécute pas pour une commande slash, un message avec une pastille de fichier ou de symbole, ou quand le curseur n’est pas à la fin du message. Si une mise à jour de dsh change ce style, aucune complétion ne s’affiche. Chaque pause pendant la saisie coûte un appel au modèle.
231
- - **Améliorer le prompt** ne voit qu’un court résumé du projet, les chemins modifiés et les chemins dont le nom correspond à vos mots : pas le code lui-même. Il peut donc manquer le bon fichier, et il ne cite que les chemins qu’il a reçus. Relisez le nouveau texte avant de l’envoyer. Il ne s’exécute pas pour une commande slash ni pour un message avec une pastille de fichier ou de symbole (le nouveau texte est du texte brut : la pastille serait perdue), et un message peut avoir au plus 8 000 caractères. Les images restent jointes : seul le texte change. Chaque clic coûte un appel au modèle ; un modèle puissant peut prendre une minute (`Esc` annule).
232
- - **Vérification de l’objectif** ne vérifie qu’un achèvement que l’agent fait lors d’une itération automatique de l’objectif : un achèvement que vous demandez dans la discussion, `/goal` et la barre de l’objectif ne sont pas vérifiés. L’agent peut modifier lui-même les tests ou les fichiers de la commande de test ; le vérificateur lit la discussion et peut le voir, mais il peut se tromper dans les deux sens (un « pas terminé » erroné coûte une itération de plus ; un « terminé » erroné ferme l’objectif). Le vérificateur voit la discussion et `git status`, pas le code lui-même. Une exécution de test n’est réutilisée que quand la dernière étape de l’agent capable de modifier des fichiers était sa propre exécution `bash` réussie d’exactement la même commande dans le même dossier ; une commande avec un pipe (`| tail`) ou `&&` n’est pas réutilisée. Le budget est mesuré à la fin d’un tour : un tour peut donc le dépasser. Seuls les appels au modèle de la discussion elle-même comptent (pas ceux de ses sous-agents). `update_goal` attend pendant la vérification (le test 15 minutes au plus, le vérificateur 3 minutes au plus). Une duplication de session reçoit un nouvel id de discussion : elle démarre donc sans la commande de test ni les limites propres de la discussion parente. Chaque achèvement qui atteint le vérificateur coûte un appel au modèle.
244
+ - **Améliorer le prompt** ne voit qu’un court résumé du projet, les chemins modifiés et les chemins dont le nom correspond à vos mots : pas le code lui-même. Il peut donc manquer le bon fichier, et il ne cite que les chemins qu’il a reçus. Relisez le nouveau texte avant de l’envoyer. Il ne s’exécute pas pour une commande slash autre que `/goal <objectif>`, pour un mot de contrôle de `/goal` (`clear`, `pause`, `resume`) ni pour un message avec une pastille de fichier ou de symbole (le nouveau texte est du texte brut : la pastille serait perdue), et un message peut avoir au plus 8 000 caractères. Pour un objectif `/goal`, il n’écrit des conditions qu’à partir du brouillon et du contexte ; une condition trop stricte peut coûter des itérations de l’objectif : relisez-la donc avant de l’envoyer. Les images restent jointes : seul le texte change. Chaque clic coûte un appel au modèle ; un modèle puissant peut prendre une minute (`Esc` annule).
245
+ - **Vérification de l’objectif** ne vérifie qu’un achèvement que l’agent fait lors d’une itération automatique de l’objectif : un achèvement que vous demandez dans la discussion, `/goal` et la barre de l’objectif ne sont pas vérifiés. L’agent peut modifier lui-même les tests ou les fichiers de la commande de test ; le vérificateur lit la discussion et peut le voir, mais il peut se tromper dans les deux sens (un « pas terminé » erroné coûte une itération de plus ; un « terminé » erroné ferme l’objectif). Le vérificateur voit la discussion et `git status`, pas le code lui-même. Une exécution de test n’est réutilisée que quand la dernière étape de l’agent capable de modifier des fichiers était sa propre exécution `bash` réussie d’exactement la même commande dans le même dossier ; une commande avec un pipe (`| tail`) ou `&&` n’est pas réutilisée. Le budget est mesuré à la fin d’un tour : un tour peut donc le dépasser. Le budget de tokens compte aussi les appels des discussions de sous-agents de la discussion (lus dans leurs journaux enregistrés à la fin de chaque tour : une discussion avec beaucoup de sous-agents prend donc un peu plus de temps à vérifier). Le tableau des preuves vient de la propre lecture de la discussion par le vérificateur : une partie qu’il dit vérifiée demande encore votre propre regard quand elle compte. `update_goal` attend pendant la vérification (le test 15 minutes au plus, le vérificateur 3 minutes au plus). Une duplication de session reçoit un nouvel id de discussion : elle démarre donc sans la commande de test ni les limites propres de la discussion parente. Chaque achèvement qui atteint le vérificateur coûte un appel au modèle.
246
+ - **Fichiers protégés** est un garde-fou, pas un sandbox. Il couvre les outils de fichiers de dsh lui-même (`read`, `read_image`, `grep` sur un fichier, `write`, `edit`, `str_replace_editor`). Une commande shell (`cat .env`), un script que l’agent écrit, le shell d’un sous-agent, un outil MCP, une liste `glob` et un `grep` sur tout un dossier peuvent encore atteindre un fichier protégé. Pour une vraie limite, utilisez les modes sandbox de dsh ou gardez les secrets hors du dossier du projet. Les motifs connaissent `*`, `**` et `?`, pas `{a,b}` ni `[ab]`, et ils ignorent la casse.
247
+ - **Commandes bloquées** est un garde-fou, pas un sandbox. Il lit seulement le texte de la commande des outils `bash` et `pwsh` de dsh. Une variable ou un alias qui nomme la commande (`CMD=npm; $CMD publish`), une fonction shell, un fichier de script que l’agent écrit, un autre programme (`python -c`, `node -e`, `make`), un outil MCP et votre propre terminal peuvent encore l’exécuter. Une règle peut correspondre à plus de choses que vous ne le voulez : n’importe quel mot d’une commande peut être le nom de la commande (`echo npm publish` correspond à `npm publish`), et d’autres mots peuvent se placer entre les mots de la règle (`git push --force` correspond aussi à `git push origin main --force`). Allongez une règle quand elle correspond à trop de choses. **demander d’abord** a besoin d’une discussion qui peut demander : dans une discussion dont la politique d’approbation est never (par exemple un sous-agent délégué), dsh ne peut pas afficher la carte, donc l’appel est refusé avec la raison. La carte d’approbation affiche la raison en anglais. **Autoriser pour cette discussion** ne répond pas à une carte **demander d’abord**.
248
+ - **Continuer dans une nouvelle discussion** envoie la discussion (messages, appels d’outils et la fin de chaque résultat d’outil, environ 60 000 caractères au plus, la partie la plus récente) au modèle de la discussion elle-même. La note de passation peut manquer une décision ou un fichier : relisez-la avant de lancer. La nouvelle discussion ne connaît que la note et la discussion liée (dsh joint l’ancienne discussion comme contexte en lecture seule) ; son contexte du modèle commence petit, et l’ancienne discussion reste telle quelle. Une seule note ou un seul lancement par discussion à la fois.
249
+ - **Répartition du contexte** affiche des estimations avec la règle de dsh lui-même (environ 4 caractères par token), la même règle que l’anneau de contexte de dsh ; le décompte du modèle lui-même peut être différent. Les définitions des outils sont celles de la requête la plus récente. Elle affiche le contexte tel que le journal de la discussion le contient ; un tour en cours apparaît après sa prochaine étape.
250
+ - **Étapes planifiées** n’économise des jetons que si le modèle planifie : tant qu’elle est activée, chaque requête porte l’outil `plan_next_steps` et une courte consigne (environ 500 jetons), aussi dans les discussions où le modèle ne planifie jamais. Une condition prouve seulement ce qu’elle dit (par exemple : le code de sortie de la compilation était 0), pas que le travail est juste. `ok` lit les marques de résultat propres à dsh (`[exit code: N]`, délais dépassés, refus du sandbox) ; une commande qui échoue sans code de sortie non nul passe. Les étapes s’exécutent une à la fois ; deux étapes prêtes en même temps reviennent au modèle. Le message de l’étape est enregistré comme un message d’assistant du modèle de la discussion (dsh n’a pas de marque pour un message écrit par un plugin), donc son texte indique que Composer Plus l’a exécutée. Pas dans Tether.
251
+ - **Tableau des tâches** ne connaît que les projets de dsh : une discussion hors d’un projet affiche **Tous les projets**, et le dossier d’une branche par discussion (`<project>/.worktrees/<name>`) compte comme son projet. Les id de projet (`acme#12`) viennent du nom du dossier et ne changent pas quand vous renommez le projet dans dsh. La règle « tenir le tableau à jour » n’entre dans une discussion que si son projet a des tâches ouvertes ; une discussion qui l’a reçue la garde. On demande aux agents de vous laisser **Terminé**, **En attente** et les tâches manuelles, mais les outils ne le refusent pas : un agent peut encore déplacer une telle carte. Les outils du tableau sont dans la liste d’outils de chaque discussion tant que la fonction est activée (environ 1 000 tokens par requête) ; désactivez-la si vous n’utilisez pas le tableau. La page lit le tableau toutes les 2 secondes tant qu’elle s’affiche ; un changement fait par un agent apparaît dans ce délai. Un texte que vous modifiez pendant qu’un agent change le même champ n’est pas enregistré : le panneau affiche le nouveau texte et la raison. Pas d’images, pas de synchronisation git entre ordinateurs et pas de partage par le réseau (Kanzo les propose). L’idée et l’apparence viennent de [Kanzo](https://github.com/emanuele-em/kanzo) par emanuele-em (AGPL-3.0) ; Composer Plus n’en utilise aucun code.
233
252
  - **Priorité au message envoyé après Arrêter** n’agit qu’après l’arrêt de la discussion (ou après un tour qui a échoué, ou à l’ouverture d’une discussion qui a encore une file) : un message envoyé pendant qu’un tour s’exécute attend toujours à la fin de la file. Il ne passe que devant vos propres messages en file : si un tour d’objectif ou une réponse à une question attend dans la file, l’ordre de dsh reste. Il lit une partie de dsh qui n’est pas une API publique (si le tour arrêté est encore en train de se terminer) ; si une mise à jour de dsh la renomme, le message ne passe devant qu’une fois ce tour terminé. Les discussions de sous-agents gardent l’ordre de dsh.
234
- - **Mémoire du projet** appartient au premier dossier de la discussion (le dossier de projet de dsh) : une discussion qui change de dossier avec `cd` garde la mémoire de son premier projet, et le même dossier ouvert par un autre chemin vers les mêmes fichiers la partage. Une discussion fige sa section de mémoire à son début : une note enregistrée plus tard apparaît donc à partir de la discussion suivante (`memory_recall` la trouve tout de suite). La revue garde seulement ce que le modèle décide de garder : elle peut manquer un fait ou en garder un faux ; ouvrez les fichiers pour les vérifier, et modifiez-les ou supprimez-les à la main quand dsh est fermé. Chaque tour terminé avec un message de vous coûte un appel au modèle ; un appel en échec relit les mêmes messages après le tour suivant. Les discussions de sous-agents ne sont pas revues. L’idée et le format de fichier viennent de [DS Bot](https://github.com/Fei2411/DS-Bot) (Apache-2.0) ; Composer Plus n’utilise pas son code et ne lit ni n’écrit jamais la mémoire propre de DS Bot.
253
+ - **Mémoire du projet** appartient au premier dossier de la discussion (le dossier de projet de dsh) : une discussion qui change de dossier avec `cd` garde la mémoire de son premier projet, et le même dossier ouvert par un autre chemin vers les mêmes fichiers la partage. Une discussion fige sa section de mémoire à son début : une note enregistrée plus tard apparaît donc à partir de la discussion suivante (`memory_recall` la trouve tout de suite). La revue garde seulement ce que le modèle décide de garder : elle peut manquer un fait ou en garder un faux ; vérifiez-les dans **Ouvrir la mémoire** et modifiez-les là, ou modifiez les fichiers à la main quand dsh est fermé. **Ouvrir la mémoire** envoie les notes du projet sélectionné et les notes globales (tous les projets quand vous sélectionnez Toutes les notes ; au plus environ 60 000 caractères, le reste est seulement compté et ne peut pas changer dans cette demande) et votre texte au modèle par défaut de dsh, pas au modèle de la discussion. Un aperçu est gardé sur le Mac 30 minutes et jusqu’au redémarrage de dsh ; si une revue ou l’agent modifie les notes entre-temps, **Appliquer** refuse et vous redemandez un aperçu. **Appliquer** enregistre toutes les modifications d’un aperçu ou aucune : si une modification ne peut pas être enregistrée (par exemple, MEMORY.md est plein), les notes restent telles quelles et la raison s’affiche. Chaque tour terminé avec un message de vous coûte un appel au modèle ; un appel en échec relit les mêmes messages après le tour suivant. Les discussions de sous-agents ne sont pas revues. L’idée et le format de fichier viennent de [DS Bot](https://github.com/Fei2411/DS-Bot) (Apache-2.0) ; Composer Plus n’utilise pas son code et ne lit ni n’écrit jamais la mémoire propre de DS Bot.
235
254
  - **Sauvegarde** utilise un seul dossier fixe, `~/Desktop/dsh-backups` (celui de dsh-backup par défaut, pour que ses archives restent utilisables) ; aucun réglage ne permet un autre dossier. Une archive est à peu près aussi grande que le dossier personnel de dsh sans `cache/` ni `dsh-runtimes/` (mesuré : 1,6 Go de fichiers ont donné une archive de 830 Mo en environ 30 s sur Apple Silicon ; dsh est resté réactif). Un fichier qui change pendant sa lecture est enregistré tel qu’il était quand la sauvegarde l’a ouvert : le journal d’une discussion ouverte peut donc se terminer par un enregistrement coupé, que dsh répare à sa prochaine écriture. Le masquage trouve un secret dans un fichier yml par le nom de sa clé sur une ligne (`token:`, `apiKey:`, …) ; un secret dans une map de flux (`{token: x}`), dans une liste sous une telle clé, dans un fichier JSON (par exemple l’`apiKey` d’un serveur MCP dans un fichier `.json`) ou sous un autre nom reste dans l’archive. Les archives par type de dsh-backup (`dsh-t-…`) ne sont pas listées. **Pour un autre ordinateur** copie l’archive (un clone sur APFS : aucun espace en plus) ; le vault ne la suit pas. **Sauvegarder maintenant** ne supprime aucune sauvegarde. Une sauvegarde automatique conserve les sauvegardes les plus récentes faites par Composer Plus (le réglage **Conserver** de **Sauvegarde automatique**) et supprime ses sauvegardes plus anciennes ; les instantanés d’avant une mise à niveau sont comptés à part (les 2 plus récents restent). Les archives de dsh-backup ne sont jamais supprimées : retirez-les avec **Supprimer**. Tant que dsh-backup est encore installé, il compte les archives de Composer Plus dans son propre nombre de copies conservées et peut les supprimer.
236
255
  - **Restaurer** ne fonctionne que dans la console de secours, quand dsh est fermé : cela remplace tout le dossier personnel de dsh. L’ancien reste à côté sous le nom `.dsh.pre-restore-<time>` jusqu’à ce que vous le supprimiez : le disque doit donc avoir de la place pour les deux. Les discussions gardent les chemins de leurs projets : sur un autre ordinateur, un projet situé à un autre chemin apparaît comme manquant jusqu’à ce que vous l’ajoutiez de nouveau. Les liens symboliques qui pointent hors du dossier personnel de dsh (par exemple des compétences liées depuis un autre dossier) reviennent comme liens ; leurs cibles doivent exister sur cet ordinateur.
237
256
  - **Vérification des journaux de session** lit le journal le plus récent de chaque discussion avec les propres règles de dsh sur ce qui s’ouvre : une ligne qui n’est pas du JSON ou qui n’est pas dans l’ordre ne compte comme un dommage que si une fin de tour vient après elle (sinon dsh ouvre la discussion sans les lignes à partir de là, donc elle n’est pas listée). Elle ne vérifie pas les événements d’un journal par rapport aux règles d’événements de dsh lui-même : un journal qu’elle juge sain peut donc quand même ne pas s’ouvrir après une mise à niveau de dsh. Une réparation prend la copie d’une sauvegarde : les messages postérieurs à cette sauvegarde sont perdus pour cette discussion (le fichier endommagé reste à côté). Une discussion ouverte dans ce dsh n’est pas réparée dans les Réglages : dsh la détient.
@@ -264,7 +283,9 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
264
283
 
265
284
  **L’agent peut-il arrêter de marquer son propre travail comme terminé, comme avec les boucles de vérification de la loop engineering ?** Oui, avec **Vérification de l’objectif** (activée par défaut) : lancez un objectif avec `/goal`. Quand l’agent dit que l’objectif est terminé, les tests du projet s’exécutent et un appel indépendant au modèle vérifie l’objectif par rapport à la discussion ; si l’un des deux échoue, l’objectif reste ouvert et l’agent lit pourquoi. Définissez votre propre commande de test, une limite de temps ou une limite de tokens avec **Modifier** dans la ligne **Vérification de l’objectif** sous l’objectif.
266
285
 
267
- **L’agent peut-il retenir mes préférences d’une discussion à l’autre, comme la mémoire de DS Bot ?** Oui, avec **Mémoire du projet** (désactivée par défaut) : activez-la dans **Réglages → Composer Plus**. Après chaque tour, vos préférences et décisions durables sont gardées sous forme de notes courtes pour le projet de la discussion, et chaque nouvelle discussion de ce projet les lit. Demandez à l’agent de retenir quelque chose : il l’enregistre tout de suite.
286
+ **L’agent peut-il retenir mes préférences d’une discussion à l’autre, comme la mémoire de DS Bot ?** Oui, avec **Mémoire du projet** (désactivée par défaut) : activez-la dans **Réglages → Composer Plus**. Après chaque tour, vos préférences et décisions durables sont gardées sous forme de notes courtes pour le projet de la discussion, et chaque nouvelle discussion de ce projet les lit. Demandez à l’agent de retenir quelque chose : il l’enregistre tout de suite. Pour voir ou modifier les notes, cliquez sur **Ouvrir la mémoire** sur la même ligne et écrivez ce qu’il faut changer.
287
+
288
+ **Mes agents et moi pouvons-nous partager un même tableau des tâches, comme avec Kanzo ?** Oui, avec **Tableau des tâches** (activé par défaut) : ouvrez-le dans la barre latérale gauche et ajoutez des tâches avec **Nouvelle tâche**. Dans une discussion, demandez à l’agent de « prendre la tâche suivante du tableau » : il déplace la carte vers **En cours**, commente ce qu’il a fait et la déplace vers **En revue**. Marquez une tâche comme **Manuelle** pour la garder pour vous.
268
289
 
269
290
  **dsh peut-il sauvegarder mes discussions et mes réglages, comme dsh-backup ?** Oui : **Réglages → Composer Plus → Sauvegarde → Sauvegarder maintenant**. Il écrit le même format d’archive dans le même dossier (`~/Desktop/dsh-backups`) : les archives de dsh-backup s’affichent donc aussi et se restaurent, et vous pouvez supprimer dsh-backup. Activez **Sauvegarde automatique** pour des sauvegardes planifiées.
270
291
 
@@ -290,6 +311,8 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
290
311
 
291
312
  **Comment voir seulement les fichiers qu’une discussion a modifiés ?** Barre latérale droite → **Modifications** → **Cette discussion**. Cliquez sur **␣** pour masquer les modifications qui ne portent que sur des espaces.
292
313
 
314
+ **Comment empêcher l’agent d’exécuter `npm publish` ou `git push --force` ?** **Réglages → Composer Plus → Commandes bloquées** : tapez `npm publish`, choisissez **bloquer** ou **demander d’abord**, puis cliquez sur **Ajouter**. **bloquer** refuse la commande et l’agent vous consulte ; **demander d’abord** affiche la carte d’approbation à chaque fois. Fichiers protégés couvre les outils de fichiers de l’agent ; Commandes bloquées couvre ses commandes shell.
315
+
293
316
  **Comment empêcher la revue automatique de redemander pour le même outil dans une discussion ?** Cliquez sur **Autoriser pour cette discussion** sur la carte d’approbation. Cela couvre cet outil précis dans cette discussion seulement, pendant 1 heure par défaut ; révoquez l’autorisation depuis la pastille de l’en-tête. Changez la durée dans **Réglages → Composer Plus → Autoriser pour cette discussion**.
294
317
 
295
318
  **J’ai perdu mon iPhone. Comment l’empêcher d’accéder à mon Mac ?** Cliquez sur **Connexion mobile** en bas à gauche de la barre latérale, puis sur **Remove** à côté de cet iPhone. Sa clé cesse tout de suite de fonctionner ; il ne peut revenir qu’avec un nouvel appairage que vous approuvez sur le Mac.
@@ -304,7 +327,7 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
304
327
 
305
328
  **Comment recevoir des notifications macOS / Windows quand une tâche dsh se termine ou a besoin d’une approbation ?** Gardez **Notifications en arrière-plan** activée (c’est le réglage par défaut) et autorisez les notifications pour DeepSeek Harness dans les réglages du système.
306
329
 
307
- **dsh peut-il ouvrir tout seul la discussion qui me pose une question ?** Oui, avec **Ouvrir la discussion en attente en cas d’inactivité** (activé par défaut) : quand une discussion attend une réponse, une approbation ou une revue du plan et que vous n’utilisez pas dsh pendant 30 secondes, dsh l’ouvre. Pendant que vous tapez, faites défiler ou bougez la souris, il attend.
330
+ **dsh peut-il ouvrir tout seul la discussion qui me pose une question ?** Oui, avec **Ouvrir la discussion en attente en cas d’inactivité** (activé par défaut) : quand une discussion attend une réponse, une approbation ou une revue du plan et que vous n’utilisez pas dsh pendant 30 secondes, dsh l’ouvre. Une discussion qui a terminé un tour que vous n’avez pas encore lu (le point vert) s’ouvre de la même façon, après les orange. Pendant que vous tapez, faites défiler ou bougez la souris, il attend.
308
331
 
309
332
  **Comment passer l’interface de DeepSeek Harness en turc, en espagnol, en japonais… ?** Réglages → Composer Plus → **Langue de l’application**.
310
333
 
@@ -318,6 +341,8 @@ Testé sur dsh `0.2.0-rc.2` (bureau et web) et `0.2.1-rc.2` (web). La CI exécut
318
341
 
319
342
  **Puis-je envoyer une photo depuis mon iPhone ?** Oui. Dans une discussion Tether, touchez **+** à côté du champ de message → Camera, Photos (jusqu’à 4) ou Paste image. Les photos arrivent dans la discussion sur le Mac comme pièces jointes de votre message, donc le modèle les voit.
320
343
 
344
+ **dsh peut-il lancer la commande suivante sans redemander au modèle ?** Oui, avec **Étapes planifiées** (désactivée par défaut) : activez-la dans Réglages → Composer Plus. Le modèle peut alors planifier ses prochaines commandes avec une condition, par exemple « lance les tests quand la compilation réussit », et Composer Plus exécute une étape sans nouvel appel au modèle quand le résultat remplit la condition. Les approbations et le sandbox ne changent pas.
345
+
321
346
  **Est-ce que cela fonctionne avec l’app de bureau ?** Oui : Réglages → Plugins → **Ajouter un plugin** → `dsh-composer-plus`. Testé sur dsh 0.2.0-rc.2 (bureau et web) et 0.2.1-rc.2 (web).
322
347
 
323
348
  ## Développement
@@ -343,6 +368,8 @@ PLAYWRIGHT=/path/to/playwright node test/browser-readme-anchors.mjs
343
368
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-keep-focus.mjs /path/to/dsh/lib/bin.js
344
369
  # Fit question card to window (fake model asks a long question at 1280 × 820): question, answers, Skip and Submit readable, height follows the window + its thumbnail
345
370
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-question-fit.mjs /path/to/dsh/lib/bin.js
371
+ # Fit chat header to window (fake model, subagent + background jobs, branch pill, grants chip): no overlap from 1280 to 320 px, wide header unchanged + its thumbnail
372
+ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-header-fit.mjs /path/to/dsh/lib/bin.js
346
373
  # Mobile connect: switch on, QR popover, a fake iPhone pairs and calls dsh through the gateway, switch off + its thumbnail
347
374
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-mobile-connect.mjs /path/to/dsh/lib/bin.js
348
375
  # Resume after restart (fake slow model, real quit and start): a running chat and a goal continue, a stopped chat does not
@@ -380,6 +407,8 @@ PLAYWRIGHT=/path/to/playwright node test/browser-continue-queue.mjs /path/to/dsh
380
407
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-stop-send.mjs /path/to/dsh/lib/bin.js
381
408
  # Edit queued message in place with images and files (slow fake model) + its thumbnail
382
409
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-edit.mjs /path/to/dsh/lib/bin.js
410
+ # Task board: the page, the agent tools (fake model), drag and drop, search, the switch
411
+ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-task-board.mjs /path/to/dsh/lib/bin.js
383
412
  ```
384
413
 
385
414
  ```sh