Initial commit
This commit is contained in:
557
commands/describe_pr.md
Normal file
557
commands/describe_pr.md
Normal file
@@ -0,0 +1,557 @@
|
||||
---
|
||||
description: Generate or update PR description with incremental changes
|
||||
category: version-control-git
|
||||
tools: Bash, Read, Write
|
||||
model: inherit
|
||||
version: 2.0.0
|
||||
---
|
||||
|
||||
# Generate/Update PR Description
|
||||
|
||||
Generates or updates PR description with incremental information, auto-updates title, and links
|
||||
Linear tickets.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before executing, verify all required tools and systems:
|
||||
|
||||
```bash
|
||||
# 1. Validate thoughts system (REQUIRED)
|
||||
if [[ -f "scripts/validate-thoughts-setup.sh" ]]; then
|
||||
./scripts/validate-thoughts-setup.sh || exit 1
|
||||
else
|
||||
# Inline validation if script not found
|
||||
if [[ ! -d "thoughts/shared" ]]; then
|
||||
echo "❌ ERROR: Thoughts system not configured"
|
||||
echo "Run: ./scripts/humanlayer/init-project.sh . {project-name}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2. Validate plugin scripts
|
||||
if [[ -f "${CLAUDE_PLUGIN_ROOT}/scripts/check-prerequisites.sh" ]]; then
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/check-prerequisites.sh" || exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## Process:
|
||||
|
||||
### 1. Read PR description template
|
||||
|
||||
```bash
|
||||
# Check if template exists
|
||||
if [ ! -f "thoughts/shared/pr_description.md" ]; then
|
||||
echo "❌ PR description template not found"
|
||||
fi
|
||||
```
|
||||
|
||||
If missing:
|
||||
|
||||
```
|
||||
❌ PR description template missing
|
||||
|
||||
Your humanlayer thoughts setup is incomplete. Create a template at:
|
||||
thoughts/shared/pr_description.md
|
||||
|
||||
See the PR description template you created earlier for reference.
|
||||
```
|
||||
|
||||
Read template fully to understand all sections.
|
||||
|
||||
### 2. Identify target PR
|
||||
|
||||
**If argument provided:**
|
||||
|
||||
- Use that PR number: `/describe_pr 123`
|
||||
|
||||
**If no argument:**
|
||||
|
||||
```bash
|
||||
# Try current branch
|
||||
gh pr view --json number,url,title,state,body,headRefName,baseRefName 2>/dev/null
|
||||
```
|
||||
|
||||
If no PR on current branch OR on main/master:
|
||||
|
||||
```bash
|
||||
# List recent PRs
|
||||
gh pr list --limit 10 --json number,title,headRefName,state
|
||||
```
|
||||
|
||||
Ask user: "Which PR would you like to describe? (enter number)"
|
||||
|
||||
### 3. Extract ticket reference
|
||||
|
||||
**From multiple sources:**
|
||||
|
||||
```bash
|
||||
# 1. From branch name
|
||||
branch=$(gh pr view $pr_number --json headRefName -q .headRefName)
|
||||
if [[ "$branch" =~ ([A-Z]+)-([0-9]+) ]]; then
|
||||
ticket="${BASH_REMATCH[0]}"
|
||||
fi
|
||||
|
||||
# 2. From PR title
|
||||
title=$(gh pr view $pr_number --json title -q .title)
|
||||
if [[ "$title" =~ ([A-Z]+)-([0-9]+) ]]; then
|
||||
ticket="${BASH_REMATCH[0]}"
|
||||
fi
|
||||
|
||||
# 3. From existing PR body
|
||||
body=$(gh pr view $pr_number --json body -q .body)
|
||||
if [[ "$body" =~ Refs:\ ([A-Z]+-[0-9]+) ]]; then
|
||||
ticket="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
```
|
||||
|
||||
### 4. Read existing descriptions
|
||||
|
||||
**Read current PR body from GitHub:**
|
||||
|
||||
```bash
|
||||
current_body=$(gh pr view $pr_number --json body -q .body)
|
||||
```
|
||||
|
||||
**Read saved description (if exists):**
|
||||
|
||||
```bash
|
||||
saved_desc="thoughts/shared/prs/${pr_number}_description.md"
|
||||
if [ -f "$saved_desc" ]; then
|
||||
# Read fully
|
||||
# Note what sections exist vs what's new
|
||||
fi
|
||||
```
|
||||
|
||||
**Check for metadata header:**
|
||||
|
||||
```markdown
|
||||
<!-- Auto-generated: 2025-10-06T10:30:00Z -->
|
||||
<!-- Last updated: 2025-10-06T14:45:00Z -->
|
||||
<!-- PR: #123 -->
|
||||
<!-- Previous commits: abc123,def456 -->
|
||||
```
|
||||
|
||||
### 5. Gather comprehensive PR information
|
||||
|
||||
```bash
|
||||
# Full diff
|
||||
gh pr diff $pr_number
|
||||
|
||||
# Commit history with messages
|
||||
gh pr view $pr_number --json commits
|
||||
|
||||
# Changed files
|
||||
gh pr view $pr_number --json files
|
||||
|
||||
# PR metadata
|
||||
gh pr view $pr_number --json url,title,number,state,baseRefName,headRefName,author
|
||||
|
||||
# CI/CD status
|
||||
gh pr checks $pr_number
|
||||
```
|
||||
|
||||
### 6. Analyze changes incrementally
|
||||
|
||||
**If this is an UPDATE (saved description exists):**
|
||||
|
||||
```bash
|
||||
# Extract previous commit list from metadata
|
||||
prev_commits=$(grep "Previous commits:" $saved_desc | sed 's/.*: //')
|
||||
|
||||
# Get current commits
|
||||
current_commits=$(gh pr view $pr_number --json commits -q '.commits[].oid' | tr '\n' ',' | sed 's/,$//')
|
||||
|
||||
# Compare
|
||||
new_commits=$(comm -13 <(echo "$prev_commits" | tr ',' '\n' | sort) <(echo "$current_commits" | tr ',' '\n' | sort))
|
||||
```
|
||||
|
||||
**Analysis:**
|
||||
|
||||
- Identify what's NEW since last description
|
||||
- Deep analysis of:
|
||||
- Code changes and architectural impact
|
||||
- Breaking changes
|
||||
- User-facing vs internal changes
|
||||
- Migration requirements
|
||||
- Security implications
|
||||
|
||||
### 7. Merge descriptions intelligently
|
||||
|
||||
**Auto-generated sections (always update):**
|
||||
|
||||
- **Summary** - regenerate based on ALL changes
|
||||
- **Changes Made** - append new changes, preserve old
|
||||
- **How to Verify It** - update checklist, rerun checks
|
||||
- **Changelog Entry** - update to reflect all changes
|
||||
|
||||
**Preserve manual edits in:**
|
||||
|
||||
- **Reviewer Notes** - keep existing unless explicitly empty
|
||||
- **Screenshots/Videos** - never overwrite
|
||||
- **Manually checked boxes** - preserve [x] marks for manual steps
|
||||
- **Post-Merge Tasks** - append new, keep existing
|
||||
|
||||
**Merging strategy:**
|
||||
|
||||
```markdown
|
||||
## Changes Made
|
||||
|
||||
### Backend Changes
|
||||
|
||||
[Existing changes from previous description]
|
||||
|
||||
**New changes** (since last update):
|
||||
|
||||
- [New change 1]
|
||||
- [New change 2]
|
||||
|
||||
### Frontend Changes
|
||||
|
||||
[Existing + new merged together]
|
||||
```
|
||||
|
||||
**Add change summary at top:**
|
||||
|
||||
```markdown
|
||||
<!-- Auto-generated: 2025-10-06T15:00:00Z -->
|
||||
<!-- Last updated: 2025-10-06T15:00:00Z -->
|
||||
<!-- PR: #123 -->
|
||||
<!-- Previous commits: abc123,def456,ghi789 -->
|
||||
|
||||
---
|
||||
|
||||
**Update History:**
|
||||
|
||||
- 2025-10-06 15:00: Added validation logic, updated tests (3 new commits)
|
||||
- 2025-10-06 10:30: Initial implementation (5 commits)
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### 8. Add Linear reference
|
||||
|
||||
If ticket found:
|
||||
|
||||
```markdown
|
||||
## Related Issues/PRs
|
||||
|
||||
- Fixes https://linear.app/{workspace}/issue/{ticket}
|
||||
- Related to [any other linked issues]
|
||||
```
|
||||
|
||||
Get Linear ticket details:
|
||||
|
||||
```bash
|
||||
# Use Linearis CLI to get ticket details
|
||||
linearis issues read "$ticket"
|
||||
|
||||
# Extract title and description with jq
|
||||
ticket_title=$(linearis issues read "$ticket" | jq -r '.title')
|
||||
ticket_description=$(linearis issues read "$ticket" | jq -r '.description')
|
||||
```
|
||||
|
||||
Use ticket title and description for context.
|
||||
|
||||
### 9. Generate updated title
|
||||
|
||||
**Title generation rules:**
|
||||
|
||||
```bash
|
||||
# If ticket exists
|
||||
if [[ "$ticket" ]]; then
|
||||
# Get ticket title from Linear
|
||||
ticket_title=$(linear API or fallback to branch)
|
||||
|
||||
# Format: TICKET: Descriptive title (max 72 chars)
|
||||
title="$ticket: ${ticket_title:0:60}"
|
||||
else
|
||||
# Generate from primary change
|
||||
# Analyze commits and code changes
|
||||
title="Brief summary of main change"
|
||||
fi
|
||||
```
|
||||
|
||||
**Auto-update without prompt** - title is auto-generated section.
|
||||
|
||||
### 10. Run verification checks
|
||||
|
||||
**For each checklist item in "How to Verify It":**
|
||||
|
||||
```bash
|
||||
# Example: "- [ ] Build passes: `make build`"
|
||||
# Extract command: make build
|
||||
|
||||
# Try to run
|
||||
if command -v make >/dev/null 2>&1; then
|
||||
if make build 2>&1; then
|
||||
# Mark as checked
|
||||
checkbox="- [x] Build passes: \`make build\` ✅"
|
||||
else
|
||||
# Mark unchecked with error
|
||||
checkbox="- [ ] Build passes: \`make build\` ❌ (failed: $error)"
|
||||
fi
|
||||
else
|
||||
# Can't run
|
||||
checkbox="- [ ] Build passes: \`make build\` (manual verification required)"
|
||||
fi
|
||||
```
|
||||
|
||||
**Common checks to attempt:**
|
||||
|
||||
- `make test` / `npm test` / `pytest`
|
||||
- `make lint` / `npm run lint`
|
||||
- `npm run typecheck` / `tsc --noEmit`
|
||||
- `make build` / `npm run build`
|
||||
|
||||
**Document results:**
|
||||
|
||||
- ✅ if passed
|
||||
- ❌ if failed (with error)
|
||||
- Manual required if can't automate
|
||||
|
||||
### 11. Save and sync
|
||||
|
||||
**Save description:**
|
||||
|
||||
```bash
|
||||
# Add metadata header
|
||||
cat > "thoughts/shared/prs/${pr_number}_description.md" <<EOF
|
||||
<!-- Auto-generated: $(date -u +%Y-%m-%dT%H:%M:%SZ) -->
|
||||
<!-- Last updated: $(date -u +%Y-%m-%dT%H:%M:%SZ) -->
|
||||
<!-- PR: #$pr_number -->
|
||||
<!-- Previous commits: $commit_list -->
|
||||
|
||||
[Full description content]
|
||||
EOF
|
||||
```
|
||||
|
||||
**Sync thoughts:**
|
||||
|
||||
```bash
|
||||
humanlayer thoughts sync
|
||||
```
|
||||
|
||||
### 12. Update PR on GitHub
|
||||
|
||||
**CRITICAL: NO CLAUDE ATTRIBUTION**
|
||||
|
||||
Before updating the PR, ensure the description contains NO Claude attribution:
|
||||
|
||||
❌ **Remove these if present**:
|
||||
- "Generated with Claude Code" or similar messages
|
||||
- "Co-Authored-By: Claude" lines
|
||||
- Any reference to AI assistance or Anthropic
|
||||
- Links to Claude Code documentation
|
||||
|
||||
✅ **Keep descriptions professional and human-authored**:
|
||||
- Focus on code changes and their purpose
|
||||
- Attribute work to the git author (the human developer)
|
||||
- Write in first-person if needed ("I added...", "We implemented...")
|
||||
|
||||
**Update title:**
|
||||
|
||||
```bash
|
||||
gh pr edit $pr_number --title "$new_title"
|
||||
```
|
||||
|
||||
**Update body:**
|
||||
|
||||
```bash
|
||||
# Ensure no Claude attribution in the description file
|
||||
gh pr edit $pr_number --body-file "thoughts/shared/prs/${pr_number}_description.md"
|
||||
```
|
||||
|
||||
### 13. Update Linear ticket
|
||||
|
||||
If ticket found:
|
||||
|
||||
```bash
|
||||
# Verify linearis is available
|
||||
if ! command -v linearis &> /dev/null; then
|
||||
echo "⚠️ Linearis CLI not found - skipping Linear ticket update"
|
||||
else
|
||||
# If not already in "In Review", move it and assign to self
|
||||
linearis issues update "$ticket" --state "In Review" --assignee "@me"
|
||||
|
||||
# Add comment about update with PR link
|
||||
linearis comments create "$ticket" \
|
||||
--body "PR description updated!\n\n**Changes**: ${updateSummary}\n**Verification**: ${checksPassedCount}/${totalChecks} automated checks passed\n\nView PR: ${prUrl}"
|
||||
fi
|
||||
```
|
||||
|
||||
### 14. Report results
|
||||
|
||||
**If first-time generation:**
|
||||
|
||||
```
|
||||
✅ PR description generated!
|
||||
|
||||
**PR**: #123 - {title}
|
||||
**URL**: {url}
|
||||
**Verification**: {X}/{Y} automated checks passed
|
||||
**Linear**: {ticket} updated
|
||||
|
||||
Manual verification steps remaining:
|
||||
- [ ] Test feature in staging
|
||||
- [ ] Verify UI on mobile
|
||||
|
||||
Review PR on GitHub!
|
||||
```
|
||||
|
||||
**If incremental update:**
|
||||
|
||||
```
|
||||
✅ PR description updated!
|
||||
|
||||
**Changes since last update**:
|
||||
- 3 new commits
|
||||
- Added validation logic
|
||||
- Updated tests
|
||||
|
||||
**Verification**: {X}/{Y} automated checks passed
|
||||
**Sections updated**: Summary, Changes Made, How to Verify It
|
||||
**Sections preserved**: Reviewer Notes, Screenshots
|
||||
|
||||
**What changed**:
|
||||
Updated: Summary, Backend Changes, Automated Checks
|
||||
Preserved: Manual verification steps, Reviewer notes
|
||||
Added: New validation section
|
||||
|
||||
Review updated PR: {url}
|
||||
```
|
||||
|
||||
## Metadata Management
|
||||
|
||||
**First generation:**
|
||||
|
||||
```markdown
|
||||
<!-- Auto-generated: 2025-10-06T10:00:00Z -->
|
||||
<!-- Last updated: 2025-10-06T10:00:00Z -->
|
||||
<!-- PR: #123 -->
|
||||
<!-- Previous commits: abc123,def456 -->
|
||||
```
|
||||
|
||||
**Subsequent updates:**
|
||||
|
||||
```markdown
|
||||
<!-- Auto-generated: 2025-10-06T10:00:00Z -->
|
||||
<!-- Last updated: 2025-10-06T15:30:00Z -->
|
||||
<!-- PR: #123 -->
|
||||
<!-- Previous commits: abc123,def456,ghi789,jkl012 -->
|
||||
|
||||
---
|
||||
|
||||
**Update History:**
|
||||
|
||||
- 2025-10-06 15:30: Added error handling, fixed tests (2 commits)
|
||||
- 2025-10-06 10:00: Initial implementation (2 commits)
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
## Incremental Update Examples
|
||||
|
||||
**Example 1: Code review changes**
|
||||
|
||||
```
|
||||
User pushes 2 commits after code review feedback
|
||||
|
||||
/catalyst-dev:describe_pr detects:
|
||||
- 2 new commits
|
||||
- Changes in validation logic
|
||||
- New tests added
|
||||
|
||||
Updates:
|
||||
- Appends to "Backend Changes"
|
||||
- Updates "How to Verify It" (reruns test check)
|
||||
- Updates Summary to mention review changes
|
||||
- Preserves reviewer notes and screenshots
|
||||
- Adds to update history
|
||||
```
|
||||
|
||||
**Example 2: Multiple updates**
|
||||
|
||||
```
|
||||
Update 1 (initial): 5 commits
|
||||
Update 2 (review): 3 commits
|
||||
Update 3 (fixes): 2 commits
|
||||
|
||||
Description shows:
|
||||
- Complete history in update log
|
||||
- All changes accumulated
|
||||
- Latest verification status
|
||||
- All manual notes preserved
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**No PR found:**
|
||||
|
||||
```
|
||||
❌ No PR found for current branch
|
||||
|
||||
Open PRs:
|
||||
#120 - Feature A (feature-a branch)
|
||||
#121 - Fix B (fix-b branch)
|
||||
|
||||
Which PR? (enter number)
|
||||
```
|
||||
|
||||
**Template missing:**
|
||||
|
||||
```
|
||||
❌ PR description template required
|
||||
|
||||
Create: thoughts/shared/pr_description.md
|
||||
See earlier in conversation for template structure.
|
||||
```
|
||||
|
||||
**Verification command fails:**
|
||||
|
||||
```
|
||||
⚠️ Some automated checks failed
|
||||
|
||||
Failed:
|
||||
- make test (exit code 1)
|
||||
Error: 2 tests failed in validation.test.ts
|
||||
|
||||
Passed:
|
||||
- make lint ✅
|
||||
- make build ✅
|
||||
|
||||
Fix failing tests before merge or document as known issues.
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Uses `.claude/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"catalyst": {
|
||||
"project": {
|
||||
"ticketPrefix": "RCW"
|
||||
},
|
||||
"linear": {
|
||||
"teamId": "team-id",
|
||||
"inReviewStatusName": "In Review"
|
||||
},
|
||||
"pr": {
|
||||
"testCommand": "make test",
|
||||
"lintCommand": "make lint",
|
||||
"buildCommand": "make build"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Remember:
|
||||
|
||||
- **No interactive prompts** - fully automated
|
||||
- **Incremental updates** - preserve manual edits, append new
|
||||
- **Auto-update title** - based on analysis
|
||||
- **Run verification** - attempt all automated checks
|
||||
- **Link Linear** - extract ticket, update status
|
||||
- **Show what changed** - clear summary of updates
|
||||
- **Full context** - read entire existing description
|
||||
- **Metadata tracking** - commit history, timestamps
|
||||
Reference in New Issue
Block a user