Skip to content

feat(ui): rebuild the logged-in shell, chat pane, dashboard widgets and sign-in - #226

Merged
vishr merged 48 commits into
mainfrom
ui/shell-rebuild
Sep 6, 2026
Merged

feat(ui): rebuild the logged-in shell, chat pane, dashboard widgets and sign-in#226
vishr merged 48 commits into
mainfrom
ui/shell-rebuild

Conversation

@vishr

@vishr vishr commented Sep 6, 2026

Copy link
Copy Markdown
Member

What changed

The logged-in app is rebuilt around a persistent navigation rail, with the chat pane, dashboard widgets, sign-in code step and typeface reworked. Spec: docs/superpowers/specs/2026-09-05-logged-in-ui-shell-design.md. Plan: docs/superpowers/plans/2026-09-05-logged-in-ui-shell.md (17 tasks, each reviewed).

  • Shell. A left rail lists chats (rename, delete, search with Cmd-K) and dashboards, with New chat and Create with AI. The header keeps the brand, the colour-scheme toggle and an account menu (email, GitHub, LabStack, sign out). The Dashboard/Chat toggle, history drawer, plus icon, hard-coded "Live" dot and footer are gone. Below md the rail lives in a drawer behind a burger.
  • Chat. The pane fills the viewport under the header with the composer at its bottom. Empty state is one line and four suggestion chips. Messages have no avatars; assistant replies get product chrome for markdown tables, code blocks (copy button) and links; hover shows a timestamp and a copy button. While a run is live the composer shows Stop and an activity line names the tool in use. Draft threads are not fetched, so a new chat no longer fires a 404; a deleted thread explains itself; a failed restore or run offers Retry. Embedded views now load their inlined fonts (font-src 'self' data: in the frame CSP), size to their content from a 240px floor, and carry a slimmer header with an icon refresh and a Retry on error.
  • Dashboard. Widgets are native ECharts bodies: health tiles with an error-rate sparkline, a circular service map, activity table, operations/P95 chart with top endpoints, trace tiles with a mini waterfall, a log histogram with entries, and window-scoped assistant questions. Cards have a title-only header, hover actions (Configure, Remove), a configure modal writing widget.config, per-type default sizes, and free-slot placement that shrinks to the space left on the row. The page header drops Refresh, Saved and the Dashboards dropdown; data refetches every 30 s with an "Updated" line. The server's default layout matches the new sizes.
  • Sign-in. Six-digit PinInput that verifies on the sixth digit, a Verify button, Resend with a 30 s cooldown, Change email, "Check your email" copy, headings at 28/32px; setup success copies the whole Authorization header line.
  • Typeface. Geist (variable) for UI, prose and headings at weight 600; Geist Mono only for code, ids, timestamps and numeric cells; tabular figures throughout; light-mode dimmed text darkened to 4.8:1. Chosen after Refero research (Linear, Better Stack, Axiom) and a check of the sibling projects. The marketing site stays on Plex until its own change.
  • Agent prompt. The model is told, first, never to draw diagrams or restate an attached view in text.
  • Shared code. format.ts, contracts.ts and the chart helpers moved to ui/ for both bundles.

Defects fixed on the way: embedded views in the system font, "994.6 Ms", the per-chat 404, header clipping at 390px, the 3 s dashboard poll, a spinner-forever on thread-load failure, an unhandled clipboard rejection, a countdown timer that never stopped after sign-in.

Verification

  • just check on 971d21f: all checks passed (host suite 66 tests across 12 files, apps and host tsc, Go tests, notices, docs and site checks).

  • Manual pass on a local instance with 60 minutes of seeded traffic at 1440x900 and 390x844, light and dark: shell, chat with embedded views and markdown tables, dashboard with all seven widget types, configure and remove, sign-in code step.

  • A dedicated UX walk of every screen produced 51 findings; the 15 Important ones are fixed in this branch, the 36 Minor ones are listed below.

  • just check

  • just test-race not run: auth, API, ingest, query and MCP paths are unchanged apart from a one-sentence system-prompt edit and a default-layout constant, both covered by go test.

  • User-facing behavior and configuration docs are current (spec and plan committed under docs/superpowers/)

  • No credentials, private telemetry, host details, or enterprise-only source are included

  • API, migration, ingest, MCP/AG-UI, or release-contract changes are called out: none. Existing dashboards keep their stored layouts (pre-release, no migration); the server default only applies to new owners.

