Compare commits

...
4 changed files with 59 additions and 19 deletions

View file

@ -81,7 +81,7 @@ hive-c0re/ host daemon + sibling operator CLI (lib + 2 bins)
fans out one Message per active target,
re-arms recurring rows, deletes fired one-shots
src/events_vacuum.rs host-side hourly sweep of every agent's
/state/hyperhive-events.sqlite
/harness/hyperhive-events.sqlite
src/crash_watch.rs poll every 10s; fire HelperEvent::ContainerCrash
when a previously-running container disappears
without an operator-initiated transient (or a
@ -130,6 +130,17 @@ hive-c0re/ host daemon + sibling operator CLI (lib + 2 bins)
read). Reconciled by `meta::sync_agents`;
operator/manager edits land via the
eventual write API.
src/tool_groups.rs per-agent tool-group config — reads/writes
`/var/lib/hyperhive/meta/tool-groups.json`;
`set_groups` + `groups_for` + `remove_agent`.
Wired into `render_flake` for `HIVE_TOOL_GROUPS`
injection; operator write via dashboard action.
src/limits.rs wire-protocol size limits (inline body cap,
reminder spill threshold) shared across agent
+ manager sockets. Single source of truth.
src/flake_check.rs pre-apply `flake.lock` validation — rejects
proposals missing `inputs.<X>.follows` wiring
(duplicate `original` node check).
src/forge.rs optional Forgejo wiring: per-agent users +
tokens, the `agent-configs` org (`push_config`),
and meta read access; mirrors each applied repo
@ -177,14 +188,14 @@ hive-ag3nt/ in-container harness crate; produces ONE `hive`
/api/compact, /api/model, /events/history,
/screen, /screen/ws)
src/turn_stats.rs per-turn analytics sink (one sqlite row per
turn at /state/hyperhive-turn-stats.sqlite);
turn at /harness/hyperhive-turn-stats.sqlite);
schema + best-effort writer
src/stats.rs read-side aggregations over turn-stats.sqlite
backing the /stats page (bucketed Snapshot:
turns / duration / tokens / model mix)
src/events.rs LiveEvent + broadcast Bus + sqlite-backed history
(/state/hyperhive-events.sqlite) + TurnState +
model selection (persisted at /state/hyperhive-model)
(/harness/hyperhive-events.sqlite) + TurnState +
model selection (persisted at /harness/hyperhive-model)
src/turn.rs claude --print + stream-json pump; --compact retry;
proactive compaction + auto session-reset
src/mcp.rs embedded MCP server (rmcp): AgentServer + ManagerServer
@ -383,3 +394,5 @@ The docs below own the details — this section just points at them.
window:** → [`docs/turn-loop.md`](docs/turn-loop.md).
- **Two-step spawn, approval flow, flake.lock validation:**
[`docs/approvals.md`](docs/approvals.md).

View file

@ -285,6 +285,7 @@ binary flavor.
| `messaging` | `send`, `recv`, `ask`, `answer` |
| `meta` | `set_status`, `get_agent_meta` |
| `inbox` | `get_loose_ends`, `cancel_loose_end`, `remind`, `request_next_turn` |
| `execution` | `bash_run`, `bash_status` |
| `lifecycle` | `kill`, `start`, `restart`, `update` *(privileged)* |
| `approvals` | `request_init_config`, `request_apply_commit`, `request_update_meta_inputs` *(privileged)* |
| `scheduling` | `request_schedule_prompt`, `fire_schedule_now`, `cancel_schedule`, `edit_schedule`, `list_schedules` *(privileged)* |
@ -307,7 +308,7 @@ the new `HIVE_TOOL_GROUPS` env var. Agents with no entry get no var.
**Runtime resolution** — at session start the harness reads `HIVE_TOOL_GROUPS`
(a comma-separated list of snake_case group names injected by the meta renderer
from `tool-groups.json`). Unrecognised tokens are logged and skipped. Falls back
to `ToolGroup::AGENT_DEFAULT` (`messaging`, `meta`, `inbox`) or
to `ToolGroup::AGENT_DEFAULT` (`messaging`, `meta`, `inbox`, `execution`) or
`ToolGroup::MANAGER_DEFAULT` (all groups) when the var is absent or empty.
**Updating the surface** — when a new `#[tool]` fn is added to `AgentServer`

View file

