Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
65d5e5f
Require inline PR review comments
dceoy Jul 7, 2026
6f7ab13
Document inline PR review comments
dceoy Jul 7, 2026
8221ce8
Update review-pr skill for inline comments
dceoy Jul 7, 2026
dacfe87
Format markdown files with prettier
dceoy Jul 7, 2026
27ff248
Format README with prettier
dceoy Jul 7, 2026
b3641c1
Format review-pr skill with prettier
dceoy Jul 7, 2026
960f0e2
Apply prettier formatting to review command
dceoy Jul 7, 2026
7fb5ef4
Apply prettier formatting to README
dceoy Jul 7, 2026
67b1cb7
Apply prettier formatting to review skill
dceoy Jul 7, 2026
73007f5
Apply prettier formatting to markdown docs
dceoy Jul 7, 2026
cd313ea
Format review skill markdown
dceoy Jul 7, 2026
f0217a9
Apply prettier formatting to review skill markdown
dceoy Jul 7, 2026
7d4be6b
Apply prettier formatting to command markdown
dceoy Jul 7, 2026
555d22b
Finalize prettier formatting for review skill
dceoy Jul 7, 2026
20f65c4
Finalize prettier formatting for markdown docs
dceoy Jul 7, 2026
19bc25a
Ensure review skill markdown is formatted
dceoy Jul 7, 2026
ac9611b
Ensure README markdown is formatted
dceoy Jul 7, 2026
af4537b
Ensure review skill markdown is prettier formatted
dceoy Jul 7, 2026
ce8296d
Address PR review submission feedback
dceoy Jul 7, 2026
9f92115
Mirror hardened review submission guidance in skill
dceoy Jul 7, 2026
00c4248
Clarify review body fallback behavior
dceoy Jul 7, 2026
c297ca4
Prefer OpenCode App token for gh reviews
dceoy Jul 7, 2026
dabe43a
Document OpenCode App token preference in skill
dceoy Jul 7, 2026
ccd21c2
Document OpenCode App-authored inline reviews
dceoy Jul 7, 2026
72382d7
Allow use-github-token in review docs validation
dceoy Jul 7, 2026
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
5 changes: 3 additions & 2 deletions .agents/skills/local-qa/scripts/validate-opencode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ cd "$(git rev-parse --show-toplevel)"
agents_dir=".opencode/agents"
docs=(.opencode/commands/review-pr.md .opencode/skills/review-pr/SKILL.md)
required_keys=(name description mode permission)
# Backtick-quoted identifiers in the docs that are skills/toolkits, not agents.
non_agents=(pr-feedback-triage pr-review-toolkit)
# Backtick-quoted identifiers in the docs that are skills, toolkits, or config
# inputs rather than agents.
non_agents=(pr-feedback-triage pr-review-toolkit use-github-token)
fail=0

warn() { echo "ERROR: $*" >&2; fail=1; }
Expand Down
151 changes: 114 additions & 37 deletions .opencode/commands/review-pr.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
---
description: Comprehensive GitHub PR review — gathers the PR via gh, runs specialized review subagents in parallel, normalizes and deduplicates findings, validates file:line references against the diff, and returns a single review response for the OpenCode GitHub integration to post.
description: Comprehensive GitHub PR review — gathers the PR via gh, runs specialized review subagents in parallel, normalizes and deduplicates findings, validates diff anchors, and submits GitHub inline review comments when findings can be anchored.
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 file:line references against the diff, and return a single review response. The surrounding `opencode github run` integration posts that response to the PR as `opencode-agent[bot]`; do not post to GitHub yourself.
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 each finding against the PR diff, and submit a GitHub pull request review with inline comments for every finding that has a valid diff anchor.

The surrounding `opencode github run` integration always posts your final text as a PR comment. Therefore, when you successfully submit GitHub review comments yourself, return only a short status message instead of a second full review body.

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

Expand All @@ -14,6 +16,29 @@ Perform a comprehensive pull request review by orchestrating specialized review
Determine whether you are reviewing a real GitHub PR (running in GitHub Actions) or working locally.

- In GitHub Actions the environment provides `GITHUB_EVENT_NAME`, `GITHUB_REPOSITORY`, `GITHUB_REF` (e.g. `refs/pull/42/merge`), and `GITHUB_EVENT_PATH`. The `gh` CLI also requires `GH_TOKEN` or `GITHUB_TOKEN` to be available in the environment.
- Before using `gh`, prefer the OpenCode GitHub App token that `opencode github run` installs into the Git extraheader when `use-github-token` is false. This makes direct `gh api` review submissions appear as `opencode-agent[bot]` instead of `github-actions[bot]`.

```bash
prepare_opencode_gh_token() {
local extraheader encoded decoded token
extraheader="$(git config --local --get http.https://github.com/.extraheader 2>/dev/null || true)"
if [[ "${extraheader}" =~ ^AUTHORIZATION:\ basic\ (.+)$ ]]; then
encoded="${BASH_REMATCH[1]}"
decoded="$(printf '%s' "${encoded}" | base64 --decode 2>/dev/null || true)"
token="${decoded#x-access-token:}"
if [[ -n "${token}" && "${token}" != "${decoded}" ]]; then
export GH_TOKEN="${token}"
export GITHUB_TOKEN="${token}"
return 0
fi
fi
return 0
}

prepare_opencode_gh_token
```

