|
| 1 | +--- |
| 2 | +name: code-review |
| 3 | +description: >- |
| 4 | + Senior engineer code review focused on catching issues before they become PR |
| 5 | + comments. Reviews only changed lines, categorizes issues by priority, and fixes |
| 6 | + them one by one. Use when the user says "code review", "review my code", |
| 7 | + "review this branch", or wants pre-PR feedback. |
| 8 | +--- |
| 9 | + |
| 10 | +# Pre-PR Code Review |
| 11 | + |
| 12 | +You are a senior engineer conducting a thorough code review. Review **only the lines that changed** in this branch (via `git diff main...HEAD`) and provide actionable feedback on code quality. Do not flag issues in unchanged code. |
| 13 | + |
| 14 | +## Determine Files to Review |
| 15 | + |
| 16 | +**Before starting the review**, identify which files to review by checking: |
| 17 | + |
| 18 | +1. **Run git commands** to check both: |
| 19 | + - Committed changes: `git diff --name-only main...HEAD` |
| 20 | + - Unstaged/staged changes: `git status --short` |
| 21 | + |
| 22 | +2. **Ask the user which set to review** if both exist: |
| 23 | + - If there are both committed changes AND unstaged/staged changes, ask: "I see you have both committed changes and unstaged/staged changes. Which would you like me to review?" |
| 24 | + - **Option A**: Committed changes in this branch (compare against main) |
| 25 | + - **Option B**: Current unstaged/staged changes |
| 26 | + - **Option C**: Both |
| 27 | + |
| 28 | +3. **Proceed automatically** if only one set exists: |
| 29 | + - If only committed changes exist → review those |
| 30 | + - If only unstaged/staged changes exist → review those |
| 31 | + - If neither exist → inform the user there are no changes to review |
| 32 | + |
| 33 | +4. **Get the file list** based on the user's choice: |
| 34 | + - For committed changes: Use `git diff --name-only main...HEAD` |
| 35 | + - For unstaged/staged: Use `git diff --name-only` and `git diff --cached --name-only` |
| 36 | + - Filter to only include files that exist (some may be deleted) |
| 37 | + |
| 38 | +**Only proceed with the review once you have the specific list of files to review.** |
| 39 | + |
| 40 | +## Review Checklist |
| 41 | + |
| 42 | +### React Best Practices |
| 43 | +- **Components**: Are functional components with hooks used consistently? |
| 44 | +- **State Management**: Is `useState` and `useEffect` used properly? Any unnecessary re-renders? |
| 45 | +- **Props**: Are prop types properly defined with TypeScript interfaces? |
| 46 | +- **Keys**: Are list items using proper unique keys (not array indices)? |
| 47 | +- **Hooks Rules**: Are hooks called at the top level and in the correct order? |
| 48 | +- **Custom Hooks**: Could any logic be extracted into reusable custom hooks? |
| 49 | + |
| 50 | +### TypeScript Best Practices |
| 51 | +- **const vs let vs var**: Is `const` used by default? Is `let` only used when reassignment is needed? Is `var` avoided entirely? |
| 52 | +- **Type Safety**: Are types explicit and avoiding `any`? Are proper interfaces/types defined? |
| 53 | +- **Type Assertions**: Are type assertions (`as`) used sparingly and only when necessary? |
| 54 | +- **Non-null Assertions**: Are non-null assertions (`!`) avoided? They bypass TypeScript's null safety and hide bugs. Use proper null checks or optional chaining instead. |
| 55 | +- **React Ref Types**: Are React refs properly typed as nullable (`useRef<T>(null)` with `RefObject<T | null>`)? Refs are null on first render and during unmount. |
| 56 | +- **Optional Chaining**: Is optional chaining (`?.`) used appropriately for potentially undefined values? |
| 57 | +- **Enums vs Union Types**: Are union types preferred over enums where appropriate? |
| 58 | + |
| 59 | +### Design System & Styling |
| 60 | +- **Component Usage**: Are design system components used instead of raw HTML elements (`<Button>` not `<button>`, `<Input>` not `<input>`)? |
| 61 | +- **No Custom Styling**: Is custom inline styling or CSS avoided in favor of design system utilities? |
| 62 | +- **Tailwind Classes**: Are Tailwind utility classes used properly and consistently? |
| 63 | +- **Tailwind JIT Compilation**: Are Tailwind classes using static strings? JavaScript variables in template literals (e.g., `` `max-w-[${variable}]` ``) break JIT compilation. Use static strings or conditional logic instead (e.g., `condition ? 'max-w-[100px]' : 'max-w-[200px]'`). |
| 64 | +- **Theme Tokens**: Are theme tokens used for colors that adapt to light/dark mode (e.g., `text-foreground`, `bg-card`, `text-muted-foreground`) instead of hardcoded colors (e.g., `text-black`, `bg-white`)? |
| 65 | +- **Variants**: Could any components benefit from additional variants or properties in the design system? |
| 66 | +- **Light and Dark Mode Support**: Are colors working properly in both light and dark modes? No broken colors? |
| 67 | +- **Responsive Layout**: Does the layout work correctly at all breakpoints? No broken layout on mobile, tablet, or desktop? |
| 68 | + |
| 69 | +### Localization (i18n) |
| 70 | +- **New Keys**: When new translation keys are added to one locale (e.g., `en`), are all other supported locales updated too? i18next falls back gracefully, but incomplete locales should be flagged. |
| 71 | +- **Removed Keys**: When UI text is removed, are the corresponding translation keys removed from all locale files? |
| 72 | +- **Raw Strings**: Are user-facing strings wrapped in `t()` calls instead of hardcoded in JSX? Non-translatable symbols (icons, punctuation, HTML entities) are acceptable with an `i18n-check-ignore` annotation. |
| 73 | + |
| 74 | +### Code Simplicity (DRY Principle) |
| 75 | +- **Duplication**: Is there any repeated code that could be extracted into functions or components? |
| 76 | +- **Complexity**: Are there overly complex functions that could be broken down? |
| 77 | +- **Logic**: Is the logic straightforward and easy to follow? |
| 78 | +- **Abstractions**: Are abstractions appropriate (not too early, not too late)? |
| 79 | +- **Guard Clauses**: Are early-return guards used to keep code shallow and readable? |
| 80 | + |
| 81 | +### Code Cleanliness |
| 82 | +- **Comments**: Are there unnecessary comments explaining obvious code? (Remove them) |
| 83 | +- **Console Logs**: Are there leftover `console.log` statements? (Remove them) |
| 84 | +- **Dead Code**: Is there unused code, commented-out code, or unused imports? |
| 85 | +- **Cross-Boundary Dead Data**: Are there struct/interface fields computed on one side of a boundary (e.g., Rust backend) but never consumed on the other (e.g., TypeScript frontend)? This wastes computation and adds noise to data contracts. |
| 86 | +- **Naming**: Are variable and function names clear and descriptive? |
| 87 | +- **Magic Numbers**: Are there magic numbers without explanation? Should they be named constants? |
| 88 | + |
| 89 | +### Animation & UI Polish |
| 90 | +- **Race Conditions**: Are there any animation race conditions or timing issues? |
| 91 | +- **Single Source of Truth**: Is state managed in one place to avoid conflicts? |
| 92 | +- **AnimatePresence**: Is it used properly with unique keys for dialog/modal transitions? |
| 93 | +- **Reduced Motion**: Is `useReducedMotion()` respected for accessibility? |
| 94 | + |
| 95 | +### Async State, Defaults & Persistence |
| 96 | +- **Async Source of Truth**: During async provider/model/session mutations, does UI/session/localStorage state update only after the backend accepts the change? If the UI updates optimistically, is there an explicit rollback path? |
| 97 | +- **UI/Backend Drift**: Could the UI show provider/model/project/persona X while the backend is still on Y after a failed mutation, delayed prepare, or pending-to-real session handoff? |
| 98 | +- **Requested vs Fallback Authority**: Do explicit user or caller selections stay authoritative over sticky defaults, saved preferences, aliases, or fallback resolution? |
| 99 | +- **Dependent State Invalidation**: When a parent selection changes (provider/project/persona/workspace/etc.), are dependent values like `modelId`, `modelName`, defaults, or cached labels cleared or recomputed so stale state does not linger? |
| 100 | +- **Persisted Preference Validation**: Are stored selections validated against current inventory/capabilities before reuse, and do stale values fail soft instead of breaking creation flows? |
| 101 | +- **Compatibility of Fallbacks**: Are default or sticky selections guaranteed to remain compatible with the active concrete provider/backend, instead of leaking across providers? |
| 102 | +- **Best-Effort Lookups**: Do inventory/config/default-resolution lookups degrade gracefully on transient failure, or can they incorrectly block a primary flow that should still work with a safe fallback? |
| 103 | +- **Draft/Home/Handoff Paths**: If the product has draft, Home, pending, or pre-created sessions, did you review those handoff paths separately from the already-active session path? |
| 104 | + |
| 105 | +### General Code Quality |
| 106 | +- **Error Handling**: Are errors handled gracefully with user-friendly messages? |
| 107 | +- **Loading States**: Are loading states shown during async operations? |
| 108 | +- **Accessibility**: Are ARIA labels, keyboard navigation, and screen reader support considered? |
| 109 | +- **Performance**: Are there any obvious performance issues (unnecessary re-renders, heavy computations)? |
| 110 | +- **Git Hygiene**: Are there any files that shouldn't be committed (env files, etc.)? |
| 111 | +- **Unrelated Changes**: Are there any stray files or changes that don't relate to the branch's main purpose? (Accidental commits, unrelated fixes) |
| 112 | + |
| 113 | +## Review & Fix Process |
| 114 | + |
| 115 | +### Step 0: Run Quality Checks |
| 116 | + |
| 117 | +Before reading any code, run the project's CI gate to establish a baseline. Use **check-only** commands so the baseline never mutates the working tree — otherwise auto-formatters can introduce unstaged diffs and you'll end up reviewing formatter output instead of the author's actual changes. |
| 118 | + |
| 119 | +Avoid `just check-everything` as the baseline in this repo: that recipe runs `cargo fmt --all` in write mode and will modify the working tree. Run the non-mutating equivalents instead: |
| 120 | + |
| 121 | +```bash |
| 122 | +cargo fmt --all -- --check |
| 123 | +cargo clippy --all-targets -- -D warnings |
| 124 | +(cd ui/desktop && pnpm run lint:check) |
| 125 | +./scripts/check-openapi-schema.sh |
| 126 | +``` |
| 127 | + |
| 128 | +If the project has a stronger pre-push or CI gate than this helper set, run that fuller gate when the review is meant to be PR-ready, but only after confirming it is also non-mutating (or run it from a clean stash). In this repo, targeted tests for the changed area plus the pre-push checks are often the practical follow-up. |
| 129 | + |
| 130 | +Report the results as pass/fail. Any failures are automatically **P0** issues and should appear at the top of the findings list. Do not skip this step even if the user only wants a quick review. |
| 131 | + |
| 132 | +### Step 1: Conduct Review |
| 133 | + |
| 134 | +For each file in the list: |
| 135 | + |
| 136 | +1. Run `git diff main...HEAD -- <file>` to get the exact lines that changed |
| 137 | +2. Review **only those changed lines** against the Review Checklist — do not flag issues in unchanged code |
| 138 | +3. For stateful UI or async flow changes, trace the full path end to end: user selection -> local/session state update -> persistence -> backend prepare/set/update call -> failure/rollback path |
| 139 | +4. Note the file path and line numbers from the diff output for each issue found |
| 140 | + |
| 141 | +### Step 2: Categorize Issues |
| 142 | + |
| 143 | +Assign each issue a priority level: |
| 144 | +- **P0**: Breaks functionality, TypeScript errors, security issues |
| 145 | +- **P1–P2**: Performance problems, accessibility issues, code quality, unnecessary complexity, poor practices, design system violations |
| 146 | +- **P3**: Style inconsistencies, minor improvements, missing type safety, animation issues, theme token usage |
| 147 | +- **P4**: Cleanup — console logs, unused imports, dead code, unnecessary comments, unrelated changes |
| 148 | + |
| 149 | +If many high-severity issues exist in a file, assess whether a full refactor would be simpler than individual fixes. |
| 150 | + |
| 151 | +### Step 3: Present Findings |
| 152 | + |
| 153 | +After reviewing all files, provide: |
| 154 | +- **Summary**: Total files reviewed, overall quality rating (1-5 stars) |
| 155 | +- **Issues**: A single numbered list ordered by priority (P0 first, P4 last). Each issue must follow this exact format: |
| 156 | + |
| 157 | + ``` |
| 158 | + 1. Short Issue Title (P0) [Must Fix] |
| 159 | + - Description of the issue and why it matters |
| 160 | + - Recommended fix |
| 161 | +
|
| 162 | + 2. Short Issue Title (P3) [Your Call] |
| 163 | + - Description of the issue and why it may or may not need addressing |
| 164 | + - Recommended fix if the user chooses to act on it |
| 165 | + ``` |
| 166 | + |
| 167 | + Use a short, descriptive title (3–6 words max) so issues can be referenced by number (e.g. "fix issue 3"). |
| 168 | + |
| 169 | +### Step 3b: Self-Check |
| 170 | + |
| 171 | +Before presenting findings to the user, silently review the issue list three times: |
| 172 | + |
| 173 | +1. **Pass 1**: For each issue, ask — is this genuinely a problem, or could it be intentional/acceptable? Remove false positives. |
| 174 | +2. **Pass 2**: For each remaining issue, ask — does the recommended fix actually improve the code, or is it a matter of preference? |
| 175 | +3. **Pass 3**: For async state/default-resolution issues, ask — can the UI, persisted state, and backend ever disagree after a failure, fallback, or session handoff? |
| 176 | + |
| 177 | +After these passes, tag each surviving issue as one of: |
| 178 | +- **[Must Fix]** — clear violation, will likely get flagged in PR review |
| 179 | +- **[Your Call]** — valid concern but may be intentional or a reasonable tradeoff (e.g. stepping outside the design system for a specific reason). Present it but let the user decide. |
| 180 | + |
| 181 | +Only present issues that survived these passes. |
| 182 | + |
| 183 | +### Step 4: Fix Issues |
| 184 | + |
| 185 | +**Before fixing**, ask: "Would you like me to fix these issues in order? Or do you have questions about any of them first? I will fix each issue one by one and ask for approval before moving to the next one." |
| 186 | + |
| 187 | +**When approved**, work through issues one at a time in numbered order (P0 → P4). After each fix: |
| 188 | +1. Explain what was changed and why |
| 189 | +2. Ask: "Does that look good? Ready to move on to issue [N]?" |
| 190 | +3. Wait for confirmation before proceeding to the next issue |
| 191 | + |
| 192 | +**Important**: When adding documentation comments: |
| 193 | +- Only add comments for non-obvious things: magic numbers, complex logic, design decisions, or workarounds |
| 194 | +- If you call out something as confusing or hard-coded in your review and suggest adding documentation, it's acceptable to add a comment when approved |
| 195 | +- Don't add comments that just restate what the code does |
| 196 | + |
| 197 | +Explain each change as you make it. If an issue is too subjective or minor, skip it and note why. |
| 198 | + |
| 199 | +**Remember**: Cleanup tasks like removing comments should always be done LAST, because earlier fixes might introduce new comments that also need removal. |
| 200 | + |
| 201 | +### Step 5: Ready to Ship |
| 202 | + |
| 203 | +Once all issues are fixed, display: |
| 204 | + |
| 205 | +--- |
| 206 | + |
| 207 | +**✅ Code review complete! All issues have been addressed.** |
| 208 | + |
| 209 | +Your code is ready to commit and push. Lefthook and CI will run the repo's configured gates when you push. |
| 210 | + |
| 211 | +Next steps: generate a PR summary that explains the intent of this change, what files were modified and why, and how to verify the changes work. |
| 212 | + |
| 213 | +--- |
0 commit comments