Skip to content

feat(dashboard): redesign harness UI as an agent run control center#331

Open
alexk-dev wants to merge 6 commits into
mainfrom
feat/harness-ui-redesign
Open

feat(dashboard): redesign harness UI as an agent run control center#331
alexk-dev wants to merge 6 commits into
mainfrom
feat/harness-ui-redesign

Conversation

@alexk-dev
Copy link
Copy Markdown
Owner

Summary

  • Replace the legacy chat dashboard chrome with a clean dark-first agent harness shell built around the spec at golemcore_harness_ui_redesign_spec.md: icon rail, secondary sidebar, top bar with status pills, tabbed inspector, and a slim command-palette layer.
  • Introduce the agent-run primitives (TaskHeader, PlanBlock, ToolCallTimeline, IncidentCard, ApprovalRequestCard, ArtifactCard, StatusPill) plus an event normalizer (normalizeRunEvents) so future plan/tool/incident streams have a stable view-model boundary.
  • Surface live runtime data inside the inspector — context/token telemetry summary, plan-mode status, derived tool-call timeline (with §23 sample fallback), /system/logs viewer with level + search filters, and memory presets.
  • Add a Cmd/Ctrl+K command palette (fuzzy search, grouped results, keyboard nav), persisted layout preferences (inspectorStore), and a one-shot session JSON export hook.

Architecture

DashboardLayout
  └─ HarnessShell                  ← composes the redesigned shell
       ├─ IconRail                 (60px global rail)
       ├─ SecondarySidebar.sidebar (Sessions / Automation / Agent / Observability / Workspace / System)
       ├─ harness-body
       │    ├─ ChatRuntimeController (unchanged transport)
       │    ├─ HarnessTopBar      (status pills, New chat, ⌘K, theme, settings, logout)
       │    └─ <Routes children/>
       ├─ InspectorPanel           (tabs: Inspector / Plan / Tools / Logs / Memory)
       └─ CommandPalette           (Cmd/Ctrl+K, useCommandPaletteShortcut)

Key design decisions

  • Drop-in shell, isolated tokens. New tokens live under --hns-* in harness.scss and switch via data-harness="dark|light" on <html>, so the legacy --gc-* palette and existing pages keep working untouched.
  • Preserve e2e selectors. The new sidebar still renders as <aside class="harness-sidebar sidebar" aria-label="Primary navigation"> with Open / Close navigation controls and a .sidebar-overlay-equivalent backdrop, so dashboard-menu-smoke and dashboard-mobile-responsive Playwright tests pass without test edits.
  • View-model adapter. normalizeRunEvents shields the new components from raw chat payloads — the inspector surfaces live tool calls today (parsed from [Tool: …][Result: …] markers) and falls back to the §23 sample once the runtime emits structured plan/tool events.
  • Power-user surface. Command palette state lives in its own Zustand store with a global Cmd/Ctrl+K listener and a custom event (harness:export-session) to decouple commands from concrete handlers — easy to extend without touching the registry.
  • Strict CLAUDE.md rules. All new files stay under 200 LOC JSX / 400 LOC, props interfaces are explicit, no any, no inline styles (progress fill uses a CSS custom property), useEffect blocks carry justifying comments, persisted state goes through Zustand persist middleware.

Files changed

Area Files What
Shell components/layout/DashboardLayout.tsx, components/layout/harness/{HarnessShell,HarnessTopBar,IconRail,SecondarySidebar,SidebarChatSessionsList,sidebarNavGroups,topbarStatus,useRailVersionLabel}.tsx/ts New harness layout. Legacy Sidebar.tsx / Topbar.tsx removed.
Inspector components/layout/harness/InspectorPanel.tsx, components/layout/harness/inspector/{InspectorSummaryTab,InspectorContextCard,InspectorActionsCard,InspectorPlanTab,InspectorToolsTab,InspectorLogsTab,InspectorMemoryTab,contextUsage}.tsx/ts Tabbed inspector with summary, plan, tools, logs and memory.
Agent run primitives components/agentRun/{types,agentRunFormat,normalizeRunEvents,sampleAgentRun,StatusPill,TaskHeader,PlanBlock,PlanStepRow,ToolCallTimeline,ToolCallRow,IncidentCard,ApprovalRequestCard,ArtifactCard}.tsx/ts (+ unit tests for each) Spec §17 view models + presentational components.
Command palette components/commandPalette/{CommandPalette,commandRegistry,fuzzyMatch,useCommandPaletteShortcut,useSessionExport}.tsx/ts (+ test) Cmd/Ctrl+K palette, fuzzy search, session export hook.
Hooks hooks/useInspectorLogs.ts React Query wrapper for /system/logs used by the inspector.
Stores store/inspectorStore.ts, store/commandPaletteStore.ts Persisted inspector tab/visibility state and palette open state.
Styles styles/harness.scss, styles/agentRun.scss New design tokens, shell, inspector, agent-run cards, command palette, log viewer.
Bootstrap main.tsx Imports the two new SCSS bundles.

