Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Cycle de vie du travail en arrière-plan

ZeroClaw dispose de plusieurs façons de poursuivre le travail après la requête entrante qui l’a démarré. Les tâches cron, les exécutions SOP, les tâches déléguées et les sous-agents instanciés à l’exécution partagent certains mécanismes d’exécution, mais ils ne partagent ni un cycle de vie unique ni un store durable unique. Le mode objectif définit un contrat cible associé qui n’est pas encore connecté de bout en bout.

Utilisez cette page lorsqu’une modification ajoute un travail planifié ou autonome, introduit un état d’attente ou d’approbation, modifie le comportement d’annulation ou de redémarrage, ou relie un travail enfant à une tâche propriétaire. La première question de conception n’est pas « comment cela s’exécute-t-il en arrière-plan ? » mais « quel sous-système est propriétaire de son cycle de vie ? »

Carte des propriétés

Type de travailPropriétaire actuel ou surface d’étatEnregistrements persistants
Tâche cronPlanificateur cron et magasindata/cron/jobs.db
Exécution SOPSopEngine et SopRunStoreMémoire de processus par défaut ; data/sop/runs.db lorsque l’initialisation SQLite durable réussit
Délégation en arrière-planPlan de contrôle des tâches durablesUne ligne de tâche requise dans data/control_plane.db ; contenu de sortie dans <workspace>/delegate_results/<task-id>.json
Sous-agent généré au moment de l’exécutionCréer le site, avec supervision du plan de contrôle lorsque disponibleUne ligne de tâche au mieux dans data/control_plane.db avec un démon démarré

Les métadonnées durables ne sont pas la même chose que l’exécution durable. Un fichier de résultat ou une ligne de tâche peut préserver ce qui était connu et permettre à la récupération de marquer le travail comme perdu, expiré ou terminal sans préserver le futur local au processus qui effectuait ce travail.

tâches Cron

Cron combine l’appartenance déclarative avec un magasin d’exécution SQLite. Les jobs créés au moment de l’exécution et les jobs de configuration réconciliés portent tous un agent_alias propriétaire ; l’exécution résout la politique de sécurité de cet agent au lieu de s’exécuter sous une identité de démon ambiante.

Le planificateur interroge les lignes échues, activées et non réservées. La réservation d’une ligne empêche une sélection en double pendant son traitement. La finalisation enregistre une sortie limitée, puis reprogramme une tâche récurrente, supprime une tâche ponctuelle à suppression automatique réussie, ou désactive une autre tâche ponctuelle. Si le processus se termine avant de libérer une réservation, le prochain démarrage du planificateur efface le verrou obsolète.

Le comportement au démarrage est explicite. Lorsque le rattrapage est activé, les tâches en retard sont prises en compte pour exécution. Sinon, une tâche unique en retard est désactivée avec un résultat ignoré, tandis qu’une tâche récurrente avance à sa prochaine occurrence future sans enregistrer de résultat d’exécution. Le planificateur vérifie son jeton d’annulation entre les itérations de scrutation, de sorte que l’arrêt attend que le lot actuel de tâches dues se termine avant que la boucle ne se termine. L’annulation du planificateur ne garantit pas qu’un effet de bord externe déjà distribué puisse être annulé.

Exécutions SOP

Les définitions SOP se trouvent dans le répertoire sops configuré. SopEngine gère la progression de l’exécution, les attentes d’approbation, les points de contrôle, les transitions terminales et la surface d’état intégrée au processus. SopRunStore fait autorité en matière de concurrence lorsqu’il admet et réclame une exécution.

La persistance des exécutions est optionnelle. Avec la valeur par défaut sop.persist_runs = false, le moteur utilise un store en mémoire. Lorsque la persistance est activée, le backend SQLite par défaut écrit runs.db sous <data_dir>/sop, sauf si run_state_dir le remplace. Une initialisation réussie du store permet aux snapshots actifs, aux enregistrements terminaux, aux événements, aux révisions et aux revendications de concurrence de prendre en charge la restauration après redémarrage. Si l’initialisation du store échoue, le daemon consigne un avertissement et bascule vers le store en mémoire.

Les enregistrements d’audit SOP dans le backend Memory constituent une surface d’observabilité distincte. Ils ne remplacent pas le store d’exécution et ne doivent pas être utilisés comme référence faisant autorité pour déterminer si une exécution est active, en pause, approuvée ou terminale.

Les états d’approbation et de point de contrôle ne sont des états de contrôle persistants que lorsque le magasin des exécutions est persistant. La stratégie d’expiration reste en mode de refus par défaut : une approbation dont le délai a expiré est escaladée et continue d’attendre, sauf si la configuration sélectionne explicitement l’annulation ou le comportement historique d’approbation automatique.

Délégation et sous-agents

Les sous-agents héritent de la frontière de sécurité effective de leur parent. Les remplacements de stratégie et de mémoire peuvent restreindre l’enveloppe du parent mais ne peuvent pas l’élargir, et la comptabilisation des actions enfants utilise le suivi du parent, de sorte que la création d’enfants ne peut pas contourner le budget d’actions du parent.

