/diagnosing-ci-and-merge-bottlenecks
Diagnoses CI and pull-request pipeline health for a GitHub repo using the engineering analytics MCP tools — pull-requests (PR list with CI status), workflow-health (per-workflow CI trends), and pr-lifecycle (a single PR's timeline). Use when asked whether CI is getting faster or
Claude Code
$ npx -y skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks --agent claude-code
Codex
$ npx skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks -a codex -y
Cursor
$ npx skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks -a cursor -y
Gemini CLI
$ npx skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks -a gemini-cli -y
GitHub Copilot
$ npx skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks -a github-copilot -y
OpenCode
$ npx skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks -a opencode -y
Windsurf
$ npx skills add PostHog/ai-plugin --skill diagnosing-ci-and-merge-bottlenecks -a windsurf -y
SKILL.md
diagnosing-ci-and-merge-bottlenecks.SKILL.mdname: diagnosing-ci-and-merge-bottlenecks
description: >
Diagnoses CI and pull-request pipeline health for a GitHub repo using the engineering analytics MCP tools —
pull-requests (PR list with CI status), workflow-health (per-workflow CI trends), and pr-lifecycle (a single PR's
timeline). Use when asked whether CI is getting faster or slower, which GitHub Actions workflow is the slow or
flaky long-pole, how long PRs take from open to merge, how an author's merge time compares to the cohort, which
open PRs have failing or pending CI, or where a specific pull request is stuck. Triggers on "engineering
analytics", "is CI getting slower", "slow workflow", "flaky CI", "time to merge", "cycle time", "PR throughput",
"failing checks", "where is PR <n> stuck", "CI long pole", "what's holding up this PR". For a verdict on one
specific CI failure (whose fault, which commit) use investigating-ci-failures; to save these numbers as insights
use turning-engineering-analytics-into-insights.
Diagnosing CI and merge bottlenecks
Engineering analytics treats a pull request like product analytics treats a user: a PR moves through a pipeline (`opened → CI → review → merged → deployed`) and the job is to find where it slows down. The surface is **named MCP tools** — you call them, you don't write SQL. Dogfooded on `PostHog/posthog`; the same tools serve autonomous agents (e.g. PostHog Desktop) reasoning about their own PRs. Scope is aggregate pipeline health: to take one failing test or red run to a verdict, switch to the `investigating-ci-failures` skill.
The tools
- **`pull-requests`** — the PR workhorse. Open PRs plus anything merged or closed since `date_from` (default
`-30d`), newest first. Each row carries `author` (nested object: `handle`, `display_name`, `is_bot`), `repo` (nested: `owner`, `name`), `state`, `is_draft`, `labels`, `open_to_merge_seconds`, `ready_to_merge_seconds`, and a `ci` rollup (`runs` / `passing` / `failing` / `pending`) from the head-SHA join. Answers most PR-level questions: which PRs have failing or pending CI, which are stuck open longest, per-author or per-repo triage, and time-to-merge stats (aggregate over the returned merged rows yourself, median and p95, never a mean; prefer `ready_to_merge_seconds` where non-null, it excludes draft time).
- **`workflow-health`** — per-workflow CI health over a window (`date_from` / `date_to`, default last 24 hours):
`run_count`, `success_rate`, `p50_seconds`, `p95_seconds`, `last_failure_at`. Answers "is CI getting faster or slower" and "which workflow is the slow or flaky long pole". There is no built-in trend — call it over two adjacent windows and compare. `success_rate` covers runs that succeeded or ended in a decisive failure (`failure`, `timed_out`, `startup_failure`, or `stale`), excluding skipped, cancelled, neutral, and action-required runs. `p50_seconds` / `p95_seconds` cover successful runs only because cancelled and failed runs end early and would bias the duration trend. Each is `null` when a window has no qualifying runs — guard for null before comparing two windows (a workflow can have runs in one and none in the other). `run_scope=pull_request` scopes to PR-attributed runs, excluding master/main (same-repo PRs only — fork runs carry no PR attribution).
- **`pr-lifecycle`** — a single PR's timeline: a header plus ordered events — opened, ready-for-review and
converted-to-draft transitions (when the issue-events table is synced), then a CI started/finished pair **per workflow run** (many on a multi-workflow repo, interleaved by time), then merged/closed. Answers "where is PR N stuck". `metric_quality` is `partial` (no review or comment events).
- **`engineering-analytics-flaky-tests`** — the active test-health queue from the per-test CI spans, over a
window (`date_from` default `-7d`, max 30 days). Evidence is counted per CI run, never per span or run attempt. `classification` is `confirmed_flake` only where the evidence proves nondeterminism (`same_commit_recovery_run_count > 0`: one commit both failed and passed the test **in the same matrix job**, via a "Re-run failed jobs" attempt going green or an in-job retry; a pass in a different leg, such as FOSS against EE, is not recovery); `quarantined` means a tolerated failure was recorded while masked; `suspected_regression` means only failures were recorded, which is absence of proof, not proof of a real break. A test qualifies on any same-commit recovery, a quarantined failure, any master/main failure, or failures on ≥ `min_failed_prs` distinct PRs (`failed_pr_count`). Answers "what is this failing test costing us" and picks quarantine candidates. **It does not answer "which tests are flaky"**: this queue only sees the main Backend pytest and Frontend Jest suites, and recovery proof only arrives when someone re-runs failed jobs (or a pytest test is hand-marked `@pytest.mark.flaky(reruns=N)`). Counts are absolute signal, never rates: passing runs are mostly not emitted, so there is no honest denominator. A CI setup break excludes every trial of the attempt, not only its failures: a run attempt whose tests errored in 3 or more jobs or for 3 or more owning teams, or a job attempt with 100 or more distinct failed or errored tests. A real break that wide is left out too, so when a whole suite or job goes red, check `workflow-health` rather than reading an empty queue as healthy.
- **`engineering-analytics-sources`**: the team's connected GitHub sources and repos. With more than one of
either, call it first and pass the chosen entry's `source_id` **and** `repo` to `pull-requests`, `workflow-health`, `pr-lifecycle`, and `team-ci-health`. Passing only `source_id` reads that source's default repo, not the one you picked. With a single source and repo the tools default to it.
There is no aggregate time-to-merge tool and no "counts" tool — derive those from `pull-requests` (th
Read more
name: diagnosing-ci-and-merge-bottlenecks description: > Diagnoses CI and pull-request pipeline health for a GitHub repo using the engineering analytics MCP tools — pull-requests (PR list with CI status), workflow-health (per-workflow CI trends), and pr-lifecycle (a single PR's timeline). Use when asked whether CI is getting faster or slower, which GitHub Actions workflow is the slow or flaky long-pole, how long PRs take from open to merge, how an author's merge time compares to the cohort, which open PRs have failing or pending CI, or where a specific pull request is stuck. Triggers on "engineering analytics", "is CI getting slower", "slow workflow", "flaky CI", "time to merge", "cycle time", "PR throughput", "failing checks", "where is PR <n> stuck", "CI long pole", "what's holding up this PR". For a verdict on one specific CI failure (whose fault, which commit) use investigating-ci-failures; to save these numbers as insights use turning-engineering-analytics-into-insights.
Diagnosing CI and merge bottlenecks
Engineering analytics treats a pull request like product analytics treats a user: a PR moves through a pipeline (`opened → CI → review → merged → deployed`) and the job is to find where it slows down. The surface is **named MCP tools** — you call them, you don't write SQL. Dogfooded on `PostHog/posthog`; the same tools serve autonomous agents (e.g. PostHog Desktop) reasoning about their own PRs. Scope is aggregate pipeline health: to take one failing test or red run to a verdict, switch to the `investigating-ci-failures` skill.
The tools
- **`pull-requests`** — the PR workhorse. Open PRs plus anything merged or closed since `date_from` (default
`-30d`), newest first. Each row carries `author` (nested object: `handle`, `display_name`, `is_bot`), `repo` (nested: `owner`, `name`), `state`, `is_draft`, `labels`, `open_to_merge_seconds`, `ready_to_merge_seconds`, and a `ci` rollup (`runs` / `passing` / `failing` / `pending`) from the head-SHA join. Answers most PR-level questions: which PRs have failing or pending CI, which are stuck open longest, per-author or per-repo triage, and time-to-merge stats (aggregate over the returned merged rows yourself, median and p95, never a mean; prefer `ready_to_merge_seconds` where non-null, it excludes draft time).
- **`workflow-health`** — per-workflow CI health over a window (`date_from` / `date_to`, default last 24 hours):
`run_count`, `success_rate`, `p50_seconds`, `p95_seconds`, `last_failure_at`. Answers "is CI getting faster or slower" and "which workflow is the slow or flaky long pole". There is no built-in trend — call it over two adjacent windows and compare. `success_rate` covers runs that succeeded or ended in a decisive failure (`failure`, `timed_out`, `startup_failure`, or `stale`), excluding skipped, cancelled, neutral, and action-required runs. `p50_seconds` / `p95_seconds` cover successful runs only because cancelled and failed runs end early and would bias the duration trend. Each is `null` when a window has no qualifying runs — guard for null before comparing two windows (a workflow can have runs in one and none in the other). `run_scope=pull_request` scopes to PR-attributed runs, excluding master/main (same-repo PRs only — fork runs carry no PR attribution).
- **`pr-lifecycle`** — a single PR's timeline: a header plus ordered events — opened, ready-for-review and
converted-to-draft transitions (when the issue-events table is synced), then a CI started/finished pair **per workflow run** (many on a multi-workflow repo, interleaved by time), then merged/closed. Answers "where is PR N stuck". `metric_quality` is `partial` (no review or comment events).
- **`engineering-analytics-flaky-tests`** — the active test-health queue from the per-test CI spans, over a
window (`date_from` default `-7d`, max 30 days). Evidence is counted per CI run, never per span or run attempt. `classification` is `confirmed_flake` only where the evidence proves nondeterminism (`same_commit_recovery_run_count > 0`: one commit both failed and passed the test **in the same matrix job**, via a "Re-run failed jobs" attempt going green or an in-job retry; a pass in a different leg, such as FOSS against EE, is not recovery); `quarantined` means a tolerated failure was recorded while masked; `suspected_regression` means only failures were recorded, which is absence of proof, not proof of a real break. A test qualifies on any same-commit recovery, a quarantined failure, any master/main failure, or failures on ≥ `min_failed_prs` distinct PRs (`failed_pr_count`). Answers "what is this failing test costing us" and picks quarantine candidates. **It does not answer "which tests are flaky"**: this queue only sees the main Backend pytest and Frontend Jest suites, and recovery proof only arrives when someone re-runs failed jobs (or a pytest test is hand-marked `@pytest.mark.flaky(reruns=N)`). Counts are absolute signal, never rates: passing runs are mostly not emitted, so there is no honest denominator. A CI setup break excludes every trial of the attempt, not only its failures: a run attempt whose tests errored in 3 or more jobs or for 3 or more owning teams, or a job attempt with 100 or more distinct failed or errored tests. A real break that wide is left out too, so when a whole suite or job goes red, check `workflow-health` rather than reading an empty queue as healthy.
- **`engineering-analytics-sources`**: the team's connected GitHub sources and repos. With more than one of
either, call it first and pass the chosen entry's `source_id` **and** `repo` to `pull-requests`, `workflow-health`, `pr-lifecycle`, and `team-ci-health`. Passing only `source_id` reads that source's default repo, not the one you picked. With a single source and repo the tools default to it.
There is no aggregate time-to-merge tool and no "counts" tool — derive those from `pull-requests` (th
Official PostHog plugin for AI clients. Access PostHog products directly from your AI coding tool.
Other skills on ai-plugin.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about diagnosing-ci-and-merge-bottlenecks.
- Which coding agents can use diagnosing-ci-and-merge-bottlenecks?
- diagnosing-ci-and-merge-bottlenecks installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

