Commit graph

4,018 commits

Author SHA1 Message Date
atlas
b422367942 deploy: separate "what this host deploys" from swarm-wide truth
`services.hyperhive.swarm.*` is meant to be identical on every host in a
swarm — it describes the swarm, and every hive needs all of it to be a
client. But it also carried the `enable` toggles, which are precisely the
values that must differ per machine. The namespace that should be the
same everywhere held the one thing that cannot be.

Adds `services.hyperhive.deploy.*` for a host's deployment decisions, and
moves the first of them (`swarm.grafana.enable` -> `deploy.grafana`) as
the pattern for the rest. Flat and named for the thing deployed rather
than grouped under a "swarm services" attribute: from the deploy side it
does not matter what kind of thing each one is, and a grouping by service
kind would re-encode the service-side taxonomy into a layer that does not
care about it.

Behaviour is unchanged. The move is a rename in the strict sense — same
type, same meaning, new path — so `mkRenamedOptionModule` carries it and
existing configs keep evaluating with one warning naming both paths. The
renames live in the new module rather than the service modules, so the
whole migration has a single home and a single file to delete when the
deprecation window closes.
2026-08-30 04:23:22 +02:00
atlas
9a01906275 hive-sh4re: drop the nix explanation from the panic message too
Same layering rule as the previous commit, one construct over. The
remediation text explained how nix wires the var and pointed at
`nix/assets.nix` -- a path that does not exist either, so it carried
both defects this branch is about.

What a developer hitting this panic needs is the layout to point at,
which is a fact about this crate.
2026-08-30 04:19:11 +02:00
atlas
1e011bcd93 hive-sh4re: state the env-var contract, not who sets it
Per review: the rust code should not explain nix stuff.

The original doc comment named nix modules as the setters of
HIVE_ASSETS_DIR, and the previous commit here made that worse -- it
replaced two stale nix paths with four accurate ones, entrenching a
cross-layer explanation instead of removing it.

What this crate actually depends on is the env var and the layout it
points at. Who sets it belongs to the layer that sets it.
2026-08-30 04:19:11 +02:00
atlas
d17aa254dd nix, hive-sh4re: name modules that exist in the stale harness-base refs
harness-base.nix has never existed in this tree. Four comments named it,
or a `harness-base` module, as the place to look:

- weston-vnc.nix: the agent user is declared and home-chowned by
  nix/agent-modules/user.nix
- hive-ci.nix: the sandbox-fallback reasoning lives in
  nix/agent-modules/default.nix -- which the very next comment block in
  the same file already cites correctly
- packages/default.nix: the per-bin consumer is
  nix/agent-modules/packages.nix
- hive-sh4re/src/assets.rs: HIVE_ASSETS_DIR is set by
  hive-c0re/environment.nix and agent-modules/default.nix +
  agent-service.nix, and the package is built by nix/packages/assets.nix
  -- not the equally nonexistent nix/assets.nix

assets.rs was twice declared out of scope on the sibling PR because it
names a module rather than a file. That distinction was real and
irrelevant: neither the module nor the nix/assets.nix path it points at
exists. Reading the wording is not checking the reference.

Every replacement path was verified to exist, with a deliberately bogus
path as a control.
2026-08-30 04:19:11 +02:00
atlas
e56fc97be8 hive-priv, hive-c0re: link docs/network.md instead of restating it
The network-isolation doc comments carried prose docs/network.md
already owns, and three of them named `harness-base.nix` — a file
that does not exist. The `hyperhive-isolated-dns` oneshot lives in
nix/agent-modules/network.nix, which the doc gets right.

That is #3749's argument reproducing itself: the same fact written
in two places goes stale in the copy nobody reads. Linking removes
the class, not just the instance — a link cannot name a nonexistent
file without the doc noticing first.

Trap and measurement comments stay put, per the issue's scope: the
load-bearing HOST_ADDRESS default-route note, the unquoted
$EXTRA_NSPAWN_FLAGS expansion, and the "isolation is the only mode"
invariants are facts about this code, not about the subsystem.
2026-08-30 04:13:22 +02:00
iris
49c3b86dfd agent ui: reset cancel-turn busy state via .finally(), not a thinking-flip effect
argus (PR review): the thinking-flip useEffect left the button stuck
disabled if the /api/cancel POST itself failed while the turn was
still genuinely thinking, since nothing re-fires the effect. Switch
onCancelTurn's signature to () => Promise<void> and reset cancelBusy
in a .finally() on that promise instead — fires on success or
failure alike, matching app.js's original
postCancelTurn().finally(() => { btn.disabled = false; }).
2026-08-30 04:05:26 +02:00
iris
b753ec2093 agent ui: restore the cancel-turn button dropped in the Preact rewrite
Root-caused mara's 'no interrupt button on agent term anymore' report:
the pre-rewrite app.js had a visible <button id=cancel-btn> (class
btn-cancel-turn, already-styled CSS still in agent.css but orphaned)
shown only while a turn was in flight, wired to /api/cancel. The
Preact rewrite (agent terminal Preact rewrite) ported the /cancel
slash command but never re-added the visible button, so interrupting
a turn now requires typing a command instead of clicking.