Follow-ups (not in this PR)

  • Backend: GET /api/agent/threads/{id} returns only the last run's activity message, so a restored thread loses earlier embedded views.
  • Site: move site/ to Geist so app and site match.
  • ui/apps font subsets: the fontsource variable package ships no latin.css; hand-written @font-face rules would cut about 34 KB per bundle.
  • Demo instance needs reseeding to show the new default layout.
  • UX walk minors deferred (row numbers from the walk): chat empty state sits high in the pane (16); markdown heading scale flattened (17); a single embedded view taller than the pane (19); emoji status glyphs and unit drift in model prose (20, 21); "Error rate x 1000" legend in the performance view (22); Enter swallowed during a run (23); search clear affordance and hint (25); Default badge size (26); actions aria-label from a truncated title (27); header control sizes and baseline (28); brand wordmark tracking under Geist and not a link (29); account menu divider and external cues (30); Cmd-K feedback (31); dashboard control-row spacing, icon and namespace field affordance (32 to 34); Add view marks nothing already present (35); modal theming (36); service map fill, log histogram height, trace body overflow, "last 1 hour" copy (37 to 40); missing-thread alert layout (41); mobile drawer body height and overlay (42, 43); sign-in tap targets, disabled email field, eyebrow copy, placeholder casing, "Copy token only" sizing (44 to 49); heading weights across surfaces (50); composer hint spacing (51).

https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N

vishr added 30 commits September 5, 2026 13:23
Persistent rail navigation, chat pane with sticky composer, native ECharts
dashboard widgets, PinInput code step, and the defects folded into the work.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
Fourteen tasks across six phases, each with its failing test, code and
commit, from the CSP font fix through the rebuilt shell, chat pane, native
dashboard widgets, six-digit sign-in and the embedded-asset gate.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
The MCP app CSP only emitted font-src when a resource domain was declared, so
the data: woff2 files the apps build inlines were blocked and every embedded
view rendered in the system font.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
Router-free rail with New chat, the chat list with rename and delete, the
dashboard list, and a search field. The old history drawer stays until the
shell adopts the rail.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
…ent rail

The rail is the only navigation: New chat, the chat list with rename and
delete, the dashboard list, and search on Cmd-K. The footer, the Live dot and
the Dashboard/Chat toggle are gone; sign out and the external links live in
the account menu. The session no longer fetches a thread it has just named,
which removes the 404 on every new chat.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
One grotesk for UI, prose and headings at weight 600, Geist Mono for code,
ids, timestamps and numeric cells, tabular figures throughout. Headings no
longer use the mono display face.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
The typeface swap changed the release dependency graph, so notices-check
(part of `just check`) went stale. Regenerated with the go.mod toolchain.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
Mantine's Typography styles a bare code element as an inline chip, and that
chip was applying inside a fenced block: one ragged background rectangle per
line, at a smaller size than the pre around it. The block now inherits its
background, padding and type from the pre.

A rail row gave its title about a hundred pixels of a 219 pixel row because
the time sat beside it and never shrank, so long titles were cut after a
dozen characters and the cut point moved with the length of the time. Title
and time are now stacked, and the title has the row to itself.

The mobile drawer autofocused search whichever way it opened, so tapping the
burger to read the lists raised the keyboard over them. The shell now
remembers why the drawer opened and focuses search only for Cmd-K.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
…nt shrink

The error-rate sparkline was a sibling of its tile, so it floated below the
tile's border and left the two tiles in the row ending at different heights.
A metric tile now takes children, draws them inside its own border, and
fills its grid cell.

The service map's force layout ran again from scratch on every thirty-second
poll, so the nodes moved while the map was being read. The widget draws a
circular layout, which puts a service in the same place every time. The chat
view keeps the force layout: it is drawn once and never polled.

The logs table let its body cell take the whole row and squeezed the
severity badge to a coloured dot, which left severity as colour alone. The
badge and service cells now hold their width.

A card that did not fit its default width started a new row and left the
columns beside it empty for the rest of the dashboard. Placement now offers
the gap on the row at the width that is left, when the card can still be
read at that width. The overview card's default height drops to three rows
to match its content, and the dashboard's control row wraps instead of
clipping "Add view" and "Ask Fanout" at 390px.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
Mantine's light-scheme dimmed grey is 3.3:1 on this ground, under WCAG AA,
and dimmed is not decoration here: page descriptions, the updated time, rail
times and section labels, the composer hint and healthy error rates all use
it. The light scheme now takes the chart palette's muted grey, which clears
AA at 4.8:1 and matches the axis labels beside it.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
A circle badge sizes itself to one character, so a two-digit count rendered
as "1…" — a truncated number reads as wrong data. The count keeps its pill.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
…ne cleanups, dashboard search empty state

