docs: job-DAG queue model; fold agent_power table into broker.sqlite

coordinator.md rewrites the queue section (node inventory, DAG shapes,
resources, desired-state reconciliation, boot reconcile); approvals.md
+ persistence.md + hivectl --graceful help updated to match. agent_power
lives in broker.sqlite like approvals/questions (own connection + busy
timeout) instead of a separate db file.
This commit is contained in:
müde 2026-07-06 20:27:44 +02:00
commit 604e1c2557
8 changed files with 293 additions and 203 deletions

View file

@ -336,50 +336,49 @@ approval id to retry. Because tags are first-class git objects,
rejected and failed trees stay browsable forever — `git log
--tags` in the applied repo is the audit trail.
### Dispatch via `rebuild_queue`
### Dispatch via the job queue
Long-running approval work — `ApplyCommit`, `UpdateMetaInputs`,
`Spawn` — no longer runs inline inside `actions::approve`. Instead
the approval handler enqueues a `QueueEntry` into the global
`rebuild_queue`:
the approval handler submits a DAG to the global job queue
(`docs/coordinator.md::Job queue`):
| `ApprovalKind` | `QueueKind` queued | `QueueSource` |
| `ApprovalKind` | DAG submitted | source |
|---|---|---|
| `ApplyCommit` | `Rebuild` | `Approval` |
| `MergeConfigPr` | `Rebuild` | `Approval` |
| `UpdateMetaInputs` | `MetaUpdate` | `Approval` |
| `Spawn` | `Spawn` | `Approval` |
| `ApplyCommit` | `rebuild` (single opaque `ApprovalDeploy` node) | `approval` |
| `MergeConfigPr` | `rebuild` (single opaque `ApprovalDeploy` node) | `approval` |
| `UpdateMetaInputs` | `meta_update` (`MetaLock` + rebuild fan-out) | `approval` |
| `Spawn` | `spawn` (`Create → WriteDropin → Reconcile`) | `approval` |
| `InitConfig` | — runs inline (sub-second git seed) | — |
| `SchedulePrompt` | — runs inline (single sqlite insert) | — |
Each queue entry carries the originating `approval_id` so the
worker can re-fetch the approval row when it dispatches, run the
kind-specific pipeline (`run_approval_apply_commit` /
`run_approval_merge_config_pr` / `run_approval_update_meta_inputs` /
`run_approval_spawn`), and
fire the matching `HelperEvent::*` on completion via
`finish_approval`.
The DAG carries the originating `approval_id`. The `ApprovalDeploy`
node runs the kind-specific pipeline (`run_approval_apply_commit` /
`run_approval_merge_config_pr` — the two-phase meta deploy stays
inside `actions.rs`) and fires the matching `HelperEvent::*` via
`finish_approval` itself; `Spawn` and `UpdateMetaInputs` DAGs resolve
through `actions::resolve_approval_dag` when the DAG settles terminal
(a spawn additionally runs the post-spawn forge bookkeeping there).
Two visible consequences:
- **Operator dashboard**: after clicking APPR0VE the work-in-progress
shows up on the *rebuild queue* card (`POST /api/state.rebuild_queue`
shows up on the *rebuild queue* card (`/api/state.rebuild_queue`
+ live `rebuild_queue_changed` events), not on the approvals panel
(which already moved the row to "approved"). A long meta-update
cascade renders as a parent entry with one child per per-agent
rebuild — see `docs/web-ui.md` for the layout.
- **Cancellation**: the dashboard's *× cancel* button on a `Queued`
entry calls `POST /api/rebuild-queue/{id}/cancel`, which flips the
entry to `Cancelled` before the worker dispatches it. Returns
`{"cancelled": true}` on success, `{"cancelled": false}` if the
entry already left `Queued` (running / done / failed) — terminal
states can't be retroactively rewritten.
cascade renders as a parent DAG with one child rebuild per affected
agent — see `docs/web-ui.md` for the layout.
- **Cancellation**: the dashboard's *× cancel* button on a still-queued
DAG calls `POST /api/rebuild-queue/{id}/cancel`, which flips it to
`Cancelled` before any node runs (and fails the approval row instead
of leaving it dangling). Returns `{"cancelled": true}` on success,
`{"cancelled": false}` once any node started — terminal states can't
be retroactively rewritten.
`QueueSource::Approval` carries the `approval_id` so a tail-end
build failure surfaces back as a failed approval row, not just a
silent queue entry. `QueueSource::Manual` (dashboard ↻ R3BU1LD)
and `QueueSource::AutoUpdate` (boot-time sweep) use the same
queue but skip the approval row plumbing.
The `approval` source + `approval_id` mean a tail-end build failure
surfaces back as a failed approval row, not just a silent queue
entry. `manual` (dashboard ↻ R3BU1LD) and `auto_update` (boot
reconcile) DAGs use the same queue but skip the approval plumbing.
### Forge mirror