From 395f655ff11c62e1e4b1bf173218dd1feaf166ca Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 7 Oct 2026 22:20:21 +0000 Subject: [PATCH] Add /merge-green-prs skill: merge green PRs from claude/* branches Checks each open PR fresh from GitHub, merges only claude/* same-repo PRs that are clean with all checks passed and no changes requested, pinned to the head SHA. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_014k4kywyN5dAo39izUPvxbw --- .claude/skills/merge-green-prs/SKILL.md | 33 +++++++++++++++++++++++++ CLAUDE.md | 1 + 2 files changed, 34 insertions(+) create mode 100644 .claude/skills/merge-green-prs/SKILL.md diff --git a/.claude/skills/merge-green-prs/SKILL.md b/.claude/skills/merge-green-prs/SKILL.md new file mode 100644 index 0000000..10b86f2 --- /dev/null +++ b/.claude/skills/merge-green-prs/SKILL.md @@ -0,0 +1,33 @@ +--- +name: merge-green-prs +description: Check this repo's open pull requests and merge the ones from claude/* branches whose tests have passed. Use when asked to merge green PRs, watch PRs, or clear the PR queue. Never merges a PR from any other branch. +--- + +# Merge green PRs + +Repo: the current repository (`owner/repo` from the git remote). Use the GitHub MCP tools (`mcp__github__*`), never `gh`. + +## Which PRs are eligible +A PR is merged only if ALL of these hold; otherwise report it and leave it alone: +1. Open and not a draft. +2. Head branch starts with `claude/` and lives in this same repo (not a fork). +3. Base branch is the default branch. +4. `mergeable_state` is `clean` (not `blocked`, `behind`, `dirty`, `unstable`, `draft`, `unknown`). +5. Its check runs (`get_check_runs`) exist, are all `completed`, and every one has conclusion `success`. +6. No review with `CHANGES_REQUESTED` (`get_reviews`) and no unresolved review thread (`get_review_comments`). + +## Steps +1. `list_pull_requests` (state `open`). Skip, with the reason, everything that fails 1-3. +2. For each remaining PR, read it fresh from GitHub: `pull_request_read` `get`, `get_check_runs`, `get_reviews`, + `get_review_comments`. Never rely on earlier results or memory for a PR's state. +3. Checks still `queued` or `in_progress` -> "waiting", do nothing. Any failure -> "red", say which check, do not merge. + `behind` or conflicted -> report; do not update the branch or merge without being asked. +4. Eligible -> `merge_pull_request` with `merge_method: merge` and `expectedHeadSha` set to the head SHA you just read + (so a push that lands in between aborts the merge). +5. Read the PR back from GitHub and confirm `merged: true`. If the session was subscribed to it, unsubscribe. +6. Finish with one table: PR number and title, outcome (merged / waiting / red / blocked / skipped), and the reason. + +## Never +- Merge a PR from a branch that doesn't start with `claude/`, a fork, a draft, or one with a failing, missing or pending check. +- Skip, disable or re-run tests to get green; push to a PR's branch; force-push; approve reviews; close PRs; delete branches. +- State a PR's status without reading it from GitHub in this run. diff --git a/CLAUDE.md b/CLAUDE.md index 32389d5..82b0369 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,6 +7,7 @@ MCP data tools and web search. User-facing docs are in `README.md`; this file is - `make check`: ruff + pytest (no network, a few seconds). Run it before every commit, on Python 3.13.5 (production; `uv venv --python 3.13.5`). GitHub CI runs the latest stable Python and Node.js instead, to catch breakage from the next upgrade early. - `make prompt-report`: token breakdown of a sample request. `python bot.py [label]` runs the bot. +- `/merge-green-prs` (`.claude/skills/merge-green-prs/SKILL.md`): check open PRs and merge the green ones from `claude/*` branches. - Tests use fakes (`tests/conftest.py`: FakeBot, user_msg; `tests/fakes.py`: ScriptedBackend, FakeMcp, fake SDK clients; `tests/fixtures/` real anonymised MCP output). Add a test next to the module you change; don't write scratch scripts.