docs: refresh CLAUDE.md for system-prompt-file, helper events, dashboard buttons, ui shape; TODO.md drop operator-inbox (done)
This commit is contained in:
parent
ace13cd785
commit
abfd2cce4b
2 changed files with 100 additions and 24 deletions
121
CLAUDE.md
121
CLAUDE.md
|
|
@ -35,7 +35,11 @@ hive-ag3nt/ in-container harness crate; produces TWO binaries
|
|||
src/login_session.rs drives `claude auth login` over stdio pipes
|
||||
src/bin/hive-ag3nt.rs sub-agent main
|
||||
src/bin/hive-m1nd.rs manager main
|
||||
assets/ CSS + JS for the per-agent UI
|
||||
assets/ index.html, agent.css, app.js (include_str!)
|
||||
prompts/ static role/tools/settings for claude (include_str!):
|
||||
agent.md — sub-agent system prompt
|
||||
manager.md — manager system prompt
|
||||
claude-settings.json — --settings JSON
|
||||
|
||||
hive-sh4re/ wire types (HostRequest/Response, AgentRequest/Response,
|
||||
ManagerRequest/Response, Message, Approval, HelperEvent)
|
||||
|
|
@ -71,11 +75,11 @@ nix/
|
|||
- **Actions are factored.** `approve` / `deny` / `destroy` live in
|
||||
`actions.rs`; the admin socket and the dashboard POST handlers both call
|
||||
into them so the two surfaces never drift.
|
||||
- **Async forms.** Dashboard mutating forms carry `data-async`; the
|
||||
`assets/async_forms.js` helper intercepts submit, shows a spinner, and
|
||||
fetches with `application/x-www-form-urlencoded` (axum `Form` extractor
|
||||
rejects multipart). New mutating forms should add `data-async` and
|
||||
optionally `data-confirm`.
|
||||
- **Async forms.** Dashboard + per-agent mutating forms carry `data-async`;
|
||||
a delegated `submit` listener in `assets/app.js` intercepts, shows a
|
||||
spinner, POSTs with `application/x-www-form-urlencoded` (axum `Form`
|
||||
extractor rejects multipart), calls `refreshState()` on success. New
|
||||
mutating forms should add `data-async` and optionally `data-confirm`.
|
||||
|
||||
## Gotchas / lessons learned
|
||||
|
||||
|
|
@ -167,17 +171,27 @@ Manager additionally:
|
|||
config change for any agent (including `hm1nd` for self-mods).
|
||||
|
||||
The shared per-turn plumbing lives in `hive_ag3nt::turn::{write_mcp_config,
|
||||
run_turn, drive_turn, emit_turn_end, wait_for_login}` so the two binaries
|
||||
can't drift.
|
||||
write_settings, write_system_prompt, run_turn, drive_turn, emit_turn_end,
|
||||
wait_for_login}` so the two binaries can't drift.
|
||||
|
||||
On harness boot, three files get dropped next to the mcp socket at
|
||||
`/run/hive/`:
|
||||
|
||||
- `claude-mcp-config.json` — re-invokes the running binary as `mcp` child.
|
||||
- `claude-settings.json` — `--settings` blob (auto-compact/auto-memory
|
||||
off, effortLevel medium).
|
||||
- `claude-system-prompt.md` — rendered from `prompts/{agent,manager}.md`
|
||||
with `{label}` substituted. Passed via `--system-prompt-file`.
|
||||
|
||||
Each turn:
|
||||
|
||||
```
|
||||
claude --print --verbose --output-format stream-json --model haiku \
|
||||
--continue --settings '{"autoCompactEnabled":false,"autoMemoryEnabled":false}' \
|
||||
--mcp-config <path> --strict-mcp-config \
|
||||
--continue --settings /run/hive/claude-settings.json \
|
||||
--system-prompt-file /run/hive/claude-system-prompt.md \
|
||||
--mcp-config /run/hive/claude-mcp-config.json --strict-mcp-config \
|
||||
--tools <builtins> --allowedTools <builtins+mcp>
|
||||
# prompt piped over stdin
|
||||
# wake prompt piped over stdin — minimal, just from/body + optional unread hint
|
||||
```
|
||||
|
||||
`--continue` keeps a persistent session per agent (claude stores sessions in
|
||||
|
|
@ -187,14 +201,15 @@ overflow, retry once).
|
|||
|
||||
**Loop control.** The harness pops one inbox message per cycle (the wake
|
||||
signal — Recv long-polls server-side for up to 30s waking instantly on a new
|
||||
broker `Sent` event for this agent) and hands claude a prompt naming the
|
||||
agent, the sender, the body, and the MCP tools. Claude drives any further
|
||||
`recv`/`send` itself.
|
||||
broker `Sent` event for this agent), peeks the remaining inbox depth with
|
||||
`Status`, and emits `TurnStart { from, body, unread }`. The wake prompt
|
||||
piped to claude includes a one-line `({unread} more pending — drain via …)`
|
||||
hint when `unread > 0`. Claude drives any further `recv`/`send` itself.
|
||||
|
||||
**Tool envelope** (`mcp::run_tool_envelope`): every MCP tool handler logs
|
||||
the request, runs the body, appends a status line (e.g.
|
||||
`[status] 3 unread message(s) in inbox` from a non-mutating `Status` peek),
|
||||
logs the result. New tools call this helper.
|
||||
the request, runs the body, logs the result. Pre-/post-log only; the old
|
||||
`[status] N unread message(s)` appendage was removed once unread moved
|
||||
into the wake prompt + UI header. New tools call this helper.
|
||||
|
||||
**Tool whitelist** (`mcp::ALLOWED_BUILTIN_TOOLS`):
|
||||
- Allowed built-ins: `Bash`, `Edit`, `Glob`, `Grep`, `Read`, `TodoWrite`,
|
||||
|
|
@ -207,9 +222,27 @@ logs the result. New tools call this helper.
|
|||
|
||||
**Live view.** Each agent runs an `events::Bus` (a
|
||||
`tokio::sync::broadcast<LiveEvent>` wrapper). The harness emits
|
||||
`TurnStart`, `Stream(value)` (one per parsed stream-json line), `Note`,
|
||||
`TurnEnd`. The web UI subscribes via `/events/stream` (SSE) and a JS panel
|
||||
appends rows. No full-page reload — operator input stays put.
|
||||
`TurnStart { from, body, unread }`, `Stream(value)` (one per parsed
|
||||
stream-json line), `Note`, `TurnEnd { ok, note }`. The web UI subscribes
|
||||
via `/events/stream` (SSE) and a JS panel (terminal-themed: Crust bg, inset
|
||||
shadow, monospace) renders rows:
|
||||
|
||||
- `TurnStart` → `◆ TURN ← <from> · N unread` header + indented body.
|
||||
- `Stream` `tool_use` → `→ Read /path` / `→ Bash $ cmd` /
|
||||
`→ send → operator: "..."` etc., per-tool pretty rather than raw JSON.
|
||||
- `Stream` `tool_result` short → flat `← ...`; long → collapsed
|
||||
`<details>` `▸ ← Nl · headline` (click to expand full body).
|
||||
- `Stream` `thinking` → shows the thinking text if claude provided one,
|
||||
otherwise the bare `· thinking …` indicator.
|
||||
- `Stream` `system init`, `result`, `rate_limit_event` are dropped — too
|
||||
noisy and `TurnEnd` already says the turn finished.
|
||||
- `Note` → `· text`.
|
||||
- `TurnEnd` → `✓ turn ok` / `✗ turn fail — note` and triggers a
|
||||
`refreshState()` so the page form view reflects state transitions
|
||||
(e.g. login just landed).
|
||||
|
||||
The operator send form sits below the live panel, so the tail is what
|
||||
you read first.
|
||||
|
||||
## Manager (hm1nd) is hive-c0re-managed
|
||||
|
||||
|
|
@ -237,6 +270,36 @@ Differences from sub-agents:
|
|||
block from your host NixOS config. hyperhive creates and updates the
|
||||
manager itself now.
|
||||
|
||||
**Manager policy** (from `prompts/manager.md`): the manager does NOT
|
||||
rubber-stamp sub-agent config requests. It verifies (role match, package
|
||||
legitimacy, cheaper alternative, blast radius) before committing +
|
||||
calling `request_apply_commit`. For ambiguous cases or anything that
|
||||
needs human signal, the manager forwards the question to the operator
|
||||
via `send(to: "operator", ...)` — a dedicated `mcp__hyperhive__ask_operator`
|
||||
tool with proper pause/resume semantics is in [TODO.md](TODO.md).
|
||||
|
||||
## Helper events to the manager
|
||||
|
||||
`Coordinator::notify_manager(&HelperEvent)` enqueues an inbox message
|
||||
from sender `system` with the event JSON in the body. The manager
|
||||
harness no longer short-circuits these — they drive a regular claude
|
||||
turn so the manager can react. 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` (Spawn-kind) +
|
||||
admin `HostRequest::Spawn`.
|
||||
- `Rebuilt { agent, ok, note }` — `auto_update::rebuild_agent` (covers
|
||||
startup scan + manual `/rebuild` from dashboard) + `actions::approve`
|
||||
(ApplyCommit).
|
||||
- `Killed { agent }` — admin `HostRequest::Kill` + dashboard `/kill`.
|
||||
- `Destroyed { agent }` — `actions::destroy`.
|
||||
|
||||
To add a new event: new `HelperEvent` variant + call sites + update
|
||||
`prompts/manager.md` so the manager knows the new shape.
|
||||
|
||||
## Auto-update on startup
|
||||
|
||||
`hive-c0re serve` runs `auto_update::run` in a background task right after
|
||||
|
|
@ -252,7 +315,23 @@ auto-update is a no-op — rebuild manually.
|
|||
The dashboard surfaces pending updates per agent: a clickable "needs update
|
||||
↻" badge appears whenever the marker differs from current rev. The badge
|
||||
POSTs `/rebuild/<name>`, calling the same `auto_update::rebuild_agent`
|
||||
path so manual triggers and the startup scan can't drift.
|
||||
path so manual triggers and the startup scan can't drift. When at least
|
||||
one container is stale, a top-level `↻ UPD4TE 4LL` button appears that
|
||||
loops over every stale container.
|
||||
|
||||
## Dashboard action surface
|
||||
|
||||
Container row buttons (rendered per-state by `assets/app.js`):
|
||||
|
||||
- Always: `↻ R3BU1LD` (calls `lifecycle::rebuild`), and for sub-agents
|
||||
`DESTR0Y` (container removed, state + creds kept).
|
||||
- Running: `↺ R3ST4RT` + (sub-agents only) `■ ST0P`.
|
||||
- Stopped: `▶ ST4RT`.
|
||||
- Stale marker: clickable `needs update ↻` badge (same target as rebuild
|
||||
but only shown when out of date).
|
||||
|
||||
Top of the containers list: `↻ UPD4TE 4LL` (when any stale) + the
|
||||
"R3QU3ST SP4WN" form for queuing a new agent through the approval flow.
|
||||
|
||||
## Approval flow
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue