prr-kit 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +260 -235
  3. package/docs/assets/banner.svg +30 -248
  4. package/docs/assets/how-it-works.svg +87 -0
  5. package/package.json +60 -60
  6. package/src/core/agents/prr-master.agent.yaml +18 -7
  7. package/src/core/tasks/clear.md +140 -0
  8. package/src/core/tasks/help.md +15 -13
  9. package/src/core/workflows/clear/workflow.md +6 -0
  10. package/src/core/workflows/help/workflow.md +6 -0
  11. package/src/core/workflows/party-mode/steps/step-01-load-reviewers.md +35 -24
  12. package/src/core/workflows/party-mode/steps/step-02-discussion.md +45 -25
  13. package/src/core/workflows/party-mode/workflow.md +2 -2
  14. package/src/prr/agents/architecture-reviewer.agent.yaml +65 -45
  15. package/src/prr/agents/business-reviewer.agent.yaml +66 -0
  16. package/src/prr/agents/general-reviewer.agent.yaml +64 -48
  17. package/src/prr/agents/performance-reviewer.agent.yaml +65 -45
  18. package/src/prr/agents/security-reviewer.agent.yaml +67 -43
  19. package/src/prr/config-template.yaml +97 -0
  20. package/src/prr/data/stacks/actix.md +55 -0
  21. package/src/prr/data/stacks/alpine.md +47 -0
  22. package/src/prr/data/stacks/android.md +53 -0
  23. package/src/prr/data/stacks/angular.md +96 -0
  24. package/src/prr/data/stacks/ansible.md +55 -0
  25. package/src/prr/data/stacks/apollo.md +54 -0
  26. package/src/prr/data/stacks/astro.md +48 -0
  27. package/src/prr/data/stacks/aws-cdk.md +55 -0
  28. package/src/prr/data/stacks/axum.md +56 -0
  29. package/src/prr/data/stacks/babylonjs.md +55 -0
  30. package/src/prr/data/stacks/bash.md +53 -0
  31. package/src/prr/data/stacks/bevy.md +53 -0
  32. package/src/prr/data/stacks/bootstrap.md +52 -0
  33. package/src/prr/data/stacks/bun.md +55 -0
  34. package/src/prr/data/stacks/cpp.md +57 -0
  35. package/src/prr/data/stacks/csharp.md +95 -0
  36. package/src/prr/data/stacks/css.md +55 -0
  37. package/src/prr/data/stacks/cypress.md +53 -0
  38. package/src/prr/data/stacks/d3.md +53 -0
  39. package/src/prr/data/stacks/deno.md +49 -0
  40. package/src/prr/data/stacks/django.md +92 -0
  41. package/src/prr/data/stacks/docker.md +79 -0
  42. package/src/prr/data/stacks/drizzle.md +54 -0
  43. package/src/prr/data/stacks/dynamodb.md +55 -0
  44. package/src/prr/data/stacks/electron.md +44 -0
  45. package/src/prr/data/stacks/elixir.md +53 -0
  46. package/src/prr/data/stacks/expo.md +53 -0
  47. package/src/prr/data/stacks/expressjs.md +82 -0
  48. package/src/prr/data/stacks/fastapi.md +88 -0
  49. package/src/prr/data/stacks/fastify.md +60 -0
  50. package/src/prr/data/stacks/fiber.md +55 -0
  51. package/src/prr/data/stacks/firebase.md +43 -0
  52. package/src/prr/data/stacks/flask.md +46 -0
  53. package/src/prr/data/stacks/flutter.md +75 -0
  54. package/src/prr/data/stacks/gin.md +57 -0
  55. package/src/prr/data/stacks/github-actions.md +71 -0
  56. package/src/prr/data/stacks/go.md +88 -0
  57. package/src/prr/data/stacks/godot.md +56 -0
  58. package/src/prr/data/stacks/graphql.md +76 -0
  59. package/src/prr/data/stacks/grpc.md +56 -0
  60. package/src/prr/data/stacks/haskell.md +48 -0
  61. package/src/prr/data/stacks/helm.md +54 -0
  62. package/src/prr/data/stacks/hono.md +54 -0
  63. package/src/prr/data/stacks/htmx.md +38 -0
  64. package/src/prr/data/stacks/java.md +87 -0
  65. package/src/prr/data/stacks/jest-vitest.md +87 -0
  66. package/src/prr/data/stacks/jquery.md +50 -0
  67. package/src/prr/data/stacks/junit.md +53 -0
  68. package/src/prr/data/stacks/kotlin.md +89 -0
  69. package/src/prr/data/stacks/kubernetes.md +148 -0
  70. package/src/prr/data/stacks/langchain.md +56 -0
  71. package/src/prr/data/stacks/laravel.md +56 -0
  72. package/src/prr/data/stacks/libgdx.md +46 -0
  73. package/src/prr/data/stacks/lit.md +49 -0
  74. package/src/prr/data/stacks/love2d.md +51 -0
  75. package/src/prr/data/stacks/lua.md +51 -0
  76. package/src/prr/data/stacks/mobx.md +54 -0
  77. package/src/prr/data/stacks/mongodb.md +85 -0
  78. package/src/prr/data/stacks/monogame.md +51 -0
  79. package/src/prr/data/stacks/mysql.md +57 -0
  80. package/src/prr/data/stacks/nestjs.md +95 -0
  81. package/src/prr/data/stacks/nextjs.md +88 -0
  82. package/src/prr/data/stacks/nginx.md +55 -0
  83. package/src/prr/data/stacks/node.md +56 -0
  84. package/src/prr/data/stacks/nuxtjs.md +91 -0
  85. package/src/prr/data/stacks/openai-api.md +54 -0
  86. package/src/prr/data/stacks/opengl.md +54 -0
  87. package/src/prr/data/stacks/phaser.md +54 -0
  88. package/src/prr/data/stacks/phoenix.md +55 -0
  89. package/src/prr/data/stacks/php.md +56 -0
  90. package/src/prr/data/stacks/playwright.md +86 -0
  91. package/src/prr/data/stacks/postgresql.md +60 -0
  92. package/src/prr/data/stacks/prisma.md +81 -0
  93. package/src/prr/data/stacks/pygame.md +52 -0
  94. package/src/prr/data/stacks/pytest.md +53 -0
  95. package/src/prr/data/stacks/python.md +94 -0
  96. package/src/prr/data/stacks/pytorch.md +54 -0
  97. package/src/prr/data/stacks/qwik.md +50 -0
  98. package/src/prr/data/stacks/rails.md +48 -0
  99. package/src/prr/data/stacks/react-native.md +77 -0
  100. package/src/prr/data/stacks/react.md +104 -0
  101. package/src/prr/data/stacks/redis.md +76 -0
  102. package/src/prr/data/stacks/redux.md +107 -0
  103. package/src/prr/data/stacks/remix.md +51 -0
  104. package/src/prr/data/stacks/rust.md +88 -0
  105. package/src/prr/data/stacks/sass.md +51 -0
  106. package/src/prr/data/stacks/scala.md +50 -0
  107. package/src/prr/data/stacks/scikit-learn.md +53 -0
  108. package/src/prr/data/stacks/sequelize.md +54 -0
  109. package/src/prr/data/stacks/socket-io.md +54 -0
  110. package/src/prr/data/stacks/solidity.md +53 -0
  111. package/src/prr/data/stacks/solidjs.md +45 -0
  112. package/src/prr/data/stacks/spring-boot.md +92 -0
  113. package/src/prr/data/stacks/sql.md +85 -0
  114. package/src/prr/data/stacks/sqlite.md +55 -0
  115. package/src/prr/data/stacks/styled-components.md +51 -0
  116. package/src/prr/data/stacks/supabase.md +57 -0
  117. package/src/prr/data/stacks/svelte.md +77 -0
  118. package/src/prr/data/stacks/sveltekit.md +54 -0
  119. package/src/prr/data/stacks/swift.md +61 -0
  120. package/src/prr/data/stacks/tailwindcss.md +10 -0
  121. package/src/prr/data/stacks/tanstack-query.md +48 -0
  122. package/src/prr/data/stacks/tauri.md +52 -0
  123. package/src/prr/data/stacks/terraform.md +53 -0
  124. package/src/prr/data/stacks/three.md +53 -0
  125. package/src/prr/data/stacks/trpc.md +49 -0
  126. package/src/prr/data/stacks/typeorm.md +40 -0
  127. package/src/prr/data/stacks/typescript.md +83 -0
  128. package/src/prr/data/stacks/unity.md +61 -0
  129. package/src/prr/data/stacks/unreal.md +58 -0
  130. package/src/prr/data/stacks/vite.md +48 -0
  131. package/src/prr/data/stacks/vue3.md +95 -0
  132. package/src/prr/data/stacks/vulkan.md +53 -0
  133. package/src/prr/data/stacks/wasm.md +49 -0
  134. package/src/prr/data/stacks/webpack.md +48 -0
  135. package/src/prr/data/stacks/zig.md +51 -0
  136. package/src/prr/data/stacks/zustand.md +56 -0
  137. package/src/prr/workflows/1-discover/select-pr/steps/step-05-confirm.md +1 -0
  138. package/src/prr/workflows/1-discover/select-pr/workflow.md +1 -1
  139. package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-01-analyze-files.md +334 -0
  140. package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-02-collect-sources.md +451 -0
  141. package/src/prr/workflows/2-analyze/collect-pr-context/steps/step-03-build-knowledge-base.md +337 -0
  142. package/src/prr/workflows/2-analyze/collect-pr-context/workflow.md +123 -0
  143. package/src/prr/workflows/2-analyze/describe-pr/steps/step-02-classify.md +12 -6
  144. package/src/prr/workflows/2-analyze/describe-pr/steps/step-03-walkthrough.md +59 -1
  145. package/src/prr/workflows/3-review/architecture-review/checklist.md +4 -0
  146. package/src/prr/workflows/3-review/architecture-review/instructions.xml +32 -4
  147. package/src/prr/workflows/3-review/architecture-review/workflow.yaml +17 -18
  148. package/src/prr/workflows/3-review/business-review/checklist.md +27 -0
  149. package/src/prr/workflows/3-review/business-review/instructions.xml +153 -0
  150. package/src/prr/workflows/3-review/business-review/workflow.yaml +17 -0
  151. package/src/prr/workflows/3-review/general-review/checklist.md +5 -1
  152. package/src/prr/workflows/3-review/general-review/instructions.xml +39 -8
  153. package/src/prr/workflows/3-review/general-review/workflow.yaml +17 -18
  154. package/src/prr/workflows/3-review/performance-review/checklist.md +3 -1
  155. package/src/prr/workflows/3-review/performance-review/instructions.xml +10 -3
  156. package/src/prr/workflows/3-review/performance-review/workflow.yaml +17 -18
  157. package/src/prr/workflows/3-review/security-review/checklist.md +2 -1
  158. package/src/prr/workflows/3-review/security-review/instructions.xml +8 -3
  159. package/src/prr/workflows/3-review/security-review/workflow.yaml +18 -19
  160. package/src/prr/workflows/4-improve/improve-code/workflow.yaml +17 -18
  161. package/src/prr/workflows/6-report/generate-report/steps/step-01-collect.md +9 -2
  162. package/src/prr/workflows/6-report/generate-report/steps/step-02-organize.md +28 -7
  163. package/src/prr/workflows/6-report/generate-report/steps/step-03-write.md +6 -4
  164. package/src/prr/workflows/6-report/generate-report/templates/review-report.template.md +124 -78
  165. package/src/prr/workflows/6-report/post-comments/steps/step-01-format.md +104 -13
  166. package/src/prr/workflows/6-report/post-comments/steps/step-02-post.md +92 -21
  167. package/src/prr/workflows/6-report/post-comments/workflow.md +6 -0
  168. package/src/prr/workflows/quick/workflow.md +138 -32
  169. package/src/prr/workflows/0-setup/collect-project-context/steps/step-01-scan-configs.md +0 -106
  170. package/src/prr/workflows/0-setup/collect-project-context/steps/step-02-extract-rules.md +0 -131
  171. package/src/prr/workflows/0-setup/collect-project-context/steps/step-03-ask-context.md +0 -194
  172. package/src/prr/workflows/0-setup/collect-project-context/steps/step-04-save-context.md +0 -161
  173. package/src/prr/workflows/0-setup/collect-project-context/workflow.md +0 -58
