docs(conventions): fix stale internal refs verified against source
- MAX_AGENT_NAME lives in lifecycle/mod.rs, not bare lifecycle.rs - agent_server::handle_send -> socket_server::handle_send (no agent_server module exists) - AgentMeta response is missing matrix_accounts in the field list - tool-group table missing list_containers/ack_until (added since written) and the forge/web_tools groups entirely - #[tool] fns live on AgentServer in hive-agent-mcp/src/mcp/mod.rs, not a HiveServer in a nonexistent hive-ag3nt/src/mcp.rs; ToolGroup::tools() lives in hive-sh4re/src/permissions.rs, not lib.rs - Capability + as_str also moved to permissions.rs; capability-check handler list was stale (agent_server.rs/mcp.rs don't exist) - async-forms listener is bindAsyncForms in frontend/packages/shared, not assets/tabs.js + assets/app.js - 'rebuild is the reconcile verb' described a monolithic lifecycle::rebuild that no longer exists — it's job_queue::templates::rebuild building a DAG, and flake.nix is no longer regenerated host-side on rebuild at all
This commit is contained in:
parent
1cc1ace681
commit
c870e230bf
1 changed files with 34 additions and 21 deletions
|
|
@ -8,7 +8,7 @@ exist because something already went wrong without them.
|
|||
- Containers are length-bounded by `nixos-container` (≤ 11 chars).
|
||||
- Sub-agents are `h-<name>` with `<name>` ≤ 9 chars.
|
||||
- One agent is the bootstrap/root container, with a fixed name (`ruth` today).
|
||||
- `MAX_AGENT_NAME` in `lifecycle.rs` enforces the cap.
|
||||
- `MAX_AGENT_NAME` in `hive-c0re/src/lifecycle/mod.rs` enforces the cap.
|
||||
- Per-agent web UI port = `WEB_PORT_BASE + FNV1a(name) % WEB_PORT_RANGE`
|
||||
(8100..8999) for every agent; dashboard
|
||||
`cfg.dashboardPort` (default 7000).
|
||||
|
|
@ -83,7 +83,7 @@ name validation rejects any character outside `[a-z0-9_-]`, so the
|
|||
angle-bracket and asterisk shapes below are structurally safe.
|
||||
|
||||
- `*` — broadcast: deliver to every running agent except the sender
|
||||
(`agent_server::handle_send` fans out via `Coordinator::broadcast_send`).
|
||||
(`socket_server::handle_send` fans out via `Coordinator::broadcast_send`).
|
||||
- `operator` — the human at the dashboard. Messages accumulate in the
|
||||
inbox view; no agent ever `recv`'s them.
|
||||
- `<parent>` — the sender's parent per `topology.json`. Rewritten at
|
||||
|
|
@ -93,7 +93,7 @@ angle-bracket and asterisk shapes below are structurally safe.
|
|||
their parent without learning the label, so runtime reparenting
|
||||
propagates with zero agent-side restart.
|
||||
- `<children>` — fan-out to every direct descendant of the sender per
|
||||
`topology.json`. Resolved in `agent_server::handle_send` via
|
||||
`topology.json`. Resolved in `socket_server::handle_send` via
|
||||
`topology::children_of(sender)`: one message is delivered to each
|
||||
child, bypassing the allow-list check (structural fan-out targets are
|
||||
never user-listed peers). No-op for leaf agents (returns `Ok` when the
|
||||
|
|
@ -279,7 +279,7 @@ an agent. Self-introspection when `name = None` (replaces the older
|
|||
`Whoami` request); target query when `name = Some`.
|
||||
|
||||
Response is `AgentMeta { name, running, hyperhive_rev,
|
||||
status_text, status_set_at, hive_name, swarm_name }`:
|
||||
status_text, status_set_at, hive_name, swarm_name, matrix_accounts }`:
|
||||
|
||||
- `hyperhive_rev`: `None` only when the configured flake URL has
|
||||
no canonical path. Otherwise carries the rev the target is
|
||||
|
|
@ -299,6 +299,9 @@ status_text, status_set_at, hive_name, swarm_name }`:
|
|||
`HYPERHIVE_HIVE_NAME` / `HYPERHIVE_SWARM_NAME` env (sourced from
|
||||
`services.hyperhive.hiveName` / `services.hyperhive.swarm.name`).
|
||||
Both `None` when the options aren't configured.
|
||||
- `matrix_accounts`: one `MatrixIdentity` per configured + live matrix
|
||||
account the agent can act as. Empty for agents with no matrix
|
||||
provisioning.
|
||||
|
||||
### Timestamps on the wire
|
||||
|
||||
|
|
@ -323,14 +326,16 @@ binary flavor.
|
|||
|
||||
| Group | Tools |
|
||||
|---|---|
|
||||
| `messaging` | `send`, `recv`, `ask`, `answer` |
|
||||
| `messaging` | `send`, `recv`, `ack_until`, `ask`, `answer` |
|
||||
| `meta` | `get_agent_meta` (`set_status` is always-on, see below) |
|
||||
| `inbox` | `get_loose_ends`, `cancel_loose_end`, `remind` |
|
||||
| `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)* |
|
||||
| `lifecycle` | `kill`, `start`, `restart`, `update`, `list_containers` *(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)* |
|
||||
| `forge` | `create_repo` — create git repos through hive-c0re (operator-gated merge) |
|
||||
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
|
||||
|
||||
**Always-on tools** — `set_status`, `compact`, and `mark_todos_done` are
|
||||
exposed to every agent regardless of which groups it holds
|
||||
|
|
@ -363,10 +368,10 @@ from `tool-groups.json`). Unrecognised tokens are logged and skipped. Falls back
|
|||
to `ToolGroup::AGENT_DEFAULT` (`messaging`, `meta`, `inbox`, `execution`) when
|
||||
the var is absent or empty.
|
||||
|
||||
**Updating the surface** — when a new `#[tool]` fn is added to `HiveServer`
|
||||
in `hive-ag3nt/src/mcp.rs`, add its name to the matching `ToolGroup::tools()`
|
||||
slice in `hive-sh4re/src/lib.rs`. That's the single source of truth;
|
||||
`mcp_config::allowed_mcp_tools` (in `hive-ag3nt/src/mcp_config.rs`) reads it at
|
||||
**Updating the surface** — when a new `#[tool]` fn is added to `AgentServer`
|
||||
in `hive-agent-mcp/src/mcp/mod.rs`, add its name to the matching `ToolGroup::tools()`
|
||||
slice in `hive-sh4re/src/permissions.rs`. That's the single source of truth;
|
||||
`mcp_config::allowed_mcp_tools` (in `hive-agent/src/mcp_config.rs`) reads it at
|
||||
session start.
|
||||
|
||||
## Capabilities
|
||||
|
|
@ -406,15 +411,18 @@ groups: an agent that could grant its own capabilities via a config commit would
|
|||
bypass the operator approval gate.
|
||||
|
||||
**Adding a new capability** — add a variant to `Capability` in
|
||||
`hive-sh4re/src/lib.rs` + an arm to `as_str`. Add it to `Capability::ALL` (the
|
||||
source of truth for the permissions UI columns). Implement the access check in
|
||||
the relevant handler (`agent_server.rs`, `mcp.rs`, or a handler under
|
||||
`hive-c0re/src/dashboard/`).
|
||||
`hive-sh4re/src/permissions.rs` + an arm to `as_str`. Add it to `Capability::ALL`
|
||||
(the source of truth for the permissions UI columns). Implement the access
|
||||
check in the relevant handler (`hive-c0re/src/socket_server/mod.rs`,
|
||||
`hive-c0re/src/socket_server/lifecycle_handlers.rs`, `coordinator.rs`, or a
|
||||
handler under `hive-c0re/src/dashboard/`).
|
||||
|
||||
## Async forms
|
||||
|
||||
Dashboard + per-agent mutating forms carry `data-async`; a delegated
|
||||
`submit` listener in `assets/tabs.js` (+ `assets/app.js` for the per-agent UI) intercepts, shows a spinner,
|
||||
Dashboard + per-agent mutating forms carry `data-async`; the shared
|
||||
`bindAsyncForms` `submit` listener (`frontend/packages/shared/src/forms.js`,
|
||||
imported as `@hive/shared/forms.js` and wired up from `tabs.js` on the
|
||||
dashboard and `app.js` on the per-agent UI) intercepts, shows a spinner,
|
||||
POSTs `application/x-www-form-urlencoded` (axum's `Form` extractor
|
||||
rejects multipart), calls `refreshState()` on success. New mutating
|
||||
forms should add `data-async` and optionally `data-confirm` (for a
|
||||
|
|
@ -429,11 +437,16 @@ via `snapshotOpenDetails` / `restoreOpenDetails`.
|
|||
|
||||
## `rebuild` is the reconcile verb
|
||||
|
||||
`lifecycle::rebuild` idempotently rewrites
|
||||
`/etc/nixos-containers/<C>.conf` (`PRIVATE_NETWORK=0`, clears
|
||||
`HOST_ADDRESS` / `LOCAL_ADDRESS`, sets `EXTRA_NSPAWN_FLAGS`),
|
||||
regenerates `applied/<name>/flake.nix`, writes the systemd limits
|
||||
drop-in, then `nixos-container update` + stop + start.
|
||||
`job_queue::templates::rebuild` builds the DAG that reconciles a
|
||||
container to its wanted state: `write_dropins` (the nspawn-conf
|
||||
rewrite — `PRIVATE_NETWORK=0`, clears `HOST_ADDRESS` / `LOCAL_ADDRESS`,
|
||||
sets `EXTRA_NSPAWN_FLAGS` — plus the systemd resource-limits drop-in)
|
||||
is folded into the `Swap` node, then `nixos-container update` + stop +
|
||||
start runs across the `StopForUpdate → Swap → RebuildBookkeeping`
|
||||
brace and the tail `Reconcile` node. `flake.nix` itself is no longer
|
||||
regenerated host-side on rebuild — it's tracked in the agent's
|
||||
proposed/applied repos and rides along on every fetch (see
|
||||
`docs/approvals.md::Two repos per agent`).
|
||||
|
||||
Anything that changes per-container state on the host should be
|
||||
re-applied here so a manual `↻ R3BU1LD` from the dashboard is
|
||||
|
|
|
|||
Loading…
Reference in a new issue