Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/opencode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ jobs:
&& (! startsWith(github.head_ref, 'renovate/'))
permissions:
contents: read
pull-requests: write
issues: write
pull-requests: read
issues: read
id-token: write
actions: read
runs-on: ubuntu-latest
Expand Down
107 changes: 33 additions & 74 deletions .opencode/commands/review-pr.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
description: Comprehensive GitHub PR review — gathers the PR via gh, runs specialized review subagents in parallel, normalizes and deduplicates findings, validates inline comment anchoring, and posts a single review with inline and summary comments back to the PR.
description: Comprehensive GitHub PR review — gathers the PR via gh, runs specialized review subagents in parallel, normalizes and deduplicates findings, validates file:line references, and returns a single concise markdown review response. The surrounding `opencode github run` integration posts the returned response to the PR as `opencode-agent[bot]`.
agent: general
---

# Comprehensive PR Review

Perform a comprehensive pull request review by orchestrating specialized review subagents in parallel. Each subagent returns only noteworthy findings in a normalized format. You then deduplicate and filter across agents, validate that findings can be anchored to the diff, and post a single review back to the PR.
Perform a comprehensive pull request review by orchestrating specialized review subagents in parallel. Each subagent returns only noteworthy findings in a normalized format. You then deduplicate and filter across agents, validate `file:line` references against the diff, and **return a single concise markdown review response**. Do **not** post anything to GitHub yourself — the surrounding `opencode github run` integration is responsible for posting the final response to the PR as `opencode-agent[bot]`.

**Requested review aspects (optional):** "$ARGUMENTS"

