Commit graph hyperhive/docs
Author SHA1 Message Date
iris
fae2025247 docs(approvals): update helper-events routing to reflect shipped behavior
notify_manager (always-root) has been replaced by notify_submitter
(routes to the approval submitter, with root fallback for legacy rows).
Update three locations:

- Step 6 of end-to-end flow: "root agent's inbox" →
  "submitting agent's inbox"; explain notify_submitter + submitter column.
- InitConfig paragraph: remove limitation note; "to the root agent's inbox
  (current limitation...)" → "to the submitting agent's inbox via notify_submitter".
- Section header + prose: "Helper events to the root agent" →
  "Helper events to the submitting agent"; rewrite lead paragraph around
  notify_submitter semantics (approvals.submitter column, legacy fallback).
2026-06-23 22:45:43 +02:00
iris
60403fd27c docs(approvals): drop tracker-tag refs; add topology.rs pointer for role
Remove three bare #NNN tracker-tag references in docs/approvals.md
(hive-rules: no #NNN in code/comments/docs):

- Step 6 of end-to-end flow: "tracked in #1953" → "a known limitation
  under active development"
- InitConfig paragraph: same rewrite
- Helper events section: same rewrite

Also add a code pointer for `can_manage_top_level_agents`: the role is
defined as ROLE_CAN_MANAGE_TOP_LEVEL_AGENTS in hive-c0re/src/topology.rs,
now noted inline so reviewers can verify the name is real.
2026-06-23 22:45:43 +02:00
iris
136102cd27 docs(approvals): reframe stale 'the manager' as the root agent
The last docs/ piece of the manager-cleanup. The manager is no longer a
structural role — root-ness is purely topological. Reframe:
- title 'Approvals + manager + helper events' -> 'Approvals + helper events'
- section headers: 'Manager view of applied'/'Manager policy'/'Manager
  (ruth) is hive-c0re-managed'/'Helper events to the manager' ->
  root-agent / root-bootstrap-container equivalents
- body prose: 'the manager (ruth)' -> 'the root agent' (or 'the submitter'
  in the approval-flow steps)
- authority semantics: 'manager-only' -> approvals are submitted by an
  agent with the approvals tool group, for its direct children
- dropped the stale 'the manager refuses to destroy itself' line (the
  bootstrap container is now destroyable + transient; recreated on startup)

Kept the genuine code/protocol identifiers (nixosConfigurations.manager,
manager_server, role:manager prompt block, notify_manager, the
/run/hyperhive/manager/ socket path) — renaming those would diverge from
the source (de-hardcoding is its own backend cleanup).
2026-06-23 22:45:43 +02:00
atlas
d340c1773a fix: ci-log durable persisted-log fallback for pruned runs
ci-log drove only the live run-view streamer (POST .../runs/<n>/jobs/<j>
with logCursors), which reads the live act_runner task record. Forgejo
prunes that record once a run completes, so the streamer 500s with
'task ... resource does not exist' on quick or older runs even though
the web UI still shows the logs — the reader (argus, atlas) then had to
ask the operator to relay the error.

Add a fallback: when the streamer errors or returns no lines, download
the persisted whole-job log via the same web route the run page's view-
raw-logs link uses, .../runs/<n>/jobs/<job>/attempt/<a>/logs, keyed by
the per-repo run number with the attempt segment. It survives the task
prune. Live and recent runs keep the rich per-step streamed view; only
the pruned case takes the flat fallback (where --step can't apply). New
--attempt flag (default 1) selects the run attempt for re-runs.

Verified against a real pruned run whose streamer 500'd: the fallback
prints the full persisted log; a completed short job ends cleanly at
'Job succeeded', confirming the route returns complete logs.
2026-06-23 22:45:05 +02:00
damocles
3d2e0ef561 feat(#1906): non-root weston gui on a fixed vnc port 2026-06-23 22:41:20 +02:00
atlas
5caec9c1a9 fix(forge): config-repo main is fast-forward-only (no auto force-push)
Per operator directive: a silent automatic force-push is a bug. The
config-repo merge path already never force-pushes (run_merge_config_pr
lands via ff_push_to_main, a non-force git push). So set the branch
protection's enable_force_push to false — main only ever advances by
fast-forward.

The legacy push_config mirror does force-push (it re-points the status
tags and rewinds main on a failed-build rollback); the protection now
rejects those non-ff updates, so the mirror runs best-effort until the
agent-opened PR-merge flow retires it. Docs + comments updated to match.
2026-06-23 22:37:27 +02:00
atlas
558552ec54 docs(forge): s/mirror/config repo/ in dashboard anchor bullet for consistency
Address iris review nit on #1948: the bullet above now reframes the
agent-configs entry as a config repo, so the dashboard-anchor bullet
should match. Pure wording, no behavior change.
2026-06-23 22:37:27 +02:00
atlas
2fe79aaef5 feat(#1787): make agent-configs/<n> the agent-editable, PR-merge config surface
Wires the per-agent config repo as the editable PR surface the #1838
merge handler (run_merge_config_pr) consumes, without yet retiring the
push_config force-mirror (that waits for #1838 P2 — the agent-opens-PR
MCP surface — so config changes keep working through the transition).

ensure_config_repo now, after creating agent-configs/<name>:
- adds the agent as a WRITE collaborator (can push config-change branches
  + open PRs);
- branch-protects main core-only via apply_config_repo_branch_protection:
  push + merge whitelists are core-only (only hive-c0re lands on main, via
  its verify-and-ff-push handler), operator-team approval required, the
  agent can't push main directly or self-merge.

The protection sets enable_force_push=true as a TRANSITIONAL allowance so
push_config's applied->main force-mirror keeps working until P2 retires it
(a protected branch otherwise rejects force-push). Forgejo's force-push
allowlist is deploy-keys-only — no per-user list — so this is a plain
enable_force_push toggle; only core is in the push-whitelist so only core
can force-push anyway. At P2, flip it to false and keep core in the
push-whitelist so ff_push_to_main still lands.

Agent code repos (AGENTS_ORG) are intentionally untouched — their merge
flow has no auto-merge handler yet, so switching them to core-only-merge
would strand those PRs.

All steps idempotent (runs on every spawn + startup sweep). Updated the
CONFIG_ORG doc comment + docs/forge.md to drop the "mirror-only" framing.
2026-06-23 22:37:27 +02:00
iris
e5da5b900e docs: fix remaining bare /kill/ and /rebuild/ paths → /api/ variants
coordinator.md: GracefulStop entry referenced the old bare /kill/<agent>
path with the lax graceful=1 bool — update to /api/kill/<agent>?graceful=true.

approvals.md: the auto-update badge description referenced /rebuild/<name>
(bare, no /api/ prefix) — update to /api/rebuild/<name>.
2026-06-23 22:05:05 +02:00
iris
4634094502 docs(web-ui/dashboard): fix stale /kill/ bare paths → /api/kill/ + graceful=true
The graceful-stop description at the ■ ST0P confirm-dialog paragraph
referenced `/kill/<name>?graceful=1` and `/kill/<name>` (bare, no /api/
prefix; lax bool `1` instead of `true`).

The backend has registered these under /api/ since the /api/-prefix
migration, and the frontend was updated to send `graceful=true` (not `1`)
in commit f2f1a0b3 (fix: send graceful=true not =1 for the kill query param).
Align the docs with shipped code.
2026-06-23 22:05:05 +02:00
iris
e18ddff0b0 docs(approvals): reframe stale 'the manager' as the root agent
The last docs/ piece of the manager-cleanup. The manager is no longer a
structural role — root-ness is purely topological. Reframe:
- title 'Approvals + manager + helper events' -> 'Approvals + helper events'
- section headers: 'Manager view of applied'/'Manager policy'/'Manager
  (ruth) is hive-c0re-managed'/'Helper events to the manager' ->
  root-agent / root-bootstrap-container equivalents
- body prose: 'the manager (ruth)' -> 'the root agent' (or 'the submitter'
  in the approval-flow steps)
- authority semantics: 'manager-only' -> approvals are submitted by an
  agent with the approvals tool group, for its direct children
- dropped the stale 'the manager refuses to destroy itself' line (the
  bootstrap container is now destroyable + transient; recreated on startup)

Kept the genuine code/protocol identifiers (nixosConfigurations.manager,
manager_server, role:manager prompt block, notify_manager, the
/run/hyperhive/manager/ socket path) — renaming those would diverge from
the source (de-hardcoding is its own backend cleanup).
2026-06-23 21:06:30 +02:00
atlas
11fb2ac0fc hive-forge: add 'reopen' verb (pr reopen / issue reopen)
hive-forge had close but no reopen, so reopening required the non-obvious
workaround 'issue edit <n> --state open'. Add a reopen verb mirroring close
(PATCH state=open), wired into both 'pr reopen' (kind-checked PR) and
'issue reopen' (kind-checked issue). Updates docs/forge.md + the subcommand
enumerations.
2026-06-23 18:35:19 +02:00
iris
efb34ef677 fix(dashboard): drop stale manager destroy-hiding comment + vestigial block
Follow-up to the destroy-guard removal — the bootstrap/root container is
now destroyable end-to-end. The frontend already offered DESTR0Y/PURG3
for every container; the only manager-gating left was a stale doc-comment
('destroy/purge hidden for the manager') and a vestigial bare block
wrapping the menu appends. Drop both (no behaviour change), and update the
dashboard.md menu doc: 'disabled for the bootstrap container' -> available
for any container (hive-c0re recreates it on next startup if destroyed).
2026-06-23 18:33:45 +02:00
damocles
00f682991c refactor(#1896): remove dead forge_notify reason plumbing + fix docs 2026-06-23 17:23:06 +02:00
atlas
c9c59c2a1d hive-forge: ci-rerun dispatches a fresh run via workflow-dispatch API
The previous implementation POSTed Forgejo's run-page rerun web route,
which is CSRF-gated and answers a bare token POST with 404 — so the verb
never actually re-ran anything against the agent token.

Rework it to dispatch a fresh run of the workflow via the
GitHub-compatible workflow-dispatch API
(POST /repos/<o>/<r>/actions/workflows/<workflow>/dispatches {"ref":<branch>}),
which accepts a plain agent token (verified end-to-end on Forgejo 15.0.3).
A dispatched run is equivalent to the old empty-commit retrigger, minus
the commit.

The branch is resolved from exactly one of --pr (the PR head branch),
--run (branch + workflow looked up from that run in the Actions runs
list), or --branch (directly); --workflow picks the workflow file for
--pr/--branch (default ci.yml). Dispatch re-runs the whole workflow, so
the old --job single-job variant is dropped.

Also add workflow_dispatch to .forgejo/workflows/ci.yml for explicitness
(Forgejo 15.0.3 dispatches the pull_request workflow without it, but the
trigger makes the API path intent-clear and cross-version robust), remove
the now-unused Client::post_web_no_content, and update docs/tools/forge.md.
2026-06-23 14:53:11 +02:00
atlas
cd4bdf4eea feat(#1778): add hive-forge ci-rerun to re-run CI without an empty commit
When a CI run fails for a transient reason (remote-builder flap, cold-daemon
window, act_runner hiccup) the only retrigger path was an empty commit, which
litters PR history and forces a force-push to clean up. This verb POSTs the
rerun action directly.

- `ci-rerun --run <n>` re-runs all jobs of a run (run number = the `runs/<n>`
  the UI shows, same value ci-log / artifact-get take, surfaced as a CI
  context's target_url by pr-status).
- `--pr <n>` resolves the run from the PR head sha's CI status target_url.
- `--job <i>` re-runs a single job.

Forgejo exposes no REST endpoint for rerunning a run, so this rides the run
page's web routes (`<base>/<owner>/<repo>/actions/runs/<n>[/jobs/<i>]/rerun`)
via a new `Client::post_web_no_content` (web base like post_json_web, tolerates
the redirect/empty response the rerun handler returns). Mirrors ci-log's
web-route approach + auth path.

docs/tools/forge.md updated with the verb.
2026-06-23 14:53:11 +02:00
iris
20e26ad28d docs(persistence): correct the root-container destroy claim (imperative, not declarative)
The 'non-destroyable (declarative; would fight with host NixOS config)'
claim was stale: the root/bootstrap container is imperative
infrastructure, managed end-to-end by hive-c0re (auto_update::
ensure_root_agent recreates it on startup if absent). The actions::
destroy bail is a soft policy guard, and destroying the container is
transient anyway — it's recreated on the next hive-c0re startup.
2026-06-23 14:48:10 +02:00
iris
80c33f5108 docs(security): drop redundant bootstrap-container allowlist entry
The hive-priv container allowlist's explicit MANAGER_NAME allow is
redundant — the bootstrap container's name passes the generic
agent-name char validation anyway. Describe the allowlist as just the
agent-name convention + the sibling service containers.
2026-06-23 14:48:10 +02:00
iris
7e0190e27c docs: address mara review on #1936
- Drop the redundant 'including the root/bootstrap container' /
  'sub-agents + root' enumerations in the port-range + state-dir
  uniformity statements — 'every agent' / 'all agents' is enough (and
  calling out '+ root' reintroduces the special-case framing).
- Stop describing the root agent's privileged (manager-flavour) socket
  as a current thing (it's being removed): drop the conventions.md
  capability clause, the network.md per-agent-privileged-socket list
  entry, and the persistence.md /run/hyperhive/manager/mcp.sock
  runtime-dir bullet.
2026-06-23 14:48:10 +02:00
iris
c24ca4dfe1 docs(dashboard): reframe stale 'the manager' as the root/submitting agent
Schedule columns, tool-group/capability defaults, terminal addressing
(@root), destroy/move guards, and approval-resolution notes now refer to
the root agent (or the submitting agent, for approval flows) rather than
'the manager'. Also fixed the stale 'moving the manager' move-refusal
example (the root agent is reparentable) to a cycle example.
2026-06-23 14:48:10 +02:00
iris
ec5c7d49c4 docs: reframe stale 'the manager' as the root/bootstrap container (infra + web-ui)
Port-range, network-isolation, state-dir, web-UI-port, priv allowlist,
and rebuild-source mentions now refer to the root/bootstrap container
rather than 'the manager' — no structural manager exists (root-ness is
topological). Real artifact names (the manager.nix template toplevel,
/run/hyperhive/manager/mcp.sock) are left as-is.
2026-06-23 14:48:10 +02:00
iris
adb76f3cdf docs(persistence): reframe stale 'the manager' as the root agent
Config-repo editor, meta RO-mount, non-destroyable container, and the
topology.json example now refer to the root agent / bootstrap container
rather than 'the manager'. The /run/hyperhive/manager/mcp.sock path is a
real runtime path, kept (clarified as the root agent's manager-flavour
socket).
2026-06-23 14:48:10 +02:00
iris
d6debd4762 docs(conventions): reframe stale 'the manager' as the root/bootstrap agent
The manager is no longer a structural role — root-ness is purely
topological (an agent with no parent). Reframe the naming + socket
lines that presented 'the manager' as a fixed coordinating agent,
while keeping the manager-flavour socket/protocol identifiers (those
still name live code).
2026-06-23 14:48:10 +02:00
damocles
ef958983e0 docs(#1838): document the merge-config-pr approval kind + queue dispatch 2026-06-23 13:12:12 +02:00
iris
9634327b59 docs(web-ui): document the 'all' stats window
Follow-up to the stats 'all' time-range feature: the agent and hive
stats endpoint docs enumerated the window options but predated 'all'.
Add it to the /api/stats and /api/stats-hive window lists, and note
that 'all' ranges from the earliest recorded turn with an adaptive
bucket width.
2026-06-23 00:21:11 +02:00
lexis
d4dd5aad3e docs(tools/forge): document read-before-comment guard + --force flag 2026-06-22 23:33:13 +02:00
lexis
73a58776fa docs(turn-loop): document graceful stop recv behavior (follow-up to #1920) 2026-06-22 23:27:33 +02:00
atlas
d4f106d590 hive-gateway: route dashboard by path, not Accept header
The dashboard vhost split static-vs-backend on the request Accept
header (map $http_accept $dashboard_spa_target), so the same URL
behaved differently by content-type — e.g. /api/state fetched with
Accept: text/html wrongly returned index.html.

Now that all hive-c0re routes live under /api/ plus the single
/webhook/knowledge endpoint, route by path instead: /api/ and
/webhook/ proxy to c0re (SSE settings on /api/), everything else
serves the dist with try_files $uri /index.html. Drops the
dashboard Accept-header map and the @c0re named location.

Updates docs/gateway.md accordingly.
2026-06-22 23:08:23 +02:00
atlas
2b4e928afe feat(#1867): make the internal forge mandatory (remove forge.enable)
The internal forge is the canonical store for the meta flake, every
agent's config repo, and the internal/* repos, so it can no longer be
optional. Remove the services.hyperhive.forge.enable toggle:

- hive-forge.nix: drop the `enable` option; the forge config now
  deploys gated on `services.hyperhive.enable` (it ships with hyperhive).
- hive-c0re.nix: HIVE_FORGE_URL env unconditional; forge-public-URL gate
  drops the enable check (keeps behindGateway).
- hive-gateway.nix: local /etc/hosts forge entry keyed on behindGateway.
- hive-ci.nix: drop the now-moot `forge.ci.enable requires forge.enable`
  assertion (forge is always present); reword the option doc.
- nix/docs/default.nix: drop the `forge.enable = mkForce false` stub
  (option gone); the options-doc eval stays light via hyperhive.enable.
- hive-c0re forge.rs / hivectl.rs: reword 'forge.enable = true' error
  text to 'wait for hive-c0re to start the container' (the runtime
  token-absent path is unchanged — it's a bootstrap-timing check, not
  the opt-out).
- docs/approvals.md, docs/ci.md: drop stale forge.enable references.

Migration: configs that set `services.hyperhive.forge.enable = false`
must drop the line — the forge is now mandatory.

Prereq/companion to #1838 (PR-based config flow, which assumes the forge
is always present).
2026-06-22 19:26:34 +02:00
iris
c091d8a4b5 docs(web-ui): align dashboard endpoint list with the /api FE routes
The 'Dashboard endpoints' list was half-migrated: newer routes were
documented under /api/* but the older ones (approve, deny, the
rebuild/kill/restart/start/destroy lifecycle group, purge-tombstone,
answer-question, cancel-question, request-spawn, update-all, op-send)
were still listed bare. The dashboard FE calls all of them under /api/
since the route migration, so the doc was stale. Prefix the bare entries
(plus the two inline references) to match what the FE actually requests.
Documentation-only; no behaviour change.
2026-06-22 19:09:53 +02:00
atlas
8ea19b3b12 feat(#1897): always auto-fill the hive domain — drop the --domain override
Per operator review (#1899): the hive's own domain should never be
typed by hand. Remove the --domain flag from peer-config and wg init
entirely; both now resolve it from the daemon (HostRequest::HiveDomain).
peer-config errors with a clear hint if the daemon can't answer; wg init
prints the peer block best-effort (skips it, still enables the mesh, if
unresolved). Regenerated docs/tools/hivectl-cli.md.
2026-06-22 19:07:56 +02:00
atlas
72d9422a7a feat(#1897): auto-fill the hive domain in peer-config (drop required --domain)
Per operator review: hivectl shouldn't make the operator retype this
hive's own domain. Add a HostRequest::HiveDomain admin-socket query
(c0re answers from HYPERHIVE_HIVE_DOMAIN, already in its service env) and
a domain field on HostResponse.

hivectl peer-config now resolves the domain as: --domain override (kept
for offline/scripted use), else the daemon query; errors with a clear
hint when neither resolves. wg init resolves it best-effort too, so it
prints the hand-over peer-config block without --domain (skipped, not
failed, when the daemon is unreachable).

Regenerated docs/tools/hivectl-cli.md.
2026-06-22 19:07:56 +02:00
atlas
8464cb95cb feat(#1897): hivectl peer-config verb to generate a federation peer block
Add `hivectl peer-config --domain <this-hive-domain>`: prints the
`services.hyperhive.swarm.peers."<domain>"` nix block a peer operator
pastes to federate with this hive. Emits `caCert = ./<hive>-ca.pem` plus
a `cp /var/lib/hive-tls/ca.pem ./<hive>-ca.pem` line when this hive
serves a self-signed CA (the cert file exists); omits caCert for
ACME/public-CA hives (trusted by the default bundle). Includes the
WireGuard public key when the mesh key exists, and the
wireguardAddress/Endpoint passed via flags.

`wg init` gains an optional --domain; when set it calls peer-config at
the end, so a fresh mesh setup prints the hand-over block in one command.

Pure output — reads local state (TLS CA cert presence, wg key), never
mutates. Regenerated docs/tools/hivectl-cli.md.

Closes #1897.
2026-06-22 19:07:56 +02:00
atlas
edad6f863c feat(#1886): trust a peer hive's root CA hive-wide for self-signed federation
Add swarm.peers.<domain>.caCert (path to a peer hive's root CA PEM),
trusted everywhere the hive's own internal CA is — so a self-signed
peer hive can federate (matrix) and any in-hive consumer validates its
certs.

Mechanism (reuses the existing hive-CA embedding): the meta-flake
renderer embeds a LIST of CA files next to each agent's flake —
hive-ca.pem (the hive's own self-signed CA, when active) plus each peer
caCert as peer-ca-<N>.pem — and emits them all in
security.pki.certificateFiles, so every agent trusts them at build
time. The matrix container trusts the same peer CAs for federation TLS.
Nothing is installed in the host trust store; the certs live in the nix
store (no mutable host file).

- meta.rs: embedded_ca_files() = hive CA + peer CAs (from new
  HIVE_PEER_CA_PATHS env); ca_embed_state() tracks the list (content +
  add/remove); sync_agents materialises + stages the list; render emits
  the multi-entry certificateFiles. Tests cover hive-only / hive+peers
  / peers-only / none.
- hive-c0re.nix: HIVE_PEER_CA_PATHS service env (colon-joined caCerts);
  caCert / certFingerprint option docs updated to the hive-wide scope.
- hive-matrix.nix + docs/swarm.md: scope + comment updates.

certFingerprint stays the c0re-only leaf-pin path.
2026-06-22 16:54:44 +02:00
damocles
f5ac6d79e3 forge_notify: leave delivered threads unread, dedupe wakes in-memory 2026-06-22 16:23:04 +02:00
iris
4342a50895 docs(web-ui): refresh matrix-accounts page for heartbeat + age-dimming + problem+json
The M4TR1X ACC0UNTS section described the pre-heartbeat state: a
snapshot 'written at startup / rewritten each daemon (re)start' with an
'ambiguous' as_of, and the live-status dot as a 'dashboard-side
follow-up'. All three shipped since:

- the daemon now force-rewrites the snapshot every ~30s (heartbeat), so
  as_of advances while alive and a stalled value is an honest dead-daemon
  signal — documented, with the full dot state table (green / dim-green
  'no heartbeat' age case / amber container-down + offline / grey);
- the login endpoint moved to /api/matrix-account-login and its failure
  body is RFC 9457 application/problem+json (message in detail), not the
  old 4xx { error } — corrected, with the 400/500 status scheme.
2026-06-22 16:07:54 +02:00
atlas
dc4c5460d5 feat(#1877): restructure hive-forge into pr/issue sub-verbs
Group issue/PR operations under `pr` and `issue` parent commands
(`hive-forge pr close 42`, `issue create …`, `pr status --pr 42`) per the
operator decision — kind-namespaced verbs replace the flat surface.

- new `verbs::pr_cmd` / `verbs::issue_cmd` parent commands wrap the existing
  per-verb modules (reuse their Args + run fns) under `#[command(subcommand)]`.
- kind-validation (the win over the old generic verbs): the generics that work
  on both (view/comment/comments/close/labels/assign/timeline) call
  `assert_kind` first, so `pr close <issue>` / `issue close <pr>` are rejected
  with a 'use the other command' message. PR-only / issue-only verbs are
  kind-correct by construction. `number` exposed `pub(crate)` on the shared
  verbs so the wrappers can probe it.
- every flat kind verb (`close`, `pr-create`, `pr-status`, `issue-edit`, …)
  kept as a `#[command(hide = true)]` back-compat alias — still parses, dropped
  from --help; removed in a later sweep once usage migrates. (`pr`/`issue`
  bare-show become `pr show` / `issue show` — the names are now parents.)
- docs/tools/forge.md documents the new surface + the deprecated aliases.

cargo build/clippy/fmt clean, 54 tests pass; --help surface + alias parsing
smoke-tested.
2026-06-22 16:01:13 +02:00
damocles
f38bc13293 matrix-accounts dashboard: live status + homeserver from daemon snapshot (be-4) 2026-06-22 13:02:43 +02:00
damocles
ad6b39b425 remove vestigial agent-ports.json tcp web-port map 2026-06-22 11:59:14 +02:00
iris
93fa264bbf dashboard: stream the running rebuild's build log inline in the queue
The C0R3 rebuild queue only linked out to the logs page (logs →). Add an
inline live-log panel under the queue that streams the currently-running
rebuild's build output, so the operator watches progress without leaving the
page.

One panel keyed to the running entry's build_log_id (the queue runs one build
at a time), reusing the build-log SSE the logs page already uses
(GET /api/build-logs/id/{id}/stream; frames stdout_append/stderr_append/done).
It lives in its own container (#rebuild-live-log) outside rebuild-queue-section
so the queue's per-row re-render — rows rebuild as the build step advances —
never tears down the open stream; it reconnects only when the running
build_log_id changes and won't reopen a stream that already sent done. Sticky-
bottom scroll, collapsible, live/ok/fail badge, raw download. Hidden when
nothing is building; each row keeps its logs → link for full history.

Frontend-only — no backend change (endpoint + build_log_id already existed).
Closes #1860.
2026-06-22 01:48:32 +02:00
atlas
4db8a8cd3d feat(#1843): static-serve the dashboard via the gateway, hive-c0re API-only
nginx proxied `<hive>/` straight to hive-c0re:7000, and hive-c0re served the
dashboard dist itself via `tower_http::ServeDir` (from `HIVE_STATIC_DIR` baked
into its service env). So a frontend-only change rebuilt the hive-c0re unit and
restarted the core daemon — every operator session dropped its SSE stream for a
pure CSS/JS change.

The gateway nginx now static-serves the dashboard dist directly; hive-c0re's
dashboard router is API-only. The split uses the Accept-header SPA fallback (the
same `map $http_accept` pattern the matrix/agent vhosts already use), so no
backend prefix has to be enumerated: a browser navigation (Accept: text/html)
whose path is not an on-disk asset gets the SPA index.html; everything else
(every /api route, the bare action/mutation routes, the two SSE streams, the
knowledge webhook — all Accept != text/html) falls through `try_files` to the
`@c0re` named location and is reverse-proxied to hive-c0re. A new c0re route
needs no gateway change.

- hive-c0re.nix: expose the themed dist as a new internal read-only option
  `services.hyperhive.c0re.servedFrontend`; drop `HIVE_STATIC_DIR` from the
  service env (the router no longer serves files).
- hive-gateway.nix: read that option in host-module scope (dashboardDist),
  static-serve `dashboard/` with the Accept-header `try_files ... @c0re` split;
  `@c0re` carries `proxy_buffering off` + a 1d read timeout for the SSE streams
  and a duplicated auth_basic block (named locations do not inherit it). The
  dashboard map is unconditional; the matrix map stays gated on the matrix GUI.
- dashboard.rs: drop the ServeDir fallback + the HIVE_STATIC_DIR resolution; the
  router 404s unmatched paths (the gateway only proxies non-static requests).
- hive-c0re/Cargo.toml: drop the now-unused tower-http dependency.
- docs/gateway.md: document the dashboard static split + the `@c0re` fall-through.

The store path is reachable inside the gateway nspawn container (shared
/nix/store), mirroring how HIVE_AGENT_FRONTEND_DIR already exposes the per-agent
UIs. The gateway and c0re changes must land together (atomic cutover) or the
dashboard 404s — this needs a watched gateway + c0re rebuild.
2026-06-22 01:18:01 +02:00
damocles
d3e3c4a41e docs: agent-hierarchy default-parent is root, not the manager 2026-06-22 00:41:42 +02:00
iris
1c47bd4333 agent-ui: real fixed-width icon column for terminal rows
Replaces the first-character-glyph + negative-text-indent trick (which let a
wide emoji or a leading disclosure caret knock the icon out of column) with a
genuine icon cell.

terminal.js: row() / details() / detailsDiff() take an optional `icon` that
goes in a fixed-width `.row-glyph` element (inline-block, 1.4em). Details
summaries wrap their text in a `.summary-text` span; the disclosure caret
moves to `.summary-text::before` so it leads the text, not the icon — keeping
the icon in the shared column. terminal.css carries the cell + caret rules.

app.js passes the per-tool emoji as `icon` for the flat tool-use row and every
expandable tool summary (Write/Edit/send/ask/answer/bash) plus the 💭 thinking
row, instead of string-prefixing it. A details `🖥️` now lines up under a flat
row's `🧠` regardless of emoji width. Doc: terminal-rendering.md layout
contract updated. Closes #1844.
2026-06-22 00:41:24 +02:00
iris
954bf8fe38 docs(web-ui): deny dialog uses themedPrompt textarea, not window.prompt
The deny-reason dialog moved from window.prompt() to a themed resizable
textarea (Enter submits, Shift+Enter newline). Update the dashboard route
reference that still described the old single-line window.prompt() flow.

Closes #1849.
2026-06-22 00:33:59 +02:00
damocles
513c828ab2 hive-c0re: default new agents to root instead of under the bootstrap container 2026-06-22 00:19:35 +02:00
damocles
0df52806f9 hive-c0re: drop the dead manager exclusion from the agent web-port map 2026-06-21 23:24:09 +02:00
iris
fb58f0e5b9 agent-ui: per-tool emoji icons + thinking/turn-end glyphs in terminal
Following the 🧠 thinking-tokens indicator (operator liked it), give terminal
rows evocative glyphs:
- 💭 thinking prose (pairs with the 🧠 token counter)
- / turn-end ok/fail (was ✓/✗)
- per-tool icons via toolIcon(name): 📤 send · 📥 recv ·  ask · ✍️ answer
  ·  remind · 🏷️ set_status · 🪢 loose-ends · ↻/⏹️/▶️/🔄 lifecycle · 📦
  request_* · ⏱️ schedule · 🖥️ bash · 💬 matrix · 📖 Read · 💾 Write · ✏️
  Edit · 🔍 Glob/Grep · 🔧 default — on both flat rows and the rich
  send/ask/answer/Write/Edit summaries.

Dropped the original 🐝 task-row glyphs: claude's nested-agent Task tool is
intentionally omitted from agents' allow-list (mcp.rs), so those rows never
render for agents. Doc table updated.

Closes the emojify-terminal request.
2026-06-21 23:15:25 +02:00
damocles
b3d002e4a7 hive-c0re: let request_init_config spawn a brand-new sub-agent under its requester 2026-06-21 22:36:35 +02:00
iris
63a79d76ba agent-ui: collapse streamed thinking_tokens ticks into one live row
claude streams a running 'estimated_tokens' counter as system/thinking_tokens
events — many per turn (thousands in a long turn). renderStream rendered each
as a '⚙ thinking_tokens' note, flooding the terminal scrollback. Coalesce
consecutive ticks into a single '🧠 thinking … ~N tokens' note row that
updates in place; reuse the row only while it's still the last one rendered
(nextElementSibling == null) so any other event starts a fresh one. Closes
#1818.
2026-06-21 22:09:31 +02:00
iris
6bb976ec72 dashboard: replace agent-tab transient list with build-queue summary banner
The SW4RM tab rendered a per-transient spinner list above the container
list, duplicating the running-step badge already shown on each agent card.
Replace it with a single compact amber banner that appears when the rebuild
queue has active (queued/running) entries — 'build queue — N running / M
queued — view queue →', linking to the full queue on /core.html. Per-agent
detail stays on the cards; the top of the tab just gives the at-a-glance
summary + a jump to the queue. Closes #1817.
2026-06-21 22:07:14 +02:00