Commit graph hyperhive/docs/turn-loop.md
Author SHA1 Message Date
atlas
246c9471b1 refactor(hive-agent): split the forge notification poller into its own crate
The poller was a `tokio::spawn` inside the `hive-agent` serve loop. It
never needed anything from that loop except a socket path, so being
in-process bought nothing and cost two things: a harness restart took
forge notifications down with it, and the whole forge/HTTP dependency
tree was linked into the serve-loop binary.

It is now `hive-forge-notify`, a per-agent daemon with its own systemd
unit, a sibling of `hive-bash-daemon` and `hive-matrix-daemon`. Same
contract as those two: it reaches the harness only by upserting todos on
the in-agent socket, and nowhere else.

The module moves verbatim (`notify.rs`) — the formatters, the activation
gates, the dedupe map and all 33 tests are unchanged. Only the socket
call sites are rewritten, onto a small local `todo_client` rather than
the harness's. That mirrors what both sibling daemons already do, and
the etiquette differs on purpose: the harness's client carries a 60s
backoff schedule sized to ride out a hive-c0re restart, which its
callers need because they have no retry of their own. This poller's two
call sites both sit inside the 30s poll loop and both treat a failure as
"leave the thread unread, try next tick", so the poll interval already
is the retry; a second backoff would only stack sleeps and delay the
rest of the batch.

The unit is `Restart=on-failure`, not `always`. An agent with no forge
account is a supported configuration and the poller reports it by
logging why and exiting 0 — under `always` that clean exit would be a
restart loop on every forge-less agent.

`forgejo-api`, `url` and `time` drop out of `hive-agent`'s dependencies
with the module.

Also corrects docs that outlived the code they described: the persisted
`forge_cursor` field is long gone (forge's own read-state is the durable
record of what has been delivered), but `docs/persistence.md` and the
`harness_state` module docs still documented it as live.
2026-07-26 21:30:29 +02:00
atlas
7ba90d5a3f feat(agent): raise a todo when the agent's disk gets tight
Closes 2718.

The operator has been going through agent dirs by hand with ncdu,
deleting 20+GB target dirs. Agents had no way to know they were the
ones sitting on the space.

New `disk_watch` module in the harness: every 15 minutes it statvfs's
the filesystem backing the agent's state dir and, past 80%, raises a
keyed `disk` todo telling the agent to free space — with the operator's
rules inline: only delete things that are actually big, build output
first, and never delete something still needed, ask for more space
instead.

Over threshold it also walks the agent's own tree (`/agents/<label>`
plus `$HOME`) and names the directories worth looking at, so the todo
says where the bytes actually went rather than just that the disk is
full. The walk is bounded on every axis — entry budget, recursion cap,
report depth — pinned to the state dir's device so it can't wander into
`/nix` or the shared bind mounts, and it does not traverse symlinks. It
reports the deepest oversized directory on each branch, so the agent
gets pointed at `<workspace>/target` rather than at `/agents/<label>`.

Anti-nag is the whole design constraint. The todo is keyed, and the
summary is deliberately stable: the percentage is bucketed to 5 points
and no raw byte counts appear anywhere in it. An unchanged situation
re-upserts as `changed == false` and never fires the wake, so a disk
that has been steady at 89% for a week sits quietly in the loose-ends
list; crossing into a new bucket speaks up once. Dropping back under
the threshold clears the row.

Harness-local by construction, per the operator's call that this gets
no core wiring: hive-c0re cannot push a todo at all (the store and its
wake live inside the container), and running in-process means this
skips even the in-agent socket and calls `Todos::upsert` directly.

Worth recording, since it shaped the scope: btrfs does NOT fold qgroup
limits into statfs. Measured with quota counting enabled and a 20G
limit set on a real subvolume, statvfs returns byte-identical whole-FS
numbers for that subvolume, an ordinary agent dir, and the root. So
this watches host-FS pressure, which is valid before and after the
planned subvolume migration; per-agent quota awareness would need the
limit handed to the agent explicitly.
2026-07-26 17:59:13 +02:00
atlas
31008c83df feat: pause an agent's turn loop without stopping its container
A paused agent keeps its container, its claude session and its
dashboard/todo servers up, but stops driving turns. Messages queue
unacked and are drained on resume.

The whole protocol is a single marker file, `<harness>/paused`. That
directory is already a bind-mount shared between host and container, so
both sides just stat the same path: the harness reads it to decide
whether to drive a turn, hive-c0re reads it to render the badge and
writes/removes it for `hivectl pause|resume`. No new wire protocol, no
container round-trip, and it is sticky across restarts by construction.

