Contrôle Droid
Automatisez les terminaux et navigateurs. Trois décisions de routage, puis les atoms vous guident pour le reste.
Règles fondamentales
- Applications réelles, environnements réels. Le comportement non-déterministe (réponses LLM, latence réseau, sortie variable) est attendu. Gérez-le avec
wait/wait-idle. Ne remplacez jamais par des fixtures ou données mockées. - Engagez-vous dans l'exécution. Une fois que vous avez choisi un driver, exécutez le plan. Si quelque chose échoue en cours d'exécution, récupérez et réessayez — ne réévaluez pas l'approche.
- Les atoms sont autonomes. Chargez-en un et suivez sa mécanique. Aucune référence croisée nécessaire.
tctlest le SEUL moyen de lancer des sessions enregistrées.tctlgère l'enregistrement en enveloppantasciinema recautour du PTY — letuistorybrut n'a pas de capacité d'enregistrement et n'en aura jamais. N'appelez jamaistuistory launchdirectement ; les flags inconnus font crashertuistory-relay. Toujours résoudreTCTLà son chemin absolu du système de fichiers avant utilisation, particulièrement quand on délègue à des workers (ils n'héritent pas de${DROID_PLUGIN_ROOT}).- Isolez chaque exécution. Plusieurs droids peuvent filmer simultanément sur la même machine. Les noms de session et chemins de sortie partagent un espace de noms global (
/tmp/tctl-sessions/). Au début de chaque workflow, générez un ID d'exécution (RUN_ID=$(date +%s)-$$ou similaire) et utilisez-le comme préfixe pour tous les noms de session et répertoire temporaire limité pour tous les fichiers de sortie :RUN_ID="$(date +%s)-$$" RUN_DIR="$(mktemp -d /tmp/droid-run-${RUN_ID}-XXXXXX)" # Noms de session : -s ${RUN_ID}-before, -s ${RUN_ID}-after # Chemins de sortie : ${RUN_DIR}/before.cast, ${RUN_DIR}/after.castN'utilisez jamais de noms de session nus comme
-s demo,-s before,-s after— ils entreront en collision avec des exécutions concurrentes.
Routage
Trois recherches indépendantes. Faites les trois, puis chargez l'union des skills qu'elles produisent.
1. Routage cible — qu'automatisez-vous ?
| Cible | Charger ces skills |
|---|---|
Droid CLI (droid-dev, droid exec) |
droid-cli + backend tuistory via ${DROID_PLUGIN_ROOT}/bin/tctl |
| Droid CLI (preuve de terminal réel) | true-input + droid-cli |
| Autre TUI terminal | Backend tuistory via ${DROID_PLUGIN_ROOT}/bin/tctl |
| Autre TUI terminal (preuve de terminal réel) | true-input |
| Page web ou application Electron | agent-browser |
| Séquences d'octets de terminal brut | true-input + pty-capture |
tuistory est le défaut pour le travail en terminal. Utilisez true-input uniquement quand vous avez besoin de preuve de rendu réel du terminal.
2. Routage stage — qu'a besoin le workflow ?
Chaque workflow traverse des stages. Chargez les atoms pour chaque stage que vous utiliserez.
| Stage | Skill | Quand charger |
|---|---|---|
| Capture | capture | Toujours — chaque workflow enregistre ou capture quelque chose |
| Compose | compose | Quand le livrable est un artefact produit (vidéo, captures d'écran annotées, image de comparaison) |
| Verify | verify | Toujours — chaque livrable est vérifié par rapport aux engagements |
3. Routage artefact — compose a-t-il besoin d'outils de finition ?
Pertinent uniquement quand compose est chargé.
| Besoin d'artefact | Également charger |
|---|---|
| Finition vitrine (chrome de fenêtre, cadre de marque, arrière-plan cinématique) | showcase |
| Effets et superpositions de frappes clavier | (compose gère ceci — ce sont des champs dans le JSON props Remotion) |
Forme du workflow
Commande (intention + engagements)
→ Routage cible (charger les atoms du driver)
→ Capture (enregistrement / capture d'écran / byte-capture)
→ Compose (assembler le livrable, si nécessaire)
→ Verify (vérifier par rapport aux engagements)
→ Rapport
Les commandes déclarent quoi produire. Les atoms possèdent le comment.
Disposition par défaut
Défaut : single. Un clip montrant la cible/l'état final. Choisissez ceci sauf si le livrable est fondamentalement une comparaison.
| Cas | Disposition |
|---|---|
| Nouvelle fonctionnalité (pas d'état antérieur significatif) | single |
| Correction de bug, preuve en un clip du chemin fonctionnant | single |
| Walkthrough / tutoriel / hero readme | single |
| Preuve de régression (cassé vs corrigé) | side-by-side |
| Refactorisation préservant le comportement (parité visuelle est le point) | side-by-side |
| L'utilisateur demande explicitement une comparaison | side-by-side |
Ne synthétisez pas un état « avant » pour justifier side-by-side. S'il n'y a pas de ligne de base réelle, utilisez single.
Délégation
L'agent parent planifie et orchestre. Le travail mécanique s'exécute dans des sous-agents workers via l'outil Task. Cela garde le contexte du parent propre et active le parallélisme.
Quoi déléguer
| Tâche | Déléguer ? | Pourquoi |
|---|---|---|
| Capturer clip (disposition single) | OUI | Le worker exécute le script d'interaction de bout en bout et retourne le chemin .cast |
| Capturer les deux clips (disposition de comparaison) | OUI — run_in_background=true pour chacun |
Les branches sont indépendantes ; s'exécutent en parallèle |
| Rendu Remotion | OUI | Nécessite uniquement JSON props, chemins de clips, chemin de sortie. Exécute render-showcase.sh (gère conversion .cast, profils de fidélité, détection de durée, nettoyage) |
| Planification, scripting d'interaction | NON — parent | Nécessite le contexte PR et jugement éditorial |
| Construction de disposition et props | NON — parent | Nécessite des décisions éditoriales sur les effets, timing, labels |
| Vérification | NON — parent | Nécessite le contexte d'engagement |
| Seul ffprobe / vérification d'existence de fichier | NON — inline | Trop trivial pour le coût du subagent |
Comment déléguer
Étape 0 : Résoudre les chemins et générer un ID d'exécution. Les workers n'héritent pas de ${DROID_PLUGIN_ROOT}. Résolvez une fois, collez partout :
TCTL="$(realpath "${DROID_PLUGIN_ROOT}/bin/tctl")"
RENDER="$(realpath "${DROID_PLUGIN_ROOT}/scripts/render-showcase.sh")"
RUN_ID="$(date +%s)-$$"
RUN_DIR="$(mktemp -d /tmp/droid-run-${RUN_ID}-XXXXXX)"
Utilisez ${RUN_DIR} pour tous les fichiers de sortie (enregistrements, props, vidéo rendue). Utilisez ${RUN_ID}- comme préfixe pour tous les noms de session. N'utilisez jamais de noms nus comme -s before ou chemins codés en dur comme /tmp/before.cast.
Donnez aux workers des commandes exactes avec les chemins absolus résolus — pas des instructions abstraites, pas tuistory, pas ${DROID_PLUGIN_ROOT}. Le parent pense ; le worker exécute :
Prompt Task pour un worker de capture :
« Exécutez ces commandes dans l'ordre. Signalez le chemin du fichier de sortie et les erreurs.
1. /abs/path/to/bin/tctl launch "droid-dev" -s 1712345678-42-before --backend tuistory \
--repo-root /abs/path/to/baseline/worktree \
--cols 120 --rows 36 --record /tmp/droid-run-1712345678-42-xxxx/before.cast \
--env FORCE_COLOR=3 --env COLORTERM=truecolor
2. /abs/path/to/bin/tctl -s 1712345678-42-before wait ">" --timeout 15000
3. /abs/path/to/bin/tctl -s 1712345678-42-before type "hello world"
4. /abs/path/to/bin/tctl -s 1712345678-42-before press enter
5. /abs/path/to/bin/tctl -s 1712345678-42-before wait-idle
6. /abs/path/to/bin/tctl -s 1712345678-42-before close »
Prompt Task pour un worker de rendu Remotion :
« Exécutez cette commande. Signalez le chemin du fichier de sortie et les erreurs.
/abs/path/to/scripts/render-showcase.sh \
--props /tmp/droid-run-1712345678-42-xxxx/showcase-props.json \
--output /tmp/droid-run-1712345678-42-xxxx/demo.mp4 \
/tmp/droid-run-1712345678-42-xxxx/before.cast /tmp/droid-run-1712345678-42-xxxx/after.cast »
Modèle de capture parallèle (flux de comparaison uniquement)
Applicable uniquement quand le tableau Disposition par défaut ci-dessus sélectionne side-by-side. Pour une disposition single, lancez un seul worker de capture et ignorez cette section.
Pour les démos de comparaison avant/après, lancez les deux workers de capture simultanément :
1. Le parent construit le script d'interaction (identique pour les deux branches)
2. Lancer worker A : capturer la branche baseline/référence avec `--repo-root` défini à ce worktree
3. Lancer worker B : capturer la branche candidate/changement avec `--repo-root` défini à ce worktree
4. Attendre que les deux se complètent (TaskOutput)
5. Collecter les chemins .cast des résultats
6. Continuer vers compose
Outillage partagé
Les drivers de terminal utilisent le wrapper tctl unifié. agent-browser a son propre CLI et n'utilise pas tctl.
Les drivers peuvent être combinés dans un workflow — p. ex., tctl pour une CLI et agent-browser pour une interface web avec laquelle elle interagit.
Prérequis
| Stage | Plateforme | Requis | Optionnel |
|---|---|---|---|
| tuistory | Tous | tuistory, asciinema, agg |
tmux |
| true-input | Linux/Wayland | cage, wtype, terminal Wayland, /dev/dri/* |
grim, wf-recorder |
| true-input | Windows (KVM) | libvirt, qemu, VM KVM avec SPICE + SSH, variables d'env DROID_VM_* |
virt-manager |
| true-input | macOS (QEMU) | qemu, socat, VM macOS avec SSH, variables d'env DROID_MAC_* |
— |
| agent-browser | Tous | agent-browser (+ agent-browser install) |
— |
| compose | Tous | ffmpeg, ffprobe, agg |
— |
| showcase | Tous | Node.js (>= 18), Chrome/Chromium | — |
Commandes d'installation
# Driver tuistory + enregistrement
npm install -g tuistory # driver PTY virtuel
pip install asciinema # enregistrement terminal (tctl enveloppe ceci)
cargo install --git https://github.com/asciinema/agg # convertisseur .cast -> .gif (compose en a besoin)
# Driver true-input (Linux/Wayland)
sudo apt-get install -y cage wtype # requis : compositeur headless + injection de frappe
sudo apt-get install -y grim wf-recorder # optionnel : capture d'écran + enregistrement vidéo
# Driver agent-browser
agent-browser install # une fois : télécharge Chromium fourni
# Compose + showcase (rendu vidéo)
sudo apt-get install -y ffmpeg # traitement vidéo (inclut ffprobe)
cd ${DROID_PLUGIN_ROOT}/remotion && npm install # dépendances Remotion
# Chrome ou Chromium doit être installé pour le rendu Remotion