Commit graph hyperhive/hive-ag3nt
Author SHA1 Message Date
damocles
8b559eceec fix: remove hive-bash-mcp cargo dep from hive-ag3nt — add minimal bash_tasks.rs for get_loose_ends 2026-06-03 18:06:59 +02:00
damocles
e86160820a feat(#1106): split bash mcp into hive-bash-daemon + hive-bash-mcp bridge
- new hive-bash-mcp crate: daemon (subprocess runner, wake signals) +
  stdio bridge (mcp tools). mirrors hive-matrix-mcp architecture
- hive-ag3nt: remove bash_runner.rs and bash_run/bash_status mcp tools;
  get_loose_ends uses hive_bash_mcp:🏃:active_tasks() via crate dep
- harness-base.nix: add hive-bash-daemon systemd service + auto-inject
  bash extraMcpServer into every agent (socket: /run/hive-bash/socket)
2026-06-03 18:06:59 +02:00
damocles
3dda286d2b fix(#1147): break wait loop immediately on unknown task id 2026-06-03 16:35:41 +02:00
damocles
faff09ef23 feat(#1147): add optional wait_seconds to bash_status 2026-06-03 16:35:41 +02:00
damocles
6be114eb05 feat(#1151): default bash_run wait_seconds to 3s 2026-06-03 16:30:38 +02:00
atlas
68e30b857c feat(#1137): rich unread summary in loose ends and wake signal
- hive-sh4re: UnreadMatrix gains summary: String field (per-room breakdown)
- hive-matrix-mcp/protocol: add RoomUnread struct + UnreadSummary request
- hive-matrix-mcp/handlers: collect_unread() fetches per-room data;
  single-unread rooms include truncated last-message body + sender;
  multi-unread rooms carry count only
- hive-matrix-mcp/wake: format_unread_summary() builds wake body from
  RoomUnread slice; terse one-liner for single-room/single-message,
  bulleted list for multi-room; always appends read-hint
- hive-matrix-mcp/timeline: wake body now covers all rooms with unread
  at fire time, not just the triggering event; falls back to per-event
  teaser if notification counts haven't updated yet
- hive-ag3nt/mcp: matrix_unread_summary() replaces matrix_unread_rooms();
  UnreadMatrix loose end carries per-room summary lines; render shows
  room breakdown with sender: body for single-unread rooms
2026-06-03 13:56:00 +02:00
atlas
46edc635f2 feat(#1134): add unread matrix messages as a loose end
When the local matrix daemon has rooms with unread notifications,
get_loose_ends now prepends an UnreadMatrix entry to the output so
agents see pending matrix activity alongside questions/reminders
without message content being exposed.

Changes:
- hive-sh4re: add LooseEnd::UnreadMatrix { rooms: u32 } variant
- hive-matrix-mcp: add DaemonRequest::UnreadCount and handler that
  counts joined rooms with notification_count > 0 (server-side push
  notification counts, cached by matrix-sdk)
- hive-ag3nt/mcp: inject UnreadMatrix entry on self-queries by
  connecting to /run/hive-matrix/socket (HIVE_MATRIX_SOCKET override);
  best-effort — agents without matrix configured are unaffected
2026-06-03 13:55:09 +02:00
damocles
057c673be8 fix: remove issue tag from comment in bash_runner 2026-06-03 12:30:30 +02:00
damocles
a1c6736ba5 feat(#1106): transient wake for bash tasks — bypass broker sqlite 2026-06-03 12:30:30 +02:00
damocles
e54c1b84d7 feat(#1095): add wait_seconds to bash_run for inline fast-command completion 2026-06-03 11:26:22 +02:00
damocles
60047eb01d feat(#1104): surface full output file path in bash_status when truncated 2026-06-03 11:25:54 +02:00
damocles
89665b94de feat(#1014): rename manager agent root→ruth across all crates + frontend 2026-06-02 18:18:06 +02:00
damocles
cbd14e9cd0 fix(#1066): retry turn once on 401 before parking for re-login 2026-06-02 12:43:41 +02:00
iris
c0f16c870f fix(web_tools): remove WebFetch/WebSearch from permissions.deny
The deny list takes precedence over --allowedTools, so granting the
web_tools group had no effect — both tools were silently blocked.

WebFetch/WebSearch are now gated solely via --tools (builtin_tools_arg):
agents without the web_tools tool group don't get them in --tools so
claude never sees them; agents with the group get them in both --tools
and --allowedTools.
2026-06-02 11:31:33 +02:00
iris
f6b80cf02e feat(#1065): web_tools tool group gates WebFetch/WebSearch built-ins
Replaces the earlier capability-based approach (closed #1069) with a
ToolGroup — capabilities are for privileged system access, web egress is
a tool permission.

Add ToolGroup::WebTools to hive-sh4re:
- tools() returns &[] (no MCP tools gated)
- builtin_tools() returns &["WebFetch", "WebSearch"] — new method on ToolGroup
- Present in ALL and as_str() → "web_tools"

In hive-ag3nt/mcp.rs:
- allowed_tools_arg() now iterates group.builtin_tools() to prepend any
  group-gated built-ins alongside the base ALLOWED_BUILTIN_TOOLS set
- builtin_tools_arg_for_flavor(flavor) replaces builtin_tools_arg() so
  the flavor-correct effective groups are used when building --tools
- builtin_tools_arg() kept as a flavor=Agent convenience alias
- turn.rs updated to call builtin_tools_arg_for_flavor(files.flavor) so
  manager sessions also see web tools when web_tools is in their groups

The dashboard T00L GR0UPS table gains a web_tools column automatically
(ToolGroup::ALL drives the columns).
2026-06-02 11:31:08 +02:00
damocles
29724f5021 drop orphaned bash-allow doc comment on load_extra_mcp 2026-06-02 09:25:50 +02:00
damocles
88f22065b0 feat(#1058): disallow built-in Bash; remove allowedBashPatterns; prompt sweep 2026-06-02 01:14:24 +02:00
atlas
4bff450343 feat(gateway): hivectl gateway user management + fix htpasswdFile assertion
Add `hivectl gateway {create-user,delete-user,list-users}` subcommands for
managing htpasswd files used by gateway Basic auth. Pure Rust bcrypt
(cost 12, $2y$ prefix nginx accepts). No external htpasswd binary required.

Also fix the NixOS module assertion: `cfg.auth ? htpasswdFile` is always
true in the module system (declared options always exist as keys); switch
to `nullOr path; default = null` + `!= null` check so the assertion
actually fires with a useful error when enable=true but no file is set.
Guard bind-mount and nginx config against null to prevent eval errors.

Update docs/gateway.md to show hivectl commands instead of raw htpasswd.
2026-06-01 23:25:28 +02:00
atlas
5c5ca38fe8 fix(#999): resolve all clippy warnings across the workspace
All crates now pass `cargo clippy --workspace -- -D warnings` cleanly.

Fixes span six crates (hive-sh4re, hive-ag3nt, hive-c0re, hive-forge,
hive-priv, hive-matrix-mcp was already clean):

- doc_markdown: wrap snake_case, type names, constants in backticks
- collapsible_if / collapsible_match: fold nested ifs into let-chains
- duration_suboptimal_units: Duration::from_secs(N) → from_mins/from_hours
- implicit_hasher: allow on HashMap-param fns where generalization is risky
- items_after_statements: hoist use to function tops
- map(f).unwrap_or(x) → map_or(x, f); map(f).unwrap_or_else(g) → map_or_else
- is_ok_and / is_none_or in place of map().unwrap_or(bool)
- needless_continue: {} instead of continue in loop match arms
- match_same_arms: Ok(None) | Err(_) merged
- format_push_str: write!() instead of push_str(&format!())
- while let replaces loop { let Some(..) = x else { break } }
- struct_excessive_bools / dead_code: allow on purpose-built structs
- too_many_lines / too_many_arguments: allow where refactor not worth it
- unused_async: remove async from poll_once in bash_runner
- needless_borrow: fix &repo deref in hive-forge comments verb
- cast_possible_truncation: allow u64→usize in fetch_tail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:31:06 +02:00
iris
0da83fa38b fix(#1023): read turn-stats db from harness_dir(), not state_dir()
turn_stats.rs writes to harness_dir()/hyperhive-turn-stats.sqlite but
stats.rs was reading from state_dir()/hyperhive-turn-stats.sqlite.
These paths diverged when the harness/state split was introduced.
The read side must match the write side.
2026-06-01 21:52:56 +02:00
damocles
d35b7ab9b4 fix(#1021): error on unauthorized target (not silent ignore); allow child targeting without cap 2026-06-01 21:26:42 +02:00
damocles
4834ca413c feat(#1021): query_agent_state capability for agent socket GetLooseEnds/CountPendingReminders/ReminderRollup 2026-06-01 21:21:25 +02:00
damocles
b9ecacaafe fix(#1004,#1006): get_host_journal - JournalPriority enum, grep/since/until, default 30/max 100, verbatim container, fix doc comment 2026-06-01 20:57:36 +02:00
damocles
dc8a4e2baf feat(#1004,#1006): capability system + read_host_journal / get_host_journal MCP tool 2026-06-01 20:57:36 +02:00
iris
0162a3f108 fixup: remove manager config path mention from ManagerServer instructions
Every agent's config lives at /agents/<name>/config/agent.nix — there
is no special case for the manager. Drop the sentence.
2026-06-01 19:18:02 +02:00
iris
0dc9d66880 rename(#162): drop non-special-case agent name examples from MCP docs 2026-06-01 19:18:02 +02:00
iris
ab278affc7 rename(#162): scrub remaining hm1nd references from comments and MCP instructions
All functional renames (MANAGER_NAME, MANAGER_AGENT → "root") were done in
earlier commits. This cleans up the stale `hm1nd` strings that remained in
doc comments, test fixture labels, and the manager MCP server instructions
(which told the manager its config lived at /agents/hm1nd/config/agent.nix).
2026-06-01 19:18:02 +02:00
damocles
e7e0675d22 rename: role badge stays 'manager'; unify harness unit name to hive-ag3nt 2026-06-01 17:33:09 +02:00
damocles
77622c0585 rename(162): update manager recipient to root in system.md 2026-06-01 17:33:09 +02:00
damocles
8e2f311e09 fix(#924): set web socket mode to 0o666 so gateway nginx can connect 2026-06-01 15:54:23 +02:00
damocles
3c853c2b58 feat: include active bash tasks in get_loose_ends output 2026-06-01 14:37:33 +02:00
damocles
083a100ba1 fix(#665): kill child on timeout, guard running-for display, drop stale doc ref 2026-06-01 13:28:31 +02:00
damocles
1178bb2999 feat(#665): harness-internal async bash task runner (option B) 2026-06-01 13:28:31 +02:00
damocles
ae6d23594d feat(#2): split harness-internal state from agent-visible state 2026-06-01 13:27:35 +02:00
damocles
98d9204ebf feat(#513): add ToolGroup enum, derive allowed_mcp_tools from groups + HIVE_TOOL_GROUPS env 2026-06-01 13:03:51 +02:00
damocles
15617cef9a refactor: unify AgentRequest/Response + ManagerRequest/Response into Request/Response (#691) 2026-06-01 11:20:10 +02:00
damocles
52cfc3ea1c reshape swarm peers: domain-as-key, certFingerprint field 2026-05-31 23:55:34 +02:00
iris
c353dc1893 fix: emit relative container link URLs from harness, update dashboard join
Container link URLs (/screen.html, /stats.html) were root-relative,
which works when the agent is accessed directly at :port/ but resolves
to the gateway root when accessed via /agent/<name>/.

Fix at the source: harness emits relative URLs (screen.html, stats.html)
and the dashboard joins containerBase + '/' + url. The agent page uses
the URL directly and relative resolution is now correct in both paths.
2026-05-31 23:24:39 +02:00
damocles
348fb3792a feat(#589): swarm peers option + HYPERHIVE_PEERS env wire v0
nix: services.hyperhive.peers attrset-of-submodules option; serialises
to HYPERHIVE_PEERS JSON ([{label,domain}]); forwarded to containers via
FORWARDED_VARS. dashboard.rs: peer_hives: Vec<PeerHiveView> in
StateSnapshot, derived as {name:label, url:"http://domain/"}.
identity.rs: PeerHive struct + peers() accessor for agent-side use.
2026-05-31 23:06:38 +02:00
iris
d3ca857659 fix(#888): use gateway forge URL in dashboard links
Dashboard links to the forge were hardcoded as http://<hostname>:3000,
which breaks when the operator accesses the dashboard through
hive-gateway (forge is served at forge.<domain> with no port).

- nix/modules/hive-c0re.nix: inject HIVE_FORGE_PUBLIC_URL when
  forge.behindGateway = true (e.g. http://forge.pr1ma.darkest.space)
- hive-c0re/src/dashboard.rs: expose forge_url: Option<String> in
  StateSnapshot, reading from HIVE_FORGE_PUBLIC_URL
- frontend/packages/dashboard/src/tabs.js: use state.forge_url when
  present; fall back to http://<hostname>:3000 for gateway-off /
  local-dev deploys
2026-05-31 22:04:52 +02:00
müde
8b238bbfaf agent UDS: chmod per-agent socket dir 0777 + log web_ui::serve errors
The harness runs as the non-root agent user; the per-agent
/run/hive-agent/<name>/ dir lands at 0755 root:root after
create_dir_all, so bind(2) of web.sock failed with EACCES. The error
was invisible because the web_ui::serve future was tokio::spawn'd with
its JoinHandle dropped — no log, no socket, agent looks unreachable
through the gateway.
2026-05-31 21:38:34 +02:00
iris
c7360cf0bb docs(#727): split docs/web-ui.md into shape / dashboard / agent
docs/web-ui.md (1315 lines) split into three sub-files:
- docs/web-ui/shape.md   — shared SPA skeleton, SSE multiplexing,
  Worker-death self-heal, terminal pane, listener bind, relative
  paths, atomic repaint, side panel
- docs/web-ui/dashboard.md — SW4RM/Y3R/SYST3M/SCH3DUL3S/S3TT1NGS
  tabs, container row, topology tree, selection bar, approval card,
  dashboard endpoints + event channel
- docs/web-ui/agent.md   — header, terminal, composer, inbox, live
  view, slash commands, per-agent endpoints, stats page

docs/web-ui.md replaced with a thin index linking all three.

Section anchors in docs (gateway.md, gotchas.md), Rust doc comments
(hive-ag3nt/src/web_ui.rs), and nix/templates/weston-vnc.nix updated
to point at the correct sub-file. README and CLAUDE.md file-map
updated with sub-file links. Inline // comments in frontend source
left unchanged (they reference the index which redirects to the right
sub-file).
2026-05-31 21:37:04 +02:00
iris
e1e5195081 dashboard + agent UI: surface hive_name + swarm_name in chrome (#701)
Damocles's backend (c41bf1b) landed HYPERHIVE_HIVE_NAME / _SWARM_NAME
env vars and identity.rs accessors. This commit wires them into the two
web surfaces:

hive-c0re/dashboard.rs:
  StateSnapshot gains `hive_name` + `swarm_name` (Option<String>),
  populated from the env vars the c0re NixOS module injects.

hive-ag3nt/web_ui.rs:
  Per-agent StateSnapshot gains the same two fields, populated from
  crate::identity::hive_name() / swarm_name().

Dashboard frontend (index.html + tabs.js):
  A `<p class="banner-thin" id="hive-identity">` sits above the tab
  strip in the chrome. refreshState() populates it with "swarm / hive"
  (or just "hive") when the fields are non-null, and updates
  document.title to "<swarm>/<hive> // h1ve-c0re". No change to
  chrome when both fields are null (backward compat).

Per-agent frontend (index.html + app.js + agent.css):
  A hidden `.agent-hive-label` span under the title row shows the
  swarm/hive label once setHeader() receives non-null names.
  document.title is updated to "<label> // <hive_name>" when hive_name
  is set, enabling browser-tab disambiguation when multiple hives are
  open in parallel. Styled as a small uppercase purple-dim sub-label.
2026-05-31 21:09:08 +02:00
damocles
36c683138d feat(#704): add <children> recipient sentinel — fan-out to direct descendants 2026-05-31 20:59:20 +02:00
damocles
252d8bf9af doc: add non-atomicity comment to emit_status RMW (argus note) 2026-05-31 20:32:13 +02:00
damocles
fce1f49f6a refactor(#838): consolidate harness state files into hyperhive-harness.json 2026-05-31 20:32:13 +02:00
iris
2a2d76d733 hive-ag3nt: scrub mcp.rs cookies (#716 batch 8)
Last #716 hotspot — scrub-only batch. All substantive prose is
already documented in docs/turn-loop.md::MCP surface (Sub-agent
tools, Manager tools, Tool whitelist, Tool envelope), so the 10
cookies in mcp.rs come out without prose extraction.

- format_agent_meta rustdoc: drop #432 attribution, add docs pointer
  for the running=false / status_text-stale rationale
- get_agent_meta hive/swarm comment: drop #710 attribution
- AgentServer + ManagerServer add-tool warnings: drop #511 attribution
  twice (kept the lockstep invariant)
- edit_schedule description: drop #474 + #478 cookies in user-facing
  tool text
- cancel_loose_end description: drop #250 cookie in user-facing text
- Manager allow-list block: drop the long #444/#235/#467/#472/#474/
  #478/#509 attribution roll, keep the lockstep invariant
- check_send_allowed (<parent> branch): drop #692, replace with the
  actual semantics ("falls back to operator for root agents")
- prompts/system.md: drop #474 cookie from edit_schedule line
- Cargo.toml [[bin]]: drop #598 pre-/post- split history, add docs
  pointer to docs/turn-loop.md::Harness binary shape

cargo check + 56 tests pass.
Closes #716 (last cookie hotspot).
2026-05-31 17:39:45 +02:00
iris
f8e0061f3f hive-ag3nt: scrub turn.rs cookies (#716 batch 7)
12 → 0 cookies in turn.rs (claude --print pump + stream-json +
compaction + wait_for_login). Cookie scrub only — substantive
prose (auth-failed detection, mtime-snapshot resumption,
DirSnapshot two-axis design, AuthFailed turn outcome) is already
documented in docs/turn-loop.md::The loop and the Turn outcomes
table. Rustdocs trimmed to point at the doc where useful
(AUTH_FAIL_MARKERS, wait_for_login).

- AUTH_FAIL_MARKERS doc: drop #658, #419 attribution
- write_settings inner comment: drop #555 attribution
- write_system_prompt doc: drop #519 attribution
- TurnOutcome::AuthFailed doc: drop #419 attribution
- wait_for_login doc: drop #542 attribution, point at docs
- wait_for_login inner emit_status comment: drop #563 attribution
- Test comments: drop #542 and argus #545 attribution
2026-05-31 17:29:20 +02:00
iris
55716be8fc hive-ag3nt + docs: extract web_ui prose (#716 batch 6)
docs/web-ui.md:
- New `### Listener bind` subsection — uncapped TCP retry rationale
  (replaces stale "12 tries" claim that contradicted the code) +
  pointer to gateway.md for unix-socket transition
- Expand `/api/logout` bullet with three-step teardown rationale
  (SIGINT race, selective cred-file wipe preserves --continue,
  wait_for_login resumption path)

hive-ag3nt/src/web_ui.rs:
- serve / bind_unix / bind_with_retry rustdocs trimmed to docs
  pointers (binding modes, .bound marker, retry budget all live in
  the prose now)
- AgentLink / StateSnapshot.links / agent_links rustdocs trimmed
  to single-line summaries
- post_logout / CRED_FILE_NAMES rustdocs reference docs/web-ui.md
- 13 → 0 cookies
2026-05-31 17:25:27 +02:00
iris
94c110fd5f hive-ag3nt + docs: extract harness binary shape prose (#716 batch 5)
`bin/hive.rs` carries ~15 attribution cookies (#598, #676, #692,
#693, #778, #788, #682, #688) plus structural prose about the
single-binary architecture (role-from-env), the `Surface` trait
pattern (zero-sized type tags + generic dispatch), boot wiring
(label fallback, plugin install → send_to_parent failure routing),
and turn-outcome branching (ack / requeue / wait_for_login / parent
notify).

Migrated to a new `docs/turn-loop.md::Harness binary shape`
subsection covering:

- Single-binary rationale (server-side privilege boundary on the
  broker socket means no escalation risk in shipping both wire
  surfaces in the same process).
- Three subcommands (`serve` / `mcp` / `wake`).
- Surface trait + zero-sized type tags (AgentSurface,
  ManagerSurface) — picks per-role FLAVOR / FORGE_IS_MANAGER and
  exposes the broker wire ops behind trait methods so the turn
  loop is written once.
- Boot wiring (HIVE_PORT, HIVE_LABEL fallback, plugin failures
  routed via send_to_parent, web_ui + forge_notify spawn).
- Turn outcomes table (Ok/Compacted/RateLimited/AuthFailed/Failed)
  + continue-sentinel pickup.

In-code rustdocs reduced to 1-line summaries + doc pointers;
inline cookies stripped from boot wiring + plugin install +
sentinel cleanup paths.

15 → 0 cookies in bin/hive.rs; cargo check -p hive-ag3nt passes.
2026-05-31 17:18:22 +02:00