Claude
Skills
Sign in
Back

design-jira-state-analyzer

Included with Lifetime
$97 forever

Designs and implements state transition analysis systems for tracking time spent in different states. Use when analyzing workflows with state changes (Jira, GitHub PRs, deployments, support tickets, etc.). Covers state machine fundamentals, temporal calculations, bottleneck detection, and business metrics. Trigger keywords: "state analysis", "duration tracking", "workflow metrics", "bottleneck", "cycle time", "state transitions", "time in status", "how long", "state duration", "workflow performance", "state machine", "changelog analysis", "SLA tracking", "process metrics".

Design

What this skill does


# Design Jira State Analyzer

## When to Use This Skill

**Explicit Triggers:**
- "Analyze state transitions in Jira"
- "Calculate time spent in each status"
- "Find workflow bottlenecks"
- "Track cycle time for tickets"
- "Measure how long tickets stay in review"
- "Analyze workflow performance"
- "Design a state analyzer"
- "Calculate business hours in status"

**Implicit Triggers:**
- Questions about "how long does it take" for workflow stages
- Requests for SLA tracking or compliance analysis
- Need to optimize process flow or reduce delays
- Questions about which states slow down delivery
- Requests to measure team velocity or throughput
- Need to analyze deployment pipeline duration

**Use This Skill When:**
- Building systems to track state changes over time
- Analyzing workflows with discrete states (Jira, GitHub PRs, deployments, support tickets)
- Calculating temporal metrics (cycle time, lead time, flow efficiency)
- Detecting bottlenecks in multi-stage processes
- Implementing SLA monitoring and compliance tracking
- Extracting insights from audit logs or changelogs

**Do NOT Use This Skill When:**
- You need real-time event processing (use stream processing instead)
- Data lacks complete state history (partial data leads to invalid metrics)
- States are not well-defined or change frequently (fix data model first)
- You need predictive analytics (this skill covers historical analysis only)

## What This Skill Does

Provides comprehensive guidance on designing and implementing state transition analysis systems. Covers state machine fundamentals, extracting transitions from audit logs, calculating temporal durations (calendar days and business hours), detecting bottlenecks, analyzing workflow metrics (cycle time, lead time, flow efficiency), and exporting results for stakeholders. Includes practical examples for Jira, GitHub PRs, and custom systems.

## Quick Start

Analyze how long a ticket spends in each state:

```python
from jira_tool.analysis.state_analyzer import StateDurationAnalyzer
from jira_tool.client import JiraClient

# Fetch issue with changelog
client = JiraClient()
issue = client.get_issue("PROJ-123", expand=["changelog"])

# Analyze state durations
analyzer = StateDurationAnalyzer()
durations = analyzer.analyze_issue(issue)

# Get results
for duration in durations:
    print(f"{duration.state}: {duration.calendar_days} days, {duration.business_hours} business hours")
```

Or use the CLI for batch analysis:
```bash
# Export issues with changelog
uv run jira-tool search "project = PROJ" --expand changelog --format json -o issues.json

# Analyze state durations
uv run jira-tool analyze state-durations issues.json -o durations.csv --business-hours
```

## Instructions

### Step 1: Understand State Machines and Transitions

Every system with state changes follows this pattern:

1. **States**: Discrete conditions (To Do, In Progress, Done, Blocked, etc.)
2. **Transitions**: Changes from one state to another (To Do → In Progress)
3. **Timeline**: When each transition occurred (from audit log/changelog)
4. **Duration**: Time between transitions

**Key Principle**: A complete state history lets you calculate exactly how long items spend in each state.

**Real-World Examples**:
- **Jira Ticket**: `Created → To Do → In Progress → Review → Done` (track days in each)
- **GitHub PR**: `Created → In Review → Approved → Merged` (track review duration)
- **Deployment**: `Queued → Building → Testing → Staging → Production` (track stage duration)
- **Support Ticket**: `New → Assigned → Investigating → Resolved → Closed` (track response time)

