- README: fix tech stack versions (Express 5.2, Tailwind 4.2, Vite 7.3) - SECURITY-AUDIT: update audit date, fix override versions, add minimatch/qs - DOC-FRESHNESS: update freshness header from v2.0.0 to v3.3.3 - ANALYTICS: remove 3 broken links to deleted internal docs - index.html: fix Vite version reference - Add docs audit summary (DOCS-AUDIT-2026-03-02.md)
12 KiB
Analytics API — Parallel Work Stream Visualization
Overview
The Analytics API provides insights into parallel task execution, agent utilization, and performance metrics. It's designed to visualize the temporal dimension of work — showing which tasks ran in parallel, how long each took, and where bottlenecks occurred.
Use Cases
- Parallelism Visualization: See how many tasks ran concurrently over time (Gantt-style)
- Lead Time Analysis: Measure average time from task creation to completion
- Agent Utilization: Track working vs. idle time per agent
- Throughput Metrics: Measure tasks completed per day/week/sprint
- Performance Bottleneck Detection: Identify periods of high or low concurrency
API Endpoints
GET /api/analytics/timeline
Returns timeline data showing task execution periods and parallelism snapshots.
Query Parameters
| Parameter | Type | Optional | Description |
|---|---|---|---|
from |
ISO 8601 datetime | Yes | Start of time range (default: earliest task time entry) |
to |
ISO 8601 datetime | Yes | End of time range (default: latest task time entry) |
agent |
string | Yes | Filter by agent type (e.g., "claude-code", "amp") |
project |
string | Yes | Filter by project ID/name |
sprint |
string | Yes | Filter by sprint ID/name |
Example Request
curl -X GET "http://localhost:3001/api/analytics/timeline?from=2026-01-01T00:00:00Z&to=2026-02-01T23:59:59Z&project=veritas"
Response Schema
{
"success": true,
"data": {
"period": {
"from": "2026-01-01T10:30:00Z",
"to": "2026-01-01T15:45:00Z"
},
"tasks": [
{
"id": "task_20260101_abc123",
"title": "Build analytics service",
"project": "veritas",
"sprint": "v1.5",
"agent": "claude-code",
"status": "done",
"startTime": "2026-01-01T10:30:00Z",
"endTime": "2026-01-01T11:45:00Z",
"durationSeconds": 4500,
"timeEntries": [
{
"id": "entry_1",
"startTime": "2026-01-01T10:30:00Z",
"endTime": "2026-01-01T10:45:00Z",
"duration": 900,
"description": "Initial setup"
}
]
}
],
"parallelism": [
{
"timestamp": "2026-01-01T10:30:00Z",
"concurrentTaskCount": 2,
"taskIds": ["task_20260101_abc123", "task_20260101_def456"]
},
{
"timestamp": "2026-01-01T11:00:00Z",
"concurrentTaskCount": 1,
"taskIds": ["task_20260101_abc123"]
}
],
"summary": {
"totalTasks": 1,
"maxConcurrency": 2,
"averageConcurrency": 1.5,
"timelineStartTime": "2026-01-01T10:30:00Z",
"timelineEndTime": "2026-01-01T15:45:00Z"
}
}
}
GET /api/analytics/metrics
Returns aggregate metrics for a time period or sprint.
Query Parameters
| Parameter | Type | Optional | Description |
|---|---|---|---|
sprint |
string | Yes | Filter by sprint ID/name |
from |
ISO 8601 datetime | Yes | Start of time range |
to |
ISO 8601 datetime | Yes | End of time range |
project |
string | Yes | Filter by project ID/name |
Note: If neither from nor to are provided, defaults to the last 30 days.
Example Request
curl -X GET "http://localhost:3001/api/analytics/metrics?sprint=v1.5"
Response Schema
{
"success": true,
"data": {
"period": {
"from": "2026-01-01T00:00:00Z",
"to": "2026-02-01T00:00:00Z",
"sprint": "v1.5"
},
"parallelism": {
"averageConcurrency": 3.2,
"maxConcurrency": 7,
"minConcurrency": 0
},
"throughput": {
"tasksCompleted": 42,
"tasksCreated": 45,
"averageCompletionTime": 86400
},
"leadTime": {
"fromTodoToDone": 172800,
"fromCreatedToStarted": 3600,
"fromStartedToDone": 169200
},
"agentUtilization": [
{
"agent": "claude-code",
"startTime": "2026-01-01T08:00:00Z",
"endTime": "2026-01-31T22:00:00Z",
"durationSeconds": 2592000,
"tasksCompleted": 28,
"totalTaskDurationSeconds": 2592000
}
],
"efficiency": {
"totalTrackedTime": 3628800,
"totalTaskCount": 42,
"averageTimePerTask": 86400,
"utilizationRate": 0.75
}
}
}
Data Models
TimelineResponse
Timeline visualization data with task execution periods and parallelism information.
interface TimelineResponse {
period: {
from: string; // ISO 8601 start time
to: string; // ISO 8601 end time
};
tasks: TaskTimeline[];
parallelism: ParallelismSnapshot[];
summary: {
totalTasks: number;
maxConcurrency: number;
averageConcurrency: number;
timelineStartTime?: string;
timelineEndTime?: string;
};
}
TaskTimeline
Task execution data extracted from time tracking.
interface TaskTimeline {
id: string;
title: string;
project?: string;
sprint?: string;
agent?: string;
status: string;
startTime?: string; // ISO 8601 of first time entry
endTime?: string; // ISO 8601 of last time entry
durationSeconds: number; // Total tracked time
timeEntries: {
id: string;
startTime: string; // ISO 8601
endTime?: string; // ISO 8601 (undefined if timer running)
duration?: number; // Seconds
description?: string;
}[];
}
ParallelismSnapshot
Point-in-time snapshot of concurrent task execution.
interface ParallelismSnapshot {
timestamp: string; // ISO 8601 timestamp
concurrentTaskCount: number; // Number of concurrent tasks
taskIds: string[]; // IDs of active tasks
}
MetricsResponse
Aggregate metrics for a time period.
interface MetricsResponse {
period: {
from: string;
to: string;
sprint?: string;
};
parallelism: {
averageConcurrency: number;
maxConcurrency: number;
minConcurrency: number;
};
throughput: {
tasksCompleted: number;
tasksCreated: number;
averageCompletionTime: number; // seconds
};
leadTime: {
fromTodoToDone: number; // seconds (average)
fromCreatedToStarted: number; // seconds (average)
fromStartedToDone: number; // seconds (average)
};
agentUtilization: AgentPeriod[];
efficiency: {
totalTrackedTime: number; // seconds
totalTaskCount: number;
averageTimePerTask: number; // seconds
utilizationRate: number; // 0-1 ratio
};
}
AgentPeriod
Agent activity breakdown.
interface AgentPeriod {
agent: string;
startTime: string; // ISO 8601
endTime: string; // ISO 8601
durationSeconds: number;
tasksCompleted: number;
totalTaskDurationSeconds: number;
}
Key Metrics Explained
Parallelism
- Average Concurrency: Mean number of tasks running simultaneously
- Max Concurrency: Peak number of concurrent tasks
- Min Concurrency: Minimum concurrent tasks (often 0 during idle periods)
Use: Identify if work is truly parallel or sequential. High parallelism suggests distributed execution; low parallelism suggests bottlenecks.
Throughput
- Tasks Completed: Number of done tasks in the period
- Tasks Created: Number of new tasks created in the period
- Average Completion Time: Mean time from creation to done
Use: Track productivity and capacity over time.
Lead Time
- From Todo to Done: Total time from creation to completion (includes all work states)
- From Created to Started: Time before work begins (waiting for resources/assignment)
- From Started to Done: Time spent actively working
Use: Understand where delays occur (waiting vs. execution).
Agent Utilization
- Working Time: Total time tasks assigned to an agent were being tracked
- Tasks Completed: Number of time entries per agent
- Idle Time: (period duration - working time) — inferred from gaps
Use: Load balance across agents; identify over/under-utilized resources.
Efficiency
- Utilization Rate: (Total tracked time) / (Period duration)
- 0.75 = 75% of the period was active work
- Complementary idle rate = 25%
- Average Time Per Task: (Total tracked time) / (Number of tasks)
Use: Assess productivity and identify tasks that take longer than expected.
Technical Implementation
Service Layer
AnalyticsService (server/src/services/analytics-service.ts)
Core service that aggregates data and computes metrics.
Key methods:
getTimeline(query): Returns timeline visualization datagetMetrics(query): Returns aggregate metricscalculateParallelism(): Detects overlapping task periodscalculateAgentUtilization(): Breaks down working time by agent
Data Sources
The service reads from:
- Task Time Tracking:
Task.timeTracking.entries[]— individual time entries with start/end times - Task Metadata:
Task.project,Task.sprint,Task.agent,Task.status
Note: Status history transitions could be used in the future to compute more precise lead time metrics (e.g., "time spent in in-progress state").
Performance Considerations
- Parallelism Sampling: Samples at 5-minute intervals for efficiency (avoids O(n²) time point analysis)
- Time Window Defaults: If no range provided, derives from earliest/latest time entries
- Filtering: Applied before metric calculation to reduce data volume
- Caching: None yet; consider caching results for historical periods
Usage Examples
Example 1: Visualize Last Week's Parallelism
FROM=$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)
TO=$(date -u +%Y-%m-%dT%H:%M:%SZ)
curl -s "http://localhost:3001/api/analytics/timeline?from=$FROM&to=$TO" | \
jq '.data.parallelism | max_by(.concurrentTaskCount)'
Example 2: Get Sprint Metrics
curl -s "http://localhost:3001/api/analytics/metrics?sprint=v1.5" | \
jq '.data.efficiency'
Example 3: Agent Comparison
curl -s "http://localhost:3001/api/analytics/metrics?from=2026-01-01T00:00:00Z&to=2026-02-01T00:00:00Z" | \
jq '.data.agentUtilization | sort_by(.durationSeconds) | reverse'
Future Enhancements
- Status History Integration: Use status transitions for more precise lead time calculations
- Caching: Cache historical metrics (periods that don't change)
- Comparison Reports: Compare metrics across sprints/agents
- Anomaly Detection: Flag unusual patterns (e.g., zero concurrency for extended periods)
- Cost Analysis: Integrate with token/cost metrics for ROI calculations
- Predictive Analytics: Estimate completion dates based on historical throughput
- Visualization UI: Build a Gantt chart view in the web dashboard
- Real-time Updates: WebSocket support for live metrics
Troubleshooting
Empty Timeline
- Cause: No time entries recorded for the period
- Solution: Ensure tasks have time tracking started/stopped
- Check
GET /api/tasksfortimeTracking.entries[]
Zero Utilization Rate
- Cause: Period window contains no tracked time
- Solution: Expand the date range or check task statuses
High Average Concurrency but Few Tasks
- Cause: Tasks have overlapping time entries (manual entries or long-running timers)
- Solution: Check individual
timeEntriesin timeline response to verify
API Design Notes
Why ISO 8601?
- Timezone-aware (always UTC with 'Z' suffix)
- Sortable as strings
- Standard web format (supported by all major languages)
Why Sample Parallelism?
- Computing exact parallelism at every microsecond is inefficient
- 5-minute sampling provides sufficient granularity for visualization
- Can be made configurable in future versions
Why Separate Timeline and Metrics Endpoints?
- Timeline is detail-oriented (suitable for visualization)
- Metrics are summary-oriented (suitable for dashboards)
- Different caching strategies (timeline: short-lived, metrics: long-lived)
See Also: