docs: scheduled prompts are swarm-level; the hive page is a read-only list
Drops docs/tools/scheduling.md and every description of hive-level schedule creation, the worker, the removed MCP tools, the scheduling tool group and the removed endpoints/events, pointing at docs/swarm/schedules.md.
This commit is contained in:
parent
a4a3f81d5c
commit
b4a2aeb5ba
18 changed files with 90 additions and 346 deletions
|
|
@ -1,7 +1,8 @@
|
|||
# Approvals + helper events
|
||||
|
||||
The approval queue is where an agent asks the operator for something it
|
||||
can't do itself: a scheduled prompt, or a meta-input bump. Config
|
||||
can't do itself. Nothing submits a new approval today: the one kind
|
||||
left, a meta-input bump, only reads back from existing rows. Config
|
||||
changes don't go through this queue: they're pull requests
|
||||
on the agent's config repo, which an operator merges on the forge, and
|
||||
that merge deploys them. The submitting agent — any agent with the
|
||||
|
|
@ -16,13 +17,6 @@ it stays informed about what happens after a decision lands.
|
|||
config (or its own, via a sub-manager) as a pull request on
|
||||
`agent-configs/<agent>`. Review it on the forge like any other PR, and
|
||||
merge it there to deploy it. See [Config changes](#config-changes).
|
||||
- **Scheduled prompt** (`SchedulePrompt`) — an agent asked to schedule
|
||||
a message to one or more inboxes at a future time. It lands on your
|
||||
dashboard's Y3R C4LL tab (or `hivectl approvals pending` /
|
||||
`approve <id>` from the CLI). You can also add schedules yourself
|
||||
directly from the SCH3DUL3S tab, which skips this approval step
|
||||
entirely — the gate here is specifically for an *agent* asking to
|
||||
schedule something, not for you doing it.
|
||||
- **Meta/flake update** (`UpdateMetaInputs`) — an existing row reads
|
||||
back and you can approve it. Approving runs the update and commits
|
||||
the lock change; it doesn't rebuild anything by itself.
|
||||
|
|
@ -113,9 +107,8 @@ merged by an operator on the forge (see [Config changes](#config-changes)).
|
|||
|
||||
### Approval kinds (wire shapes)
|
||||
|
||||
`ApprovalKind` carries two variants; each maps to a different
|
||||
`commit_ref` encoding because `ApprovalKind` overloads that field as
|
||||
the kind-specific payload carrier.
|
||||
`ApprovalKind` carries one variant, and it overloads `commit_ref` as
|
||||
its payload carrier.
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
- `UpdateMetaInputs` — `commit_ref` stores the JSON-encoded inputs
|
||||
|
|
@ -123,64 +116,8 @@ the kind-specific payload carrier.
|
|||
etc.). hive-c0re sets the `agent` field to the requesting root agent.
|
||||
On approve hive-c0re runs `nix flake update [inputs...]` on the
|
||||
meta flake and commits the resulting lock changes.
|
||||
- `SchedulePrompt` — `commit_ref` stores the JSON-encoded
|
||||
`SchedulePromptPayload` (target list, body, schedule) so the
|
||||
approval row carries the full submission verbatim. On approve
|
||||
hive-c0re inserts a row into `scheduled_prompts` with
|
||||
`source = approval:<id>`; the worker fans the body out as
|
||||
inbox messages to each target at the scheduled time, recurring
|
||||
when `interval_seconds` is set.
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
### Scheduled prompts (submit paths)
|
||||
|
||||
Two ways a row lands in `scheduled_prompts`:
|
||||
|
||||
- **Operator-direct** (`source = "operator"`): the operator adds a schedule through the dashboard form. Lands in the table immediately, no approval gate — operator action is already the trust boundary.
|
||||
- **Agent-requested** (`source = "approval:<id>"`): an agent submits a `RequestSchedulePrompt` through its MCP socket (the `request_schedule_prompt` tool, `scheduling` group). hive-c0re queues an `ApprovalKind::SchedulePrompt` row; on approve, it inserts the schedule row with `source = approval:<id>` so the audit trail points back at the operator decision (above).
|
||||
|
||||
No self-target shortcut: even agent-self schedules need approval. The existing `remind` MCP tool stays the quick self-wake path (no approval, lands directly in the agent's own inbox); this module is the bigger, multi-recipient, operator-visible thing.
|
||||
|
||||
### Scheduled prompt worker (catch-up clamp)
|
||||
|
||||
When hive-c0re comes back from being down, the worker sees rows whose `next_fire_at_unix` is well in the past. For recurring rows that would mean firing N delayed pulses in a row — spammy and useless. Instead the worker fires **once** per row and bumps `next_fire_at_unix` to the next interval slot ≥ `now`, recording how many cycles it skipped in `last_result` (per-target). Operators see "fired late, caught up from 17 skipped" instead of 17 wake-up storms.
|
||||
|
||||
The worker fires one-shot rows once (if past due, on the next worker pass) and deletes them; recurring rows survive until cancelled.
|
||||
|
||||
`targets` is its own table (`scheduled_prompt_targets`) so partial cancellation flips a single row and the dashboard can show last-fired / last-result per recipient. Cancelling every target reaps the parent row on the next worker pass.
|
||||
|
||||
### Scheduled prompt delivery: todo, not a broker message
|
||||
|
||||
An agent target's delivery is `push_todo` (`Coordinator::push_todo`,
|
||||
`docs/scheduler/coordinator.md` covers the mechanism generally), not a broker
|
||||
`Message` — a scheduled prompt wakes its target with a todo instead of
|
||||
driving an immediate turn, by design. `key = "schedule:<id>"` per
|
||||
target drives `push_todo`'s own upsert-by-key dedup: a re-fire of the
|
||||
*same schedule* against a target that hasn't reviewed the last one
|
||||
collapses into that one todo instead of stacking up.
|
||||
|
||||
### Missing-target failure
|
||||
|
||||
When a target name doesn't resolve to a known agent (container
|
||||
destroyed, typo, etc.) the worker:
|
||||
|
||||
1. Records `last_result = "no such agent: <name>"` on the
|
||||
per-target row.
|
||||
2. Sends a single advisory `Message` from `system` to `operator`
|
||||
naming the schedule, target, and reason. This one stays a `Message`
|
||||
regardless of target type — it's a to-operator advisory about a
|
||||
broken schedule, not the schedule's own delivery.
|
||||
3. Continues fanning out to the other live targets.
|
||||
|
||||
Transient broker errors (sqlite lock contention, etc.) get the same
|
||||
`last_result` annotation plus a `tracing::warn`, and then:
|
||||
|
||||
- **Recurring rows** re-arm to the next interval slot — the retry
|
||||
self-heals on the next worker pass.
|
||||
- **One-shot rows**: the worker deletes them unconditionally after their single
|
||||
fan-out pass; a broker error on a one-shot isn't retried (the
|
||||
operator advisory and `last_result` are the only audit trail).
|
||||
|
||||
### Reminder delivery: file-path semantics
|
||||
|
||||
A reminder may carry a `file_path` (the agent-visible path inside its
|
||||
|
|
@ -324,7 +261,6 @@ by the approval handler rather than run inline:
|
|||
| `ApprovalKind` | DAG submitted | source |
|
||||
|---|---|---|
|
||||
| `UpdateMetaInputs` | `meta_update` (`MetaLock` + rebuild fan-out) | `approval` |
|
||||
| `SchedulePrompt` | — runs inline (single sqlite insert) | — |
|
||||
|
||||
The DAG carries the originating `approval_id`. **Every** queued kind
|
||||
resolves through `actions::resolve_approval_dag` when its DAG settles
|
||||
|
|
@ -508,10 +444,8 @@ the `submitter` column on the `approvals` table). The harness delivers it
|
|||
as a regular `system` inbox message so it drives a normal claude turn.
|
||||
`finish_approval` fires an `ApprovalResolved` HelperEvent this way for
|
||||
**every** approval kind's terminal state. A
|
||||
"FYI, check when convenient" event doesn't need a message — those go
|
||||
through `Coordinator::push_todo` instead, a direct live dial of the target
|
||||
agent's in-container todo socket (same `UpsertTodo` request in-container
|
||||
producers use). Legacy
|
||||
"FYI, check when convenient" event doesn't need a message — hive-c0re publishes those as swarm
|
||||
lifecycle notices instead (`swarm_notices::notify`). Legacy
|
||||
approval rows that predate the submitter column fall back to the
|
||||
root agent. Variants (`hive_sh4re::manager::HelperEvent`):
|
||||
|
||||
|
|
@ -533,9 +467,8 @@ root agent. Variants (`hive_sh4re::manager::HelperEvent`):
|
|||
The remaining lower-urgency lifecycle notices — `Rebuilt`, `Killed`,
|
||||
`Destroyed`, `NeedsLogin`, `LoggedIn` — are "FYI, check
|
||||
when convenient" events with no reason to drive an immediate turn, so
|
||||
they deliver via `push_todo` (see above) instead
|
||||
of `HelperEvent`: an `agent_todo_socket` push instead of a broker
|
||||
message, `subsystem = "core"`, `key = "<event>:<agent>"` for dedup,
|
||||
they go out via `swarm_notices::notify` (see above) instead
|
||||
of a `HelperEvent`: `subsystem = "core"`, `key = "<event>:<agent>"`,
|
||||
and a single free-text `summary` (`rebuilt_todo_summary` renders
|
||||
`Rebuilt`'s `ok`/`note`/`sha`/`tag` fields into that string).
|
||||
|
||||
|
|
@ -543,7 +476,7 @@ To add a new lifecycle notice: if it needs to drive an immediate turn
|
|||
(something genuinely urgent, like `ContainerCrash`), add a
|
||||
`HelperEvent` variant + call sites + update `prompts/system.md`'s
|
||||
message-event list. If it's "FYI, check when convenient," call
|
||||
`push_todo` directly instead — no new wire type
|
||||
`swarm_notices::notify` instead — no new wire type
|
||||
needed.
|
||||
|
||||
## Autoupdate on startup
|
||||
|
|
|
|||
Loading…
Reference in a new issue