Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions skills/github/github-issue-to-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
name: github-issue-to-pr
description: "Carry a GitHub issue to a verified PR with honest CI state."
version: 0.1.0
author: Ben Barclay (benbarclay), Hermes Agent
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [GitHub, Issues, Coding, Pull-Requests, CI]
related_skills: [github-issues, github-pr-workflow, systematic-debugging, test-driven-development, requesting-code-review]
---

# GitHub Issue to Pull Request

Turn a GitHub issue into a tested, verified PR. This skill owns the end-to-end discipline — premise validation, duplicate sweeps, class-level fixes, and honest CI reporting; the sibling GitHub and development skills own their own mechanics.

## When to Use

- "Fix issue #123 and open a PR."
- "Implement this GitHub feature request."
- "Take this bug from issue to green CI."

Don't use for: reviewing an existing PR, or answering a code question with no requested change.

## Procedure

### 1. Read the live issue — body AND full thread

Use `terminal` to run `gh issue view <N> --comments`. The body is a snapshot from filing time; the newest comments carry the live state: partial fixes already merged, new root-cause analyses, maintainer decisions, or questions directed at you that change the task. Also read repository instructions (`AGENTS.md`, contribution docs) with `read_file`. Done when the currently requested behavior, non-goals, and any unanswered thread questions are known.

### 2. Sweep for existing and duplicate work

Before writing anything, run `gh pr list --search "#<N>" --state all` plus at least two keyword/synonym variants of the symptom (`gh pr list --search "<subsystem> <symptom>" --state open`). Popular issues attract multiple independent fixes; building a duplicate wastes the work and the credit. Also check whether a recent commit already fixed it: `git log --oneline -20 -- <relevant files>`. Done when you know every open PR and recent commit touching this issue, or that none exist.

### 3. Validate the premise against current code — and against design intent

Reproduce the bug or demonstrate the missing behavior on the current default branch with a failing test or fixture, using `search_files` and `read_file` to trace the reported path. Then check the second question: is the "bug" actually deliberate design? Run `git log -p -S "<symbol>"` on the code the issue wants changed and read the original commit's intent — a missing link or restriction is often the feature. Challenge stale or flawed issue prose instead of implementing it blindly. Done when the root cause or feature gap is demonstrated in current code AND the change doesn't fight an intentional design.

### 4. Define acceptance and risk

List acceptance criteria, interfaces, migrations/state changes, compatibility, security/privacy, rollout, and rollback. Map every criterion to a test or explicit verification. Done when review has a finite contract.

### 5. Implement the smallest complete change — and fix the class

Work on an isolated branch or worktree, loading `systematic-debugging` or `test-driven-development` when the bug class calls for them. Add regression tests first, then implement. When the fix is in hand, `search_files` for the same bug shape at sibling call sites and fix the whole class in this PR — an incomplete fix that leaves known siblings broken is worse than none. Every changed line must trace to the issue; no drive-by cleanup. Done when targeted tests pass, the original failure no longer reproduces, and sibling sites are fixed or explicitly ruled out.

### 6. Prove the regression test bites (sabotage run)

Temporarily restore the old behavior of the exact function under test, run the new test, and confirm it FAILS; then restore the fix and confirm it passes. A regression test that passes with and without the fix proves nothing. Done when the test demonstrably fails on pre-fix code.

### 7. Run repository quality gates, then open the PR immediately

Run the formatter, lint, typecheck, and the repo's canonical test entrypoint on affected areas; use `requesting-code-review` on the diff. Then push and open the PR right away — the PR is what dispatches CI, and CI latency is the long pole; do not sit on finished work. Load `github-pr-workflow` for PR mechanics: conventional branch/commit, body linking the issue with problem, approach, tests, risk, and exclusions. Read the PR back and verify head SHA, base, title, and files. Done when the PR exists with the intended diff and CI is running.

### 8. Shepherd CI honestly and close the loop

Inspect live checks and failure logs via `gh pr checks` / `gh run view --log-failed`. Distinguish failures introduced by your diff from pre-existing baseline or infrastructure failures — reproduce on the default branch when unsure, and rerun once only for genuine infra flakes. Never say "green," "merged," or "released" without live evidence of that exact state. When the PR lands, comment on the issue with the PR link and a one-line explanation so the reporter gets a traceable resolution. Done when CI state, remaining blockers, and the issue thread all reflect reality.

## Pitfalls

- Coding before reading issue comments, sweeping for duplicate PRs, or reading current code.
- "Fixing" behavior that the original commit shows is intentional design.
- Fixing a symptom at one call site while sibling sites keep the same bug.
- Shipping a regression test that also passes without the fix.
- Opening a PR with unrun tests or unrelated formatting churn.
- Claiming the issue is delivered because a PR exists.

## Verification

- [ ] Full issue thread read; newest comment state reflected in the plan.
- [ ] Duplicate-PR sweep run with issue number + 2 keyword variants.
- [ ] Premise reproduced on current code; design intent checked via git history.
- [ ] Regression test proven to fail without the fix.
- [ ] Sibling call sites fixed or explicitly ruled out.
- [ ] Every changed line traces to the issue.
- [ ] CI state reported from live evidence only; issue commented with the PR link.
102 changes: 102 additions & 0 deletions tests/skills/test_github_issue_to_pr_skill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Tests for the github-issue-to-pr bundled skill."""
import re
from pathlib import Path

import yaml

SKILL_PATH = (
Path(__file__).resolve().parents[2]
/ "skills"
/ "github"
/ "github-issue-to-pr"
/ "SKILL.md"
)


def _frontmatter_and_body():
content = SKILL_PATH.read_text(encoding="utf-8")
assert content.startswith("---")
m = re.search(r"\n---\s*\n", content[3:])
assert m, "frontmatter must close with ---"
fm = yaml.safe_load(content[3 : m.start() + 3])
body = content[m.end() + 3 :]
return fm, body


def test_skill_file_exists():
assert SKILL_PATH.is_file()


def test_frontmatter_required_fields():
fm, _ = _frontmatter_and_body()
for field in ("name", "description", "version", "author", "license", "platforms"):
assert field in fm, f"missing frontmatter field: {field}"
assert fm["name"] == "github-issue-to-pr"
hermes = fm["metadata"]["hermes"]
assert hermes["tags"]
assert "related_skills" in hermes


def test_description_hardline():
fm, _ = _frontmatter_and_body()
desc = fm["description"]
assert len(desc) <= 60, f"description is {len(desc)} chars; hardline is 60"
assert desc.endswith(".")


def test_author_credits_human_first():
fm, _ = _frontmatter_and_body()
assert not fm["author"].startswith("Hermes Agent"), "human contributor must be credited first"
assert "benbarclay" in fm["author"]


def test_related_skills_resolve_in_repo():
fm, _ = _frontmatter_and_body()
repo_root = SKILL_PATH.parents[3]
for name in fm["metadata"]["hermes"]["related_skills"]:
hits = (
list(repo_root.glob(f"skills/*/{name}/SKILL.md"))
+ list(repo_root.glob(f"optional-skills/*/{name}/SKILL.md"))
+ list(repo_root.glob(f"skills/*/*/{name}/SKILL.md"))
)
assert hits, f"related_skills entry does not resolve in-repo: {name}"


def test_body_structure_and_size():
_, body = _frontmatter_and_body()
for section in ("## When to Use", "## Procedure", "## Pitfalls", "## Verification"):
assert section in body, f"missing section: {section}"
assert len(SKILL_PATH.read_text(encoding="utf-8")) <= 100_000


def test_no_machine_local_paths():
content = SKILL_PATH.read_text(encoding="utf-8")
assert "/home/" not in content
assert not re.search(r"[A-Z]:\\\\Users", content)


def test_steps_have_completion_criteria():
_, body = _frontmatter_and_body()
steps = re.findall(r"^### \d+\..*?(?=^### \d+\.|^## )", body, re.MULTILINE | re.DOTALL)
assert len(steps) >= 6
for step in steps:
assert "Done when" in step, f"step missing completion criterion: {step[:60]!r}"


def test_core_disciplines_present():
"""The learnings folded in from maintainer practice must survive edits."""
_, body = _frontmatter_and_body()
assert "--comments" in body, "must read the full issue thread"
assert "pr list --search" in body, "must sweep for duplicate PRs before coding"
assert re.search(r"git log -p -S", body), "must check design intent via history"
assert "sabotage" in body.lower() or "FAILS" in body, "must prove the regression test bites"
assert "sibling" in body, "must fix the class, not the site"
assert "dispatches CI" in body, "must open the PR immediately after work exists"


def test_not_a_router_skill():
"""Steps must carry their own procedure, not just route to sibling skills."""
_, body = _frontmatter_and_body()
steps = re.findall(r"^### \d+\..*?(?=^### \d+\.|^## )", body, re.MULTILINE | re.DOTALL)
routing = [s for s in steps if re.match(r"^### \d+\.[^\n]*\n+Load `", s)]
assert len(routing) == 0, "steps must not open by delegating to another skill"
1 change: 1 addition & 0 deletions website/docs/reference/skills-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ If a skill is missing from this list but present in the repo, the catalog is reg
| [`codebase-inspection`](/docs/user-guide/skills/bundled/github/github-codebase-inspection) | Inspect codebases w/ pygount: LOC, languages, ratios. | `github/codebase-inspection` |
| [`github-auth`](/docs/user-guide/skills/bundled/github/github-github-auth) | GitHub auth setup: HTTPS tokens, SSH keys, gh CLI login. | `github/github-auth` |
| [`github-code-review`](/docs/user-guide/skills/bundled/github/github-github-code-review) | Review PRs: diffs, inline comments via gh or REST. | `github/github-code-review` |
| [`github-issue-to-pr`](/docs/user-guide/skills/bundled/github/github-github-issue-to-pr) | Carry a GitHub issue to a verified PR with honest CI state. | `github/github-issue-to-pr` |
| [`github-issues`](/docs/user-guide/skills/bundled/github/github-github-issues) | Create, triage, label, assign GitHub issues via gh or REST. | `github/github-issues` |
| [`github-pr-workflow`](/docs/user-guide/skills/bundled/github/github-github-pr-workflow) | GitHub PR lifecycle: branch, commit, open, CI, merge. | `github/github-pr-workflow` |
| [`github-repo-management`](/docs/user-guide/skills/bundled/github/github-github-repo-management) | Clone/create/fork repos; manage remotes, releases. | `github/github-repo-management` |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
title: "Github Issue To Pr — Carry a GitHub issue to a verified PR with honest CI state"
sidebar_label: "Github Issue To Pr"
description: "Carry a GitHub issue to a verified PR with honest CI state"
---

{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}

# Github Issue To Pr

Carry a GitHub issue to a verified PR with honest CI state.

## Skill metadata

| | |
|---|---|
| Source | Bundled (installed by default) |
| Path | `skills/github/github-issue-to-pr` |
| Version | `0.1.0` |
| Author | Ben Barclay (benbarclay), Hermes Agent |
| License | MIT |
| Platforms | linux, macos, windows |
| Tags | `GitHub`, `Issues`, `Coding`, `Pull-Requests`, `CI` |
| Related skills | [`github-issues`](/docs/user-guide/skills/bundled/github/github-github-issues), [`github-pr-workflow`](/docs/user-guide/skills/bundled/github/github-github-pr-workflow), [`systematic-debugging`](/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review) |

## Reference: full SKILL.md

:::info
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
:::

# GitHub Issue to Pull Request

Turn a GitHub issue into a tested, verified PR. This skill owns the end-to-end discipline — premise validation, duplicate sweeps, class-level fixes, and honest CI reporting; the sibling GitHub and development skills own their own mechanics.

## When to Use

- "Fix issue #123 and open a PR."
- "Implement this GitHub feature request."
- "Take this bug from issue to green CI."

Don't use for: reviewing an existing PR, or answering a code question with no requested change.

## Procedure

### 1. Read the live issue — body AND full thread

Use `terminal` to run `gh issue view <N> --comments`. The body is a snapshot from filing time; the newest comments carry the live state: partial fixes already merged, new root-cause analyses, maintainer decisions, or questions directed at you that change the task. Also read repository instructions (`AGENTS.md`, contribution docs) with `read_file`. Done when the currently requested behavior, non-goals, and any unanswered thread questions are known.

### 2. Sweep for existing and duplicate work

Before writing anything, run `gh pr list --search "#<N>" --state all` plus at least two keyword/synonym variants of the symptom (`gh pr list --search "<subsystem> <symptom>" --state open`). Popular issues attract multiple independent fixes; building a duplicate wastes the work and the credit. Also check whether a recent commit already fixed it: `git log --oneline -20 -- <relevant files>`. Done when you know every open PR and recent commit touching this issue, or that none exist.

### 3. Validate the premise against current code — and against design intent

Reproduce the bug or demonstrate the missing behavior on the current default branch with a failing test or fixture, using `search_files` and `read_file` to trace the reported path. Then check the second question: is the "bug" actually deliberate design? Run `git log -p -S "<symbol>"` on the code the issue wants changed and read the original commit's intent — a missing link or restriction is often the feature. Challenge stale or flawed issue prose instead of implementing it blindly. Done when the root cause or feature gap is demonstrated in current code AND the change doesn't fight an intentional design.

### 4. Define acceptance and risk

List acceptance criteria, interfaces, migrations/state changes, compatibility, security/privacy, rollout, and rollback. Map every criterion to a test or explicit verification. Done when review has a finite contract.

### 5. Implement the smallest complete change — and fix the class

Work on an isolated branch or worktree, loading `systematic-debugging` or `test-driven-development` when the bug class calls for them. Add regression tests first, then implement. When the fix is in hand, `search_files` for the same bug shape at sibling call sites and fix the whole class in this PR — an incomplete fix that leaves known siblings broken is worse than none. Every changed line must trace to the issue; no drive-by cleanup. Done when targeted tests pass, the original failure no longer reproduces, and sibling sites are fixed or explicitly ruled out.

### 6. Prove the regression test bites (sabotage run)

Temporarily restore the old behavior of the exact function under test, run the new test, and confirm it FAILS; then restore the fix and confirm it passes. A regression test that passes with and without the fix proves nothing. Done when the test demonstrably fails on pre-fix code.

### 7. Run repository quality gates, then open the PR immediately

Run the formatter, lint, typecheck, and the repo's canonical test entrypoint on affected areas; use `requesting-code-review` on the diff. Then push and open the PR right away — the PR is what dispatches CI, and CI latency is the long pole; do not sit on finished work. Load `github-pr-workflow` for PR mechanics: conventional branch/commit, body linking the issue with problem, approach, tests, risk, and exclusions. Read the PR back and verify head SHA, base, title, and files. Done when the PR exists with the intended diff and CI is running.

### 8. Shepherd CI honestly and close the loop

Inspect live checks and failure logs via `gh pr checks` / `gh run view --log-failed`. Distinguish failures introduced by your diff from pre-existing baseline or infrastructure failures — reproduce on the default branch when unsure, and rerun once only for genuine infra flakes. Never say "green," "merged," or "released" without live evidence of that exact state. When the PR lands, comment on the issue with the PR link and a one-line explanation so the reporter gets a traceable resolution. Done when CI state, remaining blockers, and the issue thread all reflect reality.

## Pitfalls

- Coding before reading issue comments, sweeping for duplicate PRs, or reading current code.
- "Fixing" behavior that the original commit shows is intentional design.
- Fixing a symptom at one call site while sibling sites keep the same bug.
- Shipping a regression test that also passes without the fix.
- Opening a PR with unrun tests or unrelated formatting churn.
- Claiming the issue is delivered because a PR exists.

## Verification

- [ ] Full issue thread read; newest comment state reflected in the plan.
- [ ] Duplicate-PR sweep run with issue number + 2 keyword variants.
- [ ] Premise reproduced on current code; design intent checked via git history.
- [ ] Regression test proven to fail without the fix.
- [ ] Sibling call sites fixed or explicitly ruled out.
- [ ] Every changed line traces to the issue.
- [ ] CI state reported from live evidence only; issue commented with the PR link.
1 change: 1 addition & 0 deletions website/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ const sidebars: SidebarsConfig = {
'user-guide/skills/bundled/github/github-codebase-inspection',
'user-guide/skills/bundled/github/github-github-auth',
'user-guide/skills/bundled/github/github-github-code-review',
'user-guide/skills/bundled/github/github-github-issue-to-pr',
'user-guide/skills/bundled/github/github-github-issues',
'user-guide/skills/bundled/github/github-github-pr-workflow',
'user-guide/skills/bundled/github/github-github-repo-management',
Expand Down
Loading