Knowledge Pack Files
SideButton Dashboard Knowledge Pack Files
Browse the source files that power the SideButton Dashboard MCP server knowledge pack.
sidebutton install sidebutton.local What This Is
The Run Logs module covers three related views for monitoring and inspecting workflow executions: the Run Log List (history + live running workflows with KPI stats), the Run Log Detail (full event timeline for a completed run), and the Execution View (real-time streaming log for an in-progress execution). Together they form the execution observability surface of the SideButton dashboard.
URL Patterns
| View | URL | Notes |
|---|---|---|
| Run Log List | /run-logs | No sidebar nav entry — reached via Skills "View Run Logs" link or other in-app navigation |
| Run Log Detail | /run-logs/{id} | id is the run log record ID (not run_id) |
| Execution View | No URL | Internal view state only — triggered by navigateToExecution(workflowId, runId). Cannot be deep-linked |
View 1: Run Log List (RunLogView.svelte)
Page Structure
+--[Header: "Run Logs" h1 + item count badge]--[Clear All] [Reload]--+
| [.kpi-bar] (only when runs exist) |
| [.kpi-hero: time saved today value + label] |
| [.kpi-time-breakdown: This Week / This Month / All Time rows] |
| [.kpi-divider] |
| [.kpi-stats: Runs Today + Success Rate] |
| |
| [Currently Running section] (only when running workflows exist) |
| h2 with .pulse dot + "Currently Running ({count})" |
| [.running-list: .running-card buttons] |
| |
| [.history-section] |
| h2 "History" (only shown when running section is also visible) |
| [.run-list: .run-card buttons] |
| |
| [.empty-state] (when no runs and not loading) |
| [.loading-state] (while fetching) |
+----------------------------------------------------------------------+
Key Elements
Header
| Element | Selector | Notes |
|---|---|---|
| Page heading | h1 containing "Run Logs" | Inside .header-left |
| Item count badge | .item-count | Shows runs.length |
| Clear All button | .btn-secondary in header | Initiates inline confirm flow — does NOT open a dialog |
| Reload button | .reload-btn | Refetches run logs and running workflows immediately |
Clear All Inline Confirm
Clicking "Clear All" does NOT use window.confirm(). It replaces the button area with an inline confirm UI in-place.
| Element | Selector | Notes |
|---|---|---|
| Confirm text | .confirm-text | Text: "Clear all logs?" |
| Confirm delete button | .btn-danger | Text: "Yes, Clear". Executes the clear operation |
| Cancel button | .btn-secondary (inside confirm) | Text: "Cancel". Dismisses confirm without action |
KPI Stats Bar
Visible only when runs.length > 0. Hidden entirely during empty state.
| Element | Selector | Notes |
|---|---|---|
| Stats bar container | .kpi-bar | Horizontal row; absent when no runs |
| Hero value | .kpi-hero-value | Large green text — time saved today (formatted duration string) |
| Hero label | .kpi-hero-label | Text: "Time Saved Today" |
| Time breakdown rows | .kpi-time-breakdown | Contains rows for This Week, This Month, All Time |
| Time row label | .kpi-time-label | e.g., "This Week", "This Month", "All Time" |
| Time row value | .kpi-time-value | Formatted duration for that period |
| Vertical divider | .kpi-divider | Separates hero + breakdown from stats column |
| Stats column | .kpi-stats | Contains Runs Today count + Success Rate percentage |
Running Workflows Section
Shown only when $runningWorkflows.length > 0.
| Element | Selector | Notes |
|---|---|---|
| Section heading | h2 with .pulse dot | Animated dot + "Currently Running ({count})" text |
| Running list | .running-list | Flex/grid container of running cards |
| Running card | button.running-card | Clickable — calls navigateToRunningExecution(run_id, workflow_id) → opens ExecutionView |
| Card header | .running-header | Contains workflow title + StatusBadge showing "running" |
| Card meta | .running-meta | Shows run_id + started time |
History Section
| Element | Selector | Notes |
|---|---|---|
| History section container | .history-section | Always rendered when runs exist |
| History heading | h2 "History" | Only rendered when the Running section is also visible (i.e., hasRunning is true) |
| Run list | .run-list | Container of completed run cards |
| Run card | button.run-card | Clickable — calls navigateToRunLogDetail(run.id) → opens Run Log Detail |
| Card header | .run-header | Contains workflow title + StatusBadge |
| Card meta | .run-meta | Shows run_id + duration + timestamp |
StatusBadge Component
Used on both running cards and history cards.
| Status value | Visual |
|---|---|
"running" | Blue badge (animated) |
"success" | Green badge |
"failed" | Red badge |
Empty and Loading States
| Element | Selector | Notes |
|---|---|---|
| Empty state | .empty-state | Clock SVG icon + h3 "No Run History" + "Workflow executions will appear here." |
| Loading state | .loading-state | Text: "Loading run logs..." |
WebSocket Behavior
- Subscribes to
running-workflows-changedevents on mount - When a running workflow completes, triggers auto-refresh of run logs after a 500ms delay
- Unsubscribes on component destroy
Data Sources
listRunLogs(50)— fetches up to 50 most recent completed run logsgetRunningWorkflows()— fetches currently active executions
View 2: Run Log Detail (RunLogDetailView.svelte)
Page Structure
+--[Back btn] [.header-actions: Delete confirm area]--+
| [.run-info container, max-width 900px] |
| [.title-row: h1 workflow title + StatusBadge] |
| [.meta-grid: auto-fill grid of .meta-item cards] |
| [.params-list] (conditional: when params exist) |
| [h2 "Events ({count})"] |
| [.events-container: .event-item rows] |
| |
| [.not-found] (when ID not found) |
| [.error] (on API error) |
| [.loading] (while fetching) |
+------------------------------------------------------+
Key Elements
Header
| Element | Selector | Notes |
|---|---|---|
| Back button | .back-btn | Text: "Back". Calls navigateToRunLogs() |
| Header actions area | .header-actions | Right side of header — contains delete button or inline confirm |
| Delete button | button inside .header-actions | Initial state — triggers inline confirm |
Delete Inline Confirm
Clicking Delete replaces the button with inline confirm UI in-place. Does NOT use window.confirm().
| Element | Selector | Notes |
|---|---|---|
| Confirm text | .confirm-text | Text: "Delete this log?" |
| Confirm delete button | .btn-danger | Text: "Yes, Delete". Deletes and navigates to run logs list |
| Cancel button | .btn-secondary | Text: "Cancel". Returns to delete button |
After delete completes: navigateToRunLogs() is called automatically.
Run Info
| Element | Selector | Notes |
|---|---|---|
| Info container | .run-info | max-width: 900px, centered |
| Title row | .title-row | Contains h1 (workflow title) + StatusBadge component |
| Meta grid | .meta-grid | grid-template-columns: repeat(auto-fill, minmax(..., 1fr)) |
| Meta item card | .meta-item | One card per metadata field |
| Meta label | .meta-item .label | Uppercase text — field name (e.g., "RUN ID", "DURATION") |
| Meta value | .meta-item .value | Field value |
| Monospace value | .meta-item .value.mono | Used for IDs and timestamps |
Meta grid fields (one card each): Run ID, Workflow ID, Duration, Events, Triggered By, Timestamp.
Parameters Section
Shown only when runLog.params has one or more entries.
| Element | Selector | Notes |
|---|---|---|
| Params list | .params-list | Grid of parameter cards |
| Param card | .param-item | One per parameter |
| Param name | .param-name | Purple text — parameter key |
| Param value | .param-value | Monospace — parameter value |
Events Section
| Element | Selector | Notes |
|---|---|---|
| Section heading | h2 | Text: "Events ({count})" |
| Events container | .events-container | Monospace font family |
| Event row | .event-item | Depth-based left padding (calc(depth * N px)) |
| Event index | .event-index | Row number (0-based) |
| Event type | .event-type | Type label with color class (see below) |
| Event message | .event-message | Content of the event |
Event Type CSS Classes
| Event type | CSS class | Color |
|---|---|---|
workflow_start | .event-run | Blue |
workflow_end | .event-end | Green |
step_start | .event-step | Gray |
step_end | .event-step-end | Purple |
error | .event-error | Red |
log | .event-log | Orange / warning |
Terminal States
| Element | Selector | Notes |
|---|---|---|
| Not found | .not-found | Text: "Run log not found." |
| Error | .error | API error message text |
| Loading | .loading | Text: "Loading run log..." |
View 3: Execution View (ExecutionView.svelte)
Page Structure
+--[.back-btn (disabled while running)] [.header-info] [.header-actions]--+
| [.error-banner] (on error) |
| |
| [.log-header: event count + run ID] |
| [.log-container: scrolling monospace log area] |
| [.empty-state with .spinner] (while waiting for first event) |
| -- or -- |
| [.log-entry rows] |
+----------------------------------------------------------------------------+
Key Elements
Header
| Element | Selector | Notes |
|---|---|---|
| Back button | .back-btn | Disabled (disabled attr) while $isRunning. Enabled when completed |
| Header info | .header-info | Contains h1 (workflow title or "Execution" if title unknown) + status badge |
| Status badge (running) | .status.running | Blue — contains .pulse animated dot |
| Status badge (completed) | .status.completed | Green |
| Header actions | .header-actions | Right side — contains Stop or Done button |
| Stop button | .btn-stop | Red-tinted. Visible while $isRunning. Calls stopWorkflow(runId) |
| Done button | .btn-primary | Visible when completed. Navigates back |
Error Banner
| Element | Selector | Notes |
|---|---|---|
| Error banner | .error-banner | Shown when an error occurs. Contains error message text |
Log Area
| Element | Selector | Notes |
|---|---|---|
| Log header | .log-header | Shows event count + run ID |
| Log container | .log-container | Monospace font, scrollable. Auto-scrolls to bottom as new entries arrive |
| Empty state | .empty-state | Shown when $logs.length === 0. Contains .spinner + "Waiting for execution events..." |
| Spinner | .spinner | Spinning blue circle (CSS animation) |
| Log entry | .log-entry | One row per event. Depth-based left padding |
| Log time | .log-time | Timestamp column |
| Log type | .log-type | Type label with color class (see below) |
| Log message | .log-message | Content text |
Log Entry Type CSS Classes
| Event type | CSS class | Color |
|---|---|---|
workflow_start | .log-run | Blue |
workflow_end (success) | .log-success | Green |
error | .log-error | Red |
step_start / step_end | .log-step | Gray |
result / step_end with result | .log-result | Purple |
log with level warn | .log-warn | Orange |
WebSocket Behavior
- Calls
initWebSocket()on mount — opens real-time connection for log event streaming $effectwatches$logs.length— auto-scrolls.log-containerto bottom on every new entrystopWorkflow(runId)stops the execution and sets$isRunningto false- Back button remains disabled (
disabledattribute) while$isRunning === true
Data Models
RunLogMetadata
| Field | Type | Notes |
|---|---|---|
| id | string | Run log record ID (used in /run-logs/{id} URL) |
| workflow_id | string | Workflow identifier |
| workflow_title | string | Display name |
| status | string | "success", "failed", or "running" |
| duration_ms | number | Total execution time in milliseconds |
| event_count | number | Number of events recorded |
| timestamp | string | ISO 8601 datetime of execution start |
| triggered_by | string | Origin: "user", "agent", etc. |
RunLog (full, fetched for detail view)
| Field | Type | Notes |
|---|---|---|
| metadata | RunLogMetadata | See above |
| events | WorkflowEvent[] | Complete ordered event list |
| params | Record<string, string> | Input parameters provided at execution time |
WorkflowEvent
| Field | Type | Notes |
|---|---|---|
| type | string | workflow_start, workflow_end, step_start, step_end, error, log |
| action_id | string | Workflow ID this event belongs to |
| action_title | string | Workflow display name |
| step_index | number | 0-based step position |
| step_type | string | Step type name |
| step_details | string | Step detail text |
| success | boolean | Outcome — present on workflow_end and step_end events |
| message | string | Error or log message text |
| result | string | Step result text (shown as .log-result / .event-step-end) |
| level | string | For log events: "info", "warn", "error" |
| depth | number | Indentation level — drives left padding in both detail and execution views |
| timestamp | string | ISO 8601 datetime of this specific event |
RunningWorkflow
| Field | Type | Notes |
|---|---|---|
| run_id | string | Active run ID (used to navigate to ExecutionView) |
| workflow_id | string | Workflow identifier |
| workflow_title | string | Display name |
| started_at | string | ISO 8601 datetime when execution started |
States
RunLogView States
| State | Trigger | Visual |
|---|---|---|
| Loading | Initial fetch in progress | .loading-state "Loading run logs..." |
| Empty | Fetched, no runs found | .empty-state with clock icon, h3 "No Run History" |
| Populated (no running) | Runs exist, none active | .kpi-bar + .history-section only |
| Populated (with running) | Runs exist + active runs | .kpi-bar + Running section + h2 "History" + history section |
| Clear All: confirm pending | Clicked "Clear All" | .confirm-text + .btn-danger + .btn-secondary replace button |
| Auto-refresh | Running workflow completes | 500ms delay then data refetched silently |
RunLogDetailView States
| State | Trigger | Visual |
|---|---|---|
| Loading | Fetching run log | .loading "Loading run log..." |
| Loaded | Fetch succeeds | .run-info with title, meta grid, optional params, events |
| Not Found | ID not in records | .not-found "Run log not found." |
| Error | API failure | .error with error message |
| Delete: confirm pending | Clicked Delete | .confirm-text + .btn-danger + .btn-secondary |
| Deleted | Confirmed delete | Navigates to run logs list |
ExecutionView States
| State | Trigger | Visual |
|---|---|---|
| Running (no events yet) | Started, WebSocket connected, no events | .empty-state with .spinner + "Waiting for execution events..." |
| Running (events streaming) | Events arriving via WebSocket | .log-entry rows; auto-scrolling; Back disabled; Stop button visible |
| Completed | Final event received | .status.completed badge; Done button; Back enabled |
| Error | Error event or API failure | .error-banner visible |
| Stopped | User clicked Stop | stopWorkflow() called; $isRunning set false; transitions to completed state |
Common Tasks
- View run history: Navigate to
/run-logs— history cards appear in.run-listsorted most-recent-first - Open a completed run: Click a
.run-cardin the history section → navigates to/run-logs/{id} - Open a live execution: Click a
.running-cardin the Running section → opens ExecutionView with real-time log stream - Read KPI stats: Load
/run-logswith existing runs —.kpi-hero-valueshows time saved today;.kpi-statsshows Runs Today count and Success Rate - Delete a run log: In Run Log Detail, click Delete button →
.confirm-textappears → click "Yes, Delete" → returns to list - Clear all logs: In Run Log List, click "Clear All" → confirm text appears → click "Yes, Clear" → all logs deleted
- Reload logs: Click
.reload-btn— immediately refetches both run logs and running workflows - Stop a running execution: In ExecutionView, click
.btn-stop→stopWorkflow(runId)called → transitions to completed state - Read event details: In Run Log Detail, inspect
.event-itemrows — color-coded by.event-*class; indented bydepth - Read parameters: In Run Log Detail,
.params-listshows input params if any were provided (absent if no params)
Tips
- Running vs History are separate data sources: Running workflows come from
getRunningWorkflows()(live store); history comes fromlistRunLogs(50). They render in separate sections and refresh independently - History heading is conditional: The
h2 "History"heading only renders when there are also running workflows visible. When there are no running workflows, the list renders without a heading - KPI bar is data-dependent:
.kpi-baris absent from the DOM whenruns.length === 0. Do not assert its presence in empty-state tests - Depth field drives indentation: Both
.event-item(detail) and.log-entry(execution) usedepthto calculate left padding — deeper nesting = more indentation - ExecutionView has no URL: It is rendered as an internal view state — navigating directly to any URL will not open it. It must be reached via a running-card click or
navigateToExecution()call - Auto-scroll is reactive: ExecutionView scrolls
.log-containerto the bottom on every new log entry via a Svelte$effect. The container is always showing the latest event during a live run idvsrun_id:RunLogMetadata.idis the database record ID used for the detail URL.run_id(onRunningWorkflow) is the active execution handle. These are distinct fields with different uses- WebSocket refresh delay: When a running workflow completes, RunLogView waits 500ms before refetching — the history list may briefly not show the just-completed run
Gotchas
- Clear All and Delete use INLINE confirm, not
window.confirm(): Clicking these buttons does NOT open a browser dialog. They transform the button area into.confirm-text+.btn-danger+.btn-secondaryin-place. Automation must click through the two-step sequence - ExecutionView Back button is disabled while running:
.back-btnhas thedisabledattribute while$isRunning. Attempting to click it during execution will have no effect — wait for completion or click Stop first - No deep link to ExecutionView:
navigateToExecution()sets internal view state only. There is no URL to construct. Cannot be reached by navigating the browser address bar - Run Log List has no sidebar nav entry:
/run-logsis not listed in the left sidebar. It must be reached from Skills "View Run Logs" or programmatic navigation — do not expect a sidebar button listRunLogs(50)cap: Only the 50 most recent logs are fetched. Older entries are not paginated — they are simply omitted from the list view- Empty event type falls back: If an event's
typedoes not match a known class (.event-run,.event-end, etc.), no color class is applied — the row renders in default text color - Params section absent when no params:
.params-listis not rendered at all whenrunLog.paramsis empty or undefined — do not assert its presence unless params are known to exist - WebSocket in ExecutionView is separate from RunLogView WebSocket: Each view manages its own WebSocket subscription. The execution view streams live events; the list view only subscribes to
running-workflows-changedfor refresh triggers - SPA 404 on direct
/run-logsnavigation: As with all routes, loading/run-logsdirectly in the browser address bar before the SPA shell is loaded returns a Fastify 404 JSON response. Must navigate through the SPA root first