askill
metrics-dashboard

metrics-dashboardSafety 90Repository

Tracks pipeline velocity, success rates, and cycle times. Use to view performance metrics, identify bottlenecks, and generate reports.

1 stars
1.2k downloads
Updated 2/8/2026

Package Files

Loading files...
SKILL.md

Metrics Dashboard

Aggregates pipeline run data to track velocity, success rates, and identify improvement areas.

Configuration

Uses the production API by default. No configuration needed for read operations.

Defaults (no setup required):

  • API URL: https://api-gateway-856475788601.us-central1.run.app
  • Read-only endpoints at /public/* require no authentication

For write operations, set:

export PIPELINE_API_KEY="..."  # Get from GCP Secret Manager or ask admin

Workflow

1. Fetch Ticket Data from API

import { PipelineClient, PipelineAPIError } from '@pipeline/client'

const client = new PipelineClient({
  apiUrl: process.env.PIPELINE_API_URL || 'https://api-gateway-856475788601.us-central1.run.app',
  agentId: process.env.AGENT_ID!,
})

// Fetch all tickets for metrics calculation
const { tickets, total } = await client.listTickets({
  limit: 1000,
})

// Filter by state if needed
const { tickets: completedTickets } = await client.listTickets({
  state: 'done',
  limit: 1000,
})

// Filter by agent
const { tickets: myTickets } = await client.listTickets({
  agent_id: process.env.AGENT_ID,
})

2. Calculate Metrics

interface TicketMetrics {
  total: number
  completed: number
  failed: number
  inProgress: number
  successRate: number
  avgCycleTimeHours: number
  minCycleTimeHours: number
  maxCycleTimeHours: number
}

function calculateMetrics(tickets: Ticket[]): TicketMetrics {
  const completed = tickets.filter((t) => t.state === 'done')
  const failed = tickets.filter((t) => t.state === 'failed')
  const inProgress = tickets.filter((t) =>
    ['intake', 'research', 'planning', 'implementation', 'pr_created'].includes(t.state)
  )

  // Calculate cycle times from timestamps
  const cycleTimes = completed
    .filter((t) => t.created_at && t.state_changed_at)
    .map((t) => {
      const start = new Date(t.created_at).getTime()
      const end = new Date(t.state_changed_at).getTime()
      return (end - start) / (1000 * 60 * 60) // hours
    })

  const avgCycleTime = cycleTimes.length > 0 ? cycleTimes.reduce((a, b) => a + b, 0) / cycleTimes.length : 0

  return {
    total: tickets.length,
    completed: completed.length,
    failed: failed.length,
    inProgress: inProgress.length,
    successRate:
      completed.length + failed.length > 0 ? (completed.length / (completed.length + failed.length)) * 100 : 0,
    avgCycleTimeHours: avgCycleTime,
    minCycleTimeHours: cycleTimes.length > 0 ? Math.min(...cycleTimes) : 0,
    maxCycleTimeHours: cycleTimes.length > 0 ? Math.max(...cycleTimes) : 0,
  }
}

const metrics = calculateMetrics(tickets)

3. Generate Dashboard

# Pipeline Metrics Dashboard

**Period:** Last 30 days | **Generated:** {timestamp}

## Summary

| Metric            | Value   | Trend      |
| ----------------- | ------- | ---------- |
| Tickets Completed | 12      | ↑ +3       |
| Success Rate      | 83%     | ↑ +5%      |
| Avg Cycle Time    | 2.5 hrs | ↓ -0.5 hrs |

## Cycle Time Breakdown

Intake ████ 5 min | Research ████████ 15 min | Planning ██████ 10 min
Implement █████████████ 25 min | Quality ████ 8 min | Review ██████ 12 min

## Success by Type

| Type     | Count | Success | Avg Time |
| -------- | ----- | ------- | -------- |
| Bug Fix  | 5     | 100%    | 1.2 hrs  |
| Feature  | 4     | 75%     | 3.5 hrs  |
| Refactor | 3     | 67%     | 2.8 hrs  |

## Failure Analysis

| Failure Point    | Count | %   |
| ---------------- | ----- | --- |
| Quality gates    | 2     | 40% |
| CI failures      | 1     | 20% |
| Review rejection | 1     | 20% |

## Recommendations

1. **Reduce implementation time** - Consider more parallel subagents
2. **Improve quality gates** - 40% of failures at this stage

4. Save Dashboard Locally

import { writeFileSync, appendFileSync } from 'fs'

// Save markdown dashboard
writeFileSync('metrics-dashboard.md', dashboardMarkdown)

// Save JSON summary
const summary = {
  generatedAt: new Date().toISOString(),
  period: '30d',
  ...metrics,
}
writeFileSync('metrics-summary.json', JSON.stringify(summary, null, 2))

// Append to history
appendFileSync(
  'metrics-history.jsonl',
  JSON.stringify({
    date: new Date().toISOString().split('T')[0],
    metrics: summary,
  }) + '\n'
)

5. Error Handling

try {
  const { tickets } = await client.listTickets({ limit: 1000 })
  const metrics = calculateMetrics(tickets)
} catch (error) {
  if (error instanceof PipelineAPIError) {
    console.error(`API error: ${error.message} (status: ${error.status})`)
  }
  throw error
}

Custom Queries

// Tickets by agent
const ticketsByAgent = tickets.reduce(
  (acc, t) => {
    const agent = t.agent_id ?? 'unassigned'
    acc[agent] = (acc[agent] ?? 0) + 1
    return acc
  },
  {} as Record<string, number>
)

// Slowest tickets
const slowestTickets = tickets
  .filter((t) => t.created_at && t.state_changed_at)
  .map((t) => ({
    id: t.id,
    title: t.title,
    cycleTime: (new Date(t.state_changed_at!).getTime() - new Date(t.created_at).getTime()) / (1000 * 60 * 60),
  }))
  .sort((a, b) => b.cycleTime - a.cycleTime)
  .slice(0, 5)

// Failed tickets by last state
const failedByState = tickets
  .filter((t) => t.state === 'failed')
  .reduce(
    (acc, t) => {
      const phase = t.previous_state ?? 'unknown'
      acc[phase] = (acc[phase] ?? 0) + 1
      return acc
    },
    {} as Record<string, number>
  )

Output Artifacts (Local)

FileDescription
metrics-dashboard.mdPoint-in-time dashboard
metrics-summary.jsonLatest metrics JSON
metrics-history.jsonlHistorical trends

Notes

  • Metrics are calculated client-side from ticket data fetched via API
  • Allows flexible aggregation across all agents in the distributed pipeline
  • Historical trends require local storage of metrics-history.jsonl

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

68/100Analyzed 2/19/2026

Well-structured technical skill with clear workflow and TypeScript code examples. Provides comprehensive metrics calculation logic and dashboard generation. However, strongly tied to specific internal infrastructure (hardcoded API URL, custom @pipeline/client package) which limits reusability beyond the christian-byrne/ticket-to-pr-pipeline project. Has good safety practices and clear documentation structure.

90
88
45
82
85

Metadata

Licenseunknown
Version-
Updated2/8/2026
Publisherchristian-byrne

Tags

apici-cdgithub-actionsobservabilitysecurity