| name | complete-github-issue |
| description | Use when asked to work on, implement, or complete a GitHub issue — before writing any code, checks issue state, existing PRs, git history, and codebase to determine what work remains or if the issue is already resolved |
| argument-hint | [issue-number] |
Complete GitHub Issue
Overview
Systematically assess a GitHub issue's completion state before implementing anything. Check the issue, git history, PRs, and codebase to determine: fully done, partially done, or not started. Then act accordingly.
Core principle: Reconnaissance before implementation. Never implement what's already done.
When to Use
- Asked to "implement issue #N" or "complete issue #N"
- Given a GitHub issue URL or number to work on
- Asked to "close" or "resolve" an issue
- Working through a backlog of issues
When NOT to use:
- Creating a new issue (not implementing one)
- Reviewing a PR (separate workflow)
- Issue is purely a discussion/question (no implementation needed)
The Process
digraph complete_issue {
rankdir=TB;
"Read issue contents via gh" [shape=box];
"Reconcile issue labels" [shape=box];
"Issue has implementation work?" [shape=diamond];
"No code needed — respond/comment" [shape=box style=filled fillcolor=lightyellow];
"Check for linked PRs and branches" [shape=box];
"Check git log for related commits" [shape=box];
"Check codebase against acceptance criteria" [shape=box];
"Fully implemented?" [shape=diamond];
"Partially implemented?" [shape=diamond];
"Find implementing commit(s)" [shape=box];
"Close issue with commit reference" [shape=box style=filled fillcolor=lightgreen];
"List remaining criteria only" [shape=box];
"Implement remaining work" [shape=box style=filled fillcolor=lightblue];
"Implement all acceptance criteria" [shape=box style=filled fillcolor=lightblue];
"Verify/create test coverage" [shape=box style=filled fillcolor=lightyellow];
"Commit, push, open PR" [shape=box style=filled fillcolor=lightgreen];
"Read issue contents via gh" -> "Reconcile issue labels";
"Reconcile issue labels" -> "Issue has implementation work?";
"Issue has implementation work?" -> "No code needed — respond/comment" [label="no"];
"Issue has implementation work?" -> "Check for linked PRs and branches" [label="yes"];
"Check for linked PRs and branches" -> "Check git log for related commits";
"Check git log for related commits" -> "Check codebase against acceptance criteria";
"Check codebase against acceptance criteria" -> "Fully implemented?";
"Fully implemented?" -> "Find implementing commit(s)" [label="yes"];
"Find implementing commit(s)" -> "Close issue with commit reference";
"Fully implemented?" -> "Partially implemented?" [label="no"];
"Partially implemented?" -> "List remaining criteria only" [label="yes"];
"List remaining criteria only" -> "Implement remaining work";
"Partially implemented?" -> "Implement all acceptance criteria" [label="no"];
"Implement remaining work" -> "Verify/create test coverage";
"Implement all acceptance criteria" -> "Verify/create test coverage";
"Verify/create test coverage" -> "Commit, push, open PR";
}
Step 1: Read the Issue
gh issue view <NUMBER> --json number,title,body,state,labels,assignees,url
Extract from the issue:
- Acceptance criteria (checkboxes, requirements, deliverables)
- Referenced files (paths, components, endpoints mentioned)
- Labels and state (open/closed, assigned, linked PRs)
If the issue lacks clear acceptance criteria, derive them from the description. List them explicitly before proceeding.
1a. Reconcile Issue Labels (Required Before Reconnaissance)
List the existing repository labels before implementation reconnaissance:
gh label list --limit 200 --json name,description
Compare the issue title, body, referenced files, and current labels with the existing repository labels.
Record the original label names from the issue response before label reconciliation.
Determine the applicable existing labels and the missing applicable labels. The missing applicable labels are the applicable labels that are not in the original label names.
- Select all clearly applicable existing work-type and affected-area labels before implementation.
- Preserve every original label.
- Never remove, create, rename, or guess a label.
Use exactly one of these branches:
- If one or more applicable labels are missing, run
gh issue edit with only the missing labels.
- If one or more applicable labels exist and every applicable label is already present, skip
gh issue edit and report that all applicable labels were already present.
- If no existing repository label applies, skip
gh issue edit and report that no applicable existing repository label exists.
For the missing-label branch, apply only the missing applicable labels:
gh issue edit <NUMBER> --add-label "<label>" --add-label "<label>"
After every branch, including both branches that skip gh issue edit, run:
gh issue view <NUMBER> --json labels
Compare the saved label names with both the original label names and the applicable label names. Verification must show every original label and every applicable label. Continue to reconnaissance only after verification succeeds. Report the selected branch state accurately.
Error Handling
- Issue read fails: abort and report the command failure. Do not infer issue contents or continue.
- Label discovery fails: abort and report the command failure. Do not guess repository labels.
- Label application fails: abort and report the command failure. Do not start reconnaissance.
- Label verification fails, omits an original label, or omits an applicable label: abort and report the mismatch. Do not start reconnaissance.
1b. Announce the Session (Claim the Issue)
Other agents may be working the same backlog. Before reconnaissance, check for
and post a claim so parallel agents skip this issue. Use the claim-issue
skill (~/.claude/skills/claim-issue/); prefer a project-local copy such as
scripts/agent-claim-issue.sh when the repo ships one:
~/.claude/skills/claim-issue/claim-issue.sh check <NUMBER>
~/.claude/skills/claim-issue/claim-issue.sh claim <NUMBER>
An active claim from another session means the issue is taken — stop and
report instead of duplicating work. When you finish or abandon the issue,
release the claim so the issue becomes available again:
~/.claude/skills/claim-issue/claim-issue.sh release <NUMBER> "<reason>"
Step 2: Reconnaissance (BEFORE Any Implementation)
Run these checks — all are required before writing any code:
2a. Check for linked PRs
gh pr list --state all --search "<ISSUE_NUMBER>" --limit 10
gh pr list --state all --search "closes #<NUMBER> OR fixes #<NUMBER> OR resolves #<NUMBER>"
If a merged PR exists that addresses the issue, skip to Step 3 (assess completion).
2b. Check git history
git log --all --oneline --grep="#<NUMBER>"
git log --all --oneline -- <referenced-files>
git branch -a | grep -i "<keyword>"
2c. Check codebase against each acceptance criterion
For EACH acceptance criterion, verify whether the code already satisfies it:
Be specific. Don't just check if a file exists — verify the actual behavior matches the criterion.
Step 3: Assess Completion State
Score each acceptance criterion:
## Completion Assessment
- [x] Criterion 1 — DONE (evidence: <file>:<line>, commit <sha>)
- [ ] Criterion 2 — NOT DONE (missing: <what's missing>)
- [x] Criterion 3 — DONE (evidence: <file>:<line>)
Present this assessment to the user before proceeding.
Decision:
| State | All criteria done? | Action |
|---|
| Fully done | Yes | Step 4a: Close with reference |
| Partially done | Some | Step 4b: Implement remaining only |
| Not started | None | Step 4c: Implement all |
Step 4a: Close with Commit Reference (Fully Done)
Find the implementing commit(s):
git log --all --oneline -- <files-that-changed>
git log --all --format="%H %s" -- <primary-file> | head -5
Then close the issue:
gh issue close <NUMBER> --comment "Implemented in <commit-sha>.
Acceptance criteria verified:
- [x] Criterion 1 (<file>:<line>)
- [x] Criterion 2 (<file>:<line>)
..."
Before closing, run Step 5 (Test Verification) to confirm tests exist and pass for the implemented criteria. If tests are missing, create them before closing — an issue isn't truly "done" without test coverage. This applies even when you didn't write the implementation.
Always include: the commit SHA, which criteria are satisfied, and where the evidence is.
Step 4b: Implement Remaining (Partially Done)
- List ONLY the unmet criteria — do not re-implement done work
- Implement each remaining criterion
- After implementation, proceed to Step 5 (Test Verification)
Step 4c: Implement All (Not Started)
- Follow normal implementation workflow
- After implementation, proceed to Step 5 (Test Verification)
Step 5: Test Verification (Required After Any Implementation)
After implementing code in Step 4b or 4c, tests MUST be checked and updated.
5a. Check existing test coverage
Glob("**/<ComponentName>*.test.*")
Glob("**/<module-name>*.test.*")
Grep(pattern: "import.*<changed-module>", glob: "*.test.*")
5b. Update or create tests
| Situation | Action |
|---|
| Tests exist and still pass | Verify coverage of NEW behavior, add test cases if gaps |
| Tests exist but fail | Fix tests to match new behavior (not the other way around) |
| No tests exist for changed code | Create tests covering the acceptance criteria |
| Only unit tests exist for a UI feature | Consider if E2E tests are needed for the workflow |
What to test:
- Each acceptance criterion should have at least one test asserting it
- Edge cases mentioned in the issue
- Regression: existing behavior that should NOT have changed
5c. Run the affected tests
Select scope by impact — do not run every suite for every change:
npm run jest -- <affected-test-files>
npm run typecheck
npm run test:e2e -- <affected-spec>
Run the full E2E suite only for cascading changes (shared auth/session, global
providers/layout/routing, API or schema contracts consumed by multiple
workflows, build/runtime/dependency configuration) or when explicitly asked
for full validation. If the project defines its own dispatcher (e.g.
/run-tests in Turin's Tavern), use it — it encodes these rules.
All selected tests must pass before claiming completion. Show output with pass/fail counts.
Step 6: Publish (Required — Green Tests Are Not Delivery)
Passing tests in a working tree nobody can see is not a completed issue. Work
that stops here is the single largest source of lost effort: an audit of one
repository found 12 of 29 parallel agents, and 9 of 10 sessions in another
batch, ran their tests green and never committed once. Their branches and
worktrees were deleted weeks later with the work still uncommitted.
Do not report the issue complete until every step below has run.
git add <files by name>
git commit
git push -u origin <branch>
gh pr create --base <default>
- Stage by name.
git status --porcelain first; stage only files this
issue touched. If unrelated changes are present, leave them unstaged and say
so.
- Commit with a Conventional Commits subject and
Closes #N in the body
(or Refs #N when the issue is not fully resolved). Never --no-verify,
never git commit -n.
- Push the branch. A local commit is not delivery either.
- Open the PR against the repository's default branch. Fill the template
if the repo has one. Apply the labels matching the diff.
- Wait for CI, then verify mergeability. Zero failing checks and checks
that have actually reported — a PR with no checks yet reads as "clean" and
is not. Confirm
MERGEABLE/CLEAN, or checks-passed MERGEABLE/BLOCKED.
- Release the claim if you took one in Step 1b, and clean up any worktree
the repo's conventions require.
Do not merge the PR. Merging needs an explicit request from the user.
If you cannot finish
Commit and push what you have on a branch anyway, then say exactly what is
missing. An unpushed working tree is unrecoverable once its worktree is
removed; a pushed branch is always recoverable.
Quick Reference
| Check | Command | Why |
|---|
| Issue details | gh issue view N | Understand requirements |
| Linked PRs | gh pr list --state all --search "N" | Find existing work |
| Commit history | git log --all --oneline --grep="#N" | Find implementing commits |
| File history | git log --all --oneline -- <files> | Track changes to relevant files |
| Feature branches | git branch -a | grep -i keyword | Find in-progress work |
| Code check | Grep/Glob for specific implementations | Verify criteria met |
Common Mistakes
Jumping straight to implementation
- You read the issue and start coding without checking if work already exists
- Fix: ALWAYS complete Step 2 reconnaissance before any implementation
Ignoring closed-but-open state mismatch
- Issue is closed but you implement anyway, or issue is open but work is already done
- Fix: Issue state is informational, not authoritative. Check the CODE, not just the label.
Shallow codebase checks
- Checking if a file exists is not the same as verifying acceptance criteria are met
- Fix: For each criterion, verify the actual behavior, not just file existence
Re-implementing done work
- Some criteria are met but you implement everything from scratch
- Fix: Score EACH criterion individually. Only implement what's missing.
Closing without evidence
- "This looks done" without specific commit references or file locations
- Fix: Always cite commit SHAs and file:line evidence in close comments
Stopping at green tests
- Tests pass, so the work is reported done — but nothing is committed, pushed, or PR'd
- Fix: Step 6 is mandatory. Delivery is a pushed branch and an open PR, not a green test run.
Skipping test verification
- Implementing code without checking for existing tests, updating broken tests, or creating missing tests
- Fix: Step 5 is mandatory. Every acceptance criterion needs test coverage.
Red Flags — STOP
If you catch yourself doing any of these, go back to Step 2:
- Writing code before checking git history
- "I'll just implement it fresh, it's faster"
- Assuming nothing exists because the issue is open
- Assuming everything exists because the issue is closed
- Skipping the completion assessment table
- Implementing without updating or creating tests
- Closing an issue when tests for the implemented criteria don't exist
- Reporting an issue complete with green tests but no pushed branch and no PR
- Leaving a worktree with uncommitted work because "the tests pass"