feat: dynamic execution mode — Undecided tasks, two-phase dispatch, assign API

- ExecutionMode enum adds Undecided variant (default for new tasks)
- Webhook creates tasks as Undecided instead of hardcoded SshCli
- Dispatch loop: Phase 1 matches ssh_cli hosts, Phase 2 marks remaining as HttpPull
- Dequeue now returns http_pull AND undecided tasks (atomic claim)
- New endpoint: POST /api/v1/tasks/{id}/assign for coordinator explicit assignment
- Backward compatible: existing SshCli/HttpPull tasks unaffected
- 37 tests passing (6 new)
This commit is contained in:
Zer4tul 2026-05-13 05:29:12 +08:00
parent a18cb2824e
commit 48c93e2ce9
13 changed files with 639 additions and 13 deletions

View file

@ -123,7 +123,7 @@ Register → Save credentials to memory → Start heartbeat loop (every 60s, run
- Maximum allowed gap: `heartbeat_interval_secs × heartbeat_timeout_threshold` (default: 180 seconds)
- If you exceed that gap, you will be marked offline and your tasks will be requeued
- This must run for the entire lifetime of the agent, not just once
4. **Dequeue** when ready for work via `POST /api/v1/tasks/dequeue`. Returns a Task or 204 No Content.
4. **Dequeue** when ready for work via `POST /api/v1/tasks/dequeue`. Returns a Task or 204 No Content. The returned task may already be `http_pull` or may have been `undecided` and atomically claimed as `http_pull` during dequeue.
5. **Update status** to `running` via `POST /api/v1/tasks/{task_id}/status`.
6. **Complete** the task via `POST /api/v1/tasks/{task_id}/complete` with a Receipt.
7. **Deregister** when shutting down via `POST /api/v1/agents/deregister`.
@ -179,7 +179,7 @@ curl -X POST http://FLEET_API_URL:PORT/api/v1/tasks/dequeue \
-d '{"agent_id": "worker-03", "capabilities": ["code:rust"]}'
```
Returns 200 with Task JSON, or 204 if no matching task.
Returns 200 with Task JSON, or 204 if no matching task. Dequeue may return tasks that were previously `undecided`; if so, the Orchestrator updates them to `http_pull` as part of the same claim.
### Get Task Detail