dashboard: side-by-side v2 dashboard mirroring ref-impl#398
dashboard: side-by-side v2 dashboard mirroring ref-impl#398arnauorriols wants to merge 19 commits into
Conversation
Mounts at #/v2 with its own tab-strip shell (Overview, Actions, Approvals, Rules, Analytics, Profiles, Devices, Settings). Both dashboards talk to the same backend; v2 is read-only everywhere except the credential modals, which are the existing clawpatrol components reused verbatim. Toggle link in each shell switches between v1 and v2 without editing the URL.
4a1a93c to
bee8e05
Compare
arnauorriols
left a comment
There was a problem hiding this comment.
Take new screenshots after the requested changes in the other comments. Also, try adding data (even if it is synthetic data written directly to the sqlite) so that the screenshots are not the empty state.
| title="switch to v2 dashboard" | ||
| > | ||
| try v2 | ||
| </a> |
There was a problem hiding this comment.
[bot-reply]
Pushed 27d0d9a addressing this comment:
- Removed the "try v2" link (and its surrounding
<a>element) fromwww/src/components/Header.tsx.
| // Gap: unclaw's per-profile workspace (integrations list, | ||
| // default LLM/Human approver pickers, session count) requires | ||
| // profile metadata that clawpatrol's read API doesn't surface. | ||
| // Renders as empty-state. |
There was a problem hiding this comment.
Extend /api/profiles so that it can serve also this page.
| <p> | ||
| The canvas-based dot charts, gridded heatmaps, and LLM cost-over-time panels that | ||
| unclaw's <code className="font-mono text-xs">AnalyticsPage</code> renders would need new | ||
| backend endpoints to power. Out of scope for cl-r3e (no new endpoints). |
There was a problem hiding this comment.
Extend the API to support the latency graph as it is in unclaw. Ignore the llm usage graph and the decisions graph.
There was a problem hiding this comment.
[bot-reply]
Pushed f874b95 addressing this comment:
- Extended
/api/analyticswith adotsfield shaped to match unclaw's per-request projection (t, us, status, host, agent, id) - Ported unclaw's
LatencySectionto the v2AnalyticsPage— log/linear toggle, color-by host/agent/status, dot scatter + binned histogram - LLM usage and decisions graphs intentionally not ported, per your note
…ls (cl-8zh4) /api/profiles now returns []ProfileInfo (name, endpoints[], rule_count, credentials[]) instead of a flat []string. The v2 ProfilesPage renders real per-profile metadata; DevicePage maps .name for its picker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply]
|
Extends /api/analytics with a `dots` field shaped like unclaw's per-request projection (t, us, status, host, agent, id), and ports unclaw's LatencySection — log/linear toggle, color-by host/agent/status, dot scatter + binned histogram — to the v2 AnalyticsPage. LLM and decisions panels intentionally not ported.
|
Take new screenshots. try adding data (even if it is synthetic data written directly to the sqlite) so that the screenshots are not the empty state. |
Reviewer asked for screenshots that aren't the empty state. Captured
against a screenshot-only gateway booted on a fresh sqlite seeded
directly with 8 devices across 4 profiles, 8 coding-agent sessions
(claude / codex with token + ctx counts), 3 connected credentials
(claude / github / notion-oauth), and 480 actions over the last 24h
(allow / deny / approved across http / sql / k8s).
Analytics, Actions, Devices, Profiles, Rules, Settings, and both
Overview pages now render real data. Two pages stay close to empty
state by design:
- Approvals — HITL pending lives in-memory, not in sqlite; the
"Nothing waiting on you" copy is what an operator sees when the
queue is genuinely empty.
- v1 main — per-agent Reqs / Activity is in-memory too. Devices,
profiles, and integrations badges all populate from the seed.
|
[bot-reply]
Two pages stay near the empty state by design, since the data lives in-memory and not in sqlite:
If having Reqs/Activity render synthetically too is wanted, that needs a code change to hydrate |
|
Five UX adjustments raised in the PR review: 1. Approvals tab folded into Actions. Pending HITL requests now appear as butter-toned highlighted rows at the top of the Actions table with inline Approve/Deny buttons. The tab's pending-count badge moves onto the Actions tab; /v2/approvals redirects to /v2/actions for shareable links that pre-date the change. 2. Rule rows expand to show the last five decisions. Each decision is a clickable link into the action detail page. Hung off a new ?rule= filter on /api/analytics and the previously- missing rule/endpoint/approver projections on the same query. 3. Profile credentials get plugin-type icons (postgres logo for postgres_credential, etc.) at a readable 24px, take the full row width, and gain a green border when connected. 4. Devices table drops the integrations column. Per-credential chips live on the Profiles page now, which is the right place to see what a device's profile binds. 5. Rules page filters to one profile at a time via a top-right dropdown. Selection mirrors into the URL hash as ?profile=<name> so a link into a specific profile's rule set is shareable. (cl-atl0) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply]
|
|
The screenshots are not yet good enough:
|
Two of the four items the reviewer flagged on PR #398 — the other two are screenshot recaptures that have to happen against a running dev gateway and aren't tractable from this worktree. 1. dev_seed.go was inserting actions through `endpoint, rule` but skipping `approver`, `approver_type`, `approver_by`. The analytics query returns those columns, so the Approver column on the v2 actions table rendered "—" for every row even when the verdict was "approved" / "denied". Populate the three columns for approved/denied verdicts (human_approver "ops", named reviewer from a small pool), leave NULL otherwise so the non-approve allow/deny rows behave like prod. 2. RulesPage grouped by facet family ("HTTPS", "SSH", "POSTGRES"). Operators reading the page ask "what governs api.github.com?", not "what's in the https family?" — regroup by endpoint name so each card answers that question directly. The endpoint column is dropped from the inner table (the card title carries it), and groups are sorted alphabetically for stable ordering. (cl-u2sf) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply]
Items #2 (pending row highlighted in actions screenshot) and #3 (rule-expansion screenshot) are not in this commit — they're screenshot recaptures against a running gateway, which this worktree can't drive headlessly cleanly. The screenshots commited in ccbbaf4 still need to be regenerated against the now-fixed seed, plus the two new framings you asked for. Flagging for the next pass. Note: I pushed from a temp branch because |
|
Can you please take a new set of screenshots after the changes? |
Two rounds of review changes (nuka's UX adjustments and raider's
seed/regroup) shipped without screenshots that reflect them.
Recaptured against the same dev-seed shape used by nitro (24
devices, 480 actions over 24h, 14 credentials across 5 profiles)
so the new behaviour is visible in the PR thread.
What's different vs the old captures:
- Approvals tab is gone — folded into Actions. The new
v2-02-actions.png shows the pending HITL rows highlighted at
the top of the table with inline Approve/Deny buttons.
Pending-count badge moved onto the Actions tab.
- Rules page regroups by endpoint name (not facet family), and
a profile picker scopes the view. v2-03-rules.png is captured
against profile=ops-team via the new ?profile= hash filter
so all six rule groups are visible.
- Profiles page renders plugin-type credential icons (postgres /
notion / slack / clickhouse logos), full-row width, green
border on connected.
- Devices page drops the integrations column.
- Actions table's Approver column now populates for
approved/denied verdicts — raider's seed fix.
File renames track the new tab order (no more Approvals):
v2-04-rules → v2-03-rules
v2-05-analytics → v2-04-analytics
v2-06-profiles → v2-05-profiles
v2-07-devices → v2-06-devices
v2-08-settings → v2-07-settings
v2-03-approvals → removed
|
[bot-reply] What's reflected in the new captures:
File numbering follows the new tab order (Approvals folded into Actions, so v2-03 is now Rules, v2-04 Analytics, …, v2-07 Settings). |
PR #398 review item #3 asked for "a screenshot showing the expansion of a rule to see the last actions that matched the rule, alongside their verdict". The Rules page has the expansion behaviour wired up (click a row → /api/analytics?range=24h&rule=<name>&limit=5 → render the five most recent matching events), but no captured screenshot demonstrated it — v2-03-rules.png shows the collapsed listing only. Captured against the same dev-seed shape used by earlier rounds (24 devices, 500 actions, 2 profiles, the four-endpoint policy that mirrors what the seeder tags actions with) with the github-reads row expanded. The capture shows: - Rules regrouped by endpoint (cards: ANTHROPIC, GITHUB-API, OPENAI, SLACK) — repeats the #4 grouping change. - github-reads row expanded under GITHUB-API, with five rows of "Last 5 decisions" showing timestamp, device hostname, verdict pill (allow/deny), method, and endpoint + path. - The profile picker scoped to ops-team (top-right). Filename uses the `v2-03b-` prefix so v2-03-rules.png (the all-rules- collapsed view) stays as the canonical Rules screenshot and the expansion is supplemental — two screenshots covering the regrouping and expansion behaviours separately. (cl-u2sf) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply]
Kept the existing Captured against the same dev-seed shape (24 devices, 500 actions over 24h) booted from a screenshot-only gateway with a four-endpoint policy that mirrors what Items #1 (approver column populated), #2 (pending row highlighted in actions), and #4 (group rules by endpoint) were already addressed by aa43849 + 6e3f141 in the earlier rounds. |
PR #398 item #4 second pass. The grouping by endpoint already landed in aa43849, but a rule declared with `endpoints = [a, b, c]` emits one RuleSummary per attachment site, so the same row shows up under each endpoint card with no visual cue that it's the same rule. Operators reading the second card had no signal that editing the rule changes what's enforced on the first. Count distinct endpoints per rule name within the filtered set and render a "shared · N endpoints" chip on the name cell when N > 1. Single-endpoint rules render unchanged. Recaptured v2-03-rules.png against `?profile=ops-team` with a new multi-endpoint rule (`block-debug-methods` across the four https endpoints in the profile) so the chip is visible in the screenshot — the existing single-endpoint rows stay clean. (cl-pdf2) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply] The endpoint regrouping itself already landed in aa43849 — the page bucketed rules by endpoint name and What this commit changes:
No backend change: |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
clawpatrol | ac35edd | Commit Preview URL Branch Preview URL |
May 19 2026, 01:28 PM |
|
In the overview page, I want to see:
I don't want the metrics boxes. |
Replaces the four-up metrics strip + Integrations / Devices /
Pending cards with the three-panel layout requested in the PR
comment:
row 1 (~75% vertical):
[25%] Recent activity — device, profile, verdict, request
[75%] Unconfigured credentials — list with "Connect →" CTA
deep-linking into the Settings tab
row 2 (~25% vertical):
[100%] Pending approvals — first ten with inline "Review →"
jump into the Actions tab
Fallback empty-states per the spec:
Recent activity → Connected devices when every declared
credential is connected (no "needs attention" rows to surface).
Pending approvals → Recent rule verdicts when the HITL queue
is empty.
The panel chrome reuses Card's two-tone header look but is a
local sibling (Panel) because Card's `mb-4` and untensioned body
fight the parent `grid-rows-[3fr_1fr]` height split. Each panel
body is `overflow-auto` so 30+ activity rows don't push the
bottom row off-screen.
Screenshots recaptured against the standard 24-device / 480-
action / 14-credential dev-seed:
docs/screenshots/v2-01-overview.png — primary state
docs/screenshots/v2-01b-overview-no-pending.png — fallback row 2
PR #398 (cl-jg3a)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply] Overview page rebuilt to match the 11:08 spec. Commit: 5216938 — "v2 dashboard: rebuild Overview per PR #398 11:08 spec" What changed The four-up metrics strip and Integrations / Devices / Pending cards are gone. The page now renders the three panels you asked for:
Empty-state fallbacks (per the spec)
Screenshots Both captured against the standard dev-seed (24 devices, 480 actions, 14 credentials across 5 profiles):
Notes
— cl-jg3a (re-attempt of cl-rogp) |
Update the screenshots |
Three review items from arnauorriols on PR #398: 1. Overview row-1 columns swap. The 25% column now holds Unconfigured credentials and the 75% column holds Recent activity / Connected devices. (Old order was credentials at 75% / activity at 25%.) Header comment updated. 2. Profiles page renders each profile's credentials as a row of pills below the endpoint chips — plugin-type logo + bare name, green border when connected, no border when not. Pills are anchors to `#/v2/settings?connect=<id>`; the existing `pendingConnect` plumbing in IntegrationsCards picks the id up and opens the same modal the Settings cards drive (OAuth, Tailscale parked URL, slots-secrets — handled per type by handleConnect, unchanged). Wired pendingConnect through V2App.parseV2Route → V2SettingsPage → IntegrationsCards and drop the query string via window.history.replaceState once consumed so a reload doesn't reopen the modal. 3. Devices page adds an Activity column rendering the existing Sparkline against Agent.activity (same data the v1 main page graphs). Column sits between In/Out and Last seen. Screenshots recaptured against the standard 24-device / 480-action / 14-credential dev-seed (gateway.hcl: /tmp/screenshot-gateway-jg3a.hcl, state_dir + ports rebased onto chrome's worktree): docs/screenshots/v2-01-overview.png — credentials L / activity R / pending bottom docs/screenshots/v2-01b-overview-no-pending.png — same layout, pending → recent verdicts fallback docs/screenshots/v2-05-profiles.png — pills + green-border connected state docs/screenshots/v2-06-devices.png — new Activity column PR #398 (cl-wxqm) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[bot-reply]
|
update the screenshots |
…ntial logos Per @arnauorriols on PR #398 (comment 4478282358): 1. Recent activity now renders one event per row across borderless, headerless columns: timestamp · device · profile · method · status · path · verdict · latency. The old two-line layout wasted vertical space and made scanning across the same field impossible. 2. Unconfigured credentials no longer carries the "needs setup" pill (Connect → button already implies it) and now leads with the credential-type logo via IntegrationIcon, matching the iconography on Profiles / Settings. Both overview screenshots re-captured against the dev-seed shape (24 devices, 480 actions, 14 credentials) used by prior PR #398 rounds.
|
[bot-reply]
|
|
In the profiles page, I don't want to see the endpoints as pills, only the credentials. And I currently don't see the logos of the credentials (however, it might be due to the screenshot being old). The read-only text at the right of the row is redundant, and should be removed. Move the stats of each profile at the same row as the name of the profile, anchored to the right of the row. Take a new screenshot of the profiles page after the changes |
Four review items from @arnauorriols on PR #398 (comment 4478585004), all on the Profiles page: 1. Endpoint pills removed. Profiles used to render endpoint chips below the meta line, before the credential pills. The reviewer wanted only credentials visible at the row level (the endpoint count still appears in the stats summary). Devices already get a standalone Endpoints page; the per-profile chip strip was noise. 2. "read-only" pill removed from the right of each row. The page subhead already says profiles live in gateway.hcl; the per-row tag was redundant. 3. Stats moved onto the profile's name row, right-anchored (`devices · endpoints · rules · credentials`). Previously they occupied their own line under the name, which broke the eye line when scanning down the list. 4. Credential logos already wired through IntegrationIcon — the missing-logo report in the comment was a stale screenshot. Screenshot re-captured against the dev-seed shape (24 devices, 480 actions) the prior PR #398 rounds use. (cl-hrfl)
|
[bot-reply]
|
|
Sync with main, fixing the git conflicts. And replicate the new redentials section of the settings page of v1, into the settings page of v2. |
# Conflicts: # www/src/App.tsx
Replicate the v1 settings page credentials section (per-type cards with expanding details table) in the v2 settings page. The post-merge v2 page was still wired to IntegrationsCards, which no longer accepts pendingConnect / onConsumePendingConnect after the main-side credentials redesign — the type error stopped the build. Preserve the ?connect=<id> deep link from the Profiles page pills by firing onConnect for the deep-linked credential from the V2 settings page itself and immediately clearing the query string.
|
[bot-reply]
Quality gates: |
|
sync with main and fix conflicts |
Main renamed www/ → dashboard/ in #452. The v2 files were the only www/src/ content that survived the merge, but they imported sibling modules via ../lib/api and ../components/* — paths that now live under dashboard/src/. Moving the v2 tree into dashboard/src/v2/ makes dashboard/src/App.tsx's existing `import ... from "./v2/V2App"` resolve and lets `make dashboard` build the bundle (cl-njbp).
|
[bot-reply]
Verified locally: |
|
Address PR #398 review: - Remove "Polecat decisions" comment block from V2App.tsx - Drop local gt path from wg-ephemeral-sessions-design.md - Delete docs/screenshots/ and site/doc/screenshots/pr-231-settings-page/
|
[bot-reply]
|
|
[bot-reply] Extending this PR with #474 — adds a Devices table with per-row Status column to the v2 Overview (cl-cw2i). Based on |
Summary
Adds a v2 dashboard that mounts at
#/v2alongside the existing one. Both dashboards live in the repo simultaneously so the layouts can be compared in-browser; the existing dashboard is unaffected.The v2 layout mirrors ref-impl's dashboard shell — top tab strip, card-based content surface, page header with optional actions. Palette stays in clawpatrol's existing tokens (
canvas/navy/rust) so v2 still feels part of this app.Design choices
#/v2. Hash routing, matches the existing app. The toggle in v1's header links to#/v2; the toggle in v2's shell links to#/.www/src/v2/self-contained, withcards/andpages/subfolders mirroring ref-impl's component organisation. Nothing inwww/src/components/knows about v2 exceptConnectModaland the credential cards, which v2 imports verbatim.IntegrationsCards+ConnectModalverbatim. No reimplementation of ref-impl's credential UX./api/state,/api/rules,/api/profiles,/api/analytics,/api/hitl/pending,/api/actions/:id,/api/config. No new endpoints added.Data-mapping gaps vs ref-impl
ref-impl's data model is richer than clawpatrol's in several places. Rather than extending the backend, these surfaces render empty-state placeholders and the v2 page notes the gap inline:
/api/profilesreturns a flat string list. v2's Profiles page lists the names with a per-profile device count derived from/api/state.AnalyticsPageis a 9-panel canvas dashboard (dot-charts, latency / size heatmaps, status-class-over-time, LLM cost / token streams). clawpatrol's/api/analyticsreturns events + by-host / by-device aggregates. v2 projects those into summary cards; the canvas-dependent panels would need new backend series.Agentkeyed by IP, so the "Awaiting approval" device list is absent./api/actionslist endpoint; v2 taps/api/analytics?range=24hand projectsEventRecordrows. Cost / token telemetry from ref-impl's action detail isn't on the wire.Screenshots
Captured against a minimal screenshot-only gateway config; the live SSE stream is blocked at the proxy layer for v1 capture so headless Chrome completes the page load.
v2 dashboard
docs/screenshots/v2-01-overview.png— Overviewdocs/screenshots/v2-02-actions.png— Actionsdocs/screenshots/v2-03-approvals.png— Approvals (renamed from Pending)docs/screenshots/v2-04-rules.png— Rules (grouped by family)docs/screenshots/v2-05-analytics.png— Analyticsdocs/screenshots/v2-06-profiles.png— Profilesdocs/screenshots/v2-07-devices.png— Devicesdocs/screenshots/v2-08-settings.png— Settings (credential modals + HCL viewer)Existing v1 dashboard, for comparison
docs/screenshots/v1-01-main.png— main (agents + live requests)docs/screenshots/v1-02-analytics.png— analyticsdocs/screenshots/v1-03-settings.png— settingsTest plan
#/, click "TRY V2" in the header, land on#/v2with all eight tabs visible.#/.npm run format:check && npm run lint && npm run buildfromwww/are clean.gofmt -l .andgo test ./...from the repo root are clean.