Skip to content

feat(prd-142): Wave 0 "Is it working?" vitals on Command Centre (US-007)#402

Merged
AutomatosAI merged 2 commits into
mainfrom
feat/prd-142-us007-dashboard-tiles
May 30, 2026
Merged

feat(prd-142): Wave 0 "Is it working?" vitals on Command Centre (US-007)#402
AutomatosAI merged 2 commits into
mainfrom
feat/prd-142-us007-dashboard-tiles

Conversation

@AutomatosAI
Copy link
Copy Markdown
Owner

@AutomatosAI AutomatosAI commented May 30, 2026

Summary

Surfaces the visible half of PRD-142 Wave 0: a five-cell "Is it working?" vitals strip on the live Command Centre (/command-center), consuming the four real measurement endpoints that merged in #400.

Re-target (this revision): the strip was first wired into the /dashboard route, which turned out to be an orphaned/dead page (not in the sidebar, reachable only via stale post-sign-in redirects). This revision moves the vitals onto the live Command Centre and deletes the dead route in the same PR.

What the user sees

/command-center renders two variants by theme/viewport — both now carry the vitals:

  • Studio desktop → new IsItWorkingStrip (the cc-stats strip idiom) rendered directly under the existing StatsStrip in command-center-shell.tsx.
  • Classic / mobile → a second StatsBar vitals row in activity-page.tsx, beneath the operational stats row.

Five cells over real endpoints:

  • ActivationGET /api/analytics/activation
  • Mission success rateGET /api/analytics/dashboard/success-rate (canonical noun Mission)
  • Error rate by subsystemGET /api/analytics/errors/by-subsystem?window=24h
  • Widget engagementGET /api/analytics/widget-engagement?window=7d
  • Per-primitive health (US-006)deferred to Wave 3; renders an explicit "metric pending" / "Not yet measured" placeholder, never a fake green. (Honest gaps over fake greens.)

Implementation

  • lib/api-client.ts — 4 typed getters + response interfaces (kept from the first commit; reused by both strips).
  • hooks/use-analytics-api.ts — 4 react-query hooks (kept).
  • components/command-center/is-it-working-strip.tsx (new) — mirrors StatsStrip exactly (cells, tones, inline Dot, honest "metric pending").
  • components/command-center/command-center-shell.tsx — render <IsItWorkingStrip /> under <StatsStrip />.
  • components/activity/activity-page.tsx — second <StatsBar> of vitals StatItem[], reusing the existing glass-card pattern.

Deletions (dead /dashboard route)

  • app/dashboard/page.tsx + components/dashboard/dashboard.tsx
  • the glass-card components/dashboard/is-it-working.tsx (wrong idiom for Command Centre, superseded)
  • 4 orphaned children imported only by dashboard.tsx: metric-cards, system-health, quick-actions, performance-chart
  • dangling-ref fixes: post-sign-in/up redirect /dashboard/chat (user-profile-button.tsx); drop /dashboard nav-highlight lines in main-layout.tsx and studio-menu.ts
  • net: +201 / −1784

Type-check

tsc --noEmit introduces zero new errors attributable to the changed files (verified: new files/symbols absent from tsc output; deletions leave no "Cannot find module"). The repo carries a large pre-existing baseline unrelated to this change; this PR net-reduces it.

Test plan

  • Railway preview builds clean
  • /command-center (Studio desktop) shows the vitals strip directly under the top StatsStrip
  • /command-center (classic/mobile) shows the second StatsBar vitals row
  • Tiles show real values for an active workspace (activation %, mission success %, error count/24h, widget sessions/7d)
  • Zero-data workspace shows honest empty states ("—" / "no missions yet"), no crash
  • Per-primitive health cell reads "metric pending" / "Not yet measured" (no fake green)
  • Labels use "Mission" (never "Workflow")
  • /dashboard is gone (404); post-sign-in lands on /chat

Summary by CodeRabbit

Release Notes

  • New Features

    • Dashboard now includes "Is it working?" system status metrics displaying activation, mission success, error tracking, and widget engagement indicators.
    • Activity page displays new vital statistics with system health metrics.
    • Command center features new system status strip for quick health monitoring.
  • Changes

    • Home page navigation updated to direct to chat interface.

Review Change Stack

