Commit graph hyperhive/hive-sh4re
Author SHA1 Message Date
iris
5d4b62ccca fix: Diagnostics description — get_logs reads sub-agent container journal, not host journal 2026-06-02 12:53:50 +02:00
iris
2368bec634 feat(#1082): add description() to ToolGroup + Capability; expose in API + UI tooltips
- hive-sh4re: ToolGroup::description() and Capability::description() return
  short human-readable strings for each variant
- hive-c0re: ToolGroupsSnapshot and CapabilitiesSnapshot now include a
  `descriptions` map (name → description); get_capabilities now iterates
  Capability::ALL instead of hardcoding the list
- tabs.js: renderToolGroups + renderCapabilities use descriptions[name] as
  the column header title attribute (native browser tooltip on hover)
2026-06-02 12:53:50 +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
iris
c7f02993d0 chore(#1055): address argus review nits
- rename cap-cap-col → cap-col; add CSS rules for .cap-col and .cap-save-col
- drop zero-width-space replace in capability header cells (nowrap makes it a no-op)
- add Capability::ALL to hive-sh4re; validate incoming cap strings in post_capabilities
2026-06-02 11:15:33 +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
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
86a1591cfc feat(#1005): capabilities UI — per-agent tool-group table in SYST3M tab
Backend (hive-c0re/src/dashboard.rs):
  GET /api/tool-groups  — returns { groups: [...], assignments: {...} };
    groups list comes from ToolGroup::ALL so the UI needs no change when
    a new group is added (satisfies the 'no extend ui' requirement)
  POST /api/tool-groups/{agent} — accepts { groups: [...] }, calls
    set_groups() then enqueues a rebuild so the new HIVE_TOOL_GROUPS
    env var takes effect immediately

hive-sh4re/src/lib.rs:
  Added ToolGroup::ALL const (ordered slice of every group)
  Added ToolGroup::as_str() — snake_case wire name, matches serde

Frontend:
  SYST3M tab: new C4P4B1L1T13S section above K3PT ST4T3 with
    #capabilities-section placeholder
  tabs.js: fetchAndRenderCapabilities() + renderCapabilities() —
    columns are built from the groups array returned by the API;
    each row has one checkbox per group and a save button that POSTs
    and re-fetches after 800ms; agents without explicit assignments
    show a (default) label; triggered on each SYST3M tab activation
  dashboard.css: .cap-table-wrap/.cap-table/.cap-row/.cap-agent-*
    styles for the scrollable matrix table
2026-06-01 20:19:11 +02:00
damocles
6ff2103a22 rename(162): MANAGER_AGENT manager -> root 2026-06-01 17:33:09 +02:00
damocles
c9eb520e7c priv: WriteNspawnFlags takes Vec<BindMount> instead of raw flag strings 2026-06-01 17:27:14 +02:00
damocles
aa7f8e5553 priv: move shared consts to hive-sh4re; WriteNspawnFlags uses Vec<String> + per-flag validation 2026-06-01 17:27:14 +02:00
damocles
89d0937473 priv: derive flake ref from agent name; WriteNspawnFlags takes flags only 2026-06-01 17:27:14 +02:00
damocles
af23047970 fix(702): replace generic variants with specific ops in PrivRequest 2026-06-01 17:27:14 +02:00
damocles
10871381f3 fix(702): replace SystemdRunMachine with specific ReloadGatewayNginx 2026-06-01 17:27:14 +02:00
damocles
c8ea28b218 feat(#702): PrivRequest/PrivResponse wire types 2026-06-01 17:27:14 +02:00
damocles
d7fa1c5a6e feat(#702): add priv_proto module to hive-sh4re 2026-06-01 17:27:14 +02:00
damocles
1178bb2999 feat(#665): harness-internal async bash task runner (option B) 2026-06-01 13:28:31 +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
450efd5429 refactor: rename manager-only annotations to privileged in Request enum 2026-06-01 11:20:10 +02:00
damocles
4263fd25f5 fix: use rustdoc comments for manager-only variant markers 2026-06-01 11:20:10 +02:00
damocles
15617cef9a refactor: unify AgentRequest/Response + ManagerRequest/Response into Request/Response (#691) 2026-06-01 11:20:10 +02:00
damocles
36c683138d feat(#704): add <children> recipient sentinel — fan-out to direct descendants 2026-05-31 20:59:20 +02:00
iris
c058558a2a hive-sh4re/lib.rs: scrub remaining self-ref cookies (#717 batch 9 final) 2026-05-31 16:28:46 +02:00
iris
777d26812a hive-sh4re + docs: extract AgentMeta wire-shape prose (#717 batch 8) 2026-05-31 16:25:10 +02:00
iris
f3fefe7f7e hive-sh4re + docs: extract HelperEvent prose (#717 batch 7) 2026-05-31 16:25:03 +02:00
iris
a12c097044 hive-sh4re + docs: extract Ask/Answer routing prose (#717 batch 2) 2026-05-31 16:18:01 +02:00
iris
fe6f96397e hive-sh4re: trim HostRequest::SetParent rustdoc (#717 batch 6) 2026-05-31 16:14:18 +02:00
iris
18d0fbfecb hive-sh4re + docs: extract Wake-injection prose (#717 batch 5) 2026-05-31 16:14:07 +02:00
iris
22b3e542c5 hive-sh4re + docs: extract LooseEnd wire-shape prose (#717 batch 4) 2026-05-31 16:13:24 +02:00
iris
a0b15ed6a4 hive-sh4re + docs: extract Approval lifecycle prose (#717 batch 3) 2026-05-31 16:12:36 +02:00
iris
a443108be5 hive-sh4re + docs: extract broker delivery/ack/requeue prose (#717 batch 1) 2026-05-31 15:53:00 +02:00
damocles
a91cf4493f get_agent_meta: include hive_name + swarm_name in response (#710) 2026-05-31 12:50:19 +02:00
damocles
7142e95c8f broker: resolve <parent> sentinel to topology parent at send time (#692) 2026-05-31 11:39:27 +02:00
iris
73684fb00a rust+nix: load static assets at runtime, drop build.rs (#555)
Cuts every `include_bytes!`/`include_str!` of a non-rust path in
the workspace over to runtime file loads from `$HIVE_ASSETS_DIR`
(the `hyperhive-assets` derivation introduced in the previous
commit). After this commit the rust derivation has no compile-time
dependency on `branding/*` or `hive-ag3nt/prompts/*` anymore.

Call-site flips:

- `hive-c0re/src/forge.rs::CORE_AVATAR_PNG` /
  `CONFIG_ORG_AVATAR_PNG`: were `include_bytes!` of
  `branding/hyperhive.png` and `$OUT_DIR/agent-configs.png`. Now
  `ensure_core_avatar` / `ensure_config_org_avatar` `tokio::fs::read`
  via `hive_sh4re::assets::{core_avatar_png, config_org_avatar_png}`
  at startup. The `agent-configs.png` is now rendered by the
  `hyperhive-assets` derivation's rsvg-convert step (was
  `hive-c0re/build.rs` + librsvg on the rust derivation's
  nativeBuildInputs — both gone in the next commit).
- `hive-ag3nt/src/prompt.rs::TEMPLATE`: `render` now takes the
  template as an argument; `write_system_prompt` reads it once from
  `$HIVE_ASSETS_DIR/prompts/system.md` before calling render. The
  test module still `include_str!`s the production template so
  `cargo test --workspace` doesn't need `HIVE_ASSETS_DIR` set —
  this is the only remaining compile-time reference to the file
  from the rust workspace, gated to `#[cfg(test)]`.
- `hive-ag3nt/src/turn.rs::CLAUDE_SETTINGS`: was `include_str!`'d
  and written via `tokio::fs::write`; now `tokio::fs::copy` from
  `$HIVE_ASSETS_DIR/prompts/claude-settings.json` into the
  per-agent socket dir.
- `hive-ag3nt/src/web_ui.rs::DEFAULT_ICON`: was `include_str!`'d;
  now read on-demand from `$HIVE_ASSETS_DIR/branding/hyperhive.svg`
  inside `serve_icon`. Falls back to an empty body if missing so
  the endpoint never panics on a misconfigured container (matches
  the existing "per-agent icon.svg override" fallthrough).

`HIVE_ASSETS_DIR` wiring:

- Inside containers: `nix/templates/harness-base.nix`
  `environment.variables` sets it to
  `${pkgs.hyperhive-assets}/share/hyperhive` (resolved through
  the default overlay applied in `mkContainer`). Verified by
  building `agent-base-toplevel` and grepping the resulting
  `/etc/set-environment`.
- Host-side: `nix/modules/hive-c0re.nix` adds an `assets` option
  defaulting to `hyperhive.packages.${system}.assets`, threaded
  in from the flake's nixosModules wiring, and sets the same env
  var on the `hive-c0re` systemd unit so the daemon's
  `forge::ensure_*_avatar` startup hooks find the PNGs.

`hive-c0re/build.rs` deleted entirely; `[package].build` removed
from `hive-c0re/Cargo.toml`; rsvg-convert dependency lives in the
assets derivation only.

Validated: `nix build .#default .#checks.x86_64-linux.clippy
.#agent-base-toplevel .#manager-toplevel --fallback` all succeed.
`/etc/set-environment` in the toplevel shows
`HIVE_ASSETS_DIR="/nix/store/.../hyperhive-assets-0.1.0/share/hyperhive"`.
2026-05-29 12:59:48 +02:00
iris
9ed58ab96d clippy: fix lints that crane's cargoClippy properly enforces (#538)
The naersk → crane swap in the parent commit flips clippy from
silently passing to actually failing on `-D warnings` (naersk's
`mode = "clippy"` mangled the `--` separator so the deny never took
effect). This commit clears the surfaced lints so the workspace
builds clean under the new enforcement — every fix is mechanical and
preserves behaviour. Tests still pass (160 across the workspace).

Auto-fixes via `cargo clippy --fix`:
- `doc_markdown` (19 sites): bare identifiers in doc comments
  wrapped in backticks
- `format_in_format_args`, `explicit_into_iter_loop`,
  `redundant_closure_for_method_calls`, `useless_conversion`, and
  a few more — mechanical rewrites of the kind cargo can apply
  safely.

Hand-fixed:
- `match_same_arms` (forge_notify::is_atx_heading): two arms returning
  `true` collapsed into a single `matches!` pattern.
- `cast_sign_loss` + `format_push_string` (mcp.rs status formatter):
  guarded `i64 → u64` through `u64::try_from(…).unwrap_or(0)` (status
  timestamps are always positive in practice; clamp the skew edge to
  0) and swapped `out.push_str(&format!(…))` for `write!` into the
  buffer with an infallible-writer `let _ =`.
- `doc_lazy_continuation` in turn.rs + manager_server.rs + sh4re/lib.rs:
  doc paragraphs that the markdown parser was treating as list-item
  continuations got either a separating blank line or a `/`-for-`+`
  word swap so the parser stops seeing a list.
- `unused_async` (manager_server::handle_request_schedule_prompt):
  function has no `.await`; dropped the `async` and its `.await` call
  site.
- `needless_pass_by_value` (scheduled_prompts::submit): take
  `&NewSchedule` instead of moving the struct in; updated two prod
  callers and eight test sites to pass references.
- `type_complexity` (approvals::mark_cancelled): hoisted the
  7-tuple SELECT row shape into a `type CancelLookupRow = (…);` alias.

Allow-with-reason for intentional patterns:
- `option_option` (6 sites across dashboard / scheduled_prompts /
  manager_server): `Option<Option<T>>` carries three-state PATCH
  semantics (missing key = leave alone, `Some(None)` = clear,
  `Some(Some(v))` = set). Collapsing to `Option<T>` loses the
  "clear" state.
- `dead_code` (rebuild_queue::QueueKind::Destroy /
  QueueSource::CrashRecover; topology::parent_of / default_seed):
  wire-shape variants + API surfaces kept for the upcoming features
  (#361 follow-ups, future `Destroy` queue routing, crash-recovery
  path). Allowed at the variant / function level with the rationale
  in `reason = "…"`.
- `too_many_lines` on three specific call-sites: a 117-line
  exhaustive-variant test (dashboard_events::kind_tag_matches_…),
  the meta-flake string template renderer
  (meta::render_flake_with_lookup), and the notification poll loop
  (forge_notify::poll_once) — splitting any of them would just hide
  the contiguous shape they exist to keep visible.

`nix flake check` formatting target is still broken on main itself
(pre-existing nixfmt drift across ~28 files unrelated to this PR);
left alone here so the scope stays "crane port + lints the port
exposed" and the operator's review doesn't have to triage drive-by
nixfmt churn.
2026-05-29 01:45:48 +02:00
iris
4b6c733afb flake: replace naersk with crane (#538)
Framework swap, no public API change.

- naersk input → crane (`github:ipetkov/crane`); crane is stateless, no
  nixpkgs.follows needed.
- `forAllSystems` exposes `craneLib = crane.mkLib pkgs`,
  `cargoArtifacts = craneLib.buildDepsOnly` (built once, reused), and
  a shared `nativeBuildInputs = [ pkgs.librsvg pkgs.git ]` consumed by
  buildDepsOnly + buildPackage + cargoClippy so the three derivations
  see the same toolchain shape.
- `packages.default = craneLib.buildPackage` (was naersk-lib.buildPackage)
  with explicit `pname = "hyperhive-workspace"; version = "0.1.0";` —
  the virtual workspace Cargo.toml has no [package].name so crane
  needs the hint.
- `checks.clippy = craneLib.cargoClippy` (was naersk + overrideAttrs
  hack). Crane parses `cargoClippyExtraArgs = "--workspace --all-targets
  -- -D warnings"` correctly; naersk's `mode = "clippy"` used to mangle
  the `--` separator which is why the old wiring went through
  overrideAttrs. The whole hack — including `doCheck = false`,
  `copyTarget = false`, and the swapped buildPhase/installPhase — is
  now gone.
- librsvg native dep (#424) preserved on all three derivations. Added
  pkgs.git too — naersk auto-included it; crane is more minimal, so
  hive-c0re's `lifecycle::tests::setup_proposed_*` (which shell out to
  `git init`+commit) need it explicit to pass under `cargo test` in
  the sandbox.
- build.rs + hive-c0re/Cargo.toml comments updated from "naersk
  derivation" to "crane derivation".
- 3 doc-list-indentation lints in hive-sh4re/src/lib.rs cleaned up
  (replaced `+`-at-line-start with `and`/`/` so doc continuations
  don't trigger `clippy::doc_lazy_continuation`).

Validated locally: `nix build .#default --fallback` succeeds, all
117 tests pass, all four bins in `result/bin/`.
2026-05-29 01:45:48 +02:00
damocles
dca62fda40 harness: remove deprecated manager-side request_spawn surface (closes #442) 2026-05-27 18:58:04 +02:00
damocles
c1f27e3b7b approvals: manager can withdraw pending approvals (closes #250) 2026-05-27 12:48:30 +02:00
damocles
5456377622 topology: operator-driven move-agent via set_parent (#486) 2026-05-26 19:30:46 +02:00
damocles
99bf4d635d scheduled prompts: add/remove targets on edit (#474 fast-follow) 2026-05-26 17:06:48 +02:00
damocles
9fee1a1e56 scheduled prompts: edit existing schedule (closes #474) 2026-05-26 16:07:13 +02:00
damocles
3cd9240594 scheduled prompts: fire-now operator + manager surfaces (closes #467) 2026-05-26 15:55:35 +02:00
damocles
aa7d8d9c9a c0re: schedule_prompt approval kind + worker + manager surface (#444 step 2) 2026-05-26 01:27:25 +02:00
iris
7b4917b256 container_view: clear live-only fields when stopped (#432)
per mara's review on #433, move the gating from the dashboard into
the host so a stopped container's stale on-disk state (rate_limited
sentinel, hyperhive-needs-login, last-turn-stats row, status blob)
never reaches the wire in the first place. when build_all sees
is_running == false:

  - needs_login → false
  - ctx_tokens / context_window_tokens → None
  - rate_limited → false
  - status_text / status_set_at → None

static / declared fields (extra_links, deployed_sha,
pending_reminders, needs_update, parent) stay populated regardless
of run state.

extend AgentMeta (both AgentResponse + ManagerResponse) with a
`running: bool` field so get_agent_meta callers can tell whether
the target is up — answers the second half of #432 ("agent meta
should probably show the info that it is not running as well").
read_agent_status_live wraps the existing read_agent_status with
the same is_running gate so the manager/agent socket handlers don't
have to know about sentinel semantics.

format_agent_meta now prints a `running: yes|no` line so claude
sees the run state in plain text alongside hyperhive_rev.

frontend follow-up in the same commit: drop the redundant
`c.running &&` guards on ctx_tokens / status_text in
renderContainers — the backend now guarantees those fields are
absent when the container is stopped, so the existing
truthy-check is sufficient. the `■ not running` badge + icon /
links fetch short-circuits stay (those are pure presentation /
network-noise wins the backend can't address).
2026-05-25 23:35:03 +02:00
damocles
73871f18c3 set_status: consolidate whoami into get_agent_meta with optional name 2026-05-23 11:32:33 +02:00
damocles
77fdaf0d1e set_status: add get_agent_meta tool for inter-agent status queries 2026-05-23 11:32:33 +02:00
damocles
8e8e8a771f set_status: add status_set_at timestamp (mtime of status file) 2026-05-23 11:32:33 +02:00