diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index db0d078b..075401cd 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -209,10 +209,12 @@ Three sub-tabs: **R3BU1LD QU3U3** (default), **M3T4 1NPUTS**, **BUILD L0GS**. Its own esbuild bundle (`builds.js`); cold-loads `/api/state` and subscribes to `/api/dashboard/stream` for `rebuild_queue_changed`, `meta_inputs_changed`, `meta_update_running`. -The SW4RM tab (`/dashboard.html`) independently self-fetches the same -`GET /api/jobq/graph` endpoint for its own card badges + queue-summary -banner (`refreshJobqGraph`, `swarm.js`) — same data source, no panel -rendering, no shared fetch between the two pages. +The SW4RM tab (`/dashboard.html`) does **not** read this endpoint (or +any job-queue state) at all — mara, on review: "swarm.js should not +need to pull in the jobq to do its job." Its per-agent pending badges +are transient-only, and its queue-summary banner is removed for now +(see Container row, below), pending a dedicated rollup endpoint it +can read directly instead of the full graph. **R3BU1LD QU3U3** — pending, in-flight, and recently-settled container operations: rebuilds, meta-update cascades, and first-spawns. One @@ -913,14 +915,16 @@ fetch entirely. their own label directly via `TransientSet`/`TransientCleared` events carrying no backing node at all. - **Queued (not-yet-started) work shows nothing on the card.** An - earlier version of this page had a job-queue-backed fallback badge - for the `Pending` case (`queuedOpsByAgent()` in swarm.js, reading - `jobqNodesState`); removed per mara, on review of hyperhive#3028's - PR: *"swarm.js should not need to pull in the jobq to do its job"*, - followed by *"remove the per agent pending stuff - only show what - is running."* `jobqNodesState` still exists in swarm.js, but now - feeds only the queue-summary banner below, not per-card badges. + **Queued (not-yet-started) work shows nothing on the card, and + `swarm.js` reads no job-queue state at all.** An earlier version of + this page had a job-queue-backed fallback badge for the `Pending` + case (`queuedOpsByAgent()`, reading a `GET /api/jobq/graph` fetch); + removed per mara, on review of hyperhive#3028's PR: *"swarm.js + should not need to pull in the jobq to do its job,"* followed by + *"remove the per agent pending stuff - only show what is running."* + The queue-summary banner below was, for the same reason, also pulled + rather than kept on that same client-side graph-fetch — see its own + entry below for why. An **active model badge** (`model · `, blue) appears when the container is running and the harness has persisted a model name (`harness/hyperhive-model`). Read by hive-c0re's `ContainerView` @@ -961,19 +965,23 @@ per-agent actions and navigation links. Contents: agent is stale. Banner pulses on each broker SSE event (`pulseBanner` with a 4s grace timer). -**Build-queue summary banner** — when `jobqNodesState` has any -`Pending` / `Running`(-or-`Finishing`) **group roots** (`parent: -null` — each an independent queued/running operation, not a raw -node count: a multi-step op's not-yet-started sub-steps don't inflate -the number), a compact amber banner sits above the container list: -`◐ build queue — N running · M queued — view queue →` (the link goes -to the BU1LDS page's R3BU1LD QU3U3). A root's own `state` already -carries its subtree's roll-up (`hive-jobq-wire`'s contract), so this -is a direct filter over `jobqNodesState`, not a client-side rollup -derivation. It replaces the old per-transient spinner list; the -actual running node for each agent is already shown on its card -(transient + in-flight-queue badges), so the top of the tab only -needs the at-a-glance summary. +**Build-queue summary banner — currently removed, coming back on a +different data source.** Previously a compact amber banner above the +container list (`◐ build queue — N running · M queued — view +queue →`, linking to the BU1LDS page), derived client-side from `GET +/api/jobq/graph` (filter to `parent: null` group roots — each an +independent operation, not a raw node count — bucket by `state`). +Pulled per mara, on review of hyperhive#3028's PR: *"dont replace one +legacy thing with another. then we will have to either wait with +this pr or split it into what can and cannot be done now"* — a +client-side derivation over the generic graph was itself judged a +stopgap not worth landing, the same way the old `DagView` read it +replaced was. Comes back once a dedicated rollup endpoint (status × +count pairs, tracked separately) exists for `swarm.js` to read +directly instead of pulling the whole graph in for a summary. Until +then, the actual running work per agent is still visible on each +card via the transient pills; only the hive-wide at-a-glance count is +missing. ### Themed dialogs diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index 251652fe..843b8b42 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -458,7 +458,11 @@ hive-agent-menu { /* Build-queue summary banner on the SW4RM tab: one compact line when the rebuild queue has active work, with a link to the full queue on - the C0R3 page. Amber to match the in-progress / "rebuilding" card tint. */ + the C0R3 page. Amber to match the in-progress / "rebuilding" card tint. + Currently unused — swarm.js dropped the banner pending a dedicated + rollup endpoint (see swarm.js's transients-section comment) — kept + here rather than deleted-then-restored, since the markup/classes are + expected to come back unchanged once that endpoint exists. */ .queue-summary { display: flex; align-items: center; diff --git a/frontend/packages/dashboard/src/swarm.js b/frontend/packages/dashboard/src/swarm.js index 1d09b63c..c86a358c 100644 --- a/frontend/packages/dashboard/src/swarm.js +++ b/frontend/packages/dashboard/src/swarm.js @@ -1,7 +1,7 @@ // SW4RM (containers) domain — extracted from tabs.js. // Agent topology, container-row rendering, selection bar, peer-hives block, -// and all live-update apply handlers for container-state, rebuild-queue, and -// transient ops. See docs/web-ui.md::Container row for the rendering contract. +// and all live-update apply handlers for container-state and transient ops. +// See docs/web-ui.md::Container row for the rendering contract. import { $, form, fmtAgeSecs, @@ -27,21 +27,6 @@ const CTX_CAUTION_TOKENS = 100_000; // fallback yellow threshold (~= 50% of 200k // ─── module-level state ───────────────────────────────────────────────────── -// Flat GraphNode[] from GET /api/jobq/graph (hive-jobq-wire's generic -// shape — see hive-jobq-wire/src/lib.rs) — feeds *only* the queue-summary -// banner in renderContainers (mara, on review: "swarm.js should not need -// to pull in the jobq to do its job" — the per-agent pending-row fallback -// that used to be this state's other consumer is gone, see -// queuedOpsByAgent's removal below). Once a dedicated rollup endpoint -// exists (status-count pairs, requested separately) the banner moves -// onto that instead and this fetch goes away entirely. "Nothing is -// hidden" on this endpoint: every retained job group's nodes ride the -// wire, `Done` included, and each group's root is an ordinary node -// (`parent: null`) whose own `state` IS the group's roll-up already — -// unlike the old DagView, no client-side rollup derivation is needed, -// just an explicit filter for what's still active. -let jobqNodesState = []; - // Keyed container row cache. Maps agent name -> { el:
  • , fingerprint }. // Allows renderContainers to skip rebuilding rows whose displayed state // hasn't changed — prevents full-wipe flicker + avoids redundant async @@ -65,42 +50,20 @@ const transientsState = new Map(); // tab-gated visibility). const selectionState = new Set(); -// ─── job queue graph ────────────────────────────────────────────────────── - -// Fetches the graph fresh and re-renders. Called on cold load (see -// tabs.js's refreshState) and whenever `rebuild_queue_changed` fires -// (applyRebuildQueueChanged below) — that event is now read purely as a -// refetch trigger, the same treatment builds.js already gives it for -// .refresh(). Best-effort: a failed fetch just leaves -// the previous snapshot in place rather than wiping badges on a network -// blip (same tolerance the per-row dashboard-state fetch below has). -export async function refreshJobqGraph() { - let nodes; - try { - const r = await fetch('/api/jobq/graph'); - if (!r.ok) return; - nodes = await r.json(); - } catch { - return; - } - jobqNodesState = nodes; - renderContainersFromState(); -} -export function applyRebuildQueueChanged() { - // No `ev.queue` payload read anymore — that event still carries its - // own DagView-shaped queue snapshot on the wire, but this page no - // longer reads it. Purely a "something changed, go refetch" signal. - refreshJobqGraph(); -} -// Per-agent queued-but-not-running badges used to have their own -// fallback here (`queuedOpsByAgent()`, reading `Pending`-state nodes -// off `jobqNodesState`). Removed per mara, on review: "remove the per -// agent pending stuff - only show what is running" — a card's pending -// badges are now driven by `transientsState` alone (see below), which -// is exactly "what is running": queued-not-yet-started work shows -// nothing on the card until a node actually starts. - // ─── transients ───────────────────────────────────────────────────────────── +// +// This is now the ONLY job-queue-derived state on this page — mara, on +// review of the DagView migration: "swarm.js should not need to pull in +// the jobq to do its job." An earlier version of this file also fetched +// GET /api/jobq/graph directly for two things now gone: a per-agent +// queued-but-not-running badge (`queuedOpsByAgent()`, removed per "remove +// the per agent pending stuff - only show what is running" — a card's +// pending badges are transients-only now, which already means "what is +// running") and the queue-summary banner (removed per "dont replace one +// legacy thing with another" — a client-side derivation over the generic +// graph was itself judged a stopgap not worth shipping; the banner comes +// back once the dedicated rollup endpoint exists, and reads that +// directly instead of pulling the graph in here at all). export function syncTransientsFromSnapshot(s) { transientsState.clear(); @@ -620,37 +583,15 @@ export function renderContainers(s) { )); } - // Queue-summary banner: when the job queue has active work, show one - // compact at-a-glance line + a link to the full queue on the BU1LDS - // page. Replaces the old per-transient spinner list — the actual - // running step is already visible per-agent on each card (transient + - // in-flight-queue badges), so the top of the tab only needs the summary. - // - // Counts distinct *groups* (root nodes, `parent == null`), not raw - // nodes — a single group can have several sequential not-yet-started - // steps, and "3 running · 2 queued" means 3/2 whole operations, not - // 3/2 individual steps. A root's own `state` already IS its subtree's - // roll-up (hive-jobq-wire's contract — no client-side derivation - // needed, unlike the old DagView), so this is a direct filter, not a - // parent-chain walk. `Finishing` counts as running (own work done, - // children still going, still in flight). Settled roots (Done/Failed/ - // Cancelled/Skipped) ride the wire too now ("nothing is hidden" — - // unlike the old DagView snapshot, which dropped them) so both counts - // filter explicitly rather than assuming absence. - const roots = jobqNodesState.filter((n) => n.parent == null); - const running = roots.filter((n) => n.state === 'Running' || n.state === 'Finishing').length; - const queued = roots.filter((n) => n.state === 'Pending').length; - if (running || queued) { - const parts = []; - if (running) parts.push(`${running} running`); - if (queued) parts.push(`${queued} queued`); - root.append(el('div', { class: 'queue-summary' }, - el('span', { class: 'glyph spinner' }, '◐'), ' ', - el('strong', {}, 'build queue'), ' — ', - parts.join(' · '), ' ', - el('a', { class: 'queue-summary-link', href: '/builds.html' }, 'view queue →'), - )); - } + // No queue-summary banner for now — the previous version derived it + // client-side from GET /api/jobq/graph, which mara flagged as + // replacing one legacy DagView-shaped hack with another rather than + // landing the real fix ("dont replace one legacy thing with another + // ... split it into what can and cannot be done now"). Comes back once + // the dedicated rollup endpoint exists, reading that directly. Until + // then the queue's actual state is still visible per-agent on each + // card via the transient pills; only the hive-wide at-a-glance summary + // is missing. if (!containers.length && !transientsState.size) { root.append(el('p', { class: 'empty' }, 'no managed containers')); diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index 70e9560a..40dda34e 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -42,8 +42,8 @@ import { renderQuestions, activeQuestionCount, } from './call.js'; import { - refreshJobqGraph, syncTransientsFromSnapshot, - applyRebuildQueueChanged, applyContainerStateChanged, applyContainerRemoved, + syncTransientsFromSnapshot, + applyContainerStateChanged, applyContainerRemoved, applyTransientSet, applyTransientCleared, renderContainers, renderContainersFromState, renderSelectionBar, renderPeerHives, @@ -234,15 +234,6 @@ window.marked = marked; // `transientsState` + `containersState`, not from `s.*`). syncTransientsFromSnapshot(s); syncContainersFromSnapshot(s); - // Job-queue graph feeds only the SW4RM queue-summary banner now - // (per-agent card badges are transient-only — see swarm.js); its - // own detailed view lives on /builds.html. Self-fetches GET - // /api/jobq/graph — not read off `s` (this page's snapshot - // carries no jobq field) — fire-and-forget: renderContainers - // below runs off whatever jobqNodesState already holds, and - // refreshJobqGraph's own re-render catches up once the fetch - // resolves. - refreshJobqGraph(); renderContainers(s); // Sync the derived approvals + questions stores from the // snapshot, then render. Live `*_added` / `*_resolved` events @@ -313,10 +304,10 @@ window.marked = marked; container_removed: applyContainerRemoved, // tombstones_changed / meta_inputs_changed / meta_update_running are // handled on /core.html now (the SYST3M panels moved there). - // rebuild_queue_changed stays: it refreshes the SW4RM queue-summary - // banner (see swarm.js — the per-agent badges it fed too, before - // mara's "only show what is running" ask, are transient-only now). - rebuild_queue_changed: applyRebuildQueueChanged, + // rebuild_queue_changed: this page no longer subscribes to it at + // all (see swarm.js's transients-section comment) — the SW4RM tab + // has nothing left that reads it, unlike /builds.html which still + // does (its own separate subscription). schedules_changed: applySchedulesChanged, capabilities_changed: applyCapabilitiesChanged, tool_groups_changed: applyToolGroupsChanged, @@ -338,7 +329,7 @@ window.marked = marked; const es = openStream( '/api/dashboard/stream?kinds=sent,approval_added,approval_resolved,' + 'question_added,question_resolved,transient_set,transient_cleared,' + - 'container_state_changed,container_removed,rebuild_queue_changed,' + + 'container_state_changed,container_removed,' + 'schedules_changed,capabilities_changed,tool_groups_changed', ); es.onmessage = (e) => {