hive-sh4re + docs: extract Approval lifecycle prose (#717 batch 3)

This commit is contained in:
iris 2026-05-31 15:56:04 +02:00 committed by mara
commit a0b15ed6a4
2 changed files with 80 additions and 56 deletions

View file

@ -88,6 +88,55 @@ creates the container; subsequent ones rebuild it with new config.
This gives the manager (and operator) an explicit review gate on the
initial configuration before any container is created.
### Approval kinds (wire shapes)
`ApprovalKind` carries five variants; each maps to a different
`commit_ref` encoding because that field is overloaded as the
kind-specific payload carrier.
- `ApplyCommit``commit_ref` is the manager-supplied git sha
(7-40 hex chars). The canonical, hive-c0re-vouched sha after the
proposal fetch lives in `fetched_sha` on the same `Approval`
row (only `ApplyCommit` populates it). See the End-to-end flow
above.
- `Spawn` — direct container creation under the default
`agent.nix` template. `commit_ref` is empty. Submitted via
`HostRequest::RequestSpawn` (operator-gated, the
`◆ R3QU3ST SP4WN` dashboard button + `hive-c0re request-spawn`
CLI). The host-level `HostRequest::Spawn` variant bypasses the
approval queue entirely — privileged-context use only (operator
on the host shell, test scripts, one-off recoveries). The
manager-side `RequestSpawn` is gone; managers go through the
`InitConfig``ApplyCommit` two-step instead so the spawn
captures their customised config.
- `InitConfig``commit_ref` is empty; the variant just gates
"seed the proposed repo with the default template" against
operator approval. Step 1 of the two-step spawn flow above.
- `UpdateMetaInputs``commit_ref` stores the JSON-encoded inputs
array (`"[]"` = all inputs, `"[\"nixpkgs\"]"` = just nixpkgs,
etc.). `agent` field is set to `hm1nd` (the requesting manager).
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.
### Destroy semantics
`HostRequest::Destroy { name, purge }` is the lifecycle tear-down,
not an approval. Stops + removes the nspawn container, drops the
systemd drop-in, fails any pending approvals. Persistent state
(proposed/applied repos, claude credentials, `/state/` notes) is
**kept by default** — recreating the agent with the same name
reuses prior config + login. With `purge = true` the agent's
`/var/lib/hyperhive/{agents,applied}/<name>/` trees are also
wiped (config history + creds + notes gone forever). The manager
refuses to destroy itself.
## Meta flake
The hive-c0re-owned repo at `/var/lib/hyperhive/meta/`

View file

@ -14,29 +14,17 @@ pub mod assets;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "cmd", rename_all = "snake_case")]
pub enum HostRequest {
/// Create and start a sub-agent container directly (no approval). Use
/// this from privileged contexts (operator on the host); it bypasses the
/// approval queue intentionally so test scripts and one-off recoveries
/// don't need a separate approve step.
/// Create and start a sub-agent container directly, bypassing the
/// approval queue. Privileged-context only. See
/// `docs/approvals.md::Approval kinds (wire shapes)`.
Spawn { name: String },
/// Submit a spawn request for the operator to approve. On approval the
/// host creates and starts the container with the default `agent.nix`
/// template. The dashboard's `◆ R3QU3ST SP4WN` button and the
/// `hive-c0re request-spawn` CLI both go through this. The
/// previously-mirrored manager-side `RequestSpawn` was removed
/// (#442) — managers now go through the two-step `request_init_config`
/// and `request_apply_commit` flow so the spawn captures the
/// manager's customised config.
/// Submit a spawn request for the operator to approve. See
/// `docs/approvals.md::Approval kinds (wire shapes)` (`Spawn`).
RequestSpawn { name: String },
/// Stop a managed container (graceful).
Kill { name: String },
/// Tear down a sub-agent container: stop + remove + drop the systemd
/// drop-in, purge pending approvals. Persistent state (proposed/applied
/// repos, Claude credentials) is KEPT by default — recreating the agent
/// with the same name reuses prior config + login. With `purge=true`
/// the agent's `/var/lib/hyperhive/{agents,applied}/<name>/` trees are
/// also wiped (config history + creds + notes gone forever). Manager
/// not destroyable.
/// Tear down a sub-agent container, optionally purging state.
/// See `docs/approvals.md::Destroy semantics`.
Destroy {
name: String,
#[serde(default)]
@ -74,22 +62,22 @@ pub struct HostResponse {
pub approvals: Option<Vec<Approval>>,
}
/// One row in the approval queue. `commit_ref` is overloaded per
/// `kind` — see `docs/approvals.md::Approval kinds (wire shapes)`
/// for the encoding table and lifecycle.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Approval {
pub id: i64,
pub agent: String,
#[serde(default)]
pub kind: ApprovalKind,
/// For `ApplyCommit`: the git sha the manager submitted. For `Spawn`:
/// empty. Note that this is the manager's *claimed* ref — the
/// canonical, hive-c0re-vouched sha after the proposal fetch lives
/// in `fetched_sha`.
/// Kind-specific payload (git sha / inputs array / schedule
/// payload / empty). See the Approval struct doc.
pub commit_ref: String,
/// The sha hive-c0re fetched from the proposed repo into applied at
/// submission time, then tagged `proposal/<id>`. Stable for the
/// lifetime of the approval — manager amends in proposed don't
/// change what gets built. Only set for `ApplyCommit` after the
/// successful fetch.
/// `ApplyCommit` only: the canonical hive-c0re-vouched sha after
/// the proposal fetch, tagged `proposal/<id>`. Stable for the
/// approval's lifetime — manager amends in proposed don't change
/// what gets built.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fetched_sha: Option<String>,
pub requested_at: i64,
@ -98,44 +86,31 @@ pub struct Approval {
pub resolved_at: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub note: Option<String>,
/// Optional free-text description the manager attached at submission
/// time — shown on the dashboard approval card so the operator can
/// understand the change without opening the diff.
/// Free-text description the manager attached at submission time;
/// shown on the dashboard approval card.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
/// What action the approval, when granted, will trigger.
/// Variant-specific payload encoding + flow lives in
/// `docs/approvals.md::Approval kinds (wire shapes)`.
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ApprovalKind {
/// Apply a manager-proposed config commit (existing flow).
/// Apply a manager-proposed config commit.
#[default]
ApplyCommit,
/// Create + start a new sub-agent container with the given name.
/// Used today by the host admin socket / dashboard "request spawn"
/// button; the manager-side `RequestSpawn` surface was removed in
/// favour of the two-step `InitConfig` → `ApplyCommit` flow (#442).
/// Create + start a new sub-agent container with the given name
/// (under the default `agent.nix` template).
Spawn,
/// Initialise a new agent's proposed config repo so the manager can
/// customise it before submitting a `request_apply_commit`. On
/// approval hive-c0re seeds `proposed/<name>/` with the default
/// `agent.nix` template but does NOT create the container — that
/// requires a subsequent `ApplyCommit` approval pinning the
/// customised config sha.
/// Seed an agent's proposed config repo for manager customisation
/// (step 1 of the two-step spawn flow).
InitConfig,
/// Run `nix flake update [inputs...]` on the meta flake and commit
/// the resulting lock changes. The `commit_ref` field stores the
/// JSON-encoded inputs array (`"[]"` = all inputs). Agent field is
/// set to `hm1nd` (the requesting manager).
/// the resulting lock changes.
UpdateMetaInputs,
/// Add a scheduled prompt (closes #444). On approval 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. `commit_ref` stores the
/// JSON-encoded `SchedulePromptPayload` so the approval row carries
/// the full submission verbatim (target list, body, schedule).
/// Add a scheduled prompt to the broker queue.
SchedulePrompt,
}
@ -146,10 +121,10 @@ pub enum ApprovalStatus {
Approved,
Denied,
Failed,
/// Manager withdrew the request before the operator acted on it
/// (closes #250). Distinct from `Denied` (operator decision) and
/// `Failed` (post-approval lifecycle error) so the dashboard can
/// chip / sort cancellations separately.
/// Manager withdrew the request before the operator acted on it.
/// Distinct from `Denied` (operator decision) and `Failed`
/// (post-approval lifecycle error). See
/// `docs/approvals.md::Withdrawing a pending approval`.
Cancelled,
}