@ -64,17 +64,17 @@ Retention:
`cancelled_at_unix`, then `reap_cancelled` drops the row on
the next worker pass.
### `/state/hyperhive-events.sqlite` (per agent)
### `/harness/hyperhive-events.sqlite` (per agent)
Lives inside each container's bind-mounted `/state/` dir (host
path: `/var/lib/hyperhive/agents/<name>/state/hyperhive-events.sqlite`).
Lives inside each container's bind-mounted `/harness/` dir (host
path: `/var/lib/hyperhive/agents/<name>/harness/hyperhive-events.sqlite`).
One table:
- `events(id, ts, kind, payload_json)` — every `LiveEvent` the
harness emits during turn loop execution.
The harness writes; the host vacuums. `hive-c0re::events_vacuum`
runs hourly and sweeps every existing agent state dir, deleting
runs hourly and sweeps every existing agent harness dir, deleting
rows older than 7 days. Age-only — no row cap — so a chatty turn
doesn't lose history sooner than a quiet one; disk pressure on a
sustained burst is the cheaper problem to have. Centralising
@ -82,12 +82,12 @@ retention on the host means a misbehaving harness can't disable
its own vacuum and agents don't need any cleanup wiring of their
own.
Path overridable via `HYPERHIVE_EVENTS_DB` (for dev / no-`/state`
Path overridable via `HYPERHIVE_EVENTS_DB` (for dev / no-`/harness`
setups). On open failure the `Bus` falls back to no-store mode
rather than crashing the harness — events still broadcast over SSE,
just nothing persisted.
### `/state/hyperhive-turn-stats.sqlite` (per agent)
### `/harness/hyperhive-turn-stats.sqlite` (per agent)
Per-turn analytics sink. One row per claude turn captures
identity (`model`, `wake_from`, `result_kind`), timing
@ -149,7 +149,7 @@ Writes are best-effort: `append_stdout` / `append_stderr` / `finish`
log a warning on sqlite error and let the build continue. A failed
log row never blocks a rebuild.
### `/state/hyperhive-model` (per agent)
### `/harness/hyperhive-model` (per agent)
Single-line text file holding the claude model name currently
selected for this agent (default `haiku` when absent). Written by
@ -169,11 +169,21 @@ Under `/var/lib/hyperhive/agents/<name>/`:
`/agents` tree bind.
- `claude/` — claude OAuth credentials, bind-mounted RW to
`/home/<name>/.claude` inside the container.
- `state/` — durable notes, the events.sqlite db, and the
turn-stats sqlite db. Bind-mounted to `/agents/<name>/state`
inside the container (uniform for sub-agents + manager).
The `$HYPERHIVE_STATE_DIR` env var exposes the same path to
in-container scripts.
- `state/` — durable notes and `hyperhive-harness.json`. Bind-mounted
to `/agents/<name>/state` inside the container (uniform for
sub-agents + manager). The `$HYPERHIVE_STATE_DIR` env var exposes
the same path to in-container scripts.
- `harness/` — harness-internal ephemeral state; not intended for
agent consumption. Bind-mounted to `/agents/<name>/harness`
inside the container (`$HYPERHIVE_HARNESS_DIR`). Contents:
- `bash-tasks/` — task JSON + stdout/stderr files for
background `bash_run` jobs. JSON files are
`<id>.json` (status + tails), `<id>.out` / `<id>.err`
(full captured output). Task files persist until container
purge.
- `hyperhive-events.sqlite` — turn-loop event log.
- `hyperhive-turn-stats.sqlite` — per-turn timing stats.
- `hyperhive-model` — single-line model name override file.
Under `/var/lib/hyperhive/applied/<name>/` — the hive-c0re-only
applied repo. Tracks `flake.nix` (module-only boilerplate; never
@ -207,7 +217,7 @@ step would re-fire).
- `PURG3` (opt-in via the dashboard button or
`hive-c0re destroy --purge <name>`) — DESTR0Y plus wipes
`/var/lib/hyperhive/{agents,applied}/<name>/`. Config history,
claude creds, /state/ notes, and the events db are all gone.
claude creds, /state/ notes, and the harness dir are all gone.
No undo.
The manager is non-destroyable from both paths (declarative
@ -314,3 +324,4 @@ trigger from the `.path` watcher becomes a no-op. Setting it to
`false` lets re-fires actually re-execute. The trade-off is the
service unit shows `inactive (dead)` between fires — visible in
`journalctl` but harmless; the `.path` unit drives the lifecycle.

View file

@ -148,7 +148,7 @@ default is set by `hyperhive.model` in the agent's `agent.nix`
(NixOS option; propagates via `HIVE_DEFAULT_MODEL` env var; falls
back to `"haiku"` if unset). The operator can flip it at runtime
with `/model <name>` in the web terminal — the next turn picks it
up. The choice is persisted to `/state/hyperhive-model` so it
up. The choice is persisted to `/harness/hyperhive-model` so it
survives restart; override path: `HYPERHIVE_MODEL_FILE` env var
for tests.
@ -369,6 +369,20 @@ it as a stdio child via `--mcp-config`. The hyperhive socket name is
continue without waiting for an external message. The next turn starts
with `from: "self"` and `body: "continue"`. No-op if new inbox
messages arrive before this turn ends. No args.
- `bash_run(cmd, timeout_secs?)` — submit a shell command for
background execution (`sh -c <cmd>`). Returns a task ID immediately;
the command runs asynchronously in a harness-managed tokio task. Stdout
and stderr stream to `harness/bash-tasks/<id>.{out,err}`. When the
task completes (or times out, or the process errors), the harness wakes
the agent with a summary body — handle on a future turn. Default
timeout 180s; pass `timeout_secs` to override. Requires the
`execution` tool group.
- `bash_status(id)` — poll the status of a task submitted with
`bash_run`. Returns status (`pending`/`running`/`done`/`timed_out`/
`interrupted`), exit code, run duration, and the last 4 KiB of stdout
and stderr (full output in the `.out`/`.err` files). Tasks marked
`interrupted` had their process killed by a harness restart; a best-
effort wake was still sent so the agent is not silently blocked.
### Waking the agent from inside the container
@ -573,3 +587,4 @@ The harness reads `/etc/hyperhive/bash-allow.json` and replaces
Commands outside the pattern list require confirmation — which in
`--print` mode means they will not run. An empty list (default) keeps
the current wholesale `Bash` entry.