The spoke dashboard is the operator UI served from
src/pkg/dashboard/static/index.html. For the behavior behind the labels the repository cards show or mutate, see Hive Labels and Control Signals. Its FAQ panel (#faq-section /
#faq-panel) is intentionally static HTML: it is not ACMM-gated, does not
fetch data, and is visible to confused L1/L2 users before they understand the
rest of the UI. Its only script is a client-side filter box (faqFilter) that
hides non-matching questions.
The FAQ is a summary surface for the current v5 hive. Each question is a
collapsible <details class="faq-q"> with a <summary>, grouped under
getting started (L1/L2), the L3-L6 trust ladder (including hold labels and
shadow mode), evidence/releases/upgrades, runs/inception/Experiment Lab,
contributors/relays/models, issue claims/attribution/audit log,
cost/cadence/pausing, and where to get help. Each answer links back to the
relevant src/docs/*.md source of truth rather than becoming a second spec,
and a footer points to Discord, the in-dashboard feedback form and the issue
tracker when an answer is missing. pkg/dashboard/faq_ui_test.go guards the
structure: section ids, one <summary> per question, at least one link per
answer, the filter input, and no inline style= inside the panel (styling is
the token-based .faq-* class set).
Contributor cards use a client-side “album cover” tint: the dashboard samples each GitHub avatar in a tiny canvas, ignores low-saturation/near-black/near-white pixels, picks dominant and secondary accent colours, and applies them only as subtle background, border, avatar-ring, and role-pill washes. When avatar sampling fails, a deterministic hue derived from the login keeps the card distinct; results are cached in browser storage for seven days.
When the FAQ names a dotted config key inside <code>...</code>, keep it in
sync with the Go config schema. pkg/dashboard has a guard test that extracts
those keys from the FAQ panel and asserts each path exists in config.Config
via YAML tags.
Every dashboard section title has a small ? mark. Hovering or focusing it shows a one-sentence summary; clicking it (or pressing Enter) opens that section's entry in Dashboard sections explained, the plain-language help page for operators. The help sentences live in one table in index.html (DASHBOARD_SECTION_HELP), and dashboardDocsHref is the single place that builds every help address: a hive built from the v6 branch or a v6.x.y tag opens the v6 page, anything else opens v5. A guard test fails when a section has no help entry or its sentence drifts from the page.
Settings fields use the same ? mark, rendered by settingHelpMark(page, anchor, label, tip): hovering or focusing it shows the setting's tooltip, and clicking it opens the guide that explains the setting, or the tab's entry in Dashboard settings explained, through the same dashboardDocsHref. Clicking the mark never changes the setting.
Dashboard UI changes should follow the shared dashboard design system, dashboard glossary and sidebar IA, and ADR-0018. The token layer is the theme contract for future user theme/background work and the migration path away from static inline styles; go test ./pkg/dashboard/... -run StyleRatchet -v ratchets inline styles and raw CSS values so the debt only goes down.
Top-level dashboard sections use the shared section-card shell for their header, border, collapse state, badges, and collapsed summaries. Notices that must stay above the reorderable dashboard — release channel/upgrade status, install/configuration warnings, and the planning intro — live in the pinned #dashboard-notices anchor before Overview so browser-local section reordering cannot move them down the page.
On the v5 line the standalone Platform section is not part of the default dashboard layout; on the v6 line Platform is a top-level section. On v5 its forge, mint-token-service, and skills facts now appear in Diagnostics → Platform, keeping the information available without consuming a top-level card. Diagnostics also includes Quality stats, a data-driven card rendered from the quality agent's configured Stats entries rather than a fixed set of deployment-specific workflow checks. The topbar health dropdown is limited to real spoke health checks from deepHealth, so repository workflow stats do not appear there.
The light dashboard topbar keeps high-signal operational state only: project name, fleet controls, health, auth, and a compact ACMM autonomy chip such as L5 · Semi-Autonomous. The chip is display-only and navigates to the ACMM Eval section; changing levels remains in the existing ACMM dialog/sidebar controls.
Build/version details live in the bottom-left sidebar chip. The collapsed chip shows the short SHA, release channel, and an orange ↑ marker only when an upgrade is available. Open the chip for the full commit link, channel/tracking state, compare/release-notes links, last upgrade status when reported, copy-version, and the manual upgrade action. On small screens the sidebar is reachable through the hamburger drawer, so the version menu remains available without returning the long version strip to the topbar.
The account/avatar menu's Export → ⬇ Widget row downloads GET /api/widget
with the same dashboard authentication as the rest of the API. The compact
payload mirrors the headline dashboard readouts: agent names and
running/paused/busy/next-kick state, governor mode, ACMM level, actionable
issue/open PR counts, 7-day PR throughput (opened/merged/closed), spoke version
and upgrade availability, and the fleet breaker state.
The main dashboard layout is browser-local and display-only. Use the ⠿ grip in each top-level section header to drag a section, or focus the grip and press Space, Up/Down, then Space/Enter to drop; Escape cancels the keyboard move. The working order is auto-saved in localStorage as hive.dashboard.layout; ACMM-hidden sections keep their slots, feature-disabled sections are excluded, and the sidebar follows the saved order. Section collapse state, hidden sections, and repository card display tweaks are captured with saved layout presets; sidebar jumps temporarily peek collapsed sections open and restore them on the next different jump unless the operator manually keeps the section open. Open the GitHub avatar menu's Layout section to save the current working layout as a named preset (default My layout), apply/rename/delete up to five saved layouts, export/import a JSON layout, or Reset layout to default. Reset asks for confirmation, clears the working layout on this device, and offers a short undo toast. The avatar shows a small dot whenever the working layout differs from the last applied preset or default.
A browser that has never stored any dashboard state (a new hive, or a first visit from a fresh profile) starts with the non-critical cards collapsed so a new operator first sees the cards that say whether the hive is alive and merging: Overview, Governor, Projects, Review, Approvals, Agents and Agent activity open expanded; Throughput, Tokens, Cost, Advisory, Knowledge, Contributors, Inception, ACMM Eval, Diagnostics, Audit Log, Agent Logs, Experiment Lab and FAQ start collapsed with their one-line summaries visible. The set is the DASHBOARD_DEFAULT_COLLAPSED_SECTIONS constant in the dashboard page. A browser that already holds dashboard state when it first loads this version is marked legacy in localStorage (hive.dashboard.collapseDefaults) and keeps the historical all-expanded default, including after Reset layout to default. An operator's explicit choice always wins: expanding a default-collapsed card stores hive-section-collapsed-<id>=0, collapsing any card stores 1, and saved presets, JSON export/import and reset round-trip those values. The avatar menu's Layout section also offers Expand all sections and Collapse all sections.
To hide a dashboard section, hover or focus its left-menu row and press the small eye-off control. The row remains in the sidebar in a muted state, while the matching dashboard card is removed from the main layout. The same control changes to Unhide
hive.dashboard.hiddenSections; Overview cannot be hidden.
The Experiment Lab (dashboard.experiment_lab) is hidden by default while
that surface is being reworked. Set dashboard.experiment_lab: true to show
the Experiment Lab dashboard section, its sidebar navigation item, and its
Nous status controls. The pre-rename key dashboard.strategy_lab is still
honoured as a deprecated alias for one release: it enables the panel, logs a
one-line deprecation at config load, and is folded into
dashboard.experiment_lab so the next config save writes the documented key.
The dashboard Governor card summarizes queue depth, operating mode, budget
posture, and cadence controls for the hive. Its collapsible PRs by model nested
sub-section reads GET /api/governor/pr-models with the selected 7d, 30d,
or all window. The nested header keeps the window/sort toggles visible and its
collapsed summary shows the current top-ranked model plus model count.
The Governor actionable issues and actionable PRs tiles use the shared server-side actionable partition described in Repository card legend, issue bands, and PR bands. Their subtitles show the per-kind reconciliation from total open work to the actionable split, and those two results always add back to the Overview Actionable now total.
Governor settings Features → Auto-Merge includes the owner-only
Trusted-author auto-merge block. It edits
auto_merge.trusted_authors.{enabled,repos,require_role,require_github_permission,exclude_labels}
through /api/config/auto-merge, with a watched-repo multi-select (no
selection means all watched repositories), role selector, GitHub permission
switch, and excluded-label list.
The cadence table starts each agent row with the same 1/0 Agent power
rocker used in the agent settings panel, so owners can enable or disable an
agent from the table; disabled rows are dimmed, and read-only viewers see the
current state without an active control. Per-mode cells are read-only operator
overview cells; continuous modes render as an ∞ continuous chip, and clicking
a mode cell opens the agent settings dialog to the Cadences form where the
operator chooses Off, Interval, or Continuous.
Rows keep the merged/open/closed PR-volume bar, then add compact effectiveness
columns from the same aggregation used by the contributor Operations Most
effective models panel: merged PRs, first-pass merge rate, verified-PR run
rate, failure rate, and completed-without-PR ("nothing to ship") rate. Models
that meet HIVE_CONTRIBUTE_EFFECTIVE_MODELS_MIN_PRS (default 5) merged PRs
get rank badges. On /contribute, Operations-style column headers in Most
effective models, Rankings, and Fleet controls tier limits are keyboard-clickable
sort controls; the selected column and direction are saved in browser
localStorage, and a third click restores each card's default live order. The
default row order is effectiveness rank; operators can toggle back to raw PR
count without changing the selected window.
The Throughput panel is a top-level dashboard section with its own sidebar entry, listed under Overview and Governor; its subtitle uses the small muted dashboard subtitle style. For a plain-language summary see Throughput.
The Throughput section (pr-throughput-section) summarizes
pull/merge requests and issues across tracked forges. It reads
GET /api/pr-throughput for selectable windows and repository filters, keeps
the historical /api/pr-throughput path and pr-throughput-* element IDs for
compatibility, and reports opened, observed merged, and observed
closed-without-merging terminal states.
Actor attribution splits created, reviewed, and merged/closed activity into precise buckets:
hive: changes merged or closed by this hive. This includes audited sweep/queue/relay/governor paths (agent_pr_created,agent_issue_created,agent_pr_reviewed, agent issue comments/claims, relay/sweep merges and issue closes) and forge-observed PR terminal events whosemerged_byactor matches this hive's configured identity or GitHub App bot login when no audit path exists.human: any non-bot GitHub login, including maintainers who merge throughgh pr merge --admin --squashor the GitHub UI.other: non-hive bot accounts only, such as Dependabot, Renovate, GitHub Actions, Copilot coding agents, and other*[bot]logins.unknown: terminal observations with no recorded actor/path. Unknown counts are kept in the actor matrix as unrecorded evidence but are excluded from the trend share math so missing attribution is never mislabeled as automation.
Issue data comes from the existing issue-request and claim-poller audit stream: agent-created issues, agent comments/claims as triage/review signals, and agent issue-close events. Historical human issue creation/review/closure is not backfilled; the actor matrix and trend chart start accumulating as new audited or observed events arrive.
The Hive vs human tile and expanded trend use the same selected actor role as the dropdown. The large percent is hive-attributed events divided by hive + human + other-automation events in the selected window, excluding unknown actors. For Merged, the share covers PR merges plus issue closes; for Closed, it covers PRs closed without merging plus issue closes. The previous percent compares against the immediately preceding window of the same length (for example, previous 24 hours for the 24h window).
The Knowledge card has a 🔌 Integrations button that opens an in-app modal for Obsidian setup plus every registered knowledge.connectors type. The Knowledge tab of the governor config dialog also has a Connectors section listing every knowledge.connectors entry: name, type, layer, a status pill (ok, syncing, error, disabled, or pending before the first sync), last sync, pages/facts, and the last error (truncated, full text on hover). Owners also get Sync now, Edit, Disable/Enable and Remove per row plus Add connector; everyone else sees a read-only table. Add/Edit uses the styled hive dialog with type-specific scope fields and a Validate button; credentials are referenced by environment variable name or secret file path only. Saves go through the owner-only PUT /api/config/knowledge/connectors. See Knowledge connectors.
Project Inception is branded as powered by Spektacular with a linked header pill and body note. Knowledge Base collapsed summaries show the total fact count (the same source as the sidebar badge); layer health stays inside the body with a short explanation that layers are knowledge-source scopes for facts.
The Audit Log viewport defaults to a taller resizable panel. Browser-local height changes are persisted in localStorage under hive.audit.panel.height; the entry cap/search controls remain in the card header area above the scrollable table. The collapsed sensitive badge is actionable: it opens the card, applies the visible Sensitive only filter for the same 24-hour window as the badge count, and jumps to the first sensitive row.
The floating 🐝 Hive Chat panel is a command-first dashboard assistant. Type
/help (or help) to render the command registry; the same registry drives
one-line help, /help <command> details, examples, and slash-command
autocomplete and argument hints. Current commands are /help, /clear,
/search, /history, /retry, /edit, /who, /agents, /beads,
/prs, /governor, /knowledge, /jam, and /spek.
The prompt behaves like a small terminal: Enter sends, Shift+Enter inserts a
newline, Tab completes slash commands, Up/Down cycle prior commands while
preserving the draft, ? opens the shortcut overlay, Esc closes the overlay
or panel, and Cmd/Ctrl+K opens and focuses it. A collapsible left cheat sheet
groups clickable examples for agents, beads/issues/PRs, governor, knowledge,
jam, and Spektacular. Spek/Spektacular examples are enabled when /api/version
reports v6/edge; otherwise they are marked v6/edge.
Chat UI state is browser-local: transcript, command history, panel size,
maximized/docked mode, cheat-sheet collapsed state, command draft, preferences,
and shortcuts live in localStorage with bounded history sizes. /clear clears
the transcript; /history clear or the cheat-sheet control clears command
history. /history <text> searches command history and /search <text>
searches the transcript. /retry resends the last prompt, /edit restores it
to the draft, suggestion chips seed common prompts, and long/code-heavy output
is collapsible with copy buttons on fenced code blocks. There is no server-side
per-user chat persistence yet because dashboard user settings are not a
general-purpose cross-browser preferences API.
Markdown is rendered from escaped input only: bold, inline code, code fences,
links, GitHub-style @mentions, and #issue / owner/repo#N references are
decorated after escaping. Repeated or long Status heartbeat output is folded
to avoid burying the conversation.
/who reads GET /api/presence. Authenticated users see display-safe
usernames/display names, GitHub avatars for plain GitHub handles, and active vs.
idle state derived from the existing focus-aware presence heartbeat. A local
dashboard with no authenticated identity does not reveal other sessions and
shows only local.
Repository cards show held issues and PRs beside the actionable pills. A user
who owns the hive, owns the repository, or has GitHub write, maintain, or
admin permission on that repository can click the ⏸ Hold chip to add a hold
or the ▶ Release chip to remove one. The server always re-checks that
permission before mutating labels. Adding
a hold applies the hive's canonical hive-pause/<hive-id> label. The name
deliberately avoids the substring hold so it is matched exactly. Removing a
hold only removes the label(s) that are actually causing the hold
(hive-pause/<hive-id> and/or the generic hold labels such as hold,
on-hold, or hold/review). The hive-specific canonical hold is
hive-pause/<hive-id>; the former hive/<hive-id> provenance label is retired
(#12539) and the boot sweep removes it from open items. On upgrade, Hive writes
/data/hive-hold-migration-<hive-id>.json: audit-backed dashboard holds are
copied to the new label, agent-provenance-only items become actionable, and
ambiguous legacy labels stay held under hive-pause/<hive-id> for operator
review. The card-level ⏸ pause / ▶ resume control uses the same permission
rule.
The collapsible Overview section above Projects summarizes the same
client-side issue and PR bands across the selected repository view. Its SVG
charts reuse the repository-card classifiers for actionable plus held
issues/PRs, so their totals match the visible band counters and respect the
Overview settings repo filter without a separate API call. A compact KPI strip
renders the partition as an equation: Total open issues + Total open PRs =
Actionable now + Held + Blocked/needs-human + Outside. This is the same
partition used by the Governor actionable issue/PR subtitles. Total open
issues and Total open PRs are forge totals for the selected configured
repositories from the existing scanner tick: open GitHub issues exclude pull
requests, while open GitHub pull requests include drafts. Their subtitles show
the per-kind terms without repeating the headline total. Actionable now is
the shared server-side count used by the Overview KPI and the Governor collapsed
split: open enumerated issues plus open enumerated PRs after hold/exempt
filters, excluding items in the waiting, done, draft, or blocked Overview
bands. The following tiles expose issue/PR splits such as 13 = 5 issues + 8 PRs, and the operator glyphs between cards make the full strip read like
41 TOTAL OPEN ISSUES + 17 TOTAL OPEN PRS = 13 ACTIONABLE NOW + 13 HELD + 10 BLOCKED / NEEDS-HUMAN + 22 OUTSIDE. The outside tile is server-side and is
broken down in /api/status as actionableNow.outside.breakdown[], with each
row naming the count, rule, current setting, and how to change it for this
hive. The rows cover hard-suppress labels (needs-direction,
needs-decision, needs-spec; needs-human is counted under
blocked/needs-human), exempt labels from governor.labels.exempt plus permanent
exempt labels, reporter-trust triage from
project.issue_filter.reporter_trust, require-label filtering from
project.issue_filter.require_labels, standing hive advisory/meta issues,
bot Dependency Dashboard issues, draft PRs, exempt PR labels, and
hold-adjacent/other remainder rows. See Outside buckets
for the bucket-by-bucket rules and labels-and-control-signals.md
for the label semantics behind hold, exempt, and hard-suppress signals. Its
actionableNow.issues and actionableNow.prs splits always sum to
actionableNow.total. Operators can
view each Issues or PRs panel as a donut,
pie, horizontal bar, single 100% stacked bar, line/spark trend, or age
histogram. Every shape is still driven by the same band slices and
server-provided classifications. Hovering a chart element, an Overview legend
row, or a repository-card band header shows its rule from the Go band specs
carried in /api/status as overview_bands. Each actionable/held issue and PR
carries band, signals, stale, and held; the browser does not classify
labels or timestamps again. Full SSE updates carry the same fields.
The Overview and Governor outside ⓘ tooltip uses this server-side table. The
Settings → Labels panel repeats it as Triage buckets: what counts as outside
and exposes the editable rows.
| Bucket | Definition | Rule/config source | How to change |
|---|---|---|---|
needs-direction |
Issue is waiting for maintainer direction before agents may work it. | Labels in project.issue_filter.hard_suppress_labels.needs_direction; default needs-direction. |
Settings → Labels → Triage buckets, or edit hive.yaml. |
needs-decision |
Issue is waiting for a maintainer decision. | Labels in project.issue_filter.hard_suppress_labels.needs_decision; default needs-decision. |
Settings → Labels → Triage buckets, or edit hive.yaml. |
needs-spec |
Issue needs specification or acceptance criteria. | Labels in project.issue_filter.hard_suppress_labels.needs_spec; default needs-spec. |
Settings → Labels → Triage buckets, or edit hive.yaml. |
| Exempt labels | Issue or PR carries a deny-list label and is never agent work. | governor.labels.exempt plus permanent labels such as do-not-merge. |
Settings → Labels → Exempt labels, or edit hive.yaml. |
| Reporter triage | Reporter trust is enabled and the issue author is not trusted yet. | project.issue_filter.reporter_trust trusted associations/logins and untrusted required labels. |
Settings → Labels → Reporter trust. |
| Project issue filter | Issue lacks every required allow-list label. | project.issue_filter.require_labels. |
Settings → Labels → Required labels. |
| Standing meta/advisory | Hive's own advisory report or issue labelled hive/advisory; it is coordination state, not work. |
Fixed scanner rule: advisory title/label. | Rename/close the advisory, or remove the advisory label if it should become work. |
| Dependency dashboard | Bot dependency dashboard control panel, not a concrete task. | Fixed scanner rule: Renovate/Dependabot-style bot author plus Dependency/Renovate Dashboard title. | File concrete child issues or close/rename the dashboard issue. |
| Draft PRs | Pull request is open but marked draft. | GitHub draft state. | Use GitHub's Ready for review action. |
| Hold-adjacent/other | Safety remainder for open items that did not match a named actionable, held, blocked, or outside classifier. | Fixed scanner fallback. | Check labels and scanner rules; add a dedicated classifier if the remainder is meaningful. |
The Issues and PRs panels link directly to /api/overview/issues.csv and
/api/overview/prs.csv by default, or to the matching .json endpoints when
JSON export is selected; non-empty legend rows add a band query filter and
repo-filtered views add one or more repo query filters.
Exports use the current cached snapshot and the same Go classifier as the
page, so a download reflects the latest server state even between page updates.
Automation can use the corresponding .json endpoints and optional band,
repo, stale, and held filters. Cookie sessions work directly; token-authenticated
pages include their API token in the download link's query string.
The Overview header's ⚙️ popover stores browser-local chart preferences under
hive-overview-charts: which chart types are in rotation, whether the carousel
is enabled, the 5-second to 5-minute interval, transition style, duration, donut
label mode, KPI visibility, export format, and the bounded
client-side line/spark history. The repo multi-select is stored separately under
hive.overview.repos, with All/None shortcuts and an Org shortcut when the
hive spans multiple GitHub organizations. The default remains donut-only with
the carousel off, a 30-second interval, fade transition, normal duration, KPI
strip on, CSV exports, and all repos selected.
Manual arrows and dot indicators are available even when timed rotation is off;
timed rotation pauses while the panel is hovered or the tab is hidden, and
reduced-motion users get instant swaps.
The Projects section uses a consistent card header grid: reorder grip, truncated repository name, status badges, labelled auto-merge switch, spacer, and actions. It also includes a compact, collapsible pill legend. It is
stored per browser in localStorage and uses the same pill classes as the cards,
so theme changes update the legend automatically. The legend lists the issue
and PR bands (rendered from the shared band table, each with its rule as a
tooltip), issue held pills, plan chips, hold/release controls, issue state
glyphs (⛔, ❓, 👤, ✓, role badges, stale 🕒) and PR states (✓,
◐, ⚠, held ⏸, failing CI ✗ CI, conflicts ⑂, stale 🕒,
reviewed 💬, auto-merge 🔀, agent role badges, review-class badges
such as FIX, and the red sentinel pill). A PR that carries the configured
sentinel alert label (sentinel.label, default sentinel-alert, matched
case-insensitively) is drawn red on its card, status chip and main pill, whether
it is listed as held or open; red wins over the held, needs-human and merge
colours, and the row keeps its other chips. The sentinel flagged it for a
possible security override, privilege escalation or codebase damage, and Hive
will not merge it until a maintainer reviews it and removes the label. Trusted
authors normally get a sentinel comment rather than the label, so their PRs are
usually not red. The label name reaches the page through /api/role
(sentinel_label, every role); until it is known no row is drawn red. Repository cards also show a labelled auto-merge switch: it is effectively off below L6, switching the hive to L6 turns it on for every active repo, and owners may toggle individual repos afterward.
Actionable issue pills are grouped client-side for display only; enumeration, holds, filters, ranking, and agent kick behaviour are unchanged. Bands are named after the action the operator should take (or an explicit "nothing needed"), not after how the dashboard classified the issue. Each issue appears in exactly one band, while non-winning states remain as badges on the pill:
- Unclaimed (
unclaimed) — no other band matched: nobody is assigned, nothing claimed it, and no human gate applies. This does not by itself mean agents will pick it up. - Claimed (
claimed) — a claim is a comment; thestage/020-claimed/stage/030-pr-in-progresslabel is a mirror Hive keeps in sync (the retiredclaimedandhive/in-progressspellings are still recognised for the migration cycle). The display band also recognises assignees andhive/claimed-by-*. - Needs triage (
triage) — anagent/<role>label and no human has acknowledged the proposal under #5117: noapproved-directionlabel and no human assignee (the snapshot'shuman_acknowledged; a human comment only satisfies the PR-time gate and is not in the payload). Acknowledge it, or close it. Once acknowledged the issue falls through to Unclaimed/Claimed with the role badge still on the pill. - Needs human (
needs human) — labels such asblocked,needs-decision,2-discussing,Epic,needs-human, orneeds-triage. Note that theneeds-triagelabel lands here, not in the Needs triage band. - Confirm & close (
close?) — labels such ashive/already-done,stage/040-covered-by-pr(and any later mirrored PR stage; formerly🐝 covered by PR/hive/covered-by-pr), andhive/likely-done: an agent believes the work landed; verify and close.
Precedence is confirm & close → needs human → claimed → needs triage → unclaimed,
so a human gate beats an assignment and done beats all other display states.
Within each band, issues sort by updated_at oldest first. The issue breakdown
also shows N no activity > 14d for actionable issues older than the stale
threshold.
Operators can tune only the display taxonomy under dashboard.issue_bands:
dashboard:
issue_bands:
waiting_labels: [blocked, needs-decision, 2-discussing, Epic, needs-human, needs-triage]
done_labels: [hive/already-done, stage/040-covered-by-pr, "🐝 covered by PR", hive/covered-by-pr, hive/likely-done]
stale_days: 14These settings deliberately do not reuse governor.labels.exempt,
contribute_skip_labels, or project.issue_filter; those decide work
eligibility, while issue bands decide how the dashboard describes already
enumerated work. Linked-PR badges render from the linked_prs payload and are not inferred by the card.
PR pills are also grouped client-side for display only. Open and held PRs appear in exactly one band; held PRs are no longer appended after the actionable list. First match wins for classification:
- Needs human —
needs-human, held,needs-decision,2-discussing, or configureddashboard.issue_bands.waiting_labels. - Merge-eligible — merge verdict
eligible, or queued for Hive auto-merge. - Blocked — merge verdict
blocked, conflicts (mergeable: no), or failing CI with failing check names. - In review — merge verdict
outstanding, a recorded Hive review link, or a GitHub review decision (see below). - Draft — draft PRs.
- Open — everything else.
The display order is needs human → merge-eligible → blocked → in review →
open → draft. Within a band, PRs sort by oldest updated_at, then review class
(fix, refactor/docs or unknown, tests), oldest created_at, and PR number.
The PR snapshot includes updated_at specifically so this order can match issue
band aging without extra GitHub API calls. The existing
dashboard.issue_bands.waiting_labels and stale_days settings are reused for
PR display; changing them does not alter enumeration, holds, review, or merge
queueing.
Repository issue pills show a 🔗 badge when Hive has verified a pull request related to that issue. Open PRs apply stage/040-covered-by-pr (the retired 🐝 covered by PR); merged PRs on still-open issues apply hive/likely-done. The badge's tooltip grades the claim: "closes via PR #N" (the PR carries a closing keyword, or Hive linked it from the branch name), "covered by PR #N (partial)" (the PR says Refs #N / Part of #N and merging it will not close the issue), or "merged via PR #N". These are pending signals, not resolution: the issue remains in the actionable list until GitHub closes it, GitHub reports the PR in closingIssuesReferences, or an operator confirms coverage.
The badge is derived from Hive's own PR-claim evidence — the same source that applies the label — not from GitHub's closing-link data, so it is present for every covered issue whether the claim is closing or partial, and whether the issue is actionable or suppressed into the card's "covered by PR" group (#12144). One badge renders per issue; when several PRs cover it the closing PR is primary, the count is appended (🔗×2), and the tooltip lists the rest. The status payload exposes the evidence as linked_prs: [{number, state, merged, url, closing, reference}] plus claim_context on each actionable github.Issue and on each claimed_by_pr entry in nonActionableIssues.
The Review section opens with a separately collapsible Pipeline tile that shows every open PR as a card in the column for its review stage, from GET /api/review/pipeline: unreviewed, reviewing, changes requested, fixing, human hold, approved (merged and abandoned columns stay empty until the API returns those PRs). Each card shows the PR link, an agent or contributor marker, time in stage, reviewer chips, P0–P3 finding counts, the fix-loop counter (red once it is within one of the cap) and the next-action link. Filter by repo, author kind or stage; column headers carry counts. A ⚡ marker on the card means a webhook push or review request triggered the review of the current head (trigger: event), ⏳ that one is queued; see Event-driven dispatch. The board refreshes every 30 seconds and keeps its scroll position. The sibling Queue tile is separately collapsible too, ranking the same open PRs in Hive’s suggested review order from GET /api/review/queue without hiding the Pipeline tile. A PR in the supersession sweep’s grace window is tagged superseded there, with a link to the merged PR and the time the sweep will close it; owners get Close now and Keep open (adds hive/keep-open, which the sweep never auto-closes). Each queue row reflects the PR's stage from the stage-label store (labels-and-control-signals.md): the stage/stalled label's tooltip reads "no activity for Xh — nobody is working this PR", a red waiting on hive Xh pill marks a PR past its stage dwell while the hive itself holds it (checks running or reviewer verdict pending — the reviewer lane, not the author, needs attention), and an N hops, M back pill carries the stage transition history (stage.history[]) in its tooltip, replacing the retired stage/regressed label.
The Hive activity monitor section (sidebar, Dashboard group; expanded by default) is the "where is my pizza" view of the hive: one entry per open issue and PR from GET /api/stage-tracker, each a title line over a thin tracker strip. Issues and PRs share one set of columns — Open → Actionable → Claimed → PR in progress → CI / Review → Merge gate → ✓ — with the step names printed once in a column header. Covering PRs nest under their issue: an issue with no PR yet draws the whole strip like any other row (its lit step is Open/Actionable/Claimed with the steps ahead faint); once exactly one PR covers it the issue and PR collapse into a single entry: the issue's #N title on the left, [author icon] #PR title in the PR in progress column of the same title line, and one continuous strip beneath — Open/Actionable/Claimed passed, then the PR's stage drives the lit chevron through CI / Review → Merge gate → ✓ (chips, tooltip and since come from the PR). With two or more covering PRs the issue's own strip stops at Claimed — all passed, nothing lit — and directly beneath, one indented sub-row per open covering PR (furthest along first) carries [author icon] #N title at the PR in progress column and that PR's own strip from there on with its own lit chevron, modifier chip, tooltip and since. A PR linked to an open issue in the list has no top-level row of its own (nested_under); PRs with no linked issue keep a full-width row. The Pull requests filter flattens the list (every PR a top-level row); Issues and All show the nested view. Only the current step is coloured (amber, named in words, pulsing; static under prefers-reduced-motion; the ✓ chevron turns green once merged); passed and upcoming steps are low-contrast shapes with a small grey glyph each. Side stages ride the step they branch from — 070/072/074 light CI / Review as "Fixing" / "Returned to contributor" / "Adopted by hive", 085/090 light Merge gate as "Needs human decision" / "Ready for human merge". The lit chevron ends with a small icon of whose move it is, in the chevron's ink (person = human, robot = clanker, hexagon = hive): the claimant on Claimed, the PR author on PR in progress and Returned to contributor, hive on CI / Review / Adopted by hive / Ready for auto merge, a human on Needs human decision / Ready for human merge; Open and Actionable carry none; 040 shares PR in progress with 030, 060/080/100 light Merge gate as "Ready for auto merge" (the chevron tooltip distinguishes "not yet admitted — reason" from "admitted, merging") (the chevron tooltip names the exact stage). Every PR stage has a word: 050/060 "CI / Review", 070 "Fixing" (the author's move — a needs-rebase chip beside it says what is being fixed; the stage labeller always puts a needs-rebase PR at 070/072, never 050/060), 072 "Returned to contributor", 074 "Adopted by hive", 080/100 "Ready for auto merge", 085 "Needs human decision", 090 "Ready for human merge". The title line carries the item's number and title on the left and, aligned under the PR in progress header, [author icon] #N title for the PR itself (standalone PR rows and nested sub-rows); the author icon is coloured by author/* kind (hive blue, clanker purple, human teal). A since column on the title line gives time on the current step (red when stalled), with at most one muted health-modifier chip to its left; the reason sentence, actor, nudges, flags and the last stage hops live in the hover tooltip. Titles never wrap: an issue title is cut with an ellipsis before it would reach the PR in progress column (leaving a clear gap, so the PR entry always starts at the column's left edge) and a PR title before the chips and since; the full title is on the title element's own hover tooltip, separate from the strip's reason tooltip. Rows are sorted furthest-along first (a covered issue ranks by its furthest-along PR, not its own 040), then longest-waiting first. The sidebar badge counts items that need attention (modifiers present, or on 072/085/090). Section details: dashboard-sections.md; stage semantics: labels-and-control-signals.md.
The endpoint returns stages (the stage table with short, branch_from and configured dwell), items (one per actionable or held issue/PR in the status snapshot: stage, stage_since, humanised reason/caption, actor, modifiers, author_kind + author_kind_source, lane, tier, linked_pr, linked_prs (number, title, url, author, author kind, stage, stage_since, caption and modifiers of each open covering PR — enough to draw the nested sub-row without a second lookup), nested_under (on a PR: the issue it is listed under), nudge info and the last eight history hops from the stage store) and author_kind_labels. It answers {"status":"initializing"} until the first scan.
PR pills also carry GitHub's own review state and conversation evidence (#8968). Every field is display-only: no enumeration, review, hold, or merge gate reads any of them.
- Review decision.
protection.review_decision(APPROVED,CHANGES_REQUESTED,REVIEW_REQUIRED), withprotection.approvals_givenandprotection.changes_requested_by, comes from the one-per-repository GraphQL query the sweep already runs for branch-protection facts (protectionCollector,pkg/github/protection_facts.go). The pill shows 👍 approved, 👎 changes requested (tooltip names the reviewers), or 👀 review required. GitHub reports a null decision on a base branch that requires no review; the decision then stays unknown — it is never inferred — and the reviewer opinions GitHub did return are shown as opinions ("2 approvals on GitHub — no review decision", "changes requested by @x — no review decision from GitHub"). Any decision or opinion places the PR in the In review band unless a higher band already claimed it. - Requested reviewers and teams.
requested_reviewers(logins) andrequested_teams(slugs) come from the list payload at enumeration time — no additional request — on actionable, held, and stale-draft PRs alike. The pill shows 👥; the tooltip lists them. - Conversation volume.
comment_countandreview_thread_countare GitHub totals (totalCountonly, no thread nodes) added to the same per-repository GraphQL request as the review decision, so they cost response size rather than an additional request. The pill shows🗨 Nwith the sum; the tooltip splits comments from review threads. Nothing is shown when both are zero. - Linked issues.
linked_issues: [{number, repo, state, url}]are the first 20closingIssuesReferencesGitHub reports for the PR, from that same request. The pill's action cluster shows a🔗badge that opens the first still-open one (else the first); the tooltip lists all. This is the PR-side mirror of the issue column'slinked_prsbadge, and like it comes only from the snapshot — the card never infers or fetches relationships.
The extended request is tried first; a forge that rejects one of the added
fields (an older GHE) is asked the decision-only query instead, so the review
decision the merge-block wording depends on is never lost to a display
field. Stale drafts, which EnrichCIStatus never touches, receive these
signals through EnrichReviewSignals — the same per-repository query and no
per-PR mergeability or check-run fetch, since a draft is not a merge
candidate.
The Reporter trust block also controls the opt-in clanker_requested policy, which steers untrusted contributors to the ClankeR relay:
- Toggle for
project.issue_filter.reporter_trust.clanker_requested(off by default). - Label name (placeholder
clanker-requested) forclanker_requested_label; it must not be blank. - Comment addendum textarea for
clanker_requested_addendum(optional, max 1000 bytes). - A live preview of the comment text, updated as you type.
GET/PUT /api/config/governor expose and validate clankerRequested, clankerRequestedLabel and clankerRequestedAddendum. See Contributor trust tiers and delegated agent roles.
Owners can choose a hive-wide dashboard theme in Settings → Appearance or by
editing the persisted config through PUT /api/config/dashboard/theme. The
config surface is:
dashboard:
theme: hive # built-in id from /api/themes, or custom
theme_overrides:
tokens:
"--accent": "#e0a33a"
background:
image: https://example.org/bg.svg # https or data: URI only
opacity: 0.08
attachment: fixed
custom_css: |
.panel { border-radius: 2px; }Built-ins are loaded from one YAML file per theme under src/pkg/dashboard/theme/themes/. Initial themes include hive, hive-dark, hive-light, star-wars, dungeons-and-dragons, star-trek, cyberpunk, terminal, solarized-dark, nord, and migrated contributor profile skins such as contributor-violet-advisor. Theme files can set scopes: [dashboard, contributor] so the same catalog drives dashboard Appearance and contributor profile styling. Tokens are
validated against the dashboard's :root CSS custom properties so typos fail
fast. Custom CSS is capped at 32 KiB, strips HTML/style-breakout characters, and
only permits https: or bounded data: URLs; inlined backgrounds are capped at
256 KiB. /api/theme.css serves the effective theme with an ETag and is linked
from the document head so the themed stylesheet is available before first paint.
The Appearance tab in Settings renders the built-in preset gallery with
swatches for background, panel, accent, and text colors. Hovering a card previews
it, Apply persists the preset, Reset to preset removes overrides, and
Apply background/CSS saves the background URL, opacity, honeycomb watermark,
and custom CSS textarea (with byte counter). The existing dark/light button asks
the theme API for the closest light or dark built-in variant and refreshes
/api/theme.css without reloading the dashboard.
Preset screenshots are committed in src/docs/images/themes/ for the shipped catalog.
The contributor profile page uses the same theme catalog. Its former local profile
style numbers map to contributor-* theme ids, so existing browser-local choices
continue to work while new themes appear in the profile picker. Contributor CSS is
layered after shared theme variables and hive-wide custom CSS: theme vars → admin
Appearance custom CSS → contributor ?style=owner/repo/path.css@ref stylesheet.
Create one YAML file in src/pkg/dashboard/theme/themes/ and give it a unique
id, display name, original description, author, dark flag, tokens,
optional background, optional custom_css, and fonts stacks. The directory
README documents the full schema and guardrails. The theme loader embeds every
*.yaml file with embed.FS; adding a file automatically makes it appear in
GET /api/themes, GET /api/theme.css?theme=<id>, and Settings → Appearance.
CI runs pkg/dashboard/theme tests that parse every file, enforce unique IDs,
and reject unsupported dashboard CSS variables, so theme-only changes are a good
first issue when the palette is original and avoids logos, copyrighted imagery,
quotes, or bundled proprietary fonts.
Hive hub and spoke UI code must not call browser-native dialog APIs such as prompt(), alert(), confirm(), showModalDialog(), or native-styled <dialog>.showModal(). Use the themed in-app helpers instead (hivePrompt, hiveConfirm, hiveAlert/toast, or the contribute admin modal) so dialogs match the dashboard, are accessible, and do not block the whole tab. The ratchet tests TestNoNativeBrowserDialogsRatchet in pkg/dashboard and pkg/hub scan shipped UI sources and should be updated only to make the rule stricter.
The Compliance tab in Settings (merger or owner) shows how this hive's configuration lines up with the selected compliance framework profiles. It opens with a banner: Hive is not certified; the tab maps your configuration to control requirements.
- Framework profile — tick the frameworks to evaluate
(
compliance.frameworks); saved by the footer Save & close through the owner-onlyPUT /api/config/governor/compliance. - Controls — every control grouped by domain with its implementing setting(s), current → recommended value and a status pill. Owners get an inline toggle for boolean settings and Apply recommended per domain (a themed confirmation lists each change); other settings link to their owning tab with Open setting. Changes are staged in the owning section and written only on Save. Mergers see the tab read-only.
Details, including which settings can be toggled inline, are in Compliance controls.