- If no OpenCode App token is available in Git config, keep the existing `GH_TOKEN` or `GITHUB_TOKEN` fallback. This happens when the workflow uses `use-github-token: true` or when running locally.
- Derive the PR number from the event payload first:

```bash
Expand All @@ -31,8 +56,8 @@ if [[ -z "${PR_NUMBER}" && "${GITHUB_REF:-}" =~ ^refs/pull/([0-9]+)/merge$ ]]; t
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**: return a review response (step 7).
- If `PR_NUMBER` is set, run `gh pr view "$PR_NUMBER" --json number,title,body,baseRefName,headRefName,headRefOid,files,url` to confirm a PR is available.
- If it succeeds, you are in **PR mode**: submit a GitHub PR review when findings exist (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.
- Do not rely on the current git branch to identify the PR. GitHub Actions pull request workflows usually check out a detached merge ref.

Expand All @@ -41,7 +66,7 @@ fi
- **PR mode:** run `gh pr diff "$PR_NUMBER"` for the full diff and use the `files` list from `gh pr view "$PR_NUMBER"` for the changed-file set. Prefer `gh pr diff "$PR_NUMBER"` over `git diff` because CI checkouts are shallow (`fetch-depth: 1`).
- **Local mode:** run `git diff --name-only HEAD` plus untracked files from `git status --short` for the changed-file set, then `git diff` for content.

Capture the changed-file list, the full diff, and the PR metadata (title, body, base/head branch) to hand to the subagents.
Capture the changed-file list, the full diff, and the PR metadata (title, body, base/head branch, head SHA) to hand to the subagents and to build the final review payload.

## 3. Choose applicable reviewers based on $ARGUMENTS

Expand Down Expand Up @@ -106,7 +131,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 returns the final response; the `opencode github run` integration posts it.
Do **not** let subagents post comments themselves. The orchestrator validates, deduplicates, and posts the final review.

## 5. Normalize, filter, and aggregate findings

Expand All @@ -120,7 +145,7 @@ Collect all findings from all subagents. Each finding must have `file`, `line`,
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).
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 a `file:line` reference 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 only when it still preserves actionable anchors**: when several findings share the same underlying root cause, keep one representative inline comment at the best anchor and mention the other affected files briefly in that comment. Do not collapse anchored findings into a top-level-only summary when an inline anchor is available.
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 @@ -133,64 +158,116 @@ Group surviving findings by severity:

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.

## 6. Validate file:line references against the diff
## 6. Validate anchors and build inline review comments

Before submitting a GitHub review, validate every finding against the PR diff and classify it as either `inline` or `summary_only`.

Before building the review response, validate every finding against the PR diff so the `file:line` references in the single OpenCode comment stay accurate.
### Inline-first contract

### Validation rules
- Every finding with a valid `file` and diff-anchorable `line` must become an inline review comment.
- Do not skip inline comments merely because the same finding is also listed in a summary.
- Do not convert all findings into a single top-level markdown response when one or more valid inline anchors exist.
- Summary-only findings are allowed only when the issue is real but cannot be safely anchored to the diff, such as a cross-file design issue or a stale/unavailable line.

### Anchor validation rules

- Obtain the diff hunk list from `gh pr diff "$PR_NUMBER"` (already gathered in step 2).
- For each finding, check whether its `line` appears in the diff or diff context for `file`.
- A line 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.
- If a finding's line **cannot be safely matched** to the diff, keep it in the summary body but reference the nearest valid anchor line (or the file alone) instead of an unverified line number. Do **not** drop it — the file is a changed file, only the line is unverifiable.
- Never fail the entire review because one finding's line is unverifiable. Adjust the reference and continue.
- For each finding, check whether its `line` is present in a hunk for `file` on the head side of the PR.
- Prefer anchoring to an added or modified line that directly caused the issue.
- If the reported line is not anchorable but the same finding has a nearby valid head-side diff line in the same file, adjust the anchor to that nearest relevant line and keep it inline.
- If no safe anchor exists, mark the finding `summary_only` with a short reason. Do not silently drop it.

## 7. Return the results
### Inline comment body format

### PR mode
Each inline comment body must be concise and self-contained:

Return a **single concise markdown review response**. Do **not** call `gh api`, `gh pr review`, or `gh pr comment` — the surrounding `opencode github run` integration is responsible for posting the final response to the PR as `opencode-agent[bot]`. Calling GitHub write APIs directly would create a duplicate `github-actions[bot]` posting.
```markdown
**<severity> · <source>**: <issue and concrete fix>
```

Include all findings (whether or not their line matched the diff) in the summary body as `file:line` references so the single top-level OpenCode comment stays actionable.
Avoid repeating the file path or line number inside the inline body because GitHub already displays the anchor. Keep each body one short paragraph unless a minimal code suggestion is genuinely useful.

**Summary body format:**
## 7. Submit the review in PR mode

```markdown
## OpenCode PR Review
### No findings

