|
| 1 | +--- |
| 2 | +name: performance-review |
| 3 | +description: Review frontend code changes for performance anti-patterns and guideline compliance. Checks query hooks, stale times, bundle impact, rendering patterns, and Zustand selectors. |
| 4 | +user_invocable: true |
| 5 | +--- |
| 6 | + |
| 7 | +# Frontend Performance Review |
| 8 | + |
| 9 | +**Reference:** `frontend/docs/performance.md` |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +## When to Invoke |
| 14 | + |
| 15 | +- Before submitting a PR that adds or modifies query hooks, page components, Zustand stores, or real-time features |
| 16 | +- When the user asks for a "performance review" or "perf check" |
| 17 | +- As part of the component-development workflow for new pages |
| 18 | + |
| 19 | +## Agent Instructions |
| 20 | + |
| 21 | +When invoked, perform the following checks in order. Report PASS/FAIL/WARN for each. Group failures by severity: **CRITICAL** (must fix before merge), **WARNING** (should fix), **INFO** (consider). |
| 22 | + |
| 23 | +### Step 1: Identify Scope |
| 24 | + |
| 25 | +Read the diff or the files specified by the user. If no files specified, use `git diff --name-only` to find changed frontend files. Identify which categories apply: query hooks, page routes, stores, real-time, bundle. |
| 26 | + |
| 27 | +### Step 2: Query Hook Checks |
| 28 | + |
| 29 | +1. Search for `useState` + `useEffect` + `api.` within 20 lines of each other in changed files. If found: **CRITICAL** — should be a TanStack Query hook. |
| 30 | +2. Check that new `useQuery` calls reference a key from `queryKeys.ts`, not an inline array. If inline: **CRITICAL**. |
| 31 | +3. Check that new query hook files are named `use<Domain>Queries.ts` and placed in `src/hooks/queries/`. If misplaced: **WARNING**. |
| 32 | +4. Check that `useMutation` calls include `onSuccess` with `queryClient.invalidateQueries()`. If missing: **WARNING**. |
| 33 | +5. Check for `skipToken` usage on conditional queries vs. `enabled: false`. Flag `enabled: false` without `skipToken` as **WARNING**. |
| 34 | + |
| 35 | +### Step 3: Stale Time Audit |
| 36 | + |
| 37 | +1. For each new `useQuery`, check if `staleTime` is set explicitly or inherits the 30s default appropriately. |
| 38 | +2. Cross-reference the data type: if the query fetches components, templates, or providers — flag missing `staleTime: Infinity` as **CRITICAL**. |
| 39 | +3. For execution queries, verify they use `executionQueryOptions.ts` factories rather than inline values. Flag inconsistency as **WARNING**. |
| 40 | +4. For queries on terminal runs, verify `terminalStaleTime()` is used rather than a hardcoded number. |
| 41 | + |
| 42 | +### Step 4: Bundle Impact |
| 43 | + |
| 44 | +1. For each new page added to `App.tsx`: verify it uses `React.lazy(() => import(...))`. Static imports are **CRITICAL**. |
| 45 | +2. Verify new sidebar pages are added to `routePrefetchMap` in `src/lib/prefetch-routes.ts`. Missing entry is **WARNING**. |
| 46 | +3. If a new conditionally-visible component imports a library > 100KB (check for `@xterm`, `posthog-js`, `lucide-react` barrel imports): flag as **WARNING** — consider deferred load pattern. |
| 47 | + |
| 48 | +### Step 5: Rendering Checks |
| 49 | + |
| 50 | +1. Search for `const [*, set*] = useState` followed by `set*` inside a `useEffect` that references query data — **CRITICAL** (should use `useMemo`). |
| 51 | +2. Look for derived data calculations inline in JSX without `useMemo` involving array operations (filter, sort, reduce) — **WARNING**. |
| 52 | +3. Check for `React.memo` usage on new components in `timeline/` or `workflow/` directories that re-render frequently — **INFO** if missing. |
| 53 | + |
| 54 | +### Step 6: Zustand Store Checks |
| 55 | + |
| 56 | +1. Search for `const store = use<X>Store()` or destructuring from `use<X>Store()` without a selector — full store subscription. **WARNING**. |
| 57 | +2. For new stores using `persist`, verify `partialize` is present. Missing is **WARNING**. |
| 58 | +3. For new `persist` stores, verify action functions are excluded from `partialize`. |
| 59 | + |
| 60 | +### Step 7: Generate Report |
| 61 | + |
| 62 | +Format the output as follows: |
| 63 | + |
| 64 | +``` |
| 65 | +## Performance Review: [description of scope] |
| 66 | +
|
| 67 | +### Critical (must fix before merge) |
| 68 | +- [file:line] Description of issue. See: performance.md § [section] |
| 69 | +
|
| 70 | +### Warnings (should fix) |
| 71 | +- [file:line] Description of issue. See: performance.md § [section] |
| 72 | +
|
| 73 | +### Info (consider) |
| 74 | +- [file:line] Description. See: performance.md § [section] |
| 75 | +
|
| 76 | +### Passed Checks |
| 77 | +- [n] query hooks using TanStack Query correctly |
| 78 | +- [n] page routes using React.lazy |
| 79 | +- [n] Zustand selectors properly scoped |
| 80 | +- staleTime: appropriate tiers applied |
| 81 | +
|
| 82 | +### Summary |
| 83 | +[1-2 sentences on overall performance hygiene of the change] |
| 84 | +``` |
| 85 | + |
| 86 | +## Rules |
| 87 | + |
| 88 | +- This is a **review only** — do NOT make code changes unless the user explicitly asks |
| 89 | +- Always cite the file and line number for each finding |
| 90 | +- Always reference `frontend/docs/performance.md` for the relevant pattern section |
| 91 | +- If no frontend files are in the diff, report "No frontend changes detected" and exit |
0 commit comments