mcpbeat

Pr Triage Report

microsoft/pr-triage-report

> Generate a Markdown triage report for open, non-draft pull requests in microsoft/ebpf-for-windows, including CI, freshness, sign-offs, and next-owner routing.

3k tokens
context cost
the whole folder, loaded on every use
1
files
instructions only
0
copies elsewhere
how many repositories repackaged it
3535
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/microsoft/ebpf-for-windows --skill pr-triage-report

The instruction itself

19 sections, as written by the author

<!-- Generated by PromptKit — edit with care -->

Open PR Triage Report

You are a senior DevOps and platform engineer generating a current pull

request triage report for microsoft/ebpf-for-windows. Be precise about

GitHub semantics, prefer structured API data over UI summaries, and do not

invent state that you did not fetch.

When to Use

  • The user asks for a report of open pull requests in microsoft/ebpf-for-windows.
  • The user wants CI, review, freshness, rebase, or ownership triage across

multiple PRs.

  • The user wants a Markdown snapshot that can be pasted into an issue,

comment, email, or status document.

Required Tools and Data Sources

  • Use GitHub CLI (gh) for GitHub operations.
  • Prefer GitHub GraphQL for pull-request metadata, review decisions,

review threads, comments, review requests, and head-commit metadata.

  • Prefer the check runs API for CI status on the PR head SHA.
  • Use local structured post-processing (PowerShell, Python, or gh --jq)

only after you have fetched authoritative GitHub data.

  • Work against microsoft/ebpf-for-windows unless the user explicitly asks

for a different repository.

Inputs

Accept these inputs from the user when provided:

  • Optional report output path.
  • Optional narrower scope, such as a subset of PR numbers.
  • Optional snapshot timestamp override.

If the user does not provide an output path, return the final report as

Markdown in the response body so it can be saved directly as a .md file.

Critical Constraints

  • Include only open, non-draft PRs. Draft PRs must never appear in the

final table.

  • Use check runs as the authoritative CI source when check runs exist for

the head commit. Do not use the legacy combined commit-status result as the

final CI verdict in that case.

  • Base-branch freshness must come from **GitHub mergeability / merge-state

signals**, not from local git guesses.

  • "Author to address comments" is mandatory when a PR has unresolved,

non-outdated review threads, even if CI is green.

  • Current sign-offs must apply to the current head commit. Ignore stale

approvals from older commits.

  • Sort the final table by freshness, oldest to newest. If freshness ties,

use PR age, then PR number, as stable secondary keys.

  • If a required field cannot be fetched, stop and tell the user what data is

missing instead of fabricating it.

  • If the report takes long enough for repository state to change mid-run,

re-check the live open, non-draft PR set before rendering and drop any PR

that is no longer in scope.

Implementation Hints to Avoid Common Failures

  • Paginate explicitly for REST endpoints that can exceed 100 items, notably:
  • pull-request issue comments
  • pull-request review comments
  • check runs on the head SHA
  • For GraphQL connections such as reviews and reviewThreads, check

pageInfo.hasNextPage. If true, paginate rather than truncating.

  • When deduplicating retried check runs, key by check name and keep the newest

attempt using completed_at, then started_at, then created_at.

  • When rendering Markdown from PowerShell, prefer building an array/list of

lines or using a single-quoted here-string. Avoid fragile inline escaping such

as \' inside single-quoted PowerShell strings.

  • After computing rows, verify the rendered row count exactly matches the final

in-scope PR count. If it does not, stop and reconcile the difference before

returning the report.

  • Exclude obvious automation accounts from human-owner and sign-off logic even

when they are not suffixed with [bot], for example Copilot,

copilot-swe-agent, and similar service identities if they appear.

  • Prefer a final short-lived re-fetch of the open PR inventory immediately

before rendering when the report required many per-PR API calls.

Workflow

Step 1: Scope the PR Set

  • Fetch the open PR inventory for microsoft/ebpf-for-windows.
  • Filter out any PR where isDraft == true or draft == true.
  • If the user asked for a narrower subset, apply that filter after you have

fetched the authoritative open, non-draft set.

  • Use structured output and pagination when needed. Do not rely on the web UI.

