From c8ed190cccf92d56bf46c364c64461cb30d71a22 Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 26 Jul 2026 17:20:48 +0200 Subject: [PATCH 1/4] fix(logs): log output scrolls internally instead of scrolling the page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #2720 (partial — logs scroll fix). Make body.logs-shell a full-viewport flex column so the visible .logs-pane fills the remaining height and .journal-output (already flex:1 overflow:auto) scrolls its content. Also handle the AUDIT tab's
output the same way. The tab bar and toolbar stay anchored at the top; only the log text scrolls. --- frontend/packages/dashboard/src/logs.css | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/frontend/packages/dashboard/src/logs.css b/frontend/packages/dashboard/src/logs.css index 576c699d..2afd794e 100644 --- a/frontend/packages/dashboard/src/logs.css +++ b/frontend/packages/dashboard/src/logs.css @@ -5,6 +5,14 @@ body.logs-shell { margin: 0; padding: 0; + /* Full-viewport flex column so the log pane can scroll internally + instead of the whole page scrolling. The sticky-top wrapper and + page-header shrink to their natural height; .logs-main takes the + rest and each visible .logs-pane fills it. */ + height: 100dvh; + display: flex; + flex-direction: column; + overflow: hidden; } /* Base tab styling now lives in @hive/shared/tabs.css (.hive-tab*). The @@ -18,10 +26,28 @@ body.logs-shell { } .logs-main { - padding: 1.2em 1.5em 2em; + padding: 1.2em 1.5em 0; + flex: 1 1 0; + min-height: 0; + display: flex; + flex-direction: column; } .logs-pane[hidden] { display: none; } +.logs-pane { + flex: 1 1 0; + min-height: 0; + display: flex; + flex-direction: column; + padding-bottom: 1.2em; +} +/* The AUDIT tab uses a
for its list instead of a
, so give
+   it the same flex-grow + internal scroll that .journal-output already has. */
+#audit-list {
+  flex: 1 1 0;
+  min-height: 0;
+  overflow-y: auto;
+}
 
 .logs-toolbar {
   display: flex;

From a58816d17e38a194727520298fe0ae30345add20 Mon Sep 17 00:00:00 2001
From: iris 
Date: Sun, 26 Jul 2026 17:21:21 +0200
Subject: [PATCH 2/4] fix(stats): move window selector into the page header tab
 bar
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #2720 (partial — stats tab placement + contrast).

The time-window nav was in 
below the page title, so it controlled hash routing but wasn't visually part of the page chrome. Move it into
(same row as ← home / ST4TS), fill the remaining header space, and right-align the buttons — consistent with the /logs.html tabbar pattern. Also set explicit color/border on inactive buttons so they remain readable on lower-contrast operator colour schemes (var(--subtext1) fallback to var(--muted)). --- frontend/packages/dashboard/src/stats.css | 21 +++++++++++++++++---- frontend/packages/dashboard/src/stats.html | 15 ++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/frontend/packages/dashboard/src/stats.css b/frontend/packages/dashboard/src/stats.css index ab991375..e7c9f665 100644 --- a/frontend/packages/dashboard/src/stats.css +++ b/frontend/packages/dashboard/src/stats.css @@ -16,14 +16,27 @@ body.stats-shell { padding: 1.2em 1.5em 2em; } -/* Window selector. Buttons keep the shared `.btn` pill look; the active - one is flagged by createTabStrip via `.hive-tab--active` (was a bespoke - `.active` toggle). */ +/* Window selector — now lives in the page-header (same row as ← home / + ST4TS title). Fills the remaining header space and right-aligns the + buttons. The shared `.btn` pill look is kept; createTabStrip flags the + active one with `.hive-tab--active`. */ .hive-stats-windows { display: flex; flex-wrap: wrap; gap: 6px; - margin: 12px 0; + flex: 1; + min-width: 0; + justify-content: flex-end; + /* Smaller than the default .btn so the pills fit comfortably in the + header without competing visually with the page title. */ + font-size: 0.82em; +} +/* Inactive buttons: slightly muted to distinguish from the active window, + but readable even on low-contrast operator colour schemes. */ +.hive-stats-windows .btn { + color: var(--subtext1, var(--muted)); + border-color: var(--border); + font-size: 1em; /* relative to the .hive-stats-windows 0.82em */ } .hive-stats-windows .btn.hive-tab--active { border-color: var(--amber); diff --git a/frontend/packages/dashboard/src/stats.html b/frontend/packages/dashboard/src/stats.html index 898e99b8..d90f66bb 100644 --- a/frontend/packages/dashboard/src/stats.html +++ b/frontend/packages/dashboard/src/stats.html @@ -18,15 +18,8 @@ - -
-

hive-wide turn statistics, aggregated across every agent over the selected window. cost is a rough estimate from approximate per-model list prices — it drifts and is a ballpark, not a bill.

- - + +
+ +
+

hive-wide turn statistics, aggregated across every agent over the selected window. cost is a rough estimate from approximate per-model list prices — it drifts and is a ballpark, not a bill.

◇ busiest agents

From 234822e81035aee0b3d7b512f3ae271ebeaaae41 Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 26 Jul 2026 17:22:52 +0200 Subject: [PATCH 3/4] =?UTF-8?q?fix(schedules,call):=20rotate=20agent=20col?= =?UTF-8?q?umns=2090=C2=B0=20+=20coherent=20history=20cards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #2720 (partial — schedules + call history fixes). schedules: - Agent-name column headers: switch from -45° CSS transform (which clipped names mid-glyph) to writing-mode:vertical-rl + rotate(180deg). Names now read bottom-to-top without truncation in their 28px column. - Shrink 'next' column from 8em → 5.5em and 'every' from 7em → 5em; these only hold short duration strings so the wider widths wasted space. call history: - Approval history
  • items now get a lightweight card treatment (bg-elev background, 1px border, 3px left accent) matching the visual weight of the pending .approval-card items above them. - Left border colour reflects outcome via :has(.glyph-*): green for approved, red for denied, amber for failed. --- frontend/packages/dashboard/src/dashboard.css | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index 8eb41047..ea2a096b 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -582,6 +582,20 @@ body.dashboard-shell { background: color-mix(in srgb, var(--purple) 8%, transparent); text-shadow: 0 0 4px currentColor; } +/* History items: lighter card treatment so they're visually coherent with + the pending .approval-card items above them. Left accent colour reflects + the outcome via :has() on the per-status glyph span. */ +.approvals-history li { + background: color-mix(in srgb, var(--bg-elev) 40%, transparent); + border: 1px solid var(--border); + border-left: 3px solid var(--subtext0); + border-radius: 3px; + padding: 0.35em 0.8em; + margin-bottom: 0.4em; +} +.approvals-history li:has(.glyph-approved) { border-left-color: var(--green); } +.approvals-history li:has(.glyph-denied) { border-left-color: var(--red); } +.approvals-history li:has(.glyph-failed) { border-left-color: var(--amber); } .approvals-history .status { font-size: 0.85em; padding: 0 0.5em; } .status-approved { color: var(--green); } .status-denied { color: var(--red); } @@ -1023,34 +1037,41 @@ footer .banner-thin { white-space: nowrap; } .schedules-table-id { width: 3em; text-align: center; } -.schedules-table-next-col { width: 8em; white-space: nowrap; } -.schedules-table-every-col { width: 7em; white-space: nowrap; } +/* next / every columns: sized to typical content (short durations). + Previous 8em / 7em wasted horizontal space. */ +.schedules-table-next-col { width: 5.5em; white-space: nowrap; } +.schedules-table-every-col { width: 5em; white-space: nowrap; } .schedules-table-body-th { min-width: 12em; } .schedules-table-actions-th { width: 7em; } +/* Agent-name columns: 90° vertical text (writing-mode) so names are fully + readable without truncation. Previously used a -45° CSS transform which + clipped names mid-glyph. writing-mode + rotate(180deg) is in-flow and + needs no absolute positioning or overflow hacks. */ .schedules-table-agent-th { width: 28px; min-width: 28px; - height: 95px; - padding: 0 !important; + height: 8em; + padding: 4px 2px !important; vertical-align: bottom; - white-space: nowrap; text-transform: none !important; letter-spacing: 0 !important; - position: relative; + overflow: hidden; } .schedules-table-agent-th > div { - position: absolute; - bottom: 4px; - left: 14px; - transform-origin: left bottom; - transform: rotate(-45deg); font-family: ui-monospace, 'JetBrains Mono', monospace; - font-size: 0.9em; + font-size: 0.85em; color: var(--fg); + /* Rotate 90° bottom-to-top (conventional rotated column header). */ + writing-mode: vertical-rl; + transform: rotate(180deg); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-height: 7.5em; } .schedules-table-agent-th > div > span { display: inline-block; - padding: 0 4px 1px; + padding: 0 2px; } /* Column for an agent no longer in the live roster — its past schedules linger but the agent is gone. Greyed + struck through so the operator From c08f47a035da644880b0891558b97cedab92299b Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 26 Jul 2026 17:23:52 +0200 Subject: [PATCH 4/4] fix(core): add card styling for K3PT ST4T3 and 1NFR4 entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #2720 (partial — kept state + infra card layout). core.html doesn't load dashboard.css so the .container-row styles from the operator SPA weren't available. Add equivalent card rules directly in core.css: .containers flex column, .container-row with bg-elev background + border + border-radius, .tombstone dashed variant, .head flex row with badge + meta, .actions flex row for the action buttons. Matches the visual weight of agent cards on the main dashboard. --- frontend/packages/dashboard/src/core.css | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/frontend/packages/dashboard/src/core.css b/frontend/packages/dashboard/src/core.css index bc16c365..15fad5e8 100644 --- a/frontend/packages/dashboard/src/core.css +++ b/frontend/packages/dashboard/src/core.css @@ -21,3 +21,51 @@ body.core-shell { /* createTabStrip toggles the native `hidden` attribute on inactive panes; ensure it wins over any inherited display. */ .core-pane[hidden] { display: none; } + +/* ─── K3PT ST4T3 + 1NFR4 container cards ──────────────────────────── + core.html doesn't load dashboard.css (that's the operator SPA), + so the .container-row card styles aren't inherited. Redefine them + here so tombstone and infra entries look like proper cards (similar + to agent cards on the main dashboard) rather than bare list items. */ +.containers { + list-style: none; + padding: 0; + margin: 0.5em 0 0; + display: flex; + flex-direction: column; + gap: 0.5em; +} +.container-row { + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: 4px; + padding: 0.55em 0.8em 0.5em; +} +.container-row.tombstone { + border-style: dashed; + background: color-mix(in srgb, var(--bg-elev) 35%, transparent); + opacity: 0.85; +} +.container-row .head { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.5em; + margin-bottom: 0.4em; +} +.container-row .head .name { + font-size: 1.05em; + font-weight: bold; +} +.container-row.tombstone .head .name { color: var(--muted); } +.container-row .head .meta { + margin-left: auto; + font-size: 0.88em; + color: var(--muted); +} +.container-row .actions { + display: flex; + flex-wrap: wrap; + gap: 0.4em; +} +.container-row .actions form.inline { display: inline-block; margin: 0; }