---
name: analyze-pr-velocity
description: Use when the user says "weekly PR health" / "cycle time" / "reviewer load" / "DORA-lite" / "PR velocity" — pulls the last 7 days of PRs from a Composio-connected code host and computes five metrics (PRs merged, median cycle time, largest PR size, reviewer concentration, open-to-merge age) with a one-line diagnosis per anomaly, written to `pr-velocity/{YYYY-Www}.md`.
---

# Analyze PR Velocity

## When to use

- Explicit: "weekly PR health", "PR velocity", "cycle time",
  "reviewer load", "DORA-lite", "what's the state of our PRs".
- Implicit: Monday review, retro prep, or anytime the founder
  senses a bottleneck forming.
- Best run weekly. Running more often is fine but noisy at small
  team sizes.

## Steps

1. **Read engineering context**:
   `../head-of-engineering/engineering-context.md`. If missing,
   tell the user to run `define-engineering-context` first and stop.
   The team's cadence and quality bar set the thresholds for
   "anomalous" — without it, diagnoses are generic.
2. **Read config**: `config/stack.json` for team size and cadence
   context if present.
3. **Fetch PR data via Composio.** Run `composio search
   code-hosting` to discover the connected slug. Pull all PRs from
   the last 7 days (both merged and still-open): title, author,
   reviewers, open-at, merge-at (or null), lines added + removed,
   changed files count, review comment count.
4. **Compute the five metrics:**
   - **PRs merged** — count of PRs merged in the window.
   - **Median cycle time** — from PR open to merge, in hours.
     Include only merged PRs.
   - **Largest PR size** — max `(linesAdded + linesRemoved)` of
     merged PRs. Flag the PR.
   - **Reviewer concentration** — of all distinct reviewers, what
     share of review comments + approvals came from the top
     reviewer. Report as a percentage.
   - **Open-to-merge age of currently-open PRs** — median age (in
     hours) of PRs still open at the end of the window.
5. **Diagnose anomalies.** For each metric, compare against
   reasonable defaults (team size permitting — from the engineering
   context) and attach a one-line diagnosis if the metric looks off.
   Examples: "Cycle time 72h — PRs waiting on review, not on
   author"; "Reviewer concentration 87% — bus factor risk; spread
   review load"; "Largest PR 1,800 lines — split the next one of
   these". Don't invent anomalies where none exist — just note
   "within normal range" if things look fine.
6. **Write the readout** to `pr-velocity/{YYYY-Www}.md` atomically
   (`*.tmp` → rename). Where `{YYYY-Www}` is ISO week (e.g.
   `2026-W17`). Structure:
   - **Header** — week range, total PRs in window.
   - **Five metrics** — each as its own short section with the
     number, the compared-against band, and the one-line diagnosis.
   - **Flagged PRs** — links to the largest PR, the oldest open
     PR, and any PR held more than 72h.
   - **Recommended actions** — 0-3 bullets the user can act on this
     week. Keep them concrete.
7. **Append to `outputs.json`** — `{ id, type: "pr-velocity",
   title, summary, path: "pr-velocity/{YYYY-Www}.md", status:
   "ready", createdAt, updatedAt }`, atomic write.
8. **Summarize to user** — the five numbers on one line each, any
   anomalies, and path to the readout.

## Never invent

If the code-host connection is missing or the query fails, stop
and tell the user which category to connect. If a metric is
unavailable (e.g. review comments not exposed by the tool), mark
it UNKNOWN rather than substituting a number.

## Outputs

- `pr-velocity/{YYYY-Www}.md`
- Appends to `outputs.json` with type `pr-velocity`.
