docs(openspec): sync cloud control plane specs

This commit is contained in:
2026-07-13 08:58:04 +08:00
parent ea9b15fce7
commit 70d15f8f0b
5 changed files with 265 additions and 11 deletions
+41 -5
View File
@@ -51,10 +51,46 @@ The system SHALL provide a `TaskDispatcher` that, for an assignment whose device
- **WHEN** `TaskDispatcher.dispatch()` is called with an assignment referencing a `WorkflowDefinition` whose device is local
- **THEN** the dispatcher runs the definition through the existing workflow-execution entry point and updates the `ScheduledTask`'s status based on the resulting workflow run's outcome
### Requirement: Remote assignments are rejected explicitly, not silently ignored
The system SHALL raise a distinct, typed error when `TaskDispatcher.dispatch()` is called for an assignment whose device is owned by a host other than the dispatching process's own host, rather than attempting execution or silently no-op'ing.
### Requirement: Assignment and device reservation are atomic
The scheduler SHALL atomically bind a queued task to one eligible device, create a bounded lease attempt, and reserve that device so no other active task can be assigned to it.
#### Scenario: Assignment targets a remote host's device
- **WHEN** `TaskDispatcher.dispatch()` is called with an assignment whose `host_id` does not match the local process's own host id
- **THEN** the dispatcher raises a `RemoteDispatchNotSupportedError` and leaves the `ScheduledTask`'s status unchanged from `assigned`
#### Scenario: Scheduler assigns an idle device
- **WHEN** a queued task matches an idle pooled device with no active reservation
- **THEN** one transaction records the assigned task, owning host/device, incremented attempt, lease identifier, lease expiry, and device reservation
#### Scenario: Later scheduler iteration sees stale idle snapshot
- **WHEN** the host snapshot still reports a device idle but that device has an active assignment lease
- **THEN** the scheduler excludes the device from candidates for every other queued task
### Requirement: Host claim transitions assigned work to dispatched
The scheduler repository SHALL allow only the authenticated owning host to atomically claim an unexpired assigned attempt and transition it to `dispatched`.
#### Scenario: Owning host claims once
- **WHEN** the owning host requests available work and an unexpired assigned attempt exists
- **THEN** exactly one request receives the assignment and its status becomes dispatched
#### Scenario: Concurrent claims race
- **WHEN** multiple requests concurrently attempt to claim the same assignment
- **THEN** at most one request succeeds and every other request receives no assignment or a conflict
### Requirement: Expired attempts follow bounded retry policy
The system SHALL detect expired assigned or dispatched leases and SHALL either requeue the task with its reservation released or mark it failed when the configured attempt limit is reached.
#### Scenario: Lease expires with attempts remaining
- **WHEN** an active lease expires before a terminal result and the task has remaining attempts
- **THEN** the task returns to queued, the previous device reservation is released, and the expired attempt remains auditable
#### Scenario: Lease expires at attempt limit
- **WHEN** an active lease expires and the task has reached its maximum attempts
- **THEN** the task becomes failed with a lease-expiry reason and its device reservation is released
### Requirement: Terminal transitions validate the active lease
The system SHALL accept a `done` or `failed` result only from the current active task attempt and lease and SHALL make repeated identical terminal reports idempotent.
#### Scenario: Active lease reports completion
- **WHEN** the active lease owner reports a terminal result
- **THEN** the task transitions once to done or failed and releases its device reservation
#### Scenario: Superseded lease reports completion
- **WHEN** a result references a lease superseded by expiry and retry
- **THEN** the result is rejected and cannot overwrite the current task attempt