diff --git a/CLAUDE.md b/CLAUDE.md index 8dd9345f..8a8c1f26 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -150,14 +150,6 @@ hive-ag3nt/ in-container harness crate; produces TWO binaries src/turn.rs claude --print + stream-json pump; --compact retry; proactive compaction + auto session-reset src/mcp.rs embedded MCP server (rmcp): AgentServer + ManagerServer - src/forge_notify.rs Forgejo webhook subscriber: formats new-issue / - new-PR / comment / review notifications as - broker messages; embeds a body excerpt - (up to BODY_TRUNCATE bytes, ATX headings - escaped) and surfaces any @mention lines that - fell outside the truncation window in a - trailing `mentions (truncated from body):` - block (#539 / #544). src/login.rs probe /root/.claude/ for a valid session src/login_session.rs drives `claude auth login` over stdio pipes src/prompt.rs system prompt renderer: filters the unified @@ -197,18 +189,10 @@ nix/ modules/hive-c0re.nix systemd service + firewall + git wiring; `contextWindowTokens` attrset (per-model, injected as env vars into all containers); - top-level `hyperhive.domain` option - (nullable; required when matrix.enable); - imports hive-forge.nix + hive-matrix.nix + imports hive-forge.nix modules/hive-forge.nix optional in-container Forgejo (`hyperhive.forge.enable`, default on); Catppuccin Mocha theme via tmpfiles C+ copy - modules/hive-matrix.nix optional in-container matrix-tuwunel - homeserver (`hyperhive.matrix.enable`, - default off); server_name derives from - `hyperhive.domain` (subdomain by default); - federation on (empty trusted_servers), - registration off, e2ee deferred (#551) templates/harness-base.nix shared scaffolding for sub-agents + manager; `hyperhive.model` option (HIVE_DEFAULT_MODEL) templates/agent-base.nix sub-agent nixosConfiguration diff --git a/docs/turn-loop.md b/docs/turn-loop.md index 5b5c64b8..7509388b 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -38,15 +38,6 @@ Each agent harness (`hive-ag3nt serve` or `hive-m1nd serve`) runs: the same path used at boot. The operator re-authenticates via the per-agent web UI login flow; on success the sentinel is cleared and the queued message drives the next turn normally. - **Mtime-snapshot resumption** (closes #542): `wait_for_login` - snapshots the `~/.claude/` dir (newest file mtime + file count) - at entry and only resumes when that snapshot advances — not - just when credentials exist on disk. This prevents a silent - infinite-401 loop: stale credentials already on disk at the - time of the 401 no longer cause an immediate false-resume. The - `DirSnapshot` struct tracks both axes; either a mtime advance - OR a file-count change triggers resume (the count axis handles - filesystems where `modified()` errors on every file). 7. Emit `LiveEvent::TurnEnd { ok, note }`. Sleep `poll_ms` to avoid tight loops on transient failures. diff --git a/docs/web-ui.md b/docs/web-ui.md index 4cf1f829..f64f5c69 100644 --- a/docs/web-ui.md +++ b/docs/web-ui.md @@ -383,10 +383,7 @@ body sits to the right with three stacked lines fetches journald via `GET /api/journal/{name}?unit=&lines=` (`journalctl -M -b --no-pager --output=short-iso`). A unit dropdown (harness service / full machine journal) and - a refresh button live in the panel. The panel uses a column-flex - layout so the `
` log surface fills the full remaining panel
-    height (#541); scroll happens inside the `
`, not the side
-    panel body.
+    a refresh button live in the panel.
   - Plain navigation links (config repo, forge profile,
     `dashboardLinks` extras) now live in the icon-only nav strip
     on Line 1 — see above (issue #262). The agent's `config` link
diff --git a/flake.lock b/flake.lock
index ccbe77f4..2e3cff8f 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,17 +1,45 @@
 {
   "nodes": {
-    "crane": {
+    "fenix": {
+      "inputs": {
+        "nixpkgs": [
+          "naersk",
+          "nixpkgs"
+        ],
+        "rust-analyzer-src": "rust-analyzer-src"
+      },
       "locked": {
-        "lastModified": 1779130139,
-        "narHash": "sha256-BLrtr42azquO7MdGFU5a7KiMl3YpFlTeIXqy1fT5GlQ=",
-        "owner": "ipetkov",
-        "repo": "crane",
-        "rev": "edb38893982a3338972bb4a2ec7ce7c29ba10fd9",
+        "lastModified": 1752475459,
+        "narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=",
+        "owner": "nix-community",
+        "repo": "fenix",
+        "rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f",
         "type": "github"
       },
       "original": {
-        "owner": "ipetkov",
-        "repo": "crane",
+        "owner": "nix-community",
+        "repo": "fenix",
+        "type": "github"
+      }
+    },
+    "naersk": {
+      "inputs": {
+        "fenix": "fenix",
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1778151388,
+        "narHash": "sha256-lldMJPUeouEjO8/7aLuwhcsIw29vVihm2ZALzjiqfec=",
+        "owner": "nix-community",
+        "repo": "naersk",
+        "rev": "efdddff9ff4d8e7d0056d57ec67dac50f75ab8f6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "naersk",
         "type": "github"
       }
     },
@@ -49,12 +77,29 @@
     },
     "root": {
       "inputs": {
-        "crane": "crane",
+        "naersk": "naersk",
         "nixpkgs": "nixpkgs",
         "nixpkgs-unstable": "nixpkgs-unstable",
         "treefmt-nix": "treefmt-nix"
       }
     },
+    "rust-analyzer-src": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1752428706,
+        "narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=",
+        "owner": "rust-lang",
+        "repo": "rust-analyzer",
+        "rev": "591e3b7624be97e4443ea7b5542c191311aa141d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "rust-lang",
+        "ref": "nightly",
+        "repo": "rust-analyzer",
+        "type": "github"
+      }
+    },
     "treefmt-nix": {
       "inputs": {
         "nixpkgs": [
diff --git a/flake.nix b/flake.nix
index b20c18f9..792bf2fb 100644
--- a/flake.nix
+++ b/flake.nix
@@ -4,10 +4,10 @@
   inputs = {
     nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
     nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
-    # Crane (replaces naersk #538). Stateless — no nixpkgs input to
-    # follow; `crane.mkLib pkgs` returns the lib at whatever pkgs we
-    # pass it (we use the project's pinned nixpkgs).
-    crane.url = "github:ipetkov/crane";
+    naersk = {
+      url = "github:nix-community/naersk";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
     treefmt-nix = {
       url = "github:numtide/treefmt-nix";
       inputs.nixpkgs.follows = "nixpkgs";
@@ -19,7 +19,7 @@
       self,
       nixpkgs,
       nixpkgs-unstable,
-      crane,
+      naersk,
       treefmt-nix,
     }:
     let
@@ -45,59 +45,22 @@
             inherit system;
             pkgs = nixpkgs.legacyPackages.${system};
             treefmt-eval = treefmt-nix.lib.evalModule pkgs treefmt-config;
-            craneLib = crane.mkLib pkgs;
-            # Build the workspace's dependency tree once, cached as
-            # its own derivation. `buildPackage` and `cargoClippy`
-            # both reuse this via `inherit cargoArtifacts;` so a
-            # workspace-only edit doesn't rebuild deps. Same
-            # `nativeBuildInputs` as the workspace build itself —
-            # build.rs runs during dep-build too (any deps with a
-            # build.rs need rsvg too if they transitively pull it
-            # in; harmless if they don't).
-            cargoArtifacts = craneLib.buildDepsOnly {
-              src = ./.;
-              # Workspace Cargo.toml is virtual (no `[package].name`),
-              # so crane can't auto-derive a name. Spell it out
-              # explicitly here and below — keeps the derivation name
-              # stable across crane bumps + silences the placeholder
-              # warning. Same `pname` everywhere so dep + workspace +
-              # clippy share a clean naming family.
-              pname = "hyperhive-workspace";
-              version = "0.1.0";
-              inherit nativeBuildInputs;
-            };
-            # Shared between buildDepsOnly + buildPackage + cargoClippy
-            # so the three derivations see the same toolchain shape.
-            # librsvg: hive-c0re/build.rs invokes `rsvg-convert` to
-            # render branding/agent-configs.svg → PNG that the daemon
-            # `include_bytes!`s (#424); SVG stays source-of-truth.
-            # git: naersk used to auto-include it; crane is more
-            # minimal, so we add it explicitly so hive-c0re's
-            # `lifecycle::tests::setup_proposed_*` (which shell out to
-            # `git init` + commit) pass under `cargo test` in the
-            # sandbox.
-            nativeBuildInputs = [
-              pkgs.librsvg
-              pkgs.git
-            ];
+            naersk-lib = pkgs.callPackage naersk { };
           }
         );
     in
     {
       packages = forAllSystems (
+        { pkgs, naersk-lib, ... }:
         {
-          pkgs,
-          craneLib,
-          cargoArtifacts,
-          nativeBuildInputs,
-          ...
-        }:
-        {
-          default = craneLib.buildPackage {
+          default = naersk-lib.buildPackage {
             src = ./.;
-            inherit cargoArtifacts nativeBuildInputs;
-            pname = "hyperhive-workspace";
-            version = "0.1.0";
+            # librsvg ships `rsvg-convert`, which hive-c0re/build.rs
+            # invokes to render branding/agent-configs.svg into the
+            # PNG it embeds via `include_bytes!` (#424). Keeps the
+            # raster out of git — SVG stays source-of-truth, PNG is
+            # a build artifact in $OUT_DIR.
+            nativeBuildInputs = [ pkgs.librsvg ];
             meta.description = "hyperhive workspace (hive-c0re, hive-ag3nt, hive-m1nd)";
           };
           # Bundled browser assets — see ./nix/frontend.nix. Output is
@@ -238,28 +201,43 @@
       checks = forAllSystems (
         {
           treefmt-eval,
-          craneLib,
-          cargoArtifacts,
-          nativeBuildInputs,
+          pkgs,
+          naersk-lib,
           ...
         }:
         {
           formatting = treefmt-eval.config.build.check self;
-          # Clippy as a check via crane's first-class `cargoClippy`
-          # builder. Reuses the shared `cargoArtifacts` (deps already
-          # built) and runs `cargo clippy --workspace --all-targets
-          # -- -D warnings` directly — no `overrideAttrs` hack needed,
-          # because crane parses `cargoClippyExtraArgs` correctly
-          # (naersk's `mode = "clippy"` used to mangle the `--`
-          # separator, which is why the old wiring went through
-          # overrideAttrs).
-          clippy = craneLib.cargoClippy {
-            src = ./.;
-            inherit cargoArtifacts nativeBuildInputs;
-            pname = "hyperhive-workspace";
-            version = "0.1.0";
-            cargoClippyExtraArgs = "--workspace --all-targets -- -D warnings";
-          };
+          # Clippy as a check: reuse naersk's vendored-deps environment but
+          # replace the build phase with `cargo clippy --workspace --all-targets
+          # -- -D warnings`. Naersk's own `mode = "clippy"` mangles the `--`
+          # separator, so we go through overrideAttrs instead.
+          clippy =
+            (naersk-lib.buildPackage {
+              src = ./.;
+              # Skip the actual build; we only care about the clippy lint.
+              doCheck = false;
+              copyTarget = false;
+              # hive-c0re/build.rs needs rsvg-convert on PATH (#424);
+              # mirror the runtime derivation's nativeBuildInputs so
+              # clippy's vendored-deps build phase doesn't break on
+              # the missing tool.
+              nativeBuildInputs = [ pkgs.librsvg ];
+            }).overrideAttrs
+              (old: {
+                name = "${old.name}-clippy";
+                nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.clippy ];
+                buildPhase = ''
+                  runHook preBuild
+                  cargo clippy --workspace --all-targets -- -D warnings
+                  runHook postBuild
+                '';
+                installPhase = ''
+                  runHook preInstall
+                  mkdir -p $out
+                  touch $out/.clippy-passed
+                  runHook postInstall
+                '';
+              });
         }
       );
     };
diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css
index 0c3231a9..deaa7e71 100644
--- a/frontend/packages/dashboard/src/dashboard.css
+++ b/frontend/packages/dashboard/src/dashboard.css
@@ -450,21 +450,11 @@ a:hover {
 .container-row.tombstone .name { color: var(--muted); }
 /* Per-container journald viewer + applied-config viewer. Both open
    in the side panel and lazy-fetch on open; output is monospace
-   inside a bordered 
, controls (unit select + refresh) above.
-   #541: the panel-body wrapper is a column flex container that fills
-   the side-panel-body so the 
 can flex-grow into a single tall
-   scrollable surface instead of a short box at the top with the rest
-   of the panel empty. */
-.journal-body {
-  display: flex;
-  flex-direction: column;
-  height: 100%;
-  gap: 0.4em;
-}
+   inside a bordered 
, controls (unit select + refresh) above. */
 .journal-controls {
-  flex: 0 0 auto;
   display: flex;
   gap: 0.5em;
+  margin-bottom: 0.4em;
   align-items: center;
 }
 .journal-unit {
@@ -482,13 +472,7 @@ a:hover {
   color: var(--fg);
   border: 1px solid var(--purple-dim);
   padding: 0.5em 0.7em;
-  /* #541: take all leftover panel height + scroll inside the pre so
-     long log fetches don't push the controls off-screen. `min-height:
-     0` is the canonical "let me actually flex-shrink for overflow"
-     escape hatch on flex children. */
-  flex: 1 1 0;
-  min-height: 0;
-  overflow: auto;
+  overflow-x: auto;
   font-size: 0.85em;
   line-height: 1.4;
   white-space: pre;
diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js
index aa46c5d2..e220b423 100644
--- a/frontend/packages/dashboard/src/tabs.js
+++ b/frontend/packages/dashboard/src/tabs.js
@@ -946,12 +946,9 @@ window.marked = marked;
             pre.textContent = 'error: ' + resp.status + '\n' + text;
           } else {
             pre.textContent = text || '(empty)';
-            // Auto-scroll to the newest lines on fresh fetch. #541
-            // moved the scroll surface from side-panel-body onto the
-            // 
 itself (the panel-body now fills the viewport and
-            // the 
 is the inner overflow container), so scroll
-            // the 
 instead of the side-panel-body.
-            pre.scrollTop = pre.scrollHeight;
+            // Auto-scroll the panel to the newest lines on fresh fetch.
+            const sb = $('side-panel-body');
+            if (sb) sb.scrollTop = sb.scrollHeight;
           }
         } catch (err) {
           pre.textContent = 'fetch failed: ' + err;
diff --git a/hive-ag3nt/Cargo.toml b/hive-ag3nt/Cargo.toml
index 2446dec4..3f0fba3e 100644
--- a/hive-ag3nt/Cargo.toml
+++ b/hive-ag3nt/Cargo.toml
@@ -24,9 +24,6 @@ tower-http.workspace = true
 tracing.workspace = true
 tracing-subscriber.workspace = true
 
-[dev-dependencies]
-tempfile = "3"
-
 [[bin]]
 name = "hive-ag3nt"
 path = "src/bin/hive-ag3nt.rs"
diff --git a/hive-ag3nt/src/events.rs b/hive-ag3nt/src/events.rs
index 8f0caea9..bae95e30 100644
--- a/hive-ag3nt/src/events.rs
+++ b/hive-ag3nt/src/events.rs
@@ -143,7 +143,10 @@ pub enum LiveEvent {
     /// compacting). `since_unix` matches `Bus::state_snapshot().1`
     /// so the client's elapsed-time ticker keeps progressing across
     /// SSE reconnects without drift.
-    TurnStateChanged { state: TurnState, since_unix: i64 },
+    TurnStateChanged {
+        state: TurnState,
+        since_unix: i64,
+    },
 }
 
 /// sqlite-backed event log. Wraps a `Connection` behind a `Mutex` so the
@@ -281,12 +284,10 @@ impl TokenUsage {
         let model_usage = v.get("modelUsage")?;
         let map = model_usage.as_object()?;
         for (_model, stats) in map {
-            if let Some(w) = stats
-                .get("contextWindow")
-                .and_then(serde_json::Value::as_u64)
-                && w > 0
-            {
-                return Some(w);
+            if let Some(w) = stats.get("contextWindow").and_then(serde_json::Value::as_u64) {
+                if w > 0 {
+                    return Some(w);
+                }
             }
         }
         None
@@ -352,21 +353,18 @@ pub fn context_window_tokens(model: &str) -> u64 {
     // Per-model env vars set by `hyperhive.contextWindowTokens` in Nix.
     for (key, val) in std::env::vars() {
         if let Some(suffix) = key.strip_prefix("HIVE_CONTEXT_WINDOW_TOKENS_")
-            && !suffix.is_empty()
-            && m.contains(&suffix.to_ascii_lowercase())
-            && let Ok(v) = val.trim().parse::()
-            && v > 0
-        {
-            return v;
-        }
+            && !suffix.is_empty() && m.contains(&suffix.to_ascii_lowercase())
+                && let Ok(v) = val.trim().parse::()
+                    && v > 0 {
+                        return v;
+                    }
     }
     // Global override (single value, any model).
     if let Ok(s) = std::env::var("HIVE_CONTEXT_WINDOW_TOKENS")
         && let Ok(v) = s.trim().parse::()
-        && v > 0
-    {
-        return v;
-    }
+            && v > 0 {
+                return v;
+            }
     // Hard fallback for dev/test outside NixOS where env vars aren't set.
     200_000
 }
@@ -452,10 +450,9 @@ impl Bus {
         // persisted runtime override > compiled-in DEFAULT_MODEL.
         // The nix config always wins on rebuild; the persisted file is kept
         // for within-session tracking only (see persist_model / set_model).
-        let initial_model = configured_model().map_or_else(
-            || load_model().unwrap_or_else(|| DEFAULT_MODEL.to_owned()),
-            str::to_owned,
-        );
+        let initial_model = configured_model()
+            .map(str::to_owned)
+            .unwrap_or_else(|| load_model().unwrap_or_else(|| DEFAULT_MODEL.to_owned()));
         // Restore rate_limited from the sentinel file — if the harness
         // crashed while parked, we should still show the right status on
         // cold load until the next turn clears it.
@@ -563,8 +560,7 @@ impl Bus {
     pub fn record_turn_usage(&self, ctx: TokenUsage, cost: TokenUsage) {
         *self.last_ctx_usage.lock().unwrap() = Some(ctx);
         *self.last_cost_usage.lock().unwrap() = Some(cost);
-        self.last_turn_ended_unix
-            .store(now_unix(), Ordering::Relaxed);
+        self.last_turn_ended_unix.store(now_unix(), Ordering::Relaxed);
         self.emit(LiveEvent::TokenUsageChanged { ctx, cost });
     }
 
diff --git a/hive-ag3nt/src/forge_notify.rs b/hive-ag3nt/src/forge_notify.rs
index cba2cd5e..fad34d8f 100644
--- a/hive-ag3nt/src/forge_notify.rs
+++ b/hive-ag3nt/src/forge_notify.rs
@@ -162,7 +162,11 @@ pub async fn run(socket: PathBuf, is_manager: bool) {
 
 /// Fetch a JSON value from a URL using the agent's forge token. Returns
 /// `None` on any HTTP or parse error (best-effort enrichment).
-async fn fetch_json(client: &reqwest::Client, url: &str, token: &str) -> Option {
+async fn fetch_json(
+    client: &reqwest::Client,
+    url: &str,
+    token: &str,
+) -> Option {
     let resp = client
         .get(url)
         .header("Authorization", format!("token {token}"))
@@ -203,7 +207,7 @@ fn notif_type_label(t: &str) -> &str {
 /// (`heading\n===`) are not handled here — rarer in practice and
 /// would need multi-line lookahead; revisit if it actually shows up.
 ///
-/// **ATX shape strictly:** `CommonMark` requires a space (or end-of-line)
+/// **ATX shape strictly:** CommonMark requires a space (or end-of-line)
 /// after the 1-6 leading `#`s to count as an ATX heading. Lines like
 /// `#tag`, `#123`, `#!/bin/bash` are NOT headings — passing them through
 /// untouched avoids the cosmetic noise argus flagged on PR #518 (`\#tag`
@@ -232,7 +236,7 @@ fn escape_md_headings(body: &str) -> String {
     out
 }
 
-/// Strict `CommonMark` ATX-heading detector: 1-6 leading `#`s followed
+/// Strict CommonMark ATX-heading detector: 1-6 leading `#`s followed
 /// by either a space, tab, or end-of-line. Anything tighter (`#tag`,
 /// `#123`) is a non-heading line that the renderer will not promote.
 fn is_atx_heading(line: &str) -> bool {
@@ -240,10 +244,11 @@ fn is_atx_heading(line: &str) -> bool {
     if !(1..=6).contains(&hashes) {
         return false;
     }
-    // Bare `#` / `##` / ... on its own line, or proper ATX with a
-    // space/tab after the run of `#`s; anything else (`#tag` / `#123`)
-    // is not a heading.
-    matches!(line.as_bytes().get(hashes), None | Some(b' ' | b'\t'))
+    match line.as_bytes().get(hashes) {
+        None => true,                            // bare `#` / `##` / ... on its own line
+        Some(b' ') | Some(b'\t') => true,        // proper ATX with space/tab after #s
+        _ => false,                              // `#tag` / `#123` — not a heading
+    }
 }
 
 fn truncate(s: &str, max: usize) -> String {
@@ -259,69 +264,6 @@ fn truncate(s: &str, max: usize) -> String {
     format!("{}…", &s[..end])
 }
 
-/// Detect `@username` mentions on a line. A mention is `@` followed by
-/// at least one username char (alphanumeric / `_` / `-`) where the `@`
-/// is at line start or follows a non-username char — so email-style
-/// `foo@bar.com` does NOT count as a mention.
-fn contains_mention(line: &str) -> bool {
-    let bytes = line.as_bytes();
-    for (i, &b) in bytes.iter().enumerate() {
-        if b != b'@' {
-            continue;
-        }
-        // Boundary: preceding byte must NOT be a username char.
-        let boundary_ok = match i.checked_sub(1).map(|j| bytes[j]) {
-            None => true,
-            Some(prev) => !is_username_byte(prev),
-        };
-        if !boundary_ok {
-            continue;
-        }
-        // Following byte must be at least one username char.
-        if bytes.get(i + 1).is_some_and(|&c| is_username_byte(c)) {
-            return true;
-        }
-    }
-    false
-}
-
-fn is_username_byte(b: u8) -> bool {
-    b.is_ascii_alphanumeric() || b == b'_' || b == b'-'
-}
-
-/// Walk `full_body` line-by-line; return lines that contain an
-/// `@username` mention AND aren't already present (as a substring) in
-/// `included_excerpt`. Used to surface mentions that fell outside the
-/// truncation window so addressed agents see they were tagged even
-/// when the body is long (closes #539).
-fn extract_truncated_mention_lines<'a>(
-    full_body: &'a str,
-    included_excerpt: &str,
-) -> Vec<&'a str> {
-    full_body
-        .lines()
-        .filter(|line| {
-            let trimmed = line.trim();
-            !trimmed.is_empty() && contains_mention(trimmed)
-        })
-        .filter(|line| !included_excerpt.contains(line.trim()))
-        .collect()
-}
-
-/// Build the trailing `mentions (truncated from body):\n  > …` block.
-/// Empty string when there's nothing to surface. Caller embeds it
-/// directly before the meta suffix.
-fn render_truncated_mentions(lines: &[&str]) -> String {
-    if lines.is_empty() {
-        return String::new();
-    }
-    let mut out = String::from("\n\nmentions (truncated from body):");
-    for line in lines {
-        write!(out, "\n  > {}", line.trim()).ok();
-    }
-    out
-}
-
 /// Map a Forgejo review state to a readable action label.
 /// Returns `None` for non-review states (regular comments have no `state` field;
 /// `PENDING` means the review was saved but not submitted yet).
@@ -385,9 +327,7 @@ async fn format_notification(
 
     // API URLs for fetching content
     let subject_api_url = notif["subject"]["url"].as_str().unwrap_or("");
-    let comment_api_url = notif["subject"]["latest_comment_url"]
-        .as_str()
-        .unwrap_or("");
+    let comment_api_url = notif["subject"]["latest_comment_url"].as_str().unwrap_or("");
     let comment_html_url = notif["subject"]["latest_comment_html_url"]
         .as_str()
         .unwrap_or("");
@@ -408,27 +348,9 @@ async fn format_notification(
     // by creation/state-change of the subject itself.
     let has_comment = !comment_api_url.is_empty() && comment_api_url != subject_api_url;
 
-    let meta = NotifMeta {
-        title,
-        notif_type,
-        html_url,
-        num,
-        repo,
-        meta_suffix,
-        reason,
-        subject,
-        is_pr,
-    };
+    let meta = NotifMeta { title, notif_type, html_url, num, repo, meta_suffix, reason, subject, is_pr };
     if has_comment {
-        format_comment_notification(
-            client,
-            token,
-            &meta,
-            comment_api_url,
-            comment_html_url,
-            own_login,
-        )
-        .await
+        format_comment_notification(client, token, &meta, comment_api_url, comment_html_url, own_login).await
     } else {
         format_state_change_notification(notif, &meta, own_login)
     }
@@ -469,28 +391,16 @@ fn build_meta_suffix(subject: Option<&serde_json::Value>, is_pr: bool, reason: &
             .and_then(|s| s["requested_reviewers"].as_array())
             .map(|arr| arr.iter().filter_map(|r| r["login"].as_str()).collect())
             .unwrap_or_default();
-        if reviewers.is_empty() {
-            None
-        } else {
-            Some(format!("reviewer: {}", reviewers.join(", ")))
-        }
+        if reviewers.is_empty() { None } else { Some(format!("reviewer: {}", reviewers.join(", "))) }
     } else {
         None
     };
     // Always include reason so multiple notifications for the same event
     // (each with a different Forgejo reason) are distinguishable (closes #110).
-    let reason_line = if reason.is_empty() {
-        None
-    } else {
-        Some(format!("reason: {reason}"))
-    };
+    let reason_line = if reason.is_empty() { None } else { Some(format!("reason: {reason}")) };
     let mut out = format!("\n{assignee_line}");
-    if let Some(r) = reviewer_line {
-        write!(out, "\n{r}").ok();
-    }
-    if let Some(r) = reason_line {
-        write!(out, "\n{r}").ok();
-    }
+    if let Some(r) = reviewer_line { write!(out, "\n{r}").ok(); }
+    if let Some(r) = reason_line   { write!(out, "\n{r}").ok(); }
     out
 }
 
@@ -531,42 +441,17 @@ async fn format_comment_notification(
         .and_then(|c| c["state"].as_str())
         .and_then(review_state_label);
 
-    let url = if comment_html_url.is_empty() {
-        meta.html_url
-    } else {
-        comment_html_url
-    };
-    let author = if actor_login.is_empty() {
-        "?"
-    } else {
-        actor_login
-    };
-    let NotifMeta {
-        title,
-        notif_type,
-        num,
-        repo,
-        meta_suffix,
-        ..
-    } = meta;
+    let url = if comment_html_url.is_empty() { meta.html_url } else { comment_html_url };
+    let author = if actor_login.is_empty() { "?" } else { actor_login };
+    let NotifMeta { title, notif_type, num, repo, meta_suffix, .. } = meta;
 
-    // Truncate the raw body first so the mention-overflow diff compares
-    // like-for-like (escape_md_headings rewrites `# foo` to `\# foo`, so
-    // doing it before the diff would re-surface heading-prefixed mention
-    // lines as fake overflow). Escape happens after for display only.
-    let raw_excerpt = truncate(body_text, BODY_TRUNCATE);
-    // Surface @mentions that fell outside the truncation window so an
-    // addressed agent never silently misses a tag on a long comment
-    // (closes #539). Skipped when the embed wasn't actually truncated.
-    let truncated_mentions = if body_text.len() > BODY_TRUNCATE {
-        render_truncated_mentions(&extract_truncated_mention_lines(body_text, &raw_excerpt))
-    } else {
-        String::new()
-    };
     // Escape ATX headings in the user-authored body so the embedded
     // text doesn't blow into top-level h1/h2 in the wrapper message
-    // when the dashboard renders it (closes #455).
-    let body_for_embed = escape_md_headings(&raw_excerpt);
+    // when the dashboard renders it (closes #455). Done once here
+    // because both code paths fall through the same truncate+embed
+    // pattern.
+    let escaped = escape_md_headings(body_text);
+    let body_for_embed = truncate(&escaped, BODY_TRUNCATE);
     if let Some(review_label) = review_state {
         // Review submission on a PR.
         let kind = format!("PR {review_label}{num}{repo}");
@@ -574,16 +459,14 @@ async fn format_comment_notification(
         if body_text.is_empty() {
             write!(out, "\n\nreviewer: {author}").ok();
         } else {
-            write!(out, "\n\n{author}: {body_for_embed}{truncated_mentions}").ok();
+            write!(out, "\n\n{author}: {body_for_embed}").ok();
         }
         out.push_str(meta_suffix);
         Some(out)
     } else {
         // Regular comment.
         let kind = format!("comment on {}{num}{repo}", notif_type_label(notif_type));
-        let mut out = format!(
-            "[{kind}] {title}\nurl: {url}\n\n{author}: {body_for_embed}{truncated_mentions}"
-        );
+        let mut out = format!("[{kind}] {title}\nurl: {url}\n\n{author}: {body_for_embed}");
         if out.ends_with('\n') {
             out.pop();
         }
@@ -616,17 +499,7 @@ fn format_state_change_notification(
         return None;
     }
 
-    let NotifMeta {
-        title,
-        notif_type,
-        html_url,
-        num,
-        repo,
-        meta_suffix,
-        reason: _,
-        subject,
-        is_pr,
-    } = meta;
+    let NotifMeta { title, notif_type, html_url, num, repo, meta_suffix, reason: _, subject, is_pr } = meta;
     let label = notif_type_label(notif_type);
     let kind = match notif_state {
         "merged" => format!("{label} merged{num}{repo}"),
@@ -653,41 +526,12 @@ fn format_state_change_notification(
         kind
     };
 
-    // Include the start of the issue/PR description so the agent gets
-    // context without a follow-up fetch (closes #539). Same escape +
-    // truncate pipeline as comment bodies. Mentions that fell outside
-    // the truncation window are surfaced separately so an addressed
-    // agent never silently misses a long-body @tag.
-    let body_block = subject
-        .as_ref()
-        .and_then(|s| s["body"].as_str())
-        .map(str::trim)
-        .filter(|s| !s.is_empty())
-        .map(|raw| {
-            // Truncate raw first so mention diff sees the same heading
-            // markers as full_body (see comment in
-            // format_comment_notification). Escape happens after for
-            // display only.
-            let raw_excerpt = truncate(raw, BODY_TRUNCATE);
-            let truncated = extract_truncated_mention_lines(raw, &raw_excerpt);
-            let mentions = render_truncated_mentions(&truncated);
-            let excerpt = escape_md_headings(&raw_excerpt);
-            format!("\n\n{excerpt}{mentions}")
-        })
-        .unwrap_or_default();
-
-    let mut out = format!("[{kind}] {title}\nurl: {html_url}{body_block}");
+    let mut out = format!("[{kind}] {title}\nurl: {html_url}");
     out.push_str(meta_suffix);
     Some(out)
 }
 
 #[allow(clippy::too_many_arguments)]
-#[allow(
-    clippy::too_many_lines,
-    reason = "single-pass notification poll loop — split would obscure the \
-              sequential 'fetch / classify / dispatch' rhythm and add helper \
-              functions for state shared across all three phases"
-)]
 async fn poll_once(
     client: &reqwest::Client,
     forge_url: &str,
@@ -730,15 +574,10 @@ async fn poll_once(
         return;
     }
 
-    debug!(
-        count = notifications.len(),
-        "forge_notify: delivering notifications"
-    );
+    debug!(count = notifications.len(), "forge_notify: delivering notifications");
 
     for notif in ¬ifications {
-        let Some(id) = notif["id"].as_u64() else {
-            continue;
-        };
+        let Some(id) = notif["id"].as_u64() else { continue };
 
         // Reason drop-list: suppress noisy reasons (subscribed/participating).
         // null/unknown reasons pass through — directed signals are never
@@ -796,30 +635,28 @@ async fn poll_once(
         // when HIVE_FORGE_KEEP_SUBSCRIPTIONS=1 — triage and other firehose
         // consumers set this to retain broad repo visibility.
         let reason = notif["reason"].as_str().unwrap_or("");
-        if !keep_subscriptions
-            && reason == "subscribed"
+        if !keep_subscriptions && reason == "subscribed"
             && let Some(repo) = notif["repository"]["full_name"].as_str()
-            && !unsubbed_repos.contains(repo)
-        {
-            let unsub_url = format!("{forge_url}/api/v1/repos/{repo}/subscription");
-            match client
-                .delete(&unsub_url)
-                .header("Authorization", format!("token {token}"))
-                .send()
-                .await
-            {
-                Ok(r) if r.status().is_success() || r.status().as_u16() == 404 => {
-                    debug!(%repo, "forge_notify: unsubscribed from repo watch");
-                    unsubbed_repos.insert(repo.to_owned());
+                && !unsubbed_repos.contains(repo) {
+                    let unsub_url = format!("{forge_url}/api/v1/repos/{repo}/subscription");
+                    match client
+                        .delete(&unsub_url)
+                        .header("Authorization", format!("token {token}"))
+                        .send()
+                        .await
+                    {
+                        Ok(r) if r.status().is_success() || r.status().as_u16() == 404 => {
+                            debug!(%repo, "forge_notify: unsubscribed from repo watch");
+                            unsubbed_repos.insert(repo.to_owned());
+                        }
+                        Ok(r) => {
+                            debug!(%repo, status = %r.status(), "forge_notify: unsub non-2xx (ignored)");
+                        }
+                        Err(e) => {
+                            debug!(%repo, error = ?e, "forge_notify: unsub request failed (ignored)");
+                        }
+                    }
                 }
-                Ok(r) => {
-                    debug!(%repo, status = %r.status(), "forge_notify: unsub non-2xx (ignored)");
-                }
-                Err(e) => {
-                    debug!(%repo, error = ?e, "forge_notify: unsub request failed (ignored)");
-                }
-            }
-        }
     }
 }
 
@@ -935,89 +772,4 @@ mod tests {
         assert_eq!(escape_md_headings("body\n"), "body\n");
         assert_eq!(escape_md_headings("no trailing"), "no trailing");
     }
-
-    #[test]
-    fn contains_mention_matches_at_line_start_and_mid_line() {
-        assert!(contains_mention("@damocles take a look"));
-        assert!(contains_mention("cc @argus please"));
-        assert!(contains_mention("see (@mara) for context"));
-        // Hyphens / underscores / digits are valid username chars.
-        assert!(contains_mention("ping @h-m1nd-2"));
-    }
-
-    #[test]
-    fn contains_mention_rejects_email_and_bare_at() {
-        // Email addresses (`foo@bar.com`) and `@` followed by
-        // whitespace or punctuation are not mentions — boundary check
-        // requires the preceding byte to NOT be a username char.
-        assert!(!contains_mention("foo@bar.com"));
-        assert!(!contains_mention("send to user@example.org"));
-        assert!(!contains_mention("just an @"));
-        assert!(!contains_mention("@ space"));
-        assert!(!contains_mention("plain text"));
-        assert!(!contains_mention(""));
-    }
-
-    #[test]
-    fn extract_truncated_keeps_mention_lines_outside_excerpt() {
-        // Long body where the @mention sits AFTER the excerpt's cutoff
-        // — the truncated extractor must surface it.
-        let full = "first line\nsecond line\n@damocles tagged here\n";
-        let excerpt = "first line\nsecond line\n…"; // mention not present
-        let lines = extract_truncated_mention_lines(full, excerpt);
-        assert_eq!(lines, vec!["@damocles tagged here"]);
-    }
-
-    #[test]
-    fn extract_truncated_drops_mentions_already_in_excerpt() {
-        // Mention is inside the embed window already — no need to
-        // re-surface, would be noise.
-        let full = "@damocles read this\nmore body\n";
-        let excerpt = "@damocles read this\nmore body\n…";
-        let lines = extract_truncated_mention_lines(full, excerpt);
-        assert!(lines.is_empty());
-    }
-
-    #[test]
-    fn extract_truncated_skips_blank_and_no_mention_lines() {
-        // Only lines with an actual mention survive — random body
-        // text past the cutoff stays dropped.
-        let full = "first\n\nsecond paragraph\n@argus reviewer\nfinal\n";
-        let excerpt = "first";
-        let lines = extract_truncated_mention_lines(full, excerpt);
-        assert_eq!(lines, vec!["@argus reviewer"]);
-    }
-
-    #[test]
-    fn extract_truncated_does_not_resurface_heading_mention_inside_window() {
-        // Regression for argus's nit on PR #544: the diff used to
-        // compare full_body against the *escaped* excerpt. Lines like
-        // `# @argus check this` survived as-is in the body but became
-        // `\# @argus check this` in the excerpt, so the `contains`
-        // check failed and the mention was re-surfaced as if it had
-        // fallen outside the window. Pass the unescaped excerpt and
-        // the duplicate disappears.
-        let full = "# @argus check this\nmore body\n";
-        let raw_excerpt = full; // fits entirely
-        let lines = extract_truncated_mention_lines(full, raw_excerpt);
-        assert!(lines.is_empty(), "heading+mention inside window must not be re-surfaced, got {lines:?}");
-    }
-
-    #[test]
-    fn render_truncated_mentions_empty_is_empty_string() {
-        // Zero overhead on the healthy short-body path: caller
-        // concatenates this directly so an empty input must produce
-        // no spacing.
-        assert_eq!(render_truncated_mentions(&[]), "");
-    }
-
-    #[test]
-    fn render_truncated_mentions_formats_block() {
-        let lines = ["cc @damocles", "  @argus second mention"];
-        let rendered = render_truncated_mentions(&lines);
-        assert_eq!(
-            rendered,
-            "\n\nmentions (truncated from body):\n  > cc @damocles\n  > @argus second mention",
-        );
-    }
 }
diff --git a/hive-ag3nt/src/mcp.rs b/hive-ag3nt/src/mcp.rs
index ca94aa6c..4cbafcde 100644
--- a/hive-ag3nt/src/mcp.rs
+++ b/hive-ag3nt/src/mcp.rs
@@ -47,7 +47,7 @@ pub enum SocketReply {
     Recent(Vec),
     Logs(String),
     /// `list_schedules` result — used by the manager surface only;
-    /// `AgentResponse` has no equivalent variant.
+    /// AgentResponse has no equivalent variant.
     Schedules(Vec),
     LooseEnds(Vec),
     PendingRemindersCount(u64),
@@ -185,7 +185,8 @@ pub fn format_recv(resp: Result) -> String {
 /// resurfaced by `RequeueInflight` on this session's boot. Same
 /// string surfaces in the wake prompt (see the bin loops) and the
 /// in-turn `recv` tool result so claude sees the warning either way.
-pub const REDELIVERY_HINT: &str = "[redelivered after harness restart — may already be handled]\n";
+pub const REDELIVERY_HINT: &str =
+    "[redelivered after harness restart — may already be handled]\n";
 
 /// Format helper for `get_loose_ends`: renders a short bulleted list
 /// of pending approvals + questions + reminders. Empty list collapses
@@ -306,32 +307,17 @@ pub fn format_agent_meta(resp: Result) -> String {
             match status_text {
                 None => out.push_str("\nstatus: "),
                 Some(s) => {
-                    use std::fmt::Write as _;
                     let age = status_set_at.and_then(|ts| {
                         let now = std::time::SystemTime::now()
                             .duration_since(std::time::UNIX_EPOCH)
                             .ok()?
                             .as_secs();
-                        // `ts` is a unix epoch second the agent itself
-                        // sourced from `SystemTime` — always positive
-                        // in normal operation. Clamp the negative
-                        // (clock-skew) edge to 0 before the unsigned
-                        // cast so the cast loses no real precision.
-                        let ts_secs = u64::try_from(ts).unwrap_or(0);
-                        let secs = now.saturating_sub(ts_secs);
+                        let secs = now.saturating_sub(ts as u64);
                         Some(format_age_secs(secs))
                     });
-                    // `write!` into the buffer instead of `push_str(&format!(…))` —
-                    // avoids the intermediate allocation clippy::format_push_string
-                    // flags. The infallible `String` writer makes this safe to
-                    // `let _ =`-ignore.
                     match age {
-                        Some(a) => {
-                            let _ = write!(out, "\nstatus: {s} (set {a} ago)");
-                        }
-                        None => {
-                            let _ = write!(out, "\nstatus: {s}");
-                        }
+                        Some(a) => out.push_str(&format!("\nstatus: {s} (set {a} ago)")),
+                        None => out.push_str(&format!("\nstatus: {s}")),
                     }
                 }
             }
@@ -640,13 +626,9 @@ impl AgentServer {
     )]
     async fn set_status(&self, Parameters(args): Parameters) -> String {
         run_tool_envelope("set_status", args.text.clone(), async move {
-            let (resp, retries) = self
-                .dispatch(hive_sh4re::AgentRequest::SetStatus { text: args.text })
-                .await;
-            annotate_retries(
-                format_ack(resp, "set_status", "status updated".to_owned()),
-                retries,
-            )
+            let (resp, retries) =
+                self.dispatch(hive_sh4re::AgentRequest::SetStatus { text: args.text }).await;
+            annotate_retries(format_ack(resp, "set_status", "status updated".to_owned()), retries)
         })
         .await
     }
@@ -662,7 +644,10 @@ impl AgentServer {
         where the system-prompt label could be stale. Status reads `` when the \
         target has never called `set_status` or has cleared it."
     )]
-    async fn get_agent_meta(&self, Parameters(args): Parameters) -> String {
+    async fn get_agent_meta(
+        &self,
+        Parameters(args): Parameters,
+    ) -> String {
         let log = args.name.clone().unwrap_or_else(|| "".to_owned());
         run_tool_envelope("get_agent_meta", log, async move {
             let (resp, retries) = self
@@ -694,11 +679,7 @@ impl AgentServer {
                 .dispatch(hive_sh4re::AgentRequest::CancelLooseEnd { kind, id })
                 .await;
             annotate_retries(
-                format_ack(
-                    resp,
-                    "cancel_loose_end",
-                    format!("cancelled {kind_label} {id}"),
-                ),
+                format_ack(resp, "cancel_loose_end", format!("cancelled {kind_label} {id}")),
                 retries,
             )
         })
@@ -740,10 +721,7 @@ impl AgentServer {
                     file_path: args.file_path,
                 })
                 .await;
-            annotate_retries(
-                format_ack(resp, "remind", "reminder scheduled".to_string()),
-                retries,
-            )
+            annotate_retries(format_ack(resp, "remind", "reminder scheduled".to_string()), retries)
         })
         .await
     }
@@ -971,7 +949,7 @@ pub struct RequestSchedulePromptArgs {
     /// `None` / absent = one-shot. `Some(n > 0)` = recurring every
     /// `n` seconds. The worker clamps catch-up so a long downtime
     /// fires ONCE on resume (skipped-cycle count surfaces in the
-    /// per-target `last_result`), not N delayed pulses in a row.
+    /// per-target last_result), not N delayed pulses in a row.
     #[serde(default)]
     pub interval_seconds: Option,
     /// Optional description shown on the dashboard approval card +
@@ -1323,7 +1301,10 @@ impl ManagerServer {
         Authorization mirrors `cancel_schedule`: you can fire your own schedules + any \
         owned by a sub-agent in your subtree per topology.json."
     )]
-    async fn fire_schedule_now(&self, Parameters(args): Parameters) -> String {
+    async fn fire_schedule_now(
+        &self,
+        Parameters(args): Parameters,
+    ) -> String {
         let log = format!("{args:?}");
         run_tool_envelope("fire_schedule_now", log, async move {
             let id = args.id;
@@ -1356,10 +1337,7 @@ impl ManagerServer {
                     targets: args.targets,
                 })
                 .await;
-            annotate_retries(
-                format_ack(resp, "cancel_schedule", format!("cancelled #{id}")),
-                retries,
-            )
+            annotate_retries(format_ack(resp, "cancel_schedule", format!("cancelled #{id}")), retries)
         })
         .await
     }
@@ -1416,9 +1394,7 @@ impl ManagerServer {
     )]
     async fn list_schedules(&self) -> String {
         run_tool_envelope("list_schedules", String::new(), async move {
-            let (resp, retries) = self
-                .dispatch(hive_sh4re::ManagerRequest::ListSchedules)
-                .await;
+            let (resp, retries) = self.dispatch(hive_sh4re::ManagerRequest::ListSchedules).await;
             let body = match resp {
                 Ok(SocketReply::Schedules(schedules)) => serde_json::to_string(&schedules)
                     .unwrap_or_else(|e| format!("list_schedules: serialise: {e:#}")),
@@ -1565,10 +1541,7 @@ impl ManagerServer {
                     file_path: args.file_path,
                 })
                 .await;
-            annotate_retries(
-                format_ack(resp, "remind", "reminder scheduled".to_string()),
-                retries,
-            )
+            annotate_retries(format_ack(resp, "remind", "reminder scheduled".to_string()), retries)
         })
         .await
     }
@@ -1600,13 +1573,9 @@ impl ManagerServer {
     )]
     async fn set_status(&self, Parameters(args): Parameters) -> String {
         run_tool_envelope("set_status", args.text.clone(), async move {
-            let (resp, retries) = self
-                .dispatch(hive_sh4re::ManagerRequest::SetStatus { text: args.text })
-                .await;
-            annotate_retries(
-                format_ack(resp, "set_status", "status updated".to_owned()),
-                retries,
-            )
+            let (resp, retries) =
+                self.dispatch(hive_sh4re::ManagerRequest::SetStatus { text: args.text }).await;
+            annotate_retries(format_ack(resp, "set_status", "status updated".to_owned()), retries)
         })
         .await
     }
@@ -1621,7 +1590,10 @@ impl ManagerServer {
         drift across renames. Status reads `` when the target has never called \
         `set_status` or has cleared it."
     )]
-    async fn get_agent_meta(&self, Parameters(args): Parameters) -> String {
+    async fn get_agent_meta(
+        &self,
+        Parameters(args): Parameters,
+    ) -> String {
         let log = args.name.clone().unwrap_or_else(|| "".to_owned());
         run_tool_envelope("get_agent_meta", log, async move {
             let (resp, retries) = self
@@ -1656,11 +1628,7 @@ impl ManagerServer {
                 .dispatch(hive_sh4re::ManagerRequest::CancelLooseEnd { kind, id })
                 .await;
             annotate_retries(
-                format_ack(
-                    resp,
-                    "cancel_loose_end",
-                    format!("cancelled {kind_label} {id}"),
-                ),
+                format_ack(resp, "cancel_loose_end", format!("cancelled {kind_label} {id}")),
                 retries,
             )
         })
@@ -1832,7 +1800,10 @@ pub fn allowed_tools_arg(flavor: Flavor) -> String {
                 if patterns.is_empty() {
                     vec!["Bash".to_owned()]
                 } else {
-                    patterns.into_iter().map(|p| format!("Bash({p})")).collect()
+                    patterns
+                        .into_iter()
+                        .map(|p| format!("Bash({p})"))
+                        .collect()
                 }
             } else {
                 vec![(*s).to_owned()]
diff --git a/hive-ag3nt/src/turn.rs b/hive-ag3nt/src/turn.rs
index 28f56205..f18a53f5 100644
--- a/hive-ag3nt/src/turn.rs
+++ b/hive-ag3nt/src/turn.rs
@@ -15,7 +15,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
 use tokio::process::Command;
 
 use crate::events::{Bus, LiveEvent};
-use crate::login::LoginState;
+use crate::login::{self, LoginState};
 use crate::mcp;
 
 /// `--settings` JSON applied to every claude invocation. Lives as a
@@ -235,7 +235,6 @@ fn effective_context_window(bus: &Bus) -> u64 {
 /// Resolve the auto-reset watermark. Priority order:
 /// 1. `HIVE_AUTO_RESET_WATERMARK_TOKENS` env var (explicit override).
 /// 2. 50% of `effective_context_window(bus)`.
-///
 /// `0` disables auto-reset entirely.
 fn auto_reset_watermark_tokens(bus: &Bus) -> u64 {
     if let Some(v) = std::env::var("HIVE_AUTO_RESET_WATERMARK_TOKENS")
@@ -260,7 +259,6 @@ fn cache_ttl_secs() -> u64 {
 /// Resolve the proactive-compaction watermark. Priority order:
 /// 1. `HIVE_COMPACT_WATERMARK_TOKENS` env var (explicit override).
 /// 2. 75% of `effective_context_window(bus)`.
-///
 /// `0` disables proactive compaction (reactive path still applies).
 fn compact_watermark_tokens(bus: &Bus) -> u64 {
     if let Some(v) = std::env::var("HIVE_COMPACT_WATERMARK_TOKENS")
@@ -301,7 +299,9 @@ pub async fn drive_turn(prompt: &str, files: &TurnFiles, bus: &Bus) -> TurnOutco
             // /compact itself would be absurd recursion; bubble it up as
             // a normal failure path.
             match compact_session(files, bus).await {
-                TurnOutcome::Ok | TurnOutcome::Compacted => run_turn(prompt, files, bus).await,
+                TurnOutcome::Ok | TurnOutcome::Compacted => {
+                    run_turn(prompt, files, bus).await
+                }
                 other => return other,
             }
         }
@@ -315,9 +315,10 @@ pub async fn drive_turn(prompt: &str, files: &TurnFiles, bus: &Bus) -> TurnOutco
     // turn overflows into the reactive path. Best-effort — never changes
     // the outcome of the turn that already succeeded, but records it as
     // `Compacted` so turn stats can distinguish it from a plain `Ok`.
-    if matches!(outcome, TurnOutcome::Ok) && maybe_checkpoint_and_compact(files, bus).await {
-        return TurnOutcome::Compacted;
-    }
+    if matches!(outcome, TurnOutcome::Ok)
+        && maybe_checkpoint_and_compact(files, bus).await {
+            return TurnOutcome::Compacted;
+        }
     outcome
 }
 
@@ -463,20 +464,9 @@ pub fn emit_turn_end(bus: &Bus, outcome: &TurnOutcome) {
     }
 }
 
-/// Block until the bound `~/.claude/` dir contains a session that
-/// post-dates this call, polling on a `poll_ms` interval (min 2s).
-/// Flips `state` to `Online` when login lands; caller resumes its
-/// serve loop.
-///
-/// **Mtime-progress, not bare existence (closes #542)**: an
-/// existence-only check (the pre-#542 behaviour) immediately returns
-/// after a 401 because the stale `credentials.json` is still on disk
-/// — the next turn then 401s on the same tokens and the harness
-/// loops forever. We snapshot the newest file mtime in `claude_dir`
-/// at entry and only resume when something has been written since
-/// that snapshot (the operator's `/login/code` flow lands a refreshed
-/// credentials file, bumping its mtime). First-time login (empty
-/// dir → `None` snapshot) still flips on the first file appearing.
+/// Block until the bound `~/.claude/` dir contains a session, polling
+/// `claude_dir` on a `poll_ms` interval (min 2s). Flips `state` to
+/// `Online` when login lands; caller resumes its serve loop.
 ///
 /// # Panics
 ///
@@ -491,12 +481,11 @@ pub async fn wait_for_login(
         claude_dir = %claude_dir.display(),
         "no claude session — staying in partial-run mode (web UI only)"
     );
-    let snapshot = snapshot_dir(claude_dir);
     let probe = Duration::from_millis(poll_ms.max(2000));
     loop {
         tokio::time::sleep(probe).await;
-        if session_refreshed(snapshot, snapshot_dir(claude_dir)) {
-            tracing::info!("claude session refreshed — entering turn loop");
+        if login::has_session(claude_dir) {
+            tracing::info!("claude session detected — entering turn loop");
             *state.lock().unwrap() = LoginState::Online;
             bus.emit_status("online");
             return;
@@ -504,61 +493,6 @@ pub async fn wait_for_login(
     }
 }
 
-/// Snapshot of the credentials dir at a point in time: number of
-/// regular files + newest `mtime` across them. The two axes are both
-/// load-bearing for `wait_for_login`'s refresh check (`session_refreshed`):
-/// mtime catches the common case (re-login overwrites an existing
-/// credentials file in-place), file_count catches the pathological case
-/// where `meta.modified()` errors on every file (exotic fs, NFS quirks)
-/// so the mtime axis stays `None` forever but new files still trigger a
-/// resume. Defaults to `{0, None}` on read_dir failure (missing or
-/// unreadable dir) — `wait_for_login` then resumes when files first
-/// appear.
-#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
-struct DirSnapshot {
-    file_count: usize,
-    newest_mtime: Option,
-}
-
-fn snapshot_dir(dir: &Path) -> DirSnapshot {
-    let Ok(entries) = std::fs::read_dir(dir) else {
-        return DirSnapshot::default();
-    };
-    let mut snap = DirSnapshot::default();
-    for entry in entries.flatten() {
-        if !entry.file_type().is_ok_and(|t| t.is_file()) {
-            continue;
-        }
-        snap.file_count += 1;
-        let Ok(meta) = entry.metadata() else { continue };
-        let Ok(mtime) = meta.modified() else { continue };
-        if snap.newest_mtime.is_none_or(|cur| mtime > cur) {
-            snap.newest_mtime = Some(mtime);
-        }
-    }
-    snap
-}
-
-/// Has the credentials dir been written since `prev`? Used as the
-/// exit condition for `wait_for_login`:
-///
-/// - file_count changed → something was added or removed, treat as
-///   refresh (covers the "all files have unreadable mtime" edge case).
-/// - newest_mtime advanced → existing file was rewritten in place
-///   (the common claude re-login path).
-/// - prev had no mtime (empty or all-unreadable) and now has one →
-///   first useful signal we've seen, treat as refresh.
-fn session_refreshed(prev: DirSnapshot, now: DirSnapshot) -> bool {
-    if now.file_count != prev.file_count {
-        return true;
-    }
-    match (prev.newest_mtime, now.newest_mtime) {
-        (None, Some(_)) => true,
-        (Some(p), Some(n)) => n > p,
-        _ => false,
-    }
-}
-
 /// Spawn `claude` for one turn and pump `stream-json` stdout into the
 /// live event bus. Prompt goes over stdin (variadic
 /// `--allowedTools`/`--tools` would otherwise eat a trailing positional
@@ -706,48 +640,53 @@ async fn run_claude(prompt: &str, files: &TurnFiles, bus: &Bus) -> Result<(bool,
             if AUTH_FAIL_MARKERS.iter().any(|m| line.contains(m)) {
                 auth_out.store(true, Ordering::Relaxed);
             }
-            if let Ok(v) = serde_json::from_str::(&line) {
-                // Rate-limit detection: only fire on JSON `error` events,
-                // not on arbitrary text content. An agent discussing a past
-                // rate limit in its response would otherwise trigger a false
-                // positive (the full conversation flows through stdout as
-                // stream-json, so any text the model outputs is visible here).
-                if v.get("type").and_then(|t| t.as_str()) == Some("error") {
-                    let raw = v.to_string();
-                    if RATE_LIMIT_MARKERS.iter().any(|m| raw.contains(m)) {
+            match serde_json::from_str::(&line) {
+                Ok(v) => {
+                    // Rate-limit detection: only fire on JSON `error` events,
+                    // not on arbitrary text content. An agent discussing a past
+                    // rate limit in its response would otherwise trigger a false
+                    // positive (the full conversation flows through stdout as
+                    // stream-json, so any text the model outputs is visible here).
+                    if v.get("type").and_then(|t| t.as_str()) == Some("error") {
+                        let raw = v.to_string();
+                        if RATE_LIMIT_MARKERS.iter().any(|m| raw.contains(m)) {
+                            rate_out.store(true, Ordering::Relaxed);
+                        }
+                    }
+                    if let Some(u) = crate::events::TokenUsage::from_assistant_event(&v) {
+                        last_inference = Some(u);
+                    }
+                    if let Some(cost) = crate::events::TokenUsage::from_stream_event(&v) {
+                        // Fallback to `cost` if the turn somehow produced
+                        // a result without any assistant event — keeps the
+                        // ctx badge from going stale on a degenerate turn.
+                        let ctx = last_inference.unwrap_or(cost);
+                        bus_out.record_turn_usage(ctx, cost);
+                    }
+                    // Seed the API-reported context-window from the result
+                    // event's `modelUsage.*.contextWindow` field. This is
+                    // the authoritative per-inference active window used for
+                    // compaction watermarks — it reflects what the model
+                    // actually enforces, which may differ from the Nix
+                    // config (e.g. 200k active window on a 1M cache model).
+                    if let Some(w) =
+                        crate::events::TokenUsage::context_window_from_result_event(&v)
+                    {
+                        bus_out.set_api_context_window(w);
+                    }
+                    bus_out.observe_stream(&v);
+                    bus_out.emit(LiveEvent::Stream(v));
+                }
+                Err(_) => {
+                    // Non-JSON stdout: raw text check is fine here since these
+                    // are claude CLI messages, not conversation content.
+                    if RATE_LIMIT_MARKERS.iter().any(|m| line.contains(m)) {
                         rate_out.store(true, Ordering::Relaxed);
                     }
+                    bus_out.emit(LiveEvent::Note {
+                        text: format!("(non-json) {line}"),
+                    });
                 }
-                if let Some(u) = crate::events::TokenUsage::from_assistant_event(&v) {
-                    last_inference = Some(u);
-                }
-                if let Some(cost) = crate::events::TokenUsage::from_stream_event(&v) {
-                    // Fallback to `cost` if the turn somehow produced
-                    // a result without any assistant event — keeps the
-                    // ctx badge from going stale on a degenerate turn.
-                    let ctx = last_inference.unwrap_or(cost);
-                    bus_out.record_turn_usage(ctx, cost);
-                }
-                // Seed the API-reported context-window from the result
-                // event's `modelUsage.*.contextWindow` field. This is
-                // the authoritative per-inference active window used for
-                // compaction watermarks — it reflects what the model
-                // actually enforces, which may differ from the Nix
-                // config (e.g. 200k active window on a 1M cache model).
-                if let Some(w) = crate::events::TokenUsage::context_window_from_result_event(&v) {
-                    bus_out.set_api_context_window(w);
-                }
-                bus_out.observe_stream(&v);
-                bus_out.emit(LiveEvent::Stream(v));
-            } else {
-                // Non-JSON stdout: raw text check is fine here since these
-                // are claude CLI messages, not conversation content.
-                if RATE_LIMIT_MARKERS.iter().any(|m| line.contains(m)) {
-                    rate_out.store(true, Ordering::Relaxed);
-                }
-                bus_out.emit(LiveEvent::Note {
-                    text: format!("(non-json) {line}"),
-                });
             }
         }
     });
@@ -798,114 +737,3 @@ async fn run_claude(prompt: &str, files: &TurnFiles, bus: &Bus) -> Result<(bool,
     }
     Ok((too_long, is_rate_limited, is_auth_failed))
 }
-
-#[cfg(test)]
-mod tests {
-    use std::fs;
-    use std::time::{Duration, SystemTime};
-
-    use super::{DirSnapshot, session_refreshed, snapshot_dir};
-
-    #[test]
-    fn snapshot_dir_empty_dir_is_default() {
-        let dir = tempfile::tempdir().unwrap();
-        let snap = snapshot_dir(dir.path());
-        assert_eq!(snap.file_count, 0);
-        assert!(snap.newest_mtime.is_none());
-    }
-
-    #[test]
-    fn snapshot_dir_missing_dir_is_default() {
-        // Defensive: a nonexistent dir must NOT panic. Bind mounts that
-        // disappear mid-poll (host purge during operator intervention)
-        // would otherwise crash the harness.
-        let missing = tempfile::tempdir()
-            .unwrap()
-            .path()
-            .join("never-created-subdir");
-        let snap = snapshot_dir(&missing);
-        assert_eq!(snap, DirSnapshot::default());
-    }
-
-    #[test]
-    fn snapshot_dir_picks_latest_mtime_and_counts_files() {
-        let dir = tempfile::tempdir().unwrap();
-        fs::write(dir.path().join("old.json"), b"{}").unwrap();
-        // Sleep so the second file's mtime is strictly greater than
-        // the first on filesystems with low timestamp resolution.
-        std::thread::sleep(Duration::from_millis(20));
-        let newer_path = dir.path().join("newer.json");
-        fs::write(&newer_path, b"{}").unwrap();
-        let snap = snapshot_dir(dir.path());
-        assert_eq!(snap.file_count, 2);
-        let newer_meta = fs::metadata(&newer_path).unwrap().modified().unwrap();
-        assert_eq!(snap.newest_mtime, Some(newer_meta));
-    }
-
-    #[test]
-    fn session_refreshed_first_login_flips_on_any_file() {
-        // Empty-dir snapshot → any file appearing means a fresh
-        // login landed. Pre-#542 semantics for first-time login.
-        let dir = tempfile::tempdir().unwrap();
-        let snapshot = snapshot_dir(dir.path());
-        assert!(!session_refreshed(snapshot, snapshot_dir(dir.path())));
-        fs::write(dir.path().join("credentials.json"), b"{}").unwrap();
-        assert!(session_refreshed(snapshot, snapshot_dir(dir.path())));
-    }
-
-    #[test]
-    fn session_refreshed_stale_creds_dont_flip_immediately() {
-        // The #542 repro: stale credentials.json already exists at
-        // entry; wait_for_login must NOT immediately return — it
-        // would loop straight into another 401-failing turn.
-        let dir = tempfile::tempdir().unwrap();
-        fs::write(dir.path().join("credentials.json"), b"{}").unwrap();
-        let snapshot = snapshot_dir(dir.path());
-        assert_eq!(snapshot.file_count, 1);
-        // No change to the file → loop must NOT exit.
-        assert!(!session_refreshed(snapshot, snapshot_dir(dir.path())));
-    }
-
-    #[test]
-    fn session_refreshed_after_creds_rewrite_flips() {
-        // After the stale-creds snapshot, the operator's `/login/code`
-        // flow lands a refreshed credentials file — its mtime bumps
-        // strictly past the snapshot and wait_for_login resumes.
-        let dir = tempfile::tempdir().unwrap();
-        fs::write(dir.path().join("credentials.json"), b"{}").unwrap();
-        let snapshot = snapshot_dir(dir.path());
-        std::thread::sleep(Duration::from_millis(20));
-        fs::write(dir.path().join("credentials.json"), b"{\"v\":2}").unwrap();
-        assert!(session_refreshed(snapshot, snapshot_dir(dir.path())));
-    }
-
-    #[test]
-    fn session_refreshed_snapshot_with_future_mtime_doesnt_flip() {
-        // Defensive: a snapshot set to a future timestamp (e.g. clock
-        // skew between snapshot and probe) must keep waiting until a
-        // file's mtime actually exceeds it, not return on first poll.
-        let dir = tempfile::tempdir().unwrap();
-        fs::write(dir.path().join("credentials.json"), b"{}").unwrap();
-        let snapshot = DirSnapshot {
-            file_count: 1,
-            newest_mtime: Some(SystemTime::now() + Duration::from_secs(3600)),
-        };
-        assert!(!session_refreshed(snapshot, snapshot_dir(dir.path())));
-    }
-
-    #[test]
-    fn session_refreshed_count_change_flips_when_mtime_unreadable() {
-        // Defensive (argus #545 nit): if all files have unreadable
-        // `meta.modified()` (exotic fs / NFS), newest_mtime stays
-        // `None` forever — but file_count axis still catches new
-        // files appearing. Simulated here by forging a snapshot with
-        // file_count=1 + no mtime, then writing a second file.
-        let dir = tempfile::tempdir().unwrap();
-        fs::write(dir.path().join("a"), b"{}").unwrap();
-        let forged = DirSnapshot { file_count: 1, newest_mtime: None };
-        fs::write(dir.path().join("b"), b"{}").unwrap();
-        // Real snapshot has file_count=2, so refresh fires even
-        // though the mtime axis would be inconclusive.
-        assert!(session_refreshed(forged, snapshot_dir(dir.path())));
-    }
-}
diff --git a/hive-c0re/Cargo.toml b/hive-c0re/Cargo.toml
index a97e91c9..73749066 100644
--- a/hive-c0re/Cargo.toml
+++ b/hive-c0re/Cargo.toml
@@ -4,7 +4,7 @@ edition.workspace = true
 version.workspace = true
 # Render branding/agent-configs.svg → $OUT_DIR/agent-configs.png at
 # compile time (#424). build.rs shells out to `rsvg-convert`
-# (librsvg, pulled in via flake.nix' crane nativeBuildInputs); the
+# (librsvg, pulled in via flake.nix' naersk nativeBuildInputs); the
 # baked PNG is included via include_bytes! from forge.rs so no
 # raster gets checked into git.
 build = "build.rs"
diff --git a/hive-c0re/build.rs b/hive-c0re/build.rs
index c8bf3fc4..5e475c36 100644
--- a/hive-c0re/build.rs
+++ b/hive-c0re/build.rs
@@ -5,7 +5,7 @@
 //! artifact.
 //!
 //! Uses `rsvg-convert` from PATH (librsvg, already available in
-//! nixpkgs and added to the crane derivation's `nativeBuildInputs`
+//! nixpkgs and added to the naersk derivation's `nativeBuildInputs`
 //! in `flake.nix`). For dev builds outside Nix, install librsvg via
 //! your system package manager (Debian/Ubuntu: `librsvg2-bin`,
 //! macOS: `brew install librsvg`).
@@ -43,7 +43,7 @@ fn main() {
             "failed to invoke rsvg-convert: {e}\n\
              install librsvg (Debian/Ubuntu: librsvg2-bin, macOS: brew install librsvg, \
              NixOS: pkgs.librsvg). The Nix derivation already pulls it in via \
-             flake.nix → craneLib.buildPackage.nativeBuildInputs.",
+             flake.nix → naersk-lib.buildPackage.nativeBuildInputs.",
         ),
     }
 }
diff --git a/hive-c0re/src/actions.rs b/hive-c0re/src/actions.rs
index 3ad26267..76998cf1 100644
--- a/hive-c0re/src/actions.rs
+++ b/hive-c0re/src/actions.rs
@@ -151,18 +151,21 @@ async fn run_approval_schedule_prompt(
     approval: hive_sh4re::Approval,
 ) -> Result<()> {
     let result: Result<()> = async {
-        let payload: hive_sh4re::SchedulePromptPayload = serde_json::from_str(&approval.commit_ref)
-            .context("decode SchedulePromptPayload from approval.commit_ref")?;
+        let payload: hive_sh4re::SchedulePromptPayload =
+            serde_json::from_str(&approval.commit_ref)
+                .context("decode SchedulePromptPayload from approval.commit_ref")?;
         coord
             .scheduled_prompts
-            .submit(&crate::scheduled_prompts::NewSchedule {
+            .submit(crate::scheduled_prompts::NewSchedule {
                 owner: approval.agent.clone(),
                 targets: payload.targets,
                 body: payload.body,
                 first_fire_at_unix: payload.first_fire_at_unix,
                 interval_seconds: payload.interval_seconds,
                 description: payload.description,
-                source: crate::scheduled_prompts::ScheduleSource::Approval { id: approval.id },
+                source: crate::scheduled_prompts::ScheduleSource::Approval {
+                    id: approval.id,
+                },
             })
             .map(|_| ())
             .context("insert scheduled prompt")
@@ -287,10 +290,9 @@ async fn forge_after_first_spawn(coord: &Arc, agent: &str) {
         tracing::warn!(%agent, error = ?e, "forge: ensure_config_repo after first spawn failed");
     }
     if let Some(core_token) = crate::forge::core_token()
-        && let Err(e) = crate::forge::meta_read_access(agent, &core_token).await
-    {
-        tracing::warn!(%agent, error = ?e, "forge: meta_read_access after first spawn failed");
-    }
+        && let Err(e) = crate::forge::meta_read_access(agent, &core_token).await {
+            tracing::warn!(%agent, error = ?e, "forge: meta_read_access after first spawn failed");
+        }
     if let Err(e) = crate::forge::ensure_meta_remote(agent).await {
         tracing::warn!(%agent, error = ?e, "forge: ensure_meta_remote after first spawn failed");
     }
@@ -464,7 +466,7 @@ async fn run_apply_commit(
                 Err(anyhow::anyhow!("read applied/main: {e:#}")),
                 None,
                 is_first_spawn,
-            );
+            )
         }
     };
 
@@ -519,7 +521,8 @@ async fn run_apply_commit(
             Ok(a) => a,
             Err(e) => {
                 let _ =
-                    lifecycle::git_update_ref(applied_dir, "refs/heads/main", &prev_main_sha).await;
+                    lifecycle::git_update_ref(applied_dir, "refs/heads/main", &prev_main_sha)
+                        .await;
                 let _ = lifecycle::git_read_tree_reset(applied_dir, "refs/heads/main").await;
                 return (
                     Err(anyhow::anyhow!("agents_for_meta_listing_with: {e:#}")),
@@ -537,7 +540,8 @@ async fn run_apply_commit(
         )
         .await
         {
-            let _ = lifecycle::git_update_ref(applied_dir, "refs/heads/main", &prev_main_sha).await;
+            let _ =
+                lifecycle::git_update_ref(applied_dir, "refs/heads/main", &prev_main_sha).await;
             let _ = lifecycle::git_read_tree_reset(applied_dir, "refs/heads/main").await;
             return (
                 Err(anyhow::anyhow!("meta sync_agents for first spawn: {e:#}")),
diff --git a/hive-c0re/src/approvals.rs b/hive-c0re/src/approvals.rs
index df9979fd..957fff1f 100644
--- a/hive-c0re/src/approvals.rs
+++ b/hive-c0re/src/approvals.rs
@@ -251,11 +251,9 @@ impl Approvals {
     /// kind / agent / sha. Errors if the approval isn't pending — once
     /// it's approved/denied/failed/cancelled, the resolution is final.
     pub fn mark_cancelled(&self, id: i64, canceller: &str) -> Result {
-        // Row-shape alias for the SELECT below so we don't trip
-        // clippy::type_complexity. Order matches the SELECT projection:
-        // agent, kind, commit_ref, requested_at, status, fetched_sha,
-        // description.
-        type CancelLookupRow = (
+        let mut conn = self.conn.lock().unwrap();
+        let tx = conn.transaction()?;
+        let row: Option<(
             String,
             String,
             String,
@@ -263,10 +261,7 @@ impl Approvals {
             String,
             Option,
             Option,
-        );
-        let mut conn = self.conn.lock().unwrap();
-        let tx = conn.transaction()?;
-        let row: Option = tx
+        )> = tx
             .query_row(
                 "SELECT agent, kind, commit_ref, requested_at, status, fetched_sha, description
                    FROM approvals WHERE id = ?1",
@@ -331,7 +326,9 @@ impl Approvals {
 /// bad row used to make `pending()` / `recent_resolved()` error out
 /// wholesale — the dashboard then rendered an empty approvals queue
 /// (issue #160, an unhandled `init_config` kind poisoning every read).
-fn collect_lenient(rows: impl Iterator>) -> Vec {
+fn collect_lenient(
+    rows: impl Iterator>,
+) -> Vec {
     rows.filter_map(|r| match r {
         Ok(a) => Some(a),
         Err(e) => {
@@ -470,12 +467,7 @@ mod tests {
         // status + a "cancelled by " note.
         let (_dir, _path, db) = open_temp();
         let id = db
-            .submit_kind(
-                "bitburner",
-                ApprovalKind::ApplyCommit,
-                "cafef00d",
-                Some("test"),
-            )
+            .submit_kind("bitburner", ApprovalKind::ApplyCommit, "cafef00d", Some("test"))
             .unwrap();
         let row = db.mark_cancelled(id, "manager").expect("cancel");
         assert_eq!(row.id, id);
diff --git a/hive-c0re/src/auto_update.rs b/hive-c0re/src/auto_update.rs
index dbf75e86..31799898 100644
--- a/hive-c0re/src/auto_update.rs
+++ b/hive-c0re/src/auto_update.rs
@@ -65,7 +65,7 @@ pub fn agent_config_pending(name: &str, deployed_sha: Option<&str>) -> bool {
 /// can't diverge.
 ///
 /// `queue_entry_id` is `Some(id)` when the rebuild was dispatched from
-/// the `rebuild_queue` worker (lets the function annotate its phase via
+/// the rebuild_queue worker (lets the function annotate its phase via
 /// `coord.set_queue_step`) and `None` when called directly (e.g. the
 /// manager-migration nudge in `ensure_manager`).
 pub async fn rebuild_agent(
@@ -220,10 +220,7 @@ pub async fn run(coord: Arc) -> Result<()> {
 
     let _current_rev = current_flake_rev(&coord.hyperhive_flake).unwrap_or_default();
 
-    tracing::info!(
-        agents = containers.len(),
-        "auto-update: queueing all on startup"
-    );
+    tracing::info!(agents = containers.len(), "auto-update: queueing all on startup");
     for container in containers {
         let logical = if container == MANAGER_NAME {
             Some(MANAGER_NAME.to_owned())
diff --git a/hive-c0re/src/crash_watch.rs b/hive-c0re/src/crash_watch.rs
index 1c844d4d..fb7fd755 100644
--- a/hive-c0re/src/crash_watch.rs
+++ b/hive-c0re/src/crash_watch.rs
@@ -139,46 +139,6 @@ fn is_deliberate_stop(
     active.is_some_and(is_op_kind) || recently_cleared.is_some_and(is_op_kind)
 }
 
-fn emit_login_transitions(
-    coord: &Coordinator,
-    prev: &HashSet,
-    current: &HashSet,
-    sub_agents: &[String],
-    prev_sub_agents: &HashSet,
-) {
-    for agent in current.difference(prev) {
-        tracing::info!(%agent, "agent logged in");
-        coord.notify_manager(&hive_sh4re::HelperEvent::LoggedIn {
-            agent: agent.clone(),
-        });
-    }
-    // Detect transitions into "needs login": an agent that was previously
-    // logged-in goes unsigned (credentials deleted), OR a brand-new agent
-    // appears without a session.
-    //
-    // prev_needs uses prev_sub_agents (the agent set from the last tick) so
-    // that a newly-spawned agent — which does not appear in prev_sub_agents —
-    // is absent from prev_needs even though it's not in prev_logged_in.
-    // Without this, new agents land in both prev_needs and current_needs and
-    // the set difference is empty, silently dropping the event.
-    let prev_needs: HashSet<&str> = prev_sub_agents
-        .iter()
-        .map(String::as_str)
-        .filter(|n| !prev.contains(*n))
-        .collect();
-    let current_needs: HashSet<&str> = sub_agents
-        .iter()
-        .map(String::as_str)
-        .filter(|n| !current.contains(*n))
-        .collect();
-    for agent in current_needs.difference(&prev_needs) {
-        tracing::info!(%agent, "agent needs login");
-        coord.notify_manager(&hive_sh4re::HelperEvent::NeedsLogin {
-            agent: (*agent).to_owned(),
-        });
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -226,3 +186,44 @@ mod tests {
         }
     }
 }
+
+fn emit_login_transitions(
+    coord: &Coordinator,
+    prev: &HashSet,
+    current: &HashSet,
+    sub_agents: &[String],
+    prev_sub_agents: &HashSet,
+) {
+    for agent in current.difference(prev) {
+        tracing::info!(%agent, "agent logged in");
+        coord.notify_manager(&hive_sh4re::HelperEvent::LoggedIn {
+            agent: agent.clone(),
+        });
+    }
+    // Detect transitions into "needs login": an agent that was previously
+    // logged-in goes unsigned (credentials deleted), OR a brand-new agent
+    // appears without a session.
+    //
+    // prev_needs uses prev_sub_agents (the agent set from the last tick) so
+    // that a newly-spawned agent — which does not appear in prev_sub_agents —
+    // is absent from prev_needs even though it's not in prev_logged_in.
+    // Without this, new agents land in both prev_needs and current_needs and
+    // the set difference is empty, silently dropping the event.
+    let prev_needs: HashSet<&str> = prev_sub_agents
+        .iter()
+        .map(String::as_str)
+        .filter(|n| !prev.contains(*n))
+        .collect();
+    let current_needs: HashSet<&str> = sub_agents
+        .iter()
+        .map(String::as_str)
+        .filter(|n| !current.contains(*n))
+        .collect();
+    for agent in current_needs.difference(&prev_needs) {
+        tracing::info!(%agent, "agent needs login");
+        coord.notify_manager(&hive_sh4re::HelperEvent::NeedsLogin {
+            agent: (*agent).to_owned(),
+        });
+    }
+}
+
diff --git a/hive-c0re/src/dashboard.rs b/hive-c0re/src/dashboard.rs
index 39b284a0..0a79bf11 100644
--- a/hive-c0re/src/dashboard.rs
+++ b/hive-c0re/src/dashboard.rs
@@ -76,13 +76,13 @@ pub async fn serve(port: u16, coord: Arc) -> Result<()> {
         .route("/op-send", post(post_op_send))
         .route("/meta-update", post(post_meta_update))
         .route("/api/schedules", get(api_schedules).post(post_schedule_new))
-        .route("/api/schedules/{id}", axum::routing::patch(patch_schedule))
+        .route(
+            "/api/schedules/{id}",
+            axum::routing::patch(patch_schedule),
+        )
         .route("/api/schedules/{id}/cancel", post(post_schedule_cancel))
         .route("/api/schedules/{id}/fire-now", post(post_schedule_fire_now))
-        .route(
-            "/api/rebuild-queue/{id}/cancel",
-            post(post_rebuild_queue_cancel),
-        )
+        .route("/api/rebuild-queue/{id}/cancel", post(post_rebuild_queue_cancel))
         .route("/dashboard/stream", get(dashboard_stream))
         .route("/dashboard/history", get(dashboard_history))
         // Anything not matched by the dynamic routes above falls
@@ -765,14 +765,7 @@ async fn dashboard_history(State(state): State) -> Response {
             let events: Vec = messages
                 .into_iter()
                 .map(|m| match m {
-                    crate::broker::MessageEvent::Sent {
-                        id,
-                        from,
-                        to,
-                        body,
-                        at,
-                        in_reply_to,
-                    } => {
+                    crate::broker::MessageEvent::Sent { id, from, to, body, at, in_reply_to } => {
                         let file_refs = scan_validated_paths(&body);
                         crate::dashboard_events::DashboardEvent::Sent {
                             seq: 0,
@@ -785,14 +778,7 @@ async fn dashboard_history(State(state): State) -> Response {
                             file_refs,
                         }
                     }
-                    crate::broker::MessageEvent::Delivered {
-                        id,
-                        from,
-                        to,
-                        body,
-                        at,
-                        in_reply_to,
-                    } => {
+                    crate::broker::MessageEvent::Delivered { id, from, to, body, at, in_reply_to } => {
                         let file_refs = scan_validated_paths(&body);
                         crate::dashboard_events::DashboardEvent::Delivered {
                             seq: 0,
@@ -1169,8 +1155,8 @@ fn resolve_state_path(
             return Err(format!("path not in allow-list: {raw}"));
         };
     reject_symlinks_below(std::path::Path::new(root), &mapped)?;
-    let canonical =
-        std::fs::canonicalize(&mapped).map_err(|e| format!("{}: {e}", mapped.display()))?;
+    let canonical = std::fs::canonicalize(&mapped)
+        .map_err(|e| format!("{}: {e}", mapped.display()))?;
     if !(canonical.starts_with(AGENTS_ROOT) || canonical.starts_with(SHARED_ROOT)) {
         return Err(format!(
             "resolved path escapes allow-list: {}",
@@ -1188,8 +1174,8 @@ fn resolve_state_path(
             ));
         }
     }
-    let meta =
-        std::fs::metadata(&canonical).map_err(|e| format!("stat {}: {e}", canonical.display()))?;
+    let meta = std::fs::metadata(&canonical)
+        .map_err(|e| format!("stat {}: {e}", canonical.display()))?;
     if meta.is_file() {
         let mode = meta.permissions().mode();
         if mode & 0o004 == 0 {
@@ -1327,10 +1313,12 @@ pub(crate) async fn emit_tombstones_snapshot(coord: &Arc) {
     let containers = coord.containers_snapshot().await;
     let transient_snapshot = coord.transient_snapshot();
     let tombstones = build_tombstone_views(coord, &containers, &transient_snapshot);
-    coord.emit_dashboard_event(crate::dashboard_events::DashboardEvent::TombstonesChanged {
-        seq: coord.next_seq(),
-        tombstones,
-    });
+    coord.emit_dashboard_event(
+        crate::dashboard_events::DashboardEvent::TombstonesChanged {
+            seq: coord.next_seq(),
+            tombstones,
+        },
+    );
 }
 
 /// Snapshot meta/flake.lock's root inputs + emit
@@ -1338,10 +1326,12 @@ pub(crate) async fn emit_tombstones_snapshot(coord: &Arc) {
 /// (`run_meta_update`, `auto_update::rebuild_agent`).
 pub(crate) fn emit_meta_inputs_snapshot(coord: &Coordinator) {
     let inputs = read_meta_inputs();
-    coord.emit_dashboard_event(crate::dashboard_events::DashboardEvent::MetaInputsChanged {
-        seq: coord.next_seq(),
-        inputs,
-    });
+    coord.emit_dashboard_event(
+        crate::dashboard_events::DashboardEvent::MetaInputsChanged {
+            seq: coord.next_seq(),
+            inputs,
+        },
+    );
 }
 
 /// Scan `body` for path-shaped tokens, validate each against the
@@ -1391,7 +1381,9 @@ pub(crate) fn scan_validated_paths(body: &str) -> Vec {
     out
 }
 
-async fn get_state_file(axum::extract::Query(q): axum::extract::Query) -> Response {
+async fn get_state_file(
+    axum::extract::Query(q): axum::extract::Query,
+) -> Response {
     const MAX_BYTES: usize = 1 << 20; // 1 MiB
     let (canonical, meta) = match resolve_state_path(&q.path) {
         Ok(pair) => pair,
@@ -1423,18 +1415,11 @@ async fn get_state_file(axum::extract::Query(q): axum::extract::Query MAX_BYTES;
-    let body_bytes = if truncated {
-        &bytes[..MAX_BYTES]
-    } else {
-        &bytes[..]
-    };
+    let body_bytes = if truncated { &bytes[..MAX_BYTES] } else { &bytes[..] };
     let mut body = String::from_utf8_lossy(body_bytes).into_owned();
     if truncated {
         use std::fmt::Write as _;
-        let _ = write!(
-            body,
-            "\n\n--- truncated at {MAX_BYTES} of {size} bytes ---\n"
-        );
+        let _ = write!(body, "\n\n--- truncated at {MAX_BYTES} of {size} bytes ---\n");
     }
     ([("content-type", "text/plain; charset=utf-8")], body).into_response()
 }
@@ -1507,7 +1492,7 @@ async fn post_schedule_new(
         description: payload.description,
         source: crate::scheduled_prompts::ScheduleSource::Operator,
     };
-    match state.coord.scheduled_prompts.submit(&new) {
+    match state.coord.scheduled_prompts.submit(new) {
         Ok(id) => axum::Json(serde_json::json!({"id": id})).into_response(),
         Err(e) => error_response(&format!("schedule submit: {e:#}")),
     }
@@ -1561,12 +1546,6 @@ struct CancelScheduleForm {
 }
 
 #[derive(serde::Deserialize, Default)]
-#[allow(
-    clippy::option_option,
-    reason = "double-Option carries three-state PATCH semantics on the wire \
-              (missing key = leave alone, JSON null = clear, value = set); \
-              collapsing to a single Option would lose the 'clear' state"
-)]
 struct EditScheduleForm {
     #[serde(default)]
     body: Option,
@@ -1692,10 +1671,7 @@ async fn get_agent_links(AxumPath(name): AxumPath) -> Response {
     match client.get(&url).send().await {
         Ok(resp) if resp.status().is_success() => match resp.json::().await {
             Ok(body) => {
-                let links = body
-                    .get("links")
-                    .cloned()
-                    .unwrap_or_else(|| serde_json::json!([]));
+                let links = body.get("links").cloned().unwrap_or_else(|| serde_json::json!([]));
                 axum::Json(links).into_response()
             }
             Err(e) => {
@@ -1876,10 +1852,7 @@ async fn post_op_send(State(state): State, Form(form): Form) -> Vec {
         .collect()
 }
 
+
 /// Multi-file unified diff between the currently-deployed tree and
 /// the proposal for this approval. Runs against the applied repo
 /// since the canonical proposal commit lives there (manager-side
@@ -2308,3 +2282,4 @@ async fn get_approval_diff(
 fn plain_text(body: String) -> Response {
     (StatusCode::OK, body).into_response()
 }
+
diff --git a/hive-c0re/src/dashboard_events.rs b/hive-c0re/src/dashboard_events.rs
index 83a3fcac..0ae794a8 100644
--- a/hive-c0re/src/dashboard_events.rs
+++ b/hive-c0re/src/dashboard_events.rs
@@ -165,7 +165,10 @@ pub enum DashboardEvent {
     /// last one cached on the coordinator. Mutation sites (lifecycle
     /// endpoints, `actions::destroy` / approve, `crash_watch`'s poll loop)
     /// call the rescan after their work lands.
-    ContainerStateChanged { seq: u64, container: ContainerView },
+    ContainerStateChanged {
+        seq: u64,
+        container: ContainerView,
+    },
     /// A container that was in the previous snapshot is gone. Clients
     /// drop the row by name. Fired alongside any
     /// `nixos-container destroy` (operator-driven or otherwise) on the
@@ -208,9 +211,12 @@ pub enum DashboardEvent {
     /// snapshot-shape rationale as `TombstonesChanged` /
     /// `MetaInputsChanged`: the list is small, snapshot semantics avoid
     /// the add/remove races a per-row event would have, and the
-    /// dashboard's grouping (`parent_id`) is most naturally re-derived
+    /// dashboard's grouping (parent_id) is most naturally re-derived
     /// from the full list.
-    RebuildQueueChanged { seq: u64, queue: Vec },
+    RebuildQueueChanged {
+        seq: u64,
+        queue: Vec,
+    },
 }
 
 impl DashboardEvent {
@@ -253,18 +259,13 @@ mod tests {
     /// the `kind` JSON field matches `kind_tag()`. The exhaustive
     /// `match` in `kind_tag` already provides compile-time variant
     /// coverage — this test is the value-side guard against
-    /// typos in the `snake_case` strings vs serde's `rename_all`
+    /// typos in the snake_case strings vs serde's `rename_all`
     /// output. `ContainerStateChanged` is omitted from the sample
     /// list only because `ContainerView` has no `Default` impl and
     /// constructing one inline here is more boilerplate than the
     /// test is worth; the variant is still covered by the
     /// `kind_tag` match arm.
     #[test]
-    #[allow(
-        clippy::too_many_lines,
-        reason = "exhaustive coverage of every DashboardEvent variant — the \
-                  length is the point"
-    )]
     fn kind_tag_matches_serde_kind_field() {
         let samples: Vec = vec![
             DashboardEvent::Sent {
@@ -366,7 +367,11 @@ mod tests {
                 .get("kind")
                 .and_then(|k| k.as_str())
                 .expect("kind field present");
-            assert_eq!(ev.kind_tag(), serde_kind, "kind_tag() drift on {ev:?}",);
+            assert_eq!(
+                ev.kind_tag(),
+                serde_kind,
+                "kind_tag() drift on {ev:?}",
+            );
         }
     }
 }
diff --git a/hive-c0re/src/manager_server.rs b/hive-c0re/src/manager_server.rs
index 3eb20919..b23cbf40 100644
--- a/hive-c0re/src/manager_server.rs
+++ b/hive-c0re/src/manager_server.rs
@@ -90,11 +90,7 @@ fn manager_recv_timeout(wait_seconds: Option) -> std::time::Duration {
 #[allow(clippy::too_many_lines)]
 async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResponse {
     match req {
-        ManagerRequest::Send {
-            to,
-            body,
-            in_reply_to,
-        } => {
+        ManagerRequest::Send { to, body, in_reply_to } => {
             if let Err(message) = crate::limits::check_size("send", body) {
                 return ManagerResponse::Err { message };
             }
@@ -199,14 +195,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
             ) {
                 Ok(id) => {
                     tracing::info!(%id, %name, "init_config approval queued");
-                    coord.emit_approval_added(
-                        id,
-                        name,
-                        "init_config",
-                        None,
-                        None,
-                        description.clone(),
-                    );
+                    coord.emit_approval_added(id, name, "init_config", None, None, description.clone());
                     ManagerResponse::Ok
                 }
                 Err(e) => ManagerResponse::Err {
@@ -313,7 +302,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
                 Err(e) => {
                     return ManagerResponse::Err {
                         message: format!("queue update_meta_inputs approval: {e:#}"),
-                    };
+                    }
                 }
             };
             tracing::info!(%id, %label, "update_meta_inputs approval queued");
@@ -328,7 +317,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
             ManagerResponse::Ok
         }
         ManagerRequest::RequestSchedulePrompt(payload) => {
-            handle_request_schedule_prompt(coord, hive_sh4re::MANAGER_AGENT, payload)
+            handle_request_schedule_prompt(coord, hive_sh4re::MANAGER_AGENT, payload).await
         }
         ManagerRequest::CancelSchedule { id, targets } => {
             handle_cancel_schedule(coord, hive_sh4re::MANAGER_AGENT, *id, targets.as_deref())
@@ -493,13 +482,12 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
         ManagerRequest::SetStatus { text } => {
             let path = Coordinator::agent_notes_dir(MANAGER_AGENT).join("hyperhive-status");
             let result = if text.trim().is_empty() {
-                std::fs::remove_file(&path).or_else(|e| {
-                    if e.kind() == std::io::ErrorKind::NotFound {
+                std::fs::remove_file(&path)
+                    .or_else(|e| if e.kind() == std::io::ErrorKind::NotFound {
                         Ok(())
                     } else {
                         Err(e)
-                    }
-                })
+                    })
             } else {
                 std::fs::write(&path, format!("{}\n", text.trim()))
             };
@@ -509,9 +497,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
                     tokio::spawn(async move { coord2.rescan_containers_and_emit().await });
                     ManagerResponse::Ok
                 }
-                Err(e) => ManagerResponse::Err {
-                    message: format!("set_status write failed: {e}"),
-                },
+                Err(e) => ManagerResponse::Err { message: format!("set_status write failed: {e}") },
             }
         }
         ManagerRequest::GetAgentMeta { name } => {
@@ -522,12 +508,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
             // tell (e.g. "iris is down" vs "iris has no status set").
             let (status_text, status_set_at, running) =
                 crate::container_view::read_agent_status_live(target).await;
-            let role = if target == MANAGER_AGENT {
-                "manager"
-            } else {
-                "agent"
-            }
-            .to_owned();
+            let role = if target == MANAGER_AGENT { "manager" } else { "agent" }.to_owned();
             ManagerResponse::AgentMeta {
                 name: target.to_owned(),
                 role,
@@ -537,12 +518,16 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc) -> ManagerResp
                 status_set_at,
             }
         }
-        ManagerRequest::CancelLooseEnd { kind, id } => {
-            crate::questions::handle_cancel_loose_end(coord, MANAGER_AGENT, *kind, *id).map_or_else(
-                |message| ManagerResponse::Err { message },
-                |()| ManagerResponse::Ok,
-            )
-        }
+        ManagerRequest::CancelLooseEnd { kind, id } => crate::questions::handle_cancel_loose_end(
+            coord,
+            MANAGER_AGENT,
+            *kind,
+            *id,
+        )
+        .map_or_else(
+            |message| ManagerResponse::Err { message },
+            |()| ManagerResponse::Ok,
+        ),
         ManagerRequest::AckTurn => match coord.broker.ack_turn(MANAGER_AGENT) {
             Ok(_n) => ManagerResponse::Ok,
             Err(e) => ManagerResponse::Err {
@@ -721,7 +706,7 @@ async fn submit_apply_commit(
 /// inputs (non-empty targets, non-empty body, sane interval) at
 /// submit time — the operator should never see a malformed schedule
 /// pending approval.
-fn handle_request_schedule_prompt(
+async fn handle_request_schedule_prompt(
     coord: &Arc,
     requester: &str,
     payload: &hive_sh4re::SchedulePromptPayload,
@@ -746,7 +731,7 @@ fn handle_request_schedule_prompt(
         Err(e) => {
             return ManagerResponse::Err {
                 message: format!("encode SchedulePromptPayload: {e:#}"),
-            };
+            }
         }
     };
     let id = match coord.approvals.submit_kind(
@@ -759,7 +744,7 @@ fn handle_request_schedule_prompt(
         Err(e) => {
             return ManagerResponse::Err {
                 message: format!("queue schedule_prompt approval: {e:#}"),
-            };
+            }
         }
     };
     tracing::info!(
@@ -798,12 +783,12 @@ fn handle_cancel_schedule(
         Ok(None) => {
             return ManagerResponse::Err {
                 message: format!("schedule {schedule_id} not found"),
-            };
+            }
         }
         Err(e) => {
             return ManagerResponse::Err {
                 message: format!("read schedule {schedule_id}: {e:#}"),
-            };
+            }
         }
     };
     if !cancel_authorized(requester, &schedule.owner) {
@@ -845,12 +830,12 @@ async fn handle_fire_schedule_now(
         Ok(None) => {
             return ManagerResponse::Err {
                 message: format!("schedule {schedule_id} not found"),
-            };
+            }
         }
         Err(e) => {
             return ManagerResponse::Err {
                 message: format!("read schedule {schedule_id}: {e:#}"),
-            };
+            }
         }
     };
     if !cancel_authorized(requester, &schedule.owner) {
@@ -873,16 +858,11 @@ async fn handle_fire_schedule_now(
 /// ownership rules as `CancelSchedule` — the manager can edit
 /// schedules it owns + any owned by an agent in its subtree.
 /// Forwards the partial payload to
-/// `ScheduledPrompts::update` which enforces the cancelled-row /
-/// zero-interval validation. Returns `Ok` on a clean update;
+/// `ScheduledPrompts::update` which enforces the cancelled-row
+/// + zero-interval validation. Returns `Ok` on a clean update;
 /// `Err` with the underlying message on any auth / validation
 /// failure so the dashboard can surface it verbatim.
 #[allow(clippy::too_many_arguments)]
-#[allow(
-    clippy::option_option,
-    reason = "double-Option carries three-state PATCH semantics: outer None = \
-              leave alone, Some(None) = clear, Some(Some(v)) = set"
-)]
 fn handle_edit_schedule(
     coord: &Arc,
     requester: &str,
@@ -899,12 +879,12 @@ fn handle_edit_schedule(
         Ok(None) => {
             return ManagerResponse::Err {
                 message: format!("schedule {schedule_id} not found"),
-            };
+            }
         }
         Err(e) => {
             return ManagerResponse::Err {
                 message: format!("read schedule {schedule_id}: {e:#}"),
-            };
+            }
         }
     };
     if !cancel_authorized(requester, &schedule.owner) {
diff --git a/hive-c0re/src/meta.rs b/hive-c0re/src/meta.rs
index 5b4f1167..dc3cd2f0 100644
--- a/hive-c0re/src/meta.rs
+++ b/hive-c0re/src/meta.rs
@@ -73,13 +73,7 @@ pub async fn sync_agents(
     let dir = meta_dir();
     std::fs::create_dir_all(&dir).with_context(|| format!("create {}", dir.display()))?;
 
-    let new_flake = render_flake(
-        hyperhive_flake,
-        dashboard_port,
-        operator_pronouns,
-        context_window_tokens,
-        agents,
-    );
+    let new_flake = render_flake(hyperhive_flake, dashboard_port, operator_pronouns, context_window_tokens, agents);
     let flake_path = dir.join("flake.nix");
     let on_disk = std::fs::read_to_string(&flake_path).unwrap_or_default();
     let initial = !dir.join(".git").exists();
@@ -314,11 +308,6 @@ fn agent_canonical_inputs(name: &str) -> Vec<&'static str> {
 
 /// Inner render helper accepting a lookup fn so tests can stub the
 /// agent flake-lock introspection.
-#[allow(
-    clippy::too_many_lines,
-    reason = "templated string-builder for the meta flake — the length is one \
-              contiguous fmt block, splitting it would just hide the shape"
-)]
 fn render_flake_with_lookup(
     hyperhive_flake: &str,
     dashboard_port: u16,
@@ -415,20 +404,16 @@ where
     sorted_tokens.sort_by_key(|(k, _)| k.as_str());
     for (key, val) in &sorted_tokens {
         let upper_key = key.to_ascii_uppercase();
-        let _ = writeln!(
-            out,
-            "                HIVE_CONTEXT_WINDOW_TOKENS_{upper_key} = \"{val}\";"
-        );
+        let _ = writeln!(out, "                HIVE_CONTEXT_WINDOW_TOKENS_{upper_key} = \"{val}\";");
     }
     // Forge URL — injected when hive-c0re itself has HIVE_FORGE_URL set
     // (the NixOS module derives it from hyperhive.forge.{domain,httpPort}).
     // Agents use it in forge_notify to poll Forgejo for PR/review events.
     if let Ok(forge_url) = std::env::var("HIVE_FORGE_URL")
-        && !forge_url.is_empty()
-    {
-        let escaped = forge_url.replace('\\', "\\\\").replace('"', "\\\"");
-        let _ = writeln!(out, "                HIVE_FORGE_URL = \"{escaped}\";");
-    }
+        && !forge_url.is_empty() {
+            let escaped = forge_url.replace('\\', "\\\\").replace('"', "\\\"");
+            let _ = writeln!(out, "                HIVE_FORGE_URL = \"{escaped}\";");
+        }
     out.push_str(
         r#"                HYPERHIVE_STATE_DIR = "/agents/${name}/state";
               };
@@ -465,82 +450,6 @@ where
     out
 }
 
-async fn git_is_clean(dir: &Path) -> Result {
-    let out = lifecycle::git_command()
-        .current_dir(dir)
-        .args(["status", "--porcelain"])
-        .output()
-        .await
-        .with_context(|| format!("git status in {}", dir.display()))?;
-    Ok(out.stdout.iter().all(u8::is_ascii_whitespace))
-}
-
-async fn git(dir: &Path, args: &[&str]) -> Result<()> {
-    let out = lifecycle::git_command()
-        .current_dir(dir)
-        .args(args)
-        .output()
-        .await
-        .with_context(|| format!("git {} in {}", args.join(" "), dir.display()))?;
-    if !out.status.success() {
-        bail!(
-            "git {} failed ({}): {}",
-            args.join(" "),
-            out.status,
-            String::from_utf8_lossy(&out.stderr).trim()
-        );
-    }
-    Ok(())
-}
-
-async fn git_commit(dir: &Path, message: &str) -> Result<()> {
-    git(
-        dir,
-        &[
-            "-c",
-            &format!("user.name={GIT_NAME}"),
-            "-c",
-            &format!("user.email={GIT_EMAIL}"),
-            "commit",
-            "-m",
-            message,
-        ],
-    )
-    .await?;
-    // Best-effort mirror to the bundled forge. No-op when the forge
-    // isn't seeded (no core token on disk); push failures log a warn
-    // but don't bubble up — a missing mirror shouldn't fail an
-    // otherwise successful deploy.
-    if let Err(e) = crate::forge::push_meta(dir).await {
-        tracing::warn!(error = ?e, "forge: meta push after commit failed (non-fatal)");
-    }
-    Ok(())
-}
-
-async fn nix(dir: &Path, args: &[&str]) -> Result<()> {
-    // `--extra-experimental-features` belt-and-suspenders for hosts
-    // that haven't set this in nix.conf. The hyperhive module's
-    // deploy guide assumes flakes are already enabled, but the cost
-    // of being defensive is one extra argv each call.
-    let mut all = vec!["--extra-experimental-features", "nix-command flakes"];
-    all.extend(args);
-    let out = Command::new("nix")
-        .current_dir(dir)
-        .args(&all)
-        .output()
-        .await
-        .with_context(|| format!("nix {} in {}", args.join(" "), dir.display()))?;
-    if !out.status.success() {
-        bail!(
-            "nix {} failed ({}): {}",
-            args.join(" "),
-            out.status,
-            String::from_utf8_lossy(&out.stderr).trim()
-        );
-    }
-    Ok(())
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -648,3 +557,79 @@ mod tests {
         );
     }
 }
+
+async fn git_is_clean(dir: &Path) -> Result {
+    let out = lifecycle::git_command()
+        .current_dir(dir)
+        .args(["status", "--porcelain"])
+        .output()
+        .await
+        .with_context(|| format!("git status in {}", dir.display()))?;
+    Ok(out.stdout.iter().all(u8::is_ascii_whitespace))
+}
+
+async fn git(dir: &Path, args: &[&str]) -> Result<()> {
+    let out = lifecycle::git_command()
+        .current_dir(dir)
+        .args(args)
+        .output()
+        .await
+        .with_context(|| format!("git {} in {}", args.join(" "), dir.display()))?;
+    if !out.status.success() {
+        bail!(
+            "git {} failed ({}): {}",
+            args.join(" "),
+            out.status,
+            String::from_utf8_lossy(&out.stderr).trim()
+        );
+    }
+    Ok(())
+}
+
+async fn git_commit(dir: &Path, message: &str) -> Result<()> {
+    git(
+        dir,
+        &[
+            "-c",
+            &format!("user.name={GIT_NAME}"),
+            "-c",
+            &format!("user.email={GIT_EMAIL}"),
+            "commit",
+            "-m",
+            message,
+        ],
+    )
+    .await?;
+    // Best-effort mirror to the bundled forge. No-op when the forge
+    // isn't seeded (no core token on disk); push failures log a warn
+    // but don't bubble up — a missing mirror shouldn't fail an
+    // otherwise successful deploy.
+    if let Err(e) = crate::forge::push_meta(dir).await {
+        tracing::warn!(error = ?e, "forge: meta push after commit failed (non-fatal)");
+    }
+    Ok(())
+}
+
+async fn nix(dir: &Path, args: &[&str]) -> Result<()> {
+    // `--extra-experimental-features` belt-and-suspenders for hosts
+    // that haven't set this in nix.conf. The hyperhive module's
+    // deploy guide assumes flakes are already enabled, but the cost
+    // of being defensive is one extra argv each call.
+    let mut all = vec!["--extra-experimental-features", "nix-command flakes"];
+    all.extend(args);
+    let out = Command::new("nix")
+        .current_dir(dir)
+        .args(&all)
+        .output()
+        .await
+        .with_context(|| format!("nix {} in {}", args.join(" "), dir.display()))?;
+    if !out.status.success() {
+        bail!(
+            "nix {} failed ({}): {}",
+            args.join(" "),
+            out.status,
+            String::from_utf8_lossy(&out.stderr).trim()
+        );
+    }
+    Ok(())
+}
diff --git a/hive-c0re/src/rebuild_queue.rs b/hive-c0re/src/rebuild_queue.rs
index e4010fe9..35a35f72 100644
--- a/hive-c0re/src/rebuild_queue.rs
+++ b/hive-c0re/src/rebuild_queue.rs
@@ -70,7 +70,6 @@ pub enum QueueKind {
     Spawn,
     /// Destroy with `--purge` (real fs work). Not yet routed here; the
     /// variant exists so the wire shape doesn't need to change later.
-    #[allow(dead_code, reason = "wire shape — routed by a future PR")]
     Destroy,
 }
 
@@ -103,11 +102,10 @@ pub enum QueueSource {
     AutoUpdate,
     /// Crash recovery path (future use — currently no auto-rebuild on
     /// crash, but the variant exists for the imminent feature).
-    #[allow(dead_code, reason = "wire shape — used by a future feature")]
     CrashRecover,
     /// Operator approved a pending `Approval` row on the dashboard.
     /// `QueueEntry.approval_id` points back at the source row so the
-    /// worker can fetch the kind-specific payload (`commit_ref`, inputs,
+    /// worker can fetch the kind-specific payload (commit_ref, inputs,
     /// description) before dispatching.
     Approval,
 }
@@ -139,10 +137,7 @@ pub enum QueueState {
 
 impl QueueState {
     pub fn is_terminal(self) -> bool {
-        matches!(
-            self,
-            QueueState::Done | QueueState::Failed | QueueState::Cancelled
-        )
+        matches!(self, QueueState::Done | QueueState::Failed | QueueState::Cancelled)
     }
 }
 
@@ -155,7 +150,7 @@ pub struct QueueEntry {
     /// so SSE upserts land in place rather than churning the list.
     pub id: u64,
     /// Target agent name, or the literal `"hyperhive"` for entries
-    /// (`MetaUpdate`) that affect the meta flake rather than a single
+    /// (MetaUpdate) that affect the meta flake rather than a single
     /// agent.
     pub agent: String,
     pub kind: QueueKind,
@@ -188,8 +183,8 @@ pub struct QueueEntry {
     pub inputs: Vec,
     /// Source approval row id when this entry was created by an
     /// operator-approve POST (`source == Approval`). The worker uses
-    /// it to re-fetch the kind-specific payload (`commit_ref` / inputs /
-    /// description / `fetched_sha`) and to fire `ApprovalResolved` on
+    /// it to re-fetch the kind-specific payload (commit_ref / inputs /
+    /// description / fetched_sha) and to fire `ApprovalResolved` on
     /// completion. `None` for non-approval entries — preserved on
     /// the wire that way too.
     #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -317,7 +312,7 @@ impl RebuildQueue {
         // docstring + #365 for why). Approval-driven entries also
         // require the approval_id to match so two distinct approvals
         // for the same agent never collapse into one queue slot.
-        for entry in &mut inner.entries {
+        for entry in inner.entries.iter_mut() {
             if entry.state == QueueState::Queued
                 && entry.kind == kind
                 && entry.agent == agent
@@ -325,8 +320,7 @@ impl RebuildQueue {
                 && entry.approval_id == approval_id
             {
                 if !entry.reason.contains(&reason) {
-                    use std::fmt::Write as _;
-                    let _ = write!(entry.reason, "\nalso requested by: {reason}");
+                    entry.reason.push_str(&format!("\nalso requested by: {reason}"));
                 }
                 return entry.id;
             }
@@ -378,10 +372,7 @@ impl RebuildQueue {
     /// and leaving a stale "in flight" label after a terminal
     /// transition would mislead the dashboard render.
     pub fn finish(&self, id: u64, state: QueueState, error: Option) {
-        debug_assert!(
-            state.is_terminal(),
-            "finish() called with non-terminal {state:?}"
-        );
+        debug_assert!(state.is_terminal(), "finish() called with non-terminal {state:?}");
         let mut inner = self.inner.lock().expect("rebuild_queue mutex poisoned");
         if let Some(entry) = inner.entries.iter_mut().find(|e| e.id == id) {
             entry.state = state;
@@ -431,7 +422,7 @@ impl RebuildQueue {
     pub fn cancel_children(&self, parent: u64) -> usize {
         let mut inner = self.inner.lock().expect("rebuild_queue mutex poisoned");
         let mut count = 0;
-        for entry in &mut inner.entries {
+        for entry in inner.entries.iter_mut() {
             if entry.parent_id == Some(parent) && entry.state == QueueState::Queued {
                 entry.state = QueueState::Cancelled;
                 entry.finished_at = Some(now_unix());
@@ -449,13 +440,13 @@ impl RebuildQueue {
     /// safely interrupted). Returns true when an entry was cancelled.
     pub fn cancel(&self, id: u64) -> bool {
         let mut inner = self.inner.lock().expect("rebuild_queue mutex poisoned");
-        if let Some(entry) = inner.entries.iter_mut().find(|e| e.id == id)
-            && entry.state == QueueState::Queued
-        {
-            entry.state = QueueState::Cancelled;
-            entry.finished_at = Some(now_unix());
-            Self::trim_history(&mut inner);
-            return true;
+        if let Some(entry) = inner.entries.iter_mut().find(|e| e.id == id) {
+            if entry.state == QueueState::Queued {
+                entry.state = QueueState::Cancelled;
+                entry.finished_at = Some(now_unix());
+                Self::trim_history(&mut inner);
+                return true;
+            }
         }
         false
     }
@@ -542,7 +533,7 @@ pub async fn run_worker(coord: std::sync::Arc)
                     return;
                 }
             }
-            () = coord.rebuild_queue.notify.notified() => {
+            _ = coord.rebuild_queue.notify.notified() => {
                 // New entry — back to the drain loop.
             }
         }
@@ -565,14 +556,12 @@ async fn dispatch(
             crate::actions::run_approval_apply_commit(coord, Some(entry.id), approval_id).await
         }
         (QueueKind::Rebuild, None) => {
-            let current_rev =
-                crate::auto_update::current_flake_rev(&coord.hyperhive_flake).unwrap_or_default();
-            crate::auto_update::rebuild_agent(coord, &entry.agent, ¤t_rev, Some(entry.id))
-                .await
+            let current_rev = crate::auto_update::current_flake_rev(&coord.hyperhive_flake)
+                .unwrap_or_default();
+            crate::auto_update::rebuild_agent(coord, &entry.agent, ¤t_rev, Some(entry.id)).await
         }
         (QueueKind::MetaUpdate, Some(approval_id)) => {
-            crate::actions::run_approval_update_meta_inputs(coord, Some(entry.id), approval_id)
-                .await
+            crate::actions::run_approval_update_meta_inputs(coord, Some(entry.id), approval_id).await
         }
         (QueueKind::MetaUpdate, None) => run_meta_update(coord, entry).await,
         (QueueKind::Spawn, Some(approval_id)) => {
@@ -612,11 +601,7 @@ async fn run_meta_update(
 ) -> anyhow::Result<()> {
     let _progress = coord.meta_update_guard();
     let inputs = entry.inputs.clone();
-    tracing::info!(
-        ?inputs,
-        parent = entry.id,
-        "rebuild_queue: meta-update starting"
-    );
+    tracing::info!(?inputs, parent = entry.id, "rebuild_queue: meta-update starting");
     coord.set_queue_step(Some(entry.id), "nix flake update");
     let result = if inputs.is_empty() {
         crate::meta::lock_update(&[]).await
@@ -648,7 +633,7 @@ async fn run_meta_update(
 
 /// Compute which agents a `nix flake update ` on the meta
 /// flake would affect. Used by callers that pre-enqueue cascade
-/// `Rebuild` entries at `MetaUpdate` submission time (issue #347) so the
+/// `Rebuild` entries at MetaUpdate submission time (issue #347) so the
 /// dashboard can render the dependent work alongside its parent before
 /// the lock bump actually runs.
 ///
@@ -673,8 +658,7 @@ pub async fn meta_update_cascade_agents(inputs: &[String]) -> Vec {
                 if c == crate::lifecycle::MANAGER_NAME {
                     Some(crate::lifecycle::MANAGER_NAME.to_owned())
                 } else {
-                    c.strip_prefix(crate::lifecycle::AGENT_PREFIX)
-                        .map(str::to_owned)
+                    c.strip_prefix(crate::lifecycle::AGENT_PREFIX).map(str::to_owned)
                 }
             })
             .collect()
@@ -798,11 +782,9 @@ mod tests {
         // Both inputs lists are preserved.
         let inputs: Vec<&[String]> = snap.iter().map(|e| e.inputs.as_slice()).collect();
         assert!(inputs.iter().any(|i| *i == ["nixpkgs"]));
-        assert!(
-            inputs
-                .iter()
-                .any(|i| *i == ["agent-bitburner/bitburner-agent"])
-        );
+        assert!(inputs
+            .iter()
+            .any(|i| *i == ["agent-bitburner/bitburner-agent"]));
     }
 
     #[test]
diff --git a/hive-c0re/src/scheduled_prompts.rs b/hive-c0re/src/scheduled_prompts.rs
index 739f7751..8b958452 100644
--- a/hive-c0re/src/scheduled_prompts.rs
+++ b/hive-c0re/src/scheduled_prompts.rs
@@ -164,12 +164,6 @@ pub struct NewSchedule {
 /// "this target is active again"; prior history was already visible
 /// at cancel time).
 #[derive(Debug, Clone, Default)]
-#[allow(
-    clippy::option_option,
-    reason = "double-Option carries three-state PATCH semantics: outer None = \
-              leave alone, Some(None) = clear, Some(Some(v)) = set. \
-              collapsing to a single Option would lose the 'clear' state"
-)]
 pub struct UpdateSchedule {
     pub body: Option,
     pub description: Option>,
@@ -206,7 +200,7 @@ impl ScheduledPrompts {
     /// Insert a new schedule. Returns the new id. Empty `targets` is
     /// rejected — a schedule with no recipients would silently
     /// never fan out, masking caller bugs.
-    pub fn submit(&self, new: &NewSchedule) -> Result {
+    pub fn submit(&self, new: NewSchedule) -> Result {
         if new.targets.is_empty() {
             bail!("schedule must have at least one target");
         }
@@ -218,13 +212,13 @@ impl ScheduledPrompts {
                  created_at_unix, source, description)
              VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
             params![
-                &new.owner,
-                &new.body,
+                new.owner,
+                new.body,
                 new.interval_seconds.map(i64::try_from).and_then(Result::ok),
                 new.first_fire_at_unix,
                 now_unix(),
                 new.source.to_db_string(),
-                &new.description,
+                new.description,
             ],
         )?;
         let id = tx.last_insert_rowid();
@@ -261,7 +255,7 @@ impl ScheduledPrompts {
 
     /// Every active (non-globally-cancelled) schedule in insert
     /// order. Used by the dashboard list view + the cancel-auth
-    /// check (the latter only needs the header but `list()` is the
+    /// check (the latter only needs the header but list() is the
     /// shared hot path).
     pub fn list(&self) -> Result> {
         let conn = self.conn.lock().unwrap();
@@ -328,7 +322,7 @@ impl ScheduledPrompts {
     /// Advance a recurring schedule's `next_fire_at` to the smallest
     /// multiple-of-interval > `from`. Returns the count of skipped
     /// cycles (≥ 0); the worker stamps that into the per-row
-    /// `last_result` so operators see "caught up from N missed".
+    /// last_result so operators see "caught up from N missed".
     ///
     /// For one-shots (`interval_seconds IS NULL`) this is a no-op
     /// at the SQL level; callers should `delete` them after fan-out
@@ -494,7 +488,10 @@ impl ScheduledPrompts {
     /// id.
     pub fn delete(&self, id: i64) -> Result<()> {
         let conn = self.conn.lock().unwrap();
-        conn.execute("DELETE FROM scheduled_prompts WHERE id = ?1", params![id])?;
+        conn.execute(
+            "DELETE FROM scheduled_prompts WHERE id = ?1",
+            params![id],
+        )?;
         Ok(())
     }
 
@@ -633,7 +630,7 @@ mod tests {
     }
 
     fn submit_one_shot(db: &ScheduledPrompts, fire_at: i64, targets: &[&str]) -> i64 {
-        db.submit(&NewSchedule {
+        db.submit(NewSchedule {
             owner: "operator".into(),
             targets: targets.iter().map(|t| (*t).to_owned()).collect(),
             body: "wake".into(),
@@ -661,7 +658,7 @@ mod tests {
     fn submit_rejects_empty_targets() {
         let (_dir, db) = open();
         let err = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "operator".into(),
                 targets: Vec::new(),
                 body: "wake".into(),
@@ -691,7 +688,7 @@ mod tests {
         let (_dir, db) = open();
         // Recurring every 60s, last fire at t=100.
         let id = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "operator".into(),
                 targets: vec!["alice".into()],
                 body: "wake".into(),
@@ -713,7 +710,7 @@ mod tests {
     fn rearm_advances_one_step_when_caught_up() {
         let (_dir, db) = open();
         let id = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "operator".into(),
                 targets: vec!["alice".into()],
                 body: "wake".into(),
@@ -745,8 +742,7 @@ mod tests {
     fn cancel_targets_auto_cancels_parent_when_last_drops() {
         let (_dir, db) = open();
         let id = submit_one_shot(&db, 100, &["alice", "bob"]);
-        db.cancel_targets(id, &["alice".to_owned()])
-            .expect("cancel");
+        db.cancel_targets(id, &["alice".to_owned()]).expect("cancel");
         let s = db.get(id).expect("get").expect("present");
         // Parent still active (bob remains).
         assert!(s.cancelled_at_unix.is_none());
@@ -779,8 +775,7 @@ mod tests {
     fn record_target_result_skips_cancelled_targets() {
         let (_dir, db) = open();
         let id = submit_one_shot(&db, 100, &["alice", "bob"]);
-        db.cancel_targets(id, &["alice".to_owned()])
-            .expect("cancel");
+        db.cancel_targets(id, &["alice".to_owned()]).expect("cancel");
         db.record_target_result(id, "alice", 200, "ok")
             .expect("record alice");
         db.record_target_result(id, "bob", 200, "ok")
@@ -799,7 +794,7 @@ mod tests {
     fn update_partial_only_touches_set_fields() {
         let (_dir, db) = open();
         let id = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "operator".into(),
                 targets: vec!["alice".into()],
                 body: "old body".into(),
@@ -829,7 +824,7 @@ mod tests {
     fn update_interval_toggle_recurring_to_one_shot() {
         let (_dir, db) = open();
         let id = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "operator".into(),
                 targets: vec!["alice".into()],
                 body: "x".into(),
@@ -904,7 +899,7 @@ mod tests {
     fn update_clears_description() {
         let (_dir, db) = open();
         let id = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "operator".into(),
                 targets: vec!["alice".into()],
                 body: "x".into(),
@@ -987,8 +982,7 @@ mod tests {
         let (_dir, db) = open();
         let id = submit_one_shot(&db, 100, &["alice", "bob"]);
         // Record some history on alice, then cancel her.
-        db.record_target_result(id, "alice", 50, "ok")
-            .expect("record");
+        db.record_target_result(id, "alice", 50, "ok").expect("record");
         db.update(
             id,
             UpdateSchedule {
@@ -1040,7 +1034,7 @@ mod tests {
     fn approval_source_round_trips() {
         let (_dir, db) = open();
         let id = db
-            .submit(&NewSchedule {
+            .submit(NewSchedule {
                 owner: "manager".into(),
                 targets: vec!["alice".into()],
                 body: "wake".into(),
diff --git a/hive-c0re/src/scheduled_prompts_worker.rs b/hive-c0re/src/scheduled_prompts_worker.rs
index 7ab6a500..2489274d 100644
--- a/hive-c0re/src/scheduled_prompts_worker.rs
+++ b/hive-c0re/src/scheduled_prompts_worker.rs
@@ -32,7 +32,7 @@
 //!    the broker send again, so transient errors self-heal.
 //!  - **one-shots** delete unconditionally after their single
 //!    fan-out pass; a broker failure on a one-shot is NOT
-//!    retried (the operator advisory + `last_result` are the only
+//!    retried (the operator advisory + last_result are the only
 //!    audit trail).
 
 use std::sync::Arc;
@@ -104,7 +104,7 @@ fn tick(coord: &Arc) {
 }
 
 /// Fan out one schedule's body to every active target. Records
-/// per-target `last_result`; advances or reaps the parent row at
+/// per-target last_result; advances or reaps the parent row at
 /// the end depending on whether `interval_seconds` is set.
 fn fire_schedule(coord: &Arc, schedule: &Schedule, now: i64) {
     let known: std::collections::HashSet = known_agents(coord);
@@ -118,11 +118,12 @@ fn fire_schedule(coord: &Arc, schedule: &Schedule, now: i64) {
         // mirrors `to == operator` into its own pane.
         if target != hive_sh4re::OPERATOR_RECIPIENT && !known.contains(target) {
             let reason = format!("no such agent: {target}");
-            if let Err(e) =
-                coord
-                    .scheduled_prompts
-                    .record_target_result(schedule.id, target, now, &reason)
-            {
+            if let Err(e) = coord.scheduled_prompts.record_target_result(
+                schedule.id,
+                target,
+                now,
+                &reason,
+            ) {
                 tracing::warn!(error = ?e, schedule = schedule.id, %target, "record_target_result failed");
             }
             notify_operator_missing_target(coord, schedule, target);
@@ -291,11 +292,7 @@ pub async fn fire_now(
     if schedule.cancelled_at_unix.is_some() {
         anyhow::bail!("schedule {schedule_id} is already cancelled");
     }
-    if !schedule
-        .targets
-        .iter()
-        .any(|t| t.cancelled_at_unix.is_none())
-    {
+    if !schedule.targets.iter().any(|t| t.cancelled_at_unix.is_none()) {
         anyhow::bail!("schedule {schedule_id} has no active targets");
     }
     let known = known_agents_async().await;
@@ -312,11 +309,12 @@ pub async fn fire_now(
         let target = &target_row.target;
         if target != hive_sh4re::OPERATOR_RECIPIENT && !known.contains(target) {
             let reason = format!("manual fire: no such agent: {target}");
-            if let Err(e) =
-                coord
-                    .scheduled_prompts
-                    .record_target_result(schedule_id, target, now, &reason)
-            {
+            if let Err(e) = coord.scheduled_prompts.record_target_result(
+                schedule_id,
+                target,
+                now,
+                &reason,
+            ) {
                 tracing::warn!(error = ?e, schedule = schedule_id, %target, "record_target_result failed");
             }
             notify_operator_missing_target(coord, &schedule, target);
diff --git a/hive-c0re/src/topology.rs b/hive-c0re/src/topology.rs
index 71ef41e1..7830e9a9 100644
--- a/hive-c0re/src/topology.rs
+++ b/hive-c0re/src/topology.rs
@@ -58,11 +58,6 @@ pub fn read() -> BTreeMap> {
 /// or absent from the file. Cheap convenience over `read()` for
 /// callers that want a single entry.
 #[must_use]
-#[allow(
-    dead_code,
-    reason = "convenience API; callers go through `read()` today, kept for the \
-              dashboard/manager-server surfaces landing in #361 follow-ups"
-)]
 pub fn parent_of(name: &str) -> Option {
     read().get(name).cloned().flatten()
 }
@@ -93,10 +88,10 @@ pub fn is_descendant_of(candidate: &str, ancestor: &str) -> bool {
     false
 }
 
-/// Persist the topology map. Sorted JSON output (`BTreeMap` is sorted by
+/// Persist the topology map. Sorted JSON output (BTreeMap is sorted by
 /// key) keeps git diffs minimal across re-writes. Best-effort —
 /// returns an `io::Error` so callers can decide whether a failure
-/// should abort their op (`sync_agents`, `RequestSetParent`) or just log.
+/// should abort their op (sync_agents, RequestSetParent) or just log.
 pub fn write(topology: &BTreeMap>) -> std::io::Result<()> {
     let path = topology_path();
     if let Some(parent) = path.parent() {
@@ -116,21 +111,13 @@ pub fn write(topology: &BTreeMap>) -> std::io::Result<()>
 /// entries — `sync_agents` only adds rows for newly-spawned agents
 /// against whatever the operator has configured.
 #[must_use]
-#[allow(
-    dead_code,
-    reason = "kept for the dashboard / RequestSetParent write API landing in \
-              #361 follow-ups; `sync_agents` does its own seeding today"
-)]
 pub fn default_seed(agent_names: &[String]) -> BTreeMap> {
     let mut out = BTreeMap::new();
     for name in agent_names {
         if name == crate::lifecycle::MANAGER_NAME {
             out.insert(name.clone(), None);
         } else {
-            out.insert(
-                name.clone(),
-                Some(crate::lifecycle::MANAGER_NAME.to_owned()),
-            );
+            out.insert(name.clone(), Some(crate::lifecycle::MANAGER_NAME.to_owned()));
         }
     }
     out
@@ -298,8 +285,8 @@ mod tests {
 
     #[test]
     fn apply_set_parent_refuses_manager_move() {
-        let err = apply_set_parent(&topo_three_level(), crate::lifecycle::MANAGER_NAME, None)
-            .unwrap_err();
+        let err =
+            apply_set_parent(&topo_three_level(), crate::lifecycle::MANAGER_NAME, None).unwrap_err();
         assert!(err.contains("manager"), "err = {err}");
     }
 
diff --git a/hive-forge/src/verbs/diff.rs b/hive-forge/src/verbs/diff.rs
index 066e0dfc..e35793b9 100644
--- a/hive-forge/src/verbs/diff.rs
+++ b/hive-forge/src/verbs/diff.rs
@@ -1,16 +1,14 @@
 //! `diff  [repo]` — print the unified diff for a PR.
 //!
-//! By default any per-file section whose target path matches a
-//! known autogenerated lockfile (`flake.lock`, `Cargo.lock`,
-//! `package-lock.json`, …) is collapsed to a single
-//! `[: contents changed (+N -M, --full for content)]`
-//! line so a `flake.lock` rev bump doesn't drown the human-
-//! authored changes in 5 000 lines of lock churn (#222). The
-//! per-file git headers (`diff --git`, `index`, `---`, `+++`,
-//! and any rename / mode metadata) are suppressed alongside the
-//! hunks since the placeholder already carries the file path and
-//! the +/- magnitude — the headers add four lines of noise per
-//! lockfile without any information the reader can act on.
+//! By default the hunks for known autogenerated lockfiles
+//! (`flake.lock`, `Cargo.lock`, `package-lock.json`, …) are
+//! collapsed to a `[: +N -M (autogenerated; pass --full for
+//! content)]` placeholder so a `flake.lock` rev bump doesn't drown
+//! the human-authored changes in 5 000 lines of lock churn
+//! (#222). The header (`diff --git`, `index`, `---`, `+++`,
+//! rename / mode metadata) is preserved so the reader can still
+//! see WHICH lockfiles changed; the +/- counts give a `diff
+//! --stat`-style magnitude (excluding the `@@` hunk header).
 //! Pass `--full` to dump the unfiltered diff.
 
 use anyhow::Result;
@@ -42,12 +40,13 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
     Ok(())
 }
 
-/// Walk a unified diff line-by-line. When a `diff --git` line
-/// names a known autogenerated file (`is_autogenerated`), suppress
-/// every line of that per-file section (the git headers AND the
-/// hunks) and emit a single `[file.lock: contents changed (+N -M,
-/// --full for content)]` line in their place. Non-autogenerated
-/// files pass through unchanged.
+/// Walk a unified diff line-by-line. For each per-file section
+/// whose target path matches a known autogenerated file
+/// (`is_autogenerated`), drop every line from the first hunk
+/// header (`@@`) onward and emit a single `diff --stat`-style
+/// `[file.lock: +N -M (autogenerated, --full for content)]`
+/// placeholder before the next file. Non-autogenerated files
+/// pass through unchanged.
 fn collapse_autogenerated(diff: &str) -> String {
     let mut out = String::with_capacity(diff.len());
     let mut state: Option = None;
@@ -62,23 +61,23 @@ fn collapse_autogenerated(diff: &str) -> String {
             if let Some(p) = path.as_deref()
                 && is_autogenerated(p)
             {
-                // Suppress the entire per-file block (headers and
-                // hunks alike). The placeholder we emit on flush
-                // carries the path, so the git headers are pure
-                // noise.
                 state = Some(CollapseState::new(p.to_owned()));
-                continue;
             }
             out.push_str(line);
             out.push('\n');
             continue;
         }
         if let Some(s) = state.as_mut() {
-            // Inside an autogenerated section. Tally `+`/`-` body
-            // lines for the placeholder; drop everything else
-            // (headers, `@@` markers, context lines).
-            if s.in_body || line.starts_with("@@") {
+            // First `@@` marks the boundary between file header and
+            // hunk content; everything from this point is
+            // suppressed (and tallied) while `state` is Some.
+            if !s.in_body && line.starts_with("@@") {
                 s.in_body = true;
+            }
+            if s.in_body {
+                // The hunk header `@@` itself counts as a body line
+                // for the +/− tally only via its descendant content
+                // lines; skip it for the counters.
                 if !line.starts_with("@@") {
                     match line.as_bytes().first() {
                         Some(b'+') => s.added += 1,
@@ -86,8 +85,8 @@ fn collapse_autogenerated(diff: &str) -> String {
                         _ => {}
                     }
                 }
+                continue;
             }
-            continue;
         }
         out.push_str(line);
         out.push('\n');
@@ -98,11 +97,11 @@ fn collapse_autogenerated(diff: &str) -> String {
     out
 }
 
-/// Per-file accumulator for the collapsed placeholder. Tracks
-/// the file's display name plus `+`/`-` line counts (excluding
-/// the `@@` hunk header), so the placeholder shows operator-
-/// meaningful magnitude instead of "N lines omitted" (which
-/// mixed context + added + removed indistinguishably).
+/// Per-file accumulator for the collapsed-hunk placeholder. Tracks
+/// the file's display name plus `+`/`−` line counts (excluding the
+/// `@@` hunk header), so the placeholder shows operator-meaningful
+/// magnitude instead of "N lines omitted" (which mixed context +
+/// added + removed indistinguishably).
 struct CollapseState {
     path: String,
     in_body: bool,
@@ -122,7 +121,7 @@ impl CollapseState {
 
     fn placeholder(&self) -> String {
         format!(
-            "[{}: contents changed (+{} -{}, --full for content)]\n",
+            "[{}: +{} -{} (autogenerated; pass --full for content)]\n",
             self.path, self.added, self.removed
         )
     }
@@ -248,23 +247,18 @@ index 3333..4444 100644
 +fn main() { println!(\"hi\"); }
 ";
         let out = collapse_autogenerated(diff);
-        // Per-file git headers for the lockfile are suppressed —
-        // the placeholder already carries the path, so the four
-        // header lines are pure noise (4 lines per lockfile, stacks
-        // fast on a multi-lockfile PR).
-        assert!(!out.contains("diff --git a/Cargo.lock"));
-        assert!(!out.contains("--- a/Cargo.lock"));
-        assert!(!out.contains("+++ b/Cargo.lock"));
+        assert!(out.contains("diff --git a/Cargo.lock"));
+        assert!(out.contains("--- a/Cargo.lock"));
+        assert!(out.contains("+++ b/Cargo.lock"));
         assert!(!out.contains("[[package]]"));
         // Stat-style placeholder: 1 added (`+name = "new"`), 1
         // removed (`-name = "old"`); context line and `@@` header
         // don't count.
         assert!(
-            out.contains("[Cargo.lock: contents changed (+1 -1, --full for content)]"),
-            "expected one-line placeholder, got: {out}"
+            out.contains("[Cargo.lock: +1 -1"),
+            "expected stat placeholder, got: {out}"
         );
         // Non-lockfile file passes through untouched.
-        assert!(out.contains("diff --git a/src/main.rs"));
         assert!(out.contains("fn main() {}"));
         assert!(out.contains("println!(\"hi\")"));
     }
@@ -306,17 +300,13 @@ index 1111..2222 100644
 +lock-line-two-bumped
 ";
         let out = collapse_autogenerated(diff);
-        // README.md (non-lockfile) passes through with its full
-        // header + hunks intact.
-        assert!(out.contains("diff --git a/README.md"));
         assert!(out.contains("-old"));
         assert!(out.contains("+new"));
-        // Lockfile is fully suppressed — no headers, no content.
-        assert!(!out.contains("diff --git a/flake.lock"));
+        assert!(out.contains("diff --git a/flake.lock"));
         assert!(!out.contains("lock-line-one"));
         assert!(
-            out.contains("[flake.lock: contents changed (+1 -1, --full for content)]"),
-            "expected one-line placeholder, got: {out}"
+            out.contains("[flake.lock: +1 -1"),
+            "expected stat placeholder, got: {out}"
         );
     }
 
@@ -341,7 +331,7 @@ index 1111..2222 100644
 ";
         let out = collapse_autogenerated(diff);
         assert!(
-            out.contains("[flake.lock: contents changed (+4 -1, --full for content)]"),
+            out.contains("[flake.lock: +4 -1"),
             "expected +4 -1, got: {out}"
         );
     }
@@ -411,14 +401,13 @@ index 1111..2222 100644
 +new
 ";
         let out = collapse_autogenerated(diff);
-        // Entire per-file block suppressed (lockfile detected).
-        assert!(!out.contains("diff --git"), "headers leaked: {out}");
+        // Content must be suppressed (lockfile detected).
         assert!(!out.contains("old\n"), "lock content leaked: {out}");
         assert!(!out.contains("+new"), "lock content leaked: {out}");
         // Placeholder uses the parsed b-side path (without quotes).
         assert!(
-            out.contains("[odd dir/Cargo.lock: contents changed (+1 -1, --full for content)]"),
-            "expected one-line placeholder for quoted-path lockfile, got: {out}"
+            out.contains("[odd dir/Cargo.lock: +1 -1"),
+            "expected stat placeholder for quoted-path lockfile, got: {out}"
         );
     }
 }
diff --git a/hive-sh4re/src/lib.rs b/hive-sh4re/src/lib.rs
index c69ad976..8ee3e12c 100644
--- a/hive-sh4re/src/lib.rs
+++ b/hive-sh4re/src/lib.rs
@@ -23,8 +23,8 @@ pub enum HostRequest {
     /// `hive-c0re request-spawn` CLI both go through this. The
     /// previously-mirrored manager-side `RequestSpawn` was removed
     /// (#442) — managers now go through the two-step `request_init_config`
-    /// and `request_apply_commit` flow so the spawn captures the
-    /// manager's customised config.
+    /// + `request_apply_commit` flow so the spawn captures the manager's
+    /// customised config.
     RequestSpawn { name: String },
     /// Stop a managed container (graceful).
     Kill { name: String },
@@ -752,10 +752,14 @@ pub enum ManagerRequest {
     Status,
     /// Operator-injected message TO the manager (from the manager's own web
     /// UI). Same shape as `AgentRequest::OperatorMsg`.
-    OperatorMsg { body: String },
+    OperatorMsg {
+        body: String,
+    },
     /// Last `limit` messages addressed to the manager, newest-first.
     /// Non-mutating; mirror of `AgentRequest::Recent`.
-    Recent { limit: u64 },
+    Recent {
+        limit: u64,
+    },
     /// Initialise a brand-new agent's proposed config repo and queue an
     /// approval for the operator to review. On approval hive-c0re seeds
     /// `/agents//config/` with the default `agent.nix` template,
@@ -772,15 +776,23 @@ pub enum ManagerRequest {
         description: Option,
     },
     /// Stop a sub-agent (graceful).
-    Kill { name: String },
+    Kill {
+        name: String,
+    },
     /// Start a previously-stopped sub-agent container.
-    Start { name: String },
+    Start {
+        name: String,
+    },
     /// Restart a sub-agent container (stop + start).
-    Restart { name: String },
+    Restart {
+        name: String,
+    },
     /// Rebuild a sub-agent: re-applies the current hyperhive flake +
     /// agent.nix, restarts the container. No approval required —
     /// it's idempotent and the manager owns its own update cadence.
-    Update { name: String },
+    Update {
+        name: String,
+    },
     /// Submit a config commit for the user to approve. `commit_ref` must
     /// be a commit sha (7-40 hex chars, short or full) in the agent's
     /// proposed config repo — a branch or tag name is rejected so the
@@ -945,8 +957,8 @@ pub enum ManagerRequest {
     /// per-target fan-out once immediately without touching
     /// `next_fire_at_unix` on recurring schedules; one-shots are
     /// consumed by the manual fire. Authorization mirrors
-    /// `CancelSchedule`: the manager can fire its own schedules and
-    /// any owned by a sub-agent in its subtree per topology.json;
+    /// `CancelSchedule`: the manager can fire its own schedules
+    /// + any owned by a sub-agent in its subtree per topology.json;
     /// the operator surface bypasses the check.
     FireScheduleNow { id: i64 },
     /// Edit an existing schedule's mutable fields (#474). Partial
@@ -1001,9 +1013,9 @@ pub struct SchedulePromptPayload {
 }
 
 /// Schedule row shape on the wire — mirror of
-/// `scheduled_prompts::Schedule` but in the public crate so the
-/// dashboard and agent surfaces can deserialize without depending
-/// on hive-c0re-internal types. Kept structurally identical to the
+/// `scheduled_prompts::Schedule` but in the public crate so dashboard
+/// + agent surfaces can deserialize without depending on
+/// hive-c0re-internal types. Kept structurally identical to the
 /// in-process type; the conversion is field-by-field in
 /// `manager_server` / `dashboard`.
 #[derive(Debug, Clone, Serialize, Deserialize)]
diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix
index 11a51173..467a5f7e 100644
--- a/nix/modules/hive-c0re.nix
+++ b/nix/modules/hive-c0re.nix
@@ -17,32 +17,8 @@ in
 {
   # The forge is part of the standard install — hive-c0re mirrors
   # every agent's applied config repo into it. On by default; opt out
-  # with `hyperhive.forge.enable = false`. hive-matrix is opt-in (off
-  # by default) and asserts that `hyperhive.domain` is set before it
-  # can be enabled.
-  imports = [
-    ./hive-forge.nix
-    ./hive-matrix.nix
-  ];
-
-  # Top-level option shared by any hyperhive subsystem that needs a
-  # stable hostname (matrix server_name today, forge ROOT_URL likely
-  # next). Type is nullable + default null so existing operator
-  # configs that don't set it still evaluate; subsystems that
-  # actually need it (matrix) assert non-null in their own config
-  # block with a helpful message.
-  options.hyperhive.domain = lib.mkOption {
-    type = lib.types.nullOr lib.types.str;
-    default = null;
-    example = "darkest.space";
-    description = ''
-      Canonical host domain for hyperhive subsystems that need a
-      stable name (currently: `hyperhive.matrix.serverName` derives
-      from this when `useSubdomain = true`). No default — subsystems
-      that opt to require it assert non-null in their own config and
-      fail eval with a helpful message if it's missing.
-    '';
-  };
+  # with `hyperhive.forge.enable = false`.
+  imports = [ ./hive-forge.nix ];
 
   options.services.hive-c0re = {
     enable = lib.mkEnableOption "hive-c0re — hyperhive coordinator daemon";
@@ -195,8 +171,7 @@ in
         # serves this via `tower_http::ServeDir` for any path it doesn't
         # match against an API/action route.
         HIVE_STATIC_DIR = "${cfg.frontend}/dashboard";
-      }
-      // lib.optionalAttrs config.hyperhive.forge.enable {
+      } // lib.optionalAttrs config.hyperhive.forge.enable {
         # Agents poll this URL for Forgejo notifications. Derived from
         # hyperhive.forge.{domain,httpPort} so it tracks forge config changes.
         HIVE_FORGE_URL = "http://${config.hyperhive.forge.domain}:${toString config.hyperhive.forge.httpPort}";
diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix
deleted file mode 100644
index e20175b6..00000000
--- a/nix/modules/hive-matrix.nix
+++ /dev/null
@@ -1,201 +0,0 @@
-{
-  pkgs,
-  lib,
-  config,
-  ...
-}:
-let
-  cfg = config.hyperhive.matrix;
-  hyperhiveDomain = config.hyperhive.domain;
-  effectiveServerName =
-    if cfg.serverName != null then cfg.serverName else "matrix.${hyperhiveDomain}";
-in
-{
-  # Private Matrix homeserver (matrix-tuwunel — the official conduwuit
-  # successor) for hyperhive agents, wrapped in a nixos-container so it
-  # doesn't fight any existing `services.matrix-*` the operator may
-  # already run on the host. Same shape as `nix/modules/hive-forge.nix`:
-  # shared host netns (`privateNetwork = false`) so agents reach it at
-  # `http://localhost:` (or via the configured server_name
-  # for federation), nixos-container only here for state + systemd-unit
-  # isolation.
-  #
-  # Container name `hive-matrix` (not `h-*`) so the lifecycle scanner
-  # ignores it; operator manages via the standard `nixos-container` CLI.
-  #
-  # Persistent state at `/var/lib/nixos-containers/hive-matrix/var/lib/
-  # matrix-tuwunel/` (survives container restart / host reboot). To
-  # wipe, destroy the container.
-  #
-  # Initial rollout (#548): federation enabled (needed for multi-hive
-  # swarms; trusted_servers starts empty so no actual federation traffic
-  # leaves until peers are explicitly listed), registration via admin
-  # API only, e2ee disabled per operator call (tracked for follow-up at
-  # #551).
-
-  options.hyperhive.matrix = {
-    enable = lib.mkOption {
-      type = lib.types.bool;
-      default = false;
-      description = ''
-        Run hive-matrix — a private matrix-tuwunel homeserver (in a
-        nixos-container) for hyperhive agents. Off by default while
-        the integration phases in; flip to `true` once the operator
-        has set `hyperhive.domain` and is ready to onboard agents.
-      '';
-    };
-
-    package = lib.mkOption {
-      type = lib.types.package;
-      default = pkgs.matrix-tuwunel;
-      defaultText = lib.literalExpression "pkgs.matrix-tuwunel";
-      description = ''
-        matrix-tuwunel package to run inside the container. Defaults
-        to nixpkgs's `pkgs.matrix-tuwunel`. Override to pin a
-        specific upstream if you need an unreleased feature.
-      '';
-    };
-
-    serverName = lib.mkOption {
-      type = lib.types.nullOr lib.types.str;
-      default = null;
-      example = "chat.example.org";
-      description = ''
-        Matrix `server_name` — the host part of every user ID
-        (`@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
-        `matrix.''${hyperhive.domain}` (always a subdomain — keeps
-        the root domain free for the dashboard or forge). Override
-        here only if you need a name that doesn't follow the
-        `matrix.` shape.
-      '';
-    };
-
-    httpPort = lib.mkOption {
-      type = lib.types.port;
-      default = 8008;
-      description = ''
-        TCP port tuwunel serves the matrix client-server API on.
-        Default 8008 is the matrix-spec well-known port. Sits
-        outside hyperhive's claimed ranges (dashboard 7000, manager
-        8000, sub-agents 8100..8999). Federation listens on
-        `federationPort` separately.
-      '';
-    };
-
-    openFirewall = lib.mkOption {
-      type = lib.types.bool;
-      default = true;
-      description = ''
-        Open `httpPort` in the host firewall. Off when the
-        homeserver should only be reachable from inside the host
-        (e.g. while bringing the integration up before announcing
-        it to other hives).
-
-        Note: federation (the matrix-spec well-known port 8448) is
-        intentionally not opened here. tuwunel serves the federation
-        API on the same `httpPort` as the client-server API by
-        default; reaching it on 8448 requires either binding tuwunel
-        to that port explicitly OR a reverse-proxy + `.well-known/
-        matrix/server` delegation, neither of which lives in this
-        module. Add that proxy config alongside whatever serves your
-        dashboard or forge on 443.
-      '';
-    };
-
-    trustedServers = lib.mkOption {
-      type = lib.types.listOf lib.types.str;
-      default = [ ];
-      example = [ "matrix.org" ];
-      description = ''
-        List of trusted matrix servers (homeservers whose signing
-        keys this server will fetch identity-server-style). Empty
-        by default — federation is enabled at the protocol level
-        but no peer is trusted until listed here, so the homeserver
-        is effectively closed until the operator declares hive
-        peers explicitly.
-      '';
-    };
-
-    maxRequestSize = lib.mkOption {
-      type = lib.types.str;
-      default = "20000000";
-      description = ''
-        Maximum size in bytes of a single matrix client request body.
-        Default 20 MB matches the matrix-spec recommendation for
-        media uploads. String-typed to match tuwunel's TOML config
-        shape (it accepts both integer + size-with-suffix strings).
-      '';
-    };
-  };
-
-  config = lib.mkIf cfg.enable {
-    # mara on #548: "there is no default, but it is required. add
-    # assertion." — fail eval with a helpful message rather than
-    # spawning a homeserver with a bogus server_name we can never
-    # change later. `hyperhive.domain` is host-wide; matrix derives
-    # the server_name from it (or from `cfg.serverName` if the
-    # operator wants to override).
-    assertions = [
-      {
-        assertion = hyperhiveDomain != null || cfg.serverName != null;
-        message = ''
-          hyperhive.matrix.enable = true requires either:
-            - hyperhive.domain set to your host's canonical domain
-              (recommended; shared with forge / dashboard), or
-            - hyperhive.matrix.serverName set explicitly.
-
-          The matrix server_name is embedded into every user ID and
-          room ID on this homeserver — it cannot be changed later
-          without losing every account and chat history. Pick a
-          stable hostname before enabling.
-        '';
-      }
-    ];
-
-    containers.hive-matrix = {
-      autoStart = true;
-      ephemeral = false;
-      # Share host netns — tuwunel's listeners look exactly like
-      # host-side services, no port-forward plumbing, and agent
-      # containers (also host netns) reach it via plain `localhost`.
-      privateNetwork = false;
-      config =
-        { ... }:
-        {
-          system.stateVersion = "26.05";
-          services.matrix-tuwunel = {
-            enable = true;
-            package = cfg.package;
-            settings.global = {
-              server_name = effectiveServerName;
-              address = "0.0.0.0";
-              port = cfg.httpPort;
-              max_request_size = cfg.maxRequestSize;
-              # Federation enabled at the protocol level so swarms
-              # can be wired up later by extending `trustedServers`
-              # without a homeserver restart. Empty trusted_servers
-              # keeps it effectively closed until peers are listed.
-              allow_federation = true;
-              trusted_servers = cfg.trustedServers;
-              # Registration off — operator seeds agent accounts via
-              # the tuwunel admin API (mirrors the forge pattern;
-              # see `hive-c0re/src/matrix.rs` once #548 PR 2 lands).
-              allow_registration = false;
-              # E2EE disabled in initial rollout per operator call
-              # (#548) — re-enabling tracked at #551.
-              allow_encryption = false;
-            };
-          };
-          environment.systemPackages = [ cfg.package ];
-        };
-    };
-
-    networking.firewall = lib.mkIf cfg.openFirewall {
-      allowedTCPPorts = [
-        cfg.httpPort
-      ];
-    };
-  };
-}