---
phase: 03-operator-experience
plan: 04
type: execute
wave: 2
depends_on: ["03-01"]
files_modified:
  - packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx
  - packages/portal/components/usage-chart.tsx
  - packages/portal/components/provider-cost-chart.tsx
  - packages/portal/components/budget-alert-badge.tsx
  - packages/portal/components/message-volume-chart.tsx
  - packages/portal/lib/queries.ts
autonomous: false
requirements:
  - AGNT-07
  - PRTA-06

must_haves:
  truths:
    - "Operator can see token usage per agent in a chart"
    - "Operator can see cost breakdown by LLM provider"
    - "Operator can see message volume per channel"
    - "Operator can filter usage data by time range"
    - "Budget alerts are visible when an agent approaches or exceeds its budget limit"
    - "Dashboard answers 'how much is this employee costing me?' at a glance"
  artifacts:
    - path: "packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx"
      provides: "Cost tracking and usage metrics dashboard page"
    - path: "packages/portal/components/usage-chart.tsx"
      provides: "Bar chart of token usage per agent (Recharts)"
    - path: "packages/portal/components/provider-cost-chart.tsx"
      provides: "Pie or bar chart of cost breakdown by LLM provider (Recharts)"
    - path: "packages/portal/components/budget-alert-badge.tsx"
      provides: "Colored badge showing budget status (ok/warning/exceeded)"
    - path: "packages/portal/components/message-volume-chart.tsx"
      provides: "Bar chart of message volume per channel (Recharts)"
  key_links:
    - from: "packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx"
      to: "/api/portal/usage/{tenantId}/summary"
      via: "TanStack Query hook fetching usage data"
      pattern: "usage.*summary"
    - from: "packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx"
      to: "/api/portal/usage/{tenantId}/budget-alerts"
      via: "TanStack Query hook fetching budget alert statuses"
      pattern: "usage.*budget-alerts"
    - from: "packages/portal/components/usage-chart.tsx"
      to: "recharts"
      via: "BarChart, ResponsiveContainer components"
      pattern: "import.*recharts"
---

<objective>
Cost tracking dashboard with per-agent token usage, provider cost breakdown, message volume, time range filtering, and budget alert indicators.

Purpose: Operators can see "how much is this employee costing me?" at a glance -- like a payroll view. Budget alerts warn when agents approach or exceed their configured limits.
Output: Usage dashboard page with Recharts visualizations, budget alert badges, and time range selector.
</objective>

<execution_context>
@/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md
@/home/adelorenzo/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/03-operator-experience/03-CONTEXT.md
@.planning/phases/03-operator-experience/03-RESEARCH.md
@.planning/phases/03-operator-experience/03-01-SUMMARY.md

<interfaces>
<!-- From Plan 01 backend APIs -->

From packages/shared/shared/api/usage.py (created in Plan 01):
```python
# GET /api/portal/usage/{tenant_id}/summary?start_date={}&end_date={}
# Returns: [{ agent_id, agent_name, prompt_tokens, completion_tokens, total_tokens, cost_usd, llm_call_count }]

# GET /api/portal/usage/{tenant_id}/by-provider?start_date={}&end_date={}
# Returns: [{ provider, cost_usd, call_count }]

# GET /api/portal/usage/{tenant_id}/message-volume?start_date={}&end_date={}
# Returns: [{ channel, message_count }]

# GET /api/portal/usage/{tenant_id}/budget-alerts
# Returns: [{ agent_id, agent_name, budget_limit_usd, current_cost_usd, status: "ok"|"warning"|"exceeded" }]
```