Le chemin spawn_subagent est synchrone : le parent attend la fin de l’exécution de l’enfant, et ce chemin ne dispose d’aucun délai d’expiration local ni de gestionnaire d’annulation en arrière-plan.

L’outil delegate peut s’exécuter de manière synchrone ou lancer une tâche en arrière-plan et renvoyer un UUID. Une tâche en arrière-plan ne démarre qu’après avoir pu ouvrir le plan de contrôle durable, résoudre son alias d’agent propriétaire et enregistrer sa ligne de tâche. Cette ligne est l’unique autorité sur le cycle de vie des états en cours d’exécution, terminé, en erreur et de reprise. Le contenu de la sortie terminée est écrit de manière atomique dans l’espace de travail transmis à l’outil ; la ligne de tâche stocke la référence à cet artefact au lieu de dupliquer le contenu.

Les lecteurs actuels restent compatibles avec les artefacts hérités contenant des informations de statut et avec la sortie de tâche en ligne héritée. L’inverse n’est pas garanti : les artefacts écrits dans le format actuel, qui ne contient que la sortie, ne sont pas lisibles par les anciens binaires ou scripts qui exigent des champs de cycle de vie intégrés. Restaurez le répertoire de données et les artefacts de l’espace de travail ensemble, ou terminez les travaux en arrière-plan en cours avant de revenir à une version antérieure.

Un registre d’annulation actif associe les identifiants de tâche à des jetons locaux au processus. L’annulation signale la tâche en cours d’exécution lorsque ce jeton est toujours disponible et utilise une transition terminale par comparaison et échange (compare-and-set) dans le magasin de tâches. Ainsi, la fin, l’échec, l’annulation et la récupération ne peuvent pas s’écraser mutuellement une fois qu’un résultat terminal l’a emporté.

Avant qu’un délégué en arrière-plan ne publie un artefact de sortie terminal, il sérialise les octets exacts, calcule leur empreinte SHA-256 et persiste une intention de règlement terminal contenant l’identifiant de la tâche, le PID et l’identité de démarrage du propriétaire actuel, le statut terminal souhaité, le chemin ou la référence de l’artefact, l’empreinte et l’erreur terminale. L’intention est une transition non appliquée ; TaskRecord.status demeure la seule autorité de cycle de vie persistée.

Le délégué écrit ensuite ces octets exacts de manière atomique, puis les synchronise. Une seule transaction SQLite compare la ligne de tâche encore non terminale et appartenant au même propriétaire à l’intention, enregistre le statut terminal souhaité ainsi que la charge utile, puis supprime l’intention inchangée. Les échecs du store survenus avant la persistance de l’intention sont réessayés sans publier l’artefact ; les échecs survenus après la publication sont réessayés en interne, dans le processus. Une annulation concurrente ou un autre vainqueur terminal est conservé et supprime l’intention obsolète.

Un superviseur distinct attend le handle de tâche Tokio exact du worker en arrière-plan. Si ce worker panique ou est interrompu alors que le processus parent survit, le superviseur ne récupère que sa tâche et le propriétaire enregistré. Il valide toute intention de règlement persistée avec les mêmes vérifications d’artefacts que celles utilisées par la récupération de processus ; une sortie manquante ou corrompue aboutit à Failed, et une sortie avant la persistance de l’intention aboutit à un résultat Failed lié au propriétaire. Les erreurs de stockage sont relancées avec un backoff plafonné. Un worker vivant n’est jamais récupéré, et un gagnant terminal concurrent ou un propriétaire transféré ne peut pas être écrasé. Ceci s’appuie sur la preuve directe de sortie du worker plutôt que sur un délai de heartbeat ou un nouveau bail.

La récupération au démarrage et périodique traite les intentions de règlement avant la réconciliation ordinaire de Lost. La récupération n’agit qu’après avoir prouvé que le propriétaire enregistré est absent ou que son PID a été réutilisé, valide les octets de l’artefact par rapport à l’empreinte enregistrée, et résout un artefact manquant ou corrompu de manière conservatrice en tant que Failed avec une erreur de persistance/récupération, plutôt que de produire Completed. Le nonce aléatoire du processus n’est pas observable via les API de processus du système d’exploitation ; le couple PID et heure de démarrage du processus reste donc conservateur pour la réutilisation d’un PID dans la même seconde : la récupération traite ce cas comme le même propriétaire.

