diff --git a/CLAUDE.md b/CLAUDE.md index b88d9d3b..a47d22b4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,9 +38,10 @@ hand-maintained per-file tree drifts out of sync with the code. and the axum operator dashboard (`dashboard.rs`). Largest crate. - **`hivectl/`** — standalone operator CLI (`hivectl` binary). Talks to the `hive-c0re` daemon over the host admin socket (`hive-host-sock` - wire types) — does NOT link `hive-c0re`. Full, always-current verb - reference (CI-enforced against the clap tree, see `docs/conventions.md`): - [`docs/tools/hivectl-cli.md`](docs/tools/hivectl-cli.md). + wire types) — does NOT link `hive-c0re`. Verbs: `list-agents`, + `agent `, `approvals `, `forge`/`matrix`/ + `github`/`gateway` provisioning, `stop`/`start`, `wg`/`peer-config`. - **`hive-agent/`**, **`hive-agent-mcp/`** — in-container harness, two sibling crates for every agent (not a single `hive-ag3nt/` dir — that's the runtime/binary-family nickname, diff --git a/docs/approvals.md b/docs/approvals.md index 0dacc7c4..e5305769 100644 --- a/docs/approvals.md +++ b/docs/approvals.md @@ -119,10 +119,10 @@ kind-specific payload carrier. - `Spawn` — direct container creation from the agent's config repo. `commit_ref` is empty. Submitted via `HostRequest::RequestSpawn` (operator-gated, the `◆ R3QU3ST SP4WN` dashboard button + - `hivectl agent request-create` CLI). The host-level `HostRequest::Spawn` + `hivectl agent 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; - `hivectl agent create`). This is the **canonical first-spawn**: a new agent's `InitConfig` + only (operator on the host shell, test scripts, one-off recoveries). + This is the **canonical first-spawn**: a new agent's `InitConfig` seeds its config repo, the submitting agent customises it, then the operator spawns to create the container. Subsequent config changes go through a `MergeConfigPr` PR. diff --git a/docs/tools/hivectl-cli.md b/docs/tools/hivectl-cli.md index 4b48d834..26a407bf 100644 --- a/docs/tools/hivectl-cli.md +++ b/docs/tools/hivectl-cli.md @@ -24,10 +24,8 @@ This document contains the help content for the `hivectl` command-line program. * [`hivectl agent restart`↴](#hivectl-agent-restart) * [`hivectl agent pause`↴](#hivectl-agent-pause) * [`hivectl agent resume`↴](#hivectl-agent-resume) -* [`hivectl agent start`↴](#hivectl-agent-start) -* [`hivectl agent create`↴](#hivectl-agent-create) -* [`hivectl agent request-create`↴](#hivectl-agent-request-create) -* [`hivectl agent stop`↴](#hivectl-agent-stop) +* [`hivectl agent spawn`↴](#hivectl-agent-spawn) +* [`hivectl agent request-spawn`↴](#hivectl-agent-request-spawn) * [`hivectl agent kill`↴](#hivectl-agent-kill) * [`hivectl agent destroy`↴](#hivectl-agent-destroy) * [`hivectl agent rebuild`↴](#hivectl-agent-rebuild) @@ -344,11 +342,9 @@ Everything here targets a single named agent (`hivectl agent foo restart`, `hive * `restart` — Stop and start this agent container without rebuilding config * `pause` — Park this agent's turn loop, leaving the container running * `resume` — Resume this paused agent — it drains whatever queued up while parked -* `start` — Start this EXISTING agent container. Fails immediately if `name` has no config/topology entry at all — it never attempts first-time creation. Use `create` for that -* `create` — Create this agent container from scratch (full first-time provisioning), bypassing the approval queue -* `request-create` — Queue a first-creation request for operator approval -* `stop` — Gracefully stop this agent container: signal → drain → reconcile. Never escalates to a hard kill — use `kill` for that -* `kill` — Hard-stop this managed container +* `spawn` — Spawn this agent container directly, bypassing the approval queue +* `request-spawn` — Queue a spawn request for operator approval +* `kill` — Stop this managed container (graceful) * `destroy` — Tear down this sub-agent container, keeping its state by default. No undo * `rebuild` — Apply pending config to this managed container * `set-parent` — Move this agent in the topology tree — under a new parent, or to root @@ -394,43 +390,27 @@ Resume this paused agent — it drains whatever queued up while parked -## `hivectl agent start` +## `hivectl agent spawn` -Start this EXISTING agent container. Fails immediately if `name` has no config/topology entry at all — it never attempts first-time creation. Use `create` for that +Spawn this agent container directly, bypassing the approval queue. -**Usage:** `hivectl agent start` +Operator-on-the-host only; use `request-spawn` for an approval-gated spawn. + +**Usage:** `hivectl agent spawn` -## `hivectl agent create` +## `hivectl agent request-spawn` -Create this agent container from scratch (full first-time provisioning), bypassing the approval queue. +Queue a spawn request for operator approval -Operator-on-the-host only; use `request-create` for an approval-gated creation. - -**Usage:** `hivectl agent create` - - - -## `hivectl agent request-create` - -Queue a first-creation request for operator approval - -**Usage:** `hivectl agent request-create` - - - -## `hivectl agent stop` - -Gracefully stop this agent container: signal → drain → reconcile. Never escalates to a hard kill — use `kill` for that - -**Usage:** `hivectl agent stop` +**Usage:** `hivectl agent request-spawn` ## `hivectl agent kill` -Hard-stop this managed container +Stop this managed container (graceful) **Usage:** `hivectl agent kill` diff --git a/hive-host-sock/src/lib.rs b/hive-host-sock/src/lib.rs index 5eb9419b..5a28902a 100644 --- a/hive-host-sock/src/lib.rs +++ b/hive-host-sock/src/lib.rs @@ -99,26 +99,14 @@ pub enum ReconcileDirection { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "cmd", rename_all = "snake_case")] pub enum HostRequest { - /// Create and start a brand-new sub-agent container directly (full - /// first-time provisioning: proposed/applied repos, state subvolume, - /// meta-flake sync, `nixos-container create`), bypassing the approval - /// queue. Privileged-context only. Exposed on the CLI as `hivectl - /// agent create`. See `docs/approvals.md::Approval kinds - /// (wire shapes)`. Wire name kept as `Spawn` (unrenamed underneath - /// the CLI-verb rename — `hivectl agent start` reuses the - /// existing scope-based [`HostRequest::Start`] below instead of a - /// new per-agent variant, see its doc comment). + /// 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: Ident }, - /// Submit a first-creation request for the operator to approve. See + /// Submit a spawn request for the operator to approve. See /// `docs/approvals.md::Approval kinds (wire shapes)` (`Spawn`). - /// Exposed on the CLI as `hivectl agent request-create`. RequestSpawn { name: Ident }, - /// Hard stop a managed container. Exposed on the CLI as `hivectl - /// agent kill` — kept distinct from the new graceful-only - /// `hivectl agent stop` (which reuses the scope-based - /// [`HostRequest::Stop`] below with `graceful: true`); `Kill` - /// escalates to a hard stop, `Stop` never does. Wire name kept as - /// `Kill`. + /// Stop a managed container (graceful). Kill { name: Ident }, /// Tear down a sub-agent container, optionally purging state. /// See `docs/approvals.md::Destroy semantics`. diff --git a/hivectl/README.md b/hivectl/README.md index 2668e6ab..afbbde0e 100644 --- a/hivectl/README.md +++ b/hivectl/README.md @@ -19,7 +19,7 @@ talk to the daemon over their own MCP tool surface One module per subcommand family; `main.rs` is just the clap parse + dispatch: -- **`agents.rs`** — container lifecycle (start/stop/create/kill/rebuild/restart/…). +- **`agents.rs`** — container lifecycle (spawn/kill/rebuild/restart/…). - **`approvals.rs`** — the config/init-config/meta-input approval queue. - **`dag_progress.rs`** — rebuild-queue progress rendering. - **`power.rs`** — restart/start/stop at the container level. diff --git a/hivectl/src/agents.rs b/hivectl/src/agents.rs index e37f33b9..d4fd9943 100644 --- a/hivectl/src/agents.rs +++ b/hivectl/src/agents.rs @@ -36,55 +36,6 @@ async fn agents_restart(socket: &Path, name: &str, no_wait: bool) -> Result<()> } } -/// `hivectl agent start` — start an EXISTING agent container. -/// Fails immediately (no request even sent) if `name` has no state dir -/// at all, rather than silently resolving to an empty scope. Reuses the -/// exact hive-wide `hivectl start` DAG (`HostRequest::Start`'s -/// scope-based path), just scoped to this one name — a separate -/// per-agent wire request would have duplicated logic this scope-based -/// one already covers. -async fn agents_start(socket: &Path, name: &str) -> Result<()> { - if !crate::util::agent_exists(socket, name).await? { - bail!( - "no such agent: '{name}' (no state dir under {}/) — use 'hivectl agent {name} create' to provision a brand-new agent", - hive_host_sock::AGENTS_ROOT - ); - } - render( - crate::client::request( - socket, - HostRequest::Start { - scope: hive_host_sock::LifecycleScope { - agent_names: vec![name.to_owned()], - ..Default::default() - }, - }, - ) - .await?, - ) -} - -/// `hivectl agent stop` — graceful-only stop (signal → drain → -/// reconcile), never escalating to a hard kill. Reuses the hive-wide -/// `hivectl stop --graceful` DAG (`HostRequest::Stop`'s scope-based -/// path), scoped to this one name. Distinct from `AgentCmd::Kill`, which -/// hard-stops via a separate DAG that does escalate. -async fn agents_stop(socket: &Path, name: &str) -> Result<()> { - render( - crate::client::request( - socket, - HostRequest::Stop { - scope: hive_host_sock::LifecycleScope { - agent_names: vec![name.to_owned()], - ..Default::default() - }, - graceful: true, - }, - ) - .await?, - ) -} - /// `hivectl list-agents` — fetch the per-agent status roster from the /// daemon (`HostRequest::AgentStatus`) and render it as a padded table, /// or the raw JSON rows with `--json`. Reuses the dashboard's @@ -198,16 +149,14 @@ pub(crate) async fn run_agent(socket: &Path, name: &str, cmd: AgentCmd) -> Resul AgentCmd::Restart { no_wait } => agents_restart(socket, name, no_wait).await, AgentCmd::Pause => set_paused(socket, name, true).await, AgentCmd::Resume => set_paused(socket, name, false).await, - AgentCmd::Start => agents_start(socket, name).await, - AgentCmd::Create => { + AgentCmd::Spawn => { let name = crate::util::parse_ident(name)?; render(crate::client::request(socket, HostRequest::Spawn { name }).await?) } - AgentCmd::RequestCreate => { + AgentCmd::RequestSpawn => { let name = crate::util::parse_ident(name)?; render(crate::client::request(socket, HostRequest::RequestSpawn { name }).await?) } - AgentCmd::Stop => agents_stop(socket, name).await, AgentCmd::Kill => { let name = crate::util::parse_ident(name)?; render(crate::client::request(socket, HostRequest::Kill { name }).await?) diff --git a/hivectl/src/cli.rs b/hivectl/src/cli.rs index 5bed6734..6a619b7d 100644 --- a/hivectl/src/cli.rs +++ b/hivectl/src/cli.rs @@ -468,22 +468,14 @@ pub enum AgentCmd { Pause, /// Resume this paused agent — it drains whatever queued up while parked. Resume, - /// Start this EXISTING agent container. Fails immediately if `name` - /// has no config/topology entry at all — it never attempts - /// first-time creation. Use `create` for that. - Start, - /// Create this agent container from scratch (full first-time - /// provisioning), bypassing the approval queue. + /// Spawn this agent container directly, bypassing the approval queue. /// - /// Operator-on-the-host only; use `request-create` for an - /// approval-gated creation. - Create, - /// Queue a first-creation request for operator approval. - RequestCreate, - /// Gracefully stop this agent container: signal → drain → reconcile. - /// Never escalates to a hard kill — use `kill` for that. - Stop, - /// Hard-stop this managed container. + /// Operator-on-the-host only; use `request-spawn` for an approval-gated + /// spawn. + Spawn, + /// Queue a spawn request for operator approval. + RequestSpawn, + /// Stop this managed container (graceful). Kill, /// Tear down this sub-agent container, keeping its state by default. /// No undo.