Ciclo de vida del trabajo en segundo plano
ZeroClaw tiene varias formas de continuar el trabajo después de la solicitud entrante que lo inició. Los trabajos cron, las ejecuciones de SOP, las tareas delegadas y los subagentes generados en tiempo de ejecución comparten cierta maquinaria de ejecución, pero no comparten un ciclo de vida ni un almacén duradero. El modo objetivo define un contrato de destino relacionado que aún no está conectado de extremo a extremo.
Utiliza esta página cuando un cambio añada trabajo programado o autónomo, introduzca un estado de espera o aprobación, modifique el comportamiento de cancelación o reinicio, o conecte trabajo secundario con una tarea propietaria. La primera pregunta de diseño no es «¿cómo se ejecuta en segundo plano?», sino «¿qué subsistema posee su ciclo de vida?».
Mapa de propiedad
| Tipo de trabajo | Propietario actual o superficie de estado | Registros duraderos |
|---|---|---|
| Tarea cron | Programador de Cron y almacenamiento | data/cron/jobs.db |
| Ejecución de SOP | SopEngine y SopRunStore | Memoria de proceso por defecto; data/sop/runs.db cuando la inicialización duradera de SQLite tiene éxito |
| Delegación en segundo plano | Plano de control de tareas duradero | Una fila de tarea requerida en data/control_plane.db; contenido de salida en <workspace>/delegate_results/<task-id>.json |
| Subagente generado en tiempo de ejecución | Generar sitio, con supervisión del plano de control cuando esté disponible | Una fila de tarea de mejor esfuerzo en data/control_plane.db bajo un daemon iniciado |
Los metadatos duraderos no son lo mismo que la ejecución duradera. Un archivo de resultados o una fila de tarea puede conservar lo que se sabía y permitir que la recuperación marque el trabajo como perdido, agotado por tiempo de espera o terminal, sin conservar el futuro local al proceso que estaba realizando el trabajo.
Trabajos cron
Cron combina la pertenencia declarativa con un almacén de ejecución SQLite. Tanto las tareas creadas en tiempo de ejecución como las tareas de configuración reconciliadas llevan un agent_alias propietario; la ejecución resuelve la política de seguridad de ese agente en lugar de ejecutarse con una identidad de daemon del entorno.
El planificador sondea filas vencidas, habilitadas y sin reclamar. Reclamar una fila evita la selección duplicada mientras está en curso. La finalización registra una salida acotada y luego reprograma un trabajo recurrente, elimina un trabajo único de eliminación automática exitoso o deshabilita otro trabajo único. Si el proceso termina antes de liberar una reclamación, el siguiente inicio del planificador limpia el bloqueo obsoleto.
El comportamiento de inicio es explícito. Con catch-up habilitado, los trabajos vencidos se consideran para su ejecución. De lo contrario, un one-shot vencido se deshabilita con un resultado skipped, mientras que un trabajo recurrente avanza a su siguiente aparición futura sin registrar un resultado de ejecución. El planificador comprueba su token de cancelación entre iteraciones de sondeo, por lo que el apagado espera a que termine el lote actual de trabajos vencidos antes de que el bucle finalice. Cancelar el planificador no es una garantía de que un efecto secundario externo ya despachado pueda revertirse.
ejecuciones de SOP
Las definiciones de SOP se encuentran en el directorio sops configurado. SopEngine gestiona el avance de las ejecuciones, las esperas de aprobación, los puntos de control, las transiciones terminales y la superficie de estado en proceso. SopRunStore es la fuente de verdad de la concurrencia cuando admite y reclama una ejecución.
La persistencia de ejecuciones es opcional. Con el valor predeterminado sop.persist_runs = false, el motor utiliza un almacén en memoria. Cuando la persistencia está habilitada, el backend SQLite predeterminado escribe runs.db en <data_dir>/sop a menos que run_state_dir lo reemplace. Una inicialización correcta del almacén permite que las instantáneas activas, los registros terminales, los eventos, las revisiones y las reclamaciones de concurrencia admitan la restauración tras un reinicio. Si la inicialización del almacén falla, el daemon registra una advertencia y recurre al almacén en memoria.
Los registros de auditoría SOP en el backend de Memory son una superficie de observabilidad independiente. No reemplazan el almacén de ejecuciones y no deben usarse como autoridad para determinar si una ejecución está activa, en pausa, aprobada o en estado terminal.
Los estados de aprobación y de punto de control son estados de control duraderos únicamente cuando el almacén de ejecuciones es duradero. La política de tiempo de espera permanece fail-closed de forma predeterminada: una aprobación que ha excedido el tiempo de espera se escala y sigue esperando, a menos que la configuración seleccione explícitamente la cancelación o el comportamiento heredado de auto-aprobación.
Delegación y subagentes
Los subagentes heredan el límite de seguridad efectivo de su elemento padre. Las anulaciones de política y de memoria pueden reducir el ámbito del padre, pero no ampliarlo, y la contabilización de acciones del hijo utiliza el rastreador del padre, de modo que la creación de hijos no puede eludir el presupuesto de acciones del padre.
La ruta de spawn_subagent es síncrona: el proceso padre espera a que finalice la ejecución del hijo, y esta ruta no tiene un tiempo de espera local ni un manejador de cancelación en segundo plano.
La herramienta delegate puede ejecutarse de forma síncrona o iniciar una tarea en segundo plano y devolver un UUID. Una tarea en segundo plano solo se inicia después de abrir el plano de control duradero, resolver el alias de su agente propietario y registrar su fila de tarea. La fila es la única autoridad del ciclo de vida para los estados de ejecución, terminación, error y recuperación. El contenido de la salida completada se escribe de forma atómica en el workspace pasado a la herramienta; la fila de tarea almacena su referencia al artefacto en lugar de duplicar el contenido.
Los lectores actuales siguen siendo compatibles con los artefactos heredados que contienen estado y con la salida heredada de tareas en línea. Lo contrario no está garantizado: los artefactos escritos en el formato actual, que solo contiene salida, no se pueden leer con binarios o scripts anteriores que requieren campos de ciclo de vida incrustados. Revierta el directorio de datos y los artefactos del espacio de trabajo juntos, o finalice el trabajo en segundo plano pendiente antes de volver a una versión anterior.
Un registro de cancelación activo asocia los IDs de tareas con tokens locales al proceso. La cancelación señala la tarea en ejecución cuando ese token todavía está disponible y utiliza una transición terminal compare-and-set en el almacén de tareas. Por tanto, la finalización, el fallo, la cancelación y la recuperación no pueden sobrescribirse entre sí una vez que un resultado terminal se ha impuesto.
Antes de que un delegado en segundo plano publique un artefacto de salida terminal, serializa los bytes exactos, calcula su resumen SHA-256 y persiste una intención de liquidación terminal que contiene el id de la tarea, el PID y la identidad de arranque del propietario actual, el estado terminal deseado, la ruta o referencia del artefacto, el resumen y el error terminal. La intención es una transición no aplicada; TaskRecord.status sigue siendo la única autoridad de ciclo de vida persistida.
El delegado escribe y sincroniza después, de forma atómica, exactamente esos bytes. Una única transacción de SQLite compara la fila de la tarea, que aún no es terminal y cuyo propietario coincide, con la intención, registra el estado terminal deseado y la carga útil, y elimina la intención sin cambios. Los fallos del almacenamiento anteriores a la persistencia de la intención reintentan sin publicar el artefacto; los fallos posteriores a la publicación reintentan la promoción en el propio proceso. Una cancelación concurrente u otro ganador terminal se conserva y elimina la intención obsoleta.
Un supervisor independiente espera el handle de tarea de Tokio exacto del worker en segundo plano. Si ese worker entra en pánico o es abortado mientras el proceso padre sigue activo, el supervisor recupera únicamente su tarea y el propietario registrado. Valida cualquier intención de liquidación persistida con las mismas comprobaciones de artefactos que usa la recuperación de procesos; una salida ausente o corrupta se resuelve como Failed, y una salida anterior a la persistencia de la intención se resuelve como un resultado Failed vinculado al propietario. Los errores del almacén se reintentan con backoff limitado. Un worker activo nunca se recupera, y un ganador terminal competidor o un propietario transferido no pueden sobrescribirse. Esto utiliza evidencia directa de salida del worker en lugar de un timeout de heartbeat ni de un nuevo lease.
El inicio y la recuperación periódica procesan las intenciones de liquidación antes de la reconciliación ordinaria de Lost. La recuperación solo actúa después de comprobar que el propietario registrado está ausente o que su PID ha sido reutilizado, valida los bytes del artefacto frente al digest registrado y resuelve un artefacto ausente o corrupto de forma conservadora como Failed con un error de persistencia/recuperación, en lugar de producir Completed. El nonce aleatorio del proceso no es observable mediante las API del sistema operativo, por lo que el PID junto con la hora de inicio del sistema operativo sigue siendo conservador ante la reutilización de PID dentro del mismo segundo: la recuperación trata ese caso como el mismo propietario.
Las filas actuales de delegate y subagent contienen agent, status, el PID del proceso propietario y su identidad de proceso, depth y las marcas de tiempo. Las filas de delegate también registran el alias del agente creador, la cadena ordenada de alias de los llamadores por encima de él y la clave de sesión del bucle de herramientas como principal. Las acciones de resultado, espera, listado y cancelación admiten un alias que creó la fila o que aparece en cualquier punto de esa cadena, mientras que la clave de sesión es solo forense y nunca se consulta en la comprobación de propietario. Las filas de subagent siguen dejando route, chain y principal sin valor. Ambas dejan la tarea padre sin valor. Las filas de delegate en segundo plano llevan un heartbeat mientras se ejecutan: cada escritura de progreso lo actualiza, al menos una vez por minuto, de modo que el timeout por antigüedad del heartbeat del reaper se aplica a ellas. Las filas de subagent siguen dejando heartbeat sin valor. La recuperación al inicio marca una fila en ejecución como lost solo cuando el proceso propietario registrado está demostrablemente terminado o su PID ha sido reutilizado; si la propiedad es incierta, falla en modo seguro. La recuperación en Windows distingue un PID inexistente de los sondeos con acceso denegado o ambiguos, y conserva la fila cuando no se puede demostrar la ausencia. timed_out se aplica solo a los productores que emiten heartbeats: los delegates en segundo plano lo hacen, los subagents no. El heartbeat de un delegate en segundo plano procede de su hilo de volcado de progreso, que reescribe la fila al menos una vez por minuto en su propia tarea, así que indica que el proceso propietario está vivo y volcando datos, no que el delegate avance. Un delegate bloqueado dentro de una llamada a herramienta mantiene un heartbeat reciente y queda acotado por su timeout agéntico. La fila supera el límite del reaper solo si el volcador se detiene o si todas las escrituras de progreso fallan durante toda la ventana. Una fila cuyo proceso propietario murió es recuperada por la recuperación al inicio, no por la antigüedad del heartbeat. La fila de tarea hace visible un hijo interrumpido, pero no recrea su ejecución.
Los archivos de resultados de delegados heredados que contienen status siguen siendo legibles cuando no existe ninguna fila de tarea. Las filas de delegados terminales creadas antes de que se registrara originator_route también siguen siendo legibles por ID de tarea exacto, incluida la salida en línea. No se pueden cancelar ni modificar de otro modo mediante la excepción heredada, y una fila de origen NULL no terminal sigue oculta. Las filas escritas antes de que existiera la cadena de originadores conservan una cadena vacía y siguen siendo solo para el creador mediante originator_route. Las filas nuevas admiten el alias creador y cada alias ancestro registrado en su cadena, tanto para lecturas como para modificaciones.
Contrato de destino en modo objetivo
ADR-008 acepta el plano de control de tareas como la autoridad futura para el ciclo de vida de objetivos, la propiedad, la ruta, el principal, la relación con el padre y la elegibilidad de recuperación. El repositorio contiene almacenamiento de objetivos y APIs del plano de control, pero la admisión y ejecución de objetivos en producción aún no están conectadas de extremo a extremo.
Una ruta en segundo plano puede participar en el modo de objetivo solo después de conservar la relación con el objetivo propietario e informarle el estado terminal y el uso del modelo. Hasta entonces, esa ruta es trabajo ordinario en segundo plano en lugar de ejecución en modo de objetivo.
Lista de verificación de cambios
Para los cambios de trabajo en segundo plano, responde estas preguntas antes de que el revisor apruebe:
- ¿Qué subsistema controla el ciclo de vida y qué almacén es el autoritativo?
- ¿El proceso de trabajo es local, tiene supervisión duradera o realmente puede reanudarse tras un reinicio?
- ¿Qué token o acción del plano de control lo cancela, y qué puede quedar en tránsito?
- ¿Qué campos de tarea padre, agente, ruta, principal, profundidad de recursión y uso puebla realmente esta ruta?
- ¿Se pueden distinguir los estados de espera, aprobación, punto de control, perdido, tiempo de espera agotado y terminal?
- ¿Puede la recuperación al inicio duplicar un efecto secundario o dejar un reclamo bloqueado silenciosamente?
- ¿La entrega de resultados sigue siendo idempotente si se observa la finalización después de un reinicio?
Punteros de origen
- Planificador cron y persistencia:
crates/zeroclaw-runtime/src/cron/scheduler.rs,crates/zeroclaw-runtime/src/cron/store.rs - Motor SOP y almacenes de ejecución:
crates/zeroclaw-runtime/src/sop/engine.rs,crates/zeroclaw-runtime/src/sop/store/ - Delegación y comportamiento de los subagentes: Delegación y subagentes,
crates/zeroclaw-runtime/src/tools/delegate.rs,crates/zeroclaw-runtime/src/tools/spawn_subagent.rs,crates/zeroclaw-runtime/src/subagent/mod.rs - Plano de control de tareas persistentes y recuperación:
crates/zeroclaw-runtime/src/control_plane/ - Decisión del modo de objetivos: ADR-008
- Guía del operador de SOP: Cómo funcionan los SOP