Files
gh-coalesce-labs-catalyst-p…/commands/describe_pr.md
2025-11-29 18:14:39 +08:00

12 KiB

description, category, tools, model, version
description category tools model version
Generate or update PR description with incremental changes version-control-git Bash, Read, Write inherit 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:

# 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

# 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:

# 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:

# 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:

# 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:

current_body=$(gh pr view $pr_number --json body -q .body)

Read saved description (if exists):

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:

<!-- 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

# 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):

# 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:

## 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:

<!-- 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:

## Related Issues/PRs

- Fixes https://linear.app/{workspace}/issue/{ticket}
- Related to [any other linked issues]

Get Linear ticket details:

# 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:

# 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":

# 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:

# 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:

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:

gh pr edit $pr_number --title "$new_title"

Update body:

# 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:

# 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:

<!-- Auto-generated: 2025-10-06T10:00:00Z -->
<!-- Last updated: 2025-10-06T10:00:00Z -->
<!-- PR: #123 -->
<!-- Previous commits: abc123,def456 -->

Subsequent updates:

<!-- 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:

{
  "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