summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/stats-tab-plan.md147
1 files changed, 147 insertions, 0 deletions
diff --git a/docs/stats-tab-plan.md b/docs/stats-tab-plan.md
new file mode 100644
index 0000000..6b6dcc4
--- /dev/null
+++ b/docs/stats-tab-plan.md
@@ -0,0 +1,147 @@
+# Stats Tab — Implementation Plan
+
+Generated: 2026-03-11
+
+---
+
+## Goal
+
+Add a **Stats** tab to the Claudomator web UI that shows:
+1. Task state distribution (counts by state)
+2. Execution health metrics for the last 24h (total runs, success rate, total cost, avg duration)
+3. A simple visual bar chart of execution outcomes
+
+---
+
+## Data Sources (no backend changes needed)
+
+| Metric | Endpoint | Fields Used |
+|--------|----------|-------------|
+| Task state counts | `GET /api/tasks` | `state` |
+| Execution history | `GET /api/executions?since=24h` | `state`, `cost_usd`, `duration_ms`, `started_at`, `finished_at` |
+
+Both endpoints already exist. No new API endpoints required.
+
+---
+
+## Component Structure
+
+```
+<div data-panel="stats" hidden>
+ <div class="stats-section">
+ <h2>Task Overview</h2>
+ <div class="stats-counts"> <!-- grid: one box per non-zero state -->
+ <div class="stats-count-box" data-state="RUNNING">
+ <span class="stats-count-number">3</span>
+ <span class="stats-count-label">RUNNING</span>
+ </div>
+ ...
+ </div>
+ </div>
+
+ <div class="stats-section">
+ <h2>Executions (Last 24h)</h2>
+ <div class="stats-kpis"> <!-- 4 KPI boxes -->
+ <div class="stats-kpi-box">
+ <span class="stats-kpi-value">42</span>
+ <span class="stats-kpi-label">Total Runs</span>
+ </div>
+ <div class="stats-kpi-box">
+ <span class="stats-kpi-value">88%</span>
+ <span class="stats-kpi-label">Success Rate</span>
+ </div>
+ <div class="stats-kpi-box">
+ <span class="stats-kpi-value">$1.24</span>
+ <span class="stats-kpi-label">Total Cost</span>
+ </div>
+ <div class="stats-kpi-box">
+ <span class="stats-kpi-value">4m 12s</span>
+ <span class="stats-kpi-label">Avg Duration</span>
+ </div>
+ </div>
+ <div class="stats-bar-chart"> <!-- bar chart of outcome distribution -->
+ <!-- one bar per outcome (completed/failed/cancelled/etc.) -->
+ </div>
+ </div>
+</div>
+```
+
+---
+
+## Data Transformation Functions (exported for testing)
+
+### `computeTaskStats(tasks)`
+Input: `Task[]`
+Output:
+```js
+{
+ byState: { PENDING: 2, RUNNING: 1, COMPLETED: 45, ... } // all states present in tasks
+}
+```
+
+### `computeExecutionStats(executions)`
+Input: `RecentExecution[]`
+Output:
+```js
+{
+ total: 42,
+ successRate: 0.88, // fraction (0–1)
+ totalCostUSD: 1.24,
+ avgDurationMs: 252000, // null if no finished executions
+ byOutcome: { completed: 37, failed: 3, cancelled: 2, ... }
+}
+```
+
+---
+
+## Files Changed
+
+| File | Change |
+|------|--------|
+| `web/index.html` | Add Stats tab button + `<div data-panel="stats">` |
+| `web/app.js` | Add `computeTaskStats`, `computeExecutionStats`, `renderStatsPanel`; update `switchTab` and `poll` |
+| `web/style.css` | Add `.stats-*` CSS rules |
+| `web/test/stats.test.mjs` | Unit tests for `computeTaskStats` and `computeExecutionStats` |
+
+---
+
+## Visualization Approach
+
+No external library. Pure CSS:
+- **State count boxes**: small colored badges using existing `--state-*` CSS variables
+- **KPI boxes**: large number + label in a 4-column grid
+- **Bar chart**: flex row of divs with percentage widths, colored per outcome state
+
+---
+
+## Tab Integration
+
+In `switchTab(name)`:
+- When `name === 'stats'`: fetch tasks + recent executions, then call `renderStatsPanel`
+- Hide `#btn-new-task` (same as other non-tasks tabs)
+
+In `poll()`:
+- If stats tab is active: re-render stats after fetching tasks
+
+---
+
+## Tests (TDD — write first, then implement)
+
+`web/test/stats.test.mjs`:
+1. `computeTaskStats` groups tasks by state correctly
+2. `computeTaskStats` returns zero counts for missing states
+3. `computeExecutionStats` calculates total, success rate, cost, avg duration
+4. `computeExecutionStats` handles empty array (zero total, null avg duration)
+5. `computeExecutionStats` calculates success rate = 0 when all failed
+6. `computeExecutionStats` ignores executions with no `duration_ms` in avg calculation
+
+---
+
+## Implementation Order (TDD)
+
+1. Write `web/test/stats.test.mjs` — all tests fail (red)
+2. Add `computeTaskStats` and `computeExecutionStats` to `app.js` — tests pass (green)
+3. Add `renderStatsPanel` and integrate into `switchTab` / `poll`
+4. Add HTML panel to `index.html`
+5. Add CSS to `style.css`
+6. Manual smoke test