diff --git a/docs/tools/bash.md b/docs/tools/bash.md index be9f8205..85c899a0 100644 --- a/docs/tools/bash.md +++ b/docs/tools/bash.md @@ -11,7 +11,7 @@ invocation regardless of tool groups. ### `run(cmd, timeout_secs?, wait_seconds?, name?)` -Submit a shell command for background execution (`sh -c `). +Submit a shell command for background execution (runs via `bash`). Stdout and stderr stream to `harness/bash-tasks/.{out,err}`. When the task completes (or times out, or the process errors), the harness fires a wake with `from: "bash-task-"` and the exit code @@ -40,7 +40,7 @@ Exposed as `mcp__bash__run`. Poll the status of a task submitted with `run`. Returns: -- `status` — `pending` / `running` / `done` / `timed_out` / `interrupted` +- `status` — `pending` / `running` / `done` / `timed_out` / `interrupted` / `killed` - `exit_code` — set when done - run duration - last 4 KiB of stdout and stderr (full output in the `.out` / `.err` files) @@ -56,6 +56,24 @@ silently blocked. Exposed as `mcp__bash__status`. +### `kill(id, force?)` + +Stop a running or pending task by its ID (from `run`). Fire-and-forget: +sends the signal and returns without waiting — handle the completion +wake (`from: "bash-task-"`) on a future turn. + +- `force: false` (default) — SIGINT to the task's **process group** + (graceful; lets the process clean up). The whole process group is + signalled, so children spawned by the shell (cargo, nix, etc.) are + also stopped. +- `force: true` — SIGKILL. + +If a SIGINT'd task doesn't exit, call `kill` again with `force: true`. +A still-pending task is cancelled before it starts. The task ends as +`killed` and fires the usual completion wake. + +Exposed as `mcp__bash__kill`. + ## Namespace note `run` and `status` live in the `bash` MCP server, not `hyperhive`. So diff --git a/docs/tools/forge.md b/docs/tools/forge.md index fb5c5821..8ff08374 100644 --- a/docs/tools/forge.md +++ b/docs/tools/forge.md @@ -34,7 +34,7 @@ hive-forge pr status --pr 42 # PR health (mergeable / CI / review hive-forge issue create --title "..." --body "..." # --- flat aliases below remain valid (hidden) --- hive-forge view 42 # title + body + comments (marks thread read) -hive-forge comments 42 # list all comments (human-readable; marks thread read) +hive-forge comments 42 # list all comments (human-readable; marks thread read); for PRs, review bodies merged in hive-forge comments 42 --tail 10 # last 10 comments (count-then-page; efficient on long threads) hive-forge --json comments 42 # same as above, JSON array (global flag) hive-forge comment 42 --body "..." # post comment (inline body) @@ -95,7 +95,7 @@ distinct output shape — pick by what you need: |------|------|-------| | The full human view of one item — title, body, **and** every comment in order | `view ` | prose dump; **marks the thread read** (clears the read-before-comment guard). Top-level `view` auto-detects issue-or-PR by number; scoped `issue view ` / `pr view ` do the same when you already know the kind | | Just the structured metadata of one item (state, labels, assignees, head sha…) | `issue ` / `pr ` | JSON object | -| Only the comments (skip the body), e.g. to catch up a long thread | `comments ` [`--tail N`] | comment list; **marks read** | +| Only the comments (skip the body), e.g. to catch up a long thread; for PRs, review bodies (approve/request-changes/comment summaries) are merged in too | `comments ` [`--tail N`] | comment + review-body list; **marks read** | | One specific comment by its id | `comment-show ` | single comment | | The audit trail — closes, label/assignee changes, commit refs, merges (no comment bodies) | `timeline ` | event list | | The code change | `diff ` | unified diff | diff --git a/docs/turn-loop.md b/docs/turn-loop.md index e221233b..92678187 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -66,8 +66,10 @@ Three subcommands: - `serve` — long-running harness loop (the inbox poll + claude-pump + ack/requeue cycle described above). -- `mcp` — stdio MCP server claude spawns via `--mcp-config` per - turn. Same binary, different mode. +- `mcp` — MCP server. Default: stdio child claude spawns via + `--mcp-config` per turn. With `--http `, runs as a persistent + streamable-HTTP daemon instead (used by the `hive-mcp-http` + systemd unit when `hyperhive.mcp.httpPort` is set). - `wake --from --body ` — push a message into our own inbox so the next turn fires with the given body. Used by co-process daemons (matrix bridge, scraper, webhook listeners) @@ -267,9 +269,13 @@ next turn picks it up like any other inbox message. `hive_ag3nt::turn::write_*` writes two files next to the per-agent socket at `/run/hive/` once at startup: -- `claude-mcp-config.json` — re-invokes the running binary as `mcp` - child (so the same binary serves as harness + as claude's MCP - child process). +- `claude-mcp-config.json` — by default re-invokes the running binary + as `mcp` stdio child (so the same binary serves as harness + MCP + server per turn). When `hyperhive.mcp.httpPort` is set in the + agent's NixOS config, the config instead points claude at the + persistent `hive-mcp-http` daemon (`http://127.0.0.1:{port}/mcp`) + — no stdio child per turn; trades the per-turn re-registration race + for a hard dependency on the daemon's uptime (`Restart=always`). - `claude-system-prompt.md` — rendered from `hive-ag3nt/prompts/system.md` by `hive_ag3nt::prompt::render`: HTML-comment markers (`...`, @@ -533,13 +539,14 @@ ttl_seconds?, to?)`, `answer(id, answer)`. `cancel_loose_end(kind, id)`, `remind(message, delay_seconds? | at_unix_timestamp?)`, `request_next_turn()`. -- `get_loose_ends(agent?)` — list pending questions (asked/owed) and - scheduled reminders. Each row carries an id + kind for - `cancel_loose_end`. Omit `agent` to list your own threads. Pass - `agent: ""` to inspect a direct child agent (always - accessible per topology enforcement); non-children require the - `query_agent_state` capability. The `"*"` hive-wide query is not - available on the agent socket. +- `get_loose_ends(agent?)` — list pending questions (asked/owed), + scheduled reminders, and active local tasks published by external MCP + daemons (e.g. running bash tasks from `hive-bash-mcp`). Each row + carries an id + kind for `cancel_loose_end`. Omit `agent` to list + your own threads. Pass `agent: ""` to inspect a direct child + agent (always accessible per topology enforcement); non-children + require the `query_agent_state` capability. The `"*"` hive-wide + query is not available on the agent socket. - `cancel_loose_end` — withdraw a `question` (posts `[cancelled by ]`), hard-delete a `reminder`, or cancel a pending `approval` row. Agents may only cancel rows they own; the `approval` kind is @@ -638,9 +645,9 @@ status hint moved to the wake prompt + UI header. `Bash` is disallowed — shell execution goes through `mcp__bash__run` (background tasks with structured output + -task-id tracking) instead of an interactive shell. The `run` / -`status` MCP tools (`mcp__bash__run` / `mcp__bash__status`) are always -in the `--allowedTools` list. +task-id tracking) instead of an interactive shell. The bash MCP server +(`run` / `status` / `kill`) uses `allowedTools = ["*"]` so all +`mcp__bash__*` tools are always available regardless of tool groups. `WebFetch` / `WebSearch` are off by default; enable the `web_tools` tool group in the P3RM1SS10NS tab and rebuild the agent to enable them. diff --git a/docs/web-ui/agent.md b/docs/web-ui/agent.md index f37869e5..711934f9 100644 --- a/docs/web-ui/agent.md +++ b/docs/web-ui/agent.md @@ -154,7 +154,7 @@ After the drain the inbox list empties on reload (the filter is `acked_at IS NULL`, so drained messages disappear). Loose-ends flyout: questions, approvals, and reminders pending against this agent (`GET /api/loose-ends`); question rows carry an inline answer form that POSTs cross-origin to -the core dashboard's `/answer-question/{id}` so the operator answers +the core dashboard's `POST /api/answer-question/{id}` so the operator answers *as operator* (see `docs/boundary.md`). Tasks flyout: in-flight bash tasks (`GET /api/bash-tasks`); each row shows status (`▶ running` / `◷ queued`), the task id, elapsed time, and a truncated one-line @@ -172,7 +172,7 @@ the slot list and pairs each unbound slot with the first unclaimed pending operator-bound question whose `question` text matches the slot's stashed `_askQuestion`. On match the slot mounts the `buildAnswerForm` (same form shape as the loose-ends flyout — -POSTs to the core's `/answer-question/{id}` cross-origin). Slots +POSTs to the core's `POST /api/answer-question/{id}` cross-origin). Slots stay in the array after binding so the reconciler can flip them to a neutral `[resolved]` tag when the question later disappears from the pending list. Disappearance can mean answered, cancelled