Les lignes de délégation et de sous-agent actuelles renseignent l’agent, le statut, le PID du processus propriétaire et son identité, la profondeur et les horodatages. Les lignes de délégation enregistrent aussi l’alias de l’agent créateur, la chaîne ordonnée des alias d’appelants situés au-dessus de lui, et la clé de session de la boucle d’outils comme principal. Les actions de résultat, d’attente, de liste et d’annulation admettent un alias qui a créé la ligne ou qui figure n’importe où dans cette chaîne, tandis que la clé de session n’a qu’un usage forensique et n’est jamais consultée par la vérification de propriétaire. Les lignes de sous-agent laissent toujours route, chain et principal absents. Les deux laissent la tâche parente absente. Les lignes de délégation en arrière-plan portent un heartbeat pendant leur exécution : chaque écriture de progression le rafraîchit, au moins une fois par minute, de sorte que le délai d’expiration du heartbeat du reaper s’applique à elles ; les lignes de sous-agent laissent toujours le heartbeat absent. La récupération au démarrage ne marque une ligne en cours comme lost que lorsque le processus propriétaire enregistré a manifestement disparu ou que son PID a été réutilisé ; une propriété incertaine échoue en mode fermé. La récupération sous Windows distingue un PID absent d’un sondage refusé pour accès ou autrement ambigu, et conserve la ligne lorsque l’absence ne peut pas être prouvée. timed_out ne s’applique qu’aux producteurs qui émettent des heartbeats : les délégués en arrière-plan en émettent, les sous-agents non. Le heartbeat d’un délégué en arrière-plan provient de son flusher de progression, qui réécrit la ligne au moins une fois par minute sur sa propre tâche ; il indique donc que le processus propriétaire est vivant et qu’il écrit ses données, et non que le délégué progresse. Un délégué bloqué dans un appel d’outil unique conserve un heartbeat récent et est alors borné par son délai d’expiration agentique. La ligne ne dépasse la limite du reaper que si le flusher s’arrête ou si chaque écriture de progression échoue pendant toute la fenêtre ; une ligne dont le processus propriétaire est mort est récupérée par la récupération au démarrage, et non par l’âge du heartbeat. La ligne de tâche rend visible un enfant interrompu, mais ne recrée pas son exécution.

Les fichiers de résultats de délégation hérités qui contiennent un statut restent lisibles lorsqu’aucune ligne de tâche n’existe. Les lignes de délégation terminales créées avant l’enregistrement de originator_route restent également lisibles par identifiant de tâche exact, y compris la sortie en ligne. Elles ne peuvent pas être annulées ni modifiées d’une autre manière par l’exception héritée, et une ligne à origine NULL non terminale reste masquée. Les lignes écrites avant l’existence de la chaîne d’origine conservent une chaîne vide et restent réservées au créateur via originator_route. Les nouvelles lignes admettent l’alias créateur et chaque alias ancêtre enregistré dans leur chaîne, pour les lectures comme pour les modifications.

Contrat cible du mode objectif

ADR-008 établit le plan de contrôle des tâches comme la future autorité pour le cycle de vie des objectifs, la propriété, la route, le principal, la relation parente et l’éligibilité à la récupération. Le dépôt contient le stockage des objectifs et les API du plan de contrôle, mais l’admission et l’exécution des objectifs en production ne sont pas encore intégrées de bout en bout.

Un chemin d’arrière-plan ne peut participer au mode objectif qu’après avoir préservé la relation d’objectif propriétaire et lui avoir signalé l’état terminal et l’utilisation du modèle. Jusqu’alors, ce chemin constitue un travail d’arrière-plan ordinaire plutôt qu’une exécution en mode objectif.

Liste de contrôle des modifications

Pour les modifications liées aux tâches en arrière-plan, répondez aux points suivants avant la validation par le relecteur :

  • Quel sous-système gère le cycle de vie et quel magasin fait autorité ?
  • Le traitement est-il local au processus, supervisé de manière durable ou réellement reprenable après redémarrage ?
  • Quel jeton ou quelle action du plan de contrôle l’annule, et qu’est-ce qui peut rester en cours d’exécution ?
  • Quels champs de tâche parente, d’agent, de route, de principal, de profondeur de récursion et d’utilisation ce chemin renseigne-t-il réellement ?
  • Les états d’attente, d’approbation, de point de contrôle, perdus, expirés et terminaux sont-ils distinguables ?
  • La récupération au démarrage peut-elle dupliquer un effet de bord ou laisser silencieusement une revendication en suspens ?
  • La livraison du résultat reste-t-elle idempotente si l’achèvement est observé après un redémarrage ?

Pointeurs source

  • Planificateur Cron et persistance : crates/zeroclaw-runtime/src/cron/scheduler.rs, crates/zeroclaw-runtime/src/cron/store.rs
  • Moteur SOP et stockages des exécutions : crates/zeroclaw-runtime/src/sop/engine.rs, crates/zeroclaw-runtime/src/sop/store/
  • Comportement de délégation et des sous-agents : Délégation et sous-agents, crates/zeroclaw-runtime/src/tools/delegate.rs, crates/zeroclaw-runtime/src/tools/spawn_subagent.rs, crates/zeroclaw-runtime/src/subagent/mod.rs
  • Plan de contrôle des tâches durables et récupération : crates/zeroclaw-runtime/src/control_plane/
  • Décision du mode objectif : ADR-008
  • Guide de l’opérateur SOP : Fonctionnement des SOP