| name | monitor-pr |
| description | Monitor one or more GitHub PRs and maintain a live status table showing
title, link, check status, resolved/total comments, and reviewer approval.
Shows a Windows dialog when a PR is ready to merge.
Input: a comma-separated list of PR numbers, "mine", or "all".
|
| argument-hint | <pr-numbers | mine | all> |
Monitor PR
Poll GitHub PRs and print a live status table to the main chat. Alert when
a PR is ready to merge.
Input
Parse $ARGUMENTS:
| Value | Meaning |
|---|
Comma-separated numbers (e.g. 1234,5678) | Monitor those specific PRs |
mine | All open PRs authored by the current user |
all | All open PRs in the repo |
If $ARGUMENTS is empty, use the ask_user tool (not plain chat text)
to prompt the user with choices: mine, all, or a freeform list of PR
numbers. Do not proceed until the user has answered.
Prerequisites
- Verify
gh is installed and authenticated (gh auth status). If not,
link to https://github.com/cli/cli#installation and stop.
- Check if PowerShell is available (
powershell -Command "echo ok"). If
unavailable, skip dialog notifications and use text-only alerts.
Step 1: Resolve the PR list
gh pr view <number> --repo "BabylonJS/Babylon.js" --json "number"
gh pr list --repo "BabylonJS/Babylon.js" -A "@me" --json "number,title,url"
gh pr list --repo "BabylonJS/Babylon.js" --json "number,title,url"
Step 2: Build and display the status table
For each PR, gather the following data (this table describes the
columns — it is not the output format):
| Column | Source |
|---|
| PR | #<number> linked to the PR URL |
| Title | gh pr view --json "title" |
| Checks | gh pr view --json "statusCheckRollup" — ✅ all pass / ❌ N fail, M pending (ETA ~Xm) / ⏳ N pending (ETA ~Xm). See ETA note below. |
| Comments | GraphQL reviewThreads query — ✅ all resolved / ❌ N/M resolved |
| Approved | gh pr view --json "reviewDecision" — ✅ approved / ❌ not approved (the field is an enum, not a count) |
| Ready | ✅ ready if all checks pass AND approved AND all comments resolved, ❌ not ready otherwise |
Review threads require the GraphQL API since gh pr view --json does not
expose them:
gh api graphql -f query='
query {
repository(owner: "BabylonJS", name: "Babylon.js") {
pullRequest(number: <NUMBER>) {
reviewThreads(first: 100) {
totalCount
nodes { isResolved }
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads | {total: .totalCount, resolved: ([.nodes[] | select(.isResolved)] | length)}'
If totalCount > 100, the single-page query above will undercount
resolved threads. Page through with pageInfo { hasNextPage endCursor }
after: until all threads are fetched, then sum the resolved counts.
Checks ETA
When any checks are still running, compute a rough ETA before rendering
the table. The Checks cell is incomplete without it.
- For each in-progress check (
status != COMPLETED):
- For each queued / not-started check (
status == QUEUED or
missing startedAt): remaining = historical (full duration).
- Checks run in parallel, so the overall PR ETA is
max(remaining) across all pending checks — not the sum.
- Round to whole minutes. If the computed ETA is negative or < 1m,
show
<1m.
Cache historical durations per check name across PRs within a single
poll iteration to avoid redundant gh calls. Do not cache across
polls (stale data risk — see the polling rule below).
Output format
Only render the table after all per-PR data (including ETA) is
gathered. Every pending-checks cell MUST end with (ETA ~Xm) (or
~Xm+ / <1m) — no ETA means the data isn't ready yet.
Render as a markdown table, one row per PR, with the columns above
as headers in the same order. Do not transpose or split into per-PR
tables. Prefix with a header line showing the OS's local time, e.g.
PR Status — 2026-04-17 05:17 PM PDT (date or Get-Date).
Example:
| PR | Title | Checks | Comments | Approved | Ready |
|---|
| #1234 | Fix foo | ⏳ 2 pending (ETA ~5m) | ✅ all resolved (4/4) | ❌ not approved | ❌ not ready |
| #5678 | Add bar | ✅ all pass | ✅ all resolved | ✅ 1 approval | ✅ ready |
Step 3: Distinguish real failures from flakes
When checks fail, read the CI logs. Source depends on which CI the
check is on — look at statusCheckRollup[].detailsUrl to tell:
-
GitHub Actions (detailsUrl on github.com) — use GitHub MCP
get_job_logs, or gh run view <run-id> --log-failed.
-
Azure DevOps Pipelines (detailsUrl on dev.azure.com) — the
Babylon.js ADO org (babylonjs) allows anonymous API access;
no auth needed. The detailsUrl looks like
https://dev.azure.com/<org>/<project-guid>/_build/results?buildId=<id>&view=logs&jobId=<job-guid>.
Fetch the build timeline and then the failing record's log:
curl -s "https://dev.azure.com/<org>/<project-guid>/_apis/build/builds/<buildId>/timeline?api-version=7.0"
curl -s "<record.log.url>"
Filter timeline.records to the failing entries (result == "failed")
and read each .log.url. If a jobId is present in detailsUrl,
scope directly to that record's children.
Classification:
- Real failure — caused by changes in the PR. Show ❌ with a brief
error summary.
- Flake — a test that failed on some iterations and passed on others,
and is not a new test added in the PR. Show ⚠️ and note it as a
suspected flake.
Step 4: Poll loop
MANDATORY: You MUST implement a continuous polling loop. Do not
display the status once and stop. Do not suggest the user re-invoke the
skill to refresh. You must keep running and re-checking every ~5 minutes
until every monitored PR is merged or closed. Use sleep 300 (or
equivalent) between polls to wait 5 minutes, then re-fetch and print
the updated table. This is the core purpose of this skill.
How to poll
- After printing the initial status table, sleep for 5 minutes:
sleep 300
- After sleeping, re-fetch ALL PR data from scratch using the same
gh and GraphQL commands as Step 2. Every column — checks, comments,
approval, state — must be queried fresh from the API. Do not reuse
or cache any data from a previous polling iteration. New commits
can restart all checks, so data from a previous poll may be stale.
- Print the fully refreshed status table to the main chat.
- Repeat from step 1.
On each poll, also check
- If a PR becomes ready to merge (all checks pass, approved, all
comments resolved):
- Show a Windows dialog (if PowerShell is available):
powershell -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('PR #<number> — <title> — is ready to merge.', 'PR Ready', 'OK', 'Information')"
- Always also print a prominent message in the chat.
- If a PR is merged or closed, remove it from the table and note it.
When to stop
Stop polling only when:
- Every monitored PR has been merged or closed, OR
- The user explicitly tells you to stop.
Do NOT stop for any other reason. Do not stop because "polling isn't
practical in a chat session." Do not stop because "the user can re-invoke
the skill." The entire point of this skill is continuous, autonomous
monitoring.
Retriggering CI
If the user asks to retrigger CI (e.g. for flakes), push an empty commit:
git commit --allow-empty -m "retrigger CI"
git push
Never force push. Always use new commits.
Guidelines
- Always read CI logs on failures — don't guess at the cause.
- Print the status table to the main chat so the user can follow along.
- You MUST keep polling until all PRs are merged/closed or the user
tells you to stop. Do not exit early. Do not suggest the user
re-invoke the skill. This skill runs continuously.