Skip to content

Commit 4120d34

Browse files
using-systemclaude
andauthored
feat(skills): add github-complete-pr and rename github-pr to github-create-update-pr (#11)
* feat(skills): add github-complete-pr and rename github-pr to github-create-update-pr Add a new skill that defines post-merge cleanup steps (switch back to the repository default branch, fast-forward it, delete the feature branch locally and on the remote if it still exists). Rename the existing github-pr skill to github-create-update-pr to make room for the full create/update/complete PR lifecycle. Also drop the per-skill table and skill listing from README so the catalogue does not need updating on every new skill. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(skills): use explicit if/else for remote branch deletion in github-complete-pr The previous `git ls-remote ... && git push --delete ... || echo "already deleted"` chain would also print "already deleted" when `git push` itself failed (permissions, network), masking real errors. Replace both occurrences with an explicit `if/else` so `git push` failures surface as errors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(skills): harden github-complete-pr force-delete and full recipe Rule §4 now distinguishes MERGED from CLOSED (unmerged) when allowing force-delete, and calls out the data-loss tradeoff for closed branches whose commits live nowhere else. Full Recipe now enforces Rule §1 by capturing PR state and headRefName from `gh pr view` and aborting when state is OPEN, refuses to delete default/protected branches, and only force-deletes after state has been validated (no more unconditional `|| git branch -D`). Deriving FEATURE_BRANCH from the PR prevents a mistyped argument from targeting the wrong branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(skills): gate force-delete on MERGED state in github-complete-pr recipe The recipe's safe-delete fallback previously ran `git branch -D` whenever `-d` failed, even for CLOSED (unmerged) PRs. This contradicted Rule §4, which requires explicit user confirmation before discarding commits that live only on a closed-unmerged branch. The fallback now branches on $PR_STATE: auto force-delete for MERGED (safe — commits are preserved under a new hash on the default branch); abort with rerun instructions for any other state so the user must opt in explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(skills): add github-resolve-pr for triaging PR review comments Defines a consistent workflow for addressing review feedback on a PR: fetch unresolved threads via GraphQL, judge each comment on technical merit (not auto-accept for bots, not auto-reject for disagreement), apply fixes on the PR branch with conventional commits, always reply with either a fix summary or a rationale for declining, and only resolve threads after push + reply. Force-delete of threads declined without user authorization is explicitly forbidden. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(skills): address PR review feedback on resolve-pr and complete-pr - github-resolve-pr: align the frontmatter description and Overview with Rule §8 — only fixed threads (or declines the user explicitly authorized closing) should be resolved. Silent resolution of a decline is now explicitly called out as forbidden. - github-resolve-pr: replace the French word "traiter" in the trigger list with "handle" to comply with the docs-english skill. - github-complete-pr: validate $DEFAULT after `gh repo view` in the full recipe and abort with a clear error when empty (gh auth/config issues or not a git repo) before running any checkout or delete steps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(skills): verify CI workflow status in github-create-update-pr Add a new rule that requires verifying CI completion after `gh pr create` or any push updating an open PR. Detects absence of workflows and no-ops; otherwise waits via `gh pr checks --watch --fail-fast`, fetches failing logs with `gh run view --log-failed`, and categorises failures (code defect, broken workflow, pre-existing unrelated failure, flake) rather than blindly adding retries or `continue-on-error`. Explicitly forbids merging around red CI without informed authorization. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(skills): prefer --jq over -q and add pagination guidance - github-complete-pr: replace `-q` with `--jq` in all four `gh pr view` / `gh repo view` calls for consistency with the existing `github-actions` skill and readability. - github-resolve-pr: Rule §1 now calls out that the fixed-size GraphQL query can truncate on large PRs and points readers at the paginated Full Recipe snippet. The Full Recipe itself loops through `reviewThreads.pageInfo.endCursor` until `hasNextPage` is false and notes that per-thread `comments.pageInfo` also needs paginating when a thread has more than 20 turns. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(skills): resolve declined threads too in github-resolve-pr Previously Rule §8 required leaving declined threads unresolved unless the user explicitly authorized closing them. In practice this left threads open forever once the rationale was on the record, burying the still-actionable ones under noise. Flip the default: resolve every thread — fix or decline — as long as a substantive reply was posted first. Silent resolution (without a reply) remains explicitly forbidden. Also reframe Rule §8 around that single invariant (never resolve without replying) and call out the reviewer-pushback path where a re-opened thread must be treated as a fresh unresolved item. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f2fea77 commit 4120d34

5 files changed

Lines changed: 564 additions & 124 deletions

File tree

README.md

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ A curated collection of personal agent extensions, skills, and CLI hooks to enha
44

55
## Skills
66

7-
| Skill | Description |
8-
|-------|-------------|
9-
| `github-actions` | Enforces GitHub Actions best practices: pin actions to SHA, verify latest versions, add version comments |
10-
| `git-commit` | Enforces Conventional Commits specification for semantic versioning compatibility |
11-
| `github-pr` | Enforces Conventional Commits naming on PR titles for squash-merge and changelog generation |
7+
Each skill lives in its own directory under [skills/](skills/) with a `SKILL.md` describing when and how it applies. Browse that folder for the current catalogue — no listing is maintained here to avoid drift.
128

139
## Installation
1410

@@ -71,13 +67,7 @@ gemini extensions install https://github.com/using-system/ai-dev-extensions
7167

7268
```
7369
ai-dev-extensions/
74-
├── skills/ # Skills (one directory per skill)
75-
│ ├── github-actions/ # GitHub Actions best practices
76-
│ │ └── SKILL.md
77-
│ ├── git-commit/ # Conventional Commits for git
78-
│ │ └── SKILL.md
79-
│ └── github-pr/ # Conventional Commits for PR titles
80-
│ └── SKILL.md
70+
├── skills/ # Skills (one directory per skill, each with a SKILL.md)
8171
├── hooks/ # Hooks for CLI agents and git
8272
│ ├── session-start # Session start hook (multi-platform)
8373
│ ├── commit-msg # Git hook: validates Conventional Commits

skills/github-complete-pr/SKILL.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
---
2+
name: github-complete-pr
3+
description: "Use when a GitHub pull request has just been merged or closed - switches back to the repository default branch, syncs it, and deletes the now-obsolete feature branch both locally and on the remote if it still exists"
4+
---
5+
6+
# GitHub Complete PR
7+
8+
## Overview
9+
10+
Once a pull request is merged or closed, the feature branch is no longer needed. Leaving it around clutters the local repo and the remote, creates stale references, and confuses future `git branch` / PR listings. This skill defines the cleanup steps to run immediately after PR completion.
11+
12+
## When to Use
13+
14+
- A pull request has just been merged (squash, rebase, or merge commit)
15+
- A pull request has been closed without merging and the branch will not be reused
16+
- The user says things like "PR is merged", "done with that PR", "close it out", "clean up the branch"
17+
18+
## Do NOT Use When
19+
20+
- The PR is still open or in draft
21+
- The branch is shared with other collaborators who still have in-flight work on it
22+
- The branch is a long-lived branch (e.g. `develop`, `release/*`, `main`) — never delete these
23+
24+
## Rules
25+
26+
### 1. Confirm the PR is actually merged or closed
27+
28+
Before deleting anything, verify the PR state via `gh`:
29+
30+
```bash
31+
gh pr view <number-or-branch> --json state,mergedAt,headRefName,baseRefName
32+
```
33+
34+
Only proceed when `state` is `MERGED` or `CLOSED`. If the PR is still `OPEN`, stop and tell the user.
35+
36+
### 2. Identify the repository default branch
37+
38+
Do not assume `main`. Query it:
39+
40+
```bash
41+
gh repo view --json defaultBranchRef --jq .defaultBranchRef.name
42+
```
43+
44+
Use whatever it returns (`main`, `master`, `trunk`, etc.) as the checkout target.
45+
46+
### 3. Switch back to the default branch and sync
47+
48+
```bash
49+
git checkout <default-branch>
50+
git pull --ff-only origin <default-branch>
51+
```
52+
53+
Use `--ff-only` to avoid accidental merge commits if the local default branch has drifted.
54+
55+
### 4. Delete the local feature branch
56+
57+
```bash
58+
git branch -d <feature-branch>
59+
```
60+
61+
Use `-d` (safe delete) first. Git will refuse when the branch is not fully merged into the default branch — this is common and expected when the PR was squash-merged or rebase-merged (the tip commit of the feature branch is not an ancestor of `main`).
62+
63+
Force-delete with `-D` is acceptable **only** when one of the following is true, confirmed via `gh pr view`:
64+
65+
- `state` is `MERGED` — the changes exist on the default branch under a new commit hash; the original commits are redundant.
66+
- `state` is `CLOSED` **and** the branch was intentionally abandoned (the user confirms the work will not be reused).
67+
68+
```bash
69+
git branch -D <feature-branch>
70+
```
71+
72+
**Data-loss warning.** For a `CLOSED` (unmerged) PR, `-D` permanently discards any commits on that branch that live nowhere else — there is no remote copy to recover from once the remote branch is also deleted in step 5. Confirm with the user before force-deleting a closed-unmerged branch.
73+
74+
Never use `-D` without first confirming PR state via `gh pr view`.
75+
76+
### 5. Delete the remote branch if it still exists
77+
78+
Many PR workflows auto-delete the remote branch on merge, but not all. Check and clean up:
79+
80+
```bash
81+
git fetch --prune origin
82+
if git ls-remote --exit-code --heads origin <feature-branch> >/dev/null 2>&1; then
83+
git push origin --delete <feature-branch>
84+
else
85+
echo "Remote branch already deleted"
86+
fi
87+
```
88+
89+
`--prune` removes stale remote-tracking refs. The `ls-remote` check avoids a noisy error when the remote branch is already gone. The explicit `if/else` (instead of `A && B || C`) ensures a real `git push --delete` failure surfaces as an error rather than being swallowed by the "already deleted" message.
90+
91+
### 6. Confirm cleanup
92+
93+
Finish by showing the user the state so they can verify:
94+
95+
```bash
96+
git branch # local branches
97+
git branch -r # remote-tracking branches
98+
```
99+
100+
The feature branch must be absent from both.
101+
102+
## Full Recipe
103+
104+
The recipe below enforces Rule §1 (abort when `state` is `OPEN`) and Rule §4 (only force-delete after state validation), and derives `FEATURE_BRANCH` from the PR itself so a mistyped argument cannot cause the wrong branch to be deleted.
105+
106+
```bash
107+
PR=<branch-or-number>
108+
109+
# 1. Verify PR state and capture the exact head branch from the PR
110+
PR_STATE=$(gh pr view "$PR" --json state --jq .state)
111+
FEATURE_BRANCH=$(gh pr view "$PR" --json headRefName --jq .headRefName)
112+
113+
if [ -z "$PR_STATE" ] || [ -z "$FEATURE_BRANCH" ]; then
114+
echo "Could not determine PR state or head branch; aborting."
115+
exit 1
116+
fi
117+
118+
if [ "$PR_STATE" = "OPEN" ]; then
119+
echo "PR is still OPEN; refusing to delete anything."
120+
exit 1
121+
fi
122+
123+
# 2. Find default branch and refuse protected branches
124+
DEFAULT=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)
125+
126+
if [ -z "$DEFAULT" ]; then
127+
echo "Could not determine default branch (gh auth/config issue, or not a git repo); aborting."
128+
exit 1
129+
fi
130+
131+
if [ "$FEATURE_BRANCH" = "$DEFAULT" ] \
132+
|| [ "$FEATURE_BRANCH" = "main" ] \
133+
|| [ "$FEATURE_BRANCH" = "master" ] \
134+
|| [ "$FEATURE_BRANCH" = "develop" ] \
135+
|| [[ "$FEATURE_BRANCH" == release/* ]]; then
136+
echo "Refusing to delete protected or default branch: $FEATURE_BRANCH"
137+
exit 1
138+
fi
139+
140+
# 3. Switch + sync
141+
git checkout "$DEFAULT"
142+
git pull --ff-only origin "$DEFAULT"
143+
144+
# 4. Delete local branch — safe delete first; auto-force-delete only for MERGED PRs.
145+
# For CLOSED (unmerged) PRs, abort and require the user to explicitly confirm data loss.
146+
if ! git branch -d "$FEATURE_BRANCH"; then
147+
if [ "$PR_STATE" = "MERGED" ]; then
148+
echo "Safe delete failed (squash/rebase merge rewrote history). Force-deleting merged branch: $FEATURE_BRANCH"
149+
git branch -D "$FEATURE_BRANCH"
150+
else
151+
echo "Safe delete failed because the branch is not fully merged."
152+
echo "PR state is $PR_STATE (not MERGED). Refusing to force-delete without explicit confirmation that the work is abandoned."
153+
echo "If you have confirmed the branch can be discarded, rerun manually:"
154+
echo " git branch -D \"$FEATURE_BRANCH\""
155+
exit 1
156+
fi
157+
fi
158+
159+
# 5. Prune + delete remote branch if still present
160+
git fetch --prune origin
161+
if git ls-remote --exit-code --heads origin "$FEATURE_BRANCH" >/dev/null 2>&1; then
162+
git push origin --delete "$FEATURE_BRANCH"
163+
else
164+
echo "Remote branch already deleted"
165+
fi
166+
167+
# 6. Verify
168+
git branch
169+
git branch -r
170+
```
171+
172+
## Red Flags — STOP
173+
174+
- PR state is `OPEN` → do not delete anything
175+
- Current branch has uncommitted changes → stash or commit before switching
176+
- Feature branch name matches the default branch or a protected pattern (`main`, `master`, `develop`, `release/*`) → never delete
177+
- Force-delete (`-D`) is needed but PR merge state is unverified → verify first
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
name: github-create-update-pr
3+
description: "Use when creating or updating GitHub pull requests - enforces Conventional Commits naming convention on PR titles for semantic versioning and squash-merge compatibility, and verifies that CI workflows (if any) complete successfully before handing the PR back to the user"
4+
---
5+
6+
# GitHub Create/Update PR Convention
7+
8+
## Overview
9+
10+
All GitHub pull request titles MUST follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. When a repo uses squash-merge, the PR title becomes the commit message, so it must be a valid conventional commit to enable automatic semantic versioning and changelog generation.
11+
12+
## When to Use
13+
14+
- Creating a new pull request
15+
- Updating an existing PR title or body
16+
- When a user asks about PR naming conventions
17+
18+
## Format
19+
20+
PR title follows the same format as a conventional commit:
21+
22+
```
23+
<type>(<scope>): <description>
24+
```
25+
26+
### Types
27+
28+
| Type | Description | SemVer Impact |
29+
|------|-------------|---------------|
30+
| `feat` | New feature | MINOR |
31+
| `fix` | Bug fix | PATCH |
32+
| `docs` | Documentation only | - |
33+
| `style` | Formatting, no code change | - |
34+
| `refactor` | Code restructuring, no behavior change | - |
35+
| `perf` | Performance improvement | PATCH |
36+
| `test` | Adding or correcting tests | - |
37+
| `build` | Build system or dependency changes | - |
38+
| `ci` | CI configuration changes | - |
39+
| `chore` | Maintenance, no src/test change | - |
40+
| `revert` | Reverts a previous change | - |
41+
42+
### Breaking Changes
43+
44+
Indicate breaking changes with `!` after the type/scope:
45+
46+
```
47+
feat(api)!: remove deprecated v1 endpoints
48+
```
49+
50+
## Rules
51+
52+
### 1. PR title must be a valid conventional commit
53+
54+
```
55+
# BAD
56+
Add login page
57+
Feature: login page
58+
[FEAT] Add login page
59+
60+
# GOOD
61+
feat: add login page
62+
feat(auth): add login page
63+
```
64+
65+
### 2. Same rules as git-commit for the title line
66+
67+
- Lowercase description
68+
- Imperative mood ("add" not "added" or "adds")
69+
- No period at the end
70+
- Type is mandatory, scope is optional but encouraged
71+
72+
### 3. PR body should complement the title
73+
74+
The PR body is free-form but should include:
75+
- **What**: summary of changes
76+
- **Why**: motivation and context
77+
- **How to test**: steps for reviewers
78+
79+
### 4. One logical change per PR
80+
81+
A PR should map to a single conventional commit type. If a PR contains both a feature and a refactor, the dominant change defines the type.
82+
83+
### 5. Branch name should align with PR title
84+
85+
```
86+
# PR title: feat(auth): add OAuth2 login flow
87+
# Branch name:
88+
feat/auth-oauth2-login-flow
89+
90+
# PR title: fix(api): handle null payment response
91+
# Branch name:
92+
fix/api-null-payment-response
93+
```
94+
95+
### 6. Verify CI workflows after creating or updating the PR
96+
97+
After every `gh pr create` or push that updates an open PR, check whether the repository has CI workflows that run on `pull_request` (or equivalent) and confirm they pass before handing control back to the user. Do not declare the PR ready if checks are red or still running.
98+
99+
#### Detect whether the repo has CI
100+
101+
```bash
102+
# Any workflows defined?
103+
ls .github/workflows 2>/dev/null
104+
105+
# What checks are expected on this PR?
106+
gh pr checks <pr-number-or-branch>
107+
```
108+
109+
If `.github/workflows/` is absent or empty **and** `gh pr checks` reports no checks, skip the rest of this rule — there is nothing to verify.
110+
111+
#### Wait for checks to complete
112+
113+
```bash
114+
gh pr checks <pr-number-or-branch> --watch --fail-fast
115+
```
116+
117+
`--watch` streams status until every check reaches a terminal state; `--fail-fast` returns a non-zero exit code as soon as one check fails so you can react immediately.
118+
119+
#### If checks pass
120+
121+
Report success to the user with the PR URL. Done.
122+
123+
#### If checks fail
124+
125+
1. Identify the failing job(s):
126+
127+
```bash
128+
gh pr checks <pr-number-or-branch>
129+
gh run list --branch <branch> --limit 5
130+
```
131+
132+
2. Fetch the failing logs:
133+
134+
```bash
135+
gh run view <run-id> --log-failed
136+
```
137+
138+
3. Diagnose the root cause before reacting. Do **not** blindly add retries, `continue-on-error`, or workflow edits just to make the red turn green — that hides real defects. Common categories:
139+
140+
- **Code defect in the PR** → fix the code, commit, push, re-verify.
141+
- **Broken workflow (misconfigured action, missing secret, wrong version pin)** → fix the workflow per the `github-actions` skill, commit, push, re-verify.
142+
- **Pre-existing failure unrelated to this PR** → stop, surface it to the user with the log evidence, and let them decide whether to fix here or in a separate PR.
143+
- **Flake** → rerun once via `gh run rerun <run-id>`. If it fails again, treat as a real defect.
144+
145+
4. After any fix, push and re-run `gh pr checks --watch --fail-fast` to confirm green.
146+
147+
#### Never merge around red CI
148+
149+
If the user asks you to merge while checks are failing, refuse and explain the failing checks. Merging past red CI is a destructive action — require explicit, informed authorization.
150+
151+
## Examples
152+
153+
```
154+
# Feature
155+
feat(dashboard): add real-time metrics widget
156+
157+
# Bug fix
158+
fix(auth): prevent token refresh race condition
159+
160+
# Documentation
161+
docs(readme): add installation guide
162+
163+
# CI improvement
164+
ci(workflows): pin GitHub Actions to SHA
165+
166+
# Breaking change
167+
feat(api)!: migrate from REST to GraphQL
168+
```

0 commit comments

Comments
 (0)