'Mirrors the logic previously embedded in hive-ag3nt' is pure provenance
(where the code moved from) — the #2077 rubric says drop impl-history. The
rest of my slice (nix modules + hive-priv/matrix-mcp/bash-mcp + forge.rs) is
already lean: surveyed it, the long comment blocks are all legit why/invariant/
contract docs under the 30-line threshold, not bloat.
ensure_mirror_repo treated 409|422 as success (copied from ensure_org, where
422 *does* mean 'org exists'). For the migrate endpoint 422 is a validation
error (bad clone_addr/service); the GET-first check is the real idempotency
guard, so 409 stays as a race guard but 422 now falls through to the bail arm
(→ caller warns) instead of silently dropping a misconfigured mirror.
Per mara: the mirror seeding belongs in hive-c0re's forge provisioning
sweep, where the core admin token + org-ensure already live — not a parallel
host-side nix oneshot.
- forge.rs: ensure_mirrors() reads HYPERHIVE_FORGE_MIRRORS (JSON list of
{upstream,dest}), ensures each dest org (reuse ensure_org) + creates the
pull-mirror via the migrate API (reuse forge_http, serde_json::json! body,
409/existing = success). Called in ensure_all() right after the SEEDED_ORGS
loop (token in scope, warn-and-continue like the other ensure_* steps).
- hive-forge.nix: forward effectiveMirrors to c0re via
systemd.services.hive-c0re.environment.HYPERHIVE_FORGE_MIRRORS; drop the
forgejo-seed-mirrors.service + its script + the host-side core-token read.
Keep the forge.mirrors option, DEFAULT_ACTIONS_URL=self (CI-gated), and the
dest-shape / no-c0re-namespace-collision assertions.
Verified locally: nix parse + treefmt (incl rustfmt) clean; serde/serde_json
patterns mirror dashboard.rs. cargo build runs in CI (no cc in my container).
nixfmt wanted the ${...} on a single line (verified locally:
nix build .#checks.x86_64-linux.formatting passes). The earlier CI 'docs'
failure was a transient muede-pc2 build hiccup — the docs check builds clean
locally on the same drv.
- drop the three cross-ref tracker tags from comments/description (prose only)
- build the orgs + migrate JSON bodies with jq -n --arg (an upstream URL
containing a quote no longer corrupts the request)
- don't auto-append the actions/checkout mirror when the operator already
declared that dest (avoids a duplicate effectiveMirrors entry when CI is on)
General-purpose mirror mechanism for the internal forge, per mara's call on
#2074 (real Forgejo pull-mirrors, nix-configured — not a pushed clone).
- services.hyperhive.forge.mirrors: list of { upstream, dest } pull-mirrors,
any repo. Each is created as a real Forgejo pull-mirror (re-syncs from
upstream), dest = <owner>/<repo> in its own org.
- When forge.ci.enable is set: an actions/checkout mirror is auto-appended +
forgejo DEFAULT_ACTIONS_URL is pointed at this instance, so CI
'uses: actions/checkout@vN' resolves on loopback — immune to a host-resolver
blip that previously reded every checkout (the seed/re-sync needs external
DNS, but that's off the CI critical path).
- forgejo-seed-mirrors.service: host-side oneshot (the core admin token never
enters a container), modelled on hive-ci-prefetch — waits <=60s for the core
token, then idempotently ensures each dest org + creates the pull-mirror via
the migrate API. partOf the forge container so it re-ensures on restart.
- assertions: dest must be <owner>/<repo>; mirror orgs can't shadow the
c0re-managed namespaces (config/shared/agents/core) so the seed never races
hive-c0re's own provisioning.
Supersedes #2074 (the raw-clone stopgap) as the durable #2072 fix.
General-purpose Forgejo pull-mirror config (services.hyperhive.forge.mirrors:
list of {upstream, dest}). When CI is enabled, auto-append an actions/checkout
mirror + point forgejo DEFAULT_ACTIONS_URL at this instance so CI's
actions/checkout@vN resolves on loopback (immune to host-resolver blips, #2072).
Seed oneshot (creates the dest orgs + pull-mirrors via the migrate API) is the
next commit.
Remove or shorten comment blocks that:
- explain where code used to live (impl history)
- duplicate rationale already in docs/web-ui.md
- contain speculative/future-work notes
Changes:
- tabs.js: drop "SYST3M tab used to render this" history; keep badge purpose
- schedules.js: drop "used to be a card layout" history + speculative nit note
- stream-worker.js: replace 10-line problem-statement with docs pointer
(rationale already in docs/web-ui.md SSE multiplexing section); trim
future-work parenthetical from subscription-tracking comment
- system-sections.css: drop extraction-history prose; keep what it does
- core.css: drop move-history prose; keep what it imports and why
Part of issue cleanup per operator feedback.
New standalone page /builds.html consolidating rebuild queue, meta
inputs, and build log history into one place, with a new 'Builds' home
tile linking to it. Addresses mara's request: new sub-page with a new
home tile, all three items moved there.
Changes:
- builds.html: new page with three sub-tabs: R3BU1LD QU3U3, M3T4 1NPUTS,
BUILD L0GS. Same minimal-chrome header + createTabStrip pattern as core
and logs pages.
- builds.js: new bundle combining rebuild queue renderer (from core.js),
meta inputs renderer (from core.js), rebuild-live-log renderer (from
core.js), and build log history renderer (from logs.js). Deep-links to
/builds.html?id=N#buildlogs. Count pill id: builds-tab-count-rebuild.
BUILD L0GS tab lazy-loads on first activation.
- builds.css: @imports system-sections.css (rebuild queue + meta inputs +
live-log styles) and logs.css (build-logs-* component styles).
- build.mjs: register builds.js, builds.css, builds.html.
- core.html: remove R3BU1LD QU3U3 + M3T4 1NPUTS tabs (now on builds.html).
Default tab changes to K3PT ST4T3.
- core.js: remove renderMetaInputs, renderRebuildQueue + helpers,
renderRebuildLiveLog + live-log state, elapsed-time tickers,
updateRebuildCount, and the rebuild_queue/meta_inputs SSE handlers.
Remove openBuildLogStream + util imports no longer needed.
- core.css: remove .rebuild-live-log-* rules (moved to system-sections.css
so builds.css can share them via @import).
- system-sections.css: add .rebuild-live-log-* styles (moved from core.css);
update comment to mention builds.html.
- logs.html: remove BUILD tab + pane (moved to builds.html).
- logs.js: remove fetchBuild(), fmtTs, fmtDuration, openBuildLogStream
import, and rebuild_queue_changed SSE debounce. Default tab: 'agent'.
SSE stream retained for audit_entry_added live-appends.
- index.html: add Builds tile (🔨, rebuild queue · meta inputs · build
logs); update Core tile desc to 'kept state · container load'; update
Logs tile desc to remove 'build'.
The variable was misleadingly named `tombstones` and commented as
'any name here is a tombstone', but kept_state_names() returns ALL
agents with a state dir on disk — both live containers and soft-deleted
tombstones. The logic was always correct (union with the live roster
filters both), but the comment would mislead future readers.
Rename the variable to `kept` and update comments to accurately
describe the contents.
Add GET /api/permissions/stale endpoint that returns agent names with
explicit capability/tool-group JSON entries but no live container AND
no kept-state tombstone. Ghost detection is now entirely server-side —
one authoritative call, no client-side roster cache, no staleness window.
The previous client-side approach in core.js made three parallel API
calls (GET /api/capabilities, GET /api/tool-groups, GET /api/state) and
filtered the result against a module-level `liveContainerNames` Set
populated only on cold load and form submits. Any container lifecycle
event (spawn, destroy) while core.html was open left `liveContainerNames`
stale, risking a false-positive ghost entry for a live container.
Changes:
- permissions.rs: add `get_stale_permissions` handler + `StalePermsResponse`
struct. Computes live roster (containers_snapshot), tombstone set
(Coordinator::kept_state_names), explicit perm names (capabilities::read
+ tool_groups::read), then returns the difference sorted.
- dashboard.rs: register GET /api/permissions/stale.
- core.js: replace the three-call client-side logic in
`fetchAndRenderStalePerms` with a single fetch to /api/permissions/stale.
Remove `liveContainerNames` state + its syncFromSnapshot population.
Adds a "stale permission entries" sub-section within the K3PT ST4T3 pane
on /core.html showing agents with explicit capability/tool-group JSON
entries but no live container — typically renamed or manually-deleted agents
whose entries persisted (e.g. the old "root" manager name after rename to
"ruth").
Each ghost agent gets a "✕ clear perms" button that calls
DELETE /api/permissions/{agent} (added in the prior commit). Lazy-loaded
on first K3PT ST4T3 tab activation; auto-refreshes on capabilities_changed
and tool_groups_changed SSE events.
core.js: track liveContainerNames from /api/state.containers; add
renderStalePerms + fetchAndRenderStalePerms; hook tab onShow + SSE handlers.
system-sections.css: new .tombstones-stale-* selectors for the ghost list
rows and error message.
core.html: add #tombstones-stale-perms div inside the K3PT ST4T3 pane;
expand comment to describe both sub-sections.
Part of the #1802 hive-forge audit: the read verbs (view / issue / pr /
comments / comment-show / timeline / diff / pr-status / pr-reviews) look
overlapping but each has a distinct output shape. Add a selection table +
rule-of-thumb so agents pick the right one (esp. 'view first' to clear the
read-before-comment guard) instead of guessing. Zero blast radius — pure
docs, no verb changes (the audit concluded the CLI is structurally clean
and renames/removals aren't worth the caller breakage).
The field was originally backed by harness/hyperhive-model; after the
rework (fab6259d) it reads from state/hyperhive-harness.json. Update
the struct-level doc comment to match.
hive-c0re was reading harness/hyperhive-model directly to surface the
model badge on the dashboard. hyperhive-model is a runtime-override
file (not the resolved priority) and adds to the marker-file count.
Instead: mirror the fully-resolved model into hyperhive-harness.json
(the consolidated state file that already replaced hyperhive-rate-limited
/ hyperhive-needs-login). Written by hive-ag3nt on:
- Bus::new() startup (captures nix config > override > default)
- set_model() runtime change (MCP set-model call)
- emit_status() (keeps model current across rate-limit / auth flips)
hive-c0re reads active_model from hyperhive-harness.json, same dir +
same read path as rate_limited / needs_login. No new files.
Read the persisted model name from each agent's harness state file
(harness/hyperhive-model) and surface it as a small blue badge on
the container row in the SW4RM tab.
- container_view.rs: add `active_model: Option<String>` to
ContainerView; populated by new `read_active_model` helper that
reads harness/hyperhive-model; only set when container is running
(stale model info from a stopped agent is misleading)
- container_view.rs: add active_model to ContainerView literal in
host_stats test helper
- tabs.js: render badge-model chip after needs-update, before
reminders; add active_model to the row fingerprint so re-renders
fire on model change
- common.css: add .badge-model (blue, 80% opacity — informational)