A dashboard saved by a newer build can name a view this one has never heard
of. The layout memo read a size off that missing key and the card looked up a
body that was not there, so one unknown type blanked the whole page. The
layout falls back to the overview size and the card renders a body that says
the view is not supported.

The trace widget computed its bar window from a span list that can be empty,
where Math.min returns Infinity; the window now lives with the bars that use
it. Its copy button holds the reset timer so a second click is not cut short
by the first one's, and clears it when the card goes away.

The sparkline registers the line chart it draws instead of relying on whichever
widget imported one first, and holds its option steady across renders. The logs
widget shows five entries as the spec says, and a dashboard search that matches
nothing says so rather than leaving an empty section under the label.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
… entry point

The embedded views rebuilt their chart on every render: init, setOption and
dispose all lived in one effect keyed on the option object and the click
handler, both of which callers pass inline. The wrapper now mirrors the host
copy — one instance per mount, the handler through a ref registered once, and
option changes applied in place with notMerge so a series that leaves the data
leaves the chart.

The font imports name index.css rather than leaning on the exports map. The
ruling asked for the latin subset, but @fontsource-variable/geist 5.3.0 ships
no per-subset stylesheet, so index.css is the same set of faces the bare
specifier already resolved to.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N
The spec said timestamps come from the AG-UI message when present, which no
message carries; they are stamped in this session and nowhere else, so a
restored thread shows the copy button without a time. The Direction comment
pointed at ui/apps/src/contracts.ts, which is now ui/contracts.ts.

Claude-Session: https://claude.ai/code/session_015K38gEgWmGkXJyyC8GiZ8N

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new rail imperative focus handle is wired through a ref prop that won’t work on a function component, and useLastUpdated leaks a React Query subscription without unsubscribing.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR rebuilds the logged-in web UI around a persistent navigation rail, a full-height chat pane, and native dashboard widgets, while also updating the shared UI tokens/theme (notably the Geist typeface) and aligning embedded MCP views and server defaults to the new presentation.

Changes:

  • Introduces a new AppShell-based layout with a left navigation rail (chats + dashboards + search) and updated chat routing/empty state/composer behavior.
  • Replaces dashboard “widgets” with native ECharts-based cards (plus config/remove actions), and updates default widget sizing/placement on both client and server.
  • Moves shared formatting/contracts/chart helpers into ui/ and updates embedded views + iframe CSP to correctly load inlined fonts.
