PR Review
Review a change against Lumen's conventions. The distinctive skill here is
platform routing: this is a cross-platform monorepo, so the same finding
category means different things in libs/ui-react (Tailwind) versus
libs/ui-rnative (useStyleSheet). Apply the right rules to the right files
and never leak one platform's rules onto the other.
Setup
Local branch
git fetch origin main
git diff origin/main...HEAD --stat
git diff origin/main...HEAD
git log origin/main...HEAD --oneline
Remote PR (GitHub link)
gh pr view <PR_NUMBER> --json title,body,baseRefName,headRefName,files
gh pr diff <PR_NUMBER>
Then read the full diff. For each changed file, read the whole file (not
just the hunk) so findings account for surrounding context. Group changes into
new files, modified files, deleted files.
Platform routing (do this first)
Derive the touched libs from the changed paths (git diff origin/main...HEAD --name-only | cut -d/ -f1-2 | sort -u), map each to its platform via the
Libraries table in AGENTS.md, then apply the matching topic skill's
## Review checks. Applying the wrong platform's rules is the main failure mode
— decide deliberately.
The concrete, diff-verifiable violations for each topic live in that topic
skill's ## Review checks table — this skill does not restate them:
| Topic |
Skill (see its ## Review checks) |
| API design & composition (props, compound, controlled state, parity) |
component-architecture |
Styling (Tailwind vs useStyleSheet) |
component-styling |
| Tests (Vitest vs Jest) |
component-testing |
| File/folder layout & required files |
component-anatomy |
| Stories |
component-stories |
| MDX docs |
component-mdx |
| Code Connect |
code-connect |
| Version plan |
release-plan (scored below) |
Rules:
- A single PR often touches both platforms (a component usually ships on web
and native together). When both
ui-react* and ui-rnative* are touched,
apply both the web and RN review checks and add the API-parity check:
prop names, defaults, and variant vocabulary should match across the two
implementations unless there's a platform reason not to (Parity).
- Never apply Tailwind rules to an RN file or
useStyleSheet rules to a web
file. The token vocabulary is shared (bg-muted ↔ t.colors.bg.muted),
the mechanism is not.
- Visualization / lib exceptions are described once in the
Libraries table
and in each skill's Review checks (e.g. RN charts under
Components/visualization/ use useTheme() + flat stories, no .mdx/figma).
Don't flag files a lib does not use.
libs/design-core/**: the CSS/Tailwind tokens and the JS theme objects must
stay in sync (see the figma-token-sync skill). If a token is added/changed
on one side only, flag it under Consistency.
libs/utils-shared/**: cross-platform TS/React — apply the shared criteria
below, no styling rules.
Already enforced — do not review by hand
These are ESLint errors (see eslint.config.mjs) and a Stop hook runs
nx affected --target=lint --fix automatically. Flagging them by hand is noise;
spend findings on things a linter can't catch. Do not raise:
- Banned imports (
no-restricted-imports): forwardRef, TouchableOpacity,
Animated/Easing/LayoutAnimation, ElementRef, MutableRefObject.
- Import hygiene:
import/order, import/no-duplicates, import/no-cycle,
import/no-default-export, import/no-unused-modules.
- Type style:
type over interface (consistent-type-definitions),
import type (consistent-type-imports), T[] over Array<T>
(array-type).
- Dead/unused code (
no-unused-vars), eqeqeq, no-negated-condition,
default-param-last, no-console, and all formatting (prettier).
- Accessibility lint (
jsx-a11y strict) and module boundaries
(@nx/enforce-module-boundaries scope tags).
- Unknown/invalid Tailwind classnames (
eslint-plugin-better-tailwindcss).
Caveat: a valid Tailwind class that should be a design token
(text-gray-500, font-bold, w-[108px]) lints clean — that stays a manual
check, see component-styling's Review checks.
Findings vs severity — independent
- Number of findings is unbounded. 0 is a valid, good result. Never pad to a
number, never cap at one.
- Severity (
X/10) rates a single finding's importance. It has nothing to do
with how many findings there are.
No hallucinated findings
Only report issues you can point to at a concrete file:line. If the code is
correct and follows conventions, report zero findings and recommend
approval. Never invent, pad, or raise speculative "could maybe" issues. Do not
flag style that already matches the codebase.
Severity scale
- 10/10 Critical — bugs, crashes, data loss, security. Must fix before merge.
- 8-9/10 Major — wrong abstraction, missing error handling, type unsafety
that compiles but fails at runtime, missing version plan.
- 6-7/10 Moderate — performance flaws, inconsistency with codebase patterns,
missing tests for important paths, wrong version-plan bump type.
- 4-5/10 Minor — naming inconsistencies, suboptimal patterns, missing JSDoc
on public API.
- 1-3/10 Nit — cosmetic, optional, preference.
Shared review criteria (both platforms)
Apply these regardless of platform; platform specifics are in the references.
Correctness
- Does the code do what it claims? Are edge cases handled (null, undefined,
empty arrays, error/loading states)?
- Async: race conditions, cleanup on unmount, no unhandled rejections.
- Nullable/optional values handled safely; user-facing error messages helpful.
- Comments explain intent (the why), never restate the code — flag
comments that just narrate mechanics, and complex logic left uncommented.
Type safety
- No
any (lint only warns) or as assertions that hide a real mismatch.
- Explicit return types on module-level functions (except JSX components).
- Generics not overly broad or narrow.
Performance
- Unnecessary re-renders: unstable objects/functions passed to memoized children.
- Large inline objects/arrays created every render; expensive work not memoized.
- List
key correctness.
Abstraction & API quality
The rules — prop naming, positive booleans, minimal public API, Base*Props
layering, compound composition, controlled/uncontrolled state, cross-platform
parity, memoization — are owned by the component-architecture skill. Apply its
## Review checks table here (routed above); this skill does not restate them.
Docs vs implementation consistency
.stories.tsx and .mdx must reflect the current API — no references to
removed/renamed props, default values match the implementation, interactive
examples still work. (Not applicable to visualization libs.)
Version plan check
The version-plan rules (when a plan is required, the exemption list, the
path→package mapping, filename convention, always-patch, one-package-per-file)
live in the release-plan skill — the single source. Load it if you need the
detail. Here, just verify and score:
git diff origin/main...HEAD --name-only -- .nx/version-plans/
- Production code under
libs/*/src/ changed but no plan exists → Major
(8/10), category Release. (A PR touching only exempt files needs no plan.)
- Bump type is not
patch → Moderate (6/10), Release, recommend
patch.
- A single file groups multiple packages (should be one file per package) →
Moderate (6/10),
Release.
- Plan names the wrong package for the changed paths (see the mapping in
release-plan) → Moderate (6/10), Release.
Output
If the review is short (fewer than ~15 findings), return it directly. If long,
write it to tmp/pr-review-[branch-name].md and report the path (tmp is
gitignored).
The review is a flat, scored list — one item per finding, sorted by severity
(highest first). No per-file nesting; each item is self-contained.
# PR Review: [branch-name]
## Summary
[1-3 sentence overview of the PR's purpose and scope]
**Platforms touched**: React web / React Native / both / design-core / utils-shared
**Files changed**: X | **Added**: +X | **Removed**: -X
## Component Checklist (if a new component was added)
[Fill in the required-files checklist from `component-anatomy` for the component's
lib, marking each item pass/fail]
## Findings
| # | Severity | Category | Finding | Location |
|---|----------|----------|---------|----------|
| 1 | 9/10 | Type Safety | Uses `any` for payload type | `libs/ui-react/src/lib/Components/core/Menu/types.ts:28` |
| 2 | 7/10 | Consistency | Raw Tailwind color `text-gray-500` instead of `text-muted` | `libs/ui-react/src/lib/Components/core/Menu/Menu.tsx:26` |
### Details
**1. [Finding title]** — 9/10 Type Safety — `libs/ui-react/src/lib/Components/core/Menu/types.ts:28`
[1-3 sentence description]
> **Fix**: [concrete suggestion]
Key rules for output
- Each finding has exactly one severity, one category, one
file:line location.
Use a range (:42-50) when it spans lines. The location in the table must
match the location in the details entry.
- Categories:
Correctness, Type Safety, Consistency, Performance,
Abstraction, API Quality, Docs Consistency, Release, Parity.
- The summary table comes first for scanning; details follow for depth.
- Zero findings is a valid result — say so explicitly and recommend approval.
Tips
- Always read the full file, not just the diff hunk.
- Compare against a similar existing component in the same library for
pattern alignment.
- Check the PR doesn't accidentally remove or break existing barrel exports.
- Verify new dependencies land in the correct
package.json (peer vs dev).
1---2name: pr-review3description: Review a PR or the current branch for a Lumen design-system change — routes each changed file to React (web/Tailwind) or React Native (useStyleSheet) guidelines, checks the Nx version plan, and reports a flat, severity-scored finding list. Use when the user asks to review a PR, review code changes, check a branch, do a local code review, or provides a GitHub PR URL.4---56# PR Review78Review a change against Lumen's conventions. The distinctive skill here is9**platform routing**: this is a cross-platform monorepo, so the same finding10category means different things in `libs/ui-react` (Tailwind) versus11`libs/ui-rnative` (`useStyleSheet`). Apply the right rules to the right files12and never leak one platform's rules onto the other.1314## Setup1516### Local branch1718```bash19git fetch origin main20git diff origin/main...HEAD --stat21git diff origin/main...HEAD22git log origin/main...HEAD --oneline23```2425### Remote PR (GitHub link)2627```bash28gh pr view <PR_NUMBER> --json title,body,baseRefName,headRefName,files29gh pr diff <PR_NUMBER>30```3132Then read the full diff. For each changed file, **read the whole file** (not33just the hunk) so findings account for surrounding context. Group changes into34new files, modified files, deleted files.3536## Platform routing (do this first)3738Derive the touched libs from the changed paths (`git diff origin/main...HEAD39--name-only | cut -d/ -f1-2 | sort -u`), map each to its platform via the40`Libraries` table in `AGENTS.md`, then apply the matching topic skill's41`## Review checks`. Applying the wrong platform's rules is the main failure mode42— decide deliberately.4344The concrete, diff-verifiable violations for each topic live in that topic45skill's `## Review checks` table — this skill does **not** restate them:4647| Topic | Skill (see its `## Review checks`) |48| --- | --- |49| API design & composition (props, compound, controlled state, parity) | `component-architecture` |50| Styling (Tailwind vs `useStyleSheet`) | `component-styling` |51| Tests (Vitest vs Jest) | `component-testing` |52| File/folder layout & required files | `component-anatomy` |53| Stories | `component-stories` |54| MDX docs | `component-mdx` |55| Code Connect | `code-connect` |56| Version plan | `release-plan` (scored below) |5758Rules:5960- A single PR often touches **both** platforms (a component usually ships on web61 and native together). When both `ui-react*` and `ui-rnative*` are touched,62 apply **both** the web and RN review checks and add the **API-parity check**:63 prop names, defaults, and variant vocabulary should match across the two64 implementations unless there's a platform reason not to (`Parity`).65- **Never apply Tailwind rules to an RN file or `useStyleSheet` rules to a web66 file.** The token *vocabulary* is shared (`bg-muted` ↔ `t.colors.bg.muted`),67 the *mechanism* is not.68- **Visualization / lib exceptions** are described once in the `Libraries` table69 and in each skill's Review checks (e.g. RN charts under70 `Components/visualization/` use `useTheme()` + flat stories, no `.mdx`/figma).71 Don't flag files a lib does not use.72- `libs/design-core/**`: the CSS/Tailwind tokens and the JS theme objects must73 stay in sync (see the `figma-token-sync` skill). If a token is added/changed74 on one side only, flag it under `Consistency`.75- `libs/utils-shared/**`: cross-platform TS/React — apply the shared criteria76 below, no styling rules.7778## Already enforced — do not review by hand7980These are ESLint errors (see `eslint.config.mjs`) and a `Stop` hook runs81`nx affected --target=lint --fix` automatically. Flagging them by hand is noise;82spend findings on things a linter can't catch. Do **not** raise:8384- Banned imports (`no-restricted-imports`): `forwardRef`, `TouchableOpacity`,85 `Animated`/`Easing`/`LayoutAnimation`, `ElementRef`, `MutableRefObject`.86- Import hygiene: `import/order`, `import/no-duplicates`, `import/no-cycle`,87 `import/no-default-export`, `import/no-unused-modules`.88- Type style: `type` over `interface` (`consistent-type-definitions`),89 `import type` (`consistent-type-imports`), `T[]` over `Array<T>`90 (`array-type`).91- Dead/unused code (`no-unused-vars`), `eqeqeq`, `no-negated-condition`,92 `default-param-last`, `no-console`, and all formatting (prettier).93- Accessibility lint (`jsx-a11y` strict) and module boundaries94 (`@nx/enforce-module-boundaries` scope tags).95- Unknown/invalid Tailwind classnames (`eslint-plugin-better-tailwindcss`).9697Caveat: a **valid** Tailwind class that should be a design token98(`text-gray-500`, `font-bold`, `w-[108px]`) lints clean — that stays a **manual**99check, see `component-styling`'s Review checks.100101## Findings vs severity — independent102103- **Number of findings is unbounded.** 0 is a valid, good result. Never pad to a104 number, never cap at one.105- **Severity (`X/10`)** rates a single finding's importance. It has nothing to do106 with how many findings there are.107108## No hallucinated findings109110Only report issues you can point to at a concrete `file:line`. If the code is111correct and follows conventions, report **zero findings** and recommend112approval. Never invent, pad, or raise speculative "could maybe" issues. Do not113flag style that already matches the codebase.114115## Severity scale116117- **10/10 Critical** — bugs, crashes, data loss, security. Must fix before merge.118- **8-9/10 Major** — wrong abstraction, missing error handling, type unsafety119 that compiles but fails at runtime, missing version plan.120- **6-7/10 Moderate** — performance flaws, inconsistency with codebase patterns,121 missing tests for important paths, wrong version-plan bump type.122- **4-5/10 Minor** — naming inconsistencies, suboptimal patterns, missing JSDoc123 on public API.124- **1-3/10 Nit** — cosmetic, optional, preference.125126## Shared review criteria (both platforms)127128Apply these regardless of platform; platform specifics are in the references.129130### Correctness131132- Does the code do what it claims? Are edge cases handled (null, undefined,133 empty arrays, error/loading states)?134- Async: race conditions, cleanup on unmount, no unhandled rejections.135- Nullable/optional values handled safely; user-facing error messages helpful.136- Comments explain **intent** (the *why*), never restate the code — flag137 comments that just narrate mechanics, and complex logic left uncommented.138139### Type safety140141- No `any` (lint only warns) or `as` assertions that hide a real mismatch.142- Explicit return types on module-level functions (except JSX components).143- Generics not overly broad or narrow.144145### Performance146147- Unnecessary re-renders: unstable objects/functions passed to memoized children.148- Large inline objects/arrays created every render; expensive work not memoized.149- List `key` correctness.150151### Abstraction & API quality152153The rules — prop naming, positive booleans, minimal public API, `Base*Props`154layering, compound composition, controlled/uncontrolled state, cross-platform155parity, memoization — are owned by the `component-architecture` skill. Apply its156`## Review checks` table here (routed above); this skill does not restate them.157158### Docs vs implementation consistency159160- `.stories.tsx` and `.mdx` must reflect the current API — no references to161 removed/renamed props, default values match the implementation, interactive162 examples still work. (Not applicable to visualization libs.)163164## Version plan check165166The version-plan **rules** (when a plan is required, the exemption list, the167path→package mapping, filename convention, always-`patch`, one-package-per-file)168live in the `release-plan` skill — the single source. Load it if you need the169detail. Here, just verify and score:170171```bash172git diff origin/main...HEAD --name-only -- .nx/version-plans/173```174175- Production code under `libs/*/src/` changed but **no plan exists** → **Major176 (8/10)**, category `Release`. (A PR touching only exempt files needs no plan.)177- Bump type is **not** `patch` → **Moderate (6/10)**, `Release`, recommend178 `patch`.179- A single file **groups multiple packages** (should be one file per package) →180 **Moderate (6/10)**, `Release`.181- Plan names the **wrong package** for the changed paths (see the mapping in182 `release-plan`) → **Moderate (6/10)**, `Release`.183184## Output185186If the review is short (fewer than ~15 findings), return it directly. If long,187write it to `tmp/pr-review-[branch-name].md` and report the path (`tmp` is188gitignored).189190The review is a **flat, scored list** — one item per finding, sorted by severity191(highest first). No per-file nesting; each item is self-contained.192193```markdown194# PR Review: [branch-name]195196## Summary197198[1-3 sentence overview of the PR's purpose and scope]199200**Platforms touched**: React web / React Native / both / design-core / utils-shared201**Files changed**: X | **Added**: +X | **Removed**: -X202203## Component Checklist (if a new component was added)204205[Fill in the required-files checklist from `component-anatomy` for the component's206lib, marking each item pass/fail]207208## Findings209210| # | Severity | Category | Finding | Location |211|---|----------|----------|---------|----------|212| 1 | 9/10 | Type Safety | Uses `any` for payload type | `libs/ui-react/src/lib/Components/core/Menu/types.ts:28` |213| 2 | 7/10 | Consistency | Raw Tailwind color `text-gray-500` instead of `text-muted` | `libs/ui-react/src/lib/Components/core/Menu/Menu.tsx:26` |214215### Details216217**1. [Finding title]** — 9/10 Type Safety — `libs/ui-react/src/lib/Components/core/Menu/types.ts:28`218[1-3 sentence description]219> **Fix**: [concrete suggestion]220```221222### Key rules for output223224- Each finding has exactly one severity, one category, one `file:line` location.225 Use a range (`:42-50`) when it spans lines. The location in the table must226 match the location in the details entry.227- Categories: `Correctness`, `Type Safety`, `Consistency`, `Performance`,228 `Abstraction`, `API Quality`, `Docs Consistency`, `Release`, `Parity`.229- The summary table comes first for scanning; details follow for depth.230- **Zero findings is a valid result** — say so explicitly and recommend approval.231232## Tips233234- Always read the full file, not just the diff hunk.235- Compare against a similar existing component in the **same** library for236 pattern alignment.237- Check the PR doesn't accidentally remove or break existing barrel exports.238- Verify new dependencies land in the correct `package.json` (peer vs dev).