Add the five-tile "Is it working?" strip to the existing System
Dashboard — no new route, no new page. Four tiles read the real Wave 0
endpoints (activation, mission success rate, error rate by subsystem,
widget engagement); the fifth (per-primitive health, US-006) is deferred
to Wave 3 and renders an explicit "not yet measured" placeholder rather
than a fake green.

- api-client: 4 typed getters + response interfaces over request()
- use-analytics-api: 4 react-query hooks
- is-it-working.tsx: new child section reusing the glass-card/motion tile
  pattern; loading + empty + error states, no hardcoded values
- dashboard.tsx: render <IsItWorking /> after <MetricCards />
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

📝 Walkthrough

Walkthrough

This PR implements PRD-142 Wave 0 "Is it working?" dashboard feature by introducing metric API contracts, analytics hooks, and integrating new IsItWorking display components across command-center, activity, and main dashboard pages. It also consolidates the app's navigation architecture to use chat as the primary home route.

Changes

Is it Working Dashboard — PRD-142 Wave 0

Layer / File(s) Summary
API metrics contract and client methods
frontend/lib/api-client.ts
Four new metric interfaces (ActivationMetric, MissionSuccessRateMetric, ErrorsBySubsystemMetric, WidgetEngagementMetric) and corresponding ApiClient methods provide typed contracts for dashboard tile data, with configurable time windows for subsystem errors and widget engagement.
Analytics hooks for dashboard metrics
frontend/hooks/use-analytics-api.ts
Four new React Query hooks (useActivationMetrics, useMissionSuccessRate, useErrorsBySubsystem, useWidgetEngagement) wrap the ApiClient methods and provide cached, typed query results with configurable time-window parameters (24h for errors, 7d for engagement).
IsItWorkingStrip component for command-center
frontend/components/command-center/is-it-working-strip.tsx
New client component that pulls live metrics from analytics hooks, computes display values including worst-subsystem selection via sorting, and renders a five-cell strip (activation, missions, errors, widget, per-primitive health) with tone-driven styling and delta indicators. Includes local Cell interface and Dot helper for tone-colored indicators.
Command-center shell integration
frontend/components/command-center/command-center-shell.tsx
Imports and renders IsItWorkingStrip immediately after StatsStrip in the command-center layout, adding the metric display to the top frame.
Activity page vitals stats section
frontend/components/activity/activity-page.tsx
New vitals section computes activation/mission/error/widget metrics from analytics hooks and renders a separate StatsBar with responsive layout. Includes updated icon imports (Zap, MessageSquare, Boxes) and placeholder "Per-primitive health" stat.
Dashboard layout integration
frontend/components/dashboard/dashboard.tsx
Imports and renders IsItWorking component under "System Status Cards" section, adding the new measurement tile area without altering existing dashboard sections.
Navigation and routing updates
frontend/app/page.tsx, frontend/components/auth/user-profile-button.tsx, frontend/components/layout/main-layout.tsx, frontend/lib/studio-menu.ts
Home page redirects to /chat, UserProfileButton auth redirects default to /chat instead of /dashboard, MainLayout removes explicit /dashboard route handling, and studio-menu resolveActiveMenuId updates routing mappings (/missions/* → "assign", /activity* → "cmd") while removing prior /dashboard* → "cmd" special-case.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • AutomatosAI/automatos-ai#61: Modifies dashboard route handling and navigation consolidation at the dashboard routing level.
  • AutomatosAI/automatos-ai#30: Both PRs touch dashboard page implementation and routing strategy, representing complementary changes to the dashboard experience.

Poem

🐇 A rabbit hops through metrics bright,
Activation, missions, errors in sight,
Five tiles dance on the strip so clean,
Activity and command now in between,
Chat's the new home, a cozy place—
The dashboard finds its rightful place! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing Wave 0 'Is it working?' vitals on the Command Centre, which matches the PR's core objective of adding a five-tile strip with analytics metrics.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/prd-142-us007-dashboard-tiles

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
frontend/lib/api-client.ts (1)

2241-2247: 💤 Low value

Redundant default parameters across client and hook layers.

Both getErrorsBySubsystem and getWidgetEngagement specify default window values ('24h' and '7d'), but the hook layer also provides identical defaults. While this defensive approach is harmless, it creates redundancy. Consider removing defaults from one layer for clarity, or document that the client-layer defaults serve as a safety fallback if the methods are called directly without hooks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/lib/api-client.ts` around lines 2241 - 2247, The client methods
getErrorsBySubsystem and getWidgetEngagement in frontend/lib/api-client.ts
redundantly declare default window values that are already provided by the hook
layer; remove the default parameter values from these two signatures (leave them
as window: string) so the hooks supply the canonical defaults, and ensure any
direct callers pass an explicit window or rely on hook-provided defaults; update
JSDoc/comments to note the client methods are a safety-pass-through without
their own defaults.
frontend/components/dashboard/is-it-working.tsx (1)

91-97: 💤 Low value

Consider removing non-null assertions by restructuring the conditional.

Lines 94 and 96 use non-null assertions (m!) after checking hasMissions. While technically safe, TypeScript should infer non-nullability from the check. Consider restructuring to avoid !:

♻️ Proposed refactor
-  const m = mission.data
-  const hasMissions = !!m && m.total_executions > 0
-  const missionValue = hasMissions ? `${Math.round(m!.value)}%` : '0%'
-  const missionSub = hasMissions
-    ? `${m!.successful_executions}/${m!.total_executions} missions`
-    : 'No missions yet'
+  const hasMissions = !!mission.data && mission.data.total_executions > 0
+  const missionValue = hasMissions ? `${Math.round(mission.data.value)}%` : '0%'
+  const missionSub = hasMissions
+    ? `${mission.data.successful_executions}/${mission.data.total_executions} missions`
+    : 'No missions yet'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/dashboard/is-it-working.tsx` around lines 91 - 97, The
code uses non-null assertions (m!) in missionValue and missionSub after
computing hasMissions; instead restructure to narrow m's type (e.g., compute
with an if (m && m.total_executions > 0) block or use const m = mission.data; if
(m && m.total_executions > 0) { const missionValue = `${Math.round(m.value)}%`;
const missionSub = `${m.successful_executions}/${m.total_executions} missions`;
} else { const missionValue = '0%'; const missionSub = 'No missions yet'; }) so
TypeScript can infer non-nullability and you can remove the m! assertions while
keeping the same logic in missionValue and missionSub (referencing mission, m,
hasMissions, missionValue, missionSub).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@frontend/components/dashboard/is-it-working.tsx`:
- Around line 91-97: The code uses non-null assertions (m!) in missionValue and
missionSub after computing hasMissions; instead restructure to narrow m's type
(e.g., compute with an if (m && m.total_executions > 0) block or use const m =
mission.data; if (m && m.total_executions > 0) { const missionValue =
`${Math.round(m.value)}%`; const missionSub =
`${m.successful_executions}/${m.total_executions} missions`; } else { const
missionValue = '0%'; const missionSub = 'No missions yet'; }) so TypeScript can
infer non-nullability and you can remove the m! assertions while keeping the
same logic in missionValue and missionSub (referencing mission, m, hasMissions,
missionValue, missionSub).

In `@frontend/lib/api-client.ts`:
- Around line 2241-2247: The client methods getErrorsBySubsystem and
getWidgetEngagement in frontend/lib/api-client.ts redundantly declare default
window values that are already provided by the hook layer; remove the default
parameter values from these two signatures (leave them as window: string) so the
hooks supply the canonical defaults, and ensure any direct callers pass an
explicit window or rely on hook-provided defaults; update JSDoc/comments to note
the client methods are a safety-pass-through without their own defaults.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b55042e5-4463-4eaa-81a2-7b530938dbb8

📥 Commits

Reviewing files that changed from the base of the PR and between efb5632 and 78f87d2.

📒 Files selected for processing (4)
  • frontend/components/dashboard/dashboard.tsx
  • frontend/components/dashboard/is-it-working.tsx
  • frontend/hooks/use-analytics-api.ts
  • frontend/lib/api-client.ts

US-007's vitals strip was wired into the orphaned /dashboard route. Move it
to the live Command Centre surface (both variants) and delete the dead route.

- Studio desktop: new IsItWorkingStrip (cc-stats idiom) rendered under
  StatsStrip in command-center-shell
- Classic/mobile: second StatsBar vitals row in ActivityPage
- Delete dead /dashboard route + dashboard.tsx, the glass-card
  is-it-working.tsx, and 4 orphaned children (metric-cards, system-health,
  quick-actions, performance-chart)
- Fix dangling /dashboard refs: post-sign-in/up redirect -> /chat, drop the
  nav-highlight lines in main-layout and studio-menu

Per-primitive health (US-006) stays an honest placeholder, deferred to Wave 3.
@AutomatosAI AutomatosAI changed the title feat(prd-142): Wave 0 "Is it working?" dashboard tiles (US-007) feat(prd-142): Wave 0 "Is it working?" vitals on Command Centre (US-007) May 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/components/activity/activity-page.tsx`:
- Around line 143-198: The vitals cards currently treat failed or loading
queries the same as valid empty data because the hooks (useActivationMetrics,
useMissionSuccessRate, useErrorsBySubsystem, useWidgetEngagement) are only
reading .data; update each hook usage to also read their isLoading/isError flags
and, when isLoading show neutral "Loading metrics…" and when isError show
"Metrics unavailable" in the vitals entries instead of the zero-data strings
(e.g. replace "No workspaces yet", "None · 24h", "No widget activity" with the
new messages); ensure the logic that computes totalWs/activationPct,
missionTotal/missionPct, errorTotal/worstSubsystem, and
widgetSessions/widgetEvents uses the presence of isLoading/isError to choose
those fallback strings and not compute numeric fallbacks when queries are not
ready (you can centralize into a small helper used when building the vitals
array).

In `@frontend/components/command-center/is-it-working-strip.tsx`:
- Around line 30-80: The tiles collapse failed or loading analytics into healthy
zero-state because the component only reads data from useActivationMetrics,
useMissionSuccessRate, useErrorsBySubsystem, and useWidgetEngagement; update the
component to check each hook's readiness (isLoading/isError/isFetching/ready
flags) before deriving totals/percentages and building the cells array, and when
a query is not ready render neutral placeholders like '—' for value and 'metrics
unavailable' or 'loading…' for delta (instead of 0/'none · 24h'/'no
workspaces'), specifically change the logic that computes totalWs/activationPct,
missionTotal/missionPct, errorTotal/worst, sessions/widgetEvents and the
corresponding delta/tone assignments in the cells definition so failed requests
show a neutral tone and copy rather than green/ok or 0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 644a9150-f955-4027-b0a0-a77cc98ed2db

📥 Commits

Reviewing files that changed from the base of the PR and between 78f87d2 and aa5fe23.

📒 Files selected for processing (13)
  • frontend/app/dashboard/page.tsx
  • frontend/app/page.tsx
  • frontend/components/activity/activity-page.tsx
  • frontend/components/auth/user-profile-button.tsx
  • frontend/components/command-center/command-center-shell.tsx
  • frontend/components/command-center/is-it-working-strip.tsx
  • frontend/components/dashboard/dashboard.tsx
  • frontend/components/dashboard/metric-cards.tsx
  • frontend/components/dashboard/performance-chart.tsx
  • frontend/components/dashboard/quick-actions.tsx
  • frontend/components/dashboard/system-health.tsx
  • frontend/components/layout/main-layout.tsx
  • frontend/lib/studio-menu.ts
💤 Files with no reviewable changes (9)
  • frontend/components/dashboard/system-health.tsx
  • frontend/components/dashboard/performance-chart.tsx
  • frontend/components/dashboard/quick-actions.tsx
  • frontend/components/layout/main-layout.tsx
  • frontend/components/dashboard/metric-cards.tsx
  • frontend/app/page.tsx
  • frontend/components/dashboard/dashboard.tsx
  • frontend/lib/studio-menu.ts
  • frontend/app/dashboard/page.tsx

Comment on lines +143 to +198
const { data: activation } = useActivationMetrics()
const { data: mission } = useMissionSuccessRate()
const { data: errors } = useErrorsBySubsystem('24h')
const { data: widget } = useWidgetEngagement('7d')

const totalWs = activation?.total_workspaces ?? 0
const activationPct = totalWs > 0 ? Math.round((activation?.rate ?? 0) * 100) : 0

const missionTotal = mission?.total_executions ?? 0
const missionPct = missionTotal > 0 ? Math.round(mission?.value ?? 0) : 0

const errorTotal = errors?.total ?? 0
const worstSubsystem = errors?.by_subsystem?.length
? [...errors.by_subsystem].sort((a, b) => b.count - a.count)[0]
: null

const widgetSessions = widget?.sessions ?? 0
const widgetEvents = widget?.by_event_type?.reduce((sum, ev) => sum + ev.count, 0) ?? 0

const vitals: StatItem[] = [
{
label: 'Activation',
value: totalWs > 0 ? `${activationPct}%` : '—',
change: totalWs > 0 ? `${activation?.activated ?? 0}/${totalWs} workspaces` : 'No workspaces yet',
icon: Zap,
iconColor: 'text-primary',
},
{
label: 'Mission success rate',
value: missionTotal > 0 ? `${missionPct}%` : '—',
change: missionTotal > 0 ? `${mission?.successful_executions ?? 0}/${missionTotal} missions` : 'No missions yet',
icon: CheckCircle2,
iconColor: 'text-[hsl(var(--success))]',
},
{
label: 'Error rate by subsystem',
value: errorTotal,
change: errorTotal > 0 && worstSubsystem ? `${worstSubsystem.subsystem} (${worstSubsystem.count}) · 24h` : 'None · 24h',
icon: AlertTriangle,
iconColor: errorTotal > 0 ? 'text-destructive' : 'text-[hsl(var(--success))]',
},
{
label: 'Widget engagement',
value: widgetSessions,
change: widgetSessions > 0 ? `${widgetEvents} events · 7d` : 'No widget activity',
icon: MessageSquare,
iconColor: 'text-[hsl(var(--info))]',
},
{
label: 'Per-primitive health',
value: '—',
change: 'Not yet measured',
icon: Boxes,
iconColor: 'text-muted-foreground',
},
]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't present analytics outages as empty-state copy.

These hooks ignore query status, so a backend failure produces the same strings as real empty data (No workspaces yet, None · 24h, No widget activity). That makes the vitals bar look healthy/empty when the source is actually unavailable. Gate the vitals copy on isLoading/isError before falling back to zero-data messaging.

🐛 Sketch of the fix
-  const { data: activation } = useActivationMetrics()
-  const { data: mission } = useMissionSuccessRate()
-  const { data: errors } = useErrorsBySubsystem('24h')
-  const { data: widget } = useWidgetEngagement('7d')
+  const activationQuery = useActivationMetrics()
+  const missionQuery = useMissionSuccessRate()
+  const errorsQuery = useErrorsBySubsystem('24h')
+  const widgetQuery = useWidgetEngagement('7d')
+
+  const { data: activation } = activationQuery
+  const { data: mission } = missionQuery
+  const { data: errors } = errorsQuery
+  const { data: widget } = widgetQuery
+  const metricsUnavailable = [activationQuery, missionQuery, errorsQuery, widgetQuery].some(
+    (query) => query.isError,
+  )

Then render neutral "Loading metrics…" / "Metrics unavailable" copy for the vitals cards instead of the current zero-data strings whenever the queries are not ready.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/activity/activity-page.tsx` around lines 143 - 198, The
vitals cards currently treat failed or loading queries the same as valid empty
data because the hooks (useActivationMetrics, useMissionSuccessRate,
useErrorsBySubsystem, useWidgetEngagement) are only reading .data; update each
hook usage to also read their isLoading/isError flags and, when isLoading show
neutral "Loading metrics…" and when isError show "Metrics unavailable" in the
vitals entries instead of the zero-data strings (e.g. replace "No workspaces
yet", "None · 24h", "No widget activity" with the new messages); ensure the
logic that computes totalWs/activationPct, missionTotal/missionPct,
errorTotal/worstSubsystem, and widgetSessions/widgetEvents uses the presence of
isLoading/isError to choose those fallback strings and not compute numeric
fallbacks when queries are not ready (you can centralize into a small helper
used when building the vitals array).

Comment on lines +30 to +80
const { data: activation } = useActivationMetrics()
const { data: mission } = useMissionSuccessRate()
const { data: errors } = useErrorsBySubsystem('24h')
const { data: widget } = useWidgetEngagement('7d')

const totalWs = activation?.total_workspaces ?? 0
const activationPct = totalWs > 0 ? Math.round((activation?.rate ?? 0) * 100) : 0

const missionTotal = mission?.total_executions ?? 0
const missionPct = missionTotal > 0 ? Math.round(mission?.value ?? 0) : 0

const errorTotal = errors?.total ?? 0
const worst = errors?.by_subsystem?.length
? [...errors.by_subsystem].sort((a, b) => b.count - a.count)[0]
: null

const sessions = widget?.sessions ?? 0
const widgetEvents = widget?.by_event_type?.reduce((sum, ev) => sum + ev.count, 0) ?? 0

const cells: Cell[] = [
{
label: 'ACTIVATION',
value: totalWs > 0 ? `${activationPct}%` : '—',
tone: totalWs > 0 ? 'ok' : 'muted',
delta: totalWs > 0 ? `${activation?.activated ?? 0}/${totalWs} workspaces` : 'no workspaces',
},
{
label: 'MISSIONS',
value: missionTotal > 0 ? `${missionPct}%` : '—',
tone: missionTotal > 0 ? 'ok' : 'muted',
delta: missionTotal > 0
? `${mission?.successful_executions ?? 0}/${missionTotal} ok`
: 'no missions yet',
},
{
label: 'ERRORS',
value: String(errorTotal),
tone: errorTotal > 0 ? 'err' : 'ok',
delta: errorTotal > 0 && worst ? `${worst.subsystem} (${worst.count}) · 24h` : 'none · 24h',
},
{
label: 'WIDGET',
value: String(sessions),
tone: sessions > 0 ? 'info' : 'muted',
delta: sessions > 0 ? `${widgetEvents} events · 7d` : '— · 7d',
},
{
label: 'PRIMITIVES',
value: '—',
tone: 'muted',
delta: 'metric pending',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't collapse failed analytics calls into healthy tiles.

These hooks only read data, so loading/error states fall through to the same copy as real zero-data. The worst case is the ERRORS tile: a failed request renders 0 with ok, which is a false green on an “is it working?” strip. Render an explicit pending/unavailable state before using the current empty-state copy.

🐛 Sketch of the fix
-export function IsItWorkingStrip() {
-  const { data: activation } = useActivationMetrics()
-  const { data: mission } = useMissionSuccessRate()
-  const { data: errors } = useErrorsBySubsystem('24h')
-  const { data: widget } = useWidgetEngagement('7d')
+export function IsItWorkingStrip() {
+  const activationQuery = useActivationMetrics()
+  const missionQuery = useMissionSuccessRate()
+  const errorsQuery = useErrorsBySubsystem('24h')
+  const widgetQuery = useWidgetEngagement('7d')
+
+  const { data: activation } = activationQuery
+  const { data: mission } = missionQuery
+  const { data: errors } = errorsQuery
+  const { data: widget } = widgetQuery
+  const metricsUnavailable = [activationQuery, missionQuery, errorsQuery, widgetQuery].some(
+    (query) => query.isError,
+  )

Then switch each cell to neutral copy such as '—' / 'metrics unavailable' (or 'loading…') when a query is not ready, instead of 0, none · 24h, and no workspaces.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/command-center/is-it-working-strip.tsx` around lines 30 -
80, The tiles collapse failed or loading analytics into healthy zero-state
because the component only reads data from useActivationMetrics,
useMissionSuccessRate, useErrorsBySubsystem, and useWidgetEngagement; update the
component to check each hook's readiness (isLoading/isError/isFetching/ready
flags) before deriving totals/percentages and building the cells array, and when
a query is not ready render neutral placeholders like '—' for value and 'metrics
unavailable' or 'loading…' for delta (instead of 0/'none · 24h'/'no
workspaces'), specifically change the logic that computes totalWs/activationPct,
missionTotal/missionPct, errorTotal/worst, sessions/widgetEvents and the
corresponding delta/tone assignments in the cells definition so failed requests
show a neutral tone and copy rather than green/ok or 0.

@AutomatosAI AutomatosAI merged commit 4b623a3 into main May 30, 2026
2 checks passed
@AutomatosAI AutomatosAI deleted the feat/prd-142-us007-dashboard-tiles branch May 31, 2026 15:45
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