> For the complete documentation index, see [llms.txt](/llms.txt).
> Markdown versions of each page are available by appending .md to any URL.

# Factory Dashboard metrics reference

Look up what each Dashboard metric counts, how Warp computes it, and its data-coverage limits, from Total runs to Cost per PR.

This reference describes every metric on a factory’s **Dashboard** page: what it counts, how Warp computes it, and the data-coverage limits that shape how to read it. For where these metrics fit into a broader measurement workflow, see [Measure and improve a factory](/factories/measure-and-improve/).

## How to read these metrics

A few things apply across most cards on the page:

-   **Most headlines are medians, not averages.** Costs and durations are heavily skewed by outliers — one expensive PR or one stuck review would drag an average off course — so Warp reports the middle value of the distribution instead. With an even number of values, the median averages the two middle ones.
-   **Cards count PRs by different points in time.** **Pull requests** counts by when a PR was opened; **Autonomy** and **Cycle time** count by when a PR merged; **Cost per PR** counts every PR opened in the range regardless of merge status. The same date range can legitimately show different totals across cards — this reflects what each metric measures, not a data error.
-   **PR-level detail needs a connected code host.** Autonomy, Cycle time, PRs merged, and the detail columns in Most expensive PRs come from webhooks on your connected code host — the Warp GitHub App on GitHub repositories, or the group webhook Warp installs when you [connect GitLab](/factories/integrations/gitlab/). Coverage starts only after that connection existed, so earlier activity legitimately reads as zero, a dash, or blank detail rather than as missing data.

## Total runs

**Total runs** counts every run your factory’s agents executed whose creation time falls in the selected range, including subruns launched by other runs — each run and subrun counts individually toward the headline. Deleted runs don’t count.

Beneath the headline, a secondary line shows the range’s **top-level runs**: runs a person or a trigger started directly, with no parent. This is the number the **By source** breakdown view sums to, since a subrun inherits no trigger source of its own.

The view dropdown redraws the chart as a stacked area chart across six dimensions: **By agent type** (the default), **By status**, **By source**, **Top-level vs subruns**, **By model**, and **By harness**. Self-improvement runs appear as their own group under **By agent type**. Each view fetches only that dimension’s counts, so switching views is fast and never re-runs the cost calculations behind Cost per PR. Hovering a point on the chart shows every group’s exact count and its share of that bin’s total; the legend below the chart names the groups but doesn’t repeat the numbers.

**Total runs** includes evaluation, benchmark, and self-improvement runs alongside the runs that produce pull requests, so a rising run count with a flat PR count can mean harder tasks, retries, or measurement activity rather than more output.

## Pull requests

The **Pull requests** chart plots two series over time:

-   **Opened** counts distinct pull requests your factory’s runs attached as artifacts. A PR is identified by its URL and counts exactly once, ever, in the bin where it first appeared — regardless of how many runs or subruns later reference it, and even if it’s reported again inside a later range.
-   **Merged** shows, of the PRs opened in a given bin, how many later merged — a cohort of the opened line, bucketed by the day the PR was **created** (or its merge day, if creation was never observed). A PR created before the selected range never counts here, even if it merges inside the range, and a recent bin’s merged count can rise later as more of its open PRs merge.

Opened and merged use different identity pipelines — opened comes from run artifacts, merged comes from webhook-collected PR facts — so the two series aren’t guaranteed to reconcile PR-for-PR. Merged reads zero for repositories without a webhook connection, and for merges that happened before Warp started collecting PR facts.

## Autonomy

**Autonomy** is the share of the factory’s merged pull requests that needed no human code push before merging. Warp counts a human opening the PR (which pushes the initial branch) as a code push, which is what keeps a human-authored PR that a factory run later revised from reading as autonomous — comments, reviews, requested changes, and the merge action itself never count as a push.

The card’s funnel — **Merged PRs**, **From this factory**, and **Autonomous** — breaks the ratio down step by step:

-   **Merged PRs** is every PR merged in the range across the factory’s configured repositories, whoever created it.
-   **From this factory** narrows that to the PRs this factory’s runs produced.
-   **Autonomous** narrows further to the subset whose full open history Warp observed (so it can prove nobody touched the PR) and which had no human code push. The headline ratio divides by this observed subset, not by every factory PR — a PR whose open event predates webhook collection can’t be proven autonomous either way, so it’s excluded from the ratio even though it still counts as a factory merge.

Membership in this funnel is counted by **merge time**, not by when the PR was opened — unlike the Pull requests chart’s opened series. This is deliberate: it lets the card describe exactly what merged inside the selected range.

