Fetch a PR/MR diff, analyze it through the active persona's lens, and post a review with inline comments — all footnoted with model and persona attribution. On consecutive runs, automatically detects previous reviews and enters re-review mode.
-
Verify active persona — a persona is active if set via /set-persona or an ad-hoc prompt (e.g., "act as a senior infosec engineer", "you are a security reviewer"). For ad-hoc, extract a short name and proceed. Announce per the observability format in ~/.claude/guidelines/context-aware-learnings.md:
- Persona already active:
🎭 Persona active: <name> — proceeding.
- No persona active: glob
.claude/personas/ and ~/.claude/commands/set-persona/ for available personas, pick the best match, announce 🎭 No persona active — recommending <name>. Set it?, and wait for operator confirmation before proceeding.
The persona shapes every aspect of the review — proceeding without one produces generic feedback.
-
Platform commands — platform-specific commands are inlined via ! preprocessing. No detection needed.
-
Resolve the request and detect mode — resolve the request number from $ARGUMENTS (URL → extract number, number → use directly, empty → detect from current branch). Then follow the base reference: Consolidated Fetch → Terminal State Handling.
Linked-repo detection: if the resolved request's repo differs from CWD's git remote, this is a linked-repo review — CWD is the fact-check substrate, the target is a different repo. Do not fall back to "detect from current branch" in this mode; require an explicit URL or <owner>/<repo>#<number>. Announce: 🔗 Linked-repo review: CWD <cwd-repo> → target <target-repo>.
-
Check for previous reviews — using the reviews data already fetched in step 3, filter for both *Persona:* <PERSONA_NAME> AND *Role:* Reviewer in review bodies. Both must match — the same persona may post as Author (via address-request-comments) and those are separate comment chains.
GitLab: Check for top-level comments containing both *Persona:* <PERSONA_NAME> and *Role:* Reviewer (requires a separate API call).
If a previous review is found, set MODE=re-review, store LAST_REVIEW_ID and LAST_REVIEW_TS, and read re-review-mode.md from the skill's base directory. Otherwise, set MODE=first-review.
Announce: 🔍 Mode: first review or 🔄 Mode: re-review (previous review from <LAST_REVIEW_TS>)
-
Quick-exit check — before fetching the full diff, check if anything has changed. This is the cheapest possible check and should short-circuit polling runs that find nothing new.
Non-negotiable: run both phases as specified. Do not reduce phase 1 fields or skip phase 2 to save tokens. Consecutive no-ops create optimization pressure — resist it. The cost is 1-2 API calls; the failure mode is missed operator comments.
Re-review mode — two-phase check, short-circuiting on the first signal:
Phase 1 (1 call): Fetch activity signals via the Fetch Activity Signals (consolidated) script. Parse the JSON response to check:
!cat ~/.claude/platform-commands/fetch-activity-signals.sh 2>/dev/null || echo "UNCONFIGURED: run setup-claude.sh to set up platform-commands"
- New commits: latest commit SHA differs from last reviewed
- New reviews from others: any review with a non-empty body submitted after
LAST_REVIEW_TS that doesn't contain our persona+role footnote. Ignore empty-body reviews — they're wrappers for inline comments, which phase 2 catches reliably.
- New top-level comments: any comment created after
LAST_REVIEW_TS
- State: if
MERGED or CLOSED → cancel cron and stop (step 3 logic)
If any activity signal → proceed to step 6+ (skip phase 2).
Phase 2 (1 call, only if phase 1 found nothing): Fetch recent inline comments (10) via the quick-exit check script. Filter out self-comments (Role:.*<YOUR_ROLE> in body). Non-self present and some new → proceed. Non-self present and all old → skip. All self → inconclusive, fall through to full incremental fetch.
!cat ~/.claude/platform-commands/fetch-recent-inline-comments.sh 2>/dev/null || echo "UNCONFIGURED: run setup-claude.sh to set up platform-commands"
This is 1 call when there's new activity in phase 1, 2 calls when polling quietly. All four activity signals (commits, non-empty reviews, top-level comments, inline comments) are covered.
First-review mode with cached analysis: If you have high-confidence cached data from a previous invocation in this session (e.g., you already analyzed the full diff and the commit SHA matches), skip the full diff fetch and trust your cached analysis. The cheap SHA check validates the cache.
If nothing has changed, emit a single line and stop — do not proceed to step 6+:
PR #<REQUEST_NUMBER>: no changes since last review (<LAST_REVIEW_TS>). Skipping. 🔄
-
Fetch PR metadata and diff — run these in parallel:
Fetch Diff:
!`cat ~/.claude/platform-commands/fetch-review-diff.sh 2>/dev/null || echo "UNCONFIGURED: run setup-claude.sh to set up platform-commands"`
Fetch Files Changed:
!`cat ~/.claude/platform-commands/fetch-review-files.sh 2>/dev/null || echo "UNCONFIGURED: run setup-claude.sh to set up platform-commands"`
Fetch Review Details:
!`cat ~/.claude/platform-commands/fetch-review-details.sh 2>/dev/null || echo "UNCONFIGURED: run setup-claude.sh to set up platform-commands"`
Fetch Commits:
!`cat ~/.claude/platform-commands/fetch-review-commits.sh 2>/dev/null || echo "UNCONFIGURED: run setup-claude.sh to set up platform-commands"`
Store the diff as FULL_DIFF, file list as CHANGED_FILES, body as REQUEST_BODY, commits as COMMITS.
For large diffs, read the full diff — thorough review requires seeing all changes.
Re-review only: Also identify NEW_COMMITS — commits with timestamps after LAST_REVIEW_TS.
-
Fetch previous comment state (re-review only) — follow re-review-mode.md.
-
Load domain-relevant learnings — match CHANGED_FILES paths and domains against learnings filenames:
- Read
~/.claude/learnings-providers.json to discover all provider directories. Glob <each provider localPath>/*.md and docs/learnings/*.md to get the full inventory
- For each changed file, derive domain terms from the path and content (e.g.,
src/api/ -> "api", .github/workflows/ -> "ci-cd", tests/ -> "testing")
- Match domain terms against learnings filenames (e.g., "ci" matches
ci-cd.md, "test" matches testing-patterns.md)
- Read matched files to ground the review in established knowledge
- Announce:
📚 Loaded domain learnings: <list>
- This supplements the persona's proactive cross-refs with PR-specific knowledge
-
Analyze changes — review through the active persona's lens. Base analysis only on MR content — the diff, changed files, MR body, commits, and loaded learnings. The consolidated fetch includes existing reviews and comments for mode detection only; do not read, reference, or let them influence your findings. Your review must be fully independent. Redundant findings across reviewers are expected; influenced findings are not.
Linked-repo review (CWD ≠ target): CWD's code is concrete implementation evidence. When the diff makes a claim CWD can verify or contradict (a contract shape, a field meaning, a behavior), grep CWD and cite the result. CWD code is evidence, not opinion — the independence rule still applies to other reviewers' findings, but verifiable code in a linked repo is the opposite of conjecture and should be used.
First review: For each file, evaluate:
- Does the change align with the persona's domain priorities?
- Are there taxonomy, placement, or architectural concerns?
- Are there patterns from loaded learnings that apply?
- Are there bugs, edge cases, or missing considerations?
- Is there unnecessary complexity or missing simplification?
Re-review: Follow re-review-mode.md — evaluate previous comment responses + review new code.
Separate identification from suggestion. Finding an issue and proposing a fix require independent reasoning. A wrong suggestion compounds — the addresser implements it, the reviewer confirms it, and the operator unwinds multiple layers. Verify a rule's scope before citing it, think about what actually improves the content, and when uncertain, identify without prescribing.
Build the output lists:
INLINE_COMMENTS: new findings on new/changed code. All specifics belong here — not in the summary. Linked-repo citations use a repo-name prefix: <repo-name>/<path>:<line>. Bare paths from a different repo are unresolvable for the target MR's reviewers.
SUMMARY_POINTS: high-level themes. No file-specific details.
No duplication between summary and inline comments. The summary names themes; inline comments carry the specifics.
-
Compose the review — build the review payload: