#406 was the JS-split refactor: pull shared helpers into
common.js (step 1), pull the flow-only IIFEs into flow.js
(step 2), then rename the legacy combined entry from app.js
to tabs.js (step 3 — this commit) to reflect that the bundle
now owns the dashboard tabs surface only.
What moved:
- `frontend/packages/dashboard/src/app.js` → `tabs.js`
- `build.mjs` entry: `src('app.js')` → `src('tabs.js')`;
output is now `static/tabs.js`
- `index.html` `<script>` src: `/static/app.js` →
`/static/tabs.js`; the FL0W-section comment retouched
- `flow.html` reference from `/static/app.js`-as-tabs to
`/static/tabs.js`; notif + offscreen-inbox comments rewired
to point at the correct owners (common.js for NOTIF,
flow.js for renderInbox)
- `common.js`, `flow.js`, `tabs.js` headers: scrub stale
"app.js" references; document that #406 steps 2 + 3 are
done and both pages import directly from common.js
- `dashboard.css` comments: every "by app.js" → "by tabs.js"
- `docs/web-ui.md`, `docs/conventions.md`: legacy
`assets/app.js` → `assets/tabs.js` (the path prefix is
itself stale from a much-earlier rename, but consistent
with the rest of those docs)
- `CLAUDE.md` file map: refresh the dashboard package's
src/ and dist/ layouts to reflect the post-split shape
(tabs.js, flow.js, common.js, stream-worker.js)
What did NOT move:
- `frontend/packages/agent/src/app.js` (per-agent UI entry)
stays named `app.js` — it's a separate package, has only
one entry point, no split happened there
- The two "no-op when target absent" guards in renderContainers
and renderQuestions are kept as belt-and-suspenders for any
future page that adds tabs.js without the corresponding
sections; comments updated to note this rather than the
pre-split flow.html reason
Functional behaviour identical; this is a pure rename + comment
sweep.
Phase 4 of #273 — the actual switch. Both axum routers now serve
their static surface via `tower_http::services::ServeDir` mounted
as a fallback service, reading the dist path from `HIVE_STATIC_DIR`
(set by Phase 3's NixOS module wiring).
Deletes:
- `hive-c0re/assets/{index.html, app.js, dashboard.css}`
- `hive-ag3nt/assets/{index.html, app.js, agent.css, stats.html,
stats.js, screen.html}`
- The whole `hive-fr0nt/` crate (workspace member dropped, both
hive-c0re and hive-ag3nt drop their `hive-fr0nt.workspace = true`
dep). Its contents now live as `@hive/shared` under
`frontend/packages/shared/`.
Rust changes:
- `hive-c0re/src/dashboard.rs`: remove `serve_index`, `serve_css`,
`serve_app_js`, `serve_shared_js`, `serve_marked_js`,
`serve_favicon` (all six `include_str!` handlers); replace their
routes with a single `.fallback_service(ServeDir::new(static_dir))`
on the router. Fail closed (anyhow::bail) if `HIVE_STATIC_DIR` is
unset or not a directory at startup.
- `hive-ag3nt/src/web_ui.rs`: remove `serve_index`, `serve_css`,
`serve_app_js`, `serve_shared_js`, `serve_marked_js`,
`serve_stats`, `serve_stats_js`, `serve_screen`; same
`fallback_service` pattern. `serve_icon` stays (consumes
`/etc/hyperhive/icon.svg` + `branding/hyperhive.svg` fallback,
neither of which lives under the frontend dist).
- `AgentLink` URLs for stats/screen switched from `/stats` / `/screen`
to `/stats.html` / `/screen.html` since ServeDir doesn't auto-
append the extension and the on-disk filename is the natural URL
post-cutover.
- `Cargo.toml` (workspace): drop `hive-fr0nt` member + workspace
dep, add `tower-http = { version = "0.6", features = ["fs"] }`.
- `hive-c0re/Cargo.toml` + `hive-ag3nt/Cargo.toml`: drop the
`hive-fr0nt.workspace = true` dep, add `tower-http.workspace =
true`.
Docs updated:
- `CLAUDE.md`: file map reflects `frontend/` (was `hive-fr0nt/` +
`assets/`) and the ServeDir/HIVE_STATIC_DIR shape.
- `docs/web-ui.md` 'Shape (shared by both)' section: describes the
ServeDir fallback + bundled-by-esbuild surface, no more
`include_str!` references.
- `docs/terminal-rendering.md`: src paths point at
`frontend/packages/{agent,shared}/src/`; marked is the npm dep,
not vendored UMD.
Validation:
- `cargo check --workspace` — clean (5 warnings, all pre-existing
in `rebuild_queue.rs`, none on changed files).
- `cargo clippy --workspace --all-targets` — clean (11 warnings,
same pre-existing source).
- `cd frontend && npm run build` from the prior commit's lockfile
produces the dist directories the new routers consume:
dashboard: `dist/{index.html, static/{app.js, dashboard.css}}`
agent: `dist/{index.html, stats.html, screen.html,
static/{app.js, stats.js, agent.css}}`
(favicon.svg lands in dashboard/ during the nix build —
`nix/frontend.nix` install phase copies `branding/hyperhive.svg`
there, since it's outside the npm tree.)
Refs #273.
Removes weston-rdp.nix (hyperhive.westonRdp.enable) and adds
weston-vnc.nix (hyperhive.gui.enable).
The ExecStart wrapper script computes a deterministic VNC port via
FNV-1a hash of the agent name (derived from hostname, same algorithm
as lifecycle::agent_web_port) in the range [15900, 16799], then writes
/etc/hyperhive/gui.json {"vnc_port": N, "auth": "none"} for the
harness WebSocket relay (issue #51), and execs weston with the VNC
backend + pixman renderer.
Type=simple so it can never abort nixos-container update; a
misconfigured weston degrades to a restart loop, not a blocked rebuild.
Closes#50
on startup (and after every applied-repo ref mutation) core pushes
each agent's hive-c0re-owned applied repo — main plus every
proposal/approved/building/deployed/failed/denied tag — to
agent-configs/<name> on the local forge. the org is private and
agents are not members, so core is the only principal that can read
it.
the tokenised push url is passed inline, never stored as a named
remote: the applied repo is bind-mounted read-only into the manager,
so a token in .git/config would leak the core admin credential to an
agent.
push_config is best-effort at every site (ensure_all, spawn,
approve, deny, submit) — a missing or down forge never blocks a
deploy.
new DashboardEvent::ContainerStateChanged + ContainerRemoved
close the last refetch loop on the dashboard. Coordinator's
rescan_containers_and_emit diffs a fresh container_view::build_all
against a cached last_containers map and fires per-row events.
called from actions::approve (post-spawn), actions::destroy,
the lifecycle_action wrapper, auto_update::rebuild_agent, and
the existing 10s crash_watch poll.
ContainerView extracted to its own module so coordinator and
dashboard can both build it. dashboard endpoints flip to 200;
container-lifecycle forms carry data-no-refresh. client drops
the periodic poll entirely — initial cold load + SSE for
everything afterwards. pending overlay reads from the existing
transientsState since the new event payload doesn't carry it.
PURG3 + meta-update keep the post-submit refetch since
tombstones + meta_inputs aren't event-derived yet; tracked in
TODO.md.
claude.md scratchpad rewritten — folds in pronouns option,
extra MCP servers + flakeInputs forwarding, ask_operator
on sub-agents, dashboard compose box with @-mentions, new-
session button, cwd=/state for claude turns, meta-mutex +
stale-lock cleanup.
readme picks up the operator pronouns option example,
the dashboard compose box description, the new slash
commands list, the deployed-sha chip, the per-agent UI
gains new-session.
docs/web-ui.md gains:
- a fuller MESS4GE FL0W description that calls out the
compose box, sticky @-mention recipient, /op-send, and
the manager-name swap
- /op-send in the dashboard endpoint table
- new-session button + /new-session slash command in the
per-agent surface
- compact endpoint now notes 'same session shape as a normal
turn'
docs/turn-loop.md:
- new-session one-shot, cwd=/state with CLAUDE.md auto-load
walking upward, operator-pronouns substitution
- sub-agent tool list grows ask_operator
- new 'Extra MCP servers (per-agent)' section documenting
hyperhive.extraMcpServers + the flakeInputs forwarding
pattern
claude.md flips 'in flight' → 'just landed' for the meta
overhaul + extends the file map with meta.rs and migrate.rs.
docs/approvals.md replaces the in-flight callout with a
proper 'Meta flake' section (two-phase deploy walkthrough,
sync_agents semantics, single-phase variants), updates the
two-repo box diagram to include the /var/lib/hyperhive/meta/
tree and tracks flake.nix in applied, rewrites the
container --flake reference to meta#<name>, replaces the
'Manager view of applied' section with a unified
'/agents + /applied + /meta' inventory listing every useful
git incantation, and explains the in-place no-state-loss
migration that now runs on hive-c0re startup.
docs/persistence.md grows entries for the meta repo + the
.meta-migration-done marker. readme box diagram picks up the
/meta RO bind; approval-flow paragraph rewritten end to end
to describe the meta lock dance.
lifecycle::flake_base deleted — the meta render hardcodes
the manager vs agent-base choice as nix expression.