Not calling `recv_next` while paused *is* the queueing semantic, so
there is no fencing to get wrong: reminders buffer in their unbounded
channel, the todo `Notify` permit coalesces, and a `request_next_turn`
that raced the pause survives because the gate sits above
`self_continue.take()`.

Graceful stop is handled host-side rather than in the harness: a paused
agent provably has no turn in flight, so `run_signal` skips the fence
entirely instead of eating the full `GRACEFUL_STOP_TIMEOUT` waiting for
a checkpoint turn that will never run.

`paused` is reported on `ContainerView` / `AgentStatusRow` for the
dashboard, orthogonal to `running` and reported for stopped containers
too.

Closes: hyperhive/hyperhive issue 2271
2026-07-26 03:11:33 +02:00
damocles
2316287327 remove hive-agent-wake — no shipped consumer 2026-07-25 20:05:32 +02:00
damocles
4745274fca refactor(#2112): remove the dead stdio transport from hive-agent-mcp 2026-07-11 00:55:41 +02:00
damocles
1ba44b77ac feat(#2112): make http-mcp the sole transport for the built-in surface 2026-07-11 00:32:51 +02:00
damocles
5027068e31 feat(#2109): harness-side idle watchdog to bail on anthropic api stall storms 2026-07-07 22:45:18 +02:00
müde
5b062dca55 refactor(hive-ag3nt): split hive bin into hive-agent / hive-agent-mcp / hive-agent-wake 2026-07-06 23:48:05 +02:00
müde
b4f54a194b fix(agent): don't eat /compact flag on failed turn; restore ctx fallback; requeue on SessionNotFound 2026-07-06 00:01:15 +02:00
müde
216eb8ae9b docs(turn-loop): split into index + claude-invocation/config/mcp sub-pages, condense the loop 2026-07-05 23:04:48 +02:00
müde
f490e07509 refactor(prompt): drop unreachable role-block defensive branches; keep marker grammar 2026-07-05 22:36:10 +02:00
müde
dd7f8c5ebb docs(turn-loop): document PromptTooLong archive+requeue, TurnOutcome=Result, credential-file session detection 2026-07-05 22:27:09 +02:00
müde
90af3e8d0b refactor(mcp): split claude launch-config layer into mcp_config.rs 2026-07-05 22:24:46 +02:00
müde
4a404c1128 docs: describe hive-claude split, InfiniteSession, deferred compact, web_ui dir 2026-07-05 20:53:56 +02:00
müde
e35acca814 fix(agent): pin claude session by constant title, archive on reset 2026-07-05 18:13:54 +02:00
iris
bd0e4d1012 fixup! docs(turn-loop): document system inbox messages and link to approvals.md helper events
Per argus review: correct routing subject from 'root/manager agent' to
'submitting agent (root agent for top-level containers; approvals-group
agent for its own subtree)', and drop the deprecated 'manager' term.
2026-07-05 02:28:26 +02:00
iris
2748ce2f4c docs(turn-loop): document system inbox messages and link to approvals.md helper events
The messaging section listed the MCP tools for send/recv/ask/answer/ack_until
but didn't mention the system events agents receive from sender 'system' —
lifecycle events (spawned, rebuilt, killed, etc.) routed to the root agent and
Q&A events (question_asked, question_answered) delivered to any agent. Add a
brief paragraph that names the events and links to the canonical reference in
docs/approvals.md where the full payload shapes and routing logic live.
2026-07-05 02:24:42 +02:00
atlas
9067398e3c chore(docs,nix): remove stale shared-netns references from matrix URL docs
Agents run in private netns (always-on isolation) and can't reach
host loopback directly. hive-c0re forwards HIVE_MATRIX_URL set to
`matrix.<domain>` via the gateway. Update two places that still
referenced the removed shared-netns path.
2026-07-04 22:54:38 +02:00
iris
0ae2dbd8fa docs(turn-loop): document forge + web_tools tool groups in Privileged tools section
The 'Privileged tools (by tool group)' section listed execution,
lifecycle/approvals, scheduling/diagnostics, capability-gated, and
matrix but was missing:

- forge (create_repo) — the only agent path to create a repo under the
  agents/ org; direct token creation is disabled for agents. Opt-in,
  not in any default preset.
- web_tools — enables Claude built-in WebFetch/WebSearch tools. Off by
  default. The tool whitelist section already mentioned these but the
  group was absent from the privileged-tools list.
2026-07-04 19:01:07 +02:00
iris
42b2f8ec40 fix: correct HIVE_DOCS_DIR path description (nix store path, not /run/ mount) 2026-07-04 14:31:39 +02:00
iris
b41e3276c3 docs(turn-loop): add dedicated section for hyperhive.docs.enable agent.nix option
The option was only mentioned in passing in the system-prompt render
section. Add a proper ### section (following the pattern of Agent icon,
user.passwordlessSudo, etc.) with the nix snippet, default, effect on
$HIVE_DOCS_DIR + system prompt, and a note on the narrow docs flake
input that avoids full container rebuilds on doc edits.
2026-07-04 14:31:39 +02:00
iris
2f8e9e2bb4 docs(turn-loop): document docs-pointer system-prompt injection, drop stale CLAUDE.md mention 2026-07-04 13:13:33 +02:00
damocles
78396c8189 recv: cap batch size at 5, default stays 1 (#2150 clarified) 2026-07-03 18:50:21 +02:00
damocles
ee45db6323 Revert "recv mcp tool: default max to a small batch of 5 (wire default stays 1)"
This reverts commit b8d608d4b6a7ed95faffdec8d8b3167ae8f3b39e.
2026-07-03 18:50:21 +02:00
damocles
d46d3c261b recv mcp tool: default max to a small batch of 5 (wire default stays 1) 2026-07-03 18:50:21 +02:00
iris
9727cee9bd docs: add infra_admin capability to tables; fix get_agent_meta matrix_accounts in turn-loop 2026-07-02 15:29:14 +02:00
iris
0de8c37233 docs(turn-loop): document ack_until tool + [msg #id] markers in recv/wake prompt
ack_until was added to the messaging group by the ack_until feature
but was missing from the turn-loop.md MCP surface documentation
entirely. Add it to:

- Messaging group signature list
- recv bullet: mention that each row is prefixed with [msg #<id>]
  so agents know what id to pass to ack_until
- New ack_until bullet explaining recipient-scoped bulk-triage use case
- Wake prompt section: mention the [msg #<id>] prefix and its purpose
2026-07-02 15:28:25 +02:00
iris
64d60e5cdb docs(turn-loop): mention kill in bash allowed-tools note
The allowed-tools note only named run/status; kill is also always
available since the bash MCP server uses allowedTools = ["*"].
Reword to name all three and explain the wildcard mechanism.
2026-07-02 14:15:49 +02:00
iris
9162ce7dc7 docs(turn-loop): document active bash tasks in get_loose_ends output
feat 3c853c2b58 added active bash tasks
to the get_loose_ends response but only updated the MCP server tool
description string; the docs/turn-loop.md entry for the tool still only
mentioned questions and reminders.

Add 'active local tasks published by external MCP daemons (e.g. running
bash tasks from hive-bash-mcp)' to the tool description so agents
reading the reference docs see the full picture.
2026-07-02 14:15:49 +02:00
iris
2f504247ed docs(turn-loop): document optional HTTP MCP transport (httpPort)
When hyperhive.mcp.httpPort is set in agent.nix, the hive-mcp-http
systemd daemon runs the embedded MCP server as a persistent streamable-
HTTP service; claude-mcp-config.json points at the HTTP URL instead of
spawning a stdio child per turn. Document both modes in the subcommand
list and the on-boot files section.
2026-07-02 14:15:46 +02:00
damocles
c7bac398b2 address mara: drop CompactionMode, always checkpoint-then-compact 2026-07-01 19:05:24 +02:00
damocles
fc42f97691 parallelize graceful agent drains, serialize container stops on fast lane; unify shutdown+checkpoint+compact prompt 2026-07-01 19:05:24 +02:00
damocles
c99fa714d9 feat(#2050): set matrix avatar in the daemon over the live client 2026-06-28 01:38:21 +02:00
damocles
c2ba841932 docs(turn-loop): present managed-settings as current state, drop changelog phrasing 2026-06-26 23:06:04 +02:00
damocles
b231ed2392 feat(#1969): ship claude settings via /etc/claude-code/managed-settings.json 2026-06-26 23:06:04 +02:00
lexis
73a58776fa docs(turn-loop): document graceful stop recv behavior (follow-up to #1920) 2026-06-22 23:27:33 +02:00
damocles
cc03af3390 docs: drop stale two-loop/two-binary framings (single hive serve loop) 2026-06-10 20:01:52 +02:00
damocles
daa6a59324 fix(#1543): drive request_next_turn continue in-process, not via the broker 2026-06-09 11:25:55 +02:00
iris
f2d57c8538 fix: drop stale claim that ruth is always reachable in allowedRecipients
The sentence 'ruth is always reachable regardless of the list' documents
a bug in check_send_allowed (name-based carve-out), not intended
behavior. The structural parent carve-out is fine to mention since it's
topology-based, not name-based.

Updated example to show [ "operator" ] (restrict to operator-only)
and replaced the ruth-name claim with a note about the parent carve-out.
2026-06-05 18:45:06 +02:00
iris
da8892aac2 fix(docs/turn-loop): correct allowedRecipients example name to ruth
The manager's logical name is 'ruth' (MANAGER_AGENT post-#954).
The example used the stale 'manager' placeholder.
2026-06-05 18:45:06 +02:00
iris
3328b396e7 docs(turn-loop): document allowedRecipients, claudePlugins, cargo.shortMessages
Five per-agent agent.nix options were undocumented:

- hyperhive.allowedRecipients — restricts which peers send() accepts;
  note added inline to the send tool description
- hyperhive.claudeMarketplaces — Claude Code plugin marketplace sources
  (default: official Anthropic marketplace)
- hyperhive.claudePlugins — plugin specs installed at harness boot
- hyperhive.claudePluginsAutoUpdate — pull latest marketplace index
  before install; off by default
- hyperhive.cargo.shortMessages — shell wrapper injecting
  --message-format short on cargo compile subcommands; on by default
2026-06-05 18:45:06 +02:00
iris
330fdf8dc7 fix(docs/turn-loop): correct forge.url tea-login description
The tea-login oneshot writes ~/.config/tea/config.yml directly via
heredoc; it never calls 'tea login add'. Fix the implementation detail.
2026-06-05 18:30:29 +02:00
iris
20269873bd docs(turn-loop): also document hyperhive.icon option
SVG path for per-agent visual identity — used in the page header,
favicon, Forgejo profile avatar (forge-avatar-sync), and Matrix
profile avatar (matrix-avatar-sync).
2026-06-05 18:30:29 +02:00
iris
8f4a8fbc07 docs(turn-loop): document passwordlessSudo, dashboardLinks, extraFiles, connectivity overrides
Five previously undocumented per-agent agent.nix options:

- hyperhive.user.passwordlessSudo: default-true sudo grant; note added
  with cross-reference to companion user.* options in agent-hierarchy.md
- hyperhive.dashboardLinks: declarative extra nav links on the dashboard
  card and per-agent page header; table of fields (label/url/icon)
- hyperhive.frontend.extraFiles: overlay files over the default agent dist;
  source/target semantics, constraints, collision guard, mergedDist
- hyperhive.forge.url: per-agent Forgejo base URL for tea login; default
  localhost:3000; validation note
- hyperhive.matrix.url: per-agent matrix-sdk homeserver URL; default
  localhost:8008; per-agent override use-cases (remote hive, VPN)
2026-06-05 18:30:29 +02:00
iris
83059a0fcb docs(turn-loop): document hyperhive.autoCompact nix option
The compaction section already documented HIVE_COMPACT_WATERMARK_TOKENS
but didn't mention the per-agent nix option (hyperhive.autoCompact,
default true) that maps to it.

Add a short note after the watermark paragraph explaining that operators
can set autoCompact = false in agent.nix to disable proactive compaction,
and note the reactive path still applies. Useful for sonnet/opus agents
where the 75% heuristic fires before the session is actually full.
2026-06-05 18:28:43 +02:00
damocles
29bc40a1d7 docs: document get_host_journal in scheduling.md and turn-loop.md 2026-06-05 00:48:05 +02:00
lexis
13fe5ef9d3 docs(turn-loop.md): document get_loose_ends agent parameter scoping
Add clarification for the agent parameter: omit to list own threads,
pass agent name for direct children (always accessible), or query_agent_state
capability for non-children. Note that hive-wide '*' query unavailable
on agent socket.
2026-06-04 18:38:19 +02:00
damocles
41eb3f806c refactor: remove hyperhive.role option — there is only one role: agent 2026-06-04 14:31:44 +02:00
damocles
9c1c4f62fb fix: add approval kind to cancel_loose_end docs; drop stale role comment in mcp.rs; fix system.md approval-cancel description 2026-06-04 13:51:39 +02:00
damocles
78a00d1258 docs(#1251): split MCP tool docs into docs/tools/ sub-mds by feature 2026-06-04 13:51:39 +02:00