Expand All @@ -32,8 +32,8 @@ fi
```

- If `PR_NUMBER` is set, run `gh pr view "$PR_NUMBER" --json number,title,body,baseRefName,headRefName,files,url` to confirm a PR is available.
- If it succeeds, you are in **PR mode**: post results back with `gh` (step 7).
- If it fails (no PR or not in CI), fall back to **local mode**: review `git diff` and `git status`, and report findings directly to the user without posting anything to GitHub.
- If it succeeds, you are in **PR mode**: use read-only `gh` calls to gather the diff (steps 2 and 6), and return the review response (step 7) for `opencode github run` to post.
- If it fails (no PR or not in CI), fall back to **local mode**: review `git diff` and `git status`, and return findings directly to the user.
- Do not rely on the current git branch to identify the PR. GitHub Actions pull request workflows usually check out a detached merge ref.

## 2. Gather the diff
Expand All @@ -56,7 +56,7 @@ Parse `$ARGUMENTS` (the requested aspects). Supported aspect keywords:
- `comments` → `comment-analyzer`
- `errors` → `silent-failure-hunter`
- `types` → `type-design-analyzer`
- `simplify` → run `code-simplifier` as a refinement step only; **do not post a review**; stop after simplification
- `simplify` → run `code-simplifier` as a refinement step only; **do not return a review**; stop after simplification
- `all` or no argument → run all applicable reviewers (see below)

### Deterministic reviewer set for `all`
Expand Down Expand Up @@ -106,7 +106,7 @@ Instruct every subagent to:

- If no noteworthy findings exist, return an empty list and a one-line "no issues" note.

Do **not** let subagents post comments themselves. The orchestrator is the only one that posts.
Do **not** let subagents post or return anything beyond their structured findings. The orchestrator is the only one that assembles the final response.

## 5. Normalize, filter, and aggregate findings

Expand All @@ -118,9 +118,9 @@ Collect all findings from all subagents. Each finding must have `file`, `line`,

1. **Drop praise-only items**: remove any entry whose message is only positive (no actionable issue).
2. **Drop nitpicks**: remove cosmetic preferences, style-only feedback, or issues with no real-world impact.
3. **Drop findings not supported by the diff**: if the file referenced is not in the changed-file set, drop the finding. Do **not** compare `line` against the changed-file set — it contains paths, not line numbers. Leave line validation to the diff-anchoring step (step 6).
3. **Drop findings not supported by the diff**: if the file referenced is not in the changed-file set, drop the finding. Do **not** compare `line` against the changed-file set — it contains paths, not line numbers. Leave line validation to the `file:line` reference validation step (step 6).
4. **Deduplicate across agents**: if two or more agents report substantially the same issue at the same location, keep the most specific one (usually from the specialized agent) and discard the duplicate.
5. **Aggregate by root cause**: when several findings share the same underlying root cause (for example, the same inconsistency repeated across README, SKILL.md, and command files), keep **one representative finding** as an inline comment and collapse the remaining occurrences into the summary body. Prefer root-cause aggregation over line-by-line repetition. Cross-document or cross-file consistency problems should usually be summarized once in the review body instead of repeated at each affected location.
5. **Aggregate by root cause**: when several findings share the same underlying root cause (for example, the same inconsistency repeated across README, SKILL.md, and command files), keep **one representative finding** as a `file:line` reference and collapse the remaining occurrences into the review body. Prefer root-cause aggregation over line-by-line repetition. Cross-document or cross-file consistency problems should usually be summarized once in the review body instead of repeated at each affected location.
6. **Orchestrator second filter**: review every remaining finding yourself and remove any you do not also deem noteworthy. This filter keeps the signal high.

### Grouping
Expand All @@ -131,58 +131,26 @@ Group surviving findings by severity:
- **Important** — should fix
- **Suggestions** — optional improvements

Prefer fewer, higher-signal comments over exhaustive lists. Optional guardrail suggestions (such as adding tests for agent frontmatter or reference validation) should be downgraded to `suggestion` severity at most.
Prefer fewer, higher-signal references over exhaustive lists. Optional guardrail suggestions (such as adding tests for agent frontmatter or reference validation) should be downgraded to `suggestion` severity at most.

## 6. Validate inline comment anchoring
## 6. Validate file:line references

Before building the review payload, validate every finding against the PR diff.
Before assembling the final response, validate every finding against the PR diff so each `file:line` reference points at a real changed location.

### Anchoring rules
### Validation rules

- Obtain the diff hunk list from `gh pr diff "$PR_NUMBER"` (already gathered in step 2).
- Obtain the diff hunk list from `gh pr diff "$PR_NUMBER"` (already gathered in step 2) in PR mode, or `git diff` in local mode.
- For each finding, check whether its `line` appears in the diff or diff context for `file`.
- A line is anchored if: it falls within a `+` hunk in the diff for the given file, or within the surrounding unchanged-context lines of that hunk.
- Use `side: "RIGHT"` and the head-file line number for every inline comment.
- If a finding's line **cannot be safely anchored** to the diff, move it to the summary body as a `file:line` reference instead of an inline comment. Do **not** drop it — the file is a changed file, only the line is unanchorable.
- Never fail the entire review because one comment is unanchorable. Move it and continue.
- A `file:line` reference is valid if: it falls within a `+` hunk in the diff for the given file, or within the surrounding unchanged-context lines of that hunk.
- Use the head-file line number for every `file:line` reference.
- If a finding's line **cannot be safely validated** against the diff, keep it in the review body as a `file`-only reference (drop the unverified `:line`) instead of a `file:line` reference. Do **not** drop the finding — the file is a changed file, only the line is unverifiable.
- Never fail the entire review because one `file:line` reference is unverifiable. Adjust it and continue.

## 7. Post the results
## 7. Return the results

### PR mode
**Return a single concise markdown review response only.** Do **not** call `gh api`, `gh pr review`, or `gh pr comment`. The surrounding `opencode github run` integration posts the returned response to the PR as `opencode-agent[bot]`.

Post a **single review** via:

```bash
gh api -X POST repos/{owner}/{repo}/pulls/$PR_NUMBER/reviews --input - <<'EOF'
{
"event": "COMMENT",
"body": "<summary — see format below>",
"comments": [
{"path": "src/foo.ts", "line": 42, "side": "RIGHT", "body": "**important**: ..."}
]
}
EOF
```

Use `{owner}` and `{repo}` from the git remote. Use the explicit `PR_NUMBER` from step 1.

**Review event policy:**

- Use `event: "COMMENT"` for normal reviews.
- Use `event: "REQUEST_CHANGES"` only when there are critical findings that block merge.

**Posting policy:**

- **Anchored findings** → inline comments on the specific representative line.
- **Unanchorable findings** (changed file but no safe diff line) → summary body as `file:line` references.
- **Duplicated root causes** → one representative inline comment plus a summary-body entry listing all affected files.
- Reserve inline comments for issues tied to a specific representative line. Cross-document or cross-file consistency problems should usually be summarized once in the review body instead of repeated across every affected file.

**Inline comment format:**

Each inline comment body should begin with the severity tag: `**critical**:`, `**important**:`, or `**suggestion**:`, followed by the finding message.

**Summary body format:**
### Response format

```markdown
## OpenCode PR Review
Expand All @@ -191,48 +159,39 @@ Reviewed <N> files across <M> areas: <comma-separated agent names>.

