diff --git a/frontend/packages/dashboard/src/stream-worker.js b/frontend/packages/dashboard/src/stream-worker.js index 166cc7eb..d40ca7b3 100644 --- a/frontend/packages/dashboard/src/stream-worker.js +++ b/frontend/packages/dashboard/src/stream-worker.js @@ -1,8 +1,7 @@ // SharedWorker that holds ONE EventSource per stream URL and fans // every server-sent event out to every connected tab via MessagePort. // -// Problem this solves (#448 — mara: "firefox disconnects bc of too -// many tabs"): every dashboard / agent tab opens its own +// Problem this solves: every dashboard / agent tab opens its own // `EventSource('/dashboard/stream')`. Browsers cap concurrent // connections per host (~6), and Firefox throttles / disconnects // background tabs when many are open. The result: tabs silently @@ -29,7 +28,7 @@ // re-sync after a reconnect gap. // { kind: 'message', url: '...', data: '' } // { kind: 'error', url: '...' } relayed from EventSource.onerror. -// { kind: 'ping' } #515: heartbeat — fired every +// { kind: 'ping' } heartbeat — fired every // PING_INTERVAL_MS to every // connected port. The client's // watchdog uses these as diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index 39dbd619..e62183d9 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -475,7 +475,7 @@ window.marked = marked; // `/agent//` URLs instead of the direct `http://:/` // TCP fallback — the gateway proxies the prefix to the per-agent // harness (TCP via `agent-ports.json` or unix-domain via - // `agent-sockets.json` per #784 / #815). See + // `agent-sockets.json`). See // `docs/web-ui.md::Container row` + `docs/gateway.md::Vhost map`. const gatewayLinks = !!(s && s.gateway_enabled); const ul = el('ul', { class: 'containers' }); diff --git a/hive-c0re/src/actions.rs b/hive-c0re/src/actions.rs index 9e9726f3..ca41dfe9 100644 --- a/hive-c0re/src/actions.rs +++ b/hive-c0re/src/actions.rs @@ -15,8 +15,7 @@ use crate::lifecycle::{self, MANAGER_NAME}; /// either runs the work inline (`InitConfig`, sub-second git ops) or /// enqueues it into `rebuild_queue` so the dashboard POST returns /// immediately while the long-running pipeline runs off-thread -/// (closes #436 — operator no longer eats a 30-90s spinner on -/// `ApplyCommit`). +/// (operator no longer blocks on a 30-90s spinner for `ApplyCommit`). /// /// Dispatch: /// - `ApplyCommit` → `QueueKind::Rebuild` (~30-90s wall time) @@ -103,9 +102,9 @@ pub async fn approve(coord: Arc, id: i64) -> Result<()> { } /// Worker entry point for `ApprovalKind::ApplyCommit` queue entries. -/// Re-fetches the approval row, runs the commit pipeline (same -/// shape as the pre-#436 inline path), and fires `ApprovalResolved` -/// + the lifecycle event (`Rebuilt` / `Spawned` for first-spawn). +/// Re-fetches the approval row, runs the commit pipeline, and fires +/// `ApprovalResolved` + the lifecycle event (`Rebuilt` / `Spawned` +/// for first-spawn). pub async fn run_approval_apply_commit( coord: &Arc, queue_entry_id: Option, diff --git a/hive-c0re/src/agent_sockets.rs b/hive-c0re/src/agent_sockets.rs index 30a2aa09..4ea40ed1 100644 --- a/hive-c0re/src/agent_sockets.rs +++ b/hive-c0re/src/agent_sockets.rs @@ -38,7 +38,7 @@ pub const SOCKET_FILENAME: &str = "web.sock"; /// sub-agent that hasn't flipped the option yet. /// /// Renamed from `.bound` (legacy) to match the `hyperhive-` prefix -/// convention for all harness-written state files (#838). `build_map` +/// convention for all harness-written state files. `build_map` /// checks both names during the transition window so existing containers /// don't lose gateway routing before their next rebuild. pub const READY_MARKER: &str = "hyperhive-socket-bound"; diff --git a/hive-c0re/src/broker.rs b/hive-c0re/src/broker.rs index 5387112a..0d16b1a6 100644 --- a/hive-c0re/src/broker.rs +++ b/hive-c0re/src/broker.rs @@ -526,8 +526,8 @@ impl Broker { /// ids the harness pulled via `recv_batch`) and `requeue_inflight` /// (which puts inflight-but-unacked rows BACK on the queue). This /// is the destructive "drain everything for this agent" path the - /// dashboard surfaces as the side-panel "mark all read" button - /// (#559). Backs `POST /api/agent/{name}/mark-all-read`. + /// dashboard surfaces as the side-panel "mark all read" button. + /// Backs `POST /api/agent/{name}/mark-all-read`. pub fn mark_all_read(&self, recipient: &str) -> Result { let mut inflight = self.inflight.lock().unwrap(); let conn = self.conn.lock().unwrap(); diff --git a/hive-c0re/src/dashboard_events.rs b/hive-c0re/src/dashboard_events.rs index fd05b19d..60e89795 100644 --- a/hive-c0re/src/dashboard_events.rs +++ b/hive-c0re/src/dashboard_events.rs @@ -178,7 +178,7 @@ pub enum DashboardEvent { /// immediately and runs the `nix flake update` + agent-rebuild /// ripple in a background task — this event lets the META INPUTS /// panel show a disabled "updating…" state for that whole window - /// instead of looking idle (issue #259). Emitted by + /// instead of looking idle. Emitted by /// `Coordinator::meta_update_guard` / `MetaUpdateGuard::drop` only /// when the active-run count crosses 0, so concurrent updates flip /// the flag exactly once. @@ -198,8 +198,8 @@ impl DashboardEvent { /// Snake-case identifier matching this variant's serde `tag` /// (e.g. `Sent` → `"sent"`, `ContainerStateChanged` → /// `"container_state_changed"`). Lets `/dashboard/stream`'s - /// `?kinds=` filter (#408) decide whether to forward a frame - /// without paying the JSON-serialise cost first. + /// `?kinds=` filter decide whether to forward a frame without + /// paying the JSON-serialise cost first. /// /// Keep in sync with `#[serde(rename_all = "snake_case", tag = /// "kind")]` on `DashboardEvent` — if a new variant lands above, diff --git a/hive-c0re/src/flake_check.rs b/hive-c0re/src/flake_check.rs index 75e22413..6771a013 100644 --- a/hive-c0re/src/flake_check.rs +++ b/hive-c0re/src/flake_check.rs @@ -1,4 +1,4 @@ -//! Pre-apply validation for agent `flake.lock` files (closes part of #317). +//! Pre-apply validation for agent `flake.lock` files. //! //! Every `request_apply_commit` lands a `proposal/` tag in the //! agent's applied repo before the operator sees the approval. We @@ -8,11 +8,10 @@ //! directive in `flake.nix` and would inflate meta's lock with //! duplicates after deploy. //! -//! Per mara's scope note on #317 (comment 4189): the check runs on -//! the agent repo, not meta, and catches *new* violations only. -//! Existing agents whose lock already has duplicates are out of -//! scope here and get a coordinated config-change pass via the -//! manager instead. +//! The check runs on the agent repo, not meta, and catches *new* +//! violations only. Existing agents whose lock already has duplicates +//! are out of scope here and get a coordinated config-change pass via +//! the manager instead. use std::collections::BTreeMap; use std::fmt::Write as _; diff --git a/hive-c0re/src/lib.rs b/hive-c0re/src/lib.rs index 2c1f808e..c11c352b 100644 --- a/hive-c0re/src/lib.rs +++ b/hive-c0re/src/lib.rs @@ -6,7 +6,7 @@ //! sockets, background sweepers. `hivectl` (sibling bin under //! `src/bin/hivectl.rs`) reuses a thin subset (`forge`, `matrix`, //! `lifecycle`) to expose host-side administration verbs — manually -//! provisioning forge / matrix users for an agent, etc. (#655). +//! provisioning forge / matrix users for an agent, etc. //! //! Every module is re-exported `pub` so anything in the crate is //! addressable from either binary; the lib doesn't have a curated diff --git a/hive-c0re/src/limits.rs b/hive-c0re/src/limits.rs index e650971f..06b68a03 100644 --- a/hive-c0re/src/limits.rs +++ b/hive-c0re/src/limits.rs @@ -50,7 +50,7 @@ pub fn check_size(label: &str, body: &str) -> Result<(), String> { /// scrolling chunk. pub const STATUS_MAX_CHARS: usize = 200; -/// Validate a `set_status` payload (#720). Single-line + bounded so +/// Validate a `set_status` payload. Single-line + bounded so /// callers can't dump multi-paragraph session reports into the /// dashboard chip. Whitespace trim is done by the caller before the /// store-to-disk step — we run validation on the trimmed form so @@ -70,8 +70,7 @@ pub fn check_status_text(text: &str) -> Result<(), String> { return Ok(()); } // Newline / carriage-return: status is a single-line chip on the - // dashboard. A multi-line argus session report is the canonical - // failure mode from #720. + // dashboard. Multi-line session reports should go to a state file. if trimmed.contains('\n') || trimmed.contains('\r') { return Err( "set_status text must be a single line — write multi-line context to \ diff --git a/hive-c0re/src/meta.rs b/hive-c0re/src/meta.rs index 4d08acd9..43fe7bf3 100644 --- a/hive-c0re/src/meta.rs +++ b/hive-c0re/src/meta.rs @@ -118,7 +118,7 @@ pub async fn sync_agents( // the gateway picks up at runtime without needing a // nixos-rebuild. The gateway container bind-mounts // /var/lib/hyperhive/ and a systemd path unit fires - // `nginx -s reload` when this file changes (#869). Same + // `nginx -s reload` when this file changes. Same // best-effort + non-fatal shape. if let Err(e) = crate::gateway_nginx::write(&agent_names) { tracing::warn!(error = ?e, "gateway_nginx::write failed (non-fatal)"); diff --git a/hive-c0re/src/server.rs b/hive-c0re/src/server.rs index c4d7d2cc..1887fdde 100644 --- a/hive-c0re/src/server.rs +++ b/hive-c0re/src/server.rs @@ -189,7 +189,7 @@ async fn dispatch(req: &HostRequest, coord: Arc) -> HostResponse { HostRequest::SetParent { child, new_parent } => { tracing::info!(%child, ?new_parent, "set_parent"); // `reparent_with_notify` wraps `topology::set_parent` - // with the three notification messages (#743) + the + // with the three notification messages + the // ContainerView rescan. Idempotent same-parent calls // skip both the messages and the disk write per the // topology fast-path. diff --git a/nix/docs/default.nix b/nix/docs/default.nix index 0dec54d7..ca4f2461 100644 --- a/nix/docs/default.nix +++ b/nix/docs/default.nix @@ -68,7 +68,7 @@ let # Filter to a set of top-level subtree roots — keeps the rendered docs # focused on hyperhive's surface instead of NixOS's 10k+ default # options. Root choice matters: see docs/gotchas.md::Nix options - # reference for the post-#615 services.hyperhive consolidation history. + # reference for the services.hyperhive consolidation history. pickSubtrees = options: roots: let diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index df54426f..126dcc04 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -75,7 +75,7 @@ in canonical readable identity. Exposed to agents as `HYPERHIVE_HIVE_NAME`; surfaced in the dashboard chrome and per-agent system prompt when set. Null falls back to the - pre-#701 behaviour (chrome shows the domain, prompt doesn't + default behaviour (chrome shows the domain, prompt doesn't mention a hive name). ''; }; @@ -141,7 +141,7 @@ in description = '' hyperhive workspace package. Provides `/bin/hive-c0re` (coordinator daemon + admin-socket CLI) and `/bin/hivectl` - (operator-facing host CLI for ad-hoc administration; #655). + (operator-facing host CLI for ad-hoc administration). ''; }; frontend = lib.mkOption { diff --git a/nix/modules/hive-forge.nix b/nix/modules/hive-forge.nix index d71c2285..b4c1535e 100644 --- a/nix/modules/hive-forge.nix +++ b/nix/modules/hive-forge.nix @@ -10,8 +10,7 @@ let hyperhiveDomain = config.services.hyperhive.domain; # ROOT_URL forgejo advertises in clone links + outbound URLs. When - # served behind the gateway (#749 — mara verdict at issue:9609, - # sub-domain over sub-path), `cfg.domain` doubles as both the + # served behind the gateway, `cfg.domain` doubles as both the # forgejo `DOMAIN` setting AND the gateway vhost server-name, so # ROOT_URL just uses it directly (drops the port suffix when the # gateway is on the canonical port 80). When direct (gateway off @@ -83,18 +82,16 @@ in Public hostname for the forge. Doubles as both the forgejo `DOMAIN` setting (clone URLs forgejo advertises) AND the gateway vhost server-name when `behindGateway = true` - (#749, mara verdict at issue:9609 — sub-domain over sub-path). + (sub-domain routing — see `docs/gateway.md`). Defaults to `forge.''${services.hyperhive.domain}` when the hive-domain is set (idiomatic sub-domain shape — `forge` labelled under the hive's bare domain), falling back to - `localhost` otherwise (pre-#749 direct-on-port behaviour). + `localhost` otherwise (direct-on-port behaviour). Set to a full hostname (`git.example.com`, `forge.internal.lan`, etc.) for a bespoke vhost shape — the - full domain goes here, no separate sub-domain-label option - (mara on #754:9684 — "specify full forge domain in options - instead"). + full domain goes here, no separate sub-domain-label option. ''; }; @@ -120,8 +117,7 @@ in description = '' Serve forgejo through the hive-gateway nginx as a sub-domain vhost (`server_name = cfg.domain`) instead of directly on - `httpPort` (#749, mara verdict at issue:9609 — sub-domain - over sub-path). + `httpPort` (sub-domain routing — see `docs/gateway.md`). When `true`: - The gateway adds a `server { server_name = ''${cfg.domain}; }` @@ -137,11 +133,10 @@ in gateway is running (e.g. an external git client that doesn't traverse the gateway). - The mara-call on #749:9609 picks sub-domain over sub-path for - forge + matrix (both are external standard apps with sub-domain- - native config defaults). Per-agent UIs stay on sub-path - (`/agent//`) because they're hyperhive-internal + - already base-path-aware via #731. + Sub-domain routing is the preferred shape for forge + matrix + (both are external standard apps with sub-domain-native config + defaults). Per-agent UIs stay on sub-path (`/agent//`) + because they're hyperhive-internal + already base-path-aware. ''; }; @@ -171,18 +166,18 @@ in example = true; description = '' Open `httpPort` + `sshPort` in the host firewall. Off by - default (#651, secure-by-default): the forge is reachable - from the host + every agent container via `localhost` either - way (shared netns), so the firewall opens only matter for - access from outside the host. Flip to `true` when you want - the operator's browser / external git clients to hit the - forge directly. (The container shares host netns, so this - is the only firewall layer that matters.) + default (secure-by-default): the forge is reachable from the + host + every agent container via `localhost` either way + (shared netns), so the firewall opens only matter for access + from outside the host. Flip to `true` when you want the + operator's browser / external git clients to hit the forge + directly. (The container shares host netns, so this is the + only firewall layer that matters.) - **Breaking change as of #651**: this used to default to - `true`. If you relied on the old default for external - reach, add `services.hyperhive.forge.openFirewall = true;` - to your host config before rebuilding. + **Breaking change**: this used to default to `true`. If you + relied on the old default for external reach, add + `services.hyperhive.forge.openFirewall = true;` to your host + config before rebuilding. ''; }; }; diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index f0480736..23c5ab81 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -117,20 +117,19 @@ in (`@argus:`) and room ID minted on this homeserver. CRITICAL: must be stable from day one because it's embedded irrevocably in the identifiers. Defaults to - `services.hyperhive.domain` (the bare hive domain — per mara - on #660). Combined with the `.well-known/matrix/{client,server}` - routes the hive-gateway serves at that domain (also #660), - clients auto-discover the actual matrix endpoint without - needing a subdomain. Override here only if you need a - different server_name shape (e.g. `matrix.` if you - want the subdomain split, or `chat.example.org` for a - bespoke hostname). + `services.hyperhive.domain` (the bare hive domain). Combined + with the `.well-known/matrix/{client,server}` routes the + hive-gateway serves at that domain, clients auto-discover the + actual matrix endpoint without needing a subdomain. Override + here only if you need a different server_name shape (e.g. + `matrix.` if you want the subdomain split, or + `chat.example.org` for a bespoke hostname). - **Breaking change as of #660**: this used to default to + **Breaking change**: this used to default to `matrix.''${services.hyperhive.domain}`. matrix IDs embed the server_name irrevocably, so existing homeservers must set `services.hyperhive.matrix.serverName = "matrix.''${services.hyperhive.domain}";` - explicitly to preserve their pre-#660 user / room IDs + explicitly to preserve their existing user / room IDs before rebuilding. ''; }; @@ -160,15 +159,15 @@ in description = '' Public hostname for the matrix homeserver behind the gateway. Defaults to `matrix.''${services.hyperhive.domain}` (sub-domain - shape per mara on #749:9609). Set to `null` to skip the gateway - vhost (tuwunel stays direct on `httpPort`). See + shape — see `docs/gateway.md`). Set to `null` to skip the + gateway vhost (tuwunel stays direct on `httpPort`). See `docs/gateway.md` for the vhost map + matrix discovery flow, and the federation port-8448 caveat at the bottom of that doc. Note: `gatewayHost` is the API listener hostname (where nginx proxies `/_matrix/*`); `serverName` is the matrix-identifier - domain embedded irrevocably in user/room IDs (per #660 - default = bare hive-domain). The two are distinct. + domain embedded irrevocably in user/room IDs (default = bare + hive-domain). The two are distinct. ''; }; @@ -177,18 +176,18 @@ in default = false; example = true; description = '' - Open `httpPort` in the host firewall. Off by default (#651, - secure-by-default): the homeserver is reachable from the + Open `httpPort` in the host firewall. Off by default + (secure-by-default): the homeserver is reachable from the host + every agent container via `localhost` either way - (shared netns), so the firewall open only matters for - access from outside the host. Flip to `true` when announcing - the homeserver to other hives or when an external matrix - client needs to reach the client-server API directly. + (shared netns), so the firewall open only matters for access + from outside the host. Flip to `true` when announcing the + homeserver to other hives or when an external matrix client + needs to reach the client-server API directly. - **Breaking change as of #651**: this used to default to - `true`. If you relied on the old default for external reach, - add `services.hyperhive.matrix.openFirewall = true;` to - your host config before rebuilding. + **Breaking change**: this used to default to `true`. If you + relied on the old default for external reach, add + `services.hyperhive.matrix.openFirewall = true;` to your host + config before rebuilding. Note: federation (the matrix-spec well-known port 8448) is intentionally not opened here. tuwunel serves the federation @@ -260,8 +259,8 @@ in type = lib.types.package; default = fluffychat-web-fixed; defaultText = lib.literalMD '' - `pkgs.fluffychat-web` + #685 `postInstall` patch (adds the - three files `flutter341.buildFlutterApplication` skips). + `pkgs.fluffychat-web` with a `postInstall` patch that adds + the three files `flutter341.buildFlutterApplication` skips. ''; description = '' Static web client dist served at `matrix./`. Override @@ -275,9 +274,9 @@ in }; config = lib.mkIf cfg.enable { - # serverName must exist (mara on #548 — irrevocably embedded in - # user/room IDs); gatewayHost may not be "" (argus 🟡 on #764 — - # same footgun as forge.domain). docs/matrix.md::Assertion + # serverName must exist (irrevocably embedded in user/room IDs); + # gatewayHost may not be "" (same footgun as forge.domain — + # nginx rejects an empty server_name). docs/matrix.md::Assertion # rationale. assertions = [ { @@ -307,9 +306,9 @@ in } ]; - # Activation-time token generation (argus #565: the bind-mount - # would otherwise hand tuwunel an empty file on first boot and - # break every registration until restart). Idempotent; + # Activation-time token generation — without this the bind-mount + # would hand tuwunel an empty file on first boot and break every + # registration until restart. Idempotent; # docs/matrix.md::Provisioning flow. system.activationScripts.hive-matrix-register-token = lib.stringAfter [ "var" ] '' tokenFile=${lib.escapeShellArg (toString cfg.registrationTokenFile)} @@ -358,13 +357,13 @@ in # LoadCredential below copies the host file into a # 0400 dynamic-user-owned path; tuwunel reads from there. registration_token_file = "/run/credentials/tuwunel.service/registration_token"; - # E2EE disabled in initial rollout (#548); re-enable at #551. + # E2EE disabled in initial rollout; tracked in the issue tracker. allow_encryption = false; }; }; # Keeps DynamicUser=true + PrivateUsers=true intact — no - # host-side chown :tuwunel / GID-pin gymnastics needed (#644 / - # iris on 8043). See `man systemd.exec` → LoadCredential. + # host-side chown :tuwunel / GID-pin gymnastics needed. + # See `man systemd.exec` → LoadCredential. systemd.services.tuwunel.serviceConfig.LoadCredential = [ "registration_token:${toString cfg.registrationTokenFile}" ]; diff --git a/nix/packages/hive-forge-tools.nix b/nix/packages/hive-forge-tools.nix index e8c28f09..7079d857 100644 --- a/nix/packages/hive-forge-tools.nix +++ b/nix/packages/hive-forge-tools.nix @@ -1,5 +1,5 @@ { pkgs, lib }: -# hive-forge — Forgejo CLI wrapper for hyperhive (closes #280). +# hive-forge — Forgejo CLI wrapper for hyperhive. # # Previously a ~600-line bash script. Rewritten as a proper Rust # binary in `/hive-forge` so we get: @@ -7,8 +7,7 @@ # reading the case statement), # - one reqwest client with consistent error surfaces (no more # `curl --fail-with-body` repeated per verb), -# - sane shell quoting (no more HEREDOC-eaten-by-positional traps -# like #379), +# - sane shell quoting (no more HEREDOC-eaten-by-positional traps), # - and a single test surface. # # This Nix file is now a thin extractor: it pulls just the diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index b14ae3ff..9d098608 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -10,8 +10,8 @@ ... }: let - # Agent user metadata (#658). `userName` defaults to `"agent"` when - # the meta-flake doesn't inject the per-agent override (stand-alone + # Agent user metadata. `userName` defaults to `"agent"` when the + # meta-flake doesn't inject the per-agent override (stand-alone # `nixos-rebuild` against `nixosConfigurations.agent-base` works # without erroring on a missing per-agent name). `homeDir` derives # from `userName` to keep them coupled. @@ -29,7 +29,7 @@ in # only opts in from its own `agent.nix`. imports = [ ./weston-vnc.nix ]; - # Per-agent unix user the harness + co-process daemons run as (#658). + # Per-agent unix user the harness + co-process daemons run as. # Defaults to `"agent"` so a standalone evaluation (e.g. # `nix flake check` against `nixosConfigurations.agent-base`) builds # cleanly; the meta-flake's per-agent module rebinds this to the @@ -83,22 +83,17 @@ in When `true`, set `HIVE_WEB_SOCKET=/run/hive-agent/${userName}/web.sock` on the harness service env, which makes `web_ui::serve` bind a `UnixListener` at that path instead of the legacy TCP listener - on `HIVE_PORT`. Closes the third hop of the #784 rollout: PR - #800 added the harness-side opt-in, #809 / #813 added the c0re - bind-mount + JSON-map plumbing, this is the per-agent flip - that activates the unix-domain path. + on `HIVE_PORT`. Default `false` so an agent's web UI keeps binding TCP until the per-agent flip is explicit. Rollout shape: - 1. flip one canary agent (atlas volunteered) to `true` via its - `agent.nix` once #813 lands; + 1. flip one canary agent to `true` via its `agent.nix`; 2. validate the gateway's `proxy_pass http://unix:.../web.sock` - end-to-end against that canary (atlas's step 3); + end-to-end against that canary; 3. flip remaining agents per-agent as the gateway side soaks; - 4. eventually drop this option once every agent's on unix + - atlas's gateway is the only path — step 4 of #784 drops the - harness's TCP fallback at the same time. + 4. eventually drop this option once every agent is on unix and + the TCP fallback is removed from the harness. Sub-agent-only by design: the manager's UI serves at `/` via the c0re dashboard upstream, not via `/agent//`, so this @@ -128,9 +123,6 @@ in it's exposed so a standalone `nixos-rebuild` against `nixosConfigurations.manager` keeps working without the meta-flake wrapper around it. - - Closes #671: harness + manager templates merged into a - single `harness-base.nix` driven by this option. ''; }; @@ -267,8 +259,8 @@ in type = lib.types.bool; default = true; description = '' - Enable per-agent matrix integration via `hive-matrix-mcp` - (#548 phase 3). When true (the default), the harness: + Enable per-agent matrix integration via `hive-matrix-mcp`. + When true (the default), the harness: - runs `hive-matrix-daemon` as a systemd unit that holds a matrix-sdk Client + sync against the homeserver at @@ -276,8 +268,8 @@ in in-host tuwunel from `nix/modules/hive-matrix.nix`). The daemon auto-skips when `/matrix-token` is missing, and a `systemd.paths` watcher restarts it the moment - hive-c0re provisions the token (mirrors `matrix-avatar-sync` - shape from #571). + hive-c0re provisions the token (same path-trigger shape + as `matrix-avatar-sync`). - exposes the matrix tool surface (send_message, send_dm, send_reaction, send_reply, mark_read, list_rooms, list_room_members, read_room) to claude via an auto-injected @@ -577,9 +569,8 @@ in # all contributions across modules into one file. Loaded via # `$BASH_ENV` for non-interactive shells (claude's `Bash` tool # runs `bash -c`) and via `programs.bash.interactiveShellInit` - # for interactive shells. Generic by design (mara on #779) so - # future hooks don't need to either rename this file or invent - # a parallel dispatcher. + # for interactive shells. Generic by design so future hooks + # don't need to rename this file or invent a parallel dispatcher. options.hyperhive._bashEnvFragments = lib.mkOption { type = lib.types.lines; default = ""; @@ -606,7 +597,7 @@ in anything else) invokes `cargo` inside this container. Saves tokens + context — the verbose default output floods the response window with per-crate progress lines that - carry no signal beyond the warning/error summary (#777). + carry no signal beyond the warning/error summary. Implementation: contributes a `cargo` shell function to `/etc/hyperhive/bash-env.sh` (see `hyperhive._bashEnvFragments`). @@ -742,10 +733,10 @@ in } ]; - # Post-#658 first-boot migration to the per-agent unix user — - # creates the home dir, chowns the bind-mounted state + - # `~/.claude/`, and (marker-guarded) moves any leftover - # `/root/.claude` content from the pre-#658 root-run shape. See + # First-boot migration to the per-agent unix user — creates the + # home dir, chowns the bind-mounted state + `~/.claude/`, and + # (marker-guarded) moves any leftover `/root/.claude` content + # from the previous root-run shape. See # `docs/persistence.md::First-boot agent-user migration` for the # step-by-step rationale; this script implements it. system.activationScripts.hive-agent-user-migrate = lib.stringAfter [ "users" "specialfs" ] '' @@ -772,8 +763,8 @@ in fi ''; - # Auto-inject the matrix MCP entry when matrix is enabled (#548 - # phase 3). Operator can override or disable by setting their own + # Auto-inject the matrix MCP entry when matrix is enabled. + # Operator can override or disable by setting their own # `extraMcpServers.matrix` (nix submodule merge takes the operator's # value) or by flipping `hyperhive.matrix.enable = false`. hyperhive.extraMcpServers = lib.mkIf config.hyperhive.matrix.enable { @@ -781,9 +772,9 @@ in command = "${pkgs.hyperhive}/bin/hive-matrix-mcp"; args = [ ]; # Same socket path the hive-matrix-daemon service binds - # via its `RuntimeDirectory = "hive-matrix"` (#658). Keeps - # the bridge + daemon in sync without baking the new path - # into the Rust default — the env override wins for both. + # via its `RuntimeDirectory = "hive-matrix"`. Keeps the + # bridge + daemon in sync without baking the path into + # the Rust default — the env override wins for both. env.HIVE_MATRIX_SOCKET = "/run/hive-matrix/socket"; allowedTools = [ "*" ]; }; @@ -798,18 +789,18 @@ in source = config.hyperhive.icon; }; - # Cargo `--message-format short` injector (#777). Contributes a - # `cargo` shell function to `hyperhive._bashEnvFragments`; the - # bash-env infrastructure below packages that into a single file - # sourced by both non-interactive and interactive shells. + # Cargo `--message-format short` injector. Contributes a `cargo` + # shell function to `hyperhive._bashEnvFragments`; the bash-env + # infrastructure below packages that into a single file sourced + # by both non-interactive and interactive shells. # `command cargo …` falls back to the un-wrapped binary in PATH # (the rust toolchain's cargo — either from `environment.systemPackages` # or from whatever `nix develop` shell the agent's working in). hyperhive._bashEnvFragments = lib.mkIf config.hyperhive.cargo.shortMessages '' # Auto-injects --message-format short on cargo compile # subcommands so per-crate progress lines don't flood - # claude's context (#777). Bypassed when the caller - # already passes --message-format (any form). + # claude's context. Bypassed when the caller already passes + # --message-format (any form). cargo() { # Strip leading +toolchain selectors (cargo +nightly …). local pre=() @@ -915,7 +906,7 @@ in # feature hook's snippet into scope without touching # `/etc/profile` (login-only). Interactive shells source the # same file via the `interactiveShellInit` hook below so - # behaviour matches across both modes (#777). + # behaviour matches across both modes. BASH_ENV = "/etc/hyperhive/bash-env.sh"; }; @@ -1185,9 +1176,9 @@ in fi TOKEN=$(cat "$TOKEN_FILE") # Local tuwunel reachable on shared host netns at the - # default matrix-spec port. Override via the future - # `hyperhive.matrix.url` if the operator ever runs the - # homeserver elsewhere (deferred to #548 phase 4). + # default matrix-spec port. Override via + # `hyperhive.matrix.url` if the operator runs the + # homeserver elsewhere. MATRIX_URL=http://localhost:8008 # whoami → user_id. Needed to scope the avatar set call. # Tolerant of the homeserver being unreachable (`-f` makes @@ -1320,13 +1311,13 @@ in HIVE_ROLE = config.hyperhive.role; } // lib.optionalAttrs config.hyperhive.web.useUnixSocket { - # Per-agent unix-socket flip for the web UI (#784 phase 2 - # step 2c). When set, the harness's `web_ui::serve` binds - # a `UnixListener` at this path instead of TCP. Path - # matches `hive_c0re::agent_sockets::socket_path_for(name)` - # so the lifecycle bind-mount (#813) and the gateway's - # upstream config all derive from the same canonical - # `/run/hive-agent//web.sock` shape — no triangulation. + # Per-agent unix-socket path for the web UI. When set, + # the harness's `web_ui::serve` binds a `UnixListener` + # at this path instead of TCP. Path matches + # `hive_c0re::agent_sockets::socket_path_for(name)` so + # the lifecycle bind-mount and the gateway's upstream + # config all derive from the same canonical + # `/run/hive-agent//web.sock` shape. HIVE_WEB_SOCKET = "/run/hive-agent/${userName}/web.sock"; } // lib.optionalAttrs isManager { diff --git a/nix/templates/weston-vnc.nix b/nix/templates/weston-vnc.nix index 227e6248..601d4c53 100644 --- a/nix/templates/weston-vnc.nix +++ b/nix/templates/weston-vnc.nix @@ -99,7 +99,7 @@ # effect unconditionally — any Wayland client launched by any # systemd service in this container automatically connects to # this compositor instead of failing or starting a second - # isolated display. Closes #540 (double-screen: VNC shows blank + # isolated display (fixes double-screen: VNC showing blank # weston desktop while services render on a different seat). exec ${pkgs.weston}/bin/weston \ --config="$WESTON_INI" \ @@ -118,13 +118,13 @@ # container so Wayland clients (e.g. bitburner started via # `systemd.services.*` in agent.nix) can find the compositor # without per-service wiring. `systemd.globalEnvironment` is the - # correct path (established by #608 for HYPERHIVE_STATE_DIR) — - # it sets DefaultEnvironment in systemd.conf, reaching all units - # started by PID 1. `environment.variables` goes to /etc/environment - # (PAM sessions only) and is NOT visible to systemd service units. - # Without these vars a service starting a Wayland client would either - # fail to connect (libwayland falls back to a headless display) or - # open a second compositor — VNC shows a blank desktop (#540). + # correct path — it sets DefaultEnvironment in systemd.conf, + # reaching all units started by PID 1. `environment.variables` + # goes to /etc/environment (PAM sessions only) and is NOT visible + # to systemd service units. Without these vars a service starting + # a Wayland client would either fail to connect (libwayland falls + # back to a headless display) or open a second compositor — VNC + # shows a blank desktop. systemd.globalEnvironment = { WAYLAND_DISPLAY = "wayland-0"; XDG_RUNTIME_DIR = "/run/user/0";