Session en attente
L'opérateur s'absente ; une file de tâches est traitée. Chaque tâche s'exécute dans un nouveau processus sans tête, donc une limite d'utilisation ou un crash ne coûte qu'une itération, pas la nuit. L'état est conservé sur disque dans le dossier de la session ; la fin du processus remplace /clear. Les faits marqués pour claude -p sont dans la compétence headless-claude.
Configuration et profil du dépôt. <repo>/.claude/project-workflow.json est facultatif ; cette compétence lit ses clés projects_dir (par défaut my-projects), profile (par défaut <projects_dir>/WORKFLOW.md), backlog_file (par défaut <projects_dir>/backlog.md) et bootstrap (une liste d'arguments, ou null). Lire le § Session en attente du profil si le fichier existe : commandes de test, sources de découverte, classes auto-autorisées. Là où le profil et cette compétence diffèrent, le profil l'emporte.
Phases — charger un fichier, à l'entrée de sa phase
| Phase | Qui | Lit |
|---|---|---|
| armement | opérateur présent | § Armement ci-dessous, puis discover.md pour construire la file |
| itération | away-orchestrator, un par processus | iteration.md |
| statut, désarmement | opérateur | § Statut, § Désarmement ci-dessous |
project-workflow et away-run partagent des fichiers (le fichier de backlog, <projects_dir>/proposals/open/), pas des appels, sauf un : une ligne project invoque /project-workflow via l'outil Skill en mode non surveillé.
Une vague de projet s'étend sur plusieurs lignes project, un groupe d'étapes wave.md § Forme de session chacune (1 ; 2-3 ; 4-7). Chaque ligne travaille du nom ## Resume de l'étape jusqu'à la fin de son groupe, effectue un commit chore(<NNNN>): checkpoint vague N à l'étape <n>, et ajoute la ligne de suivi pour l'étape suivante sauf si la limite a été atteinte. Une ligne en ajoute une, avec attempts 0, seulement si elle a terminé au moins une étape ; une ligne qui n'en a terminé aucune reste claimed et réessaie avec son propre attempts. Cela se termine : chaque ligne de suivi suit au moins une des sept étapes de la vague, et le plafond d'essais met fin à une étape qui ne se termine jamais. Le checkpoint et ## Resume sont la seule transition (iteration.md § 3).
Disposition
<dépôt>-worktrees/away-<date>/ worktree, branche away/<date> depuis main
<dossier session>/ suivi sur away/<date> ; arm.ps1 -RunFolder,
queue.md decisions.md log.md par défaut <projects_dir>/away/<date>/
morning-report.md écrit par l'itération de clôture
<dépôt>-worktrees/away-<date>-run/ scratch, non suivi : away.env, watchdog.sh,
entry-prompt.md, watchdog.log, iter-NNN.*, verrous
tâche planifiée away-<dépôt>-<date> toutes les 15 minutes jusqu'à l'arrêt forcé
Lignes de la file
templates/queue.md contient le schéma. Colonnes : id | item | agent | status | claimed_by | lease_until | attempts | evidence. agent est mechanical-worker, stream-worker, researcher, project ou discover. Chaque modification de la file prend le verrou : mkdir <scratch>/queue.lock (atomique ; si échec, réessayer toutes les 10 s pendant 2 minutes ; un dossier de verrou dont la dernière modification remonte à plus de 10 minutes est périmé, avec ou sans son fichier owner : le supprimer), modifier, rm -rf le verrou. Ce qui suit un échec de 2 minutes de tentatives est dans iteration.md § 2 et § 4. Une revendication (claim) définit claimed_by sur la balise de revendication de l'itération (iter-NNN, exactement comme donnée par l'invite d'entrée) et lease_until ; un bail expiré signifie une itération morte et la ligne peut être réclamée à nouveau, avec attempts + 1.
Armement (opérateur présent)
- File. La construire avec
discover.md: lignes de niveau 1 uniquement, chacune avec une vérification nommée. Le travail de niveau 2 devient des propositions. Nommer la valeur par défaut pour chaque décision qu'une ligne peut rencontrer ; une ligne avec une décision ouverte et sans valeur par défaut n'est pas mise en file. - Posture. Dire clairement : la session utilise
--permission-mode bypassPermissions, donc chaque appel d'outil s'exécute sans invite ; les règles de refus global s'appliquent toujours. "Pas de barrières" (les questions ouvertes deviennent des valeurs par défaut nommées, les échecs sautent et réessayent) est activé par session, défini commegates: nonedans l'en-tête de la file ; jamais déduit d'une session antérieure. - Armement. D'abord à sec, puis pour de vrai, depuis PowerShell :
powershell -NoProfile -File <skill>/arm.ps1 -Repo <chemin> -StopAt "<AAAA-MM-JJ HH:MM>" -Queue <queue.md> -WhatIf. Il crée le worktree suraway/<date>depuismain, initialise le dossier de session à partir detemplates/et le commite avec la file, exécute les argumentsbootstrapde la configuration ({worktree}remplacé par le chemin du worktree, répertoire courant le checkout principal ; ignoré si la clé est absente ou nulle) et attend sa fin, copiewatchdog.shetentry-prompt.mddans le scratch, écritaway.env, et enregistre la tâche (Register-ScheduledTask, jamaisschtasks /Create: PowerShell 5.1 détruit les guillemets de/TR). Un code de retour non nul du bootstrap refuse avant l'existence d'une tâche ; le worktree et la branche restent pour inspection. La tâche n'a pas de principal, donc elle ne s'exécute que tant que l'opérateur est connecté, dans une fenêtre console dont la fermeture la tue : verrouiller l'écran, ne pas se déconnecter. - Vérification.
Get-ScheduledTask -TaskName 'away-*'affiche la tâche ; la première exécution écritwatchdog updanswatchdog.log. - Modifications ultérieures de la file. arm.ps1 commite la file une fois. Commiter vous-même toute modification de la file effectuée après l'armement sur
away/<date>(sous le verrou de la file une fois que la tâche a démarré) : les itérations traitent le travail non commité qu'elles n'ont pas créé comme appartenant à quelqu'un d'autre et ne le préparent jamais.
Ce que fait le chien de garde (watchdog.sh)
- Lance
claude -p --agent away-orchestrator --max-turns N, invite sur l'entrée standard. Le modèle et l'effort proviennent de l'en-tête de l'agent ; pas de--effort, pas de drapeau TTL, pas de--disable-slash-commands(cela désactiverait Skill). - Juge une itération par
is_error/api_error_statuset siqueue.mda changé, jamais parnum_turns. Trois itérations sans changement de file y mettent fin. - Limite d'utilisation : attend la réinitialisation que le message indique. "Vous avez atteint votre limite Opus" continue sur Sonnet (
--model sonnet) pour les lignesmechanical-workeruniquement ; sans ligne réclamable, il attend la réinitialisation. - Dépassement de budget (
subtypeerror_max_budget_usd, typebudget) : pas d'attente, car le plafond est par processus. Il conserve la revendication de la ligne, donc l'itération suivante prend la ligne suivante et celle-ci revient lorsque son bail expire ; les dépassements comptent dansFAIL_MAXcomme les erreurs. - Réserve de quota : à
WINDOW_CAP_USDde dépense imputée dans une fenêtre glissante de 5 heures, il attend jusqu'à ce que la fenêtre se libère ; les dernièresRESERVE_MINminutes sont consacrées à la clôture. - File vide : une itération de clôture écrit le rapport matinal, puis se termine. Toute autre sortie laisse un rapport partiel écrit par le chien de garde. Chaque sortie écrit
STOP, donc les déclenchements ultérieurs de la tâche sont sans effet ; le supprimer pour reprendre. - Après chaque itération d'élément, il expire les baux détenus sous la balise de revendication de cette itération, donc une ligne interrompue par une limite ou une erreur est réessayée, pas bloquée jusqu'à la clôture. Il saute cette étape après la clôture, qui ne revendique rien, et après un dépassement de budget (ci-dessus).
- Enregistre
claude: <chemin>au début de chaque itération : le binaire qu'il va exécuter. - Refuse de s'exécuter sur
main, sur un checkout principal, ou sur une branche qui n'est pasaway/*. - Test à sec :
CLAUDE=<script factice> AWAY_NO_SLEEP=1 bash watchdog.sh <away.env>contre un worktree de test suraway/*; les attentes sont enregistrées, pas exécutées. UnCLAUDEouPYdéfini dans l'environnement l'emporte sur celui nommé paraway.env, donc le script factice s'exécute même avec unaway.envécrit par l'armement ; le confirmer par la ligne de logclaude: <script factice>.
Statut
Consulter <scratch>/watchdog.log ; lire queue.md. Avant de croire "un autre chien de garde est actif", confirmer un processus claude.exe (tasklist) et une ligne itération N démarrant récente : un verrou orphelin bloque silencieusement chaque déclenchement. Git Bash n'a pas pgrep.
Désarmement
powershell -NoProfile -File <skill>/disarm.ps1 -Repo <chemin> -Date <date> : il écrit STOP, désenregistre la tâche et vérifie que Get-ScheduledTask -TaskName 'away-*' ne retourne rien. Une tâche laissée enregistrée continue de lancer bash toutes les 15 minutes. Le worktree et la branche restent pour révision : lire le rapport matinal, puis fusionner away/<date> par la méthode habituelle du dépôt, ou le supprimer.
Pourquoi c'est construit ainsi
- La résilience réside en dehors du CLI.
CronCreate durable:trueest revenu limité à la session (2026-09-19) ;/looprentre dans la même session ; unnohup … &depuis un appel d'outil Bash est attaché à ce shell ; Git Bash n'a passetsid. - Une limite d'utilisation est attendue jusqu'à la réinitialisation que son message indique, pas par un backoff croissant, et une itération n'est jamais jugée en échec par un faible
num_turns: un backoff dépasse la réinitialisation, et une itération peut fermer une ligne en un seul tour signalé.