Reuse the existing @pierre/diffs Shiki highlighter and registered DOT
grammar (already used on the workflow definition page) so the Source
view renders workflow.fabro with proper highlighting instead of plain
monospace text.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Toggling to Source unmounted the graph container, so switching back
mounted a fresh inner div without re-running the render effect — leaving
"Loading diagram..." stuck. Hide the graph via the hidden attribute
instead so the cached SVG and pan/zoom state survive view switches.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add GET /api/v1/runs/{id}/graph/source returning text/vnd.graphviz so
the run graph can be inspected as the original Graphviz DOT in addition
to the rendered SVG. Refactor get_graph to share DOT loading with the
new handler. The web run-graph view gains a Graph | Source toggle that
lazy-loads and displays the DOT with a copy button.
Replace React Router loader/action state paths with SWR query and mutation hooks.
Add targeted run and board EventSource managers that invalidate SWR keys, and refresh embedded SPA assets.
Removes unused annotateRunningNodes from run-graph and inlines the
const gt = graphTheme / const theme = graphTheme shims left over from
the dark-mode-only refactor. Template strings reference graphTheme
directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the light/dark toggle infrastructure in favor of a single dark
theme. Deletes the theme context, boot script, light-mode CSS overrides,
logotype-light asset, and the pierre-light diff theme. Collapses
graph-theme into a single constant. Adds scheme-only-dark on <html> so
native controls and the server-injected Graphviz @media query render
dark.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
run-stages:
- replace the full-width tinted System/Assistant cards with a subtler
left-accent bar and header so dense streams read cleanly
- unify the Running/Timed out/exit/duration indicators under a shared
StatusPill, and bump stdout/stderr labels from 10px to 11px
- raise the selected stage header from text-sm font-medium to
text-base font-semibold
- command output preformatted text is now text-sm on mobile
run-overview and run-graph:
- extract the floating direction/fit/zoom controls into a single
GraphToolbar capsule with internal dividers, shared between both
graph views
- drop the translucent canvas in favor of solid bg-panel-alt
- wrap the "no workflow graph" message in a proper empty-state panel
run-billing:
- tfoot now uses bg-overlay so totals read heavier than the body
- table headers gain font-medium and a readable fg-3 instead of
fg-muted
- "By model" heading is a real section heading, not an eyebrow
- add an empty state when a run has no billing yet
stage-sidebar:
- cancelled stages now use NoSymbolIcon so they don't look identical
to failed stages at a glance
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add direction toggle (LR/TB) to overview and graph pages, re-fetching
SVG from server with ?direction= param on change
- Add failed node colors (red) to graph theme for both dark and light modes
- Color failed stages red and exit node green/red based on run outcome
- Skip pointer capture on graph node clicks so navigation works
- Hide workflow breadcrumb segment in non-demo mode
- Show empty state on stages page when no stages exist instead of 500
- Use apiJsonOrNull for stages endpoint to handle missing data gracefully
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract shared StageSidebar component from 4 duplicated implementations
across run-overview, run-graph, run-settings, and run-stages routes.
Add SSE subscription in run-detail parent layout so all child routes
get live stage updates — stages appear immediately when they start,
show a spinning icon while running, and display a ticking elapsed timer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix run detail status: display actual API status (submitted, running,
succeeded, failed, etc.) instead of always showing "Working"
- Implement /runs/{id}/stages endpoint in non-demo mode, reading from
checkpoint + events to build stage list with statuses and durations
- Fix /runs/{id}/graph to fall through to durable store when run is not
in the live map
- Render real workflow graph SVG on overview and graph pages instead of
hardcoded demo graph; remove unused DotDiagram component from overview
- Add dark mode CSS overrides for server-rendered SVG graphs
- Wire stage detail page to real event data: fetch from /events, filter
by node_id, and render as system/assistant/tool blocks
- Fix stage page 500: use apiJsonOrNull for unimplemented /turns endpoint
- Filter start/exit graph control nodes from stage lists in the UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server changes:
- Add /boards/runs to demo routes (delegates to list_runs)
- Fix demo get_run_status to return StoreRunSummary shape matching OpenAPI spec
- Enrich real /boards/runs to return RunListItem shape with board column mapping
(Running->working, Paused->pending, Completed->merge; others excluded)
- Update existing tests that asserted old RunStatusResponse fields from /boards/runs
Web UI changes:
- Add DemoModeProvider context and useDemoMode hook
- Hide Workflows/Insights nav items in production mode via getVisibleNavigation
- Change run-detail loader to use /runs/{id} directly instead of searching /boards/runs
- Add mapRunSummaryToRunItem for mapping server response to UI shape
- Add Graph tab, hide Stages tab in production mode, always hide Files tab
- Make run-overview and run-graph loaders resilient to 501 via apiJsonOrNull
- Add isNotImplemented and apiJsonOrNull helpers to api.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the old React Router SSR setup with a static SPA build served by
fabro-server, move setup and GitHub auth handling into Rust, and update the
default local web URL and stale Arc-era references to match the Fabro name.