anima-pwa: dashboard stats from DashboardService, not mock-fallback list APIs #276

Merged
toasterson merged 1 commit from fix/pwa-dashboard-real-aggregates into main 2026-06-29 19:59:13 +00:00
Owner

Problem

The Dashboard showed 18k active sessions and 2 pending decisions against the live backend — both fake:

  • Active Sessions = listSessions().length — returns all agent_sessions with no status filter, so it counted ~18,498 historical failed rows (runaway-incident era) as "active".
  • Pending Decisions = listDecisions().length, and listDecisions() with no projectId silently falls back to the mock (the || !projectId branch) → 2 hardcoded fixtures.
  • Active Work Slices = listSlices() — same no-projectId mock fallback → the whole section and its "N active sessions" were fixtures, contradicting the real "0".

Fix

All three now come from DashboardService.getDashboard, which already computes them server-side — cross-project, status-filtered, and (post #275) excluding external_pr bookkeeping. activeSessions sums the per-project provisioning/running counts; slices map the real activeSlices. getDashboardSummary folds these out of the single getDashboard response the page already fetched, so it removes a call rather than adding one.

listActivity() / listProjects() were already safe (mock only when !useGrpc).

Verified live (dev server → prod)

Pending Decisions 0, Active Sessions 0, Total Projects 13, and Active Work Slices now show real Anima slices with consistent 0 active sessions. npm run verify green (89 tests).

Frontend-only; no backend change.

🤖 Generated with Claude Code

## Problem The Dashboard showed **18k active sessions** and **2 pending decisions** against the live backend — both fake: - **Active Sessions** = `listSessions().length` — returns *all* `agent_sessions` with no status filter, so it counted ~18,498 historical `failed` rows (runaway-incident era) as "active". - **Pending Decisions** = `listDecisions().length`, and `listDecisions()` with no `projectId` **silently falls back to the mock** (the `|| !projectId` branch) → 2 hardcoded fixtures. - **Active Work Slices** = `listSlices()` — same no-`projectId` mock fallback → the whole section and its "N active sessions" were fixtures, contradicting the real "0". ## Fix All three now come from `DashboardService.getDashboard`, which already computes them server-side — cross-project, status-filtered, and (post [#275](https://code.aopc.cloud/toasterson/Anima/pulls/275)) excluding `external_pr` bookkeeping. `activeSessions` sums the per-project provisioning/running counts; `slices` map the real `activeSlices`. `getDashboardSummary` folds these out of the single `getDashboard` response the page already fetched, so it *removes* a call rather than adding one. `listActivity()` / `listProjects()` were already safe (mock only when `!useGrpc`). ## Verified live (dev server → prod) Pending Decisions **0**, Active Sessions **0**, Total Projects 13, and Active Work Slices now show real Anima slices with consistent `0 active sessions`. `npm run verify` green (89 tests). Frontend-only; no backend change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The Dashboard derived its three stat cards and the Active Work Slices
section from per-resource list calls that returned the wrong data against
a real backend:

- "Active Sessions" = listSessions().length, which returns ALL agent_sessions
  with no status filter → counted ~18k historical `failed` rows as active.
- "Pending Decisions" = listDecisions().length, and listDecisions() with no
  projectId silently FALLS BACK TO THE MOCK (the `|| !projectId` branch) →
  showed 2 hardcoded fixtures.
- "Active Work Slices" = listSlices(), same no-projectId mock fallback →
  the whole section + its "N active sessions" were fixtures, contradicting
  the real counts.

All three now come from DashboardService.getDashboard, which already
computes them server-side: cross-project, status-filtered, and (post
PR #275) excluding external_pr bookkeeping. activeSessions sums the
per-project provisioning/running counts; slices map the real activeSlices.
getDashboardSummary folds these out of the single getDashboard response
the page already fetched, so it removes a call rather than adding one.

listActivity()/listProjects() were already safe (mock only when !useGrpc).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
toasterson deleted branch fix/pwa-dashboard-real-aggregates 2026-06-29 19:59:14 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
toasterson/Anima!276
No description provided.