@@ -0,0 +1,104 @@
1
+ # React — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.jsx` / `*.tsx` files, `from 'react'`, `useState`, `useEffect`, JSX syntax, `react` in package.json deps, `createRoot`, `use client`, `use server`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** `dangerouslySetInnerHTML` with user-controlled content → XSS. Use text content or DOMPurify if HTML rendering truly needed.
11
+ - **[CRITICAL]** `eval()` or `new Function()` called with user input inside component → remote code execution.
12
+ - **[CRITICAL]** Server Actions (`'use server'`) not validating/authenticating caller → any client can invoke with arbitrary data.
13
+ - **[HIGH]** `href` set to user-provided URL without protocol validation → `javascript:` XSS. Validate with allowlist `['http','https']`.
14
+ - **[HIGH]** Storing auth tokens in `localStorage` / `sessionStorage` → accessible to any script on page. Use httpOnly cookies.
15
+ - **[HIGH]** Third-party script loaded via `dangerouslySetInnerHTML` script tag → XSS vector outside React's tree.
16
+ - **[HIGH]** `window.location.href = userInput` without validation → open redirect / XSS.
17
+ - **[HIGH]** React Server Components fetching data with credentials from user-controlled params → IDOR.
18
+ - **[MEDIUM]** Sensitive data in component state logged via `console.log` in dev → often shipped to production.
19
+ - **[MEDIUM]** Missing sanitization on user input before storing in state that feeds rendered content.
20
+ - **[MEDIUM]** `dangerouslySetInnerHTML` used for markdown rendering without a safe library (use `remark`/`rehype` with proper plugins).
21
+ - **[MEDIUM]** User-controlled CSS via `style` prop with `content` property → CSS injection.
22
+ - **[LOW]** React DevTools exposing component state with sensitive fields in development builds shipped to staging.
23
+
24
+ ---
25
+
26
+ ## Performance
27
+
28
+ - **[CRITICAL]** `useEffect` with no dependency array AND side effects that trigger state → infinite re-render loop.
29
+ - **[HIGH]** `useEffect` with object/array literal in deps (`deps: [{}]`, `deps: [[]]`) → new reference every render → infinite loop.
30
+ - **[HIGH]** Missing `React.memo` on expensive pure child components receiving stable props → re-renders on every parent render.
31
+ - **[HIGH]** Context provider with large value object created inline (`value={{ a, b, c }}`) → new reference every render → all consumers re-render. Split context or memoize value.
32
+ - **[HIGH]** Event listener / timer / subscription / WebSocket not cleaned up in `useEffect` return → memory leak.
33
+ - **[HIGH]** Large lists rendered without virtualization (react-window, TanStack Virtual) → DOM overload at 200+ items.
34
+ - **[HIGH]** `useMemo`/`useCallback` dependencies including unstable references → memoization always invalidated, overhead with no benefit.
35
+ - **[HIGH]** Server Components importing heavy client libraries unnecessarily → increases server bundle.
36
+ - **[HIGH]** Missing `Suspense` boundaries → whole tree waits for slowest data fetch; waterfall instead of parallel.
37
+ - **[MEDIUM]** Missing `useMemo` for expensive calculations (sort, filter, transform on large arrays) run every render.
38
+ - **[MEDIUM]** Missing `useCallback` for handlers passed as props to memoized children → `React.memo` ineffective.
39
+ - **[MEDIUM]** `React.lazy` not used for heavy route components → single large initial bundle.
40
+ - **[MEDIUM]** Context split not done — single context with frequently-changing + rarely-changing data → all consumers re-render on any change.
41
+ - **[MEDIUM]** `useTransition` not used for expensive state updates → UI blocked during transition.
42
+ - **[MEDIUM]** Images not using `loading="lazy"` / `next/image` equivalent → blocking initial render.
43
+ - **[LOW]** `key` changed unnecessarily on stable list items → forced remount instead of update.
44
+ - **[LOW]** `React.StrictMode` disabled in dev to hide bugs → keep it on, fix double-invoke issues instead.
45
+ - **[LOW]** `startTransition` wrapping urgent updates → deprioritizes UI that should be immediate.
46
+
47
+ ---
48
+
49
+ ## Architecture
50
+
51
+ - **[HIGH]** Data fetching directly in component body → side effects in render → bugs and double fetching in StrictMode.
52
+ - **[HIGH]** Custom hooks not prefixed with `use` → ESLint rules-of-hooks cannot protect them.
53
+ - **[HIGH]** Directly mutating state: `state.items.push(x)` → UI out of sync, React does not detect change.
54
+ - **[HIGH]** Prop drilling >3 levels for shared state → lift to Context or state manager.
55
+ - **[HIGH]** Business logic mixed into JSX event handlers inline → untestable, bloated render.
56
+ - **[HIGH]** `'use client'` on root layout/page → entire subtree opts out of RSC; be precise about boundaries.
57
+ - **[HIGH]** Server Component importing client-only libraries (browser APIs) → build error or runtime crash.
58
+ - **[HIGH]** Mixing `useState` for server-fetched data with local UI state → use TanStack Query / SWR for server state.
59
+ - **[MEDIUM]** Multiple `useState` for closely related state → prefer `useReducer` for complex state transitions.
60
+ - **[MEDIUM]** Component doing too many things (fetch + transform + render) → split container/presentational.
61
+ - **[MEDIUM]** `useEffect` used for state derived from other state → compute inline or `useMemo`.
62
+ - **[MEDIUM]** Context used for high-frequency updates (mouse position, scroll) → kills performance; use Zustand/Jotai.
63
+ - **[MEDIUM]** Colocation not followed — component, hook, and test in separate far-away directories → hard to maintain.
64
+ - **[MEDIUM]** `forwardRef` not used when parent needs DOM ref access to child → workaround via prop is anti-pattern.
65
+ - **[LOW]** Global mutable variables (module-scope `let`) shared across component instances → state not isolated per mount.
66
+ - **[LOW]** HOC pattern used where custom hook would be cleaner (React 16.8+).
67
+
68
+ ---
69
+
70
+ ## Code Quality
71
+
72
+ - **[HIGH]** Missing `key` prop in list renders → broken reconciliation, wrong element reuse.
73
+ - **[HIGH]** Array index as `key` in lists that reorder/delete → state/animation bugs.
74
+ - **[HIGH]** `async` function passed directly to `useEffect` (`useEffect(async () => {...})`) → returns Promise not cleanup function. Use inner IIFE.
75
+ - **[HIGH]** Stale closure in `useEffect` — reading state/props captured at creation time. Use functional state updates or `useRef` for latest value.
76
+ - **[HIGH]** Missing `eslint-plugin-react-hooks` → violations not caught.
77
+ - **[MEDIUM]** PropTypes not defined (non-TS projects) → no runtime prop validation.
78
+ - **[MEDIUM]** `useImperativeHandle` overused → exposing too many internals via refs breaks encapsulation.
79
+ - **[MEDIUM]** Component returning `null` for loading state instead of `<Suspense>` → no concurrent rendering benefit.
80
+ - **[MEDIUM]** Boolean prop without value: `<Comp flag />` for false intent → always explicit `flag={true}`.
81
+ - **[MEDIUM]** Ternary with JSX getting too deep (3+ levels) → extract to named variable or component.
82
+ - **[LOW]** `displayName` missing on `forwardRef`/HOC → poor DevTools debugging.
83
+ - **[LOW]** Default export for components → harder to refactor/rename; prefer named exports.
84
+ - **[LOW]** Fragment shorthand `<>` vs `<Fragment key={...}>` confusion when key needed.
85
+
86
+ ---
87
+
88
+ ## Common Bugs & Pitfalls
89
+
90
+ - **[CRITICAL]** `useEffect` dependency array missing variables used inside → stale data silently, linter off → add `react-hooks/exhaustive-deps`.
91
+ - **[HIGH]** `setState` called after component unmounts → memory leak warning (pre-React 18) / noop (React 18+) but indicates cleanup missing.
92
+ - **[HIGH]** `useEffect` cleanup function not returning properly → double subscription on StrictMode double-invoke.
93
+ - **[HIGH]** Reading stale ref value inside `useEffect` → ref value at capture time, not current.
94
+ - **[HIGH]** `useLayoutEffect` on server → SSR warning; wrap with check or replace with `useEffect`.
95
+ - **[HIGH]** `React.use(promise)` called conditionally → violates rules of hooks (React 19).
96
+ - **[HIGH]** Optimistic update not rolled back on error → UI shows wrong state permanently.
97
+ - **[MEDIUM]** Double-rendering in StrictMode (dev only) breaks non-idempotent effects → effects must be idempotent.
98
+ - **[MEDIUM]** `useContext` in component that does not need full context → re-renders on any context change; split context.
99
+ - **[MEDIUM]** `key` reset trick used for component reset → intentional but must be documented.
100
+ - **[MEDIUM]** `startTransition` callback not synchronous → async inside startTransition does not work.
101
+ - **[MEDIUM]** Server Action called inside `useEffect` → should use event handlers or form actions.
102
+ - **[MEDIUM]** `useOptimistic` update not matching final server response shape → causes flash.
103
+ - **[LOW]** Missing `displayName` on memoized components → `React.memo(Component)` shows as "memo" in DevTools.
104
+ - **[LOW]** `children` prop type not using `React.ReactNode` in TypeScript → too narrow or too broad.
@@ -0,0 +1,76 @@
1
+ # Redis — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `ioredis` / `redis` in deps · `createClient()` · `HSET` / `GET` / `SET` · `redis://` connection strings · `RedisTemplate` (Spring) · `EXPIRE` · `SCAN`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** Redis bound to `0.0.0.0` without `requirepass` or firewall → anyone on network reads/writes/deletes all data and runs `CONFIG SET`.
11
+ - **[CRITICAL]** `EVAL` with user-controlled Lua script content → arbitrary code execution on Redis server.
12
+ - **[HIGH]** Sensitive data (session tokens, PII, payment info) stored without encryption → plaintext in memory, RDB snapshots, AOF logs.
13
+ - **[HIGH]** Redis connection without TLS (`rediss://`) on non-loopback → data in transit unencrypted.
14
+ - **[HIGH]** Default `nopass` ACL user in production → any client with network access has full access.
15
+ - **[HIGH]** `CONFIG SET` / `DEBUG` commands not disabled → attacker can reconfigure Redis, write to disk.
16
+ - **[MEDIUM]** Overly permissive ACLs → use Redis ACLs to restrict commands per application role.
17
+ - **[MEDIUM]** Redis used as session store without secure session ID generation → session fixation.
18
+ - **[LOW]** Redis admin port accessible from application servers that don't need admin access.
19
+
20
+ ---
21
+
22
+ ## Performance
23
+
24
+ - **[CRITICAL]** `KEYS pattern` in production → O(n) over all keys, blocks single-threaded server. Use `SCAN` with cursor.
25
+ - **[HIGH]** No TTL on cache/session keys → unbounded memory growth, hot data evicted by `maxmemory` policy.
26
+ - **[HIGH]** Sequential commands where pipelining / `MULTI/EXEC` works → N round-trips instead of 1.
27
+ - **[HIGH]** New connection per request → connection overhead. Use connection pool (`maxRetriesPerRequest`, `enableOfflineQueue`).
28
+ - **[HIGH]** Storing large JSON blobs as string → entire object deserialized for partial read. Use `HSET` for field access.
29
+ - **[MEDIUM]** `HGETALL` on very large hashes → loads entire hash. Use `HSCAN` or separate keys.
30
+ - **[MEDIUM]** `LRANGE 0 -1` on large list → full list loaded into memory.
31
+ - **[MEDIUM]** Not using Redis Cluster for large datasets → single node bottleneck.
32
+ - **[MEDIUM]** `SUBSCRIBE` / `PSUBSCRIBE` on same connection handling requests → blocking subscriber connection.
33
+ - **[LOW]** `DEL` on many keys in loop → use `UNLINK` (async) for large deletes.
34
+ - **[LOW]** Not using `OBJECT ENCODING` to verify compact encoding used for small hashes/sets.
35
+
36
+ ---
37
+
38
+ ## Architecture
39
+
40
+ - **[HIGH]** Redis as primary durable database without proper persistence config → data loss on crash. Use PostgreSQL for source of truth.
41
+ - **[HIGH]** Check-then-set race condition without `WATCH` + `MULTI/EXEC` or Lua → lost update under concurrency.
42
+ - **[HIGH]** Cache invalidation not implemented → stale data served indefinitely after DB update.
43
+ - **[HIGH]** Pub/Sub used for guaranteed message delivery → Redis Pub/Sub is fire-and-forget. Use Redis Streams or a proper message queue.
44
+ - **[MEDIUM]** No namespace/key prefix → collisions between services sharing Redis instance. Use `service:entity:id` pattern.
45
+ - **[MEDIUM]** TTL not refreshed on cache hit (sliding expiration) when needed → cache expires despite active use.
46
+ - **[MEDIUM]** Redis Cluster not configured for multi-key operations → `MGET`/`MSET` across slots fails.
47
+ - **[MEDIUM]** Not using Redis Streams for event sourcing/audit log → losing ordered event history.
48
+ - **[LOW]** Using `SORT` on large sets without LIMIT → expensive full sort.
49
+ - **[LOW]** Not using `OBJECT FREQ` with `allkeys-lfu` eviction for smart caching.
50
+
51
+ ---
52
+
53
+ ## Code Quality
54
+
55
+ - **[HIGH]** Error handling missing on Redis commands → connection failure crashes entire request.
56
+ - **[HIGH]** `SET key value` then `EXPIRE key n` → not atomic; crash between commands = no TTL. Use `SET key value EX n`.
57
+ - **[MEDIUM]** `nil` return from `GET` treated as empty string → key doesn't exist vs empty string confusion.
58
+ - **[MEDIUM]** Hardcoded key strings scattered across codebase → create key builder functions.
59
+ - **[MEDIUM]** Not using `MULTI/EXEC` transaction for related operations → partial state on failure.
60
+ - **[LOW]** `DEL` return value not checked → 0 means key didn't exist, may indicate logic error.
61
+ - **[LOW]** Not using `DEBUG OBJECT` / `MEMORY USAGE` for memory profiling large keys.
62
+
63
+ ---
64
+
65
+ ## Common Bugs & Pitfalls
66
+
67
+ - **[HIGH]** `nil` from `GET` used without null check → NullPointerException / undefined behavior.
68
+ - **[HIGH]** `INCR` on non-existent key → creates with 0 and increments to 1 (by design, but surprising).
69
+ - **[HIGH]** `EXPIRE` with negative TTL → immediately deletes key. Validate TTL before calling.
70
+ - **[HIGH]** Lua script error mid-execution → Lua is atomic but partial state changes before error persist.
71
+ - **[MEDIUM]** `WATCH` not retried on `MULTI/EXEC` nil response → optimistic lock failed, operation silently skipped.
72
+ - **[MEDIUM]** Connection lost mid-pipeline → partial commands sent, partial responses received → state corruption.
73
+ - **[MEDIUM]** `EXPIRE` called on non-existent key → returns 0 (no error), silently fails.
74
+ - **[MEDIUM]** Key type mismatch (`LPUSH` on string key) → `WRONGTYPE` error at runtime.
75
+ - **[LOW]** `KEYS *` used in development → habits carry to production.
76
+ - **[LOW]** Not monitoring `redis-cli --latency` → latency spikes from blocking operations undetected.
@@ -0,0 +1,107 @@
1
+ # Redux Stack Rules
2
+
3
+ ## Detection Signals
4
+ `redux` or `@reduxjs/toolkit` in deps · `createSlice` · `configureStore` · `useSelector` · `useDispatch` · `createAsyncThunk` · `createSelector` · RTK Query
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ **[HIGH]** Sensitive data (auth tokens, PII, payment info) stored in Redux store → Redux DevTools extension serializes and exposes entire store to anyone with browser devtools. Store tokens in HttpOnly cookies or memory-only variables outside Redux.
11
+
12
+ **[HIGH]** Redux Persist writing sensitive store slices to localStorage → plaintext in browser storage, readable by any XSS payload on the same origin. Exclude sensitive slices from persistence using a blacklist, or encrypt with redux-persist-transform-encrypt.
13
+
14
+ **[MEDIUM]** Redux DevTools enabled in production build → exposes full action history and state snapshots to any user with browser devtools installed. Disable DevTools in production via the devTools flag in configureStore.
15
+
16
+ **[MEDIUM]** Action payloads logged to console or external logger without sanitization → tokens or PII visible to log aggregators and third-party logging services. Sanitize sensitive fields before logging actions.
17
+
18
+ **[LOW]** Third-party Redux middleware with unknown provenance included in store → middleware has full access to all actions and state, including sensitive data. Audit middleware source code and pin dependency versions.
19
+ ---
20
+
21
+ ## Performance
22
+
23
+ **[CRITICAL]** Selector not memoized with `createSelector` (Reselect) → selector recomputes on every render whenever any part of store state changes, even unrelated slices. Memoize all derived or filtered data with createSelector.
24
+
25
+ **[HIGH]** `useSelector` selecting entire slice: `useSelector(state => state.users)` → component re-renders on any change to any field in the slice, even fields it does not use. Select the minimal required value or field.
26
+
27
+ **[HIGH]** `dispatch` called inside `useEffect` without correct dependency array → infinite dispatch loop or missing updates when dependencies are stale. Audit effect dependency arrays and add exhaustive-deps lint rule.
28
+
29
+ **[HIGH]** Multiple sequential dispatches for related state changes → each dispatch triggers a full render cycle, so N dispatches cause N renders. Batch related updates with a single combined action or the RTK batch() helper.
30
+
31
+ **[HIGH]** Not using RTK Query for server-side data fetching → manually reimplementing caching, deduplication, invalidation, and loading states in every feature. Adopt RTK Query for all API interactions.
32
+
33
+ **[MEDIUM]** Storing derived or computed data in Redux (filtered lists, formatted values) → sync issues when source data changes and redundant state to keep consistent. Compute with memoized selectors instead of storing computed results.
34
+
35
+ **[MEDIUM]** `createSelector` input selector returning a new object or array on every call → memoization cache always misses, selector recomputes on every render. Return primitive values or stable references from input selectors.
36
+
37
+ **[MEDIUM]** `useSelector` called in parent component and result passed as prop to children → parent re-renders on any state change even if children do not use the changed data. Move `useSelector` calls into the child components that actually use the data.
38
+
39
+ **[MEDIUM]** Not normalizing relational data with `createEntityAdapter` → duplicate data across list and detail views leads to inconsistent updates and O(n) lookups by id. Use EntityAdapter for all list-type state.
40
+
41
+ **[LOW]** Overly normalized state requiring many selector joins to render a single view → excessive computation on every render in read-heavy components. Denormalize read-heavy slices using createEntityAdapter selectors or derived selectors.
42
+ ---
43
+
44
+ ## Architecture
45
+
46
+ **[CRITICAL]** Direct state mutation in reducer outside RTK/Immer context → Redux requires immutability for change detection; mutations cause missed re-renders and stale UI. Use spread operators or RTK with Immer which handles immutability automatically.
47
+
48
+ **[HIGH]** Non-serializable values in Redux state (functions, class instances, Map, Set, Promise, Date objects) → Redux DevTools breaks, persistence fails, and RTK middleware emits serialization warnings. Use plain serializable values only.
49
+
50
+ **[HIGH]** All application state stored in Redux including form state, modal open/closed, and local UI toggles → unnecessary complexity and boilerplate for ephemeral state. Use local useState for UI-only state that no other component needs.
51
+
52
+ **[HIGH]** Redux Thunk used for all async operations instead of RTK Query → verbose code with no built-in caching, deduplication, or invalidation; every feature reimplements the same patterns. Use RTK Query for server data and Thunk only for complex multi-step async logic.
53
+
54
+ **[HIGH]** Selectors defined inline inside component functions instead of in slice files → not reusable across components, not memoizable with createSelector, not independently testable. Define all selectors in the slice file using createSelector.
55
+
56
+ **[MEDIUM]** `createAsyncThunk` result not handled with `.unwrap()` in the calling component → errors from rejected thunks are silently swallowed at the call site. Use dispatch(thunk()).unwrap() and catch the promise to surface errors.
57
+
58
+ **[MEDIUM]** Missing loading, error, and success state tracking for async operations → UI cannot show loading spinners or error messages, user has no feedback on async progress. Handle all three lifecycle states (pending, fulfilled, rejected) in extraReducers.
59
+
60
+ **[MEDIUM]** Action type strings not namespaced (SET_USER instead of users/setUser) → collision risk in large applications with many slices. RTK slices auto-namespace actions; migrate hand-written action types to createSlice.
61
+
62
+ **[MEDIUM]** Store shape not typed with RootState and AppDispatch exports → useSelector returns any type, typed dispatch not enforced, runtime type errors in reducers. Export RootState type from store and use TypedUseSelectorHook in a typed hooks file.
63
+
64
+ **[LOW]** Large switch statement reducers not migrated to `createSlice` → verbose, error-prone string action types, and manual immutable update logic. Migrate to RTK createSlice for automatic action creators and Immer-powered reducers.
65
+ ---
66
+
67
+ ## Code Quality
68
+
69
+ **[HIGH]** `extraReducers` missing pending and rejected cases for async thunks → no loading or error state tracked in the slice, UI cannot reflect async progress. Handle all three lifecycle states for every createAsyncThunk.
70
+
71
+ **[HIGH]** Large switch statement reducer instead of `createSlice` → verbose action type strings, error-prone manual immutability, no automatic action creators. Migrate to RTK createSlice.
72
+
73
+ **[HIGH]** Accessing `action.payload` without type guard in manually typed reducers → runtime error if payload shape differs from expectation. Use RTK createSlice with typed PayloadAction or add explicit type guards.
74
+
75
+ **[MEDIUM]** Slice actions exported incorrectly or forgotten from the slice file → action creator not available in components, dispatch(undefined) silently fails or throws. Always export actions from slice.actions and verify imports.
76
+
77
+ **[MEDIUM]** `combineReducers` not typed → implicit any on slice reducers, no autocomplete for state shape. Use TypedUseSelectorHook with explicit RootState type.
78
+
79
+ **[MEDIUM]** Not using `createEntityAdapter` for list-type state → manual CRUD operations on arrays are verbose, error-prone, and hard to keep normalized. Use EntityAdapter for all collections with id-keyed access.
80
+
81
+ **[MEDIUM]** RTK Query endpoint tags not defined on query endpoints → cache is never invalidated after mutations, stale data shown indefinitely after writes. Define providesTags on queries and invalidatesTags on mutations.
82
+
83
+ **[MEDIUM]** RTK Query not using providesTags and invalidatesTags for cache management → manual refetch needed after every mutation; users see outdated data. Define tag relationships to enable automatic cache invalidation.
84
+
85
+ **[LOW]** initialState with undefined values instead of explicit null → undefined vs null causes subtle comparison bugs in reducers and selectors. Use explicit null for absent optional values in initialState.
86
+
87
+ **[LOW]** Store configured with middleware array spread accidentally removed → default middleware (thunk, DevTools, serializability check) silently removed when middleware array is not spread correctly. Always spread getDefaultMiddleware() when adding custom middleware.
88
+
89
+ ---
90
+
91
+ ## Common Bugs & Pitfalls
92
+
93
+ **[HIGH]** Immer reducer mixes mutation and new object return: state.items.push(x); return {...state} → Immer error at runtime; you must either mutate the draft or return a new value, never both. Do one or the other, never mix in the same reducer case.
94
+
95
+ **[HIGH]** Action creator called without dispatch: fetchUser(id) instead of dispatch(fetchUser(id)) → action object created but never dispatched, state never updates, no error thrown. Always call dispatch() around every action creator or thunk.
96
+
97
+ **[HIGH]** `useSelector` called outside React component tree (in event handler or module scope) → stale closure value, not reactive to state changes, potential runtime error. Always call useSelector inside a React function component or custom hook.
98
+
99
+ **[HIGH]** RTK Query hook called conditionally (inside if/switch before other hooks) → violates React hook rules, causes runtime error on conditional renders. All hook calls must be at the top level of the component unconditionally.
100
+
101
+ **[MEDIUM]** `createSelector` not given stable input selectors → recomputes every render because input reference changes each call, memoization never hits. Ensure input selectors are stable functions defined outside the component.
102
+
103
+ **[MEDIUM]** RTK Query optimistic update not rolled back on error → UI shows updated state even after server rejects the mutation, permanently out of sync. Implement onQueryStarted with patchResult.undo() in the catch block.
104
+
105
+ **[MEDIUM]** `useDispatch` result incorrectly added to useEffect dependency array → useDispatch returns a stable reference; adding it to deps is harmless but misleading and can cause confusion. Remove dispatch from effect deps arrays.
106
+
107
+ **[LOW]** Redux state shape deeply nested (more than 3 levels) → verbose spread operators required for immutable updates, easy to accidentally mutate. Flatten state shape or use createEntityAdapter to eliminate nesting.
@@ -0,0 +1,51 @@
1
+ # Remix — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `remix.config.*`, `from '@remix-run/react'`, `from '@remix-run/node'`, `loader`, `action` exports, `app/routes/`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** `loader` returning sensitive data without authentication check → any user can access protected resources. Add session validation at the top of every `loader` before touching data.
10
+ - **[CRITICAL]** SQL injection via unvalidated `params` or `request.formData()` values passed directly to queries → database compromise. Validate and sanitize all input with Zod or similar before use in queries.
11
+ - **[CRITICAL]** `dangerouslySetInnerHTML` with user-controlled content → XSS. Replace with safe text rendering; sanitize with DOMPurify if HTML is required.
12
+ - **[HIGH]** Missing CSRF protection on `action` mutations → cross-site request forgery. Use `remix-utils` CSRF helpers or validate `Origin`/`Referer` headers in actions.
13
+ - **[HIGH]** Session data trusted without server-side re-validation → privilege escalation if session is tampered. Re-fetch user role/permissions from DB in loader rather than trusting session fields.
14
+ - **[HIGH]** Environment secrets accessed via `window.ENV` pattern without restricting which vars are exposed → secrets in client bundle. Only inject non-sensitive config to client; keep secrets server-only.
15
+
16
+ ---
17
+
18
+ ## Performance
19
+ - **[HIGH]** `loader` returning large JSON payloads not needed by the UI → slow TTFB and large JS hydration cost. Select only fields consumed by the route component; use projection queries.
20
+ - **[HIGH]** Missing HTTP caching headers (`Cache-Control`) in `loader` responses → every request hits the server. Return `headers` with appropriate `Cache-Control` from loaders for cacheable data.
21
+ - **[HIGH]** N+1 queries in nested route loaders each hitting the DB independently → multiplicative query count. Use `Promise.all` for parallel queries or a DataLoader/batching layer.
22
+ - **[MEDIUM]** Sequential `loader` + `useFetcher` calls creating client-side waterfall → delayed content display. Move secondary data into the route `loader` or use parallel `Promise.all` fetches.
23
+ - **[MEDIUM]** Non-critical data not using `defer()` + `<Await>` → page blocked on slow data before render. Wrap slow, non-essential fetches in `defer()` and render with `<Suspense>`/`<Await>`.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+ - **[HIGH]** Business logic (validation, DB calls, external API) written directly inside `loader`/`action` → untestable, bloated route files. Extract to a service/model layer and call from loaders/actions.
29
+ - **[HIGH]** Client-side `fetch` calls for data that should come through `loader` → bypasses Remix data flow, breaks SSR. Move all initial data fetching into `loader`; use `useFetcher` only for non-navigating updates.
30
+ - **[HIGH]** Missing `ErrorBoundary` export on routes → unhandled loader/action errors bubble to root with no context. Export an `ErrorBoundary` component from every route that fetches data.
31
+ - **[MEDIUM]** Not using Remix nested routing for shared UI (nav, sidebar) → duplicated layout markup across routes. Leverage parent route layouts with `<Outlet>` to share chrome and loaders.
32
+ - **[MEDIUM]** Overusing `clientLoader` when a server `loader` suffices → unnecessary client JS and loss of server caching. Reserve `clientLoader` for browser-only data (localStorage, IndexedDB).
33
+
34
+ ---
35
+
36
+ ## Code Quality
37
+ - **[HIGH]** Missing `LoaderFunctionArgs`/`ActionFunctionArgs` types → untyped `request` and `params`, runtime surprises. Type every `loader` and `action` with the appropriate Remix args type.
38
+ - **[HIGH]** `action` without input schema validation (e.g. Zod) → invalid data silently processed. Parse `formData` through a Zod schema and return field errors on failure.
39
+ - **[MEDIUM]** `useFetcher` not used for non-navigating mutations (e.g. like button) → full navigation triggered on submit. Use `fetcher.Form` or `fetcher.submit` for in-place mutations.
40
+ - **[MEDIUM]** Inline `fetch` inside React component for data available in `loader` → duplicate request, hydration mismatch. Use `useLoaderData()` to consume data already fetched server-side.
41
+ - **[MEDIUM]** Not using `json()` helper for loader responses → missing default `Content-Type` and status code control. Wrap all loader return values with the `json()` helper from `@remix-run/node`.
42
+ - **[LOW]** Route files exceeding 300 lines with mixed concerns → hard to review and maintain. Split into co-located component, loader, action, and service files.
43
+
44
+ ---
45
+
46
+ ## Common Bugs & Pitfalls
47
+ - **[HIGH]** `useLoaderData()` called outside its route module (e.g. in a child component) → returns `undefined` or wrong route's data. Pass data as props or use `useRouteLoaderData(routeId)` for ancestor data.
48
+ - **[HIGH]** Cookies not set with `httpOnly` and `secure` flags → session cookies accessible via JS and sent over HTTP. Always create cookies with `{ httpOnly: true, secure: process.env.NODE_ENV === 'production' }`.
49
+ - **[HIGH]** `defer` data error state not handled inside `<Await>` `errorElement` prop → unhandled promise rejection in UI. Always provide `errorElement` to every `<Await>` wrapping deferred data.
50
+ - **[MEDIUM]** `action` returning a redirect without `303` status code → browser may cache the redirect or re-POST on back. Use `redirect(url, { status: 303 })` after successful mutations.
51
+ - **[MEDIUM]** Using `<form>` (native HTML) instead of Remix `<Form>` → loses progressive enhancement, pending state, and revalidation. Use Remix `<Form>` for all route-level form submissions.
@@ -0,0 +1,88 @@
1
+ # Rust — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.rs` files · `Cargo.toml` · `Cargo.lock` · `fn main()` · `use std::` · `impl` · `cargo` commands · `tokio` · `async fn`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** `unsafe` block without safety comment explaining invariants → makes auditing impossible. Every `unsafe` MUST document WHY it's safe.
11
+ - **[CRITICAL]** `unsafe` used to bypass borrow checker for mutable aliasing → undefined behavior, data races.
12
+ - **[HIGH]** `unwrap()` / `expect()` on user-facing code paths or library public API → panic = DoS for caller. Return `Result<>`.
13
+ - **[HIGH]** Deserializing untrusted input with `serde` without value validation → `#[derive(Deserialize)]` checks structure, not semantics (ranges, lengths).
14
+ - **[HIGH]** `std::fs::read_to_string(user_path)` without path canonicalization → path traversal.
15
+ - **[HIGH]** `Command::new("sh").arg("-c").arg(user_input)` → command injection. Use arg list, never shell string.
16
+ - **[HIGH]** Integer cast `as usize` from signed type without range check → negative wraps to huge `usize` → out-of-bounds.
17
+ - **[MEDIUM]** Sensitive data (secrets, tokens) stored in heap `String` → may not be zeroed on drop. Use `zeroize` crate.
18
+ - **[MEDIUM]** `transmute` between types of different sizes → undefined behavior crash.
19
+ - **[MEDIUM]** `std::process::exit()` used → bypasses `Drop`, skips cleanup and zeroize.
20
+ - **[LOW]** Logging user-provided strings without sanitization → log injection.
21
+
22
+ ---
23
+
24
+ ## Performance
25
+
26
+ - **[HIGH]** `.clone()` where borrow suffices → unnecessary heap allocation. Audit every `.clone()`.
27
+ - **[HIGH]** `String::from()` / `.to_string()` / `.to_owned()` in hot path where `&str` would work → allocates.
28
+ - **[HIGH]** Blocking I/O (`std::fs`, `std::net`, `std::thread::sleep`) inside `async fn` → stalls tokio runtime worker thread. Use `tokio::fs`, `tokio::net`, `tokio::time::sleep`.
29
+ - **[HIGH]** `Arc<Mutex<T>>` with long-held lock across `.await` points → deadlock or starvation under async.
30
+ - **[HIGH]** `.collect::<Vec<_>>()` before iterating once → unnecessary heap allocation. Chain iterators.
31
+ - **[HIGH]** `Box<dyn Trait>` (dynamic dispatch) where generics / `impl Trait` work → vtable + heap overhead.
32
+ - **[MEDIUM]** `Mutex<T>` where `RwLock<T>` fits (many readers, rare writes) → unnecessary read contention.
33
+ - **[MEDIUM]** `HashMap` with default hasher in security-sensitive context → HashDoS. Use `ahash` for performance or `BTreeMap` for determinism.
34
+ - **[MEDIUM]** `format!("{}", x)` in hot path → allocates. Use `write!` to pre-allocated buffer.
35
+ - **[MEDIUM]** `Vec::push` in tight loop without `reserve()` → multiple reallocations.
36
+ - **[MEDIUM]** Not using `#[inline]` on small hot functions called across crate boundaries.
37
+ - **[LOW]** `String::new()` + repeated `push_str` → use `String::with_capacity()`.
38
+ - **[LOW]** Not using `Cow<'a, str>` where sometimes owned, sometimes borrowed.
39
+
40
+ ---
41
+
42
+ ## Architecture
43
+
44
+ - **[HIGH]** `.unwrap()` in library code → caller cannot handle error. Always return `Result<T, E>`.
45
+ - **[HIGH]** `Arc<Mutex<T>>` shared widely across many tasks → lock contention + deadlock risk. Prefer message passing via `tokio::sync::mpsc`.
46
+ - **[HIGH]** Mixing `async` and sync code without `spawn_blocking` for sync I/O → executor starvation.
47
+ - **[HIGH]** Error type is `Box<dyn std::error::Error>` or `String` in library public API → poor ergonomics. Use `thiserror`.
48
+ - **[HIGH]** `panic!` / `unwrap()` in `Drop` → if another panic is unwinding, double-panic aborts.
49
+ - **[MEDIUM]** `async fn` in trait without boxing (pre-stable RPIT in traits) → compile error or `Box<dyn Future>` overhead.
50
+ - **[MEDIUM]** `pub` fields on public struct → breaks encapsulation, prevents future refactoring. Use methods.
51
+ - **[MEDIUM]** Global `static mut` → requires `unsafe` to access, data race in multithreaded code. Use `OnceLock`, `LazyLock`, or `Mutex`.
52
+ - **[MEDIUM]** Not using workspace (`Cargo.toml` `[workspace]`) in multi-crate project → dependency version drift.
53
+ - **[MEDIUM]** Shared mutable state via `RefCell` in multi-threaded context → panics at runtime on borrow violation.
54
+ - **[LOW]** Not using feature flags to gate optional heavy dependencies.
55
+ - **[LOW]** Not using `#[non_exhaustive]` on public enums/structs → breaking changes when adding variants.
56
+
57
+ ---
58
+
59
+ ## Code Quality
60
+
61
+ - **[HIGH]** `#[allow(dead_code)]` / `#[allow(unused_variables)]` without explanation → suppresses meaningful warnings.
62
+ - **[HIGH]** `let _ = some_result` → silently ignores `Result` or `Option`. Use `if let`, `match`, or `?`.
63
+ - **[HIGH]** `unwrap()` / `expect()` in tests without descriptive message → cryptic panic output on failure.
64
+ - **[HIGH]** Not using `?` operator for error propagation → verbose `match` chains.
65
+ - **[MEDIUM]** Missing `#[derive(Debug)]` on public types → `{:?}` doesn't work, poor debuggability.
66
+ - **[MEDIUM]** Not using `clippy` in CI → many best-practice violations undetected.
67
+ - **[MEDIUM]** `match` arm with `_` catch-all prevents exhaustiveness when new variants added.
68
+ - **[MEDIUM]** `impl From<X> for Y` not implemented → `.into()` / `.from()` not usable, manual conversions everywhere.
69
+ - **[MEDIUM]** `pub use` re-exports not organized → messy crate public API.
70
+ - **[LOW]** Not using `rustfmt` → inconsistent formatting.
71
+ - **[LOW]** Long `impl` blocks → consider splitting concerns into multiple traits.
72
+
73
+ ---
74
+
75
+ ## Common Bugs & Pitfalls
76
+
77
+ - **[HIGH]** `Rc<RefCell<T>>` in async code → `Rc` is not `Send`, compile error across `.await`. Use `Arc<Mutex<T>>`.
78
+ - **[HIGH]** Integer overflow: debug builds panic, release builds silently wrap → use `checked_add`/`saturating_add` for user values.
79
+ - **[HIGH]** Lifetime annotation outliving actual data → `'static` bound used when shorter lifetime is correct → dangling reference.
80
+ - **[HIGH]** Futures not polled → `async fn` does nothing until `.await`ed. Spawning required for concurrent execution.
81
+ - **[HIGH]** `tokio::spawn` task panics → panic not propagated to spawner, silently dropped unless `JoinHandle` checked.
82
+ - **[MEDIUM]** `Vec::iter()` vs `Vec::into_iter()` confusion → `iter()` borrows, `into_iter()` consumes.
83
+ - **[MEDIUM]** `HashMap` with `String` keys and `&str` lookup requires `.to_string()` → use `.get("key")` via `Borrow<str>`.
84
+ - **[MEDIUM]** `&str` borrowed from temporary `String` doesn't live long enough → lifetime error.
85
+ - **[MEDIUM]** Shared reference to `Mutex` dropped before lock used → deadlock on reacquire.
86
+ - **[MEDIUM]** `async move` closure capturing `Arc` → clone before move or wrap in `Arc`.
87
+ - **[LOW]** `match` on `String` requires `str::as_str()` → match `&*s` or `s.as_str()`.
88
+ - **[LOW]** Not using `Cow<'_, str>` where conditionally cloning → always-clone is wasteful.
@@ -0,0 +1,51 @@
1
+ # Sass/SCSS — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.scss`, `*.sass`, `from 'sass'`, `$variable`, `@mixin`, `@include`, `@extend`, `@use`, `@forward`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** User-controlled values interpolated into `url()` via `#{}` in Sass → path traversal or injection in the compiled CSS `url()` function. Never interpolate unvalidated user input into `url()` calls; use only static or config-defined paths.
10
+ - **[MEDIUM]** Server-rendered Sass variables populated from user input before compilation → CSS injection allowing layout manipulation or data exfiltration via CSS. Treat Sass compilation as server-side code; never pass user input into the Sass variable pipeline.
11
+ - **[MEDIUM]** Sensitive asset paths exposed in Sass `@import` or `@use` error messages in development → internal directory structure revealed in browser console or build output. Suppress detailed Sass error output in production builds.
12
+ - **[LOW]** `@import` of external Sass files from user-configurable URLs → arbitrary remote Sass executed during build. Restrict `@import`/`@use` to local paths only; validate any configurable paths.
13
+
14
+ ---
15
+
16
+ ## Performance
17
+ - **[HIGH]** Nesting depth exceeding 4 levels → over-specific CSS selectors in output, large stylesheet, and slow browser style recalculation. Limit nesting to 3 levels maximum; use BEM or component-scoped class names to avoid deep nesting.
18
+ - **[HIGH]** `@extend` used with widely-used class selectors (not placeholders) → all matched selectors grouped in the output CSS, causing unintended selector combinations and bloated output. Use `%placeholder` selectors with `@extend`, or prefer `@include` with mixins.
19
+ - **[MEDIUM]** `@import` used instead of `@use`/`@forward` → `@import` causes all variables, mixins, and functions to be re-evaluated and duplicated in every file that imports them. Migrate to `@use`/`@forward` to deduplicate compiled output.
20
+ - **[MEDIUM]** `background-image: url("#{$var}")` in frequently rendered components → prevents CSS-level optimization and HTTP/2 push hints. Use static `url()` values in Sass and inject dynamic values via CSS custom properties at runtime.
21
+ - **[LOW]** `outputStyle: 'compressed'` not enabled in production Sass compilation → unminified CSS increases file size and parse time. Set `style: 'compressed'` in the Sass compiler options for production builds.
22
+ - **[LOW]** Unused Sass variables and mixins not removed → dead code inflates the source, and some Sass configurations may include them in output. Audit and prune unused abstractions.
23
+
24
+ ---
25
+
26
+ ## Architecture
27
+ - **[HIGH]** `@import` used in a modern Sass codebase instead of `@use`/`@forward` → global namespace pollution where all variables/mixins are available everywhere, `@import` is deprecated and will be removed. Replace all `@import` with `@use 'module'` and expose public APIs via `@forward`.
28
+ - **[HIGH]** Design tokens (colors, spacing, typography) defined in multiple files without a single canonical source → values diverge across files causing visual inconsistency. Define all tokens in one `_tokens.scss` or `_variables.scss` partial and `@forward` it from an index.
29
+ - **[MEDIUM]** Presentation mixins mixed with logic helpers (`@if`, `@each`, `@for`) in the same file → hard to locate specific abstractions. Separate utility/logic mixins from visual/component mixins into distinct partials.
30
+ - **[MEDIUM]** Partial files not following the `_partial.scss` underscore naming convention → Sass compiler treats them as standalone entry points and compiles them to individual CSS files. Prefix all partials with `_` to signal they are not standalone entry points.
31
+ - **[LOW]** No clear decision on when to use mixins vs `%placeholders` vs utility classes → inconsistent approach across the codebase. Document and enforce the team's chosen abstraction strategy.
32
+
33
+ ---
34
+
35
+ ## Code Quality
36
+ - **[HIGH]** `!important` used inside mixins or component styles → creates an unresolvable specificity arms race as every override also requires `!important`. Remove `!important` from reusable code; use specificity or cascade order to resolve conflicts.
37
+ - **[MEDIUM]** Magic numbers used inline instead of extracted to named variables → values like `24px`, `1.5`, `#3a86ff` appear without explanation and must be updated in multiple places. Extract all repeated or meaningful values to named Sass variables or CSS custom properties.
38
+ - **[MEDIUM]** Vendor prefix mixins maintained manually instead of using Autoprefixer → manually added prefixes become outdated and no-ops, while newer prefixes are missed. Remove manual vendor prefixes and integrate Autoprefixer as a PostCSS step.
39
+ - **[MEDIUM]** `@extend` used across different partial files → creates brittle coupling where changes to one file's placeholder affect compiled output in unrelated files. Restrict `@extend` to within the same partial; prefer `@include` for cross-file reuse.
40
+ - **[LOW]** `@mixin` defined with required arguments not documented with comments → consumers must read implementation to understand usage. Add JSDoc-style comments above each mixin describing parameters, types, and usage.
41
+
42
+ ---
43
+
44
+ ## Common Bugs & Pitfalls
45
+ - **[HIGH]** `@use 'module'` statement not placed at the top of the file before any other rules → Sass throws a compile error. `@use` and `@forward` must be the first statements in a file, before any CSS rules, variables, or mixins.
46
+ - **[HIGH]** Division using the `/` operator `$value / 2` → Sass treats this as ambiguous CSS division in newer versions and issues a deprecation warning or compiles incorrectly. Replace with `math.div($value, 2)` after `@use 'sass:math'`, or use `calc()` for runtime division.
47
+ - **[MEDIUM]** Local variable inside a mixin or block shadowing a module-level variable of the same name → unexpected value used in nested context with no warning. Use the `!global` flag intentionally when writing to module scope, and prefix local variables distinctly.
48
+ - **[MEDIUM]** `@mixin` with default argument of `null` used without checking before passing to a CSS property → `property: null` outputs `property: ` which is invalid CSS and may cause parse errors. Guard with `@if $param != null { property: $param; }`.
49
+ - **[MEDIUM]** `@each` loop over a map generating utility classes not purged by CSS purge tools → tools like PurgeCSS cannot detect dynamically generated class names. Document generated class patterns or safelist them in the PurgeCSS configuration.
50
+ - **[LOW]** Compiled CSS class order differing from expected source order when using `@extend` → `@extend` groups selectors at the location of the placeholder, not the `@extend` call. Understand that `@extend` changes class order in output; use `@include` when cascade order matters.
51
+ - **[LOW]** `@use` namespace collision when two modules share the same filename → `@use 'utils/colors'` and `@use 'theme/colors'` both default to `colors.variable`. Use `@use 'path' as alias` to avoid namespace conflicts.
@@ -0,0 +1,50 @@
1
+ # Scala — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.scala`, `import scala.`, `object `, `case class`, `trait `, `def `, `implicit`, `Future`, `sbt`, `build.sbt`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** Deserialization with Java's `ObjectInputStream` on untrusted data → arbitrary code execution via gadget chains. Use a type-safe serialization library (Circe, uPickle, Protobuf) and never deserialize from untrusted sources with Java's native mechanism.
10
+ - **[HIGH]** SQL injection via string interpolation in Slick/Doobie raw queries (`sql"SELECT ... $userInput"`) → database compromise. Use typed interpolators (`sql"... ${param}"` with Doobie's parameterized queries) which bind values safely.
11
+ - **[HIGH]** `sys.process` constructed from user-controlled strings → command injection. Use the sequence form (`Seq("cmd", "--flag", userValue).!`) which bypasses shell interpretation.
12
+ - **[MEDIUM]** `Future` failure cases not handled with `recover` or `recoverWith` → unhandled exceptions surface as `Future.failed` silently swallowed by callers. Attach `recover`/`onComplete` at every boundary; log and report failures explicitly.
13
+ - **[MEDIUM]** Akka HTTP or Play exposing internal exception messages in HTTP responses → information disclosure of stack traces and class names. Catch all `Throwable` at route boundaries and return sanitized error DTOs.
14
+
15
+ ---
16
+
17
+ ## Performance
18
+ - **[HIGH]** Blocking operations (`Await.result`, JDBC, blocking IO) inside a `Future` without a dedicated blocking execution context → thread starvation on the default `ExecutionContext`. Wrap blocking calls in `blocking { ... }` or dispatch to a fixed-thread-pool EC.
19
+ - **[HIGH]** `List` used for large collections requiring random access → `List` access is O(n). Use `Vector` (effectively O(log n)) or `ArrayBuffer` for indexed access patterns.
20
+ - **[HIGH]** Chaining `flatMap`/`map` on large in-memory collections → intermediate collection allocated at each step. Use `Iterator`, `LazyList`, or `fs2.Stream` to process elements lazily without intermediates.
21
+ - **[MEDIUM]** Non-exhaustive pattern match inside a `match` expression → `MatchError` thrown at runtime for unhandled cases. Enable `-Wunreachable-code` and `-Wexhaustive` compiler flags; seal all ADT base traits.
22
+ - **[MEDIUM]** Complex implicit resolution chains → compilation slowdowns of 10–100×. Prefer explicit type class summoning (`implicitly[TC[A]]`), use `given`/`using` in Scala 3, and minimize implicit scope pollution.
23
+ - **[LOW]** Deep recursion without tail call optimization → stack overflow on large inputs. Annotate with `@tailrec` to get compile-time verification; convert non-tail recursion to trampolining with `cats.free.Trampoline`.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+ - **[HIGH]** Mutable `var` state in business logic when immutable design is feasible → shared mutable state causes race conditions and reasoning difficulty. Model state transitions explicitly with immutable case classes and `State` monad or `Ref` from Cats Effect.
29
+ - **[HIGH]** Exceptions used for control flow instead of `Either`/`Try`/`Option` → callers unaware a function can fail; exceptions cross `Future` boundaries unpredictably. Return `Either[Error, A]` or `IO[A]` for all fallible operations.
30
+ - **[MEDIUM]** Cake pattern or deeply nested implicit hierarchies instead of explicit dependency injection → difficult to understand, test, and refactor. Use constructor injection with a DI framework (ZIO layers, Koin, or simple manual wiring).
31
+ - **[MEDIUM]** `Future` chains without `.recover` or `.recoverWith` at service boundaries → errors propagate as unhandled `Future.failed` to the API layer. Add recovery at each service boundary to translate domain errors to typed responses.
32
+ - **[LOW]** Not using Cats, Cats Effect, or ZIO for effect management in applications with concurrency → ad hoc `Future` usage becomes hard to reason about. Adopt a consistent effect system and its resource management (`Resource`, `ZIO.acquireRelease`).
33
+
34
+ ---
35
+
36
+ ## Code Quality
37
+ - **[HIGH]** Non-exhaustive pattern match without a wildcard catch-all → `MatchError` in production for unhandled ADT variants. Seal all base traits/classes and enable the `-Wunreachable-code` compiler warning.
38
+ - **[HIGH]** `Option.get` called without an `isDefined` guard → `NoSuchElementException` at runtime. Use `getOrElse`, `fold`, `for`-comprehension, or pattern match; never call `.get` directly.
39
+ - **[MEDIUM]** Implicit conversions causing unexpected type coercions → code behaves differently than it reads. Limit implicit conversions to extension methods; avoid `implicit def` that transforms one type to another silently.
40
+ - **[MEDIUM]** Recursive function not annotated with `@tailrec` when intended to be tail-recursive → JVM does not optimize, causing stack overflow. Add `@tailrec` to get a compile error if the recursion is not in tail position.
41
+ - **[LOW]** `toString` not overridden on domain classes → log output shows unhelpful `MyClass@1a2b3c`. Override `toString` or use `case class` which auto-generates a meaningful representation.
42
+
43
+ ---
44
+
45
+ ## Common Bugs & Pitfalls
46
+ - **[HIGH]** `Future` created without an implicit `ExecutionContext` in scope → compile error, or the wrong global EC used inadvertently. Always import or pass an explicit `ExecutionContext`; use `ExecutionContext.parasitic` for pure transformations.
47
+ - **[HIGH]** `==` used on Java-interop objects → Scala forwards `==` to `equals()` for non-primitives, but Java objects may not override `equals()`, falling back to reference equality. Check Java API docs and use `.equals()` or wrap in a Scala case class.
48
+ - **[MEDIUM]** `for`-comprehension mixing monads of different types (e.g., `Option` and `Future`) → type mismatch compile error with a confusing message. Keep all generator types consistent; use `OptionT[Future, A]` from Cats to combine.
49
+ - **[MEDIUM]** `null` returned from Java interop method used directly in Scala code → `NullPointerException`. Wrap all Java interop results with `Option(javaValue)` immediately at the boundary.
50
+ - **[LOW]** `Unit` return type not explicitly annotated on a method that should return `Unit` → inferred as a more specific type if the last expression is non-unit, masking a logic error. Annotate all side-effecting methods with `: Unit` explicitly.
@@ -0,0 +1,53 @@
1
+ # scikit-learn — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `from sklearn`, `import sklearn`, `sklearn.`, `fit(`, `predict(`, `Pipeline(`, `GridSearchCV`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** `joblib.load()` or `pickle.load()` used to load models from untrusted or user-supplied file paths → arbitrary Python code executed on deserialization. Only load model files from trusted, integrity-verified sources; consider ONNX export for untrusted distribution.
10
+ - **[HIGH]** Production model trained on data containing user PII without anonymization or differential privacy → model can memorize and leak training data. Apply anonymization, aggregation, or differential privacy techniques before training on personal data.
11
+ - **[MEDIUM]** Feature names or column names exposed in model metadata, error messages, or API responses → internal data structure leakage that aids inference attacks. Sanitize error messages and abstract feature names in API-facing layers.
12
+ - **[MEDIUM]** Model prediction endpoint not authenticated or rate limited → API open to abuse, model extraction attacks, or denial-of-service via expensive inference. Apply authentication and rate limiting to all prediction endpoints.
13
+ - **[LOW]** Model artifacts stored in version control with Git LFS not configured → large binary files bloat repository history. Store model artifacts in object storage (S3, GCS) and reference them by hash in version control.
14
+
15
+ ---
16
+
17
+ ## Performance
18
+ - **[HIGH]** Estimators that support parallel execution (RandomForest, GridSearchCV, cross_val_score) called without `n_jobs=-1` → only one CPU core used for embarrassingly parallel work. Set `n_jobs=-1` to use all available cores.
19
+ - **[HIGH]** `GridSearchCV` used with an exhaustive parameter grid over many combinations → combinatorial explosion in search time. Use `RandomizedSearchCV` with `n_iter` budget, or Bayesian optimisation with `optuna`.
20
+ - **[HIGH]** `StandardScaler` or `OneHotEncoder` fitted on the full dataset before train/test split → data leakage: test set statistics influence the scaler, producing optimistically biased evaluation metrics. Split data first; fit transformers only on the training set.
21
+ - **[MEDIUM]** Preprocessing steps applied manually outside a `Pipeline` → transforms applied inconsistently between training and inference. Wrap all preprocessing + estimator steps in `Pipeline` to ensure identical transforms at inference.
22
+ - **[MEDIUM]** Entire dataset loaded into memory as a dense NumPy array → out-of-memory for large datasets. Use sparse matrices for high-cardinality categorical data; use `partial_fit` estimators for incremental learning.
23
+ - **[LOW]** Expensive feature transformations recomputed on every cross-validation fold → slow CV. Use `joblib.Memory` caching with `Pipeline`'s `memory` parameter to cache intermediate transform outputs.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+ - **[CRITICAL]** Preprocessing fitted on the full dataset (train + test) before the train/test split → data leakage causes inflated and unreliable evaluation metrics. Always split data before any fitting, without exception.
29
+ - **[HIGH]** Model evaluated on training data only → accuracy appears near-perfect, masking severe overfitting. Always evaluate on a held-out test set and use cross-validation for hyperparameter selection.
30
+ - **[HIGH]** Preprocessing steps applied outside a `Pipeline` during cross-validation → test fold data leaks into scaler fit during CV, producing misleadingly optimistic CV scores. Encapsulate all steps in `Pipeline` before passing to `cross_val_score` or `GridSearchCV`.
31
+ - **[MEDIUM]** Model not persisted with `joblib.dump()` or `pickle` after training → model retrained from scratch on every application restart. Serialize the fitted pipeline and load it at serving time.
32
+ - **[MEDIUM]** Single train/test split used instead of cross-validation for model selection → evaluation highly sensitive to the random split. Use k-fold cross-validation for more reliable model selection.
33
+ - **[LOW]** Hyperparameters hardcoded in the script → reproducibility and experimentation require editing source files. Define hyperparameters in a config file (YAML, JSON) or pass them via CLI arguments.
34
+
35
+ ---
36
+
37
+ ## Code Quality
38
+ - **[HIGH]** Model metrics computed only on the training set → misleading evaluation reported as model performance. Always report metrics on the test set; include precision, recall, and F1 alongside accuracy.
39
+ - **[HIGH]** Class imbalance not addressed for classification tasks → model biased toward the majority class with high accuracy but poor minority-class recall. Apply `class_weight='balanced'`, oversampling (SMOTE), or undersampling as appropriate.
40
+ - **[MEDIUM]** Feature importance or coefficients not inspected after training → model behaviour opaque and potential data leakage features go undetected. Log `feature_importances_` or `coef_` and review top features before deployment.
41
+ - **[MEDIUM]** `set_output(transform='pandas')` not used when downstream code expects DataFrames → transform output is a NumPy array, losing column names. Call `set_output(transform='pandas')` on the pipeline for DataFrame-compatible output.
42
+ - **[MEDIUM]** Evaluation metric not aligned with the business objective → optimising accuracy for a cost-sensitive problem ignores the cost of false negatives vs false positives. Choose metrics (ROC-AUC, average precision, custom cost function) that reflect real-world consequences.
43
+ - **[LOW]** `random_state` not set on estimators and splitters → results not reproducible across runs. Set `random_state` to a fixed integer on all stochastic components.
44
+
45
+ ---
46
+
47
+ ## Common Bugs & Pitfalls
48
+ - **[CRITICAL]** Scaler, encoder, or imputer fitted on the combined dataset before splitting → optimistic test metrics that overestimate production performance. This is the single most common ML mistake; always fit on train only and transform test separately.
49
+ - **[HIGH]** `predict_proba()` output used as calibrated probabilities without calibration → raw scikit-learn probabilities are often poorly calibrated for SVMs and boosted trees. Apply `CalibratedClassifierCV` when probabilities are used for decision-making.
50
+ - **[MEDIUM]** Categorical features passed to tree-based models as raw strings → most sklearn estimators do not accept string features. Apply `OrdinalEncoder` or `OneHotEncoder` before fitting; use `ColumnTransformer` inside a `Pipeline`.
51
+ - **[MEDIUM]** `SimpleImputer` fitted on the full dataset before the train/test split → imputation statistics computed from the test set leak into the model. Include the imputer as the first step in a `Pipeline` fitted only on training data.
52
+ - **[MEDIUM]** `LabelEncoder` used to encode feature columns → `LabelEncoder` is designed for target labels and raises an error on unseen categories at inference. Use `OrdinalEncoder` for ordinal features and `OneHotEncoder` for nominal features.
53
+ - **[LOW]** `cross_val_score` used with a regression metric string for a classifier or vice versa → wrong scoring produces meaningless numbers without an error. Pass the correct `scoring` parameter explicitly and verify it matches the estimator type.