docs: sync to current state of the world
claude.md scratchpad rewritten — folds in pronouns option, extra MCP servers + flakeInputs forwarding, ask_operator on sub-agents, dashboard compose box with @-mentions, new- session button, cwd=/state for claude turns, meta-mutex + stale-lock cleanup. readme picks up the operator pronouns option example, the dashboard compose box description, the new slash commands list, the deployed-sha chip, the per-agent UI gains new-session. docs/web-ui.md gains: - a fuller MESS4GE FL0W description that calls out the compose box, sticky @-mention recipient, /op-send, and the manager-name swap - /op-send in the dashboard endpoint table - new-session button + /new-session slash command in the per-agent surface - compact endpoint now notes 'same session shape as a normal turn' docs/turn-loop.md: - new-session one-shot, cwd=/state with CLAUDE.md auto-load walking upward, operator-pronouns substitution - sub-agent tool list grows ask_operator - new 'Extra MCP servers (per-agent)' section documenting hyperhive.extraMcpServers + the flakeInputs forwarding pattern
This commit is contained in:
parent
2d277038a7
commit
1278f880da
4 changed files with 137 additions and 37 deletions
72
CLAUDE.md
72
CLAUDE.md
|
|
@ -123,31 +123,53 @@ In-flight or recent context that hasn't earned a section yet.
|
||||||
Prune freely.
|
Prune freely.
|
||||||
|
|
||||||
- **Just landed:** meta-flake overhaul. Each agent's applied
|
- **Just landed:** meta-flake overhaul. Each agent's applied
|
||||||
repo is a tiny module-only flake (`nixosModules.default =
|
repo is a module-only flake (forwards every `inputs.*`
|
||||||
import ./agent.nix`); `agent.nix` is a plain NixOS module
|
through to `agent.nix` as the `flakeInputs` module arg —
|
||||||
function — no extendModules, no hyperhive input visible to
|
manager edits `inputs` to pull in external flakes like an
|
||||||
the manager. A single hive-c0re-owned repo at
|
MCP server's own flake; the new sha lands in the agent's
|
||||||
`/var/lib/hyperhive/meta/` declares one input per agent
|
own `flake.lock` and rolls up to meta's). A single
|
||||||
(pointing at that agent's applied repo via `git+file://`)
|
hive-c0re-owned repo at `/var/lib/hyperhive/meta/`
|
||||||
and one `nixosConfigurations.<n>` output per agent,
|
declares one input per agent and one
|
||||||
wrapping `inputs.agent-<n>.nixosModules.default` with the
|
`nixosConfigurations.<n>` output, wrapping the agent's
|
||||||
identity + `HIVE_PORT` / `HIVE_LABEL` /
|
`nixosModules.default` with identity + `HIVE_PORT` /
|
||||||
`HIVE_DASHBOARD_PORT` injection. Containers run against
|
`HIVE_LABEL` / `HIVE_DASHBOARD_PORT` /
|
||||||
`meta#<n>`. Every approve runs `nix flake lock
|
`HIVE_OPERATOR_PRONOUNS`. Containers run against
|
||||||
--update-input agent-<n>` (two-phase: prepare on the
|
`meta#<n>`. Every approve uses two-phase staging
|
||||||
build path, finalize/abort on the result) — meta's git
|
(prepare → build → finalize/abort) so meta's git log only
|
||||||
log is the system-wide deploy audit trail; failures and
|
records successful deploys; failures + denials live as
|
||||||
denials live as annotated tags in applied. The manager
|
annotated tags in applied. All meta operations
|
||||||
has `/applied` and `/meta` RO-bound and the `applied`
|
serialize behind a tokio mutex; stale `.git/index.lock`
|
||||||
remote pre-wired in every proposed repo so `git fetch
|
is cleared on hive-c0re startup. Manager has `/applied`
|
||||||
applied`, `git show applied/refs/tags/deployed/<id>`,
|
+ `/meta` RO-bound + the `applied` remote pre-wired in
|
||||||
`git -C /meta log --oneline`, `cat /meta/flake.lock`
|
every proposed repo. Migration runs idempotently on
|
||||||
all just work. Migration runs idempotently on
|
startup (`HIVE_SKIP_META_MIGRATION=1` skips). Operator
|
||||||
hive-c0re startup (`HIVE_SKIP_META_MIGRATION=1` skips it):
|
pronouns are a NixOS module option
|
||||||
rewrites pre-meta applied flakes to module-only, wires
|
(`services.hive-c0re.operatorPronouns`, default
|
||||||
the proposed remote, seeds meta, and repoints every
|
`"she/her"`); the harness substitutes them into the
|
||||||
container at `meta#<n>` (guarded by a marker so the
|
system prompt at boot.
|
||||||
expensive phase only runs once).
|
- **Just landed:** per-agent extra MCP servers via the
|
||||||
|
`hyperhive.extraMcpServers.<key>` NixOS option in
|
||||||
|
`agent.nix`. Declares `{ command, args, env,
|
||||||
|
allowedTools }`; the module writes the whole map to
|
||||||
|
`/etc/hyperhive/extra-mcp.json`; the harness reads that
|
||||||
|
file and merges each entry into both `--mcp-config`
|
||||||
|
and `--allowedTools` (mapped to `mcp__<key>__<pattern>`).
|
||||||
|
Unblocks matrix / bitburner / any agent with rich
|
||||||
|
domain tooling — the agent flake's `inputs` block pulls
|
||||||
|
the external flake, `agent.nix` references it via
|
||||||
|
`flakeInputs.<name>.packages.${pkgs.system}.default`.
|
||||||
|
- **Just landed:** `mcp__hyperhive__ask_operator` is now on
|
||||||
|
the sub-agent surface too (not just the manager). Answer
|
||||||
|
routes back to whichever agent asked via
|
||||||
|
`coord.notify_agent`; the dashboard already shows the
|
||||||
|
asker on each question row.
|
||||||
|
- **Just landed:** dashboard now has a terminal-style
|
||||||
|
compose textbox under the message-flow stream — `@name`
|
||||||
|
picks the recipient (sticky in localStorage, auto-
|
||||||
|
completed from `containers[]`), POSTs `/op-send`. New
|
||||||
|
per-agent `↻ new session` button drops `--continue` for
|
||||||
|
one turn. Claude spawns with `cwd = /state` so relative
|
||||||
|
paths in tool calls land in the durable dir.
|
||||||
- **Just landed (prior overhaul still underneath):** tag-
|
- **Just landed (prior overhaul still underneath):** tag-
|
||||||
driven config-apply. Two-repo split (proposed = manager
|
driven config-apply. Two-repo split (proposed = manager
|
||||||
RW, applied = core-only); `request_apply_commit` fetches
|
RW, applied = core-only); `request_apply_commit` fetches
|
||||||
|
|
|
||||||
29
README.md
29
README.md
|
|
@ -36,7 +36,9 @@ host (NixOS, runs hive-c0re.service)
|
||||||
│ ask_operator) + web UI on :8000
|
│ ask_operator) + web UI on :8000
|
||||||
│
|
│
|
||||||
└── h-<name> hive-ag3nt serve : claude turn loop +
|
└── h-<name> hive-ag3nt serve : claude turn loop +
|
||||||
MCP (send / recv) + web UI on a hashed :8100-8999
|
MCP (send / recv / ask_operator + agent-declared extras
|
||||||
|
via hyperhive.extraMcpServers) + web UI on a
|
||||||
|
hashed :8100-8999
|
||||||
```
|
```
|
||||||
|
|
||||||
Each turn: harness pops one inbox message (Recv long-polls server-side and
|
Each turn: harness pops one inbox message (Recv long-polls server-side and
|
||||||
|
|
@ -47,12 +49,20 @@ claude drives any further `recv`/`send` itself via the embedded MCP server.
|
||||||
|
|
||||||
Operator surface per agent: terminal-themed live tail with a textarea
|
Operator surface per agent: terminal-themed live tail with a textarea
|
||||||
prompt; slash commands `/help` `/clear` `/cancel` `/compact`
|
prompt; slash commands `/help` `/clear` `/cancel` `/compact`
|
||||||
`/model <name>`; granular state badge (idle / thinking /
|
`/model <name>` `/new-session`; granular state badge (idle / thinking
|
||||||
compacting / offline) with age timer + last-turn duration chip +
|
/ compacting / offline) with age timer + last-turn duration chip +
|
||||||
model chip; cancel-turn button while thinking; sticky-bottom
|
model chip; cancel-turn + new-session buttons in the state row;
|
||||||
auto-scroll with "↓ N new" pill; event history backfilled on page
|
sticky-bottom auto-scroll with "↓ N new" pill; event history
|
||||||
load; collapsible inbox + collapsible journald viewer + collapsible
|
backfilled on page load; collapsible inbox + collapsible journald
|
||||||
`agent.nix` viewer per agent on the dashboard.
|
viewer + collapsible `agent.nix` viewer per agent on the dashboard;
|
||||||
|
deployed-sha chip per container (read from meta's `flake.lock`).
|
||||||
|
|
||||||
|
Operator surface on the dashboard itself: a terminal compose box
|
||||||
|
under the message-flow stream — `@name` picks the recipient with
|
||||||
|
auto-complete from the live container list, sticky across sends,
|
||||||
|
POSTs `/op-send` which drops the message into the broker as
|
||||||
|
`{from:"operator", to:<name>, body}`. Same shape any sub-agent
|
||||||
|
sees as a regular inbox message.
|
||||||
|
|
||||||
Config changes flow the other way: manager edits files under
|
Config changes flow the other way: manager edits files under
|
||||||
`/agents/<name>/config/` — `agent.nix` is a plain NixOS module function
|
`/agents/<name>/config/` — `agent.nix` is a plain NixOS module function
|
||||||
|
|
@ -102,6 +112,11 @@ Minimal `flake.nix` for a host that runs hive-c0re:
|
||||||
hyperhive.nixosModules.hive-c0re
|
hyperhive.nixosModules.hive-c0re
|
||||||
({ ... }: {
|
({ ... }: {
|
||||||
services.hive-c0re.enable = true;
|
services.hive-c0re.enable = true;
|
||||||
|
# Free-text operator pronouns — defaults to "she/her", threaded
|
||||||
|
# through to every agent's system prompt as HIVE_OPERATOR_PRONOUNS
|
||||||
|
# so claude refers to you naturally in third person.
|
||||||
|
# services.hive-c0re.operatorPronouns = "they/them";
|
||||||
|
|
||||||
# ... rest of your host config (hardware, networking, users, …)
|
# ... rest of your host config (hardware, networking, users, …)
|
||||||
system.stateVersion = "25.11";
|
system.stateVersion = "25.11";
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,18 @@ sessions in `~/.claude/projects/`, which is bind-mounted
|
||||||
persistently). Auto-compact and auto-memory are disabled via
|
persistently). Auto-compact and auto-memory are disabled via
|
||||||
`--settings` because hyperhive owns compaction (`/compact` on
|
`--settings` because hyperhive owns compaction (`/compact` on
|
||||||
overflow, retry once; operator can also force one via `/api/compact`).
|
overflow, retry once; operator can also force one via `/api/compact`).
|
||||||
|
A one-shot `--continue` suppression is available via
|
||||||
|
`POST /api/new-session` (or `/new-session` slash command in the
|
||||||
|
per-agent terminal) — `Bus::take_skip_continue()` flips an
|
||||||
|
`AtomicBool` once per turn, the next claude invocation drops
|
||||||
|
`--continue`, every subsequent turn resumes normal behaviour.
|
||||||
|
|
||||||
|
The child runs with `cwd = /state` (when the bind exists; falls
|
||||||
|
back to the parent's cwd in dev), so any relative path in a tool
|
||||||
|
call (`Read foo.md`, `Bash ls`, `Write notes.md`) lands in the
|
||||||
|
agent's durable bind-mounted dir. CLAUDE.md auto-load walks
|
||||||
|
upward from `/state` — drop a per-agent CLAUDE.md there if you
|
||||||
|
want long-term hints that survive destroy/recreate.
|
||||||
|
|
||||||
The wake prompt is intentionally minimal: just the popped message's
|
The wake prompt is intentionally minimal: just the popped message's
|
||||||
`from`/`body`, plus an inline `({unread} more pending — drain via
|
`from`/`body`, plus an inline `({unread} more pending — drain via
|
||||||
|
|
@ -68,8 +80,11 @@ socket at `/run/hive/` once at startup:
|
||||||
- `claude-settings.json` — the `--settings` blob (auto-compact and
|
- `claude-settings.json` — the `--settings` blob (auto-compact and
|
||||||
auto-memory off, effortLevel medium).
|
auto-memory off, effortLevel medium).
|
||||||
- `claude-system-prompt.md` — rendered from
|
- `claude-system-prompt.md` — rendered from
|
||||||
`hive-ag3nt/prompts/{agent,manager}.md` with `{label}`
|
`hive-ag3nt/prompts/{agent,manager}.md` with `{label}` and
|
||||||
substituted. Passed via `--system-prompt-file`.
|
`{operator_pronouns}` substituted. Pronouns come from
|
||||||
|
`HIVE_OPERATOR_PRONOUNS` env (set by the meta flake from
|
||||||
|
`services.hive-c0re.operatorPronouns`, default `she/her`).
|
||||||
|
Passed via `--system-prompt-file`.
|
||||||
|
|
||||||
The shared per-turn plumbing lives in `hive_ag3nt::turn::{write_mcp_config,
|
The shared per-turn plumbing lives in `hive_ag3nt::turn::{write_mcp_config,
|
||||||
write_settings, write_system_prompt, run_turn, drive_turn,
|
write_settings, write_system_prompt, run_turn, drive_turn,
|
||||||
|
|
@ -92,6 +107,25 @@ it as a stdio child via `--mcp-config`. The hyperhive socket name is
|
||||||
omitted). Agents use a long wait to park their turn waiting for
|
omitted). Agents use a long wait to park their turn waiting for
|
||||||
work instead of busy-looping with short polls — they wake
|
work instead of busy-looping with short polls — they wake
|
||||||
instantly when a message arrives.
|
instantly when a message arrives.
|
||||||
|
- `ask_operator(question, options?, multi?, ttl_seconds?)` —
|
||||||
|
surface a question on the dashboard. Same shape as the manager's;
|
||||||
|
answer routes back to the asker's own inbox as
|
||||||
|
`HelperEvent::OperatorAnswered` via `coord.notify_agent`.
|
||||||
|
|
||||||
|
### Extra MCP servers (per-agent)
|
||||||
|
|
||||||
|
Each agent's NixOS config can declare additional MCP servers via
|
||||||
|
`hyperhive.extraMcpServers.<key> = { command, args, env,
|
||||||
|
allowedTools }`. The module writes the map to
|
||||||
|
`/etc/hyperhive/extra-mcp.json`; the harness reads it at boot and
|
||||||
|
merges every entry into `--mcp-config` (under `mcpServers.<key>`)
|
||||||
|
and `--allowedTools` (as `mcp__<key>__<pattern>`). The agent's
|
||||||
|
flake.nix forwards every flake input to `agent.nix` as the
|
||||||
|
`flakeInputs` module arg, so external MCP-server flakes are pulled
|
||||||
|
in by adding them to `inputs.*` and referenced as
|
||||||
|
`flakeInputs.<name>.packages.${pkgs.system}.default` — the
|
||||||
|
resolved sha lands in the agent's own `flake.lock` and rolls up to
|
||||||
|
meta's.
|
||||||
|
|
||||||
### Manager tools (in addition to send/recv)
|
### Manager tools (in addition to send/recv)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,21 @@ the previous process's socket release resolves itself.
|
||||||
6. **P3NDING APPR0VALS** — the queue. The R3QU3ST SP4WN form
|
6. **P3NDING APPR0VALS** — the queue. The R3QU3ST SP4WN form
|
||||||
lives at the top of this section since submitting it
|
lives at the top of this section since submitting it
|
||||||
immediately queues an approval that lands directly below.
|
immediately queues an approval that lands directly below.
|
||||||
7. **MESS4GE FL0W** — live broker SSE tail.
|
7. **MESS4GE FL0W** — live broker SSE tail (newest-first).
|
||||||
|
Each row is one broker event — `sent` or `delivered` — with
|
||||||
|
`from → to: body`; per-agent thinking / tool calls / claude
|
||||||
|
chatter stay out of this view, only what passes through
|
||||||
|
hive-c0re's broker. Below the stream sits a terminal-style
|
||||||
|
compose box: `@name` picks the recipient (sticky across
|
||||||
|
sends via localStorage; auto-complete from the live
|
||||||
|
container list, Tab/Enter to confirm), starting a message
|
||||||
|
with `@<name> body` retargets in one stroke, plain text
|
||||||
|
sends to the sticky recipient. `POST /op-send` drops
|
||||||
|
`{from:"operator", to, body}` into the broker — same shape
|
||||||
|
any sub-agent sees as a regular inbox message. Manager is
|
||||||
|
addressed as `@manager` (the broker recipient string), not
|
||||||
|
`@hm1nd` (the container name); the auto-complete swaps
|
||||||
|
automatically.
|
||||||
|
|
||||||
### Container row
|
### Container row
|
||||||
|
|
||||||
|
|
@ -140,6 +154,9 @@ not ours.
|
||||||
the sentinel `[cancelled]`. Same code path as a real answer.
|
the sentinel `[cancelled]`. Same code path as a real answer.
|
||||||
- `POST /request-spawn` — queue a Spawn approval.
|
- `POST /request-spawn` — queue a Spawn approval.
|
||||||
- `POST /update-all` — rebuild every stale container.
|
- `POST /update-all` — rebuild every stale container.
|
||||||
|
- `POST /op-send` (`to=<name>`, `body=<text>`) — drop an
|
||||||
|
operator-authored message into `<name>`'s inbox. Used by the
|
||||||
|
compose textbox under MESS4GE FL0W.
|
||||||
- `GET /api/journal/{name}?unit=&lines=` — journalctl viewer for
|
- `GET /api/journal/{name}?unit=&lines=` — journalctl viewer for
|
||||||
a managed container.
|
a managed container.
|
||||||
- `GET /api/agent-config/{name}` — read-only view of the applied
|
- `GET /api/agent-config/{name}` — read-only view of the applied
|
||||||
|
|
@ -158,7 +175,7 @@ Layout, top to bottom:
|
||||||
- Title with `↑ DASHB04RD` back-link (new tab) + `↻ R3BU1LD`.
|
- Title with `↑ DASHB04RD` back-link (new tab) + `↻ R3BU1LD`.
|
||||||
- Status section (online / needs login / login-in-progress).
|
- Status section (online / needs login / login-in-progress).
|
||||||
- **State row**: state badge + model chip + last-turn timing +
|
- **State row**: state badge + model chip + last-turn timing +
|
||||||
cancel-turn button.
|
cancel-turn button + new-session button.
|
||||||
- State badge: `💤 idle` / `🧠 thinking` / `📦 compacting` /
|
- State badge: `💤 idle` / `🧠 thinking` / `📦 compacting` /
|
||||||
`○ offline` / `… booting`, with an age suffix (`12s`,
|
`○ offline` / `… booting`, with an age suffix (`12s`,
|
||||||
`2m 14s`). Driven from `/api/state.turn_state` +
|
`2m 14s`). Driven from `/api/state.turn_state` +
|
||||||
|
|
@ -170,6 +187,11 @@ Layout, top to bottom:
|
||||||
turn ends, computed from the state-since deltas.
|
turn ends, computed from the state-since deltas.
|
||||||
- `■ cancel turn` button: visible only while state=thinking,
|
- `■ cancel turn` button: visible only while state=thinking,
|
||||||
POSTs `/api/cancel`.
|
POSTs `/api/cancel`.
|
||||||
|
- `↻ new session` button: always visible, amber. Confirms
|
||||||
|
via `window.confirm()` then POSTs `/api/new-session` to
|
||||||
|
arm a one-shot Bus flag — the next turn drops
|
||||||
|
`--continue`, starting a fresh claude session. Subsequent
|
||||||
|
turns resume normal `--continue`.
|
||||||
- Inbox `<details>` block (collapsed): `inbox · N` — last 30
|
- Inbox `<details>` block (collapsed): `inbox · N` — last 30
|
||||||
messages addressed to this agent, fetched via
|
messages addressed to this agent, fetched via
|
||||||
`AgentRequest::Recent { limit: 30 }`. (Separate from
|
`AgentRequest::Recent { limit: 30 }`. (Separate from
|
||||||
|
|
@ -238,6 +260,9 @@ Slash commands today:
|
||||||
Takes effect on the next turn; persisted to
|
Takes effect on the next turn; persisted to
|
||||||
`/state/hyperhive-model` so the override survives harness
|
`/state/hyperhive-model` so the override survives harness
|
||||||
restart / rebuild.
|
restart / rebuild.
|
||||||
|
- `/new-session` — `POST /api/new-session` (confirms first).
|
||||||
|
Arms a one-shot on the Bus; next turn runs without
|
||||||
|
`--continue`, dropping the resume session entirely.
|
||||||
|
|
||||||
Unknown `/foo` shows an error row instead of being silently sent.
|
Unknown `/foo` shows an error row instead of being silently sent.
|
||||||
|
|
||||||
|
|
@ -246,7 +271,11 @@ Unknown `/foo` shows an error row instead of being silently sent.
|
||||||
- `POST /send` — operator-injected message into this agent's inbox.
|
- `POST /send` — operator-injected message into this agent's inbox.
|
||||||
- `POST /login/{start,code,cancel}` — claude OAuth login flow.
|
- `POST /login/{start,code,cancel}` — claude OAuth login flow.
|
||||||
- `POST /api/cancel` — SIGINT the in-flight claude turn.
|
- `POST /api/cancel` — SIGINT the in-flight claude turn.
|
||||||
- `POST /api/compact` — run `/compact` on the persistent session.
|
- `POST /api/compact` — run `/compact` on the persistent session
|
||||||
|
(same MCP config + system prompt + allowed tools as a normal
|
||||||
|
turn — only the stdin payload differs).
|
||||||
- `POST /api/model` (`model=<name>`) — switch the model for
|
- `POST /api/model` (`model=<name>`) — switch the model for
|
||||||
future turns.
|
future turns.
|
||||||
|
- `POST /api/new-session` — arm a one-shot for the next turn to
|
||||||
|
drop `--continue`.
|
||||||
- `GET /events/history` — replay buffer for the terminal.
|
- `GET /events/history` — replay buffer for the terminal.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue