hive-sh4re + docs: extract Approval lifecycle prose (#717 batch 3)
This commit is contained in:
parent
eacfa9bdb3
commit
a0b15ed6a4
2 changed files with 80 additions and 56 deletions
|
|
@ -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
|
This gives the manager (and operator) an explicit review gate on the
|
||||||
initial configuration before any container is created.
|
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
|
## Meta flake
|
||||||
|
|
||||||
The hive-c0re-owned repo at `/var/lib/hyperhive/meta/`
|
The hive-c0re-owned repo at `/var/lib/hyperhive/meta/`
|
||||||
|
|
|
||||||
|
|
@ -14,29 +14,17 @@ pub mod assets;
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(tag = "cmd", rename_all = "snake_case")]
|
#[serde(tag = "cmd", rename_all = "snake_case")]
|
||||||
pub enum HostRequest {
|
pub enum HostRequest {
|
||||||
/// Create and start a sub-agent container directly (no approval). Use
|
/// Create and start a sub-agent container directly, bypassing the
|
||||||
/// this from privileged contexts (operator on the host); it bypasses the
|
/// approval queue. Privileged-context only. See
|
||||||
/// approval queue intentionally so test scripts and one-off recoveries
|
/// `docs/approvals.md::Approval kinds (wire shapes)`.
|
||||||
/// don't need a separate approve step.
|
|
||||||
Spawn { name: String },
|
Spawn { name: String },
|
||||||
/// Submit a spawn request for the operator to approve. On approval the
|
/// Submit a spawn request for the operator to approve. See
|
||||||
/// host creates and starts the container with the default `agent.nix`
|
/// `docs/approvals.md::Approval kinds (wire shapes)` (`Spawn`).
|
||||||
/// 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.
|
|
||||||
RequestSpawn { name: String },
|
RequestSpawn { name: String },
|
||||||
/// Stop a managed container (graceful).
|
/// Stop a managed container (graceful).
|
||||||
Kill { name: String },
|
Kill { name: String },
|
||||||
/// Tear down a sub-agent container: stop + remove + drop the systemd
|
/// Tear down a sub-agent container, optionally purging state.
|
||||||
/// drop-in, purge pending approvals. Persistent state (proposed/applied
|
/// See `docs/approvals.md::Destroy semantics`.
|
||||||
/// 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.
|
|
||||||
Destroy {
|
Destroy {
|
||||||
name: String,
|
name: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -74,22 +62,22 @@ pub struct HostResponse {
|
||||||
pub approvals: Option<Vec<Approval>>,
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Approval {
|
pub struct Approval {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub agent: String,
|
pub agent: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub kind: ApprovalKind,
|
pub kind: ApprovalKind,
|
||||||
/// For `ApplyCommit`: the git sha the manager submitted. For `Spawn`:
|
/// Kind-specific payload (git sha / inputs array / schedule
|
||||||
/// empty. Note that this is the manager's *claimed* ref — the
|
/// payload / empty). See the Approval struct doc.
|
||||||
/// canonical, hive-c0re-vouched sha after the proposal fetch lives
|
|
||||||
/// in `fetched_sha`.
|
|
||||||
pub commit_ref: String,
|
pub commit_ref: String,
|
||||||
/// The sha hive-c0re fetched from the proposed repo into applied at
|
/// `ApplyCommit` only: the canonical hive-c0re-vouched sha after
|
||||||
/// submission time, then tagged `proposal/<id>`. Stable for the
|
/// the proposal fetch, tagged `proposal/<id>`. Stable for the
|
||||||
/// lifetime of the approval — manager amends in proposed don't
|
/// approval's lifetime — manager amends in proposed don't change
|
||||||
/// change what gets built. Only set for `ApplyCommit` after the
|
/// what gets built.
|
||||||
/// successful fetch.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub fetched_sha: Option<String>,
|
pub fetched_sha: Option<String>,
|
||||||
pub requested_at: i64,
|
pub requested_at: i64,
|
||||||
|
|
@ -98,44 +86,31 @@ pub struct Approval {
|
||||||
pub resolved_at: Option<i64>,
|
pub resolved_at: Option<i64>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub note: Option<String>,
|
pub note: Option<String>,
|
||||||
/// Optional free-text description the manager attached at submission
|
/// Free-text description the manager attached at submission time;
|
||||||
/// time — shown on the dashboard approval card so the operator can
|
/// shown on the dashboard approval card.
|
||||||
/// understand the change without opening the diff.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What action the approval, when granted, will trigger.
|
/// 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)]
|
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum ApprovalKind {
|
pub enum ApprovalKind {
|
||||||
/// Apply a manager-proposed config commit (existing flow).
|
/// Apply a manager-proposed config commit.
|
||||||
#[default]
|
#[default]
|
||||||
ApplyCommit,
|
ApplyCommit,
|
||||||
/// Create + start a new sub-agent container with the given name.
|
/// Create + start a new sub-agent container with the given name
|
||||||
/// Used today by the host admin socket / dashboard "request spawn"
|
/// (under the default `agent.nix` template).
|
||||||
/// button; the manager-side `RequestSpawn` surface was removed in
|
|
||||||
/// favour of the two-step `InitConfig` → `ApplyCommit` flow (#442).
|
|
||||||
Spawn,
|
Spawn,
|
||||||
/// Initialise a new agent's proposed config repo so the manager can
|
/// Seed an agent's proposed config repo for manager customisation
|
||||||
/// customise it before submitting a `request_apply_commit`. On
|
/// (step 1 of the two-step spawn flow).
|
||||||
/// 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.
|
|
||||||
InitConfig,
|
InitConfig,
|
||||||
/// Run `nix flake update [inputs...]` on the meta flake and commit
|
/// Run `nix flake update [inputs...]` on the meta flake and commit
|
||||||
/// the resulting lock changes. The `commit_ref` field stores the
|
/// the resulting lock changes.
|
||||||
/// JSON-encoded inputs array (`"[]"` = all inputs). Agent field is
|
|
||||||
/// set to `hm1nd` (the requesting manager).
|
|
||||||
UpdateMetaInputs,
|
UpdateMetaInputs,
|
||||||
/// Add a scheduled prompt (closes #444). On approval hive-c0re
|
/// Add a scheduled prompt to the broker queue.
|
||||||
/// 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).
|
|
||||||
SchedulePrompt,
|
SchedulePrompt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,10 +121,10 @@ pub enum ApprovalStatus {
|
||||||
Approved,
|
Approved,
|
||||||
Denied,
|
Denied,
|
||||||
Failed,
|
Failed,
|
||||||
/// Manager withdrew the request before the operator acted on it
|
/// Manager withdrew the request before the operator acted on it.
|
||||||
/// (closes #250). Distinct from `Denied` (operator decision) and
|
/// Distinct from `Denied` (operator decision) and `Failed`
|
||||||
/// `Failed` (post-approval lifecycle error) so the dashboard can
|
/// (post-approval lifecycle error). See
|
||||||
/// chip / sort cancellations separately.
|
/// `docs/approvals.md::Withdrawing a pending approval`.
|
||||||
Cancelled,
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue