Commit graph

888 commits

Author SHA1 Message Date
lexis
822a1b15fa docs: matrix gui.enable defaults to matrix.enable, gateway serves /matrix/ (follow-up to #635) 2026-05-30 15:51:17 +02:00
damocles
2bea5d80b5 matrix: reword gui.enable description, use literalMD for package defaultText (argus #635 nits) 2026-05-30 14:59:24 +02:00
damocles
effe00889f matrix: drop c0re /matrix mount, use targetFlags --base-href, surface availability via env (mara on #634) 2026-05-30 14:56:52 +02:00
damocles
433c972db1 matrix: default gui.enable to matrix.enable + patch fluffychat-web base href for /matrix/ subpath (#634) 2026-05-30 14:41:21 +02:00
lexis
f943976f14 docs(CLAUDE.md): nix/docs.nix → nix/docs/ directory with default.nix + style.css (follow-up to #626) 2026-05-30 13:43:25 +02:00
atlas
8377600f0c nix/meta: follow hyperhive's nixpkgs instead of duplicating channel pin
mara via triage on #619 (post-merge follow-up):
> "I thought all nixpkgs follow the one hyperhive was deployed
>  with?! if not, thats what we should fix."

This is the fix. Flip the rendered meta flake from:

    nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
    nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    hyperhive.url = "...";
    hyperhive.inputs.nixpkgs.follows = "nixpkgs";
    hyperhive.inputs.nixpkgs-unstable.follows = "nixpkgs-unstable";

to:

    hyperhive.url = "...";
    nixpkgs.follows = "hyperhive/nixpkgs";
    nixpkgs-unstable.follows = "hyperhive/nixpkgs-unstable";

Net effect: hyperhive's `flake.nix` is the single channel-pin
authority. Operators who want to slide the whole swarm onto a
different channel do it at the host level via
`inputs.hyperhive.inputs.nixpkgs.follows = "nixpkgs"`, which makes
hyperhive's nixpkgs = the host's nixpkgs and cascades through every
agent transparently.

This is the same shape I shipped in #619 v1 (then reverted per mara
on comment 7354, then re-affirmed via triage). Going with the
re-affirmed direction.

Closes #317 invariant still satisfied — `nixpkgs` is a single
canonical name in the meta tree, just resolving through hyperhive
instead of being its own root input.

Tests:
- rename `render_flake_declares_canonical_nixpkgs` →
  `render_flake_aliases_nixpkgs_to_hyperhive`, asserts the new
  follows-form AND the absence of any literal `nixpkgs.url`
- drop `render_flake_collapses_hyperhive_nixpkgs_via_follows` (no
  separate meta-level nixpkgs to collapse anymore)
2026-05-30 13:43:10 +02:00
atlas
1de4a6f654 nix/docs: fix empty host options page — pick under services.hyperhive.* (#630)
mara on #630: host options page came up empty (template chrome with no
`<h2>` option headers).

Root cause: `pickSubtrees` filtered the host eval against the pre-#615
roots `[ "hyperhive" ]` and `[ "services" "hive-c0re" ]`. #615 moved
the whole host option tree under `services.hyperhive.*`; neither old
root matches anymore, so the filter silently produced an empty tree
and the rendered page degraded to just `<nav> + <main><h1></h1></main>
+ <footer>` chrome.

Fix: pick under `[ "services" "hyperhive" ]`. Agent options stay at
`[ "hyperhive" ]` — per-agent harness options weren't moved by #615.

Before: 100 lines, 0 `<h2>` headers
After:  661 lines, 33 `<h2>` headers covering:
  services.hyperhive.{enable,domain,c0re.*,forge.*,matrix.*,gateway.*}

Closes #630.
2026-05-30 13:05:04 +02:00
atlas
0a376321bf nix/hive-c0re: gate direct c0re port firewall opens on gateway.enable (#621)
Per #621 (filed as follow-up to #620 v0): when the gateway is on
(now the default), the c0re dashboard / manager / sub-agent direct
ports should NOT be open in the host firewall — the gateway nginx
is the sole external entry point, proxying to `127.0.0.1:7000` etc.
internally. Leaving them open in the firewall defeats the "single
front door" story.

Wraps the existing `allowedTCPPorts` + `allowedTCPPortRanges` blocks
in `lib.mkIf (!config.services.hyperhive.gateway.enable)`. Operators
who opt out of the gateway still get the direct ports opened so the
legacy `http://<host>:7000/` flow keeps working.

Verified via `nix eval`:

| gateway | allowedTCPPorts (host firewall) | allowedTCPPortRanges |
| --- | --- | --- |
| on  | `[80 2222 3000]` (gateway + forge) | `[]` |
| off | `[2222 3000 7000 8000]` (forge + c0re + manager) | `[{from=8100; to=8999}]` (agents) |

Forge ports stay direct in both modes — `hive-forge.nix` opens them
independently and they're not proxied through the gateway (that's a
separate follow-up if wanted).

Closes #621.
2026-05-30 12:52:44 +02:00
lexis
e1a21d36ab docs(CLAUDE.md): add hive-gateway.nix entry to file map (follow-up to #620) 2026-05-30 12:52:28 +02:00
lexis
2788501507 docs(README): update matrix.gui to reference hive-gateway (post #620) 2026-05-30 12:52:18 +02:00
lexis
115e500ea5 docs(README): update matrix.gui option to services.hyperhive.* namespace (#615) 2026-05-30 12:52:18 +02:00
lexis
c78f728bc1 docs(README): clarify matrix GUI works with any homeserver, not just hyperhive.matrix 2026-05-30 12:52:18 +02:00
lexis
60ead89efc docs(README): remove package override mention per mara (not supported) 2026-05-30 12:52:18 +02:00
lexis
01988f34f9 docs(README): add hyperhive.matrix.gui.enable + package host options (follow-up to #610 #613) 2026-05-30 12:52:18 +02:00
atlas
32661cf806 nix/docs: extract CSS into sibling file (#625)
Per mara on #622 comment 7442:
> follow up moving scripts and css and stuff out of the nix file.
> can live in the same dir.

Layout:

    nix/docs/
      default.nix   ← what was nix/docs.nix
      style.css     ← extracted from inline `styleCSS = '' ... ''`

`builtins.readFile ./style.css` loads the stylesheet at evaluation
time, so the rendered HTML stays byte-identical (CSS inlined into
each page's `<style>` block — verified). Future client-side scripts
can land at `nix/docs/script.js` with the same `builtins.readFile`
pattern.

Bonus: the docs.nix stub NixOS eval was still force-disabling
`hyperhive.{forge,matrix}.enable` on the pre-#615 namespace; updated
to `services.hyperhive.{forge,matrix}.enable` so `nix flake check`
passes against current main. (Same fix lives on PRs #619 + #620;
whichever lands first wins, the others rebase to a no-op.)

`flake.nix` references updated: `./nix/docs.nix` → `./nix/docs`.

Verified:
- `nix flake check --no-build` passes clean
- `nix build .#docs` produces 5-file bundle identical to pre-PR shape
- inline CSS still appears 3× per HTML page (one per index/host/agent)
2026-05-30 12:51:44 +02:00
atlas
7ab3b125ec nix/docs: update stub-eval + index text to services.hyperhive.* namespace
two stale spots in `nix/docs.nix` that #622 didn't catch:

- the stub NixOS eval was force-disabling `hyperhive.{forge,matrix}.enable`
  on the old paths, which fail eval post-#615 (`The option `hyperhive'
  does not exist`)
- the rendered index page text still listed the old namespace shape

both updated to use `services.hyperhive.*` consistently. necessary on
this branch for `nix flake check` to pass; the same fix lives on PR
a no-op.
2026-05-30 12:03:53 +02:00
atlas
d12da84740 nix/meta: keep concrete nixpkgs.url per mara on #619
mara on #619 comment 7354:
> agent flake needs the url actually so the configuring agent
> can eval against it

Reverts the meta.rs `nixpkgs.follows = "hyperhive/nixpkgs"` shape from
this PR's earlier commit. Restores the pre-PR rendered shape with the
concrete `nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"` baked
into meta + the `hyperhive.inputs.nixpkgs.follows = "nixpkgs"`
redirect, so a configuring agent (or manager pre-apply check) can
evaluate the rendered meta flake without having to resolve through
hyperhive first.

Net behaviour for this PR is now:
- `flake.nix` line 5 bumped 25.11 → 26.05 (kept)
- `meta.rs` literal bumped to match (channel-pin in two places stays
  acknowledged as duplication — drift fixable later if needed)
- `flake_check.rs` test fixtures bumped cosmetically (kept)
- meta.rs tests restored to assert the concrete-URL shape

3 meta tests pass via `nix develop -c cargo test`.
2026-05-30 12:02:48 +02:00
atlas
a43a95cc90 nix: hyperhive owns nixpkgs pin via follows; bump to nixos-26.05 (#526)
Drops the hardcoded `nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"`
from the meta flake renderer. meta now declares:

    nixpkgs.follows         = "hyperhive/nixpkgs";
    nixpkgs-unstable.follows = "hyperhive/nixpkgs-unstable";

so every agent-level `inputs.<X>.inputs.nixpkgs.follows = "nixpkgs"`
resolves transitively to hyperhive's own pin. One channel decision
in the whole tree (hyperhive/flake.nix line 5), no second source
to drift.

`closes #317` invariant still holds: `nixpkgs` is a single canonical
name in the meta tree, it just resolves through hyperhive instead
of being its own root input.

Also:
- bump hyperhive/flake.nix line 5: `nixos-25.11` → `nixos-26.05`,
  flake.lock relocked
- flake_check.rs fixtures bumped cosmetically (synthetic data, not
  shape-affecting)
- rename + rewrite `render_flake_declares_canonical_nixpkgs` →
  `render_flake_aliases_nixpkgs_to_hyperhive`; asserts the new
  follows-form AND the absence of any literal `nixpkgs.url`
- drop the now-redundant `render_flake_collapses_hyperhive_nixpkgs_via_follows`
  test (the old indirection it covered no longer exists)

Closes #526.
2026-05-30 12:02:48 +02:00
atlas
34f0c11936 nix/docs: update stub-eval to services.hyperhive.* namespace
Trailing #615 + #620 rebase fix: `nix/docs.nix`'s stub NixOS eval still
referenced the old `hyperhive.{forge,matrix}.enable` paths that #615
moved under `services.hyperhive.*`. Update to match + also force-disable
the new `services.hyperhive.gateway.enable` so the docs eval doesn't
spawn the gateway container as part of `nix build .#docs`.

`packages.docs{,-host,-agent}` and `checks.docs` all evaluate cleanly
on the post-#615 / post-#620 shape verified via `nix flake check`.
2026-05-30 12:01:01 +02:00
atlas
b37c353f0e nix: hive-gateway v0 — nginx in front of c0re (#609)
Per mara's directive on #609: stand up a single nginx in its own
nixos-container, serve the matrix GUI static dist there, proxy
everything else to hive-c0re. v0 is HTTP-only; TLS / public-domain
shape lands in follow-ups.

New `nix/modules/hive-gateway.nix` declaring `containers.hive-gateway`
modelled on `hive-forge`:

- nixos-container running nginx, shares host netns
- `location /matrix/` → static-serves `hyperhive.matrix.gui.package`
  (fluffychat-web by default) when `matrix.gui.enable` is true
- `location /` → proxy_pass to `127.0.0.1:${dashboardPort}` with
  websocket + SSE upgrade headers + 1d read timeout

Options (`hyperhive.gateway.*`):
- `enable` (default `true`) — gateway on by default, opt out to bypass
- `port` (default `80`) — nginx listen port on the host
- `upstreamHost` / `upstreamPort` — c0re target, defaults to
  `127.0.0.1:${services.hive-c0re.dashboardPort}`
- `openFirewall` (default `true`) — open the listen port
- `localHostsEntry` (default `false`) — when true, adds an
  `/etc/hosts` entry mapping `hyperhive.domain` → `127.0.0.1` for
  local-dev / test loops without real DNS (per mara's spec)

`hive-c0re.nix` updates: when gateway is enabled, skip wiring
`HIVE_MATRIX_GUI_DIR` (gateway owns `/matrix/` now). When gateway is
off, c0re's pre-existing matrix mount stays as the fallback.

README: short "Optional" block introducing the gateway + the
`localHostsEntry` knob.

```sh
nix flake check --no-build

nix build .#docs-host
```

End-to-end eval matrix:

| gateway.enable | matrix.gui.enable | c0re HIVE_MATRIX_GUI_DIR | gateway container |
| --- | --- | --- | --- |
| true (default)  | true  | unset (gateway serves) | present |
| true            | false | unset                  | present, no /matrix |
| false           | true  | set (c0re serves)      | absent  |
| false           | false | unset                  | absent  |

- TLS termination — separate follow-up once mara picks a story
  (self-signed-mkcert vs operator-provided certs)
- Per-agent UI routing (`/agent/<name>/`) — depends on agent base-path
  support which is a frontend lift
- Subdomain routing for `matrix.${hyperhive.domain}` — same-origin
  `/matrix/` is the v0 shape per mara ("leave everything else as is")

Closes part of #609 (matrix GUI re-rooting onto nginx); leaves the
issue open for the subdomain re-root + `.well-known/matrix/client`
piece once the multi-host story matures.
2026-05-30 12:01:01 +02:00
lexis
1a839d45e3 docs(CLAUDE.md): update host option namespace to services.hyperhive.* (#615); add nix/docs.nix entry (#618) 2026-05-30 12:00:46 +02:00
atlas
983a4fa229 nix/docs: demote index sections h2 → h3 (argus #622 nit)
argus on #622 comment 7419 🟡:
> monospace h2 on index — the CSS styles `h2` with `ui-monospace`
> font (intended for option-name headings in the per-option pages).
> on the index page, "host options" / "agent options" / "Regenerate"
> headings also get monospace treatment. cosmetic; reads as
> intentional if not, easy to scope.

Index page now uses h3 for section headers, leaves h2 free for the
auto-generated option-name headings on host.html / agent.html where
the monospace styling is appropriate.

(Other argus nit — stale namespace text in indexHTML's option
listings — will be addressed when this branch rebases post-#615
merge, same as #620.)
2026-05-30 11:27:31 +02:00
atlas
0cc27fbe32 nix/docs: add HTML output for the options reference (mara/internal-requests#8)
mara on mara/internal-requests#8:
> nix/docs.nix currently only emits CommonMark via doc.optionsCommonMark;
> add HTML output alongside.

Renders host + agent option pages as standalone HTML using cmark-gfm
(stock nixpkgs, no pandoc). Each page is wrapped in a minimal
inline-CSS template — no external stylesheets, no second HTTP fetch.

New bundle layout (consumed by nginx at `hyperhive.darkest.space/options/`):

    index.html   — landing page with cross-links + regenerate snippet
    host.html    — services.hive-c0re.* / hyperhive.{domain,forge,matrix}.*
    agent.html   — hyperhive.{model,allowedRecipients,extraMcpServers,…}
    host.md      — same content, CommonMark source-of-truth
    agent.md     — same content, CommonMark source-of-truth

All asset paths inside the rendered HTML are relative (`./host.html`
etc.) per mara's spec — the bundle mounts at any URL prefix without
rebuild. Forge source links from `transformOptions` are preserved
as proper `<a href>` (verified: `forge.darkest.space/.../nix/...`).

`packages.<system>.docs` now emits HTML primarily; `docs-host` and
`docs-agent` outputs flip from .md to .html (the .md content is still
in the `docs` bundle for callers that want the source shape).

The native nixos-render-docs `options html` subcommand doesn't exist
(only `manpage` / `commonmark` / `asciidoc`). The `manual html` path
exists but needs a full manual structure for what we're treating as
two standalone pages — overkill. cmark-gfm over the existing
CommonMark output is the leanest path.

Verified:

    nix flake check --no-build
    nix build .#docs        # bundled site (5 files)
    nix build .#docs-host   # standalone HTML page
    nix build .#docs-agent  # standalone HTML page
2026-05-30 11:27:31 +02:00
atlas
3b500bba1b nix: pivot to services.hyperhive.* per mara directive (#612)
Per [mara on PR #615 comment 7349](http://localhost:3000/hyperhive/hyperhive/pulls/615#issuecomment-7349):
> follow nix conventions, services.hyperhive it is. the earlier we
> change this, the less breakage.

Renames the entire host-side option tree under `services.hyperhive.*`:

- `services.hive-c0re.*` → `services.hyperhive.c0re.*`
- `hyperhive.enable` → `services.hyperhive.enable`
- `hyperhive.domain` → `services.hyperhive.domain`
- `hyperhive.forge.*` → `services.hyperhive.forge.*`
- `hyperhive.matrix.*` → `services.hyperhive.matrix.*`

Per mara's "earlier = less breakage", the previous `services.hive-c0re.enable`
deprecation alias is dropped. Operators get a clear eval error on the
old paths pointing at the rename. Single migration moment.

Per-agent options in `nix/templates/harness-base.nix` (`hyperhive.model`,
`hyperhive.allowedRecipients`, etc.) stay at `hyperhive.*` — they're
container-level config, not services in the NixOS sense.

Verified via `nix flake check --no-build` + an end-to-end NixOS eval
exercising every renamed path.

Follow-up needed: rust source comments referencing the old NixOS
option names (`hive-c0re/src/{meta,coordinator,main,dashboard}.rs`)
should be updated in a separate pure-rust PR to keep this one
strictly nix-only.
2026-05-30 11:07:57 +02:00
atlas
32148179e6 refactor: move hive-c0re options to hyperhive namespace (#612)
- Move options.services.hive-c0re → options.hyperhive.c0re
- Add options.hyperhive.enable to auto-enable c0re + subsystems
- Add deprecation alias for services.hive-c0re.enable (backward compat)
- Update doc references in README, flake.nix, docs, harness-base.nix
- Simplifies config: 'hyperhive.enable = true' now enables everything

Existing operator configs using services.hive-c0re.enable will
continue to work but emit a deprecation warning. Aligns the option
namespace with the existing hyperhive.* family (matrix, forge, domain).

fixes #612
2026-05-30 11:07:57 +02:00
atlas
24f61f3386 nix/docs: drop dead walk helper + dedupe checks.docs eval
argus review notes on #618:

- `walk` in `pickSubtrees` was leftover from an earlier traversal
  design; `pick` does everything we need. drop it.
- `checks.docs` was re-importing `nix/docs.nix` independently of
  `packages.docs`; the comment claimed they shared eval but they
  didn't (nix's lazy eval + import caching made the *result*
  identical, not the eval). switch to `inherit (self.packages.\${system}) docs;`
  so the check is literally the package output, no second import.
2026-05-29 23:46:39 +02:00
atlas
6a64770c79 nix: add options docs outputs for host + agent surfaces (#616)
Auto-generate CommonMark references for hyperhive's two NixOS module
surfaces via `pkgs.nixosOptionsDoc`:

- `packages.<system>.docs-host` — operator-facing options exposed by
  `hyperhive.nixosModules.default` (`services.hive-c0re.*`,
  `hyperhive.domain`, `hyperhive.forge.*`, `hyperhive.matrix.*`).
- `packages.<system>.docs-agent` — per-agent options declared in
  `nix/templates/harness-base.nix` (model, allowedRecipients,
  extraMcpServers, frontend, forge, matrix, gui, …).
- `packages.<system>.docs` — both pages plus a thin `README.md`
  index, bundled for publishing.

Declaration links are rewritten to point at the forge source tree
instead of nix-store paths.

Host options come from a stubbed `nixosSystem` eval that force-disables
all hyperhive subsystems — only the *declarations* feed the doc
renderer, no heavy build inputs end up in the closure. Agent options
reuse `nixosConfigurations.agent-base.options` (already evaluated).

Also wired as `checks.<system>.docs` so CI fails fast on eval breakage.
2026-05-29 23:42:24 +02:00
lexis
d074b25fac docs(agent-hierarchy): mark section D done — legacy /state mount dropped (#604) 2026-05-29 22:10:13 +02:00
iris
40b9a7f2cd dashboard: M4TR1X → tab strip entry for matrix GUI (#607)
Frontend half of #607 v0 — adds the `◆ M4TR1X ◆ →` page-link entry
to the dashboard tab strip between SCH3DUL3S and FL0W →. Same
`tab-link` class as FL0W → since /matrix/ is its own SPA, not an
in-place pane swap.

Hidden via the `hidden` attribute by default; tabs.js's `refreshState`
flips it based on `s.matrix_gui_enabled` (added in #610). When the
operator hasn't set `hyperhive.matrix.gui.enable = true` the snapshot
returns false and the tab strip doesn't surface a dead link.

docs/web-ui.md updated:
- chrome-header tab-strip list now includes M4TR1X → with the
  hidden-when-disabled note
- new "M4TR1X page" section under FL0W explaining the same-origin
  serve via hive-c0re ServeDir + the manual homeserver URL pick on
  first login (with #609 tracking the post-#15 nginx-front re-root +
  .well-known/matrix/client auto-discovery)
2026-05-29 22:06:28 +02:00
damocles
360f2af15f dashboard: optional matrix GUI static mount at /matrix (#607 v0) 2026-05-29 21:40:05 +02:00
damocles
dc99e64b2d drop legacy /state mount for manager (#604) 2026-05-29 21:21:44 +02:00
lexis
7aadf38483 docs: fix matrix tool signatures per damocles nits (room not room_id, no format?, member_count not unread) 2026-05-29 21:02:25 +02:00
lexis
744494ba73 docs: matrix MCP per-agent option + tool surface (follow-up to #603) 2026-05-29 20:58:16 +02:00
damocles
30c9eed562 matrix-mcp: drop dual-line PathExists, trim watcher comments (mara nag) 2026-05-29 20:51:01 +02:00
damocles
688058c429 matrix-mcp: reframe state-mount comments as #604 migration fallback (mara nag) 2026-05-29 20:51:01 +02:00
damocles
b4bcd3da05 matrix-mcp: copy state-mount comment to hive-matrix-daemon.path (iris #603 suggestion) 2026-05-29 20:51:01 +02:00
damocles
61133e71e7 matrix-mcp: surface serialise errors + clarify ping doc (argus #603 nits) 2026-05-29 20:51:01 +02:00
damocles
e6c53045ad matrix: hive-matrix-mcp crate (daemon+stdio bridge) + harness wiring (#548 phase 3) 2026-05-29 20:51:01 +02:00
lexis
23ed124881 docs(web-ui): fix interval composer wording + SSE->re-render (iris nits) 2026-05-29 20:38:16 +02:00
lexis
efdd1dd156 docs(web-ui): schedule creation is now inline table bottom row (follow-up to #602) 2026-05-29 20:36:26 +02:00
iris
0deca50352 dashboard: fold schedule creation into the table view (closes #564)
The N3W SCH3DUL3 vertical form is gone. The schedules table now
carries an always-visible inline create row at the bottom — fill the
cells, click + to POST /api/schedules, the new schedule appears
above on the next refresh.

Per-column inputs match the display semantics:
- `next` → `<input type="datetime-local">` (defaults to now+5min)
- `every` → 4 mini d/h/m/s number inputs (blank/all-zero = one-shot)
- `body` → `<textarea rows=1>` expanding to 4em on focus-within
  so multi-line prompts still fit (closes mara's "prompt may still be
  multi-line" requirement)
- per-agent columns → checkbox (whole cell clickable via padded label)
- actions → + submit + ⌫ reset (clears the carry without POSTing)

`newScheduleCarry` module-scope object survives the paintAtomic
re-render so mid-typed values stick across schedule-list refreshes
(same pattern as `scheduleEditCarry` from #474).

H2 collapses from "N3W SCH3DUL3" + "QU3U3D SCH3DUL3S" down to a
single "SCH3DUL3S" since the section now does both. Empty-state
branch on `renderSchedulesList` is gone — the table always renders
because the create row is always there.

`#schedule-new-section` div + `renderScheduleNewForm` /
`readScheduleFormCarry` / `submitNewSchedule` and the
`.schedule-new-form` CSS selector all removed. The edit-form path
(#474 `renderScheduleEditForm` colspan'd row on `✎` toggle) is
unchanged — "edit mode is inline in the table" already shipped
there, this PR just adds the same mental model for create.

Validations match the old form: empty targets / empty body /
invalid datetime / non-integer interval each surface an `alert()`.
The + button shows a spinner while the POST is in flight, then
clears the carry + triggers `refreshSchedules()`.
2026-05-29 19:57:14 +02:00
lexis
c9e1c79035 docs(CLAUDE.md): trim identity.rs entry to index-style summary 2026-05-29 19:46:35 +02:00
lexis
38d811d5b1 docs(CLAUDE.md): add identity module file map entry (follow-up to #595) 2026-05-29 19:46:35 +02:00
lexis
0769c1e814 docs: fix cancel-X glyph: ✕ → ✗ (U+2715 → U+2717, nit from iris review) 2026-05-29 19:43:51 +02:00
lexis
b6bff2556d docs(web-ui): logout, mark-all-read, cancel-X queue, qualified_label (follow-up to #576 #559 #575 #595) 2026-05-29 19:43:51 +02:00
iris
1ae939499c dashboard: hide selection bar outside SW4RM tab (closes #596)
The sticky bulk-action bar (#443) was visible on every tab whenever the
selection was non-empty. On Y3R C4LL / SYST3M / SCH3DUL3S the operator
sees a floating bar without the agent cards next to it for cross-
reference — which is what mara called out in #596.

Fix: gate the bar on `document.body.dataset.activeTab === 'swarm'` in
addition to the existing non-empty-selection check. Selection state
itself stays in memory, so the bar reappears on return to SW4RM if any
agents are still ticked. The `activateTab` hook now sets the data
attribute and re-runs `renderSelectionBar` so the toggle takes effect
on hashchange without waiting for the next SSE update.
2026-05-29 19:35:30 +02:00
iris
a725d34b19 harness: emit needs_login_idle on every wait_for_login entry (closes #563)
mara on #563: 'we fixed the agent to not start turns in that
state (it fell back to online before), but this does not show on
dashboard properly'.

Root cause: the per-agent harness flips LoginState::NeedsLogin in
memory on three entry paths (cold-boot without a session, 401
mid-turn, /api/logout) and parks in wait_for_login. But
wait_for_login itself never called bus.emit_status('needs_login_idle')
at entry — only the /api/logout handler does that today. So:

- Cold boot: agent has no session, harness shows 'needs login'
  on its own web UI (via LoginState mutex), but the dashboard's
  needs_login field stays false because the
  {state_dir}/hyperhive-needs-login sentinel was never written.
- 401 mid-turn: same — the 'after a turn failed' path in
  hive-ag3nt.rs / hive-m1nd.rs flips LoginState directly without
  emitting status, then calls wait_for_login, which now waits
  silently with no sentinel write.

Fix: hoist the emit_status('needs_login_idle') call into
wait_for_login itself. All three entry paths get the sentinel
write for free; the /api/logout handler's explicit call (web_ui.rs
line 966) becomes redundant but idempotent — no behaviour change
there. The 'online' clear at session refresh stays exactly where
it was at the loop's exit.

Both hive-ag3nt and hive-m1nd binaries share wait_for_login, so the
manager harness benefits without a separate change.
2026-05-29 19:28:42 +02:00
iris
5a0b6ca907 identity: serialise env-mutating tests on a module mutex (damocles #595 nit)
Cargo's default test runner parallelises tests within a binary,
so the original 'tests run serially' comment was wrong — two
`with_env` calls running concurrently would race the
process-wide HIVE_LABEL / HYPERHIVE_HIVE_DOMAIN state.

Added a module-scope `static ENV_LOCK: Mutex<()>` and acquire it
at the top of `with_env` so each set / run / restore window is
exclusive. Poison recovery via `unwrap_or_else(into_inner)` so a
single test panic doesn't cascade through the rest of the module.

Lighter than pulling in serial_test for one module. No new deps.
2026-05-29 19:13:01 +02:00
iris
f44bf19707 hive-ag3nt: identity module with hive-qualified label (#589 phase A, first PR)
First chunk of #589 v0 phase A: plumbing the hive-qualified
'name@hive' form through the per-agent surfaces that the harness
itself owns. Broker from/to + dashboard rendering + container_view
follow in subsequent PRs once damocles ships the HYPERHIVE_HIVE_DOMAIN
env var in harness-base.nix.

- new hive_ag3nt::identity module: label() / hive_domain() /
  qualified_label() / qualify(label). Reads HYPERHIVE_HIVE_DOMAIN
  (set by hive-c0re.nix module from hyperhive.domain) — when unset
  or empty, qualified_label degrades to just the short label so
  existing single-hive deployments are unchanged. Six unit tests
  cover the set / unset / empty / arbitrary-label paths.
- prompt::render gains {qualified_label} substitution alongside
  the existing {label}. system.md template uses both: the agent
  intro now reads 'You are hyperhive agent iris (qualified:
  iris@darkest.space) in a multi-agent system. ... When you're
  talking to or about a peer on a different hive, use the
  qualified form (name@hive) so the operator + the manager can
  disambiguate'. Manager flavor gets the same treatment.
- /api/state gains qualified_label: String. Always present, equals
  label when no domain is configured.
- frontend setHeader takes the qualified_label, drives the browser
  tab title (so two  tabs from different hives are
  distinguishable in the tab bar) while the glyphic #title stays
  short for the cinematic header.

Gated on env var presence — no behaviour change for single-hive
deployments. Pairs with damocles's upcoming harness-base.nix
HYPERHIVE_HIVE_DOMAIN ship; safe to land in either order.
2026-05-29 19:09:44 +02:00
damocles
977bb16678 dashboard: format guard on post_purge_tombstone (path traversal hole — argus 🔴 on #593) 2026-05-29 18:54:22 +02:00