File summaries
File Description
ui/tokens.ts Updates font token stacks to Geist Variable / Geist Mono Variable.
ui/theme.ts Aligns Mantine theme headings + dimmed color with new typography and chart palette.
ui/host/src/widgets/widgets.test.tsx Adds integration-style widget tests with mocked fetch + EChart.
ui/host/src/widgets/widget-card.tsx Introduces widget card chrome with actions/config modal and unknown-type fallback.
ui/host/src/widgets/trace.tsx Adds Trace widget (summary tiles, mini waterfall, copy trace id).
ui/host/src/widgets/topology.tsx Adds Topology widget using ECharts graph with stable node ordering and chat deep-link.
ui/host/src/widgets/pieces.tsx Adds shared widget UI pieces (Metric, Empty, Error, Sparkline, HealthBadge).
ui/host/src/widgets/performance.tsx Adds Performance widget (ops + p95 trend + top endpoints table).
ui/host/src/widgets/overview.tsx Adds Overview widget (health/error rate tiles + sparkline + distribution bar).
ui/host/src/widgets/logs.tsx Adds Logs widget (severity histogram + entries table).
ui/host/src/widgets/data.ts Adds shared widget data/query helpers and “last updated” tracking hook.
ui/host/src/widgets/data.test.tsx Tests widgetParams/config helpers and the update-time hook.
ui/host/src/widgets/configure.tsx Adds per-widget configuration modal writing widget.config.
ui/host/src/widgets/assistant.tsx Adds assistant widget with window-scoped question chips.
ui/host/src/widgets/activity.tsx Adds activity widget (service table sorted by health/error rate).
ui/host/src/theme.test.ts Tests the new typeface and light-scheme dimmed override.
ui/host/src/test-setup.ts Adds happy-dom document.fonts stub for Mantine autosize behavior.
ui/host/src/shell.tsx New AppShell layout: header + rail navbar + mobile drawer + account menu.
ui/host/src/routes/dashboards.index.tsx Updates dashboard routes to use the new app context import.
ui/host/src/routes/dashboards.$dashboardId.tsx Updates dashboard routes to use the new app context import.
ui/host/src/routes/chat.index.tsx Routes /chat/ directly to ChatPage (draft chat behavior).
ui/host/src/routes/chat.$threadId.tsx Routes /chat/$threadId to ChatPage from the new module.
ui/host/src/rail.tsx New rail component: chat history + dashboards list + rename/delete + search.
ui/host/src/rail.test.tsx Tests rail rendering, searching, and thread rename/delete flows.
ui/host/src/mcp-app-frame.tsx Updates iframe CSP (font-src data:) and removes tool-specific min-heights.
ui/host/src/mcp-app-frame.test.tsx Updates tests for new iframe min-height and CSP behavior.
ui/host/src/main.tsx Switches loaded typeface packages to Geist variable families.
ui/host/src/index.css Adds new rail/widget/chat pane CSS and tabular-nums base styling.
ui/host/src/echart.tsx Adds host-side ECharts wrapper (single instance, resize observer, aria).
ui/host/src/echart.test.tsx Tests EChart instance reuse and click handler routing.
ui/host/src/dashboard.test.tsx Updates dashboard tests for new header behavior and widget placement.
ui/host/src/dashboard-layout.ts Adds widget type list, per-type defaults, and “next free slot” placement.
ui/host/src/dashboard-layout.test.ts Tests widget placement and default sizing invariants.
ui/host/src/chat.tsx New chat pane UI: markdown chrome, empty state, composer, errors, embedded views.
ui/host/src/chat.test.tsx Tests chat suggestions, markdown chrome, running state, retry/missing thread, clipboard failures.
ui/host/src/chat-history.tsx Removes the legacy chat history drawer implementation.
ui/host/src/chat-history.test.tsx Removes tests for the legacy chat history drawer.
ui/host/src/auth.test.tsx Extends auth tests for new sign-in behavior and viewer exposure.
ui/host/src/app.test.tsx Adds tests for draft chat behavior (no thread fetch) and restore retry semantics.
ui/host/src/app-context.ts Introduces a shared app context API (activity labels, dashboard prompt, etc.).
ui/host/src/api.ts Centralizes host API helpers/types and query keys used by rail/widgets.
ui/host/package.json Swaps font dependencies, adds echarts to host app deps.
ui/host/bun.lock Lockfile updates for new deps (Geist variable fonts, echarts, tslib changes).
ui/format.ts Adds shared formatting helpers (percent/duration/windowLabel/timestamps).
ui/contracts.ts Adds shared TS contracts for observability payloads + envelopes.
ui/chart.ts Adds shared chart/status helpers for host + embedded views.
ui/apps/src/trace.tsx Updates embedded trace view to import shared helpers/contracts and adds retry UI.
ui/apps/src/topology.tsx Updates embedded topology view to import shared helpers/contracts and adds retry UI.
ui/apps/src/performance.tsx Updates embedded performance view to import shared helpers/contracts and adds retry UI.
ui/apps/src/overview.tsx Updates embedded overview view to import shared helpers/contracts and adds retry UI.
ui/apps/src/logs.tsx Updates embedded logs view to import shared helpers/contracts and adds retry UI.
ui/apps/src/echart.tsx Aligns embedded EChart wrapper behavior with host (instance reuse, latest click handler).
ui/apps/src/components.tsx Updates embedded app shell/header/status UI + swaps to Geist variable font CSS.
ui/apps/package.json Swaps embedded app font dependencies to Geist variable families.
ui/apps/bun.lock Lockfile updates for embedded app font dependency swap.
THIRD_PARTY_NOTICES Updates notices for font packages (IBM Plex → Geist).
internal/ui/dist/index.html Updates compiled asset references after UI rebuild.
internal/ui/dist/assets/useNavigate-BEpS2iE5.js Removes an old compiled asset.
internal/ui/dist/assets/Table-BcfmFrO2.js Adds a new compiled asset.
internal/ui/dist/assets/routes-UYU1YEPx.js Removes an old compiled asset.
internal/ui/dist/assets/routes-BnFL5jvM.js Adds a new compiled asset.
internal/ui/dist/assets/dashboards.index-DzfpVEyI.js Removes an old compiled asset.
internal/ui/dist/assets/dashboards.index-B2QXPF6y.js Adds a new compiled asset.
internal/ui/dist/assets/dashboards._dashboardId-KKL4Xn45.js Adds a new compiled asset.
internal/ui/dist/assets/dashboards._dashboardId-Cd4hot0K.js Removes an old compiled asset.
internal/ui/dist/assets/chat.index-BdqtxCeK.js Adds a new compiled asset.
internal/ui/dist/assets/chat.index-BCfx7LKm.js Removes an old compiled asset.
internal/ui/dist/assets/chat._threadId-CzfhQ5YC.js Removes an old compiled asset.
internal/ui/dist/assets/chat._threadId-BdqtxCeK.js Adds a new compiled asset.
internal/observability/contracts.go Updates comment reference to the new shared TS contract path.
internal/dashboard/service.go Updates server default dashboard layout to match new widget sizes.
internal/dashboard/service_test.go Adds test asserting server default layout matches client widget sizing/validation.
internal/agent/runtime.go Updates system prompt to forbid text diagrams/restating attached views.
internal/agent/runtime_test.go Adds test asserting the new system prompt constraints are present.
docs/superpowers/specs/2026-09-05-logged-in-ui-shell-design.md Adds the UI shell rebuild spec document.
Review details

