Instructions#
1. Identify the PR#
The user may provide a PR URL, number, or nothing:
- URL provided (e.g.,
https://github.com/RoboFinSystems/robosystems-app/pull/280): Extract the repo and PR number - Number provided (e.g.,
280): Use the current repository - Nothing provided: Detect from the current branch using
gh pr view --json number,url— if no open PR exists for the current branch, ask the user which PR to review
2. Gather PR Data#
Run these gh commands to collect all context:
# PR metadata + conversation comments in one call
gh pr view <NUMBER> --json number,url,title,body,author,state,isDraft,labels,comments,reviews,reviewDecision,latestReviews,reviewRequests,statusCheckRollup,mergeStateStatus,headRefName,headRefOid,baseRefName,additions,deletions,changedFiles,files,closingIssuesReferences,createdAt,updatedAt
# PR diff (the actual code changes)
gh pr diff <NUMBER>
# Inline review comments — no --json equivalent exists, so this call is still required
gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)/pulls/<NUMBER>/comments --paginateField notes:
reviewsnotreviewers—reviewersis not a valid field and errors.reviewDecisionis the single field that answers "has this been approved."commentscovers the top-level conversation, so no separateissues/<n>/commentscall is needed.closingIssuesReferencesgives the linked issue (needed for step 5's requirements check);filesgives per-file add/delete counts (needed for triaging a large diff);headRefOidis the HEAD SHA.- Keep
--paginatebare. Adding-q/--jqmakes gh emit one JSON document per page instead of a merged array, and--slurpcan't be combined with--jq. Pipe tojqafter the call, not through it.
3. Categorize Review Feedback#
Organize all comments and checks into categories:
- Human Reviews: Comments from human reviewers (approve, request changes, general feedback)
- AI Reviews: Comments from Claude, Copilot, or other AI review bots
- Code Quality: Comments from linters, formatters, type checkers
- Security: Findings from security scanners (Dependabot, CodeQL, Trivy)
- CI/CD: Build status, test results, deployment checks
How feedback actually arrives in this repo — don't read the categories too literally:
- Formal
reviewsand inlinepulls/<n>/commentsare typically empty, andreviewDecisionis usually blank. That's the norm here, not a signal that review was skipped. Don't report "no review feedback" on the strength of an emptyreviewsarray. - AI review is opt-in.
claude.ymlonly fires on an explicit@claudemention from anOWNER/MEMBER/COLLABORATOR— there is no automatic review on PR open. When it has run, the findings are a bot comment in the conversationcomments, not a formal review. Absence of AI feedback usually means nobody asked. - CI is the
test.ymlreusable workflow (vitest → typecheck → lint → format:check →npm run build→ cfn-lint → Trivy). A green suite with a red build is the common shape — the build step catches what the gate does not. - In
statusCheckRollup, checks expose.namewhile legacy statuses expose.context, and aconclusionofNEUTRALorSKIPPEDis not a failure. Read the conclusion, don't pattern-match on non-SUCCESS.
4. Review the Diff#
With the full PR diff in hand, perform your own review focusing on:
- Correctness: Does the code do what the PR description says?
- Patterns: Does it follow existing codebase patterns (check
CLAUDE.md)? - Right repo: Is this app-local code, or a patch over something that belongs in
@robosystems/core? A fix applied here to a shared component gets overwritten by the next version bump — that's a blocking issue, not a nit. Same for behavior that belongs in the RoboSystems API. - Client/server boundary (Next.js 16, App Router): is
'use client'applied at the right level, and does anything server-only leak into a client component? Note that middleware issrc/proxy.tsin this version — notsrc/middleware.ts. - Secret exposure:
NEXT_PUBLIC_*values are baked into the client bundle at build time and are public forever. Any secret that gained aNEXT_PUBLIC_prefix is a blocking finding. Conversely, a server-only variable read from a client component is a bug. - API routes (
src/app/api/): the public-facing ones (contact,support) carry rate limiting (src/lib/rate-limiter.ts), Turnstile verification (src/lib/turnstile-server.ts), and client-IP derivation (src/lib/client-ip.ts). A new public endpoint that skips those is a gap; a change to IP derivation deserves close reading, since it's what rate limiting keys on. - Auth: is session validation actually enforced for the surface being added, or only visually hidden?
- Security: any OWASP top 10 concerns — XSS via
dangerouslySetInnerHTML, unvalidated redirects, injection intofetchURLs? - UI consistency: Flowbite components and existing Tailwind idiom, dark mode on every new surface, and responsive behavior. These regress silently and no test catches them.
- Accessibility: labels, keyboard reachability, heading order.
eslint-plugin-jsx-a11yis configured, so a finding it can't see is the one worth writing down. - Error handling: does a failed API call surface something to the user, or fail silently?
- Tests: are changes covered? Read the test, don't trust that it's green — a test that asserts the buggy behavior passes just as happily as a correct one. Check whether new
@robosystems/*imports need mock coverage insrc/__mocks__/(missing mocks fail as opaque module-resolution errors, not assertion failures). - Disclosure hygiene (this repo is public): does the PR text over-disclose? A security-fix description should name the area hardened, never the mechanism — no exploit mechanics, attack scenarios, affected-route enumerations, or payloads. Also check sequencing: deploys here are manual, so a merged fix can sit undeployed while the diff describes a live bug. Flag it.
- Missing changes: any files that should have been updated but weren't? Common misses: a new env var not added to
.env.example/build.yml/cloudformation/template.yaml, a new route missing fromsitemap.tsorrobots.ts, a new page without a test.
5. Output Format#
Provide a structured review:
## PR Summary
**Title**: ...
**Author**: ... | **Branch**: ... → ...
**Status**: ... | **Changes**: +X / -Y across Z files
<Brief summary of what the PR does>
## Existing Review Feedback
### Human Reviews
<Summarize human reviewer comments and their status>
### AI Reviews
<Summarize AI review comments — highlight unresolved items>
### Code Quality
<Summarize code quality bot findings>
### Security
<Summarize security scanner findings — flag anything critical>
### CI/CD Status
<Pass/fail status of all checks>
## My Review
### Issues (should fix before merge)
<Numbered list of problems found>
### Suggestions (non-blocking improvements)
<Numbered list of suggestions>
### Questions
<Anything unclear that needs clarification>
## Verdict
<APPROVE / REQUEST_CHANGES / NEEDS_DISCUSSION — with brief rationale>
Notes#
- If the PR diff is very large (>2000 lines), use the
filesarray to triage by churn and note which files were skimmed - For security findings, always err on the side of flagging — false positives are better than missed vulnerabilities
- Cross-reference the PR description with the actual diff to catch scope creep or missing implementation
- If the PR references an issue (
closingIssuesReferences), check that the issue requirements are met
$ARGUMENTS