Reviewed <N> files across <M> areas: <comma-separated agent names>.
If there are no findings after filtering, return exactly:

### Critical (<count>)
```text
No noteworthy issues found.
```

Do not post a GitHub review with an empty comments array.

### Findings with at least one inline anchor

- `file:line` — issue
Submit a single GitHub pull request review using the REST API via `gh api`. Do not use `gh pr review` for inline findings because it cannot submit a structured `comments` array for per-line anchors in this workflow.

### Important (<count>)
Before submission, call `prepare_opencode_gh_token` again. This ensures `gh api` uses the OpenCode GitHub App token when available, even if the workflow also provided a default `GITHUB_TOKEN`.

- `file:line` — issue
Build the review body from trusted strings and normalized findings. It must enumerate every summary-only item, including its fallback reason:

### Suggestions (<count>)
```markdown
OpenCode PR Review: <N> inline finding(s), <M> summary-only finding(s).

- `file:line` — issue
Summary-only findings:
- `<file>` — <fallback reason>: <issue and concrete fix>
```

When a root cause affects multiple files, add a single summary entry naming all affected files (e.g. `Same inconsistency across README.md, SKILL.md, review-pr.md`).
Build the JSON payload with `jq`, not string interpolation, so PR-authored content cannot break JSON structure or inject fields. Write it to a private temporary file and always remove it after submission:

If there are **no findings at all**, return:
```bash
prepare_opencode_gh_token

review_payload="$(mktemp "${TMPDIR:-/tmp}/opencode-pr-review.XXXXXX.json")"
chmod 600 "$review_payload"
trap 'rm -f "$review_payload"' EXIT

jq -n \
--arg commit_id "$head_oid" \
--arg body "$review_body" \
--argjson comments "$comments_json" \
'{commit_id: $commit_id, event: "COMMENT", body: $body, comments: $comments}' \
> "$review_payload"

gh api \
--method POST \
"repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/reviews" \
--input "$review_payload"
```

Operational requirements:

- Prefer the OpenCode GitHub App token from Git config for `gh` commands so inline review submissions are authored by `opencode-agent[bot]`.
- If no OpenCode App token is available, fall back to `GH_TOKEN` or `GITHUB_TOKEN`; this may make direct review submissions appear as `github-actions[bot]`.
- Use the PR head SHA from `gh pr view --json headRefOid` as `commit_id`.
Comment thread
dceoy marked this conversation as resolved.
- Include `summary_only` findings in the review `body`, not as fake inline comments.
- Handle only GitHub 422 anchor-validation failures with the inline-comment retry path. Inspect the response `errors[].field` values such as `comments[0].line` to map failures back to specific `comments[N]` entries.
- If GitHub rejects one or more inline anchors and the offending entries can be identified, move only those findings to `summary_only` with the rejection reason and retry once.
- If a 422 anchor error does not identify the offending `comments[N]` entry, move all inline findings from that failed attempt to `summary_only` before retrying or falling back so no finding is lost.
- If the error indicates the `commit_id` is stale or is no longer part of the pull request, refetch `headRefOid`, rebuild the payload with the new SHA, and retry once. If the refetched SHA still fails, use the fallback path.
- If the retry still fails, do not claim inline comments were posted. Return a concise failure report and convert every attempted inline finding into a summary-only fallback entry, including its file, line, severity, source, message, and failure reason.

After a successful submission, return only a concise status for the surrounding OpenCode integration to post, for example:

```text
No noteworthy issues found.
Submitted OpenCode PR review with 3 inline comment(s) and 1 summary-only finding.
```

Do not spam praise or padding. One concise confirmation is sufficient.
### Findings without inline anchors

If all findings are valid but none can be safely anchored inline, return a concise markdown review body as a top-level fallback and explicitly state why inline comments were not used.

### Local mode
## 8. Local mode

Print the same summary to the user. Do not call `gh`.
Print the same normalized review summary to the user. Do not call `gh api`, `gh pr review`, or `gh pr comment`.

## 8. Notes
## 9. Notes

- Keep feedback concise. A short review with real signal beats a long review with padding.
- Never include secrets, tokens, or full file contents in the review response.
- The `opencode github run` integration posts your final response to the PR as `opencode-agent[bot]`; do not call `gh api`, `gh pr review`, or `gh pr comment` yourself. The workflow may still grant `pull-requests: write` for the integration's posting, and `GH_TOKEN` or `GITHUB_TOKEN` is needed only for `gh pr diff` / `gh pr view` reads. Do not attempt to push commits or merge.
- Never include secrets, tokens, or full file contents in the review response or GitHub comments.
- Do not print tokens or decoded Git authentication headers in logs.
- Do not call `gh pr comment`; it creates top-level noise and bypasses inline review anchors.
- Use `gh api` only for the single final PR review submission after all findings are normalized, deduplicated, and anchor-validated.
- If `$ARGUMENTS` lists specific aspects, respect them and skip the rest.
- Re-run after fixes to verify issues are resolved.
Loading