Established portal patterns:
- shadcn/ui components (Card, Badge, Select)
- TanStack Query for data fetching
- Recharts installed in Plan 01 (npm install recharts)
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Cost dashboard page with Recharts visualizations and budget alerts</name>
  <files>
    packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx,
    packages/portal/components/usage-chart.tsx,
    packages/portal/components/provider-cost-chart.tsx,
    packages/portal/components/message-volume-chart.tsx,
    packages/portal/components/budget-alert-badge.tsx,
    packages/portal/lib/queries.ts
  </files>
  <action>
    1. Create `packages/portal/components/budget-alert-badge.tsx`:
       - Colored badge based on status:
         - "ok" -> green (or no badge if usage is low)
         - "warning" -> amber with "80%+ budget used" text
         - "exceeded" -> red with "Budget exceeded" text
       - Null budget_limit_usd -> gray "No limit set" text (not a warning)
       - Uses shadcn/ui Badge

    2. Create `packages/portal/components/usage-chart.tsx`:
       - Recharts BarChart showing total_tokens per agent
       - ResponsiveContainer for adaptive sizing
       - XAxis: agent name, YAxis: token count
       - Tooltip showing prompt_tokens, completion_tokens, total_tokens, cost_usd
       - Color: indigo-500 (#6366f1) for consistency
       - Handles empty state: "No usage data for this period" message

    3. Create `packages/portal/components/provider-cost-chart.tsx`:
       - Recharts BarChart (horizontal) showing cost_usd per provider
       - Each provider gets a distinct color (openai=green, anthropic=orange, ollama=blue)
       - Tooltip: provider name, cost, call count
       - Handles empty state

    4. Create `packages/portal/components/message-volume-chart.tsx`:
       - Recharts BarChart showing message_count per channel (slack, whatsapp)
       - Channel-specific colors (slack=purple, whatsapp=green)
       - Handles empty state

    5. Create `packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx`:
       - Time range selector at top: simple <select> with options: "Last 7 days", "Last 30 days", "This month", "Last 3 months". Default: "Last 30 days". Drives start_date/end_date query params.
       - Layout (responsive grid, 1 col mobile, 2 cols desktop):
         - **Top row:** Summary cards — total cost, total tokens, total messages (large numbers, shadcn Card)
         - **Row 2 left:** UsageChart (tokens per agent)
         - **Row 2 right:** ProviderCostChart (cost by provider)
         - **Row 3 left:** MessageVolumeChart (messages by channel)
         - **Row 3 right:** Budget Alerts table — list each agent with BudgetAlertBadge, current cost, limit. Only show agents that have a budget_limit_usd set.
       - All data fetched via TanStack Query hooks with start_date/end_date params
       - Loading skeletons while data loads
       - Per user decision: this should feel like a "payroll view" — answer "how much is this employee costing me?" at a glance

    6. Add TanStack Query hooks to `packages/portal/lib/queries.ts`:
       - useUsageSummary(tenantId, startDate, endDate)
       - useUsageByProvider(tenantId, startDate, endDate)
       - useMessageVolume(tenantId, startDate, endDate)
       - useBudgetAlerts(tenantId)

    7. Add "Usage" link to dashboard navigation/sidebar, linking to /usage/{tenantId}.
  </action>
  <verify>
    <automated>cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20</automated>
  </verify>
  <done>
    - Usage page renders with time range selector defaulting to "Last 30 days"
    - Token usage bar chart renders per agent (or empty state)
    - Provider cost chart renders per provider
    - Message volume chart renders per channel
    - Budget alert badges show correct colors (ok/warning/exceeded)
    - Summary cards show totals at the top
    - Responsive layout works on mobile and desktop
    - Portal builds without errors
  </done>
</task>

<task type="checkpoint:human-verify" gate="blocking">
  <name>Task 2: Verify cost dashboard and budget alerts</name>
  <files>n/a</files>
  <action>
    Human verifies the cost tracking dashboard:
    1. Start the portal: `cd packages/portal && npm run dev`
    2. Navigate to /usage/{tenantId} — verify dashboard renders
    3. Verify time range selector shows options (Last 7 days, Last 30 days, This month, Last 3 months)
    4. Verify chart areas render (may show empty state if no audit data)
    5. Verify budget alerts section is visible
    6. Verify summary cards at top show totals
    7. Verify responsive layout (resize browser to mobile width)
    8. Verify "Usage" link in dashboard navigation
    9. Confirm it feels like a "payroll view" — quick answer to "how much is this employee costing me?"
  </action>
  <verify>Human visual inspection of cost dashboard</verify>
  <done>Operator confirms cost dashboard renders with charts, budget alerts, and time range selector</done>
</task>

</tasks>

<verification>
- Portal builds: `cd packages/portal && npx next build`
- Usage page accessible at /usage/{tenantId}
- Charts render with Recharts (or show empty state gracefully)
- Budget alerts display with correct color coding
- Time range selector changes data display
</verification>

<success_criteria>
- Operator sees token usage per agent in a bar chart
- Operator sees cost breakdown by LLM provider
- Operator sees message volume per channel
- Time range selector filters displayed data
- Budget alerts show amber at 80%, red at 100%+ of configured limit
- Dashboard layout is clean and answers "what is this costing me?" at a glance
- Portal builds successfully
</success_criteria>

<output>
After completion, create `.planning/phases/03-operator-experience/03-04-SUMMARY.md`
</output>
