Submit pr
Open or update exactly one GitHub pull request from an already-committed branch — a Conventional-Commit title, a body a reviewer reads in 30 seconds (Summary, Changes, Verification, Test plan), driven to green CI, then subscribed to respond to reviewer code-change comments until merged. Use when asked to open a PR, submit a PR, raise a pull request, or push a branch for review. Stops for title and body approval; never merges or approves.From its SKILL.md
npx -y skills add jaredwray/agentic --skill submit-prAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
28.0 KB, as published. Nobody here has run it
Submit a Pull Request to GitHub
Operation manual for opening (or updating) a single pull request on GitHub from a branch that is already committed locally. The deliverable is a PR URL with a Conventional-Commit-compliant title, a structured body the reviewer can read in 30 seconds, green CI, and a PR that stays responsive to reviewer code-change suggestions until it's merged or closed. One PR per invocation.
When this document is loaded, begin executing immediately. Do not ask the user what to do — start with Workflow Step 1. Step 1 figures out what is being shipped (which branch, which base, which commits). Only stop to ask when the document explicitly says to stop and report.
Persona. Act as a release engineer who treats the PR title as the permanent commit log entry. Once this PR merges, the title is what
git logshows for the rest of the project's life. Spend the effort on the title and body that a careful reviewer would expect — not a minute less, not a minute more.Three stop points in the happy path before green and one quiet phase after: (a) a dirty working tree on entry — stop and tell the user to commit or stash first; (b) the title-and-body draft — present it once and wait for approval before any push; (c) CI is green on the opened PR — report, then proceed to (d) subscribe to PR activity and end the turn, resuming only when a reviewer comment arrives. Everywhere else the agent proceeds autonomously, including pushing fixes when CI fails and pushing fixes for agreed-with review suggestions per Reference § 6.
One PR per invocation. Drive one PR to "open + green + subscribed" and stop. Do not approve, merge, enable auto-merge, request reviewers, or set labels — those are the maintainer's calls, not the agent's.
Scope
In scope: opening or updating exactly one PR for a feature branch that is already committed locally, and keeping that PR responsive to reviewer code-change suggestions until it's merged or closed. The agent:
- Identifies the change set (current branch vs. default branch).
- Picks a single Conventional Commit type (
feat,fix,perf,refactor,style,test,docs,chore,build,ci,revert, with optional!for breaking) and composes a compliant title. - Renders a PR body using the project's standard skeleton (Summary / Changes / Verification / Test plan).
- Pushes the branch and posts the PR via the GitHub MCP tools.
- Drives CI to green by diagnosing failures, pushing fixes, and rechecking — until every required check passes or the failure is a known flake on
main. - Subscribes to PR activity and responds to every non-self review comment that suggests a code change — either applying the fix and acknowledging with the new commit SHA, or replying with the concrete reason for disagreement. See Reference § 6.
Out of scope:
- Writing the underlying commits before the PR is open. This document assumes the branch is committed when the workflow starts. If the working tree is dirty, stop and ask the user to commit or stash first — do not commit on their behalf. (Fixes pushed in response to CI failures or to agreed-with review suggestions are in scope; they are this primitive's job.)
- Reviewing this PR's own diff. Critiquing the agent's own change for bugs, security, or architecture is a different job — defer to the
code-reviewskill. This primitive only reacts to reviews left by others. - Release cuts. Version bumps,
CHANGELOG.mdupdates, and release notes are owned by therelease-cutskill. Do not run that workflow from here. - Approving, merging, enabling auto-merge, requesting reviewers, or setting labels. These are maintainer actions, not agent actions.
Workflow
Run these steps on the first invocation, and again on every resume when the user says submit again, update the PR, next branch, or similar.
-
Identify the change set. Resolve the default branch ref with
git symbolic-ref --short refs/remotes/origin/HEAD(typicallyorigin/mainororigin/master); if that command fails, fall back to whichever oforigin/mainororigin/masterexists. Strip theorigin/prefix to get the bare base branch name (e.g.origin/main→main) — Step 7 passes that bare name as thebaseargument tomcp__github__create_pull_request, which rejects remote-prefixed refs. Resolve the current branch withgit rev-parse --abbrev-ref HEAD. If the current branch is the default branch, or HEAD is detached, stop and report — there is nothing to open a PR for.Collect the change set:
git log <base>..HEAD --oneline— the commits this PR will contain.git diff <base>...HEAD --stat— the file-level summary (three-dot, so it's against the merge base).
Record: base ref, head ref, commit count, files-changed count, lines added/removed. Stop and report if the commit count is zero.
-
Check the working tree and remote. Run
git status --short. If output is non-empty, stop and report: "Working tree has uncommitted changes — commit or stash first, then re-run." Do not commit on the user's behalf; this primitive only opens PRs for already-committed work.Resolve the upstream with
git rev-parse --abbrev-ref --symbolic-full-name @{u}(suppress stderr). If no upstream is set, the push in Step 7 will need-u origin <branch>. If nooriginremote exists at all, stop and tell the user togit remote add origin <url>— do not invent a URL. -
Check for an existing PR on this branch. Call
mcp__github__list_pull_requestswithhead=<owner>:<branch>andstate=open. If a PR already exists for this branch, switch to update mode for Steps 6–7: the existing PR's number is the target,mcp__github__update_pull_requestis the write call, and the user is told upfront that this is an update, not a new PR.If zero PRs match, the agent is in new-PR mode. If multiple open PRs match (rare — usually a stale fork PR), stop and ask which one to update, or whether to open a new one against a different base.
-
Draft the title. Apply Reference § 1 (format rules) and Reference § 2 (type selection). The title is a single line:
<type>(<optional-scope>)<optional-!>: <imperative subject>- One Conventional Commit type. When commits span categories, pick the highest-impact one that any commit forces (see § 2).
- ≤70 characters total. Imperative mood (
add, notadded/adds). Lowercase subject. No trailing period. No issue number in the title — link issues in the body. - Add
!before the colon and aBREAKING CHANGE:paragraph in the body's Summary when any commit is breaking.
-
Draft the body. Render per Reference § 3. The skeleton is fixed:
Summary,Changes,Verification,Test plan. Rules:- Bullets in
Changescome from the actual commit log — one line per commit (or per logical group of commits if a PR was iterated locally). Do not paraphrase the diff; the reviewer has the diff. - Checkboxes in
Verificationare only for things the agent actually ran. An unchecked box is fine; a checked box that wasn't run is a lie. Test plandescribes how a reviewer would verify the change in a fresh checkout — commands, URLs, expected output.- If any commit message contains
Closes #<n>,Fixes #<n>, or similar, surface those in the Summary so GitHub auto-closes the issue on merge.
- Bullets in
-
Stop and present the title + body for approval. This is the only approval gate. Show, in one chat message:
- Mode:
new PRorupdate PR #<n>. - Base → head:
main ← feat/retry-budget(with the resolved refs). - Title: the drafted title, in a single-backtick code span so the user can copy it.
- Body: the full rendered markdown body, wrapped in a four-backtick fenced block so any internal three-backtick fences render verbatim.
- Change summary:
<n> commits, <m> files changed, +<add>/−<rm>. - Draft state:
ready(the default) ordraft(only if the user has previously asked, or local checks haven't been run). - A literal prompt to approve, e.g. "Reply
ship it(orlgtm,approved) to push and open. Reply with edits (e.g.change type to fix,drop the scope,rewrite the summary) for changes first."
Then wait. Do not push. Do not call any GitHub MCP write tool. The agent only proceeds on explicit approval.
- Mode:
-
Push and open (or update). On approval:
- Push.
git push -u origin <branch>if no upstream is set, otherwisegit push. If the push is rejected because the remote has new commits (rare for a feature branch the agent owns), stop and report — do not force-push without an explicit instruction. - Open or update. In new-PR mode:
mcp__github__create_pull_requestwithowner,repo,title,body,head=<branch>,base=<default-branch>,draft=false. In update mode:mcp__github__update_pull_requestwithpull_number=<n>,title,body. - Capture the result. Record the PR number, URL, and the SHA the PR currently points at.
- Push.
-
Drive CI to green. Poll the PR's check runs via
mcp__github__pull_request_read(requestmethod: "status"or the checks view). For each failing check:- Read the failure (job logs, failed test names, error output).
- Decide: is this a real failure (introduced by this PR) or flaky on
maintoo (intermittent, unrelated)? Confirm flakes by checking the same check on the latestmainSHA. - If real: fix it locally (the same way you would for any bug — see the
debugskill if needed), commit with a focused message (fix: <what>ortest: <what>), push, and re-poll. - If flake: leave a one-line PR comment via
mcp__github__add_issue_commentcalling out the flake (with a link to themainfailure), and treat the check as passing for the purpose of this workflow.
Cap the fix-and-push loop at 3 iterations. If CI is still red after 3 attempts, stop and report the remaining failures with diagnosis — the user decides whether to keep going.
On green (every required check passing, or the only red checks are confirmed flakes with comments), report:
- PR URL, number, title.
- Final commit SHA.
- Check summary:
<n> passed, <m> flaky-on-main(orall green). - The next manual step is the maintainer's: review and merge.
Then proceed to Step 9. Do not request reviewers, do not add labels, do not enable auto-merge, do not merge — those remain the maintainer's calls.
-
Subscribe to PR activity, then end the turn. Call
mcp__github__subscribe_pr_activitywith the PR number from Step 7 and end the turn. The session resumes only when a<github-webhook-activity>event arrives. From this point on, the agent's job is to react to reviewer comments per Reference § 6 — not to keep working on its own and not to poll. Callmcp__github__unsubscribe_pr_activityonly when the PR is merged or closed, or the user saysstop watching,unsubscribe, ordone with this PR.
Reference
Section numbers below are referenced from the workflow above.
1. Title format
The title is one line, in this shape:
<type>(<optional-scope>)<optional-!>: <subject>
| Element | Rule |
|---|---|
<type> | Required. Exactly one of the 11 Conventional Commit types in § 2. |
(<scope>) | Optional. The slice of the codebase the change touches — usually a package name (feat(api):), a subsystem (fix(parser):), or a directory (docs(readme):). Omit when the change spans multiple scopes or the repo has no clear scoping. |
! | Optional. Append ! before the colon for any breaking change. Always pair with a BREAKING CHANGE: paragraph in the body's Summary. |
: <subject> | Required. Colon, single space, then the imperative-mood subject. |
Subject rules:
- ≤70 characters total (title length, not just the subject). GitHub truncates longer titles in the commit list.
- Imperative mood.
add retry budget, notadded retry budget, notadds retry budget, notadding retry budget. The test: the subject should complete the sentence "If applied, this commit will ___". - Lowercase.
add, notAdd. Exception: proper nouns and identifiers keep their casing (add OAuth2 support,update CHANGELOG.md). - No trailing period. Titles are headlines, not sentences.
- No issue numbers.
#123belongs in the body (Closes #123), not the title. The title is the permanent log entry; issue links rot. - No conjoined types.
feat+fix:andfeat: ... and fix: ...are not valid. Pick one type (§ 2 explains how).
Good titles:
feat(retry): add exponential backoff with jitter
fix(parser): handle UTF-8 BOM in source files
perf: avoid quadratic scan in dependency resolver
refactor(auth)!: split session store into its own module
docs: document the rate-limit headers
chore(deps): bump tsx to 4.20.0
Bad titles (and what's wrong):
Update stuff # no type, vague subject
feat: Added new endpoint. # past tense, capitalized, trailing period
fix #123: parser bug # issue number in title
feat+fix: retry + parser fix # multi-type
chore: rewrite the entire auth layer to use OAuth2 and add session support # >70 chars, and chore: is wrong (it's a feat)
2. Conventional Commit type selection
Pick one type. When the PR contains commits spanning multiple types, pick the highest-impact type that any commit in the PR forces.
| Type | Use when… | Impact (high → low) |
|---|---|---|
feat | The PR adds a user-visible feature, capability, option, flag, or public API. | 1 (highest) |
fix | The PR fixes a bug — observed wrong behavior becomes right. | 2 |
perf | The PR improves performance without changing observable behavior. | 3 |
refactor | The PR restructures code without changing behavior or performance. If it touches the public API, consider feat instead. | 4 |
style | Pure formatting / whitespace / lint fixes. No logic change. | 5 |
test | Adds or fixes tests only. No production code change. | 6 |
docs | Documentation-only changes (README, comments, the docs/ tree, this very file). | 7 |
chore | Maintenance that doesn't fit elsewhere: dep bumps, repo plumbing, internal scripts, codeowners updates. | 8 |
build | Changes to the build system or external dependencies (bundler config, lockfile-only changes, Dockerfile). | 9 |
ci | Changes to CI configuration (.github/workflows/, CI scripts, release pipelines). | 10 |
revert | A revert of a previous commit. The body must reference the reverted SHA. | matches the reverted commit's type (inherits its impact number) |
Breaking changes override everything. Any commit that removes, renames, or incompatibly changes a public API is a breaking change. Mark the title with ! (e.g. feat(api)!: rename listSessions to listActiveSessions) and include a BREAKING CHANGE: paragraph in the body's Summary describing the break and the migration. See the release-cut skill § 1 for how breaking changes flow through semver — this primitive only needs to flag them; the release-cut workflow handles the version bump.
Decision rule for mixed-type PRs: walk every commit, classify it, then pick the lowest-numbered type on the table above. A PR with one feat: commit and ten chore: commits is a feat: PR. A PR that adds a feature and fixes an unrelated bug should usually be split into two PRs — but if it isn't, the title is feat: and the body's Changes section calls out the bug fix as a second bullet.
Anti-pattern: using chore: to hide a user-facing change because the diff is small. If a user can observe the change, it is feat / fix / perf / refactor — not chore.
3. PR body template
Render the body in this exact shape. Drop empty sections (no Verification block if nothing was run), but keep the section order.
## Summary
<2–4 sentences. What this PR does and why. Lead with the user-visible change, not the implementation. If breaking, lead with the breaking change.>
<For breaking PRs only:>
**BREAKING CHANGE:** <what breaks, in one sentence>.
**Migration:** <how consumers update, in one sentence>.
Closes #<n>. <!-- optional, only if a commit references it -->
## Changes
- <one bullet per commit (or per logical group), in commit order — strip the `type:` prefix, keep the subject>
- <…>
## Verification
- [x] <local check that was actually run, e.g. `pnpm test` passes locally>
- [x] <e.g. manual smoke test of the new endpoint at `/api/sessions`>
- [ ] <unchecked box for something a reviewer should verify but the agent couldn't, e.g. `production smoke test after deploy`>
## Test plan
- <how a reviewer reproduces the change in a fresh checkout>
- <commands, URLs, expected output>
- <edge cases worth poking at>
Rules for the body:
- No diff paraphrase. The reviewer has the diff. The body explains intent — what changed in the user's world, not what changed in the source tree.
- No marketing. "Massively improved performance" → "reduces median response time from 240ms to 80ms on the
/searchendpoint." - Checkboxes are promises. A checked box says "I ran this and it passed." Never check a box for something you didn't run. Unchecked boxes are an acceptable handoff to the reviewer.
- Link issues, don't repeat them.
Closes #123is enough. Do not paste the issue body into the PR. - Keep
Test planreproducible. Vague test plans (make sure it works) are not test plans. Name the commands, the URLs, the expected output.
4. Branch & commit hygiene
The agent does not create commits in this workflow (that's out of scope), but the branch state affects the PR.
- Branch naming. When the branch is being created elsewhere, prefer
<type>/<short-slug>(feat/retry-budget,fix/parser-bom,docs/submit-pr-primitive). The branch name is not the title — but a good slug makes the PR list scannable. - Single-commit PRs in squash-merge repos. When the PR contains one commit, the commit subject and the PR title should match. GitHub uses the PR title as the squash-merge subject by default, so a mismatch creates a third version of the message in
git log. - Multi-commit PRs. The PR title summarizes the whole change. Individual commit subjects can be more granular. They will be preserved on
rebase-and-merge, replaced by the PR title onsquash-and-merge, and noisy oncreate-a-merge-commit— match the repo's merge policy. - Rebase before push. When the base branch has moved significantly, rebase onto it (
git fetch origin && git rebase origin/<base>) before pushing. A PR that conflicts on day zero is a worse review experience than one that's already integrated. - Force-push policy for update mode. When updating an existing PR, force-push (
git push --force-with-lease) only when rebasing or rewriting history is necessary. For new commits on top, a regular push is enough and preserves review comment line numbers.
5. Posting via GitHub MCP
Use the GitHub MCP tools — not gh CLI, not raw API. The tools accept structured arguments and the agent has scoped repository permissions.
| Tool | Used in | Required args |
|---|---|---|
mcp__github__list_pull_requests | Step 3 — dedupe | owner, repo, head=<owner>:<branch>, state=open |
mcp__github__create_pull_request | Step 7 — new-PR mode | owner, repo, title, body, head, base, draft=false |
mcp__github__update_pull_request | Step 7 — update mode | owner, repo, pull_number, title, body |
mcp__github__pull_request_read | Step 8 — CI polling, Step 9 — fetching review threads | owner, repo, pullNumber, method (get_status, get_check_runs, get_review_comments, get_reviews, get_comments as needed) |
mcp__github__add_issue_comment | Step 8 — flake comment | owner, repo, issue_number=<pull_number>, body |
mcp__github__subscribe_pr_activity | Step 9 — start monitoring | owner, repo, pullNumber |
mcp__github__add_reply_to_pull_request_comment | § 6 — inline reply on a review thread | owner, repo, pullNumber, commentId, body |
mcp__github__resolve_review_thread | § 6 — close an agreed-and-fixed thread | owner, repo, threadId (GraphQL node ID from get_review_comments) |
mcp__github__unsubscribe_pr_activity | § 6 — stop monitoring on merge/close or user request | owner, repo, pullNumber |
Defaults to enforce:
draft: false. Open PRs as ready for review, not draft. Draft mode hides the PR from review queues and bypasses required-reviewer policies — use it only when the user explicitly asks, or when local checks haven't been run and the PR exists just to share a WIP link.- Do not call
mcp__github__merge_pull_request,mcp__github__enable_pr_auto_merge,mcp__github__pull_request_review_write(forAPPROVE), ormcp__github__request_copilot_reviewfrom this workflow. Merging and approving are out of scope.
Fallback when MCP is unavailable. If the GitHub MCP server is disconnected (the tools fail with "tool not found" or similar), do not improvise with gh CLI or curl — that's a different transport with different auth. Stop and report the title + body to the user so they can open the PR by hand. The agent's job ends at "PR content drafted, transport unavailable."
6. Handling code-change review comments
Once Step 9 has subscribed the session, every <github-webhook-activity> event for a non-self review comment that targets a specific piece of this PR's code — an inline review-thread comment, a RequestedChanges review body that names a concrete change, a bot suggestion with a code block (CodeQL, Copilot review, Gemini, etc.) — is mandatory to handle. Self-authored comments are skipped. There are exactly two responses for code-change comments, and there is no third "ignore" path.
Classifying the comment. Before responding, fetch the thread context with mcp__github__pull_request_read method=get_review_comments (for inline threads) or get_reviews / get_comments for top-level review and PR-level comments. A comment is a code-change comment when it asks for a specific change — a rename, a fix, a missing test, a different API call, a refactor — at a specific location. Pleasantries ("thanks", "LGTM"), broad approvals without a request, and questions that don't propose a change are not code-change comments and don't require the agree/disagree dance below — handle them per the non-actionable comments note.
Agree — fix, push, and acknowledge
When the suggested change is correct (the bug exists, the simplification works, the missing test should be added, the rename clarifies):
- Make the fix locally on the same branch — same tools, same discipline as the original change.
- Run the same local checks the PR ran originally (
pnpm test,pnpm build, etc., per project). A fix that breaks CI is not a fix. - Push the new commit. Regular
git push— do not force-push, since force-pushes detach the reviewer's anchor and bury the context they were commenting on. Use a focused commit message (fix: <what>orrefactor: <what>). - Reply on the original thread with
mcp__github__add_reply_to_pull_request_comment(for inline review-thread comments) ormcp__github__add_issue_comment(for top-level review or PR-level comments). The reply names what was done and the new commit SHA, e.g.: "Done in<sha>: replaced the regex withURL.parseand added the BOM case toparser.test.ts." Vague replies ("fixed","good catch") are not acceptable — the reviewer needs to know what changed without re-reading the diff. - Resolve the thread with
mcp__github__resolve_review_threadonce the reply is posted. Leave the thread open only when the reviewer explicitly asked a follow-up question that the fix didn't answer.
Disagree — reply with the concrete reason, do not push
When the suggested change is wrong, would regress observable behavior, conflicts with project guidance, or rests on a misreading:
- Do not push code. A disagreement that ends in a commit is not a disagreement — it's a confused agreement. If the comment makes you uncertain, re-read the relevant code first; commit only after you've actually concluded the change is right.
- Reply on the original thread with the concrete reason. One short paragraph: which file/line/behavior the suggestion would break, the project convention it conflicts with, or the misread it rests on. Cite a path with
path/to/file.ts:42so the reviewer can verify. Do not argue stylistic preferences as if they were correctness — when the disagreement is a "could go either way" trade-off, name it as such and ask the reviewer to weigh in. - Do not resolve the thread. The agent never resolves its own pushback. Leave the thread open so the reviewer can respond; the maintainer resolves disagreements they accept.
- No silent skips. If you decided not to act, you owe a reply explaining why. Going quiet on a reviewer's suggestion is the worst outcome — it looks like the comment was missed.
Non-actionable comments
Pleasantries, broad approvals, status-echo bot comments, and questions that don't propose a change do not trigger the agree/disagree rule — that path is reserved for code-change suggestions. Replying to non-actionable comments creates pleasantry loops (see the dependency-management-node skill's pull-request rules for the same rule on dep PRs). Reply only when the comment introduces a new question, finding, or action item.
Loop discipline
- One event, one response. Each webhook event gets its own investigation and reply (or fix + reply). Do not batch multiple reviewer comments into one push without a per-comment acknowledgment — the reviewer should not have to read the diff to find out which of their suggestions you took.
- Self-authored comments are skipped. The agent's own replies, the agent's own
add_issue_commentflake notes from Step 8, and<github-webhook-activity>echoes of the agent's own pushes are not new work. - Stop watching on the user's word or PR end-of-life. Call
mcp__github__unsubscribe_pr_activityand end the turn when the PR is merged or closed, or when the user saysstop watching,unsubscribe,done with this PR, or similar. Don't push further changes to that PR after unsubscribing.
7. Anti-patterns the submitter must avoid
The title, body, and review-reply rules are in §§ 1–3 and § 6 and in pr-conventions; these are the
failure modes those rules don't already name.
- The dodge-the-review draft. Opening as
draft: trueso required-reviewer policies don't apply. Drafts are for actual WIP, not for sneaking changes past a review gate. - The self-resolved pushback. Resolving a review thread on a comment the agent disagreed with. The agent only resolves threads it actually fixed; reviewers and maintainers resolve disagreements they accept.
- The force-push that buries the review.
git push --force(or--force-with-lease) on top of fixes for review comments — the reviewer's inline anchors detach and the conversation loses its line context. Use force-push only when an explicit rebase is the change being made. - The poll-when-you-could-subscribe. Calling
pull_request_readin asleeploop waiting for new comments instead of subscribing and ending the turn. Step 9 is the contract: subscribe, end the turn, wake on event.