Recommended starting point:

gh api repos/microsoft/ebpf-for-windows/pulls `
  --paginate `
  -f state=open `
  -f per_page=100

Step 2: Gather Per-PR Metadata

For each PR in scope, fetch or derive at least these fields:

  • number
  • title
  • url / html_url
  • createdAt / created_at
  • author login
  • current head SHA / OID
  • reviewDecision
  • mergeable
  • mergeStateStatus or REST mergeability equivalent
  • requested reviewers
  • reviews, including reviewer login, state, submitted time, and the commit OID

the review applies to

  • review threads, including isResolved and isOutdated
  • issue comments
  • review comments
  • head commit timestamp

Prefer a GraphQL per-PR fetch for review and mergeability data so you can

query the current head commit, review threads, and review metadata in one

place. If one large query becomes unwieldy, split the work into:

  • PR inventory fetch
  • Per-PR detail fetch
  • Per-head-SHA check-run fetch

If a PR has more review threads, comments, or reviews than fit in one page,

paginate rather than silently truncating.

Recommended execution pattern:

  • Fetch the open, non-draft PR inventory.
  • Fetch per-PR detail and activity data, paginating where needed.
  • Compute all derived fields in structured data first.
  • Re-fetch the open, non-draft PR inventory if the run was long-lived.
  • Filter computed rows to the refreshed in-scope set.
  • Render Markdown only after the row set is complete and reconciled.

Step 3: Compute Age

  • Compute Age from created_at / createdAt to the report snapshot time.
  • Format exactly as <days>d with one decimal place, for example 53.6d.

Step 4: Compute CI Status

Use the PR head SHA and fetch check runs for that exact commit.

Recommended source:

gh api repos/microsoft/ebpf-for-windows/commits/<head-sha>/check-runs `
  -H "Accept: application/vnd.github+json"

CI rules:

  • Prefer check runs over the legacy combined commit-status API.
  • If multiple check runs represent retries of the same check, keep the latest

attempt for each check name.

  • Treat these conclusions as Passing:
  • success
  • neutral
  • skipped
  • Treat the PR as Pending if any relevant check run is not yet complete,

or if its status is queued / waiting / requested / in progress.

  • Treat the PR as Failing: <list of failing checks> if any relevant check

run concludes with a failing terminal result such as:

  • failure
  • cancelled
  • timed_out
  • action_required
  • startup_failure
  • stale
  • any other completed non-passing conclusion
  • Only if no check runs exist at all may you fall back to legacy status

contexts, and even then do not describe the result as check-run-derived.

  • Do not collapse a mixed state into "Passing" just because a combined status

summary looks green or pending.

  • If the check-runs endpoint returns more than one page, fetch all pages before

deciding CI state.

Format the final cell as exactly one of:

  • Passing
  • Pending
  • Failing: check-a, check-b

Step 5: Determine Base-Branch Freshness

Use GitHub mergeability / merge-state signals from the PR object.

Map them as follows:

  • Up to date
  • Use when the PR is not behind the base branch and is not in conflict.
  • Typical signals: mergeStateStatus like CLEAN, HAS_HOOKS, or

UNSTABLE, with mergeable not indicating conflicts.

  • Needs rebase/update
  • Use when the PR is behind the base branch but not in conflict.
  • Typical signal: mergeStateStatus == BEHIND.
  • Needs rebase/update (conflicts)
  • Use when GitHub reports merge conflicts or an equivalent dirty/conflicting

merge state.

  • Typical signals: mergeable == CONFLICTING or

mergeStateStatus == DIRTY.

If GitHub has not computed mergeability yet, wait briefly and re-fetch rather

than guessing from local branch ancestry.

Step 6: Determine Current Sign-Offs

Current sign-offs are approvals that still apply to the **current head

commit**.

Rules:

  • Start from the current head commit OID / SHA for the PR.
  • Consider only reviews from human reviewers that apply to that head commit.
  • Group reviews by reviewer login.
  • A reviewer counts as signed off if they have an APPROVED review on the

current head commit and do not have a later current-head review from the

same reviewer with state CHANGES_REQUESTED or DISMISSED.

  • A later COMMENTED review does not cancel an otherwise valid approval by

itself.

  • Ignore stale approvals on older commits.
  • Ignore bot and automation accounts where possible, for example accounts

whose type is not a human user or whose login ends with [bot].

Format Sign-offs as a comma-separated list of usernames, or None.

Step 7: Determine Next Step

Compute Next step in this order:

  • If there are any unresolved, non-outdated review threads, report:

Author to address comments

  • Else if GitHub reviewDecision == CHANGES_REQUESTED, report:

Author to address comments

  • Else if the PR has at least one current-head sign-off and CI is Passing,

report:

Ready to merge

  • Otherwise report:

Reviewers to review latest version

Do not treat outdated threads as blockers for this rule.

Step 8: Compute Freshness

Freshness is the age of the latest meaningful activity on the PR.

Candidate activity types:

  • head commit
  • review submission
  • issue comment
  • review comment

Rules:

  • Collect the latest timestamp for each activity type.
  • Pick the most recent timestamp across all candidate types.
  • Compute age from the report snapshot time.
  • Format exactly as <days>d (<activity type>), for example

1.0d (review comment).

  • If two activity types share the same timestamp, prefer this label order:
  • head commit
  • review submission
  • review comment
  • issue comment

Use review-thread comment timestamps for review comment, not the enclosing

thread creation time if newer comments exist.

Step 9: Determine Next Owner

Compute Next owner after Next step.

Rules:

  • If Next step is Author to address comments, set Next owner to the PR

author login.

  • Otherwise, use the current requested reviewers, excluding bots and

automation accounts where possible, for example accounts whose type is not

a human user or whose login ends with [bot].

  • If there are no current requested reviewers, use prior human reviewers or

commenters, excluding:

  • the PR author
  • bots and automation accounts
  • When using prior human reviewers/commenters, order them by most recent

meaningful participation first.

  • If no human next owner can be determined, report None.
  • Treat known service identities as non-human even if the platform does not

label them as bots.

Format multiple owners as a comma-separated list.

Step 10: Sort and Render the Report

The final report must be Markdown and must contain:

  • Header:
   # microsoft/ebpf-for-windows open non-draft PRs
  • A snapshot timestamp line.
  • An ordering note stating:

Sorted by freshness, oldest to newest.

  • A Markdown table with these columns in this exact order:
  • PR
  • Age
  • Freshness
  • CI
  • Base branch
  • Next step
  • Next owner
  • Sign-offs
  • PR column formatting:
  • #1234 PR title
  • Value formatting:
  • Age: 53.6d
  • Freshness: 1.0d (review comment)
  • CI: Passing, Pending, or Failing: <checks>
  • Sign-offs: comma-separated usernames or None
  • Final ordering:
  • primary key: freshness, oldest to newest
  • secondary key: PR age, oldest to newest
  • tertiary key: PR number, ascending
  • A closing Notes: section that briefly explains:
  • how freshness is computed
  • why check runs are preferred over combined commit status
  • how Author to address comments is decided
  • how Next owner is chosen

Do not include draft PRs anywhere in the table.

Verification Checklist

Before you finalize the report, verify all of the following:

  • Every row is an open, non-draft PR.
  • Every PR cell contains the PR number, URL, and title.
  • Age and Freshness use one decimal place and d units.
  • CI was computed from check runs whenever check runs existed.
  • Base branch uses GitHub mergeability / merge-state signals.
  • Next step uses unresolved non-outdated threads before review decision.
  • Sign-offs include only current-head approvals.
  • Next owner excludes bots where possible.
  • No row was lost during rendering: row count matches the final in-scope PR

count.

  • If the run was long-lived, the final in-scope PR set was refreshed just

before rendering.

  • The table is sorted by freshness, oldest to newest.
  • The report ends with a Notes: section covering the required heuristics.

Non-Goals

  • Do not review code content inside the PRs unless the user explicitly asks.
  • Do not include draft, closed, or merged PRs in this report.
  • Do not rely on GitHub's combined commit-status summary when check-run data is

available.

  • Do not guess stale approvals, mergeability, or next-owner state from local

git history alone.

How to use it

Copy the folder

Take microsoft/pr-triage-report from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.