- reprise lancée une fois en arrière-plan ; suivre et sleep refusés pendant l'attente - réveil lu par le plugin : résultat et conduite selon fin, gain compté à ce moment - lecture entière d'une sortie au verdict valide refusée, sauf chemins sensibles (réglage chemins_sensibles) - compteurs d'attentes, d'essais et d'échecs de contrôle dans /miam-economies - skill deleguer : controle, attendus, reprise et tableau des fin ; README et cahier à jour Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 KiB
Forcer la délégation par les hooks
État au 2026-11-02, base de travail du plugin. But : que Claude pilote et que MIAM, l'API ou Haiku écrivent. Claude découpe, confie, contrôle par des machines, et n'écrit lui-même que ce qui ne peut pas être confié.
1. Constat
MIAM (v2.5.2-dev, phase 2) sait déjà router : modèle local (27B, 15,5 Go, un seul à la fois), API OpenRouter
(plafond 2 /jour, ~0,0135 dépensés le 2026-11-02), OpenCode, et Haiku côté Claude. moteur="auto" choisit entre
local et API. Les moyens existent ; c'est Claude qui ne les utilise pas spontanément.
Journal : 185 délégations (165 ok, 10 refusées, 3 erreurs, 3 annulées, 4 rejetées), dont 9 API et 5 OpenCode. Par jour : 103 (30/10), 52, 19, 12 (02/11, journée en cours). La baisse n'est pas rapportée au volume de travail : elle alerte, elle ne prouve rien.
Session du 2026-11-02, tâche PH2-D1 : seule la lecture imposée par le hook de démarrage a été déléguée. 8 tests répétitifs écrits à la main alors que leur modèle était dans le fichier. Les délégations suivantes ont toutes suivi un rappel de l'utilisateur.
Pourquoi les hooks actuels n'ont pas suffi
| Mécanisme actuel | Ce qui a échappé |
|---|---|
Refus de Read si fichier ≥ 20 000 caractères sans limit ≤ 400 |
Contourné légalement : plusieurs plages de 75 à 240 lignes sur instances.py, allow_large sur des lignes géantes de tasks-P2.md |
| Retenue des sorties shell ≥ 20 000 caractères | Ne voit que la taille d'un appel, pas le cumul |
Rappel texte (1 toutes les 10 min), consigne prompt.compose, mémoire |
Coût nul pour Claude au moment de décider : ignorés |
Edit, Write, NotebookEdit |
Aucun contrôle : seule la comptabilité des corrections |
| Suivi « ce tour a délégué » | Non présent pour l'agent principal |
| Hooks de fin de tour et de soumission | Non présents |
Conclusion : une consigne perd face à la facilité. Il faut qu'écrire soi-même soit plus lent que déléguer, à l'instant où l'écriture est tentée.
Frictions côté délégation
deleguersansmoteuréchoue si aucun modèle n'est chargé ; il faut penser àmoteur="auto".- Le bench occupe le GPU ;
autolocal peut le préempter (corrigé pour les refus,093f110, pas pour le reste). plugin-claude-miamn'est pas autorisé pour l'API, et la config afficheprojets: nullpour OpenRouter (à éclaircir).- Un fichier hors projet (scratchpad) fait échouer le routage API.
- Rien n'oriente vers Haiku quand local et API sont indisponibles.
- Pas de contrôle automatique du résultat : Claude relit tout, ce qui annule une partie du gain.
2. Principes
- Refuser, pas rappeler. Un
denyau moment de l'écriture, avec l'appel prêt à copier dans le message. - Budget cumulé, pas seuil par appel. Compter lignes écrites et caractères lus par tour et par fichier.
- Découper avant d'écrire. Pas de code sans liste de bouts.
- La machine juge, Claude arbitre. Tests, ruff et contrat décident ; Claude ne lit qu'en cas d'échec.
- Une sortie de secours chère et visible. Exception motivée, journalisée, affichée.
- Ne jamais bloquer le travail. Si aucun exécutant ne répond, la règle s'ouvre et le signale.
3. Pistes de hooks
Seuils proposés, à régler sur les mesures.
| # | Hook | Déclencheur | Action | Priorité |
|---|---|---|---|---|
| 1 | Portillon tests | Write/Edit de l'agent principal sur tests/**, *.test.* ajoutant > 10 lignes |
deny + appel deleguer prêt |
P0 |
| 2 | Budget d'écriture | Cumul > 30 lignes de code ajoutées par l'agent principal depuis la dernière délégation réussie | deny jusqu'à une délégation ou une exception |
P0 |
| 3 | Portillon commit | git commit sans message issu de deleguer dans le tour |
deny |
P0 |
| 4 | Écritures par shell | Bash/PowerShell avec Set-Content, Out-File, >, sed -i, Python écrivant un fichier |
Comptés comme le hook 2 ; sinon le contournement est immédiat | P0 |
| 5 | Budget de lecture | Cumul par tour > 40 000 caractères, ou > 400 lignes par fichier, allow_large et Grep compris |
deny + « confie la question » |
P1 |
| 6 | Portillon découpage | Premier Edit/Write de code d'un tour sans plan |
deny : écrire .claude/miam-plan.json (section 4) |
P1 |
| 7 | Sélecteur d'exécutant | Tout deny ci-dessus |
Message calculé : local si prêt et sans bench ; API si projet autorisé ; sinon subagent Haiku | P1 |
| 8 | Bilan de fin de tour | Fin de tour de l'agent principal | Injecte lignes écrites par Claude et par délégation ; bloque la fin si un bout du plan reste « délégable » non traité | P2 |
| 9 | Compteur visible | Ligne d'état | délégué 82 % · exceptions 1 pour le tour et la session |
P2 |
| 10 | Docs et docstrings | *.md hors plan/, docstrings ajoutées en lot |
Comme le hook 1 | P2 |
| 11 | Attente unique | deleguer en file (ok: null avec reprise) ; commande /attendre lancée sans run_in_background |
Injecte « lance reprise en arrière-plan » ; deny sur l'appel au premier plan |
P0 |
| 12 | Pas de suivi pendant l'attente | suivre sur une demande attendue, sleep ou boucle d'attente en Bash |
deny : « tu seras réveillé à la fin » ; permis si fin vaut besoin_claude |
P0 |
| 13 | Confiance au verdict | Read complet du fichier sortie après fin: "valide" |
deny hors chemins sensibles : aperçu ou offset/limit |
P1 |
Hors comptage : fichiers écrits par MIAM (déjà mesurés en corrections), plan/** et journal de suivi,
modifications ≤ 3 lignes, subagents (agentId défini), config locale.
Exception : outil exception(raison, fichiers, lignes) avec motifs fermés (concurrence, securite,
debogage-multi-fichiers, secret). Elle ouvre un budget limité aux fichiers cités, est journalisée et apparaît dans le
bilan. Pour la concurrence, liste de chemins sensibles à définir plutôt qu'un jugement de Claude.
Repli : si aucun des trois exécutants ne répond, règle ouverte pour le tour et toast. Réutiliser joignable.
Options : garder imposer et incitation, ajouter budget_ecriture, budget_lecture, chemins_sensibles.
À vérifier avant de coder
- Existence d'un événement de fin de tour de l'agent principal capable de relancer Claude (
turn.completen'est utilisé que pour les subagents). - Capacité de
tool.callà lire le contenu deWrite/Editavant exécution pour compter les lignes. - Possibilité de déclarer
exception: outil MCP côté MIAM, ou fichier lu par le hook.
4. Découper en bouts atomiques
Plan attendu par le hook 6 :
{ "tache": "PH2-D1", "bouts": [
{ "id": 1, "quoi": "tests start_all", "fichier": "tests/x.py", "moteur": "auto", "modele": "tests/x.py:613-637",
"contrat": "4 instances, ordre d, b, c, erreurs par nom", "controle": "pytest -k start_all" },
{ "id": 2, "quoi": "ordre des réservations dans start_instance", "moteur": "claude", "motif": "concurrence" }
] }
Un bout délégable : une fonction ou un groupe de tests, un fichier de sortie, ≤ 80 lignes, signature donnée, exemple à imiter en plage de lignes, contrôle exécutable. Consigne en anglais, langue de sortie précisée. Modules joints, car le 27B invente champs et valeurs.
Relecture de D1 avec ce découpage :
| Bout | Exécutant possible |
|---|---|
Choix du port réservé, messages d'erreur, start_all, stop_all à partir de leur contrat |
Délégable, contrôlé par tests |
| 8 tests, tests du view model | Délégable, modèles présents |
| Boutons du dashboard, branchement du tray | Délégable, patron existant |
| Lignes de suivi, message de commit | Délégable |
Absence d'await entre contrôle et réservation dans start_instance |
Claude (concurrence) |
| Inventaire des fichiers à modifier | Délégable ; Claude lit le résultat |
Claude n'aurait gardé que le découpage, le point de concurrence et l'intégration.
5. Faire confiance aux retours
Contrôle par niveaux, du moins cher au plus cher :
- Automatique :
format="code",sortie=,retour="apercu"; pytest, ruff,ruff format --check. - Test rouge d'abord : le test échoue sans le code, passe avec.
- Taille du diff : conforme au bout annoncé.
- Lecture par Claude : seulement si un contrôle échoue, ou en zone sensible.
En cas d'échec, renvoyer la sortie du test à l'exécutant (2 essais) avant toute reprise par Claude.
Pièges connus du 27B à garder en contrôle : docstrings omises, valeurs inventées ; ajouter docstrings et champs aux contrôles plutôt qu'à la relecture.
Risque accepté : des erreurs passeront les tests. La parade est de meilleurs contrats, avec la revue par Claude réservée aux zones sensibles et au diff final.
5 bis. Contrôle automatique des réponses par MIAM
Livré dans MIAM (PH2-H11), sauf commande et perimetre ; contrat exact en section 11. But : Claude reçoit un verdict plutôt que le code ; MIAM juge, retente, escalade.
Contrat de la demande : nouveau paramètre optionnel controle sur deleguer.
| contrôle | s'applique à | ce qu'il vérifie |
|---|---|---|
format |
tous | JSON valide, schéma si fourni ; Python via ast.parse, TypeScript via transpile uniquement |
complet |
tous | non vide, non tronqué, symboles demandés présents (fonctions, nombre de tests) |
symboles |
code | chaque identifiant importé ou appelé existe dans les modules joints, pour attraper les champs inventés (faiblesse connue du 27B) |
docstrings |
code | fonctions publiques documentées (faiblesse connue du 27B) |
lint |
code | ruff check et ruff format --check, ou l'équivalent du projet |
commande |
code | commande de test lancée dans un clone à l'intérieur du bac à sable AppContainer existant, sans réseau, commandes limitées à celles déclarées par projet |
perimetre |
code | seuls les fichiers déclarés changent |
citations |
extraction, résumé | toute valeur, nombre ou identifiant cité doit se retrouver dans les fichiers source |
traduction |
traduction | placeholders, code et nombres conservés, ratio de longueur plausible |
Défauts par type : format + complet toujours ; code ajoute symboles, docstrings, lint ; extraction ajoute citations ; commande seulement si fourni.
Boucle : en cas d'échec, MIAM renvoie l'échec exact au modèle, 2 tentatives maximum, puis escalade local → API → rend la main à Claude avec statut echec_controle, sans accepter silencieusement.
Réponse à Claude : champs verdict (valide, echec_controle, non_controle), controles (nom, résultat, message court), essais, moteur_final, sortie (chemin de fichier), stats de diff ; pas de corps de code quand valide et retour="apercu".
Application : rien n'est écrit dans l'arbre de travail avant que tous les contrôles passent ; le résultat reste dans le clone ou un fichier temporaire ; puis écrit comme sortie déclarée.
Sécurité : la sortie du modèle est non fiable ; elle n'est jamais exécutée hors du bac à sable ; seules les commandes déclarées ; aucun secret dans le clone.
Mesure : le journal reçoit controles, essais, verdict ; echec_controle ne compte aucun gain ; le taux de réussite au premier essai par modèle alimente le choix de modèle (type/seuil) et le taux de réparation ; le temps passé dans les contrôles est suivi.
Limites : des tests écrits par le même modèle peuvent valider un comportement faux : exiger d'abord un test rouge (le test doit échouer sans le code) ou un test écrit séparément ; citations prouve la présence, pas le sens correct ; commande coûte du temps ; passer les contrôles ne remplace pas la revue de Claude sur les zones sensibles (concurrence, sécurité).
Découpage en bouts :
- Contrôles purs (
format,complet,symboles,docstrings,citations,traduction) avec leurs tests. - Contrôles outillés (
lint,perimetre) avec leurs tests. - Boucle de retentative et escalade local → API →
echec_controle. - Contrôle
commandedans le bac à sable, sur clone, sans réseau. - Champs de réponse (
verdict,controles,essais,moteur_final,sortie, stats de diff) et écriture différée. - Journal (
controles,essais,verdict, temps) et plugin (le hook litverdictet saute la lecture quandvalide).
Reprise de la main sans suivi répété
Livré dans MIAM (PH2-H11), sauf le chien de garde. miam-attendre est devenu la commande curl donnée dans reprise : aucun exécutable à installer. Contrat exact en section 11.
Problème : suivre plafonne chaque attente à call_wait_s (45 s), donc une tâche longue fait revenir Claude toutes les 45 s, et chaque retour coûte des tokens.
Principe : le temps n'est pas une limite, le seul coût est les tours de Claude. MIAM exécute contrôles, corrections et escalade seul. Claude est réveillé une fois, à un état terminal.
Attente unique : Claude lance une fois, en arrière-plan via Bash avec run_in_background, une petite commande miam-attendre <demande_id>. Elle bloque sur une route HTTP locale authentifiée de MIAM (long polling), imprime une ligne JSON, sort. Claude Code réveille Claude quand une commande d'arrière-plan se termine : aucun token pendant l'attente. Claude termine son tour ou continue autre chose.
États terminaux :
| état | sens | ce que fait Claude |
|---|---|---|
valide |
tous les contrôles passés, fichier écrit | intègre, sans lecture |
echec_controle |
tentatives et escalade épuisées ; le rapport donne le dernier échec | reprend la main ou re-découpe |
besoin_claude |
décision réservée à Claude : permission, plafond de dépense API atteint, instruction ambiguë | répond puis attend à nouveau |
annule |
demande annulée | rien |
perdue |
MIAM redémarré ou injoignable | renvoie ou fait lui-même |
Pas de limite de durée, mais pas d'attente sans fin : pas de timeout total. Un chien de garde détecte l'absence de progrès : aucun token généré, aucun contrôle terminé et aucun changement de tentative pendant mcp.sans_progres_s (proposé 600 s) donne besoin_claude avec l'étape bloquée. Les tentatives sont bornées (2 par moteur, puis escalade), donc la boucle se termine toujours. miam-attendre sort en perdue après plusieurs échecs de contact avec MIAM.
Hook du plugin : tant que miam-attendre tourne pour une demande, suivre sur cette demande est refusé avec le message « tu seras réveillé à la fin » ; idem pour les boucles de sleep en Bash. Le hook part du demande_id renvoyé en « en_file ».
Réponse de deleguer : si non terminé dans call_wait_s, la réponse donne demande_id, etat et reprise : la commande exacte à lancer.
Autres clients : un client sans commandes d'arrière-plan (OpenCode) garde suivre, avec un attente_s long unique, plus plafonné à 45 s, dans la limite du timeout du client MCP, à vérifier.
Coût attendu : un lancement et un réveil par délégation, indépendamment de la durée.
Bouts :
- États terminaux et chien de garde en logique pure, avec tests.
- Route de long polling authentifiée.
- Commande
miam-attendre, avec tests. - Champ
reprisedansdeleguer. - Hook du plugin refusant
suivre.
6. Évolutions côté MIAM
| Évolution | Effet |
|---|---|
moteur="auto" par défaut, repli explicite si tout est indisponible |
Supprime l'erreur « aucun modèle chargé » |
routage qui peut répondre « subagent Haiku » |
Échelle complète local → API → Haiku |
| Délégation courte pendant un bench : API plutôt que préemption | Ne coupe plus les tests |
Projet du plugin autorisé pour l'API ; clarifier projets: null |
Lève le refus rencontré |
deleguer(..., controle="pytest -k x", essais=2) : exécute et renvoie l'échec au modèle |
Niveau 1 sans Claude, détail en 5 bis |
lot=[...] : plusieurs bouts en un appel |
Moins de tours de pilotage |
| Écriture directe dans le dépôt avec diff court en retour | Claude ne reçoit pas le code |
7. Limites
- Un hook contrôle des appels, pas le raisonnement : Claude peut toujours rédiger puis découper artificiellement.
- Chaque délégation coûte une consigne et un suivi : sous ~10 lignes, écrire peut être moins cher, d'où les seuils.
- Des seuils trop stricts multiplieront les exceptions : les suivre dès le début.
- Le hook 6 ajoute un tour au départ de chaque tâche ; il doit rester sans objet pour une correction minime.
8. Ordre de travail
Chaque lot est découpé en bouts confiés à MIAM : le plugin sert de premier terrain d'essai.
- Lot 1 (P0) : compteurs par tour, hooks 1, 2, 3, 4, exception, repli. Vérifier d'abord les points de la section 3.
- Lot 2 (MIAM) :
autopar défaut, API pendant le bench, projet du plugin. - Lot 3 (P1) : budget de lecture, plan, sélecteur d'exécutant.
- Lot 4 :
controle=,lot=, écriture directe. - Lot 5 (P2) : bilan, compteur, documentation.
Mesures par session : part des lignes écrites par délégation, net de tokens, taux de reprise, nombre d'exceptions par motif, refus jugés à tort. Objectif proposé après le lot 1 : ≥ 70 % des lignes hors zones sensibles.
9. Décisions attendues
- Seuils de départ : 10 lignes pour les tests, 30 pour le code, ou plus strict.
- Mode : refus immédiat, ou une semaine en mesure seule pour régler les seuils (recommandé : refus immédiat sur les tests et le commit, mesure sur le reste).
- Liste des chemins sensibles exemptés.
- Part acceptable de Haiku dans l'échelle, à comparer au coût de l'API.
10. Version cible : plugin v0.9.0
But : une version dont les gains de tokens sont réels et mesurés, parce que Claude délègue par défaut.
Valeurs retenues par défaut (issues de la section 9, modifiables) : 10 lignes pour les tests, 30 lignes pour le code, refus immédiat sur tous les hooks P0, budget de lecture de 40 000 caractères par tour et 400 lignes par fichier ; chemins sensibles : src/miam/services/mcp.py, src/miam/services/instances.py, src/miam/core/aio.py plus tout ce qui correspond à *sandbox*, liste à confirmer.
Périmètre plugin (checklist) : compteurs de tour (lignes écrites par l'agent principal, caractères lus, dernière délégation réussie) ; hooks 1, 2, 3, 4 (section 3) ; hook 5 budget de lecture ; hook 6 plan de découpage ; hook 7 sélecteur d'exécutant ; exception avec raisons fermées ; repli quand aucun exécutant ne répond ; refus de suivre pendant miam-attendre ; rapport de fin de tour et compteur visible (hooks 8, 9) ; skill deleguer mis à jour pour enseigner le découpage, moteur="auto" et reprise.
Prérequis MIAM (PH2-H11, même livraison) : moteur="auto" par défaut ; API au lieu de la préemption pendant un benchmark ; projet plugin autorisé pour l'API ; controle avec contrôles purs et lint ; boucle de correction et escalade ; états terminaux, miam-attendre, reprise, chien de garde mcp.sans_progres_s ; verdict. lot=, écritures directes et commande en sandbox peuvent suivre plus tard sans bloquer la v0.9.0.
Vérifications préalables (bloquantes) : les trois points de « À vérifier avant de coder » en section 3 ; durée maximale de blocage tolérée par un client MCP. Fait le 03/11/2026 : une commande en arrière-plan de 11 min réveille bien Claude à sa sortie, sans token pendant l'attente.
Critères d'acceptation (checklist, chacun testable) : une édition de test de l'agent principal de plus de 10 lignes est refusée avec un appel prêt ; une écriture via le shell est comptée ; un git commit sans message délégué est refusé ; une tâche découpée en plusieurs morceaux lisant le même fichier dépasse le budget de lecture et est refusée ; tous les exécutants étant indisponibles, le travail continue et un toast le signale ; une délégation longue coûte un lancement et un réveil, sans appel à suivre ; un echec_controle rend la main avec le dernier échec ; les résultats valide sont intégrés sans que Claude lise le corps du code ; les exceptions apparaissent dans le rapport ; les sous-agents ne sont pas soumis aux budgets ; tous les tests du plugin passent.
Mesure du gain : gain réel = tokens Claude effectivement consommés, lus depuis session.usage, pas les evites estimés. Protocole : rejouer des tâches comparables (une fonction pure avec tests, une tâche UI multi-fichiers, une extraction de document) sur v0.8.0 et v0.9.0, mêmes prompts ; enregistrer tokens Claude totaux, coût cloud, durée, corrections, exceptions, actions refusées à tort, bugs trouvés ensuite. Comparer aussi net (evites - pilotage - corrections) à la différence mesurée pour calibrer l'estimation. Version valide seulement si les tokens Claude mesurés baissent sans hausse des bugs post-merge ; la cible est fixée après la première comparaison, aucun chiffre décidé maintenant.
Ordre des bouts :
- vérifications ;
- compteurs avec tests ;
- hooks P0 et exception ;
- prérequis MIAM ;
- budget de lecture, plan, sélecteur ;
- rapport de fin de tour et compteur ;
- skill et docs ;
- mesure puis release v0.9.0.
Chaque bout suit la section 4 et est délégué.
11. Contrat livré par MIAM (PH2-H11) et travail restant côté plugin
État au 03/11/2026, code de MIAM non commité, tests verts. Le MIAM installé doit être reconstruit pour l'exposer.
Ce que MIAM accepte
deleguer(..., controle=[...], attendus=[...]) :
controle: liste parmisyntaxe,complet,symboles,docstrings,citations,traduction,lint.[]désactive les contrôles.- Par défaut :
format="code"avec unesortieen.pydonnesyntaxe,complet,symboles,docstrings,lint; tout le reste donnecomplet. attendus: noms qui doivent figurer dans la réponse (fonctions, classes), vérifiés parcomplet.lint:ruff check --select F,E9seulement (vraies erreurs, pas le style) ; ignoré si ruff est introuvable (cas de l'exe).symbolesetcitationscomparent la réponse aux fichiers joints : joindre les modules utilisés.- Tentatives :
mcp.controle_essais(2) par moteur ; une demande locale passe ensuite à l'API.
Écarts avec la section 5 bis : format s'appelle syntaxe (Python seulement) ; commande et perimetre ne sont pas faits ; il n'y a ni moteur_final ni statistiques de diff.
Ce que MIAM renvoie
| cas | réponse | fin (route /attendre) |
|---|---|---|
| terminé, contrôles passés | ok: true, verdict: "valide", controles: [{nom, ok, message?}], essais, sortie si demandée |
valide |
| terminé sans contrôle | ok: true, verdict: "non_controle" |
termine |
| contrôles échoués partout | ok: false, erreur: "echec_controle : nom : message ; …" |
echec_controle |
| annulé | ok: false, etat: "annulee" |
annule |
| demande inconnue (MIAM redémarré) | ok: false, sans etat |
perdue |
| permission OpenCode, autre cas en attente | ok: null |
besoin_claude |
pas fini dans call_wait_s (45 s) |
ok: null, demande_id, etat, reprise, message |
(sans objet) |
sortie n'est écrite qu'après le verdict valide. Les tentatives rejetées sont journalisées dans delegations.jsonl avec statut: "rejete", sans gain.
Attente unique
reprise vaut exactement :
curl -s -H @"<logs>/mcp/attente.hdr" "http://127.0.0.1:<port>/attendre?demande_id=<id>"
attente.hdrcontient l'en-têteAuthorization, écrit par MIAM au démarrage du serveur MCP : aucun jeton dans la commande ni dans la conversation.GET /attendrerépond une seule fois, à l'état final : la même réponse quesuivre, plusfin. Chaque attente interne dure au plusATTENTE_ROUTE_S(3600 s) et reprend en boucle tant que la demande n'est pas finie.- À lancer avec
Bashetrun_in_background: true(Git Bash sous Windows : la commande est en syntaxe POSIX). Vérifié le 03/11/2026 sur le vrai serveur HTTP.
Encore manquant côté MIAM
- Chien de garde
mcp.sans_progres_s: pas encore fait, car le modèle répond sans flux et rien ne mesure l'avancement. La seule limite restetimeout_execution_s, multiplié par le nombre de tentatives. Une très longue tâche peut donc finir en expiration (ok: false,fin: "besoin_claude"ouperdue). - Contrôles
commande(tests en bac à sable) etperimetre. moteur="auto"par défaut ; API au lieu de la préemption pendant un benchmark.
À coder dans le plugin (v0.9.0), par bouts
Fait le 03/11/2026 (bouts 1 à 7, hooks/attente.ts et register.tsx, tests sur réponses figées), avec deux écarts :
le réveil est lu par un hook prompt.submit, qui reconnaît la notification à l'id de la commande d'arrière-plan relevé
au lancement et lit lui-même la sortie (une ligne JSON) ; PowerShell est refusé pour reprise, en syntaxe POSIX.
Pas encore essayé sur le vrai serveur.
- Hook PostToolUse sur
deleguer: siokestnullet qu'il y a unereprise, ajouter au contexte « lancerepriseune fois avecrun_in_background, puis termine ton tour ou fais autre chose », et noterdemande_idcomme en attente dans l'état du tour. - Hook PreToolUse sur
Bash: reconnaître une commande qui contient/attendre?demande_id=; sansrun_in_background, la refuser (« lance-la en arrière-plan ») ; avec, passer la demande à « attendue ». - Hook PreToolUse sur
suivre: refuser si la demande est « attendue », avec « tu seras réveillé à la fin ». Refuser aussi lessleepet les boucles d'attente enBashpendant une attente. Laisser passersuivresifinvautbesoin_claude(permission à donner). - Hook sur la sortie de la commande d'arrière-plan (ou PostToolUse sur la notification) : lire
finet injecter la conduite :valide: intégrer sans relire le corps, ne pasReadlasortieen entier ;termine: relire ;echec_controle: reprendre la main ou redécouper, avec le dernier motif ;besoin_claude: répondre (autoriser), puis relancerreprise;annule: rien ;perdue: renvoyer la demande ou faire soi-même.
- Hook PreToolUse sur
Read: aprèsvalide, refuser une lecture complète du fichiersortie(aperçu ouoffset/limitseulement), sauf chemin sensible. - Skill
deleguer: enseignercontroleetattendus, joindre les modules poursymboles, lancerrepriseen arrière-plan, et le tableaufinci-dessus. - Compteurs :
essais, nombre deechec_controleet attentes uniques par session, pour la mesure de la section 10.
Tests de chaque hook sur des réponses figées tirées du tableau ci-dessus ; les autres hooks (sections 3 et 10) suivent l'ordre de la section 10.