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
|
|
@ -31,8 +31,8 @@ hand-maintained per-file tree drifts out of sync with the code.
|
||||||
user). `src/main.rs` is the `hive-c0re` binary — **daemon-only**
|
user). `src/main.rs` is the `hive-c0re` binary — **daemon-only**
|
||||||
(`serve` + the periodic vacuum/sweep loops); the operator CLI lives in
|
(`serve` + the periodic vacuum/sweep loops); the operator CLI lives in
|
||||||
the separate `hivectl` crate, which talks to the daemon over the host
|
the separate `hivectl` crate, which talks to the daemon over the host
|
||||||
admin socket. Owns the sqlite broker, approval + reminder +
|
admin socket. Owns the sqlite broker, approval + reminder
|
||||||
schedule queues, the meta flake, lifecycle (`nixos-container`
|
queues, the meta flake, lifecycle (`nixos-container`
|
||||||
shellouts), gateway / forge / matrix wiring (agent forge and matrix
|
shellouts), gateway / forge / matrix wiring (agent forge and matrix
|
||||||
accounts are `swarm-controller`'s), per-container stats, and the axum
|
accounts are `swarm-controller`'s), per-container stats, and the axum
|
||||||
operator dashboard (`dashboard/`). Largest crate.
|
operator dashboard (`dashboard/`). Largest crate.
|
||||||
|
|
|
||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -1769,7 +1769,6 @@ dependencies = [
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"forgejo-api",
|
"forgejo-api",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hive-agent-sock",
|
|
||||||
"hive-core-agent-sock",
|
"hive-core-agent-sock",
|
||||||
"hive-host-sock",
|
"hive-host-sock",
|
||||||
"hive-jobq",
|
"hive-jobq",
|
||||||
|
|
@ -1777,7 +1776,6 @@ dependencies = [
|
||||||
"hive-log",
|
"hive-log",
|
||||||
"hive-priv-sock",
|
"hive-priv-sock",
|
||||||
"hive-sh4re",
|
"hive-sh4re",
|
||||||
"hive-sock-client",
|
|
||||||
"hive-types",
|
"hive-types",
|
||||||
"hmac 0.13.0",
|
"hmac 0.13.0",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ sudo inside the cage) and a durable, self-compacting session. Out of the
|
||||||
box it gets:
|
box it gets:
|
||||||
|
|
||||||
- **messaging** — `send` / `recv` to other agents and the operator,
|
- **messaging** — `send` / `recv` to other agents and the operator,
|
||||||
`remind` and recurring schedules to wake itself, and a todo list that
|
`remind` to wake itself, scheduled prompts the operator sets for it at
|
||||||
forge notifications and other producers feed. →
|
swarm level, and a todo list that forge notifications and other
|
||||||
[scheduling](docs/tools/scheduling.md)
|
producers feed. → [schedules](docs/swarm/schedules.md)
|
||||||
- **background bash** — long-running commands as tracked tasks
|
- **background bash** — long-running commands as tracked tasks
|
||||||
(`run` / `status` / `kill`), so a build doesn't block the turn. →
|
(`run` / `status` / `kill`), so a build doesn't block the turn. →
|
||||||
[bash](docs/tools/bash.md)
|
[bash](docs/tools/bash.md)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ declarations.
|
||||||
go deeper into implementation.
|
go deeper into implementation.
|
||||||
- **What tools does an agent (or the operator) have available?** →
|
- **What tools does an agent (or the operator) have available?** →
|
||||||
[`tools/`](tools/README.md) — `hivectl` (yours) plus every agent's MCP
|
[`tools/`](tools/README.md) — `hivectl` (yours) plus every agent's MCP
|
||||||
tool surface (bash, forge, lifecycle, matrix, scheduling).
|
tool surface (bash, forge, lifecycle, matrix).
|
||||||
|
|
||||||
## Agent lifecycle
|
## Agent lifecycle
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,12 +94,8 @@ apply.
|
||||||
approval step — every other agent is created at swarm level
|
approval step — every other agent is created at swarm level
|
||||||
(`swarmctl agent create`).
|
(`swarmctl agent create`).
|
||||||
Roster-wise, `ruth` is just another entry.
|
Roster-wise, `ruth` is just another entry.
|
||||||
- **Wire-protocol** — the `*(privileged)*` `Request` variants in
|
- **Wire-protocol** — `hive-core-agent-sock`'s unified `Request` enum
|
||||||
`hive-core-agent-sock`'s unified enum are the scheduling ops
|
is the same on both socket flavours. Container lifecycle
|
||||||
(`RequestSchedulePrompt`, `CancelSchedule`, `FireScheduleNow`,
|
|
||||||
`EditSchedule`), reachable only from the manager's socket flavour,
|
|
||||||
matching the `scheduling` tool group
|
|
||||||
([`docs/turn-loop/mcp.md`](../turn-loop/mcp.md)). Container lifecycle
|
|
||||||
ops (kill/start/restart/rebuild) go through the separate host-admin
|
ops (kill/start/restart/rebuild) go through the separate host-admin
|
||||||
socket `hivectl` speaks. `Wake` (inject a `from: <X>` message straight
|
socket `hivectl` speaks. `Wake` (inject a `from: <X>` message straight
|
||||||
into the caller's own inbox) is on this socket too, unprivileged on
|
into the caller's own inbox) is on this socket too, unprivileged on
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
# Approvals + helper events
|
# Approvals + helper events
|
||||||
|
|
||||||
The approval queue is where an agent asks the operator for something it
|
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
|
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
|
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
|
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
|
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
|
`agent-configs/<agent>`. Review it on the forge like any other PR, and
|
||||||
merge it there to deploy it. See [Config changes](#config-changes).
|
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
|
- **Meta/flake update** (`UpdateMetaInputs`) — an existing row reads
|
||||||
back and you can approve it. Approving runs the update and commits
|
back and you can approve it. Approving runs the update and commits
|
||||||
the lock change; it doesn't rebuild anything by itself.
|
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)
|
### Approval kinds (wire shapes)
|
||||||
|
|
||||||
`ApprovalKind` carries two variants; each maps to a different
|
`ApprovalKind` carries one variant, and it overloads `commit_ref` as
|
||||||
`commit_ref` encoding because `ApprovalKind` overloads that field as
|
its payload carrier.
|
||||||
the kind-specific payload carrier.
|
|
||||||
|
|
||||||
<!-- vale write-good.Passive = NO -->
|
<!-- vale write-good.Passive = NO -->
|
||||||
- `UpdateMetaInputs` — `commit_ref` stores the JSON-encoded inputs
|
- `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.
|
etc.). hive-c0re sets the `agent` field to the requesting root agent.
|
||||||
On approve hive-c0re runs `nix flake update [inputs...]` on the
|
On approve hive-c0re runs `nix flake update [inputs...]` on the
|
||||||
meta flake and commits the resulting lock changes.
|
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 -->
|
<!-- 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
|
### Reminder delivery: file-path semantics
|
||||||
|
|
||||||
A reminder may carry a `file_path` (the agent-visible path inside its
|
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 |
|
| `ApprovalKind` | DAG submitted | source |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `UpdateMetaInputs` | `meta_update` (`MetaLock` + rebuild fan-out) | `approval` |
|
| `UpdateMetaInputs` | `meta_update` (`MetaLock` + rebuild fan-out) | `approval` |
|
||||||
| `SchedulePrompt` | — runs inline (single sqlite insert) | — |
|
|
||||||
|
|
||||||
The DAG carries the originating `approval_id`. **Every** queued kind
|
The DAG carries the originating `approval_id`. **Every** queued kind
|
||||||
resolves through `actions::resolve_approval_dag` when its DAG settles
|
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.
|
as a regular `system` inbox message so it drives a normal claude turn.
|
||||||
`finish_approval` fires an `ApprovalResolved` HelperEvent this way for
|
`finish_approval` fires an `ApprovalResolved` HelperEvent this way for
|
||||||
**every** approval kind's terminal state. A
|
**every** approval kind's terminal state. A
|
||||||
"FYI, check when convenient" event doesn't need a message — those go
|
"FYI, check when convenient" event doesn't need a message — hive-c0re publishes those as swarm
|
||||||
through `Coordinator::push_todo` instead, a direct live dial of the target
|
lifecycle notices instead (`swarm_notices::notify`). Legacy
|
||||||
agent's in-container todo socket (same `UpsertTodo` request in-container
|
|
||||||
producers use). Legacy
|
|
||||||
approval rows that predate the submitter column fall back to the
|
approval rows that predate the submitter column fall back to the
|
||||||
root agent. Variants (`hive_sh4re::manager::HelperEvent`):
|
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`,
|
The remaining lower-urgency lifecycle notices — `Rebuilt`, `Killed`,
|
||||||
`Destroyed`, `NeedsLogin`, `LoggedIn` — are "FYI, check
|
`Destroyed`, `NeedsLogin`, `LoggedIn` — are "FYI, check
|
||||||
when convenient" events with no reason to drive an immediate turn, so
|
when convenient" events with no reason to drive an immediate turn, so
|
||||||
they deliver via `push_todo` (see above) instead
|
they go out via `swarm_notices::notify` (see above) instead
|
||||||
of `HelperEvent`: an `agent_todo_socket` push instead of a broker
|
of a `HelperEvent`: `subsystem = "core"`, `key = "<event>:<agent>"`,
|
||||||
message, `subsystem = "core"`, `key = "<event>:<agent>"` for dedup,
|
|
||||||
and a single free-text `summary` (`rebuilt_todo_summary` renders
|
and a single free-text `summary` (`rebuilt_todo_summary` renders
|
||||||
`Rebuilt`'s `ok`/`note`/`sha`/`tag` fields into that string).
|
`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
|
(something genuinely urgent, like `ContainerCrash`), add a
|
||||||
`HelperEvent` variant + call sites + update `prompts/system.md`'s
|
`HelperEvent` variant + call sites + update `prompts/system.md`'s
|
||||||
message-event list. If it's "FYI, check when convenient," call
|
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.
|
needed.
|
||||||
|
|
||||||
## Autoupdate on startup
|
## Autoupdate on startup
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ schemas, file layouts, and internal migration mechanics.
|
||||||
|
|
||||||
### `/var/lib/hyperhive/db/broker.sqlite` (host)
|
### `/var/lib/hyperhive/db/broker.sqlite` (host)
|
||||||
|
|
||||||
Seven tables, all in one file — three queues, a small key/value
|
Six tables, all in one file — two queues, a small key/value table,
|
||||||
table, the schedule header/targets split, and the per-agent
|
the read-only schedule header/targets split, and the per-agent
|
||||||
power-intent registry:
|
power-intent registry:
|
||||||
|
|
||||||
- `messages` — every inter-agent / operator-bound message.
|
- `messages` — every inter-agent / operator-bound message.
|
||||||
|
|
@ -56,21 +56,19 @@ power-intent registry:
|
||||||
per-agent store — see [`/harness/` contents
|
per-agent store — see [`/harness/` contents
|
||||||
below](#state-dirs-per-agent) for where reminders (and todos)
|
below](#state-dirs-per-agent) for where reminders (and todos)
|
||||||
live.
|
live.
|
||||||
- `approvals` — the queue. `agent / kind (update_meta_inputs |
|
- `approvals` — the queue. `agent / kind (update_meta_inputs) /
|
||||||
schedule_prompt) /
|
|
||||||
commit_ref / requested_at / status / resolved_at / note`.
|
commit_ref / requested_at / status / resolved_at / note`.
|
||||||
- `scheduled_prompts` — recurring + one-shot prompt queue.
|
- `scheduled_prompts` — the scheduled prompts left from before they
|
||||||
|
moved to swarm level ([`swarm/schedules.md`](../swarm/schedules.md)).
|
||||||
`owner / body / interval_seconds (NULL = one-shot) /
|
`owner / body / interval_seconds (NULL = one-shot) /
|
||||||
next_fire_at_unix / created_at_unix / source ("operator" or
|
next_fire_at_unix / created_at_unix / source ("operator" or
|
||||||
"approval:<id>") / cancelled_at_unix / description`. `owner`
|
"approval:<id>") / cancelled_at_unix / description / paused_at_unix`.
|
||||||
drives cancel-permission checks (operator vs the submitting
|
Read-only: the dashboard's SCH3DUL3S tab lists them so the operator
|
||||||
agent). The worker tombstones and reaps cancelled rows
|
can recreate them with `swarmctl schedule`; nothing writes or fires
|
||||||
on its next pass.
|
them.
|
||||||
- `scheduled_prompt_targets` — per-target state for each schedule.
|
- `scheduled_prompt_targets` — per-target state for each schedule.
|
||||||
`schedule_id / target / cancelled_at_unix /
|
`schedule_id / target / cancelled_at_unix /
|
||||||
last_fired_at_unix / last_result`. `ON DELETE CASCADE` from
|
last_fired_at_unix / last_result`.
|
||||||
`scheduled_prompts(id)` — requires `PRAGMA foreign_keys = ON`
|
|
||||||
per connection (set at open).
|
|
||||||
- `agent_power` — one row per agent: `agent PK / wanted (up |
|
- `agent_power` — one row per agent: `agent PK / wanted (up |
|
||||||
offline) / updated_at`, owned by `hive-c0re/src/stores/power.rs`.
|
offline) / updated_at`, owned by `hive-c0re/src/stores/power.rs`.
|
||||||
This is the durable power *intent* the job queue reconciles the
|
This is the durable power *intent* the job queue reconciles the
|
||||||
|
|
@ -90,11 +88,7 @@ Retention:
|
||||||
an unacked row on a crash.
|
an unacked row on a crash.
|
||||||
- hive-c0re keeps approvals indefinitely — an audit trail. `actions::destroy`
|
- hive-c0re keeps approvals indefinitely — an audit trail. `actions::destroy`
|
||||||
rows stay visible to anything that queries by id.
|
rows stay visible to anything that queries by id.
|
||||||
- Scheduled prompts: the worker deletes one-shot rows on fire;
|
- Scheduled prompts: nothing deletes them; the rows stay as they are.
|
||||||
recurring rows live until the operator cancels them
|
|
||||||
(`cancel_schedule` MCP / dashboard ✗) which tombstones via
|
|
||||||
`cancelled_at_unix`, then `reap_cancelled` drops the row on
|
|
||||||
the next worker pass.
|
|
||||||
- `agent_power` rows live until the operator destroys the agent (one row per
|
- `agent_power` rows live until the operator destroys the agent (one row per
|
||||||
agent — nothing to vacuum).
|
agent — nothing to vacuum).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -254,8 +254,8 @@ the wire structs in hive-sh4re) serialize as **RFC 3339 UTC strings**
|
||||||
fields as `i64` unix seconds internally, only the JSON representation
|
fields as `i64` unix seconds internally, only the JSON representation
|
||||||
changes, and deserialization accepts both the string form and a bare
|
changes, and deserialization accepts both the string form and a bare
|
||||||
integer (rolling-deploy skew, persisted blobs).
|
integer (rolling-deploy skew, persisted blobs).
|
||||||
**Input-direction** fields agents compute as epoch (`first_fire_at_unix`,
|
**Input-direction** fields agents compute as epoch (`remind`'s
|
||||||
schedule-edit `next_fire_at_unix`, `Wakeup::At`) stay integers. The
|
`at_unix_timestamp`) stay integers. The
|
||||||
`*_unix` field *names* stay for now — renaming is the wire-types
|
`*_unix` field *names* stay for now — renaming is the wire-types
|
||||||
refactor's concern. The dashboard frontend parses via
|
refactor's concern. The dashboard frontend parses via
|
||||||
`util.js::epochSec` wherever it needs arithmetic and feeds the string
|
`util.js::epochSec` wherever it needs arithmetic and feeds the string
|
||||||
|
|
@ -297,7 +297,6 @@ binary flavor.
|
||||||
| `execution` | vestigial — `mcp__bash__run` / `mcp__bash__status` are always available unconditionally via `extraMcpServers`; this group's entries expand to non-existent `mcp__hyperhive__run` / `mcp__hyperhive__status` and have no effect. See `docs/tools/bash.md`. |
|
| `execution` | vestigial — `mcp__bash__run` / `mcp__bash__status` are always available unconditionally via `extraMcpServers`; this group's entries expand to non-existent `mcp__hyperhive__run` / `mcp__hyperhive__status` and have no effect. See `docs/tools/bash.md`. |
|
||||||
| `lifecycle` | none |
|
| `lifecycle` | none |
|
||||||
| `approvals` | none — gates `cancel_loose_end`'s approval-cancel arm server-side. |
|
| `approvals` | none — gates `cancel_loose_end`'s approval-cancel arm server-side. |
|
||||||
| `scheduling` | `request_schedule_prompt`, `fire_schedule_now`, `cancel_schedule`, `edit_schedule`, `list_schedules` *(privileged)* |
|
|
||||||
| `forge` | none |
|
| `forge` | none |
|
||||||
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
|
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
|
||||||
|
|
||||||
|
|
@ -375,8 +374,7 @@ bypass the operator approval gate.
|
||||||
`hive-sh4re/src/permissions.rs` + an arm to `as_str`. Add it to `Capability::ALL`
|
`hive-sh4re/src/permissions.rs` + an arm to `as_str`. Add it to `Capability::ALL`
|
||||||
(the source of truth for the permissions UI columns). Implement the access
|
(the source of truth for the permissions UI columns). Implement the access
|
||||||
check in the relevant handler (`hive-c0re/src/socket_server/mod.rs`,
|
check in the relevant handler (`hive-c0re/src/socket_server/mod.rs`,
|
||||||
`hive-c0re/src/socket_server/schedules.rs`, `coordinator.rs`, or a
|
`coordinator.rs`, or a handler under `hive-c0re/src/dashboard/`).
|
||||||
handler under `hive-c0re/src/dashboard/`).
|
|
||||||
|
|
||||||
## Async forms
|
## Async forms
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -521,7 +521,7 @@ which is almost never desired. Leave off on non-x86 hosts.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
- `docs/agent-lifecycle/approvals.md` — approval flow + scheduled prompts
|
- `docs/agent-lifecycle/approvals.md` — approval flow
|
||||||
- `docs/agent-lifecycle/persistence.md` — SQLite schema, state-dir layout
|
- `docs/agent-lifecycle/persistence.md` — SQLite schema, state-dir layout
|
||||||
- `docs/process/conventions.md` — wire protocol, recipient sentinels
|
- `docs/process/conventions.md` — wire protocol, recipient sentinels
|
||||||
- `docs/agent-lifecycle/agent-roster.md` — the agent roster and privilege
|
- `docs/agent-lifecycle/agent-roster.md` — the agent roster and privilege
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,11 @@ works them out from the prompt itself, so:
|
||||||
watches the paused prompt; if the agent was down for the whole pause, it
|
watches the paused prompt; if the agent was down for the whole pause, it
|
||||||
fires the latest time it missed once, as above.
|
fires the latest time it missed once, as above.
|
||||||
|
|
||||||
A fire reaches the agent as a `schedule` loose end with the prompt's text,
|
A fire reaches the agent as a `schedule` loose end with the prompt's text.
|
||||||
the same as a hive schedule's. The agent's turn loop wakes for it like any
|
The agent's turn loop wakes for it like any other loose end. If the agent
|
||||||
other loose end. If the agent hasn't dealt with the previous fire yet, the
|
hasn't dealt with the previous fire yet, the new fire replaces it rather
|
||||||
new fire replaces it rather than adding a second one; once the agent
|
than adding a second one; once the agent dismissed the previous one, the
|
||||||
dismissed the previous one, the next fire opens a new one.
|
next fire opens a new one.
|
||||||
|
|
||||||
Each agent reads its prompts every 10 seconds, so a fire can land up to 10
|
Each agent reads its prompts every 10 seconds, so a fire can land up to 10
|
||||||
seconds after its time. A change reaches each agent within the same window,
|
seconds after its time. A change reaches each agent within the same window,
|
||||||
|
|
|
||||||
|
|
@ -43,5 +43,3 @@ debug agent behavior.
|
||||||
- **[matrix](matrix.md)** — the matrix MCP tool surface
|
- **[matrix](matrix.md)** — the matrix MCP tool surface
|
||||||
(`mcp__matrix__*`) for agents with a matrix account, multiple
|
(`mcp__matrix__*`) for agents with a matrix account, multiple
|
||||||
accounts per agent, and declaring extra MCP servers generally.
|
accounts per agent, and declaring extra MCP servers generally.
|
||||||
- **[scheduling](scheduling.md)** — scheduled prompts (operator
|
|
||||||
approval required).
|
|
||||||
|
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
# Scheduling and diagnostics tools
|
|
||||||
|
|
||||||
## `scheduling` tool group
|
|
||||||
|
|
||||||
Scheduled prompts fan a message body out to one or more agent inboxes
|
|
||||||
at a future time, optionally recurring.
|
|
||||||
|
|
||||||
**Creating** one goes through the operator approval queue, even when it
|
|
||||||
targets only yourself — use `remind` for an unapproved self-wake. The
|
|
||||||
other four verbs need no approval: holding the `scheduling` tool group
|
|
||||||
is the whole gate.
|
|
||||||
|
|
||||||
Authorization is one rule for all four verbs: you reach every schedule in
|
|
||||||
the hive, whoever owns it. `list_schedules` shows the same set, so the
|
|
||||||
snapshot only ever shows schedules you could also cancel.
|
|
||||||
|
|
||||||
### `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)`
|
|
||||||
|
|
||||||
<!-- vale write-good.Passive = NO -->
|
|
||||||
|
|
||||||
Queue an operator-approval for a scheduled prompt. On approve,
|
|
||||||
hive-c0re fans `body` out to each agent in `targets` at
|
|
||||||
`first_fire_at_unix` (Unix timestamp). Recurring when `interval_seconds`
|
|
||||||
is set, one-shot otherwise.
|
|
||||||
|
|
||||||
<!-- vale write-good.Passive = YES -->
|
|
||||||
|
|
||||||
Catch-up clamp: if hive-c0re is down across multiple intervals, only
|
|
||||||
ONE delayed fire happens on resume (per recurring schedule). The
|
|
||||||
skipped-cycle count surfaces in the per-target `last_result` for
|
|
||||||
audit.
|
|
||||||
|
|
||||||
### `edit_schedule(id, body?, description?, interval_seconds?, next_fire_at_unix?, targets_add?, targets_remove?)`
|
|
||||||
|
|
||||||
Partial-update a schedule. Pass only the fields to change; absent
|
|
||||||
fields stay untouched. `targets_add` / `targets_remove` mutate the
|
|
||||||
recipient list in the same transaction — re-adding a previously
|
|
||||||
cancelled target drops its tombstone and starts fresh.
|
|
||||||
`interval_seconds` accepts positive values only via this tool (omit
|
|
||||||
to keep the existing cadence; pass a new positive value to change
|
|
||||||
it). Toggling recurring → one-shot (clearing the interval) is
|
|
||||||
operator-only via the dashboard PATCH endpoint. Refuses cancelled
|
|
||||||
rows (terminal state).
|
|
||||||
|
|
||||||
### `cancel_schedule(id, targets?)`
|
|
||||||
|
|
||||||
<!-- vale write-good.Passive = NO -->
|
|
||||||
|
|
||||||
Cancel a schedule. Omit `targets` / pass empty to cancel the whole
|
|
||||||
schedule; pass a list to cancel just those recipients (the schedule
|
|
||||||
autocancels once every target is gone).
|
|
||||||
|
|
||||||
<!-- vale write-good.Passive = YES -->
|
|
||||||
|
|
||||||
### `fire_schedule_now(id)`
|
|
||||||
|
|
||||||
Fire a scheduled prompt out of band immediately. Recurring schedules
|
|
||||||
keep their cadence — the manual fire is additive. The manual fire
|
|
||||||
consumes one-shot schedules and cancels them afterwards.
|
|
||||||
|
|
||||||
### `list_schedules()`
|
|
||||||
|
|
||||||
Snapshot every schedule in the hive (active, and cancelled but not yet
|
|
||||||
reaped) — same read scope as the rest of this group. Returns id, owner,
|
|
||||||
body, per-target `last_fired_at` and `last_result`,
|
|
||||||
`next_fire_at_unix`, `interval_seconds`. Use to look up an id before
|
|
||||||
cancelling, or to audit upcoming wake-ups across the hive.
|
|
||||||
|
|
||||||
## See also
|
|
||||||
|
|
||||||
- `remind` (no-approval self-wake path) — documented in
|
|
||||||
[`docs/turn-loop/`](../turn-loop/README.md).
|
|
||||||
- [`docs/agent-lifecycle/approvals.md`](../agent-lifecycle/approvals.md) — approval flow for
|
|
||||||
`request_schedule_prompt`.
|
|
||||||
|
|
@ -131,10 +131,10 @@ checkpoints**, not about sandboxing the agent from its own tools:
|
||||||
settings nor merge its own PR. It's **not** set up for external VCS (GitHub
|
settings nor merge its own PR. It's **not** set up for external VCS (GitHub
|
||||||
etc.), though — there, operator-merge is process + accepted risk, not a
|
etc.), though — there, operator-merge is process + accepted risk, not a
|
||||||
technical control.
|
technical control.
|
||||||
- **Approvals** — schedule additions and other blast-radius-y operations
|
- **Approvals** — config changes are config PRs an operator merges on the
|
||||||
route through the operator approval queue; config changes are config PRs
|
forge (see [`approvals.md`](../agent-lifecycle/approvals.md)), and
|
||||||
an operator merges on the forge
|
scheduled prompts are operator-only, set at swarm level
|
||||||
(see [`approvals.md`](../agent-lifecycle/approvals.md)).
|
(see [`schedules.md`](../swarm/schedules.md)).
|
||||||
|
|
||||||
### Capability = accepted risk
|
### Capability = accepted risk
|
||||||
|
|
||||||
|
|
@ -327,6 +327,6 @@ writes to only the paths `hive-priv` legitimately needs.
|
||||||
|
|
||||||
| Component | Runs as | Privilege needed for |
|
| Component | Runs as | Privilege needed for |
|
||||||
| ---------------------------- | -------------- | ------------------------------------------------------------ |
|
| ---------------------------- | -------------- | ------------------------------------------------------------ |
|
||||||
| `hive-c0re` | `hive-core` | broker, HTTP dashboard, scheduling, approvals |
|
| `hive-c0re` | `hive-core` | broker, HTTP dashboard, approvals |
|
||||||
| `hive-priv` | `root` | container lifecycle, journal reads, bind mounts, cred writes |
|
| `hive-priv` | `root` | container lifecycle, journal reads, bind mounts, cred writes |
|
||||||
| `hive-ag3nt` (per-container) | per-agent user | turn execution, MCP serving |
|
| `hive-ag3nt` (per-container) | per-agent user | turn execution, MCP serving |
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ for what reaches a subagent's own `--mcp-config` and what doesn't.
|
||||||
|
|
||||||
Tool groups (`HIVE_TOOL_GROUPS`) gate tool access. The default
|
Tool groups (`HIVE_TOOL_GROUPS`) gate tool access. The default
|
||||||
preset (`AGENT_DEFAULT`) includes `messaging`, `meta`, `inbox`, and
|
preset (`AGENT_DEFAULT`) includes `messaging`, `meta`, `inbox`, and
|
||||||
`execution`. Privileged groups (`lifecycle`, `approvals`, `scheduling`)
|
`execution`. Privileged groups (`lifecycle`, `approvals`)
|
||||||
are opt-in via the P3RM1SS10NS tab.
|
are opt-in via the P3RM1SS10NS tab.
|
||||||
|
|
||||||
## Core tools (always available)
|
## Core tools (always available)
|
||||||
|
|
@ -149,8 +149,6 @@ hive_name?, swarm_name?, matrix_accounts? }`. `matrix_accounts` is a
|
||||||
`lifecycle` gates nothing.
|
`lifecycle` gates nothing.
|
||||||
Config changes go through a forge PR on `agent-configs/<name>` — see
|
Config changes go through a forge PR on `agent-configs/<name>` — see
|
||||||
[`docs/agent-lifecycle/approvals.md`](../agent-lifecycle/approvals.md).
|
[`docs/agent-lifecycle/approvals.md`](../agent-lifecycle/approvals.md).
|
||||||
- **Scheduling** (`scheduling`) — scheduled prompts. See
|
|
||||||
[`docs/tools/scheduling.md`](../tools/scheduling.md).
|
|
||||||
- **Forge repos** (`forge`) — gates nothing.
|
- **Forge repos** (`forge`) — gates nothing.
|
||||||
- **Web egress** (`web_tools`) — enables Claude's built-in `WebFetch`
|
- **Web egress** (`web_tools`) — enables Claude's built-in `WebFetch`
|
||||||
and `WebSearch` tools (not MCP tools; added directly to the
|
and `WebSearch` tools (not MCP tools; added directly to the
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ of your time. It's a single page with exactly four tabs:
|
||||||
- **Y3R C4LL** — anything waiting on _you_: pending approvals. If an
|
- **Y3R C4LL** — anything waiting on _you_: pending approvals. If an
|
||||||
agent needs a decision from you, it's here.
|
agent needs a decision from you, it's here.
|
||||||
- **P3RM1SS10NS** — what tools and system-level access each agent has.
|
- **P3RM1SS10NS** — what tools and system-level access each agent has.
|
||||||
- **SCH3DUL3S** — scheduled prompts and agent self-reminders.
|
- **SCH3DUL3S** — a read-only list of the scheduled prompts left in the
|
||||||
|
hive, due for removal; operators set schedules at swarm level now.
|
||||||
|
|
||||||
Everything else lives on its own page instead, all reachable from the
|
Everything else lives on its own page instead, all reachable from the
|
||||||
H0M3 hub: **Flow** (`/flow.html`, the raw live message stream across
|
H0M3 hub: **Flow** (`/flow.html`, the raw live message stream across
|
||||||
|
|
@ -48,9 +49,8 @@ and quick links (stats, screen, forge profile). Select the name to open
|
||||||
its terminal and watch it work in real time.
|
its terminal and watch it work in real time.
|
||||||
|
|
||||||
**Approve something an agent is waiting on.** Y3R C4LL is the one tab
|
**Approve something an agent is waiting on.** Y3R C4LL is the one tab
|
||||||
worth checking regularly — it's everything that needs _you_: an agent's
|
worth checking regularly — it's everything that needs _you_. The tab's
|
||||||
request to schedule a prompt. The tab's count pill tells you at a glance if
|
count pill tells you at a glance if anything's pending.
|
||||||
anything's pending.
|
|
||||||
|
|
||||||
**Review a config change.** Agent config changes (new packages, env
|
**Review a config change.** Agent config changes (new packages, env
|
||||||
vars, MCP servers) are pull requests on the agent's `agent-configs`
|
vars, MCP servers) are pull requests on the agent's `agent-configs`
|
||||||
|
|
@ -76,9 +76,10 @@ save queues a rebuild for whichever agents actually changed.
|
||||||
journald view for any agent + service; the per-agent `⋮` menu's
|
journald view for any agent + service; the per-agent `⋮` menu's
|
||||||
**journal logs →** link jumps straight there, pre-filtered.
|
**journal logs →** link jumps straight there, pre-filtered.
|
||||||
|
|
||||||
**Set up a schedule or check on a reminder.** SCH3DUL3S covers both —
|
**Set up a schedule.** Scheduled prompts are swarm-level: set them with
|
||||||
recurring or one-shot prompts you schedule for one or more agents, and
|
`swarmctl schedule` ([`swarm/schedules.md`](../swarm/schedules.md)).
|
||||||
reminders agents have set for themselves.
|
SCH3DUL3S only lists the ones still in the hive, so you can copy them
|
||||||
|
over.
|
||||||
|
|
||||||
## More depth
|
## More depth
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ from the dashboard tab strip.
|
||||||
live on their own pages too, all reachable from the
|
live on their own pages too, all reachable from the
|
||||||
H0M3 hub (not the tab strip). Count pills on SW4RM
|
H0M3 hub (not the tab strip). Count pills on SW4RM
|
||||||
(container count), Y3R C4LL (pending approvals + unread
|
(container count), Y3R C4LL (pending approvals + unread
|
||||||
operator messages), and SCH3DUL3S (active schedules).
|
operator messages), and SCH3DUL3S (active schedules left to copy).
|
||||||
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
|
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
|
||||||
— sits below the tab strip.
|
— sits below the tab strip.
|
||||||
- **Server-warnings banner** — a generic, sticky top-of-page strip shown
|
- **Server-warnings banner** — a generic, sticky top-of-page strip shown
|
||||||
|
|
@ -50,7 +50,7 @@ from the dashboard tab strip.
|
||||||
page prepends a `(N)` prefix — `(3) pr1ma // h1ve-c0re` — so the
|
page prepends a `(N)` prefix — `(3) pr1ma // h1ve-c0re` — so the
|
||||||
operator can see the call count in an unfocused browser tab without
|
operator can see the call count in an unfocused browser tab without
|
||||||
opening the dashboard. The page sets the prefix on the initial
|
opening the dashboard. The page sets the prefix on the initial
|
||||||
`/api/state` cold-load and updates it live via `approval_added` /
|
`/api/state` cold-load and updates it live via
|
||||||
`approval_resolved` SSE events; it's preserved when `hive_name` /
|
`approval_resolved` SSE events; it's preserved when `hive_name` /
|
||||||
`swarm_name` later replace the raw title.
|
`swarm_name` later replace the raw title.
|
||||||
|
|
||||||
|
|
@ -332,7 +332,7 @@ named buckets of MCP tools; each agent starts with a role default
|
||||||
(sub-agents: `messaging`, `meta`, `inbox`, `execution` —
|
(sub-agents: `messaging`, `meta`, `inbox`, `execution` —
|
||||||
`ToolGroup::AGENT_DEFAULT`; hive-c0re seeds the root agent to
|
`ToolGroup::AGENT_DEFAULT`; hive-c0re seeds the root agent to
|
||||||
`ToolGroup::MANAGER_DEFAULT` — `messaging`, `meta`, `inbox`,
|
`ToolGroup::MANAGER_DEFAULT` — `messaging`, `meta`, `inbox`,
|
||||||
`lifecycle`, `approvals`, `scheduling`, `execution`,
|
`lifecycle`, `approvals`, `execution`,
|
||||||
that is, every group except `forge` and `web_tools`). Checking /
|
that is, every group except `forge` and `web_tools`). Checking /
|
||||||
unchecking stages which groups are active for the agent; the
|
unchecking stages which groups are active for the agent; the
|
||||||
page-level **save all** button (below) commits it. Columns come from
|
page-level **save all** button (below) commits it. Columns come from
|
||||||
|
|
@ -341,7 +341,7 @@ takes effect.
|
||||||
<!-- vale write-good.Passive = YES -->
|
<!-- vale write-good.Passive = YES -->
|
||||||
|
|
||||||
The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`,
|
The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`,
|
||||||
`approvals`, `scheduling`, `forge`, `execution`,
|
`approvals`, `forge`, `execution`,
|
||||||
`web_tools`. All listed in `ToolGroup::ALL` in `hive-sh4re`. The
|
`web_tools`. All listed in `ToolGroup::ALL` in `hive-sh4re`. The
|
||||||
`web_tools` group is special: it carries no MCP tools; instead it adds
|
`web_tools` group is special: it carries no MCP tools; instead it adds
|
||||||
Claude's built-in `WebFetch` and `WebSearch` to `--tools` /
|
Claude's built-in `WebFetch` and `WebSearch` to `--tools` /
|
||||||
|
|
@ -374,83 +374,31 @@ isn't clobbered.
|
||||||
|
|
||||||
## SCH3DUL3S tab
|
## SCH3DUL3S tab
|
||||||
|
|
||||||
Anything that fires at a future time. The operator creates schedules
|
A read-only list of the scheduled prompts still in the hive's store.
|
||||||
inline in the table (last row); agent self-paced
|
The hive no longer fires them: scheduled prompts live at swarm level
|
||||||
reminders surface at the bottom as a sibling list — they
|
([`swarm/schedules.md`](../swarm/schedules.md)), and a warning banner at
|
||||||
share enough conceptual ground to live together.
|
the top of the tab says the page is due for removal and points at
|
||||||
|
`swarmctl schedule`. The list is there so the operator can recreate each
|
||||||
|
row with `swarmctl schedule add`.
|
||||||
|
|
||||||
**N3W SCH3DUL3 / QU3U3D SCH3DUL3S** — operator-managed
|
**Single-table layout**: each schedule is one `<tr>`; columns are
|
||||||
scheduled prompts. **Single-table layout**: each schedule is
|
`# | src | next | every | owner | body | …agents…`. Agent columns are
|
||||||
one `<tr>`; columns are
|
dynamic — every live container plus any extra name that appears as a
|
||||||
`# | src | next | every | owner | body | …agents… | actions`.
|
target on some schedule but isn't a current container (struck through
|
||||||
Agent columns are dynamic — `operator` + `root` + every
|
as gone). Column headers render vertically so each column reads as a
|
||||||
live container + any extra name that appears as a target on
|
narrow ~28px strip; per-agent cells show `✓` for an active target, a
|
||||||
some schedule but isn't a current container (same
|
muted `✕` for a cancelled one, and nothing when the agent isn't a
|
||||||
`buildTargetChips` membership rule the new/edit forms use,
|
target. Hovering a target cell shows its last fire and result.
|
||||||
so table and forms agree on what's addressable). Column
|
|
||||||
headers tilt –45° via CSS so each column reads as a narrow
|
|
||||||
~28px strip; per-agent cells render as:
|
|
||||||
|
|
||||||
- **active target** → `<button>✓</button>` that cancels just
|
The `next` column shows the stored next fire time as an absolute UTC
|
||||||
that one target on selection
|
timestamp, the value to pass as `--at`; paused and cancelled rows say
|
||||||
- **cancelled target** → muted `✕` glyph (no button —
|
so instead, with the time in the cell's tooltip. The body cell
|
||||||
re-adding goes through the edit form's targets multi-select)
|
truncates; hovering shows the full body and description.
|
||||||
- **not a target** → empty cell
|
|
||||||
|
|
||||||
Per-schedule action column:
|
The tab has no controls: nothing creates, edits, pauses, fires or
|
||||||
|
cancels a row. The tab pill shows the count of active schedules (at least one
|
||||||
- **`↯ fire now`** — sends an out-of-band manual pulse to every
|
live target not yet cancelled). Fetched from `GET /api/schedules` on
|
||||||
active target (recurring schedules keep their cadence; the manual
|
tab activation and on each dashboard state load.
|
||||||
fire consumes one-shots). Disabled for paused schedules.
|
|
||||||
- **`⏸` / `▶` pause/resume toggle** — only on recurring schedules
|
|
||||||
(the operator may also pause one-shots to delay a one-time fire, so
|
|
||||||
the button always appears). Paused rows show a `⏸ paused` badge in
|
|
||||||
the `next` column; the table sorts them to the middle bucket (after
|
|
||||||
active, before cancelled). A paused schedule doesn't fire regardless of
|
|
||||||
`next_fire_at`; resuming (`▶`) clears the pause without adjusting
|
|
||||||
the next-fire time. POSTs to `/api/schedules/{id}/pause` or
|
|
||||||
`/api/schedules/{id}/resume`.
|
|
||||||
- **`✎ edit`** — expands an inline edit form as a colspan'd row
|
|
||||||
directly under the schedule's row (body / description / interval /
|
|
||||||
next-fire / targets all editable; targets are a multi-select diff'd
|
|
||||||
against the original active set so unchecked-was-active =
|
|
||||||
`targets_remove`, checked-not-originally-active = `targets_add`;
|
|
||||||
submit PATCHes `/api/schedules/{id}`).
|
|
||||||
- **`✕`** — cancels the whole schedule
|
|
||||||
(`POST /api/schedules/{id}/cancel`).
|
|
||||||
|
|
||||||
The `next` column cell (`.sched-due`) carries a `data-due-at`
|
|
||||||
Unix timestamp attribute; a shared 1s ticker rewrites it
|
|
||||||
in-place showing `fmtDuration` while in the future and
|
|
||||||
`overdue X ago` once the fire time has passed — same
|
|
||||||
zero-re-render pattern as the reminder due-at labels.
|
|
||||||
|
|
||||||
The table's last row is a permanent inline creation row:
|
|
||||||
inputs live directly in table cells (targets as checkboxes,
|
|
||||||
body textarea that expands on focus, datetime-local pre-filled
|
|
||||||
to 5 minutes from now, mini d/h/m/s number inputs (blank or
|
|
||||||
all-zero = one-shot), description). Select `+` to POST to
|
|
||||||
`/api/schedules` as JSON (or `⌫` to clear the half-filled row);
|
|
||||||
carry-state preserves partially typed inputs across re-renders. The tab pill shows the count of active
|
|
||||||
schedules (at least one live target not yet cancelled).
|
|
||||||
Refreshed on tab activation and after each submit/cancel. Backed by
|
|
||||||
`GET /api/schedules`. No hive-c0re changes for the table layout
|
|
||||||
— it renders entirely from existing `schedulesState` +
|
|
||||||
`containersState`.
|
|
||||||
|
|
||||||
**QU3U3D R3M1ND3RS** — reminders agents have scheduled for
|
|
||||||
themselves (via the `remind` tool) but not yet delivered.
|
|
||||||
Each row shows the owner, due time, and message; a `CANC3L`
|
|
||||||
button hard-deletes (`POST /api/cancel-reminder/{id}`) and a
|
|
||||||
`R3TRY` button re-arms one whose delivery failed
|
|
||||||
(`POST /api/retry-reminder/{id}`). Backed by `GET /api/reminders`.
|
|
||||||
Lives in the SCH3DUL3S tab alongside operator schedules so the
|
|
||||||
operator has one place for everything time-fired. The due-time
|
|
||||||
label (`.reminder-due`) carries a `data-due-at` Unix timestamp
|
|
||||||
attribute; a shared 1s ticker rewrites it in-place — showing
|
|
||||||
`in Xm Ys` while the reminder is in the future and
|
|
||||||
`overdue X ago` once the deadline passes — without triggering a
|
|
||||||
full re-render of the list.
|
|
||||||
|
|
||||||
## ST4TS page (`/stats.html`)
|
## ST4TS page (`/stats.html`)
|
||||||
|
|
||||||
|
|
@ -880,7 +828,6 @@ renderApprovals`) with three stacked sections:
|
||||||
| kind | glyph | chip |
|
| kind | glyph | chip |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `update_meta_inputs` | `↻` | `meta-update` |
|
| `update_meta_inputs` | `↻` | `meta-update` |
|
||||||
| `schedule_prompt` | `⏱` | `schedule` |
|
|
||||||
|
|
||||||
<!-- vale write-good.Passive = NO -->
|
<!-- vale write-good.Passive = NO -->
|
||||||
The chip ticks live every second via a `data-requested-at`
|
The chip ticks live every second via a `data-requested-at`
|
||||||
|
|
@ -889,8 +836,7 @@ renderApprovals`) with three stacked sections:
|
||||||
the `.stale` class flips precisely at the 3600s boundary rather
|
the `.stale` class flips precisely at the 3600s boundary rather
|
||||||
than at the next `renderApprovals` call.
|
than at the next `renderApprovals` call.
|
||||||
- **what-changed body** — the submitting agent's description, then the
|
- **what-changed body** — the submitting agent's description, then the
|
||||||
kind's payload: the inputs to bump (`update_meta_inputs`) or the prompt to
|
kind's payload: the inputs to bump (`update_meta_inputs`).
|
||||||
schedule (`schedule_prompt`).
|
|
||||||
- **decision actions** — `◆ APPR0VE` and `DENY`. Deny pops a
|
- **decision actions** — `◆ APPR0VE` and `DENY`. Deny pops a
|
||||||
`prompt()` for an optional reason carried to the submitting agent as
|
`prompt()` for an optional reason carried to the submitting agent as
|
||||||
`HelperEvent::ApprovalResolved.note`.
|
`HelperEvent::ApprovalResolved.note`.
|
||||||
|
|
@ -1075,42 +1021,9 @@ below — some endpoints aren't in it yet.
|
||||||
rows with both fields omitted rather than erroring on them.
|
rows with both fields omitted rather than erroring on them.
|
||||||
Returns `200 "ok"` on
|
Returns `200 "ok"` on
|
||||||
success.
|
success.
|
||||||
- `GET /api/schedules` — list all schedules (active and
|
- `GET /api/schedules` — list every schedule row left in the hive's
|
||||||
recently cancelled) for the SCH3DUL3S scheduled-prompts panel.
|
store (cancelled ones included) for the read-only SCH3DUL3S tab.
|
||||||
- `POST /api/schedules` — operator-direct schedule create:
|
Targets naming an agent that no longer exists are left out.
|
||||||
`{ targets, body, first_fire_at_unix, interval_seconds?, description? }`.
|
|
||||||
Agent-initiated schedules go through the approval queue instead
|
|
||||||
(via the `request_schedule_prompt` MCP tool).
|
|
||||||
- `PATCH /api/schedules/{id}` — partial edit. JSON body
|
|
||||||
`{ body?, description?, interval_seconds?, next_fire_at_unix?,
|
|
||||||
targets_add?, targets_remove? }`.
|
|
||||||
Missing key = "leave alone"; explicit `null` on
|
|
||||||
`description` / `interval_seconds` clears the field (so a
|
|
||||||
recurring schedule flips to one-shot when the caller sends
|
|
||||||
`interval_seconds` as `null`). `targets_add` is replace-on-conflict:
|
|
||||||
re-adding a previously cancelled target drops the tombstone
|
|
||||||
and the target starts fresh (operator intent on re-add =
|
|
||||||
"this target is active again"). `targets_remove` delegates
|
|
||||||
to the same path as `cancel_targets` — tombstones preserve
|
|
||||||
audit, parent schedule autocancels when no active targets
|
|
||||||
remain. Refuses cancelled rows; returns the updated
|
|
||||||
`WireSchedule` on success.
|
|
||||||
- `POST /api/schedules/{id}/cancel` — cancel a schedule. Body
|
|
||||||
`{ targets?: ["name", …] }` cancels just those recipients;
|
|
||||||
absent or empty body cancels the whole schedule.
|
|
||||||
- `POST /api/schedules/{id}/fire-now` — out-of-band manual
|
|
||||||
pulse. Fires the schedule body once immediately to
|
|
||||||
every active target. Recurring schedules: `next_fire_at_unix`
|
|
||||||
is untouched; the regular cadence continues. One-shots: the
|
|
||||||
manual fan-out consumes the schedule (cancels it).
|
|
||||||
The endpoint annotates per-target `last_result` as a manual fire so
|
|
||||||
the audit trail distinguishes scheduled fires from operator-
|
|
||||||
triggered ones.
|
|
||||||
- `POST /api/schedules/{id}/pause` — pause a recurring or
|
|
||||||
one-shot schedule. A paused schedule doesn't fire regardless
|
|
||||||
of `next_fire_at`; the row gains a `⏸ paused` badge.
|
|
||||||
- `POST /api/schedules/{id}/resume` — resume a paused schedule.
|
|
||||||
Clears the pause flag without adjusting `next_fire_at`.
|
|
||||||
- `POST /api/meta-update` — `nix flake update` the selected
|
- `POST /api/meta-update` — `nix flake update` the selected
|
||||||
`meta/flake.lock` inputs, then rebuild the affected agents.
|
`meta/flake.lock` inputs, then rebuild the affected agents.
|
||||||
- `GET /api/dashboard/stream` — unified live event channel:
|
- `GET /api/dashboard/stream` — unified live event channel:
|
||||||
|
|
@ -1133,10 +1046,9 @@ payload):
|
||||||
rows with a `↳ reply` tag that scroll-highlights the parent
|
rows with a `↳ reply` tag that scroll-highlights the parent
|
||||||
row on selection. Used by the message-flow terminal renderer and
|
row on selection. Used by the message-flow terminal renderer and
|
||||||
the operator-inbox derived state.
|
the operator-inbox derived state.
|
||||||
- `approval_added` (id, agent, approval_kind, sha_short, diff,
|
- `approval_resolved` (id, agent, approval_kind, status,
|
||||||
description) / `approval_resolved` (id, agent, approval_kind,
|
resolved_at, note, description) — moves a row from the pending
|
||||||
sha_short, status, resolved_at, note, description) — pending
|
queue to history. Client mutates a derived store and
|
||||||
queue + history mutations. Client mutates a derived store and
|
|
||||||
re-renders only the approvals section.
|
re-renders only the approvals section.
|
||||||
- `transient_set` (name, transient_kind, since_unix) /
|
- `transient_set` (name, transient_kind, since_unix) /
|
||||||
`transient_cleared` (name) — lifecycle action spinners. The
|
`transient_cleared` (name) — lifecycle action spinners. The
|
||||||
|
|
@ -1158,16 +1070,6 @@ payload):
|
||||||
terminal-history trim). Unlike the snapshot events below it ships
|
terminal-history trim). Unlike the snapshot events below it ships
|
||||||
no state at all: the client re-fetches `GET /api/jobq/graph`, which
|
no state at all: the client re-fetches `GET /api/jobq/graph`, which
|
||||||
is where it reads the queue from cold too.
|
is where it reads the queue from cold too.
|
||||||
- `schedules_changed` (seq, schedules: `Vec<WireSchedule>`) —
|
|
||||||
full snapshot of all scheduled prompts. Emitted after every
|
|
||||||
operator mutation via the `/api/schedules` surface (new /
|
|
||||||
edit / cancel / fire-now) and after the worker fires or
|
|
||||||
rearms a row. Same snapshot-shape rationale as
|
|
||||||
`tombstones_changed` / `meta_inputs_changed` (small list, no
|
|
||||||
add/remove races). The SCH3DUL3S tab subscribes and
|
|
||||||
re-renders `schedulesState` on receipt; tab activation still
|
|
||||||
re-fetches as a safety net for approval-path inserts and
|
|
||||||
disconnect windows.
|
|
||||||
- `reminders_changed` (seq, reminders: `Vec<PendingReminder>`) —
|
- `reminders_changed` (seq, reminders: `Vec<PendingReminder>`) —
|
||||||
full snapshot of all pending reminders. Emitted after every
|
full snapshot of all pending reminders. Emitted after every
|
||||||
reminder mutation: agent `remind` calls (`agent_server`),
|
reminder mutation: agent `remind` calls (`agent_server`),
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
(per-agent) → `text/event-stream` SSE for live updates. The
|
(per-agent) → `text/event-stream` SSE for live updates. The
|
||||||
dashboard stream carries broker `Sent` / `Delivered` (mirrored
|
dashboard stream carries broker `Sent` / `Delivered` (mirrored
|
||||||
by a forwarder task from the broker's intra-process channel)
|
by a forwarder task from the broker's intra-process channel)
|
||||||
plus mutation events (`approval_added` / `approval_resolved`,
|
plus mutation events (`approval_resolved`,
|
||||||
`transient_set` / `transient_cleared`). Each frame carries a `seq`. The
|
`transient_set` / `transient_cleared`). Each frame carries a `seq`. The
|
||||||
matching backfill endpoint is `GET /api/dashboard/history` (last
|
matching backfill endpoint is `GET /api/dashboard/history` (last
|
||||||
~200 broker messages wrapped in `{ seq, events }`) on the
|
~200 broker messages wrapped in `{ seq, events }`) on the
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# hive-c0re
|
# hive-c0re
|
||||||
|
|
||||||
The unprivileged host daemon (runs as `hive-core`). Owns the sqlite
|
The unprivileged host daemon (runs as `hive-core`). Owns the sqlite
|
||||||
broker, the approval/reminder/schedule queues, the generic job-DAG
|
broker, the approval/reminder queues, the generic job-DAG
|
||||||
queue, container lifecycle, gateway vhost wiring, forge/matrix config
|
queue, container lifecycle, gateway vhost wiring, forge/matrix config
|
||||||
reconciliation, per-container stats, and the axum operator dashboard.
|
reconciliation, per-container stats, and the axum operator dashboard.
|
||||||
Largest crate in the workspace — bin-only, no separate lib.
|
Largest crate in the workspace — bin-only, no separate lib.
|
||||||
|
|
@ -32,7 +32,7 @@ to track it:
|
||||||
- **`lifecycle/`** — `nixos-container` lifecycle + per-agent config
|
- **`lifecycle/`** — `nixos-container` lifecycle + per-agent config
|
||||||
flake generation.
|
flake generation.
|
||||||
- **`stores/`** — sqlite-backed stores (broker, queues, audit, power).
|
- **`stores/`** — sqlite-backed stores (broker, queues, audit, power).
|
||||||
- **`workers/`** — background sweeps (crash watch, scheduled prompts,
|
- **`workers/`** — background sweeps (crash watch,
|
||||||
autoupdate, knowledge sync).
|
autoupdate, knowledge sync).
|
||||||
- **`agent_config/`** — per-agent registries (tool groups,
|
- **`agent_config/`** — per-agent registries (tool groups,
|
||||||
capabilities, resource limits, topology).
|
capabilities, resource limits, topology).
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue