agentsclimarketplace

Time to merge analysis

Skill cxcscmu/SkillLearnBench/skills/b4-skill-creator-claude-haiku-4-5/github-repo-analytics/time-to-merge-analysis

[COLM'26] SkillLearnBench is the first benchmark for evaluating continual learning methods that automatically generate agent skills.

Install
npx -y skills add cxcscmu/SkillLearnBench --skill time-to-merge-analysis

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Calculate average time-to-merge from PR creation to merge timestamps, handling edge cases like unmerged and closed PRs. Use this skill whenever computing PR velocity metrics, measuring merge turnaround, or analyzing PR lifecycle duration.

SKILL.md

2.9 KB, 778 tokens by cl100k_base, as published. Nobody here has run it

Time-to-Merge Analysis

Calculate the average time it takes for pull requests to be merged from creation time.

Calculation Overview

Time-to-merge is defined as the elapsed time between PR creation and merge, measured in days.

time_to_merge_days = (mergedAt - createdAt) / 86400  # seconds per day

Algorithm

  1. Filter: Include only PRs where state == "MERGED" and mergedAt is not null
  2. Calculate: For each merged PR, compute (mergedAt - createdAt) in days
  3. Average: Sum all durations and divide by count
  4. Round: Round to one decimal place (e.g., 3.7 days)

Example Calculation

Given three merged PRs:

PR #1: created 2024-12-01 10:00, merged 2024-12-03 14:00 → 2.17 days
PR #2: created 2024-12-05 09:00, merged 2024-12-06 17:00 → 1.33 days
PR #3: created 2024-12-10 12:00, merged 2024-12-12 12:00 → 2.00 days

Average: (2.17 + 1.33 + 2.00) / 3 = 1.8 days

Implementation (Python)

from datetime import datetime
from typing import List, Dict

def calculate_avg_merge_days(prs: List[Dict]) -> float:
    """
    Args:
        prs: List of PR objects from GitHub API with createdAt, mergedAt, state

    Returns:
        Average time-to-merge in days, rounded to 1 decimal place
    """
    merged_prs = [pr for pr in prs if pr['state'] == 'MERGED' and pr.get('mergedAt')]

    if not merged_prs:
        return 0.0

    total_days = 0
    for pr in merged_prs:
        created = datetime.fromisoformat(pr['createdAt'].replace('Z', '+00:00'))
        merged = datetime.fromisoformat(pr['mergedAt'].replace('Z', '+00:00'))
        days = (merged - created).total_seconds() / 86400
        total_days += days

    average = total_days / len(merged_prs)
    return round(average, 1)

Edge Cases

  • Unmerged PRs: Filter these out; they have no mergedAt timestamp
  • Closed without merge: These have state == "CLOSED" and no mergedAt; exclude them
  • Same-day merges: Valid; results in ~0.0 days (or small fraction)
  • Very fast merges: PRs merged within minutes are normal; round appropriately

Implementation (Bash)

If using jq to process JSON from gh:

jq -r '.[] | select(.state == "MERGED") |
  (((.mergedAt | fromdateiso8601) - (.createdAt | fromdateiso8601)) / 86400) ' \
  prs.json | \
  awk '{sum+=$1; count++} END {if(count>0) printf "%.1f\n", sum/count}'

Verification

Before finalizing:

  • Confirm count of merged PRs matches the "merged" count from other metrics
  • Spot-check 2-3 calculations manually to ensure timestamp parsing is correct
  • Verify no division-by-zero when count is 0 (return 0.0 in that case)

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,132. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.