## Cycle time

**Cycle time** reports how long the factory’s merged pull requests took to move through the pipeline, as four independent medians: **Kickoff → PR**, **PR → first human review**, **first human review → merge**, and the headline **Kickoff → merge**. Membership is counted by merge time, the same as Autonomy.

Kickoff is the creation time of the earliest factory run linked to the PR. First review is the earliest review from a human reviewer with a recorded time — bot and GitHub App reviews (agent reviewers, CI checks) never start this stage, but every human review state counts, including approvals. Each stage’s median covers only the PRs where both of that stage’s endpoints were observed, so the three stage medians do **not** sum to the headline — they’re independent distributions, each with its own sample size. A stage reads as a dash when no merged PR in the range has both of its endpoints recorded, never as zero.

The two review-anchored stages depend on your code host delivering review webhooks; without that coverage, they’re legitimately unmeasured rather than fast.

## Cost per PR

**Cost per PR** headlines the **median** attributed cost of the pull requests opened in the selected range — merged and unmerged PRs count alike, unlike the merge-time cards above. A secondary line shows the range’s total cost and PR count.

Cost attribution works at the level of a **run tree** — a run plus every subrun it launched. If any run in a tree produced a PR, the entire tree’s cost attributes to that PR. When one tree produces several distinct PRs, its cost splits evenly across them, so a credit is never counted toward more than one PR — but it does mean a range’s summed PR costs can include a share of a tree whose other PRs fall outside that range.

Cost breaks down into three components — **compute**, **platform**, and **inference** — each converted from credits to US dollars at your team’s current credit price. That conversion is an approximation, not a billing figure: it uses today’s rate rather than the rate at the time the credits were spent, and credit recording isn’t complete on every run, so the figures are a lower bound on true cost.

The card’s view picker swaps its chart between two breakdowns of the same per-PR costs:

-   **Cost breakdown** (the default) plots one line per cost component, each the bin’s median of that component’s own per-PR distribution. The three component medians are independent of each other and of the headline — they don’t sum to it, because a median has no component decomposition. A bin with zero PRs plots as a gap in every line, never a zero, since an undefined median isn’t the same as a free PR.
-   **By PR size** groups the same per-PR costs by the pull request’s size — additions plus deletions under 100 lines is **S**, under 500 is **M**, under 1,000 is **L**, and anything larger is **XL** — and plots a median cost line per size. This buckets the size of the diff, not engineering complexity. PRs whose line counts were never observed (no webhook coverage, or the PR predates fact collection) don’t belong to any size bucket; the card footnotes their count as “Sized N of M PRs” rather than silently excluding them from the total.

### Most expensive PRs

Below the chart, **Most expensive PRs** lists the 20 costliest pull requests first seen in the range, most expensive first. Each row shows the PR’s status (open, draft, merged, or closed), who kicked off the run, the trigger source, a model-mix bar (segments sized by each model’s share of the PR’s inference cost), diff stats, and — when the PR’s open event was observed — whether it was autonomous, using the same no-human-code-push definition as the Autonomy card. The section is collapsed by default and loads its data only once expanded, since the underlying query is expensive. PRs that predate PR-fact collection still appear, since their cost is known, but their detail columns read as a dash.

## Scorer cards

When a factory has Scorers configured, one card per Scorer appears at the bottom of the Dashboard, each showing its pass rate over the selected range alongside a trend chart and the agents it evaluates. A card reads “No scores in this range” when the range has no scored conversations — this covers the whole Dashboard range, not a fixed recent window, so it means the range itself has nothing scored rather than that the Scorer has never run. See [Configure Scorers](/factories/measure-and-improve/#configure-scorers) to set one up.

## Self-improvement pull requests

Self-improvement pull requests aren’t a Dashboard card — they’re tracked on the factory’s own **Self-improvement** page, which lists every pull request self-improvement opened regardless of the Dashboard’s date range. See [Configure and review Self-improvement](/factories/measure-and-improve/#configure-and-review-self-improvement) for how to turn it on and review its output.

## Related pages

-   [Factory dashboard](/factories/factory-dashboard/) - An orientation to the whole factory dashboard, including the **Dashboard** page’s place in it.
-   [Measure and improve a factory](/factories/measure-and-improve/) - How Dashboard metrics fit alongside Scorers, benchmarks, and Self-improvement.
-   [Connect GitHub to your factory](/factories/integrations/github/) and [Connect a factory to GitLab](/factories/integrations/gitlab/) - Set up the code-host connection that PR-level metrics depend on.