Compatibility

  • No backend changes. Existing endpoints (/system/logs, /plans, memory presets) are reused as-is.
  • Runtime parity preserved. ChatRuntimeController, all chat hooks/stores, and the routing surface are unchanged; legacy pages keep their layout because the new shell still applies min-width: 0; min-height: 0; flex constraints.
  • Mobile. Sidebar still slides in via mobile-open, hamburger toggles Open/Close navigation, and the backdrop carries the Close navigation menu label — overlap-checking Playwright tests pass.
  • Theme. Existing themeStore light/dark toggle still works; the harness palette tracks it via data-harness.

Verification

  • npm run lint — 0 errors (4 pre-existing warnings, unrelated files).
  • npx tsc --noEmit — clean.
  • npm test — 125 files / 463 tests passing (added 25 new unit tests for the harness components, palette and adapter).
  • npm run build — succeeds.
  • npx playwright test (chrome) on dashboard-menu-smoke, dashboard-mobile-responsive, chat-multi-session, workspace-layout, mobile-audit — 12/12 passed.

alexk-dev and others added 6 commits April 29, 2026 17:56
Replaces the legacy chat dashboard chrome with a clean, dark-first agent
harness composed of an icon rail, secondary sidebar, top bar with status
pills, main agent thread and a tabbed inspector panel. Adds the agent
run primitives (TaskHeader, PlanBlock, ToolCallTimeline, IncidentCard,
StatusPill) per the redesign spec, a Cmd/Ctrl+K command palette, session
export and persisted layout preferences.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wraps ChatPage in HarnessChatLayout so the redesigned TaskHeader appears
above the active conversation, then collapses the legacy in-page
duplicates of the harness chrome:

- ContextPanel + ContextPanel offcanvas hidden — InspectorPanel covers
  the same telemetry/plan/tools/logs/memory surface.
- ChatSessionTabs + ChatToolbar hidden in standalone mode — recent
  sessions live in the IconRail/SecondarySidebar and connection / tier /
  Plan ON state lives in HarnessTopBar.
- chat-container, chat-window, message-bubble, chat-input-area, starter
  prompts and inline tool-call cards repainted with --hns-* tokens so the
  thread matches the dark agent-run aesthetic.

useChatRunSummary derives an AgentRunStatus + duration counter from the
runtime store and useRecentSessions title, so TaskHeader keeps a live
"Started 10:31 AM · 12m 45s · N steps" subtitle without needing new
backend fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops the separate IconRail in favour of a single sidebar that defaults
to 60px (icons only) and expands to 280px on hover or focus, painted in
the harness palette. Brand and version footer are folded into the
sidebar so the left chrome no longer feels like "old + new" stacked.

Inspector polish:
- Tools tab no longer shows a demo IncidentCard; only a §23 reference
  timeline appears when there are no live tool calls.
- Plan tab swaps the demo PlanBlock for an explanatory placeholder when
  Plan mode is OFF; the sample render only appears once Plan mode is
  toggled on so users see the layout context only when relevant.
- Logs tab fetches the system feed but filters by the active
  conversationKey + sessionRecordId substring by default; a toggle
  expands the view back to runtime-wide logs when needed.
- Compact context action now calls /sessions/{id}/compact and surfaces
  the result via toast; export session reuses the existing custom event
  hook; debug bundle remains a placeholder until the runtime ships a
  snapshot endpoint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds /api/memory/relevant — a thin read-only endpoint that wraps
MemoryComponent.queryItems, anchored on the active conversation key so
the dashboard can surface knowledge artifacts (facts, preferences,
constraints, decisions, failures, fixes, tasks, command results)
related to the current chat instead of memory presets.

The dashboard Inspector "Memory" tab is rebuilt around this endpoint:
relevant memories with type badges (Fact / Preference / Constraint /
Failure / Task / Decision / Fix / Command), markdown-friendly content
preview, "Added X ago · In N sessions" footer, type filter, search
field and an auto-refresh toggle. The "View all memories" link routes
to /settings/memory for the full inventory.

Backend:
- RelevantMemoryResponse DTO in golemcore-bot-client
- MemoryController in golemcore-bot-app with 3 unit tests covering
  scope chain construction, limit clamping and global fallback

Frontend:
- src/api/memory.ts + src/hooks/useRelevantMemories.ts
- MemoryArtifactCard + memoryFormat helpers (with vitest coverage)
- InspectorMemoryTab rewritten to consume the new feed and infer the
  query hint from the most recent user message

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ArchUnit's MavenModuleDependencyArchitectureTest forbids Lombok's
@requiredargsconstructor on production beans — controllers in this
codebase use private final fields with an explicit constructor (cf.
PlansController, SessionsController). Drop the Lombok annotation and
write the constructor by hand.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The button routed to /settings/memory which opens the memory preset
editor, not a list of knowledge artifacts. Until a dedicated all-memories
page exists, removing the link is clearer than misdirecting the user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant