Install
$ agentstack add skill-mitodl-agent-kit-github-pr-triage ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
GitHub PR Triage
Turns a sprawling list of open PRs into a report grouped by required action, and optionally executes that action. The core pattern is enumerate → enrich → classify → report → (optionally) act, using gh search prs / gh pr view for data and deterministic jq rules for the classification — no code archaeology needed, unlike issue triage.
Three deterministic scripts do the mechanical work, so most of this skill is about reading their output correctly and knowing when to escalate to judgment:
| Script | Purpose | |--------|---------| | scripts/fetch-prs.sh | Enumerate open PRs by author across an org | | scripts/enrich-prs.sh | Fetch review/check/mergeability detail per PR, in parallel | | scripts/classify-prs.sh | Bucket the enriched PRs by required action |
Action scripts (used only after explicit per-PR confirmation — see Phase 5):
| Script | Purpose | |--------|---------| | scripts/request-review.sh | Request a first-pass review from Copilot and/or Claude; refuses drafts and PRs that already have review activity | | scripts/merge-pr.sh | Merge an approved, green PR and delete its branch |
Scope: figure out mode before running anything
Two independent choices govern the whole run — resolve both up front, asking the user if either is ambiguous:
- Report or act? A pure status report never mutates anything. Acting means
requesting reviews, posting comments, pushing fixes, or merging — all of which are visible to others and some of which are hard to reverse. Default to report-only unless the user clearly asked to take action ("merge the ready ones", "kick off reviews", "clear my backlog").
- Which org/repo, which author? Default author is
@me(the currentgh
user) — this skill is built around "my open PRs", matching how the four buckets below are framed (things you, the author, are waiting on or need to act on). If the user wants PRs where they're a reviewer instead, that's a different query (gh search prs --review-requested @me) — say so rather than silently reinterpreting the request.
Phase 1 — Enumerate
./skills/process/github-pr-triage/scripts/fetch-prs.sh mitodl /tmp/prs_fetched.json
# or a non-default author:
./skills/process/github-pr-triage/scripts/fetch-prs.sh mitodl /tmp/prs_fetched.json --author someone-else
This is one gh search prs --owner --author --state open call, so it works across every repo in the org in one shot — no per-repo iteration needed. It captures number, title, url, repository, isDraft, createdAt, updatedAt, author, but not review state — GitHub's search JSON doesn't expose reviewDecision, so that requires a per-PR detail call (Phase 2).
Phase 2 — Enrich
./skills/process/github-pr-triage/scripts/enrich-prs.sh /tmp/prs_fetched.json /tmp/prs_enriched.json
Runs gh pr view per PR (8-way parallel) to pull reviewDecision, latestReviews, reviewRequests, statusCheckRollup, mergeable, mergeStateStatus, comments. For a normal backlog (tens of PRs) this takes a few seconds. If a single PR's detail fetch fails (deleted branch, permissions), it's silently dropped rather than aborting the whole run — check the count in the output message against the fetch count if that matters.
Phase 3 — Classify
./skills/process/github-pr-triage/scripts/classify-prs.sh /tmp/prs_enriched.json > /tmp/prs_classified.json
Buckets, in the order the report should present them (most actionable first):
| Bucket | Meaning | Typical action | |--------|---------|-----------------| | approved_ready_to_merge | APPROVED, mergeable, checks green | Merge | | approved_blocked | APPROVED but conflicting / checks red / mergeability not yet computed | Resolve conflict, fix CI, or just re-check later | | changes_requested | Formal CHANGES_REQUESTED review | Address feedback, push, re-request review | | has_review_comments | A review left in COMMENTED state (this is how Copilot, Gemini, and most review bots report findings — they rarely use formal approve/request-changes) but no formal decision | Read the comments, decide if they're addressed | | awaiting_review | A reviewer (human or bot) is requested; nothing submitted yet | Nothing to do — wait, or nudge if stale | | needs_first_pass_review | No reviews, no reviewer requested at all | Kick off a first-pass review | | draft | Not marked ready for review | Report separately; skip review/merge actions |
reviewDecision alone under-counts feedback. GitHub only sets it for formal APPROVED / CHANGES_REQUESTED reviews. Bot reviewers overwhelmingly leave COMMENTED-state reviews with the substance in the review body — those show up with reviewDecision: "" and land in has_review_comments. In practice this is usually the largest bucket. Don't skip it just because reviewDecision looks empty.
mergeable can be "UNKNOWN". GitHub computes mergeability lazily in the background; a PR that was just pushed to, or hasn't been polled recently, can show UNKNOWN even with no real conflict. classify-prs.sh surfaces this as blocked_reason: "unknown_pending_recompute" — re-run scripts/pr-detail.sh on that PR (or just gh pr view) after a few seconds before assuming it's actually blocked.
feedback_likely_addressed is a heuristic, not a verdict. For has_review_comments and changes_requested, the classifier compares the newest review's timestamp against the newest PR comment's timestamp — if a comment landed after the review, someone probably already responded. It has no visibility into new commits pushed without a comment, and it can't tell whether the response actually resolved the concern. Use it to prioritize which PRs to read first, never to skip reading them.
Phase 4 — Report
Present the classification as grouped markdown tables, ordered per the bucket table above (most actionable first), each PR as one row:
### ✅ Approved & ready to merge (3)
| PR | Title | Repo |
|----|-------|------|
| [#4902](https://github.com/mitodl/ol-infrastructure/pull/4902) | Add Pulumi program for ol-analytics-api K8s deployment | ol-infrastructure |
### 🚧 Approved but blocked (3)
| PR | Reason |
|----|--------|
| [#4693](...) | unknown_pending_recompute — re-check mergeability |
### 🔴 Changes requested (4)
...
### 💬 Has review comments — verify addressed (32, ~2 likely already addressed)
...
### ⏳ Awaiting review (N)
...
### 🆕 Needs first-pass review (1)
...
### 📝 Draft (2)
...
Keep rows terse — title, repo, one-line status. Put counts in the section headers so the user can see backlog shape at a glance. End with a one-line bottom line: "N ready to merge, M need your response, K just need a first pass."
If this is report-only, stop here.
Phase 5 — Act (only when the user asked for it)
Confirm before mutating anything per PR or per clearly-scoped batch — see [references/action-playbook.md](references/action-playbook.md) for the exact commands, confirmation phrasing, and edge cases for each bucket. Summary:
needs_first_pass_review— request a bot review with
scripts/request-review.sh [copilot|claude|all] (default all; it self-guards against drafts and PRs that already have review activity), and/or do an in-session first pass yourself. The portable path, which works on any platform including stock Pi, is this repo's [code-review](../code-review/SKILL.md) skill run against the PR number from a local checkout of that repo (it resolves the diff with gh pr diff ), or a direct gh pr diff -R read when no checkout is at hand. Claude Code's built-in /review is a Claude-specific alternative, used only where that command exists. Either way the result is a report; posting it on the PR is a separate, confirmed step.
approved_ready_to_merge— confirm per PR, then
scripts/merge-pr.sh [merge|squash|rebase]. Never batch-merge without the user seeing the specific list first.
changes_requested/has_review_comments(not likely addressed) —
read the actual review bodies and comments, check out the branch locally if code changes are needed, fix, push, then comment summarizing what changed (see the playbook for the multi-repo parallel-fix pattern).
awaiting_review— no action by default; offer to post a polite nudge
comment only for PRs stale beyond a threshold the user specifies.
approved_blocked— surface the reason; onlyunknown_pending_recompute
is safely auto-resolved by re-checking. Conflicts and failing checks need case-specific investigation.
draft— report only, never act.
See the playbook for command-level detail on each of these.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mitodl
- Source: mitodl/agent-kit
- License: BSD-3-Clause
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.