### Critical (<count>)

- `file:line` — issue (unanchorable findings and aggregated root-cause occurrences; anchored ones appear inline)
- `file:line` — issue (unverifiable-line findings and aggregated root-cause occurrences use `file`-only references)

### Important (<count>)

- `file:line` — issue (unanchorable findings and aggregated root-cause occurrences)
- `file:line` — issue (unverifiable-line findings and aggregated root-cause occurrences)

### Suggestions (<count>)

- `file:line` — issue (unanchorable findings and aggregated root-cause occurrences)
```

When a root cause affects multiple files, list the representative inline comment once and add a single summary entry naming all affected files (e.g. `Same inconsistency across README.md, SKILL.md, review-pr.md — see inline comment on README.md:42`).

If there are **no findings at all**, post:

```text
No noteworthy issues found.
- `file:line` — issue (unverifiable-line findings and aggregated root-cause occurrences)
```

Do not spam praise or padding. One concise confirmation is sufficient.
When a root cause affects multiple files, add a single entry naming all affected files (e.g. `Same inconsistency across README.md, SKILL.md, review-pr.md — see representative entry on README.md:42`).

### Failure fallback
Each finding entry should begin with the severity tag: `**critical**:`, `**important**:`, or `**suggestion**:`, followed by the finding message.

If `gh api .../reviews` fails:
### No findings

1. **Retry without invalid inline comments**: if the error message identifies a specific invalid comment, remove it (move that finding to the summary body) and retry once.
2. **Fall back to top-level comment**: if still failing, post a single top-level comment with the full summary plus all findings as `file:line` references:
If there are **no findings at all**, return only:

```bash
gh pr comment "$PR_NUMBER" --body "$SUMMARY"
```text
No noteworthy issues found.
```

Never leave the user with no feedback.
Do not include praise, padding, duplicate summaries, or status logs. One concise confirmation is sufficient.

### Local mode

Print the same summary to the user. Do not call `gh`.
Return the same response to the user. Do not call `gh`.

## 8. Notes

- Keep feedback concise. A short review with real signal beats a long review with padding.
- Never post secrets, tokens, or full file contents in comments.
- The workflow grants `pull-requests: write`, so `GH_TOKEN` or `GITHUB_TOKEN` can post reviews when passed to the OpenCode step. Do not attempt to push commits or merge.
- Never include secrets, tokens, or full file contents in the response.
- The workflow grants only read access to pull requests and issues, so `GH_TOKEN` or `GITHUB_TOKEN` cannot post reviews. Do **not** attempt to call `gh api`, `gh pr review`, `gh pr comment`, push commits, or merge. The OpenCode App integration handles all PR-visible posting as `opencode-agent[bot]`.
- If `$ARGUMENTS` lists specific aspects, respect them and skip the rest.
- Re-run after fixes to verify issues are resolved.
Loading