Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ description: |
when_to_use: |
Invoke when a maintainer says "review my PRs", "go through the PRs assigned to me", "review my queue", "review the
area:scheduler PRs", "review PR NNN", "do my review pass", or any variation on "look over the code on PRs I'm
responsible for, one at a time." Distinct from `pr-triage`, which decides *whether* to engage with a PR. This skill is
responsible for, one at a time." Distinct from `pr-management-triage`, which decides *whether* to engage with a PR. This skill is
invoked **after** triage has produced PRs marked `ready for maintainer review` (or any other curated selector) and a
human reviewer is doing the actual code review.
license: Apache-2.0
Expand All @@ -39,7 +39,7 @@ two questions per PR:
> *If not, what specifically should change before it lands?*

It is the review-bench counterpart to
[`pr-triage`](../pr-triage/SKILL.md). Triage decides whether to
[`pr-management-triage`](../pr-management-triage/SKILL.md). Triage decides whether to
*engage* with a PR (draft / comment / close / rebase / rerun /
mark-ready / ping). This skill takes PRs that have already
cleared triage (or any other curated selector) and produces an
Expand All @@ -65,14 +65,14 @@ Detail files in this directory break the logic out topic-by-topic:
This skill resolves project-specific content from the adopter's
`<project-config>/` directory:

- [`<project-config>/pr-maintainer-review-criteria.md`](../../../projects/_template/pr-maintainer-review-criteria.md) — list of the project's review-criteria source files (repo-wide AGENTS.md, code-review docs, per-area AGENTS.md), security-model calibration doc, backport-branch pattern, and section-anchor URLs the framework links per finding.
- [`<project-config>/pr-management-code-review-criteria.md`](../../../projects/_template/pr-management-code-review-criteria.md) — list of the project's review-criteria source files (repo-wide AGENTS.md, code-review docs, per-area AGENTS.md), security-model calibration doc, backport-branch pattern, and section-anchor URLs the framework links per finding.

The framework's [`criteria.md`](criteria.md) currently embeds
airflow's source-file paths inline as the default. Follow-up work
will move them out so the skill reads exclusively from the
adopter config — until then, non-airflow adopters override by
forking [`criteria.md`](criteria.md) into their own
`.claude/skills/pr-maintainer-review/`.
`.claude/skills/pr-management-code-review/`.

---

Expand Down Expand Up @@ -181,11 +181,11 @@ check rollup; see [`prerequisites.md#ci-precheck`](prerequisites.md).
**Golden rule 9 — out of scope: triage actions.** This skill
does not convert PRs to draft, close them, rebase them, ping
reviewers, or rerun CI. Those are
[`pr-triage`](../pr-triage/SKILL.md) actions. If the maintainer
[`pr-management-triage`](../pr-management-triage/SKILL.md) actions. If the maintainer
discovers during review that a PR needs a triage action (e.g. it
should really be drafted because of merge conflicts that
appeared), the skill says so explicitly and points them at
`/pr-triage pr:<N>`. It does not silently invoke triage actions.
`/pr-management-triage pr:<N>`. It does not silently invoke triage actions.

**Golden rule 10 — every PR number is rendered as its full
URL.** A bare `#65981` is unclickable in most terminals; the
Expand Down Expand Up @@ -246,7 +246,7 @@ headline-confirm gate anyway).
Before running, resolve the maintainer's selector into a concrete
query.

