refactor(#2416): remove the non-pr config-change flow (request_apply_commit / applycommit)
This commit is contained in:
parent
fbbd5d921c
commit
c2bd7db998
34 changed files with 293 additions and 1635 deletions
|
|
@ -98,7 +98,7 @@ Once enforcement lands the rules collapse into:
|
|||
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| `kill` / `start` / `restart` / `update` (any descendant) | any ancestor |
|
||||
| `request_init_config` (spawn a new child) | any agent, child added under self |
|
||||
| `request_apply_commit` (any descendant's config) | any ancestor |
|
||||
| config change via forge PR (any descendant's config) | any ancestor |
|
||||
| `get_logs` (any descendant) | any ancestor |
|
||||
| moderate questions / reminders (cancel any open thread of a descendant) | any ancestor |
|
||||
| `send` / `recv` routing | parent ↔ same-parent siblings ↔ self ↔ descendants; explicit allow-list for anyone else |
|
||||
|
|
@ -133,7 +133,6 @@ can't:
|
|||
| variant | semantic | post-milestone |
|
||||
| --------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `RequestInitConfig` | seed an agent's proposed config repo | **topology** — existing direct child (re-init) or a brand-new name (child added under self on approval); a name owned by a different parent is refused |
|
||||
| `RequestApplyCommit` | submit a commit sha for operator approval | **topology** — descendants only |
|
||||
| `Kill` / `Start` / `Restart` / `Update` | container lifecycle on an existing agent | **topology** — descendants only |
|
||||
| `RequestUpdateMetaInputs` | bump meta `flake.lock` | **per-agent cap** (root-only today; a future "let coder bump its own input" might grant it) |
|
||||
| `GetLogs` | journalctl scrape of a sub-agent | **topology** — descendants only |
|
||||
|
|
|
|||
|
|
@ -10,67 +10,55 @@ informed about what happens after a decision lands.
|
|||
|
||||
## End-to-end approval flow
|
||||
|
||||
Config changes flow through a **forge pull request** on the agent's
|
||||
`agent-configs/<name>` repo — the same surface agents use for code PRs.
|
||||
There is no bespoke MCP tool for config changes: opening the PR IS the
|
||||
request.
|
||||
|
||||
1. The submitting agent (the child's parent, holding the `approvals`
|
||||
tool group) edits files in the child's proposed config repo
|
||||
(any tracked path, but `agent.nix` is the contract entry point)
|
||||
and commits with its own git identity. The parent's container has
|
||||
the child's proposed config repo bind-mounted read-write at
|
||||
(any tracked path, but `agent.nix` is the contract entry point),
|
||||
commits with its own git identity, and pushes a branch + opens a PR
|
||||
on `agent-configs/<name>` with `hive-forge`. The parent's container
|
||||
has the child's proposed config repo bind-mounted read-write at
|
||||
`/agents/<name>/config/` (topology-driven via `set_nspawn_flags`;
|
||||
the agent's *own* config at `/agents/<self>/config/` is read-only).
|
||||
2. The submitting agent submits the commit sha via `request_apply_commit(agent,
|
||||
commit_ref)`. `commit_ref` must be a commit **sha** (7-40 hex
|
||||
chars, short or full) — a branch or tag name is rejected so the
|
||||
approval pins an immutable commit.
|
||||
3. **hive-c0re immediately fetches that commit from the proposed
|
||||
repo into the applied repo and tags it `proposal/<id>`.** It
|
||||
resolves the sha locally against the proposed repo, fetches all
|
||||
of proposed's heads into applied's object db, then tags the
|
||||
resolved commit — `git fetch <remote> <sha>:<dst>` can't fetch
|
||||
by a bare sha (the left side of a refspec is a remote *ref
|
||||
name*), so the resolution happens on hive-c0re's side. The
|
||||
approval row stores both the submitted sha and the
|
||||
canonical hive-c0re-vouched sha. From here on the proposed
|
||||
repo is irrelevant for this approval — the submitter can amend,
|
||||
force-push, or `rm -rf` the proposed repo and the queued
|
||||
approval still points at an immutable git object inside
|
||||
applied.
|
||||
3a. **Flake validation (ApplyCommit only):** after the proposal tag
|
||||
is planted, hive-c0re reads `proposal/<id>:flake.lock` and
|
||||
runs two checks. If either check fails, no
|
||||
pending approval is created for the operator — the row is
|
||||
marked failed and surfaces on the dashboard with the
|
||||
validation message:
|
||||
- **Stale lock** — materialises the commit in a temp worktree,
|
||||
runs `nix flake lock` (no `--update-input` flags, so it only
|
||||
fills missing entries), and rejects if the committed
|
||||
`flake.lock` differs from the result. Triggered when the
|
||||
submitter added or removed `inputs` in `flake.nix` without
|
||||
re-running `nix flake lock`. Fix: run `nix flake lock` in
|
||||
the config repo, commit, and re-submit.
|
||||
- **Duplicate inputs** — groups lock nodes by their canonical
|
||||
`original` field; rejects if two or more nodes share the same
|
||||
source. This usually means an input is missing
|
||||
`inputs.<x>.inputs.nixpkgs.follows = "nixpkgs"`. Fix: add
|
||||
the `follows` directive, re-lock, and re-submit.
|
||||
Both checks only flag *new* violations — agents whose lock
|
||||
already carried duplicates before this check was added are
|
||||
unaffected until a coordinated config-change pass.
|
||||
4. Operator sees the proposal as a card on the dashboard — a
|
||||
full multi-file diff, toggleable between three bases (vs the
|
||||
running tree / vs the last approved proposal / vs the
|
||||
previous queued proposal) — and clicks ◆ APPR0VE (or
|
||||
`hive-c0re approve <id>` on the CLI).
|
||||
5. hive-c0re moves the working tree to `proposal/<id>` and runs
|
||||
the build under a sequence of tags (see below). On success,
|
||||
`applied/main` fast-forwards to the proposal commit. On
|
||||
failure, main stays put and the working tree resets back to
|
||||
the previous deployed commit.
|
||||
6. `HelperEvent::ApprovalResolved` (and `Rebuilt` for the
|
||||
ApplyCommit kind) land in the **submitting agent's** inbox, carrying
|
||||
both the canonical sha and the terminal tag. Helper events route to
|
||||
the submitting agent via `notify_submitter` (the approval row carries
|
||||
a `submitter` column recording which agent called `request_apply_commit`
|
||||
or `request_init_config`).
|
||||
Branch protection (push/merge whitelist = `core`, approvals whitelist
|
||||
= operator team; see "Forge mirror" and #1787) makes the agent a
|
||||
write collaborator that **cannot merge its own config PR**.
|
||||
2. hive-c0re's `/webhook/config-pr` endpoint receives the Forgejo
|
||||
`pull_request` event (opened / synchronized / reopened) and queues a
|
||||
`MergeConfigPr` approval; a poll fallback catches any missed webhook.
|
||||
The approval row stores the PR **number** (`commit_ref`) and the PR
|
||||
**head sha at queue time** (`fetched_sha` — the "reviewed" sha). If
|
||||
the PR head later moves, the stale approval is superseded by a fresh
|
||||
one pinned to the new head, so the operator always reviews what will
|
||||
actually deploy.
|
||||
3. The operator reviews the PR **on the forge** (native diff, threaded
|
||||
comments, CI status) and sees a matching card on the dashboard with a
|
||||
"review PR on forge" deep link. They click ◆ APPR0VE (or
|
||||
`hive-c0re approve <id>` on the CLI) once satisfied.
|
||||
4. On approve, `run_merge_config_pr`:
|
||||
- re-reads the live PR head and **aborts if it drifted** from the
|
||||
reviewed `fetched_sha` (the submitter must push again, which queues
|
||||
a fresh approval);
|
||||
- fetches that head into the applied repo and **eval-verifies** it —
|
||||
a flake eval on a throwaway checkout. This is the trust gate: it
|
||||
relies on c0re's own eval, not on any in-repo (agent-forgeable)
|
||||
signal like a CI status;
|
||||
- fast-forwards the forge config repo's `main` to the reviewed head
|
||||
(this IS the merge — a `core`-authenticated ff-push, so a moved PR
|
||||
head can't substitute bytes) and marks the PR merged (best-effort;
|
||||
`main` is already there);
|
||||
- runs the shared deploy tail (`deploy_applied_target`): builds under
|
||||
the tag sequence below, and on success `applied/main`
|
||||
fast-forwards to the reviewed commit + the meta lock bumps. On
|
||||
failure, main stays put and the working tree resets to the previous
|
||||
deployed commit.
|
||||
5. `HelperEvent::ApprovalResolved` (and `Rebuilt`) land in the
|
||||
**submitting agent's** inbox via `notify_submitter`, carrying both the
|
||||
canonical sha and the terminal tag (the approval row carries a
|
||||
`submitter` column recording the agent the change is for).
|
||||
|
||||
### Withdrawing a pending approval
|
||||
|
||||
|
|
@ -88,53 +76,47 @@ 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 are the first step in a two-step spawn
|
||||
flow. On approve, hive-c0re seeds the proposed config repo with
|
||||
a default `agent.nix` template and sends `HelperEvent::ConfigReady { agent }`
|
||||
to the submitting agent's inbox via `notify_submitter`. The submitting
|
||||
agent then reviews,
|
||||
edits, and commits the template before calling `request_apply_commit`
|
||||
to proceed to an `ApplyCommit` approval. The first `ApplyCommit`
|
||||
creates the container; subsequent ones rebuild it with new config.
|
||||
This gives the submitting agent (and operator) an explicit review gate on the
|
||||
initial configuration before any container is created.
|
||||
`InitConfig` approvals seed a brand-new agent's proposed config repo.
|
||||
On approve, hive-c0re seeds it with a default `agent.nix` template and
|
||||
sends `HelperEvent::ConfigReady { agent }` to the submitting agent's
|
||||
inbox via `notify_submitter`. The submitting agent reviews, edits, and
|
||||
commits the template; the operator then **spawns** the agent (the
|
||||
`Spawn` approval / `◆ R3QU3ST SP4WN` button), which creates the
|
||||
container from that config. From then on, config changes go through a
|
||||
forge PR (`MergeConfigPr`) — never a fresh spawn. This gives the
|
||||
submitting agent (and operator) an explicit review gate on the initial
|
||||
configuration before any container is created.
|
||||
|
||||
### Approval kinds (wire shapes)
|
||||
|
||||
`ApprovalKind` carries six variants; each maps to a different
|
||||
`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 submitted 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.
|
||||
- `MergeConfigPr` — the PR-based config flow's counterpart to
|
||||
`ApplyCommit`. Triggered automatically: when an agent opens (or
|
||||
force-pushes) a PR on its `agent-configs/<agent>` forge repo,
|
||||
hive-c0re's `/webhook/config-pr` endpoint receives the Forgejo
|
||||
pull_request event and queues this approval row. No MCP tool call
|
||||
needed — the forge PR IS the request. `commit_ref` stores the
|
||||
**PR number** (decimal), and `fetched_sha` is the PR **head sha
|
||||
at queue time** (the "reviewed" sha). On approve,
|
||||
- `MergeConfigPr` — the config-change flow. Triggered automatically:
|
||||
when an agent opens (or force-pushes) a PR on its
|
||||
`agent-configs/<agent>` forge repo, hive-c0re's `/webhook/config-pr`
|
||||
endpoint receives the Forgejo pull_request event and queues this
|
||||
approval row. No MCP tool call needed — the forge PR IS the request.
|
||||
`commit_ref` stores the **PR number** (decimal), and `fetched_sha` is
|
||||
the PR **head sha at queue time** (the "reviewed" sha). On approve,
|
||||
`run_merge_config_pr` re-reads the live PR head and aborts if it
|
||||
drifted from `fetched_sha` (submitter must push again to
|
||||
re-trigger), then fetches that head into the applied repo,
|
||||
eval-verifies it, fast-forwards the forge config repo's `main` to
|
||||
it (the merge), marks the PR merged (best-effort — `main` is
|
||||
already there), and runs the same shared deploy tail as
|
||||
`ApplyCommit` (`deploy_applied_target`). Never a first spawn.
|
||||
- `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
|
||||
agent-side `RequestSpawn` is gone; the submitting agent goes through the
|
||||
`InitConfig` → `ApplyCommit` two-step instead so the spawn
|
||||
captures the customised config.
|
||||
already there), and runs the shared deploy tail
|
||||
(`deploy_applied_target`). Never a first spawn.
|
||||
- `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 +
|
||||
`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).
|
||||
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.
|
||||
|
|
@ -239,14 +221,14 @@ module that `setup_applied` used to generate inline.
|
|||
Containers run against `--flake /var/lib/hyperhive/meta#<n>`.
|
||||
|
||||
Per-deploy lock flow (two-phase, owned by
|
||||
`actions::run_apply_commit` → `meta::{prepare,finalize,abort}
|
||||
_deploy`):
|
||||
`actions::run_merge_config_pr` → `deploy_applied_target` →
|
||||
`meta::{prepare,finalize,abort}_deploy`):
|
||||
|
||||
1. `meta::prepare_deploy(name)` runs
|
||||
`nix flake lock --update-input agent-<n>` without
|
||||
committing. Working tree of meta now points the input at
|
||||
`applied/<n>/main` (which `run_apply_commit` already
|
||||
fast-forwarded to `proposal/<id>`).
|
||||
`applied/<n>/main` (which the deploy already fast-forwarded to
|
||||
the reviewed PR head).
|
||||
2. `lifecycle::rebuild_no_meta` runs
|
||||
`nixos-container update <c> --flake meta#<name>`. Nix
|
||||
evaluates against the staged lock.
|
||||
|
|
@ -323,34 +305,29 @@ wraps it with identity + `HIVE_PORT` / `HIVE_LABEL` /
|
|||
|
||||
### Tag state machine
|
||||
|
||||
Every approval id walks through a fixed set of tags on the
|
||||
underlying commit inside the applied repo:
|
||||
Each deploy leaves a tag on the underlying commit inside the applied
|
||||
repo:
|
||||
|
||||
| Tag | When | Annotated? |
|
||||
|---|---|---|
|
||||
| `proposal/<id>` | request_apply_commit, after fetch | no |
|
||||
| `approved/<id>` | operator approve | no |
|
||||
| `building/<id>` | rebuild started | no |
|
||||
| `deployed/<id>` | rebuild succeeded — `main` ff's here | no |
|
||||
| `failed/<id>` | rebuild failed | yes (body = error) |
|
||||
| `denied/<id>` | operator deny | yes (body = operator note) |
|
||||
|
||||
`applied/main` is always the latest `deployed/*`. `denied/` and
|
||||
`failed/` are terminal; the submitting agent submits a new commit + new
|
||||
approval id to retry. Because tags are first-class git objects,
|
||||
rejected and failed trees stay browsable forever — `git log
|
||||
--tags` in the applied repo is the audit trail.
|
||||
`deployed/0` is planted at first spawn. `applied/main` is always the
|
||||
latest `deployed/*`. A `failed/` tree stays browsable forever — `git log
|
||||
--tags` in the applied repo is the audit trail. A denied or failed config
|
||||
PR carries no extra state on the forge side: the PR stays open, and the
|
||||
submitter pushes again (or closes it) to retry.
|
||||
|
||||
### Dispatch via the job queue
|
||||
|
||||
Long-running approval work — `ApplyCommit`, `UpdateMetaInputs`,
|
||||
Long-running approval work — `MergeConfigPr`, `UpdateMetaInputs`,
|
||||
`Spawn` — no longer runs inline inside `actions::approve`. Instead
|
||||
the approval handler submits a DAG to the global job queue
|
||||
(`docs/coordinator.md::Job queue`):
|
||||
|
||||
| `ApprovalKind` | DAG submitted | source |
|
||||
|---|---|---|
|
||||
| `ApplyCommit` | `rebuild` (single opaque `ApprovalDeploy` node) | `approval` |
|
||||
| `MergeConfigPr` | `rebuild` (single opaque `ApprovalDeploy` node) | `approval` |
|
||||
| `UpdateMetaInputs` | `meta_update` (`MetaLock` + rebuild fan-out) | `approval` |
|
||||
| `Spawn` | `spawn` (`Create → WriteDropin → Reconcile`) | `approval` |
|
||||
|
|
@ -358,9 +335,8 @@ the approval handler submits a DAG to the global job queue
|
|||
| `SchedulePrompt` | — runs inline (single sqlite insert) | — |
|
||||
|
||||
The DAG carries the originating `approval_id`. The `ApprovalDeploy`
|
||||
node runs the kind-specific pipeline (`run_approval_apply_commit` /
|
||||
`run_approval_merge_config_pr` — the two-phase meta deploy stays
|
||||
inside `actions.rs`) and fires the matching `HelperEvent::*` via
|
||||
node runs `run_approval_merge_config_pr` (the two-phase meta deploy
|
||||
stays inside `actions.rs`) and fires the matching `HelperEvent::*` via
|
||||
`finish_approval` itself; `Spawn` and `UpdateMetaInputs` DAGs resolve
|
||||
through `actions::resolve_approval_dag` when the DAG settles terminal
|
||||
(a spawn additionally runs the post-spawn forge bookkeeping there).
|
||||
|
|
@ -391,22 +367,25 @@ The bundled `hive-forge` container is mandatory (it deploys with
|
|||
hyperhive), and hive-c0re mirrors every agent's applied repo into a
|
||||
private `agent-configs` Forgejo org. `forge::push_config(<name>)` pushes `applied/main` plus
|
||||
every tag to `agent-configs/<name>` after each ref mutation:
|
||||
the spawn that seeds `deployed/0`, every `request_apply_commit`
|
||||
(which plants `proposal/<id>`), every approve / deny, and a
|
||||
the spawn that seeds `deployed/0`, every successful deploy (which
|
||||
plants `deployed/<id>`) or failed build (`failed/<id>`), and a
|
||||
sweep at startup. Pushes are best-effort — a missing or stopped
|
||||
forge never blocks a deploy.
|
||||
|
||||
The org is private and agents are not members, so only the
|
||||
`core` user (a Forgejo site admin) can read it: an agent can't
|
||||
reach another agent's config — or even its own — through the
|
||||
forge. The tokenised push URL is passed inline to `git push`,
|
||||
never written into `applied/<n>/.git/config`; that repo is
|
||||
RO-bind-mounted into the root agent, and a stored token would leak
|
||||
core's admin credential to an agent.
|
||||
Each agent is a **write collaborator on its own** `agent-configs/<name>`
|
||||
repo — so it can push a branch and open a config PR — but not a member
|
||||
of any other agent's, so it can't reach another agent's config through
|
||||
the forge. Branch protection keeps `main` push/merge `core`-only with
|
||||
operator-team approval, so an agent can't fast-forward its own config or
|
||||
self-merge its PR (see the End-to-end flow + #1787). The tokenised push
|
||||
URL is passed inline to `git push`, never written into
|
||||
`applied/<n>/.git/config`; that repo is RO-bind-mounted into the root
|
||||
agent, and a stored token would leak core's admin credential to an
|
||||
agent.
|
||||
|
||||
The dashboard deep-links into this org — a `config repo` link
|
||||
per container row and a `commit on forge` link per approval
|
||||
card. See `docs/web-ui.md`.
|
||||
per container row and a `review PR on forge` link per config-PR
|
||||
approval card. See `docs/web-ui.md`.
|
||||
|
||||
### Submitting agent's view of config repos
|
||||
|
||||
|
|
@ -484,8 +463,8 @@ hive-c0re creates it. The root agent's flake lives at
|
|||
`/var/lib/hyperhive/applied/ruth/`; its proposed config at
|
||||
`/var/lib/hyperhive/agents/ruth/config/`. The root agent can edit its own
|
||||
`agent.nix` (visible inside the container at `/agents/ruth/config/`)
|
||||
and submit `request_apply_commit("ruth", <sha>)` for operator
|
||||
approval.
|
||||
and open a config PR on `agent-configs/ruth` for operator approval,
|
||||
same as any other agent.
|
||||
|
||||
Differences from sub-agents:
|
||||
|
||||
|
|
@ -559,11 +538,11 @@ root agent. Variants (`hive_sh4re::HelperEvent`):
|
|||
- `ApprovalResolved { id, agent, commit_ref, status, note }` —
|
||||
fired by `actions::approve` + `actions::deny` whenever an
|
||||
approval transitions to its terminal state.
|
||||
- `Spawned { agent, ok, note }` — `actions::approve` (first-time
|
||||
ApplyCommit-kind) + admin `HostRequest::Spawn` (deprecated).
|
||||
- `Spawned { agent, ok, note }` — the `Spawn` approval DAG +
|
||||
admin `HostRequest::Spawn`.
|
||||
- `Rebuilt { agent, ok, note }` — `auto_update::rebuild_agent`
|
||||
(covers startup scan + manual `/rebuild` from dashboard) +
|
||||
`actions::approve` (ApplyCommit).
|
||||
the `MergeConfigPr` deploy.
|
||||
- `Killed { agent }` — admin `HostRequest::Kill` + dashboard
|
||||
`/kill` + the `Kill` MCP tool.
|
||||
- `Destroyed { agent }` — `actions::destroy`.
|
||||
|
|
@ -582,9 +561,9 @@ root agent. Variants (`hive_sh4re::HelperEvent`):
|
|||
often greets the agent on this event.
|
||||
- `ConfigReady { agent }` — a new agent's proposed config repo was
|
||||
just seeded (post-`InitConfig` approval). The root agent can now
|
||||
edit `/agents/<agent>/config/agent.nix`, commit the changes,
|
||||
and submit `request_apply_commit` with the commit sha to create
|
||||
the container (first ApplyCommit also triggers spawn bookkeeping).
|
||||
edit `/agents/<agent>/config/agent.nix`, commit the changes, and
|
||||
hand off to the operator to **spawn** the agent (the `Spawn`
|
||||
approval creates the container from that config).
|
||||
- `NeedsUpdate { agent }` — sub-agent's recorded flake rev is
|
||||
stale. The root agent calls `update(name)` to rebuild — idempotent,
|
||||
no approval required.
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ binary flavor.
|
|||
| `inbox` | `get_loose_ends`, `cancel_loose_end`, `remind`, `request_next_turn` |
|
||||
| `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` | `kill`, `start`, `restart`, `update` *(privileged)* |
|
||||
| `approvals` | `request_init_config`, `request_apply_commit`, `request_update_meta_inputs` *(privileged)* |
|
||||
| `approvals` | `request_init_config`, `request_update_meta_inputs` *(privileged)* |
|
||||
| `scheduling` | `request_schedule_prompt`, `fire_schedule_now`, `cancel_schedule`, `edit_schedule`, `list_schedules` *(privileged)* |
|
||||
| `diagnostics` | `get_logs` *(privileged)* |
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ per template.
|
|||
|
||||
### Approvals
|
||||
|
||||
`ApplyCommit` / `MergeConfigPr` approvals ride as single-node
|
||||
`MergeConfigPr` approvals ride as single-node
|
||||
`ApprovalDeploy` DAGs: the two-phase `prepare_deploy` / `finalize_deploy` /
|
||||
`abort_deploy` meta orchestration stays inside `actions.rs` in v1
|
||||
(deliberately not modeled as scheduler nodes) and resolves the approval
|
||||
|
|
@ -274,7 +274,7 @@ Key operations:
|
|||
init the repo on first call, relock if the rendered contents changed, commit.
|
||||
Called by spawn / destroy / startup migration.
|
||||
- **`prepare_deploy` + `finalize_deploy` / `abort_deploy`** — two-phase for the
|
||||
`RequestApplyCommit` path so a failed `nixos-container update` leaves no orphan
|
||||
`MergeConfigPr` deploy path so a failed `nixos-container update` leaves no orphan
|
||||
commit in meta. Prepare writes the new lock without committing; finalize commits
|
||||
with the deploy message; abort restores the lock.
|
||||
- **`lock_update_hyperhive`** — one-shot for the boot-reconcile path (the
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ header/targets split, and the per-agent power-intent registry:
|
|||
under the agent's state dir; the worker delivers a short
|
||||
pointer instead. `attempt_count` / `last_error` accumulate
|
||||
on delivery-failed retries.
|
||||
- `approvals` — the queue. `agent / kind (apply_commit | spawn |
|
||||
- `approvals` — the queue. `agent / kind (merge_config_pr | spawn |
|
||||
init_config | update_meta_inputs | schedule_prompt) /
|
||||
commit_ref / requested_at / status / resolved_at / note`.
|
||||
- `operator_questions` — `ask` / `answer` queue (despite the
|
||||
|
|
|
|||
|
|
@ -65,12 +65,15 @@ the container, via MCP tools):
|
|||
request_init_config(name: "iris")
|
||||
# → operator approves → config_ready event lands in the inbox
|
||||
|
||||
# Step 2: edit /agents/iris/config/agent.nix, commit it, then:
|
||||
request_apply_commit(agent: "iris", commit_ref: "<sha>")
|
||||
# → operator approves → container built + started
|
||||
# Step 2: edit /agents/iris/config/agent.nix and commit it. Then the
|
||||
# operator spawns iris (dashboard ◆ R3QU3ST SP4WN / Spawn approval),
|
||||
# which builds + starts the container from that config.
|
||||
|
||||
# Later config changes: open a PR on agent-configs/iris (hive-forge);
|
||||
# the operator reviews + approves it — no MCP tool call.
|
||||
```
|
||||
|
||||
See [`approvals.md`](approvals.md) for the full two-step flow.
|
||||
See [`approvals.md`](approvals.md) for the full flow.
|
||||
|
||||
### 5 · Useful host commands
|
||||
|
||||
|
|
@ -97,8 +100,8 @@ See [`tools/hivectl.md`](tools/hivectl.md) for every `hivectl` verb.
|
|||
- **No forge admin token is stored in any agent state dir.** Agents
|
||||
hold a regular agent token in their `forge-token` file; sensitive
|
||||
creds (the core token, the matrix admin token) live on the host.
|
||||
- All config changes (`request_apply_commit`) go through operator
|
||||
approval — agents can't unilaterally rebuild containers, by design.
|
||||
- All config changes (forge PRs on `agent-configs/<name>`) go through
|
||||
operator approval — agents can't unilaterally rebuild containers, by design.
|
||||
See [`boundary.md`](boundary.md) and [`security.md`](security.md).
|
||||
|
||||
Once the hive is running, ruth records anything it needs to remember
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ name as-is.
|
|||
| `get_logs*` | `get_logs* name` or `get_logs* name NL` |
|
||||
| `get_host_journal*` | `get_host_journal*()` or with `[container] · [/grep/] · NL` |
|
||||
| **Approvals / config** | |
|
||||
| `request_apply_commit*` | `request_apply_commit* agent @ sha12` |
|
||||
| `request_init_config*` | `request_init_config* name` |
|
||||
| `request_update_meta_inputs*` | `request_update_meta_inputs* [inp1, …]` or `all` |
|
||||
| **Scheduling** | |
|
||||
|
|
|
|||
|
|
@ -45,24 +45,17 @@ Step 1 of spawning a new direct child agent. Queues an `InitConfig`
|
|||
approval; on operator approve, hive-c0re seeds the proposed config
|
||||
repo at `/agents/<name>/config/agent.nix` with a default template and
|
||||
delivers a `config_ready` system event. Then edit `agent.nix`, commit,
|
||||
and call `request_apply_commit` with the commit sha — the first
|
||||
`ApplyCommit` on a freshly-init'd config creates the container.
|
||||
and the operator **spawns** the agent (the dashboard `◆ R3QU3ST SP4WN`
|
||||
button / `Spawn` approval, routed via `HostRequest::RequestSpawn`),
|
||||
which creates the container from that config.
|
||||
|
||||
Subsequent config changes go through a **forge PR** on the agent's
|
||||
`agent-configs/<name>` repo (queues a `MergeConfigPr` approval on
|
||||
open/update — no MCP tool involved), not a tool call. See
|
||||
`docs/approvals.md`.
|
||||
|
||||
Fails if a proposed config repo for `name` already exists.
|
||||
`name` is ≤ 9 characters. The operator can also spawn an empty agent
|
||||
via the dashboard `◆ R3QU3ST SP4WN` button, which routes via
|
||||
`HostRequest::RequestSpawn`.
|
||||
|
||||
### `request_apply_commit(agent, commit_ref, description?)`
|
||||
|
||||
Step 2 of spawning (or updating an existing child's config). Submit a
|
||||
commit sha from the child's proposed config repo for operator
|
||||
approval. On approve, hive-c0re rebuilds the container with the
|
||||
pinned commit.
|
||||
|
||||
`commit_ref` must be a 7-40 char hex sha (branch/tag names are
|
||||
rejected — the approval pins the exact commit). `agent` must be a
|
||||
direct child. Topology-enforced.
|
||||
`name` is ≤ 9 characters.
|
||||
|
||||
### `request_update_meta_inputs(inputs?, description?)`
|
||||
|
||||
|
|
@ -81,7 +74,6 @@ agents after the approval resolves.
|
|||
| `kill` / `start` / `restart` / `update` | No | Direct children |
|
||||
| `list_containers` | No | All descendants |
|
||||
| `request_init_config` | Yes (InitConfig) | New direct child only |
|
||||
| `request_apply_commit` | Yes (ApplyCommit) | Direct children |
|
||||
| `request_update_meta_inputs` | Yes (MetaUpdate) | Meta flake (global) |
|
||||
|
||||
## See also
|
||||
|
|
|
|||
|
|
@ -1066,7 +1066,6 @@ renderApprovals`) with three stacked sections:
|
|||
|
||||
| kind | glyph | chip | sha shown |
|
||||
|---|---|---|---|
|
||||
| `apply_commit` | `→` | `apply` | proposal sha (`sha_short`) |
|
||||
| `merge_config_pr` | `⇒` | `merge-pr` | PR-head sha (`sha_short`) |
|
||||
| `update_meta_inputs` | `↻` | `meta-update` | — |
|
||||
| `schedule_prompt` | `⏱` | `schedule` | — |
|
||||
|
|
@ -1080,26 +1079,16 @@ renderApprovals`) with three stacked sections:
|
|||
than at the next `renderApprovals` call.
|
||||
- **what-changed body** — the submitting agent's description, then
|
||||
kind-specific drill-in triggers:
|
||||
- `apply_commit`: `↳ view diff` opens the inline diff side-panel;
|
||||
`↳ commit on forge ↗` deep-links the proposal commit into
|
||||
`agent-configs/<agent>` (shown only when `forge_present`).
|
||||
- `merge_config_pr`: `↳ review PR on forge ↗` deep-links the
|
||||
config PR into `agent-configs/<agent>/pulls/<pr_number>` (shown
|
||||
only when `forge_present` and `pr_number` is set). No inline diff
|
||||
side-panel (apply_commit-only for now).
|
||||
only when `forge_present` and `pr_number` is set). The config diff
|
||||
lives on the forge PR itself — no inline diff side-panel.
|
||||
- `init_config` / `spawn`: a one-line "container will be created"
|
||||
note instead.
|
||||
- **decision actions** — `◆ APPR0VE` and `DENY`. Deny pops a
|
||||
`prompt()` for an optional reason carried to the submitting agent as
|
||||
`HelperEvent::ApprovalResolved.note`.
|
||||
|
||||
The diff panel has a 3-way base toggle — **vs applied** (the
|
||||
running tree, served instantly from the diff already on the
|
||||
approval), **vs last-approved**, **vs previous proposal** — the
|
||||
latter two fetched on click from `GET /api/approval-diff/{id}
|
||||
?base=approved|previous`. Each line is classified client-side
|
||||
(`+` / `-` / `@@` / `--- ` / `+++ ` → add / del / hunk / file).
|
||||
|
||||
A `pending · N` / `history · N` tab pair switches the section
|
||||
between the live queue and the last 30 resolved approvals.
|
||||
|
||||
|
|
@ -1199,12 +1188,8 @@ that's a browser-level decision, not ours.
|
|||
`"ok"`/`"err"`, `detail` nullable), newest first, server-clamped to
|
||||
500; `total` is the full row count for a "latest 500 of N" header.
|
||||
Backs the LOGS page AUDIT sub-tab.
|
||||
- `GET /api/approval-diff/{id}?base=applied|approved|previous` —
|
||||
on-demand unified diff for an `ApplyCommit` approval against
|
||||
the chosen base (running tree / last approved proposal /
|
||||
previous queued proposal). Raw diff text, classified
|
||||
client-side. `GET /static/marked.js` serves the vendored
|
||||
`marked` bundle the side panel uses for markdown previews.
|
||||
- `GET /static/marked.js` serves the vendored `marked` bundle used
|
||||
for markdown previews.
|
||||
- `GET /api/state-file?path=<host-or-container-path>` — bounded
|
||||
text read of a file under the per-agent `state/` subtree or
|
||||
the shared `/var/lib/hyperhive/shared/`. Accepts the
|
||||
|
|
|
|||
Loading…
Reference in a new issue