### Step 2: Extract State Transitions from Audit Logs

The foundation of state analysis is reliable transition data. Most systems provide this through:
- **Changelog** (Jira issues, GitHub API)
- **Audit logs** (enterprise systems)
- **Event streams** (modern event-driven architectures)
- **Status history** (deployment platforms)

**Pattern**: Extract raw transition data into structured records:

```python
from dataclasses import dataclass
from datetime import datetime

@dataclass
class StateTransition:
    timestamp: datetime        # When it changed
    from_state: str | None    # Previous state (None if created)
    to_state: str             # New state
    author: str | None        # Who made the change
```

**Example from Jira changelog**:
```json
{
  "created": "2024-01-15T10:30:00Z",
  "changelog": {
    "histories": [
      {
        "created": "2024-01-15T10:30:00Z",
        "items": [
          {
            "field": "status",
            "fromString": null,
            "toString": "To Do"
          }
        ]
      },
      {
        "created": "2024-01-16T09:00:00Z",
        "items": [
          {
            "field": "status",
            "fromString": "To Do",
            "toString": "In Progress"
          }
        ]
      }
    ]
  }
}
```

**Extraction Logic**: For each status change in changelog, create a StateTransition

### Step 3: Calculate Duration Between Transitions

Once you have transitions, calculate time spent in each state:

**Duration Metrics**:
1. **Calendar Days**: Total elapsed days (includes nights, weekends)
2. **Business Hours**: Time within working hours (e.g., 9 AM - 5 PM, weekdays only)
3. **Active Hours**: Excludes explicitly defined off-hours

**Implementation Pattern**:

```python
from datetime import datetime, timedelta, UTC

@dataclass
class StateDuration:
    state: str
    start_time: datetime
    end_time: datetime | None      # None if still in state
    calendar_days: float
    business_hours: float

def calculate_calendar_days(start: datetime, end: datetime) -> float:
    """Calculate elapsed calendar days."""
    delta = end - start
    return delta.total_seconds() / (24 * 3600)

def calculate_business_hours(
    start: datetime,
    end: datetime,
    business_start: int = 9,       # 9 AM
    business_end: int = 17,        # 5 PM
) -> float:
    """Calculate time within business hours (Mon-Fri, 9-5)."""
    current = start
    hours = 0.0

    while current < end:
        # Only count weekdays
        if current.weekday() < 5:  # Mon=0, Fri=4
            day_start = current.replace(hour=business_start, minute=0, second=0)
            day_end = current.replace(hour=business_end, minute=0, second=0)

            # Clamp to actual interval
            interval_start = max(current, day_start)
            interval_end = min(end, day_end)

            if interval_start < interval_end:
                hours += (interval_end - interval_start).total_seconds() / 3600

        # Move to next day
        current = (current + timedelta(days=1)).replace(
            hour=0, minute=0, second=0, microsecond=0
        )

    return hours
```

**Considerations**:
- **Timezone Awareness**: Always use UTC internally, convert for display
- **Partial Days**: Handle transitions at any time (not just business hour boundaries)
- **Open Issues**: Current state has `end_time = None` (still ongoing)
- **Business Hours**: Configurable per organization (not all use 9-5)

### Step 4: Detect Bottlenecks

Once you have durations, find which states take the longest:

**Pattern**: Aggregate by state and sort by duration

```python
def find_bottlenecks(durations: list[StateDuration]) -> dict[str, dict]:
    """Identify states where items spend most time."""
    by_state = {}

    for duration in durations:
        if duration.state not in by_state:
            by_state[duration.state] = {
                'total_days': 0,
                'count': 0,
                'max_days': 0,
                'avg_business_hours': 0
            }

        stats = by_state[duration.state]
        if duration.end_time:  # Only closed items
            stats['total_days'] += duration.calendar_days
            stats['count'] += 1
            stats['max_days'] = max(stats['max_days'], duration.calendar_days)

    # Calculate averages
    for state, stats in by_state.items():
        if stats['count'] > 

Related in Design