diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index 9691bf49..b87a4c08 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -26,6 +26,16 @@ swap. `state.matrix_gui_enabled` from `/api/state`. - **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`) — sits below the tab strip. +- **Browser tab title** — `hive / c0re` by default; updated to + ` / ` once `hive_name` / `swarm_name` arrive in the + state snapshot. When there are pending approvals or unanswered + questions, a `(N)` prefix is prepended — `(3) pr1ma / hive-c0re` + — so the operator can see the call count in an unfocused browser + tab without opening the dashboard. The prefix is set on the + initial `/api/state` cold-load and updated live by + `approval_added` / `approval_resolved` / `question_added` / + `question_resolved` SSE events; it's preserved when + `hive_name` / `swarm_name` later replace the raw title. The FL0W page reuses the same chrome strip but its `◆ S3TT1NGS ◆ →` entry is a cross-page link back to the dashboard diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index 5ef70fc0..22ab322b 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -3684,7 +3684,10 @@ window.marked = marked; : hive || swarm; hiveId.textContent = label; hiveId.hidden = false; - document.title = label + ' // h1ve-c0re'; + // Preserve any (N) call-count prefix already applied by + // refreshTabCounts so the title doesn't flicker on reload. + const existingPrefix = document.title.match(/^(\(\d+\) )/)?.[1] || ''; + document.title = existingPrefix + label + ' // h1ve-c0re'; } } const openDetails = snapshotOpenDetails(); @@ -4036,6 +4039,12 @@ window.marked = marked; (approvalsState?.pending?.length ?? 0) + (questionsState?.pending?.length ?? 0); setTabCount('call', callCount); + // Browser tab title prefix — lets the operator see the pending + // call count without switching to the window. Strips any existing + // `(N) ` prefix before re-applying so identity-title updates + // (which run once on state load, not every tick) compose cleanly. + const rawTitle = document.title.replace(/^\(\d+\) /, ''); + document.title = callCount > 0 ? `(${callCount}) ${rawTitle}` : rawTitle; // SYST3M — queued + running rebuild_queue entries (terminal // entries are kept for history but aren't 'attention'). let sysCount = 0;