Skip to content

feat: PR review support via GitHub URL#324

Merged
backnotprop merged 13 commits into
mainfrom
feat/pr-reviews
Mar 18, 2026
Merged

feat: PR review support via GitHub URL#324
backnotprop merged 13 commits into
mainfrom
feat/pr-reviews

Conversation

@backnotprop
Copy link
Copy Markdown
Owner

Summary

  • Adds /plannotator-review https://github.com/owner/repo/pull/123 to review pull requests in the Plannotator UI
  • Fetches diff and metadata via gh CLI (handles auth for private repos)
  • Expandable file context fetches from GitHub API using base/head SHAs
  • Review server gates diff switching and staging in PR mode
  • UI shows "PR Review" badge with PR title, number, and link

Architecture

  • packages/shared/pr-provider.ts — runtime-agnostic PR provider (same PRRuntime interface pattern as ReviewGitRuntime)
  • packages/server/pr.ts — Bun wrapper (same pattern as git.ts)
  • Server, entry points, and UI consume the provider through clean APIs

Test plan

  • plannotator review https://github.com/backnotprop/plannotator/pull/324 — this PR itself
  • Verify PR metadata shows in header (title, number, link)
  • Verify diff switcher and staging buttons are hidden
  • Expand collapsed lines — should fetch from GitHub API
  • Annotate files and send feedback
  • plannotator review (no URL) — local mode unchanged
  • Invalid URL shows clear error
  • Without gh auth shows clear error

🤖 Generated with Claude Code

backnotprop and others added 13 commits March 17, 2026 18:12
Introduces `packages/shared/pr-provider.ts` with a `PRRuntime` interface
(same pattern as ReviewGitRuntime in review-core.ts) and GitHub PR
operations: URL parsing, auth check, diff/metadata fetching, and file
content retrieval via `gh` CLI.

`packages/server/pr.ts` is the Bun wrapper that pre-binds the runtime,
matching the git.ts pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When `prMetadata` is provided to `startReviewServer`, the server enters
PR mode: `/api/diff` includes PR metadata and omits gitContext,
`/api/diff/switch` and `/api/git-add` return 400 (not applicable),
and `/api/file-content` fetches from GitHub API using base/head SHAs
instead of local git.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Detects URL argument in `/plannotator-review` command. When a GitHub PR
URL is provided, fetches diff and metadata via `gh` CLI and starts the
review server in PR mode. Local review mode is unchanged when no URL
is passed.

Updates slash command definitions to pass $ARGUMENTS through.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows "PR Review" badge, PR title with link, and owner/repo in the
header when reviewing a pull request. Diff switcher and staging
controls auto-hide since gitContext is omitted in PR mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In PR mode, the feedback markdown now includes PR metadata (repo,
number, title, branches, URL) so the agent has full context about
the remote PR being reviewed. Removes the aggressive "address all
of them" instruction in PR mode since the content is self-explanatory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moves the pure feedback construction function from App.tsx to
utils/exportFeedback.ts so it can be unit tested. Drops the unused
`files` parameter. 11 tests covering local/PR headers, annotation
grouping, sorting, file-scope ordering, and suggested code rendering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces shallow header checks with comprehensive boundary assertions:
local mode must never contain PR-specific content (repo, URL, branches),
PR mode must include all context fields and exclude the generic header.
Covers null/undefined prMetadata edge cases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covered by the "no annotations: returns generic empty regardless of
prMetadata" test which checks all three cases (no arg, null, PR mode).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Main refactored OpenCode's review/annotate handlers into commands.ts.
Accepts theirs for index.ts (thin dispatcher), applies PR mode support
to the new handleReviewCommand() in commands.ts instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap fetchPR() in try/catch in both hook and OpenCode entry points
  so network/auth errors show a clean message instead of a stack trace
- Replace atob() with Buffer.from() for UTF-8 correct base64 decoding
  of PR file content from GitHub API
- Fix stale useCallback deps in handleCopyFeedback (files → prMetadata)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Install scripts were writing the review slash command without
$ARGUMENTS, so PR URLs passed to /plannotator-review were silently
dropped. Also switches PS1 heredoc to single-quoted to prevent
$ARGUMENTS from being expanded as a PowerShell variable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@backnotprop
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@backnotprop backnotprop merged commit 216815c into main Mar 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant