refactor(skills): Make gitea_pr_review action-oriented

Transform the skill from a comment-reply tool to a PR-progress driver:

- Categorize comments by actionability (actionable/question/acknowledged/blocked)
- Launch parallel subagents to make code changes for actionable comments
- Commit and push changes before posting summary
- Post single summary comment describing all actions taken
- Add nix prerequisite note as requested in review

Addresses review comments:
- gitea_pr_review.md:12 - Added nix+nixpkgs note to prerequisites
- gitea_pr_review.md:50 - Acknowledged CI variant as separate skill
This commit is contained in:
2026-01-13 07:55:43 -08:00
parent f3af982304
commit 3a2773dcce

View File

@@ -1,17 +1,27 @@
---
description: Manage and respond to Gitea/Forgejo PR review comments
description: Address Gitea/Forgejo PR review comments with code changes
---
# Gitea PR Review
You are tasked with reading PR review comments and posting replies on Gitea/Forgejo instances. This skill uses the REST API for reading comments and the `tea` CLI for posting replies.
You are tasked with **addressing** PR review comments by making code changes, then summarizing what was done. This skill drives PR progress, not just conversation.
## Philosophy
**Comments are work items, not conversation starters.**
When a reviewer leaves a comment, they're identifying something that needs attention. This skill:
1. Categorizes comments by actionability
2. Makes code changes to address actionable comments
3. Commits and pushes those changes
4. Posts a single summary comment describing what was done
## Prerequisites
- `tea` CLI configured with a Gitea/Forgejo instance
- `yq` installed for parsing tea config
- Access token from tea config: `~/.config/tea/config.yml`
- Repository must be a Gitea/Forgejo remote (not GitHub)
- **Nix users**: All tools available via nixpkgs (`nix-shell -p tea`)
## Initial Setup
@@ -23,26 +33,25 @@ When this command is invoked:
2. **Verify required tools are available**:
```bash
which tea && which yq
which tea
```
If either tool is missing:
If tea is missing:
```
Error: Required tools not found.
Missing: {tea|yq|both}
Error: `tea` CLI not found.
Please install:
- tea: https://gitea.com/gitea/tea
- yq: Available via package manager (nix, brew, apt)
- Nix: nix-shell -p tea
- Other: https://gitea.com/gitea/tea
```
**STOP** if tools are missing.
**STOP** if tea is missing.
3. **Extract configuration from tea config**:
```bash
# Get the Gitea URL and token from tea config
GITEA_URL=$(yq -r '.logins[0].url' ~/.config/tea/config.yml)
TOKEN=$(yq -r '.logins[0].token' ~/.config/tea/config.yml)
# Read tea config (it's YAML but simple enough to grep)
TEA_CONFIG="$HOME/.config/tea/config.yml"
GITEA_URL=$(grep -A1 'logins:' "$TEA_CONFIG" | grep 'url:' | head -1 | sed 's/.*url: //')
TOKEN=$(grep -A5 'logins:' "$TEA_CONFIG" | grep 'token:' | head -1 | sed 's/.*token: //')
```
If config is missing or invalid:
@@ -50,27 +59,31 @@ When this command is invoked:
Error: Could not read tea config at ~/.config/tea/config.yml
Please ensure `tea` is installed and configured:
1. Install tea: https://gitea.com/gitea/tea
1. Install tea
2. Log in: tea login add --url https://your-gitea-instance --token YOUR_TOKEN
```
**STOP** if config is invalid.
4. **Detect repository info from git remote**:
```bash
# Get the remote URL and parse owner/repo
REMOTE_URL=$(git remote get-url origin)
# Parse owner and repo from URL (handles both SSH and HTTPS)
# Example: git@git.example.com:owner/repo.git -> owner/repo
# Example: https://git.example.com/owner/repo.git -> owner/repo
OWNER=$(echo "$REMOTE_URL" | sed -E 's#.*[:/]([^/]+)/[^/]+\.git$#\1#')
REPO=$(echo "$REMOTE_URL" | sed -E 's#.*/([^/]+)\.git$#\1#')
```
5. **Respond with**:
5. **Ensure we're on the PR branch**:
```bash
CURRENT_BRANCH=$(git branch --show-current)
# Verify this branch corresponds to the PR
```
Fetching PR review comments for PR #{PR_NUMBER}...
6. **Respond with**:
```
Addressing PR review comments for PR #{PR_NUMBER}...
Repository: {OWNER}/{REPO}
Branch: {CURRENT_BRANCH}
Gitea URL: {GITEA_URL}
```
@@ -79,10 +92,7 @@ When this command is invoked:
If no PR number is provided, detect from the current branch:
```bash
# Get current branch name
CURRENT_BRANCH=$(git branch --show-current)
# List PRs and find one matching the current branch
tea pr list --fields index,head --output simple | grep "$CURRENT_BRANCH"
```
@@ -94,201 +104,223 @@ No PR found for branch '{CURRENT_BRANCH}'.
Would you like to:
1. Enter a PR number manually
2. Cancel
Which option?
```
- If option 1: Ask for the PR number and continue
- If option 2: End the skill with "No PR to review. Exiting."
## Workflow
### Step 1: Fetch Reviews
### Step 1: Fetch and Parse Comments
Fetch all reviews for the PR:
Fetch all reviews and their comments:
```bash
# Fetch reviews
curl -s -H "Authorization: token $TOKEN" \
"$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews"
```
Parse the response to extract:
- `id`: Review ID (needed for fetching comments)
- `user.login`: Reviewer username
- `state`: Review state (COMMENT, REQUEST_CHANGES, APPROVE, PENDING)
- `body`: Review body text (may be empty for inline-only reviews)
If no reviews found:
```
No reviews found for PR #{PR_NUMBER}.
This PR has no review comments to respond to.
```
**STOP** here.
### Step 2: Fetch Review Comments
For each review with state `COMMENT` or `REQUEST_CHANGES`, fetch inline comments:
```bash
REVIEW_ID="{review_id}"
# For each review, fetch comments
curl -s -H "Authorization: token $TOKEN" \
"$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews/$REVIEW_ID/comments"
```
Parse each comment for:
- `id`: Comment ID
- `path`: File path
- `line`: Line number (may be null for file-level comments)
- `body`: Comment text
- `created_at`: Timestamp
### Step 3: Display Comments Needing Response
Format and display comments grouped by review:
If no reviews found:
```
## Review by {reviewer} ({state})
No reviews found for PR #{PR_NUMBER}.
Nothing to address.
```
**STOP** here.
### Comment 1: {file_path}:{line}
{comment_body}
### Step 2: Categorize Comments
### Comment 2: {file_path}:{line}
{comment_body}
For each comment, categorize it as one of:
---
| Category | Description | Action |
|----------|-------------|--------|
| **actionable** | Requests a code change, addition, or fix | Launch subagent to make change |
| **question** | Asks for clarification or explanation | Include answer in summary |
| **acknowledged** | FYI, self-resolved, or "no action needed" noted | Note in summary |
| **blocked** | Requires external input or is out of scope | Flag for user |
**Categorization heuristics**:
- Contains "add", "change", "fix", "update", "consider adding", "should be" → **actionable**
- Contains "?" or "why", "how", "what" → **question**
- Contains "no need to update", "will be separate", "acknowledged" → **acknowledged**
- Contains "discuss", "later", "out of scope", "blocked by" → **blocked**
Display the categorization:
```
## Comment Analysis
### Actionable (will make changes):
1. {file}:{line} - "{comment_summary}" → Will add nix note to prerequisites
### Questions (will answer in summary):
2. {file}:{line} - "{comment_summary}" → Explain CI token approach
### Acknowledged (no action needed):
3. {file}:{line} - "{comment_summary}" → Reviewer noted separate skill
### Blocked (needs input):
(none)
```
If there are general review comments (without inline location), show them as:
```
### General Review Comment
{review_body}
```
### Step 3: User Confirmation
### Step 4: Select Comments to Address
Use `AskUserQuestion` to let the user choose which comments to address:
Use `AskUserQuestion` to confirm the plan:
```
Which review comments would you like to address?
I've categorized {N} comments. My plan:
1. {file_path}:{line} - "{truncated_comment_first_50_chars}..."
2. {file_path}:{line} - "{truncated_comment_first_50_chars}..."
3. All comments
4. None (just viewing)
**Will make changes for:**
- {file}:{line}: {planned_change}
Enter your choice (comma-separated for multiple, e.g., "1,2"):
**Will explain in summary:**
- {file}:{line}: {planned_explanation}
**No action needed:**
- {file}:{line}: {reason}
Proceed with this plan?
```
- If "All comments" (3): Process all comments
- If "None" (4): End with "No comments to address. You can view the PR at: {PR_URL}"
- Otherwise: Process selected comment numbers
Options:
1. **Proceed** - Execute the plan
2. **Modify** - Let user adjust categorization
3. **Cancel** - Exit without changes
### Step 5: Compose Replies
### Step 4: Address Actionable Comments (Parallel Subagents)
For each selected comment:
For each actionable comment, launch a subagent using the Task tool:
1. **Show the full context**:
```
## Addressing comment on {file_path}:{line}
```
Launch Task subagent with:
- subagent_type: "general-purpose"
- prompt: |
You are addressing a PR review comment. Make the requested change and nothing else.
**Original comment by {reviewer}:**
> {full_comment_body}
**File**: {file_path}
**Line**: {line_number}
**Comment**: {comment_body}
**Diff context**:
```
{diff_hunk}
```
**Current code at that location:**
```
Instructions:
1. Read the file to understand context
2. Make the minimal change to address the comment
3. Do NOT commit - just make the edit
4. Report what you changed
Read the file and show relevant code around the line:
Be precise. Only change what's needed to address this specific comment.
```
**Important**: Launch actionable comment subagents in parallel when they touch different files. For comments on the same file, run sequentially to avoid conflicts.
Wait for all subagents to complete and collect their results.
### Step 5: Commit and Push
After all subagents complete:
1. **Stage changes**:
```bash
# Show 5 lines of context around the commented line
sed -n '{line-5},{line+5}p' {file_path}
git add -A
```
2. **Draft a response**:
- If the comment asks a question, answer it based on the code
- If the comment suggests a change, check if it was addressed and explain
- If the comment points out an issue, acknowledge and describe the fix or reasoning
2. **Create commit with summary**:
```bash
git commit -m "Address PR review comments
3. **Ask user to confirm or modify** using `AskUserQuestion`:
```
**Proposed response:**
Changes made:
- {file1}: {change_summary}
- {file2}: {change_summary}
{draft_response}
Options:
1. Send as-is
2. Edit response (I'll ask for your text)
3. Skip this comment
How would you like to proceed?
Addresses comments from review by {reviewer}"
```
- If "Edit response" (2): Ask "Please provide your response text:" and use that instead
- If "Skip" (3): Move to next comment
3. **Push to remote**:
```bash
git push
```
### Step 6: Post Replies
### Step 6: Post Summary Comment
Post each confirmed reply using `tea comment` with file:line context:
Post a single comment summarizing all actions taken:
```bash
tea comment $PR_NUMBER "Re: @{reviewer}'s comment on \`{file_path}:{line}\`
tea comment $PR_NUMBER "$(cat <<'EOF'
## Review Comments Addressed
{response_body}"
**Changes made** (commit {SHORT_SHA}):
- `{file1}:{line}`: {what_was_changed}
- `{file2}:{line}`: {what_was_changed}
**Responses to questions**:
- `{file3}:{line}`: {answer_to_question}
**Acknowledged** (no action needed):
- `{file4}:{line}`: {reason_no_action}
---
*Automated response via /gitea_pr_review*
EOF
)"
```
**Important**: The Gitea REST API does not support replying directly to review comment threads. This skill posts top-level comments with context as a reliable workaround. For true inline thread replies, users should use the Gitea web UI.
### Step 7: Final Summary
After posting:
```
Posted reply for {file_path}:{line}
```
### Step 7: Summary
After processing all selected comments:
Display to user:
```
## Summary
## PR Review Complete
Posted {N} replies to PR #{PR_NUMBER}:
**Commit**: {SHA}
**Changes**: {N} files modified
- {file_path}:{line} - Response posted
- {file_path}:{line} - Response posted
- {file_path}:{line} - Skipped
### Actions Taken:
- [x] {file1}:{line} - Added nix prerequisite note
- [x] {file2}:{line} - Explained CI approach in comment
- [ ] {file3}:{line} - Acknowledged (separate skill)
You can view the PR at: {GITEA_URL}/{OWNER}/{REPO}/pulls/{PR_NUMBER}
**Comment posted**: {comment_url}
**Note**: Replies are posted as top-level comments with file:line context.
For true inline thread replies, use the Gitea web UI.
PR URL: {GITEA_URL}/{OWNER}/{REPO}/pulls/{PR_NUMBER}
```
## Error Handling
### API request failed
### Subagent failed to make change
If a subagent fails:
```
Error fetching reviews: {error_message}
Warning: Could not address comment on {file}:{line}
Please check:
- Your token is valid and not expired
- The repository exists and you have access
- The Gitea instance is reachable
Reason: {error}
HTTP Status: {status_code}
Response: {response_body}
Options:
1. Skip this comment and continue
2. Retry with manual guidance
3. Abort all changes
```
### tea comment failed
### Push failed
```
Error posting comment: {error_message}
Error pushing changes: {error}
The comment was not posted. You can try:
1. Post manually via Gitea web UI
2. Retry the comment
Your changes are committed locally. You may need to:
1. Pull and resolve conflicts: git pull --rebase
2. Push again: git push
```
Comment text was:
{comment_text}
### No actionable comments
If all comments are questions/acknowledged:
```
No code changes needed.
All comments are either questions or acknowledged items.
Posting summary comment with explanations...
```
## API Reference
@@ -299,7 +331,7 @@ Comment text was:
|--------|--------|----------|
| List reviews | GET | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews` |
| Get review comments | GET | `/api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments` |
| Create issue comment | POST | `/api/v1/repos/{owner}/{repo}/issues/{index}/comments` (via `tea comment`) |
| Create issue comment | POST | via `tea comment` |
### Review States
@@ -310,39 +342,64 @@ Comment text was:
## Limitations
1. **Thread replies**: The Gitea REST API does not support replying directly to review comment threads. This skill posts top-level comments with file:line context as a workaround.
1. **Thread replies**: Gitea API doesn't support inline thread replies. We post a single summary comment instead.
2. **Authentication**: Uses the token from tea config. Session-based auth (for true thread replies) is not supported.
2. **Complex changes**: For comments requiring significant refactoring, the subagent may need guidance. The skill will flag these as "blocked" for user input.
3. **Single Gitea instance**: Uses the first login from tea config. If you have multiple Gitea instances, ensure the correct one is first in your config.
3. **Merge conflicts**: If the branch is behind, you may need to rebase before changes can be pushed.
## Example Invocation
## Example Session
```
User: /gitea_pr_review 5
Assistant: Fetching PR review comments for PR #5...
User: /gitea_pr_review 26
Assistant: Addressing PR review comments for PR #26...
Repository: johno/nixos-configs
Branch: bead/nixos-configs-vru
Gitea URL: https://git.johnogle.info
## Review by johno (REQUEST_CHANGES)
## Comment Analysis
### Comment 1: home/roles/base-linux/default.nix:15
Consider adding a comment explaining why this option is needed.
### Actionable (will make changes):
1. gitea_pr_review.md:12 - "could we indicate nix+nixpkgs satisfies this?"
→ Will add note that nix users can get tools via nixpkgs
---
### Questions (will answer in summary):
(none)
Which review comments would you like to address?
### Acknowledged (no action needed):
2. gitea_pr_review.md:50 - "we eventually want to run this in CI..."
→ Reviewer noted this will be a separate skill
1. home/roles/base-linux/default.nix:15 - "Consider adding a comment..."
2. All comments
3. None (just viewing)
Proceed with this plan? [Proceed]
Enter your choice:
Launching subagent to address comment 1...
[Subagent completes edit]
Committing changes...
[abc1234] Address PR review comments
Pushing to remote...
Done.
Posting summary comment...
## PR Review Complete
**Commit**: abc1234
**Changes**: 1 file modified
### Actions Taken:
- [x] gitea_pr_review.md:12 - Added nix prerequisite note
- [ ] gitea_pr_review.md:50 - Acknowledged (separate skill)
**Comment posted**: https://git.johnogle.info/.../pulls/26#issuecomment-XXX
PR URL: https://git.johnogle.info/johno/nixos-configs/pulls/26
```
## See Also
- `tea` CLI: https://gitea.com/gitea/tea
- Gitea API: https://docs.gitea.com/api/
- `/beads_workflow` for full development workflow
- `/beads_workflow` for full development workflow