Execute a Task using a TDD loop; record decisions/progress on the issue; open a PR that closes the Task.
/plugin marketplace add el-feo/ai-context/plugin install ghpm@jebs-dev-toolsResolution order if omitted:
ghpm/task-<N>-* or task-<N>-*, use NTask assigned to @me:
gh issue list -l Task -a @me -s open --limit 1 --json number -q '.[0].number'gh issue list -l Task -s open --limit 1 --json number -q '.[0].number'
</arguments>
<usage_examples> With task number:
/ghpm:tdd-task task=#42
With focus hint:
/ghpm:tdd-task task=#42 focus=unit
Auto-resolve from branch:
# On branch: ghpm/task-42-add-auth
/ghpm:tdd-task
Auto-resolve from GitHub:
# No arguments - uses most recent assigned Task
/ghpm:tdd-task
</usage_examples>
<operating_rules>
<conventional_commits>
All commits and PR titles must follow the Conventional Commits specification to enable automated changelog generation.
<type>[optional scope]: <description> (#<issue>)
[optional body]
[optional footer(s)]
| Type | Description | Changelog Section |
|---|---|---|
feat | New feature or capability | Features |
fix | Bug fix | Bug Fixes |
refactor | Code restructuring without behavior change | Code Refactoring |
perf | Performance improvement | Performance |
test | Adding or updating tests | Testing |
docs | Documentation only changes | Documentation |
style | Formatting, whitespace (no code change) | (excluded) |
chore | Build, CI, dependencies, tooling | Maintenance |
revert | Revert a previous commit | Reverts |
Infer the type from the Task context:
enhancement → feat, bug → fixfeat; "fix", "resolve", "correct" → fixfeat, Bug epic → fix, Tech debt epic → refactortest, if primarily docs → docsFor breaking changes, add `!` after the type or include `BREAKING CHANGE:` in the footer:
feat!: remove deprecated API endpoint (#123)
BREAKING CHANGE: The /v1/users endpoint has been removed. Use /v2/users instead.
Feature commit:
feat(auth): add OAuth2 login flow (#42)
Bug fix commit:
fix(payments): resolve null pointer in checkout (#103)
Refactor commit:
refactor(users): extract email service into separate module (#87)
Test commit:
test(api): add integration tests for user endpoints (#156)
During Red-Green-Refactor cycles, commit at each meaningful milestone:
test(<scope>): add failing test for <behavior> (#<task>)feat(<scope>): implement <behavior> (#<task>) or fix(<scope>): ...refactor(<scope>): <improvement description> (#<task>)</conventional_commits>
<workflow>Resolve the task number and fetch context:
# Resolve task number from arguments, branch, or auto-select
TASK={resolved_task_number}
# Fetch issue details
gh issue view "$TASK" --json title,body,url,labels,comments -q '.'
Extract from issue:
Before proceeding, check if the task is already closed or marked as done:
# Fetch issue state and labels
ISSUE_DATA=$(gh issue view "$TASK" --json state,labels,projectItems -q '.')
STATE=$(echo "$ISSUE_DATA" | jq -r '.state')
# Check if issue is closed
if [ "$STATE" = "CLOSED" ]; then
echo "Task #$TASK is already CLOSED. Cannot proceed with TDD."
exit 0
fi
# Check for "Done" label
DONE_LABEL=$(echo "$ISSUE_DATA" | jq -r '.labels[]?.name | select(. == "Done" or . == "done" or . == "DONE")')
if [ -n "$DONE_LABEL" ]; then
echo "Task #$TASK has 'Done' label. Cannot proceed with TDD."
exit 0
fi
# Check project status field (if linked to a project)
PROJECT_STATUS=$(echo "$ISSUE_DATA" | jq -r '.projectItems[]?.status?.name // empty')
if [ "$PROJECT_STATUS" = "Done" ] || [ "$PROJECT_STATUS" = "Completed" ]; then
echo "Task #$TASK has project status '$PROJECT_STATUS'. Cannot proceed with TDD."
exit 0
fi
Behavior:
Comment on the Task with your implementation plan:
## TDD Plan
- **Objective:**
- **Target behavior / acceptance criteria:**
- **Test strategy (focus level + what to cover):**
- **Proposed minimal design (non-binding):**
- **Commands (build/test/lint) you will run:**
- **Milestones (Red/Green/Refactor slices):**
Execute:
gh issue comment "$TASK" --body "<markdown>"
git checkout -b "ghpm/task-$TASK-<short-slug>"
Comment branch name to the issue (same comment or a follow-up).
For each slice:
test(<scope>): add failing test for <behavior> (#$TASK)<type>(<scope>): <description> (#$TASK) (typically feat or fix)refactor(<scope>): <description> (#$TASK)Commit after each phase using conventional commit format. Determine the type from Task context (see <conventional_commits> section).
After each slice, comment on the Task with:
Edit the issue body to append:
## Task Report (auto)
### Implementation summary
### Files changed
### How to validate locally
### Test command(s) and results
### Decision log
### Follow-ups (if any)
Execute:
gh issue edit "$TASK" --body "<updated markdown>"
Push branch and create PR using Conventional Commits format for the title:
git push -u origin HEAD
# Determine type from Task context (see <conventional_commits> section)
# Format: <type>(<scope>): <description> (#$TASK)
gh pr create --title "<type>(<scope>): <description> (#$TASK)" --body "$(cat <<'EOF'
Closes #$TASK
## Summary
- ...
## Test Plan
- `<test command>`
## Commits
<list of conventional commits made during TDD>
EOF
)"
PR Title Examples:
feat(auth): add OAuth2 login flow (#42)fix(payments): resolve checkout null pointer (#103)refactor(users): extract email service (#87)Comment the PR URL back onto the Task:
gh issue comment "$TASK" --body "PR created: <PR_URL>"
<success_criteria> Command completes when:
Closes #$TASK in the body<error_handling> If tests fail during a cycle:
If PR creation fails:
Proceed now.