5.2 KiB
5.2 KiB
Why
Task cancellation has been an explicit, repeatedly-acknowledged gap: cloud-console,
cloud-control-plane-integration, and cloud-console-governance each excluded it from
scope and deferred it to "a later lifecycle capability." Operators currently have no way
to stop a queued, assigned, or in-flight task short of letting it run to completion,
failure, or lease expiry — including tasks stuck against an offline device or a runaway
plan. core/models.py's TaskStatus already reserves a "cancelled" value that no code
path ever sets, and workflow/ already proves the collaborative-stop pattern this change
extends to goal-based cloud tasks.
What Changes
- Add a
cancelledscheduler-side task status (cloud/scheduler.py'sScheduledTaskStatus) reachable fromqueued,assigned, anddispatched. - Add a public SDK endpoint (
POST /v1/tasks/{task_id}/cancel, gated by the existingtasks:submitscope — the repository has no per-task submitter/ownership tracking to authorize against more narrowly) that immediately cancels aqueuedtask and otherwise records a cancellation request against anassigned/dispatchedtask. - Add an internal Host Agent protocol signal:
LeaseRenewalResponsegains acancel_requested: boolfield; the Cloud repository'srenew_leasereports it when the active attempt has a pending cancellation. This is the only new edge on the existing outbound-only Host Agent protocol — no inbound push, no new endpoint on the Host side. - Extend the Host Agent's existing
should_stopcollaborative-stop mechanism (ActiveAssignmentRunner→AssignmentExecutor→TaskRunner/WorkflowRunner) so acancel_requestedsignal observed at lease-renewal time stops execution the same way a lost lease does today, and reports acancelled-flavored terminal result. - Add
"cancelled"as a real, reachable value ofcore/models.py'sTaskStatus(the_interrupt_taskpath already flowing throughshould_stopgains a cancellation-vs-lease-loss distinction) and confirmTerminalResultRequest.statuscan express it end to end. - Add an Alembic migration recording cancellation request/acknowledgement metadata on
scheduled_tasks/task_attempts(requestor, requested-at, and the terminalcancelledoutcome) — no schema change to unrelated tables. - Add a "Cancel" action to the Cloud Console
TasksView.vuetask-detail panel (visible forqueued/assigned/dispatchedtasks the operator is authorized to act on) and to the status filter dropdown; add a matchingPOST /tasks/{id}/cancelroute + button to the Host Agent local console's task detail page for Host-local visibility/action on tasks running on that Host. - BREAKING: none of the existing status literals are renamed or removed;
cancelledis purely additive. Callers that exhaustivelymatch/switch overTaskStatus(Python) orTaskStatus(TypeScript) without a default arm will need to add a case — flagged in design.md's migration plan.
Capabilities
New Capabilities
task-cancellation: cancellation request lifecycle acrosstask-scheduler(queued/ assigned/dispatched states),host-agent-protocol(collaborative cancel signal over lease renewal), andagent-runtime/workflow execution (stopping mid-task on a cancellation signal, distinct from lease loss).
Modified Capabilities
task-scheduler:ScheduledTaskStatusgainscancelled; task submission/assignment requirements are unchanged, but the status-transition requirements need a new terminal transition path fromqueued/assigned/dispatched.host-agent-protocol: the lease-renewal requirement ("Active execution renews its lease") gains a new SHALL for surfacing a cancellation request in the renewal response and treating it as a stop condition alongside lease loss.platform-sdk: new cancel endpoint and scope-authorization requirement; task-status responses gain thecancelledstatus value.cloud-console-ui: task list/detail view gains a Cancel action and thecancelledstatus value in filtering/display.
Impact
- Cloud API / persistence:
packages/cloud-platform/cloud/scheduler.py,repository.py(Protocol),sql_repository.py,db_models.py, new Alembic migration,internal_api/models.py+internal_api/api.py(renew/claim/cancel routes),sdk/api.py+sdk/models.py(new public cancel endpoint),auth.py(scope reuse). - Host Agent:
apps/device-host-agent/host_agent/lease.py(ActiveAssignmentRunnercancellation-aware stop),client.py(surfacecancel_requestedfrom renew response),processor.py/assignment.py(terminal status reporting), local console (host_agent/web/app.py+templates/task_detail.html) new cancel route. - Runtime:
core/models.py(TaskStatusreachability),runtime/task.py(_interrupt_taskcancellation-vs-interruption distinction),workflow/runner.py(reuse of the already-existingcancelledterminal status — no change needed there). - Cloud Console frontend:
cloud-console/src/views/TasksView.vue,src/types.ts,src/api.ts(newcancelTaskclient method). - Docs:
docs/CLOUD_DEPLOYMENT.mdgets a short note on cancellation being collaborative (not instantaneous) and its ~1/3-lease-period latency bound.