Suppressed comments (1)

ui/host/src/rail.tsx:48

  • Even after renaming the prop in RailProps, the component still destructures ref and passes it to useImperativeHandle. Update the parameter name and useImperativeHandle call to match the renamed prop (or use a real forwarded ref).
  • Files reviewed: 61/120 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ui/host/src/rail.tsx
Comment thread ui/host/src/shell.tsx
Comment thread ui/host/src/widgets/data.ts

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a few correctness issues in new UI code (notably unguarded async state updates in clipboard copy handlers and non-deterministic thread-group ordering) that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 61/120 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread ui/host/src/chat.tsx Outdated
Comment thread ui/host/src/rail.tsx Outdated
Comment thread ui/host/src/widgets/trace.tsx Outdated
CopyButton in chat.tsx scheduled a bare setTimeout it never held or
cleared, so a second click inside the 1500ms window got cut short by
the first click's reset timer, and nothing was cleared on unmount.
CopyTraceID in trace.tsx already had the right shape (ref-held timer,
cleared on unmount and before rescheduling); extract it into a shared
useCopy hook in copy.ts and have both call sites use it.

Claude-Session: https://claude.ai/code/session_014P9NvJjVkRiJPpdKevKkNE
groupThreads returned sections in whatever order the Map first saw
their labels in, which followed the order threads arrived from the
API rather than a stable most-to-least-recent order. Fix the section
order to Today, Yesterday, Previous 7 days, Older via a module-level
constant, skipping labels with no threads.

Claude-Session: https://claude.ai/code/session_014P9NvJjVkRiJPpdKevKkNE

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change set is very large (new shell + navigation + chat + widget system + dependency/build artifact updates), so it needs final human review despite only minor actionable issues found here.

Review details
  • Files reviewed: 62/121 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread ui/host/src/chat.tsx Outdated
Comment thread ui/host/src/shell.tsx Outdated
rel=noreferrer already implies noopener per the HTML spec, so this changes
no behaviour; the pair is the idiom readers and scanners expect.

Claude-Session: https://claude.ai/code/session_014P9NvJjVkRiJPpdKevKkNE

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A few small but concrete issues remain (Burger aria-label doesn’t reflect open/close state, avatar initial can become empty, and Widget type narrowing forces unsafe casts for unknown widget types).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 62/121 changed files
  • Comments generated: 4
  • Review effort level: Lite

Comment thread ui/host/src/chat.tsx
Comment thread ui/host/src/widgets/widget-card.tsx Outdated
Comment thread ui/host/src/shell.tsx Outdated
Comment thread ui/host/src/shell.tsx Outdated
The header Burger always said "Open navigation" even while the drawer
was open, and AccountMenu's avatar initial fell back to email or "?"
only when name was falsy, so a whitespace-only name won the `||`,
trimmed to empty, and rendered a blank avatar. The Burger now flips its
aria-label with drawerOpened, and the initial is computed from trimmed
candidates so an empty one correctly falls through to the next.

Claude-Session: https://claude.ai/code/session_014P9NvJjVkRiJPpdKevKkNE
Widget.type claimed WidgetType, an exhaustiveness the code never had —
WidgetCard already falls back to UnknownWidget for a type it does not
recognize, and dashboard.tsx needed two `as` casts just to hand it a
record. Widget now aliases DashboardWidgetRecord (type: string, the
truth of what the server can send), and each lookup into a
WidgetType-keyed map goes through a small Object.hasOwn guard instead
of a cast, so the maps themselves stay exhaustive over WidgetType.

Claude-Session: https://claude.ai/code/session_014P9NvJjVkRiJPpdKevKkNE

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change set is a broad UI/UX rebuild spanning routing, layout, widgets, shared contracts, and rebuilt dist artifacts, so it warrants final human review despite strong test coverage.

Review details
  • Files reviewed: 62/121 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@vishr
vishr merged commit b56e462 into main Sep 6, 2026
9 checks passed
@vishr
vishr deleted the ui/shell-rebuild branch September 6, 2026 05:16
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.

2 participants