lifecycle
lifecycle
¶
Task lifecycle — create, rename, delete, archive-on-delete, stop, login,
and the status display. These are the state-mutating and interactive
operations, layered on top of the meta
I/O boundary and the query read models.
__all__ = ['TaskDeleteResult', 'capture_task_logs', 'get_login_command', 'task_delete', 'task_login', 'task_new', 'task_rename', 'task_status', 'task_stop', 'wait_for_container_exit']
module-attribute
¶
TaskDeleteResult(task_id, warnings)
dataclass
¶
Outcome of a task deletion — always completes, collects warnings.
The task is considered deleted regardless (metadata and workspace
removed), but individual cleanup steps may fail. warnings
carries human-readable descriptions of any steps that did not
complete cleanly.
task_new(project_id, *, name=None)
¶
Create a new task with a fresh workspace for a project.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
project_id
|
str
|
The project to create the task under. |
required |
name
|
str | None
|
Optional human-readable name. Allowed characters are
lowercase letters, digits, hyphens, and underscores.
If |
None
|
Workspace Initialization Protocol:¶
Each task gets its own workspace directory that persists across container runs. When a container starts, the init script (init-ssh-and-repo.sh) needs to know whether this is:
- A NEW task that should be reset to the latest remote HEAD
- A RESTARTED task where local changes should be preserved
We use a marker file (.new-task-marker) to signal intent:
- task_new() creates the marker in the workspace directory
- init-ssh-and-repo.sh checks for the marker:
- If marker exists: reset to origin/HEAD, then delete marker
- If no marker: fetch only, preserve local state
- Subsequent container runs on the same task won't see the marker, so local work is preserved
This handles edge cases like: - Stale workspace from incompletely deleted previous task with same ID - Ensuring new tasks always start with latest code
Source code in src/terok/lib/orchestration/tasks/lifecycle.py
task_rename(project_id, task_id, new_name)
¶
Rename a task by updating its metadata file.
Sanitizes new_name and writes the result to the task's metadata file.
Raises SystemExit if the task is unknown or the sanitized name is invalid.
Source code in src/terok/lib/orchestration/tasks/lifecycle.py
capture_task_logs(project, task_id, mode)
¶
Capture container logs to the task's logs/ directory on the host.
Writes stdout/stderr from podman logs to
<tasks_root>/<task_id>/logs/container.log. Returns the log file
path on success, or None if the container doesn't exist or podman
fails.
project may be a ProjectConfig or a project-ID string
(the string form loads the config internally for backward compat).
Source code in src/terok/lib/orchestration/tasks/lifecycle.py
task_delete(project_id, task_id)
¶
Delete a task's workspace, metadata, and any associated containers.
Before removal, captures container logs and archives the task metadata
and logs to archive/<project_id>/tasks/. Containers are stopped
best-effort via podman using the <project.id>-<mode>-<task_id>
naming scheme. Returns a TaskDeleteResult so the caller can
present any warnings from cleanup steps that failed.
Source code in src/terok/lib/orchestration/tasks/lifecycle.py
get_login_command(project_id, task_id)
¶
Return the podman exec command to log into a task container.
task_login(project_id, task_id)
¶
task_stop(project_id, task_id, *, timeout=None)
¶
Gracefully stop a running task container.
Uses podman stop --time <N> to give the container timeout seconds
before SIGKILL. When timeout is None the project's
run.shutdown_timeout setting is used (default 10 s).
Source code in src/terok/lib/orchestration/tasks/lifecycle.py
task_status(project_id, task_id)
¶
Show live task status with container state diagnostics.
Source code in src/terok/lib/orchestration/tasks/lifecycle.py
wait_for_container_exit(container_name, project_id, task_id, timeout=7200)
¶
Wait for container_name to exit and record its code in task metadata.
Returns (exit_code, error_message). On a successful wait
error_message is None and the real exit code is persisted
— including a legitimate exit code of 124, which is no longer
conflated with the watcher's own timeout. On timeout exit_code
is None and the error message describes it.