The **default selector** — what `/pr-maintainer-review` with no
The **default selector** — what `/pr-management-code-review` with no
arguments resolves to — is the working list called
**"my reviews"**: every open PR on `<repo>` that matches at
least one of the five signals below, all rooted on
Expand Down Expand Up @@ -306,26 +306,26 @@ labels (the skill warns and degrades gracefully — see

## How to invoke — examples

The slash command is `/pr-maintainer-review`. A few worked
The slash command is `/pr-management-code-review`. A few worked
examples a maintainer can paste:

| Goal | Invocation |
|---|---|
| Walk through everything in **"my reviews"**, newest first | `/pr-maintainer-review` |
| Review a single PR (the most common ad-hoc trigger) | `/pr-maintainer-review pr:65981` |
| Just the PRs where I'm a CODEOWNER, ignore the rest | `/pr-maintainer-review codeowner-only` |
| PRs that explicitly `@`-mention me, skip the noise | `/pr-maintainer-review mentioned-only` |
| Re-look at the PRs I already reviewed (follow-ups after author push) | `/pr-maintainer-review reviewed-before-only` |
| My-reviews **but** drop touching-mine (too noisy this morning) | `/pr-maintainer-review no-touching-mine` |
| My-reviews limited to scheduler-area, max 5 | `/pr-maintainer-review area:scheduler max:5` |
| My-reviews scoped to non-collaborator authors (extra-careful pass) | `/pr-maintainer-review collab:false` |
| The team queue (PRs where `<upstream>-providers-amazon` is requested) | `/pr-maintainer-review team:airflow-providers-amazon` |
| The wider curated queue triage already promoted | `/pr-maintainer-review ready` |
| Stay body-only this session (no inline picker) | `/pr-maintainer-review inline:off` |
| Dry-run the queue — draft everything, post nothing | `/pr-maintainer-review dry-run` |
| Same, against a different repo | `/pr-maintainer-review dry-run repo:<upstream>-site` |
| Pair with an adversarial reviewer for a second read on each PR | `/pr-maintainer-review with-reviewer:/codex-plugin:adversarial-review` |
| Skip background analysis subagents (tiny queue, prefetch is wasted) | `/pr-maintainer-review max:1 no-prefetch` |
| Walk through everything in **"my reviews"**, newest first | `/pr-management-code-review` |
| Review a single PR (the most common ad-hoc trigger) | `/pr-management-code-review pr:65981` |
| Just the PRs where I'm a CODEOWNER, ignore the rest | `/pr-management-code-review codeowner-only` |
| PRs that explicitly `@`-mention me, skip the noise | `/pr-management-code-review mentioned-only` |
| Re-look at the PRs I already reviewed (follow-ups after author push) | `/pr-management-code-review reviewed-before-only` |
| My-reviews **but** drop touching-mine (too noisy this morning) | `/pr-management-code-review no-touching-mine` |
| My-reviews limited to scheduler-area, max 5 | `/pr-management-code-review area:scheduler max:5` |
| My-reviews scoped to non-collaborator authors (extra-careful pass) | `/pr-management-code-review collab:false` |
| The team queue (PRs where `<upstream>-providers-amazon` is requested) | `/pr-management-code-review team:airflow-providers-amazon` |
| The wider curated queue triage already promoted | `/pr-management-code-review ready` |
| Stay body-only this session (no inline picker) | `/pr-management-code-review inline:off` |
| Dry-run the queue — draft everything, post nothing | `/pr-management-code-review dry-run` |
| Same, against a different repo | `/pr-management-code-review dry-run repo:<upstream>-site` |
| Pair with an adversarial reviewer for a second read on each PR | `/pr-management-code-review with-reviewer:/codex-plugin:adversarial-review` |
| Skip background analysis subagents (tiny queue, prefetch is wasted) | `/pr-management-code-review max:1 no-prefetch` |

Selectors compose freely. Most flags carry through cleanly:
`area:scheduler reviewed-before-only since:7d` is "PRs in
Expand Down Expand Up @@ -475,9 +475,9 @@ writes a session log to disk.

- **First-pass triage actions.** Drafting, closing, rebasing,
pinging, rerunning CI, marking `ready for maintainer review` —
all live in [`pr-triage`](../pr-triage/SKILL.md). If the
all live in [`pr-management-triage`](../pr-management-triage/SKILL.md). If the
current PR needs one of those, the skill says so and points
at `/pr-triage pr:<N>`.
at `/pr-management-triage pr:<N>`.
- **Merging.** Merging is a conscious maintainer action that
belongs in a separate flow.
- **Submitting reviews on closed / merged PRs.** The skill only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Pass the slash command to invoke as the `with-reviewer:`
selector:

```text
/pr-maintainer-review with-reviewer:/some-plugin:adversarial-review
/pr-management-code-review with-reviewer:/some-plugin:adversarial-review
```

The skill stores that command for the session and proposes it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ a separate call. The state is one of:
`SKILL.md`, `APPROVE` is off the table; downgrade to
`COMMENT` or `REQUEST_CHANGES`.
- `EXPECTED` (workflow approval pending) — surface explicitly
and recommend `/pr-triage pr:<N>` for the workflow-approval
and recommend `/pr-management-triage pr:<N>` for the workflow-approval
flow first; do not attempt to review the PR until CI has
actually run.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ default working list — referred to throughout the docs as
PRs that already have a `gh pr review`-submitted review
from `<viewer>` (state `APPROVED`, `CHANGES_REQUESTED`, or
`COMMENTED`). **Triage comments do not count** — the
`pr-triage` skill's PR-conversation comments live in
`pr-management-triage` skill's PR-conversation comments live in
`comments[]`, never in `reviews[]`, so they are excluded
automatically. See
[`reviewed-before`](#reviewed-before--prs-i-already-reviewed)
Expand Down Expand Up @@ -337,7 +337,7 @@ A PR is **reviewed-before by `<viewer>`** if its `reviews[]`
array contains any entry with `author.login == <viewer>`,
regardless of `state`.

**Triage comments do NOT count.** The `pr-triage` skill posts
**Triage comments do NOT count.** The `pr-management-triage` skill posts
its notes via `gh pr comment`, which lands in the PR's
`comments` array (the GitHub *issue-comment* endpoint). Those
never appear in `reviews`. So the reviewed-before filter
Expand Down Expand Up @@ -545,7 +545,7 @@ why the assistant proposes but does not invoke.
Example:

```text
/pr-maintainer-review with-reviewer:/some-plugin:adversarial-review
/pr-management-code-review with-reviewer:/some-plugin:adversarial-review
```

If `with-reviewer:` is not passed, the skill checks the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: pr-stats
name: pr-management-stats
description: |
Produce maintainer-facing statistics about open pull requests on
the configured `<upstream>` repo (default: read from `<project-config>/project.md → upstream_repo`). Successor to
Expand All @@ -23,7 +23,7 @@ description: |
<viewer> → the authenticated GitHub login of the maintainer running the skill
Substitute these before running any `gh` command below. -->

# pr-stats
# pr-management-stats

Read-only skill that answers "what does the open-PR backlog
*look* like" as two tables:
Expand All @@ -33,14 +33,14 @@ Read-only skill that answers "what does the open-PR backlog
| **Triaged final-state** | closed / merged PRs since a cutoff date, broken down by `area:*` label | Shows triage outcomes — what fraction of triaged PRs merged, closed, or got an author response before closing. |
| **Triaged still-open** | all currently-open PRs, broken down by `area:*` label | Shows current queue pressure — triage coverage, author-response rate, ready-for-review count, age buckets. |

The skill is the statistical complement of [`pr-triage`](../pr-triage/SKILL.md) — same repo, same classification logic, no mutations. Running the two in sequence (stats → triage → stats) lets a maintainer measure a sweep's effect.
The skill is the statistical complement of [`pr-management-triage`](../pr-management-triage/SKILL.md) — same repo, same classification logic, no mutations. Running the two in sequence (stats → triage → stats) lets a maintainer measure a sweep's effect.

Detail files:

| File | Purpose |
|---|---|
| [`fetch.md`](fetch.md) | GraphQL templates for open-PR list and closed/merged-since-cutoff list. |
| [`classify.md`](classify.md) | Triage-status detection (waiting vs. responded vs. never-triaged) — reuses the `Pull Request quality criteria` marker from `pr-triage`. |
| [`classify.md`](classify.md) | Triage-status detection (waiting vs. responded vs. never-triaged) — reuses the `Pull Request quality criteria` marker from `pr-management-triage`. |
| [`aggregate.md`](aggregate.md) | Area grouping, age buckets, totals, percentage rules. |
| [`render.md`](render.md) | The two tables — column order, footers, header wording. |

Expand All @@ -49,23 +49,23 @@ Detail files:
## Adopter configuration

This skill reads the same area-label prefix and triage-marker
string declared in [`pr-triage`'s adopter config](../pr-triage/SKILL.md#adopter-configuration):
string declared in [`pr-management-triage`'s adopter config](../pr-management-triage/SKILL.md#adopter-configuration):

- [`<project-config>/pr-triage-config.md → area_label_prefix`](../../../projects/_template/pr-triage-config.md) — drives the area grouping in both stats tables.
- [`<project-config>/pr-triage-comment-templates.md → Triage-marker visible link text`](../../../projects/_template/pr-triage-comment-templates.md) — the literal string that classifies a PR as triaged. **Both `pr-triage` and `pr-stats` must agree** on this string; the framework defaults to `Pull Request quality criteria`.
- [`<project-config>/pr-management-config.md → area_label_prefix`](../../../projects/_template/pr-management-config.md) — drives the area grouping in both stats tables.
- [`<project-config>/pr-management-triage-comment-templates.md → Triage-marker visible link text`](../../../projects/_template/pr-management-triage-comment-templates.md) — the literal string that classifies a PR as triaged. **Both `pr-management-triage` and `pr-management-stats` must agree** on this string; the framework defaults to `Pull Request quality criteria`.

No `pr-stats`-specific config file is needed — the skill is
read-only and inherits everything from `pr-triage`'s contract.
No `pr-management-stats`-specific config file is needed — the skill is
read-only and inherits everything from `pr-management-triage`'s contract.

---

## Golden rules

**Golden rule 1 — no mutations, ever.** This skill only reads. It must not post comments, add labels, close, rebase, or approve anything. If the maintainer asks for stats and also wants an action, decline the mutation and redirect to `pr-triage`.
**Golden rule 1 — no mutations, ever.** This skill only reads. It must not post comments, add labels, close, rebase, or approve anything. If the maintainer asks for stats and also wants an action, decline the mutation and redirect to `pr-management-triage`.

**Golden rule 2 — reuse pr-triage's triage-detection.** The "triaged" count and "responded" count depend on the same `Pull Request quality criteria` marker string and the same collaborator set (`OWNER`/`MEMBER`/`COLLABORATOR`) that drive the triage-marker rows in `pr-triage/classify-and-act.md` (rows 3–4 — `already_triaged`). Don't invent a second definition — both skills must agree on "is this PR triaged".
**Golden rule 2 — reuse pr-management-triage's triage-detection.** The "triaged" count and "responded" count depend on the same `Pull Request quality criteria` marker string and the same collaborator set (`OWNER`/`MEMBER`/`COLLABORATOR`) that drive the triage-marker rows in `pr-management-triage/classify-and-act.md` (rows 3–4 — `already_triaged`). Don't invent a second definition — both skills must agree on "is this PR triaged".

**Golden rule 3 — one GraphQL call per batch, not per PR.** Same rule as `pr-triage/fetch-and-batch.md`. One aliased query covers the open-PR list for a whole page; the closed/merged fetch is paginated by GitHub's search cursor. Never call `gh pr view` per PR.
**Golden rule 3 — one GraphQL call per batch, not per PR.** Same rule as `pr-management-triage/fetch-and-batch.md`. One aliased query covers the open-PR list for a whole page; the closed/merged fetch is paginated by GitHub's search cursor. Never call `gh pr view` per PR.

**Golden rule 4 — include a legend with every render.** The tables are dense (15+ columns on Table 2). Always print a short legend after the tables explaining the columns — `Contrib.` = non-collaborator, `Responded` = author replied after the triage comment, `Drafted by triager` = PR converted to draft by the viewer, etc. Nobody remembers column abbreviations in isolation.

Expand All @@ -91,8 +91,8 @@ No per-PR drill-in — this skill is aggregate-only.
## Step 0 — Pre-flight

1. `gh auth status` must succeed; capture the viewer login (needed for the triage-marker check in step 2).
2. Run one GraphQL query that asks both for `viewer { login }` and for `repository(owner, name) { name }` to confirm the repo is reachable. `viewerPermission` is NOT required (this skill doesn't mutate) — skip the write-check that `pr-triage` does.
3. Read or initialise the scratch cache at `/tmp/pr-stats-cache-<repo-slug>.json` (see [`aggregate.md#cache`](aggregate.md)). The cache stores the viewer login and a map of `pr_number → (head_sha, triage_status)` so a re-run inside the same session skips the per-PR enrichment.
2. Run one GraphQL query that asks both for `viewer { login }` and for `repository(owner, name) { name }` to confirm the repo is reachable. `viewerPermission` is NOT required (this skill doesn't mutate) — skip the write-check that `pr-management-triage` does.
3. Read or initialise the scratch cache at `/tmp/pr-management-stats-cache-<repo-slug>.json` (see [`aggregate.md#cache`](aggregate.md)). The cache stores the viewer login and a map of `pr_number → (head_sha, triage_status)` so a re-run inside the same session skips the per-PR enrichment.

A failure at step 1 is a **stop**. Steps 2 and 3 degrade with warnings.

Expand All @@ -102,7 +102,7 @@ A failure at step 1 is a **stop**. Steps 2 and 3 degrade with warnings.

Use the query template in [`fetch.md#open-prs`](fetch.md) to get every open PR with the fields needed for classification (labels, `isDraft`, `authorAssociation`, `createdAt`, last commit `committedDate`, last 10 comments for the triage-marker scan).

Paginate until `pageInfo.hasNextPage == false`. Batch size of 50 is safe (the open-PR selection set is lighter than `pr-triage`'s — no `statusCheckRollup`, no `reviewThreads`, no `latestReviews`). For a 300-PR backlog that's six GraphQL calls.
Paginate until `pageInfo.hasNextPage == false`. Batch size of 50 is safe (the open-PR selection set is lighter than `pr-management-triage`'s — no `statusCheckRollup`, no `reviewThreads`, no `latestReviews`). For a 300-PR backlog that's six GraphQL calls.

---

Expand Down Expand Up @@ -152,10 +152,10 @@ The tables are Markdown (GitHub-flavoured) so the same output renders cleanly in
## What this skill does NOT do

- **No mutations.** See Golden rule 1.
- **No per-PR drill-in.** The output is aggregate — if the maintainer wants to inspect a specific PR, they run `pr-triage pr:<N>` or open it in the browser.
- **No per-PR drill-in.** The output is aggregate — if the maintainer wants to inspect a specific PR, they run `pr-management-triage pr:<N>` or open it in the browser.
- **No timeline / trend charts.** A single snapshot per invocation. Tracking week-over-week is the maintainer's job — re-run the skill at a different `since:` date if needed.
- **No author-level stats.** Grouping is by area label, not by author login. A stats-by-author skill is a separate scope.
- **No PR *quality* scoring.** CI pass/fail, diff size, and review-thread counts are all omitted from the aggregate — they belong in the per-PR `pr-triage` view.
- **No PR *quality* scoring.** CI pass/fail, diff size, and review-thread counts are all omitted from the aggregate — they belong in the per-PR `pr-management-triage` view.

---

Expand Down
Loading
Loading