Adds thinking/onCancelTurn props to StatusChips, rendering the same
btn-cancel-turn markup only while turn_state === thinking, wired to
the existing postCancelTurn() (termActions.ts) + refresh(). Verified
with real headless-chromium screenshots against a mock /api/state:
button renders while thinking, is absent while idle.
2026-08-30 04:05:26 +02:00
iris
3747d46fae agent ui: stop pause/resume from navigating to hive-c0re's raw response
pauseAction.ts submitted a real <form> POST, so clicking pause/resume
navigated the whole page to hive-c0re's plain-text "ok" response body
instead of staying on the agent terminal. Switch to a fetch with
mode: 'no-cors' (still cross-origin-safe, no CORS headers needed from
hive-c0re) + credentials: 'include' to match the form's cookie
behavior, then refresh() the agent state afterward, matching the
existing postModel/postEffort pattern right next to it in Root.tsx.
2026-08-30 03:57:11 +02:00
damocles
aaac939cb2 choosing-a-comms-channel: drop the history framing, state the guidance plainly 2026-08-30 03:42:57 +02:00
damocles
63c7c4ae2c hive-c0re: drop stale 'question' example from check_size doc 2026-08-30 03:42:57 +02:00
damocles
b7b8aae8e8 hive-c0re/hive-agent-mcp: fix 3 leftover ask/answer-removal doc comments 2026-08-30 03:42:57 +02:00
atlas
4d8e740890 hive-priv: the call-site comment too, not just the function's doc
The inline comment above write_bridge_dns_marker still said the marker
is 'written on isolate, removed otherwise, so the same shared container
toplevel behaves correctly in both modes'. There is one mode now.

Caught because argus pointed out that reading every changed function's
doc comment does not cover comments at the call sites -- the complete
form is to read every comment in the context around each hunk, which is
what git diff -U15 shows.
2026-08-30 03:32:08 +02:00
atlas
bb732a106c hive-priv, hive-c0re: two more doc comments describing the deleted branch
set_nspawn_flags said PRIVATE_NETWORK was forced 0 for web-UI
reachability; it is now unconditionally 1 and the UI is reached over the
bridge. write_bridge_dns_marker said it writes or removes the marker;
the removal path went with the host-netns case.

Neither was reachable by the sweeps that found the earlier ones: this
prose describes the *value in words* ('forced 0'), not the code's
literal PRIVATE_NETWORK=0, and neither names the env var. Found by
reading the doc comment of every function whose body this branch
changed.
2026-08-30 03:32:08 +02:00
atlas
aaf55b9c27 docs: network.md + conventions.md no longer describe the removed toggle
argus caught docs/network.md still listing HIVE_NETWORK_ISOLATION as a
live c0re signal and saying hive-c0re reads it. Neither is true after
this branch. conventions.md had the same shape one file over: it
described write_dropins as writing PRIVATE_NETWORK=0.

docs/gotchas.md has the same staleness and is deliberately untouched --
#3723 already rewrites that passage, and editing it here would conflict
with a PR that has been reviewed five times.

git grep now reports no HIVE_NETWORK_ISOLATION anywhere in tracked
files.
2026-08-30 03:32:08 +02:00
atlas
83c0e4b4bf require network isolation, deleting the residual non-isolated branch
Per mara on #3725: the on/off toggle is removed, and required env vars
unset lead to a crash. HIVE_NETWORK_ISOLATION is gone from
hive-network.nix -- it was the toggle.

Validation happens once at daemon startup rather than per container.
The variables are process-global, so a bad value breaks every container
rather than one: failing at boot gives a single diagnostic naming the
bad value, and cannot reach a state where some containers were
configured before it was noticed.

Option<NetworkIsolation> collapses to NetworkIsolation through the wire
type, client and helper, which deletes the branch instead of leaving it
unreachable. serde(default) is dropped on that field deliberately: a
request omitting isolation is now rejected rather than defaulting to a
container sharing the host's network namespace.

What this replaces was a silent security downgrade. Of the four ways
into the old fallback, two logged nothing at all -- a container came up
without isolation and the journal agreed it was fine.

