refactor(hive-c0re): drop the request_init_config tool and InitConfig approval
swarm-controller's `InitAgentConfigRepo` node already covers config-repo creation, so this deletes a duplicate rather than a capability; old `init_config` rows are skipped by `collect_lenient` with no migration, by operator decision. Refs #4398
This commit is contained in:
parent
3f086bc659
commit
a3b672d1d5
31 changed files with 134 additions and 601 deletions
|
|
@ -21,11 +21,10 @@ Topology lives in the hive-c0re-owned **meta repo**, alongside
|
|||
|
||||
`null` = root-level agent. New agents **default to root** — there is no
|
||||
structural manager that everything hangs under. Hierarchy is built
|
||||
explicitly: an agent that requests a sub-agent gets a
|
||||
requester-as-parent edge written at its `init_config` approval (so
|
||||
`alice` spawned `bob` above), and the operator can reparent any
|
||||
agent, including the bootstrap container (`ruth`) — it's just another
|
||||
root. The manager is reparentable like any other agent; there's no
|
||||
explicitly: an agent gets a parent edge written before its first spawn,
|
||||
or the operator reparents it afterwards (so `bob` above sits under
|
||||
`alice`). Any agent is reparentable, the bootstrap container (`ruth`)
|
||||
included — it's just another root. The manager is reparentable like any other agent; there's no
|
||||
"structurally root" carve-out. Its privileges live on its MCP socket,
|
||||
not its tree position (see _Manager special-casing today_ below).
|
||||
|
||||
|
|
@ -63,10 +62,11 @@ where system-level facts live.
|
|||
install that hasn't synced yet).
|
||||
- **Reconcile** — runs alongside the periodic meta/flake regeneration.
|
||||
New agents default to root unless they already carry an explicit
|
||||
parent edge from an `init_config` approval; Reconcile preserves existing entries
|
||||
(including operator overrides); removed agents drop.
|
||||
Agents that are approved but not yet spawned keep their edge too, so
|
||||
it survives the gap until the container actually appears.
|
||||
parent edge written before their first spawn; Reconcile preserves
|
||||
existing entries (including operator overrides); removed agents drop.
|
||||
Agents whose config repo exists but that haven't spawned yet keep
|
||||
their edge too, so it survives the gap until the container actually
|
||||
appears.
|
||||
- **Inject** — hive-c0re exposes each container's parent (if any) to its own
|
||||
environment as `HIVE_PARENT`, so the harness / system-prompt
|
||||
renderer can see it.
|
||||
|
|
@ -90,7 +90,6 @@ umount-old / mount-new / restart-cascade step.
|
|||
| operation | who can do it |
|
||||
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| `kill` / `start` / `restart` / `update` (any descendant) | any ancestor |
|
||||
| `request_init_config` (spawn a new child) | any agent, child added under self |
|
||||
| config change via forge PR (any descendant's config) | any ancestor |
|
||||
| `get_logs` (any descendant) | any ancestor |
|
||||
| moderate reminders (cancel any open thread of a descendant) | any ancestor |
|
||||
|
|
@ -110,15 +109,15 @@ other agents don't:
|
|||
- **Naming/bootstrap** — the manager's broker recipient name, state-dir
|
||||
key, and nixos-container name are all `ruth` (container `h-ruth`).
|
||||
`hive-c0re` spawns it directly at boot if missing, with no operator
|
||||
approval step — every other agent goes through `request_init_config`
|
||||
→ approval. Topology-wise, `ruth` is still just another root agent.
|
||||
approval step — every other agent goes through a `Spawn` approval.
|
||||
Topology-wise, `ruth` is still just another root agent.
|
||||
- **Wire-protocol** — the privileged `Request` variants
|
||||
(`RequestInitConfig`; `Kill` / `Start` / `Restart` / `Update`;
|
||||
(`Kill` / `Start` / `Restart` / `Update`;
|
||||
`GetLogs`; `RequestUpdateMetaInputs`) — marked `*(privileged)*` in
|
||||
`hive-core-agent-sock`'s unified `Request` enum — are reachable only
|
||||
from the manager's socket flavour today. Planned rule for each is in the
|
||||
table above ("any agent, child added under self" for init-config,
|
||||
"any ancestor" for lifecycle/logs); `RequestUpdateMetaInputs` stays
|
||||
table above ("any ancestor" for lifecycle/logs);
|
||||
`RequestUpdateMetaInputs` stays
|
||||
a root-only capability even post-milestone, not a topology rule.
|
||||
One exception: `Wake` (inject a `from: <X>` message into the
|
||||
caller's own inbox) isn't really privileged — every per-agent daemon
|
||||
|
|
|
|||
|
|
@ -24,12 +24,14 @@ CLI) before it takes effect. What you'll see, and what to do with it:
|
|||
anything in that chain fails, the change rolls back automatically —
|
||||
the agent stays on its last-good config, no recovery action needed
|
||||
from you.
|
||||
- **New agent** (`InitConfig` then `Spawn`) — creating a brand-new
|
||||
agent is two approvals. `InitConfig` creates the config repo and
|
||||
seeds it from a template; `Spawn` creates the container from that
|
||||
config. Tailoring the template first isn't a separate mechanism —
|
||||
it's the config-change flow above, a PR you review like any other. Every later change goes through the config-change flow
|
||||
above — there's no repeat "spawn" for an existing agent.
|
||||
- **New agent** (`Spawn`) — the one approval in creating a brand-new
|
||||
agent. Its config repo is scaffolded first, outside the approval
|
||||
queue, by the swarm controller's `InitAgentConfigRepo` job
|
||||
(`POST /api/agents`); `Spawn` then creates the container from that
|
||||
config. Tailoring what the template seeded isn't a separate
|
||||
mechanism — it's the config-change flow above, a PR you review like
|
||||
any other. Every later change goes through that flow — there's no
|
||||
repeat "spawn" for an existing agent.
|
||||
- **Meta/flake update** (`UpdateMetaInputs`) — an agent asked to bump
|
||||
one or more Nix flake inputs (or all of them). Approving runs the
|
||||
update and commits the lock change; it doesn't rebuild anything by
|
||||
|
|
@ -131,11 +133,10 @@ agent that lacks the `approvals` tool group: only an agent with that
|
|||
group submits approvals (for its direct children), so an agent
|
||||
without it has nothing of its own to withdraw.
|
||||
|
||||
`InitConfig` approvals create a brand-new agent's config repo. On
|
||||
approve, hive-c0re seeds it with a default `agent.nix` template and
|
||||
pushes a todo (`push_todo_submitter`) into the submitting agent's
|
||||
in-container store. The operator then **spawns** the agent (the
|
||||
`Spawn` approval / `◆ R3QU3ST SP4WN` button), which creates the
|
||||
A brand-new agent's config repo is created outside this queue, by the
|
||||
swarm controller's `InitAgentConfigRepo` job, which seeds it with a
|
||||
default `agent.nix` template. The operator then **spawns** the agent
|
||||
(the `Spawn` approval / `◆ R3QU3ST SP4WN` button), which creates the
|
||||
container from that config.
|
||||
|
||||
Changing what the template seeded isn't a special case: like every
|
||||
|
|
@ -146,7 +147,7 @@ through the web UI or the forge.
|
|||
|
||||
### Approval kinds (wire shapes)
|
||||
|
||||
`ApprovalKind` carries five variants; each maps to a different
|
||||
`ApprovalKind` carries four variants; each maps to a different
|
||||
`commit_ref` encoding because that field is overloaded as the
|
||||
kind-specific payload carrier.
|
||||
|
||||
|
|
@ -169,13 +170,11 @@ kind-specific payload carrier.
|
|||
`hivectl agent <name> request-create` 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 <name> create`). 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.
|
||||
- `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.
|
||||
`hivectl agent <name> create`). This is the **canonical first-spawn**: the
|
||||
swarm controller's `InitAgentConfigRepo` job seeds the agent's config
|
||||
repo, it gets customised through a PR, then the operator spawns to
|
||||
create the container. Subsequent config changes go through a
|
||||
`MergeConfigPr` PR.
|
||||
- `UpdateMetaInputs` — `commit_ref` stores the JSON-encoded inputs
|
||||
array (`"[]"` = all inputs, `"[\"nixpkgs\"]"` = just nixpkgs,
|
||||
etc.). hive-c0re sets the `agent` field to the requesting root agent.
|
||||
|
|
@ -421,7 +420,6 @@ rather than run inline:
|
|||
| `MergeConfigPr` | `rebuild` (`DeployWindow` root + `MergeVerify → DeployApply` + `DeployTail`) | `approval` |
|
||||
| `UpdateMetaInputs` | `meta_update` (`MetaLock` + rebuild fan-out) | `approval` |
|
||||
| `Spawn` | `spawn` (`Create → WriteDropin → Reconcile`) | `approval` |
|
||||
| `InitConfig` | — runs inline (sub-second git seed) | — |
|
||||
| `SchedulePrompt` | — runs inline (single sqlite insert) | — |
|
||||
|
||||
The DAG carries the originating `approval_id`, surfaced on the node that
|
||||
|
|
@ -604,7 +602,7 @@ as a regular `system` inbox message so it drives a normal claude turn.
|
|||
through `Coordinator::push_todo`/`push_todo_submitter` instead, a direct
|
||||
live dial of the target agent's in-container todo socket (same
|
||||
`UpsertTodo` request in-container producers use); `finish_approval` fires
|
||||
one of these too for `InitConfig`/`Spawn`/`MergeConfigPr`, *in addition to*
|
||||
one of these too for `Spawn`/`MergeConfigPr`, *in addition to*
|
||||
the `ApprovalResolved` HelperEvent above, not instead of it. Legacy
|
||||
approval rows that predate the submitter column fall back to the
|
||||
root agent. Variants (`hive_sh4re::manager::HelperEvent`):
|
||||
|
|
@ -625,7 +623,7 @@ root agent. Variants (`hive_sh4re::manager::HelperEvent`):
|
|||
no approval required.
|
||||
|
||||
The remaining lower-urgency lifecycle notices — `Rebuilt`, `Killed`,
|
||||
`Destroyed`, `NeedsLogin`, `LoggedIn`, `ConfigReady` — are "FYI, check
|
||||
`Destroyed`, `NeedsLogin`, `LoggedIn` — are "FYI, check
|
||||
when convenient" events with no reason to drive an immediate turn, so
|
||||
they deliver via `push_todo`/`push_todo_submitter` (see above) instead
|
||||
of `HelperEvent`: an `agent_todo_socket` push instead of a broker
|
||||
|
|
@ -638,7 +636,7 @@ hive-c0re-vouched commit sha. Optional `tag` carries the deploy
|
|||
bookkeeping tag — `deployed/<id>` on a successful build or
|
||||
`failed/<id>` on a failed one, planted by the `MergeConfigPr` deploy.
|
||||
Both fields are `Option`: `None` on the paths that don't deploy a new
|
||||
commit (spawn / init_config / meta-update / deny, and the autoupdate
|
||||
commit (spawn / meta-update / deny, and the autoupdate
|
||||
sweep's `job_queue::templates::rebuild` reapplying the existing main,
|
||||
or the dashboard `↻ R3BU1LD` button when the lock didn't move). When set,
|
||||
`git show <sha>` against `/applied/<n>/.git` inside the
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ power-intent registry:
|
|||
below](#state-dirs-per-agent) for where reminders (and todos)
|
||||
actually live now.
|
||||
- `approvals` — the queue. `agent / kind (merge_config_pr | spawn |
|
||||
init_config | update_meta_inputs | schedule_prompt) /
|
||||
update_meta_inputs | schedule_prompt) /
|
||||
commit_ref / requested_at / status / resolved_at / note`.
|
||||
- `scheduled_prompts` — recurring + one-shot prompt queue.
|
||||
`owner / body / interval_seconds (NULL = one-shot) /
|
||||
|
|
@ -353,9 +353,9 @@ tree anyone edits in place. Mounting it writable would leave a second
|
|||
path to the same file that skips the review entirely, which makes the
|
||||
boundary a convention rather than a permission.
|
||||
|
||||
⚠️ Not to be confused with the seeding done when an `InitConfig`
|
||||
approval resolves: that writes the child's initial config repo as
|
||||
**hive-c0re, against the host path**, and `read_only` on a bind
|
||||
⚠️ Not to be confused with the config-repo seeding hive-c0re does at
|
||||
spawn (`lifecycle::setup_proposed`): that writes the child's initial
|
||||
config repo as **hive-c0re, against the host path**, and `read_only` on a bind
|
||||
constrains writers *inside* a container only. The two are unrelated —
|
||||
conflating them can lead you to reason your way into thinking this
|
||||
mount should be writable when it shouldn't.
|
||||
|
|
@ -443,7 +443,7 @@ nothing is automigrated: existing agents keep their plain dirs
|
|||
until an explicit opt-in upgrade.
|
||||
|
||||
- **Creation:** `lifecycle::ensure_agent_state_subvolume` runs before
|
||||
hive-c0re creates the per-agent subdirs (spawn / rebuild / InitConfig).
|
||||
hive-c0re creates the per-agent subdirs (spawn / rebuild).
|
||||
It skips the work when the root already exists; otherwise it asks
|
||||
hive-priv (`EnsureAgentSubvolume`) to `btrfs subvolume create` the
|
||||
root when the FS is btrfs (`statfs` magic gate) and chown it to the
|
||||
|
|
|
|||
Loading…
Reference in a new issue