Doc comments that still described the removed branch are updated
(argus's note on #3723 scoped that to this issue). The hive-priv one is
a minimal edit inside the block #3723 rewrites; de-splicing is that
PR's job.
2026-08-30 03:32:08 +02:00
damocles
16ac84ca63 docs/hive-c0re: fix ask/answer removal doc gaps argus caught on #3741 2026-08-30 03:02:31 +02:00
damocles
2850270829 hive-c0re/hive-sh4re: remove the ask/answer wire protocol + core routing 2026-08-30 01:18:17 +02:00
damocles
46183795dd hive-c0re, docs: sweep remaining stale ask/answer-dashboard references 2026-08-29 23:28:32 +02:00
damocles
47cac50e6e hive-c0re: remove the dashboard's ask/answer surface 2026-08-29 23:20:17 +02:00
damocles
a295fba09c hive-agent-mcp: drop stale ask/answer language from tool descriptions 2026-08-29 22:27:28 +02:00
damocles
c865114743 hive-agent: remove the in-container questions mirror 2026-08-29 22:27:28 +02:00
damocles
1c4d662cf1 address review: drop stale ask/answer refs from the messaging tool group + a comment 2026-08-29 22:26:23 +02:00
damocles
c10e551b2a hive-agent-mcp: remove the ask/answer MCP tools 2026-08-29 22:26:23 +02:00
damocles
c661d699ad enable clippy::must_use_candidate, add #[must_use] to the 3 flagged fns 2026-08-29 20:45:07 +02:00
iris
760e5ad4cc badge: fix quiet-variant regression under an explicit theme override
argus review: the two :root[data-theme='...'] glass-override rules
have specificity 0-3-0 (:root + [data-theme] + .ui-badge), beating
.ui-badge-quiet's 0-1-0 — so whenever a user has an explicit theme
override set (not just relying on prefers-color-scheme), these rules
reintroduced a fill on quiet badges, regressing the settings/links
trigger fix. Scope both overrides with :not(.ui-badge-quiet).

Verified with a real repro (same synthetic striped-bg test page,
before/after) rather than just the specificity arithmetic.
2026-08-29 20:43:11 +02:00
iris
79a689364b badge: frosted-glass fill for the default filled variant
Translucent color-mix background + backdrop-filter blur/saturate,
same recipe as the header chrome/terminal glass (chrome.css,
terminal.css). Dark (mocha) palette only: applies the glass look to
the default filled badges, keeps light (latte) mode's plain solid
fill unchanged since a bright/busy background behind a badge would
lose legibility from the same transparency that helps on a dark
background. variant="quiet" badges are untouched (they already have
no permanent fill to frost).

Verified with a synthetic striped-background test page (raw CSS
against colors.css/theme.css/Badge.css, not the bundled app) to make
the blur/transparency visually obvious, plus real headless-chromium
screenshots of the built agent + swarm-ui dist to confirm no
regression against real content — the effect is real but subtle
there since the chrome background is flat, which is expected.
2026-08-29 20:43:11 +02:00
damocles
ff0a6660aa dashboard: remove the Y3R C4LL questions pane (ask/answer removal, frontend) 2026-08-29 20:35:27 +02:00
iris
e1aae29068 badge: add a quiet variant for icon-only header triggers
Badge's default look is a filled pill, right for status/picker chips
but wrong for an icon-only header button like the settings gear or
agent links trigger, which should read as chrome. Add variant='quiet'
(same naming/shape as Button's ButtonVariant) that drops the idle
background, keeping the existing hover/expanded feedback.

Apply it to the two icon-only Badge triggers: shared SettingsMenu
(used by both swarm-ui and the agent page) and the agent page's own
MetaNav links trigger. Add a components-page showcase sample so the
variant has a visible regression check going forward.
2026-08-29 20:28:19 +02:00
damocles
592af562f9 hive-priv: finish extracting exec's remaining match arms 2026-08-29 14:00:22 +02:00
damocles
584a973344 hive-priv: extract exec's non-delegating match arms into named functions 2026-08-29 13:05:14 +02:00
damocles
f1c5d49289 docs/gotchas: drop the env-var/removed-option framing, just state the always-isolated behavior 2026-08-29 12:54:07 +02:00
damocles
e3ef4a9630 docs/gotchas: drop mention of the branch slated for removal, describe only the real behavior 2026-08-29 12:54:07 +02:00
damocles
0f337756c8 docs/gotchas: point at hyperhive#3725 for removing the residual non-isolated branch 2026-08-29 12:54:07 +02:00
damocles
07f4b96a72 docs/gotchas: correct network-isolation description (it's the only mode now, not opt-in) 2026-08-29 12:54:07 +02:00
damocles
fcdba9e681 docs/gotchas: describe hive-priv's network-isolation nspawn-conf branch, fix a spliced doc comment 2026-08-29 12:54:07 +02:00
damocles
734fc6599c docs/persistence: document the todo/reminder retention windows vacuum.rs already enforces 2026-08-29 11:55:34 +02:00
iris
4175ae86e3 icons: restore inline-SVG link/gear icons, share them across all three pages
Fixes a regression + a longer-standing inconsistency (mara: "agent
page link icons is different from swarm ui, settings icon looks weird
since component extract").

- The `SettingsMenu` shared-component extraction swapped swarm-ui's
  original inline-SVG gear trigger for a plain `⚙` text glyph (matching
  agent's `MetaNav`, which was itself still on the `🔗` emoji at the
  time). An emoji/text glyph is rendered by the OS/browser's own font
  at that font's fixed metrics — it can never match a neighbouring
  icon in size or weight, and some codepoints (the gear included)
  aren't even reliably covered by every font.
- New `@hive/shared/icons.js` (`GearIcon`, `LinkIcon`) — the exact SVG
  markup that used to live only in swarm-ui's `SettingsMenu`/
  `LinksMenu` as two separate inline copies, now the one shared source.
- `SettingsMenu` (shared) uses `GearIcon`; agent's `MetaNav` and
  swarm-ui's `LinksMenu` both use `LinkIcon` — three consumers, one
  rendering path, matching stroke/viewBox/size everywhere.

Verified with real screenshots on both agent and swarm-ui — both
trigger icons render as the same crisp line-icon style now.
2026-08-29 11:54:21 +02:00
damocles
350b4e9fb7 swarm-otel/swarm-controller: authenticate + route the swarm-tier OTLP producer through the gateway 2026-08-29 11:17:24 +02:00
damocles
f3be08f6b6 move otel_http_client from swarm-queue-client into swarm-controller 2026-08-29 11:17:24 +02:00
damocles
361396cab8 wire the authenticated OTLP push into vcs_metrics and hive-jobq-metrics 2026-08-29 11:17:24 +02:00
damocles
7913be5435 swarm-queue-client: add an authenticated HttpClient for OTLP exporters (otel-auth feature) 2026-08-29 11:17:24 +02:00
damocles
e8584e595b swarm-queue-client: audience-scoped tokens + a blocking mint for a non-reactor caller 2026-08-29 11:17:24 +02:00
damocles
2aa33f12d2 swarm-otel: add an unauthenticated swarm-tier OTLP receiver for swarm-controller to push to 2026-08-29 11:17:24 +02:00
iris
9720bdfad0 settings: move the theme/motion panel into @hive/shared, add motion to agent
Review feedback on this PR (mara): "i think the component should be
shared. motion setting is missing." Both addressed:

- `settings-storage.ts` (generic localStorage hook), `theme-apply.ts`,
  `motion-apply.ts`, and `SettingsMenu.tsx`/`.css` all move from
  swarm-ui's `lib/`/`shell/` into `@hive/shared/src/settings/` —
  agent's previous local copies are deleted outright rather than kept
  as a second implementation. One component, `Badge` trigger
  everywhere (already used elsewhere in swarm-ui, so not a new visual
  language there either) — storage keys stay caller-owned (`themeKey`/
  `motionKey` props + matching `useApplyThemeOverride`/
  `useApplyMotionOverride` calls at each package's single mount point)
  so agent and swarm-ui keep fully independent, non-colliding
  persisted settings.
- Agent's settings menu now includes the motion row, matching
  swarm-ui's. No animation in the agent package is gated behind
  `data-motion` yet — same as when swarm-ui first built this plumbing
  ahead of having a consumer — so it's currently inert there, ready for
  whenever agent grows a motion-guarded animation.
- swarm-ui's own theme default flips to `'dark'` as part of this move
  (`theme-apply.ts`'s new default), superseding PR #3715 — that PR
  becomes redundant once this lands and will be closed rather than
  merged, to avoid the two colliding on the same file.

Verified end-to-end with real screenshots on both pages: shared
component renders identically (Badge trigger, theme+motion rows, dark
default) on agent's mock server and a static rebuild of swarm-ui's
dist.
2026-08-29 11:11:39 +02:00
iris
b28e8f1c4e agent: add a settings menu with a theme override, defaulted to dark
Ports swarm-ui's `SettingsMenu` (mara: "agent terminal page should get
the settings panel from swarm ui as well") — same shape as `MetaNav`
already in this header: a `Badge` icon trigger ("⚙"), popover, close on
outside-click/Escape.

`theme-apply.ts` + `settings-storage.ts` are near-verbatim ports of
swarm-ui's own (duplicated rather than moved into `@hive/shared` for
this pass — lower risk than reworking swarm-ui's imports in the same
change). Defaults the stored override to 'dark', not 'system', for the
same reason as swarm-ui's own default flip: `prefers-color-scheme` has
no real "unset" value, so 'system' silently reads as light for anyone
who's never touched an OS dark-mode toggle.

Motion NOT ported — agent has no animation gated behind `data-motion`
yet, so that plumbing would have nothing to control.

Verified end-to-end: default dark on a fresh load, and an explicit
localStorage override to 'light' correctly re-themes the whole page via
the existing `colors.css` `:root[data-theme='light']` block (already
shipped, previously only reachable from swarm-ui).
2026-08-29 11:00:11 +02:00
iris
51a9262202 theme: add --muted-on-dim, a --muted anchored to --purple-dim instead of --bg
--muted is color-mix()'d toward --base00/--bg — correct for dimmed text
on the page background, wrong for dimmed text sitting on the elevated
--purple-dim fill (badge/dropdown-item backgrounds). Badge's label/caret
used bare --muted there and mara measured it at ~1.3:1 contrast against
her theme's badge fill, essentially invisible.

--muted-on-dim mixes toward --purple-dim instead, same contrast-floor
technique as --muted itself, just anchored to the surface it's actually
used on. Applied to .ui-badge-label/.ui-badge-caret and to Dropdown's
active-item description (same bug: its row bg is --purple-dim too).

Ceiling note: even plain --fg only reaches ~3.4:1 against --purple-dim
in mara's theme, short of formal 4.5:1 AA — that's the theme's own
limit, not something the anchor choice can fix on its own. 90% gets
close to that ceiling (~3:1, more than double the old ~1.3:1) while
keeping a hint of the label/value visual distinction.
2026-08-29 10:43:38 +02:00
iris
cd339af91b agent.css: delete dead .overflow-btn/.overflow-menu/.overflow-item rules
`OverflowMenu.tsx`/`.css` were deleted (rebuild button removed outright,
dashboard link moved into `MetaNav`), but `agent.css` still carried the
whole trigger+popover+item rule set — grepped the entire `agent`
package, none of these classnames appear in any current markup.

Also fixed three tombstone comments elsewhere in the file that pointed
at the now-also-deleted `.overflow-item-*` classes as "where it moved
to" — they'd have dangled once those rules were gone too. And two stale
doc claims caught in the same sweep: `docs/web-ui/agent.md` still listed
`OverflowMenu.tsx` in the header's component tree and described "the
overflow menu" as a live effort-picker location.
2026-08-29 10:16:00 +02:00
iris
302778573d agent: HeaderPill wraps Badge instead of a hand-styled pill
Badge already covers icon+label+value+onClick -- exactly HeaderPill's
shape. mara, reviewing the first cut (a bespoke .header-pill matched to
Badge's own CSS values): "cant we reuse the badge component". HeaderPill
now renders <Badge> directly and only owns hiding at count 0 + the
inbox/todos tone (amber/green on the count, same as before). Drops the
now-unused .header-pill* CSS from agent.css entirely.
2026-08-29 10:12:19 +02:00
iris
ad58894c25 agent: fill the inbox/todos header pill to match the rest of the cluster
HeaderPill used the bordered/transparent .hive-pill shape while every
other chip in .agent-header-pills (StatusChips, MetaNav's trigger) is
@hive/shared's filled Badge (.ui-badge) -- the one visibly hollow pill
in a row of filled ones. Restyled .header-pill with .ui-badge's own
values (filled --purple-dim background, no border, matching radius/
padding/hover) instead of a new shape, and dropped hive-pill from the
markup since it no longer describes what this component looks like.
2026-08-29 10:12:19 +02:00
iris
3e4ffa9312 badge: mix accent color into --fg for a contrast floor on any theme
Badge.css's colored-value classes (positive/warning/negative/accent)
used the raw semantic accent color directly on --purple-dim, same class
of bug already fixed by hand for the bundled Latte palette (see
colors.css's comment on --latte-base08..0F) but never applied to an
arbitrary stylix-fed scheme. Blend each accent 60/40 with --fg via
color-mix() instead of using it bare -- --fg is the one color the
base16 contract already guarantees legible on every surface, so mixing
toward it gives every accent a contrast floor without trying to
compute/fix an operator's own theme.
2026-08-28 23:54:25 +02:00