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,56 @@
1
+ # gRPC — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: grpc, .proto files, protoc, grpc-js, grpcio, google.golang.org/grpc, @grpc/grpc-js, protobuf
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** gRPC server not configured with TLS → all traffic transmitted in plaintext over the network. Configure mutual TLS or server-side TLS for all production gRPC servers.
10
+ - **[CRITICAL]** No authentication interceptor → unauthenticated calls accepted by all service methods. Add a server interceptor that validates JWT, mTLS certificate, or API key on every incoming RPC.
11
+ - **[HIGH]** Metadata headers not validated for auth tokens → auth data present in metadata but not verified, allowing forged tokens. Extract and validate tokens from incoming metadata in the auth interceptor.
12
+ - **[HIGH]** Server reflection enabled in production → attackers can enumerate all service definitions and methods, aiding targeted attacks. Disable server reflection in production; enable only in development.
13
+ - **[HIGH]** Unvalidated proto message fields → missing required field validation allows invalid data into business logic, causing panics or incorrect behavior. Use protoc-gen-validate or protovalidate to enforce field constraints.
14
+ - **[HIGH]** SSRF via server-side gRPC calls to user-provided service addresses → attacker routes internal requests to arbitrary targets. Validate and whitelist allowed gRPC endpoints before dialing.
15
+ - **[MEDIUM]** Error messages in gRPC status details exposing internal implementation → stack traces or DB errors sent to clients aid attackers. Return sanitized error messages; log detailed errors server-side only.
16
+ - **[MEDIUM]** Insufficient input size limits on streaming RPCs → oversized messages exhaust server memory. Configure max message size limits on the server and validate message sizes in streaming handlers.
17
+
18
+ ---
19
+
20
+ ## Performance
21
+ - **[HIGH]** Unary RPC used for streaming use cases (large result sets, real-time events) → high latency and excessive overhead from repeated round-trips. Use server-streaming or bidirectional-streaming RPCs for continuous data flows.
22
+ - **[HIGH]** Large proto messages not using field streaming or chunking → entire payload buffered in memory, causing high latency and memory pressure. Break large payloads into streaming chunks or paginate with server-streaming.
23
+ - **[HIGH]** Client connection not reused across calls → TLS handshake and TCP connection established per call, adding significant latency. Create a single gRPC client connection or connection pool and reuse it.
24
+ - **[HIGH]** Missing deadline or timeout on every RPC call → slow or unresponsive servers hold goroutines/threads indefinitely, exhausting client resources. Always set a deadline via context: ctx, cancel := context.WithTimeout(ctx, 5*time.Second).
25
+ - **[MEDIUM]** No client-side load balancing configured → all calls routed to a single server instance, negating horizontal scaling. Configure gRPC client-side load balancing (round-robin, pick-first) or use a service mesh.
26
+ - **[MEDIUM]** Not retrying idempotent RPCs on transient failures → network blips cause unnecessary failures for safe-to-retry operations. Configure retry policy or implement exponential backoff for UNAVAILABLE and DEADLINE_EXCEEDED errors.
27
+ - **[LOW]** Not enabling gzip compression for large message payloads → large proto messages consume excess bandwidth. Enable compression codec on both client and server for message-heavy services.
28
+
29
+ ---
30
+
31
+ ## Architecture
32
+ - **[MEDIUM]** Proto definitions not in a separate shared proto repository or directory → service teams duplicate definitions, leading to drift and incompatibility. Centralize proto files in a shared repo with versioned packages.
33
+ - **[HIGH]** Breaking proto changes (renaming fields, changing field numbers, removing fields) without versioning → existing clients break when server updates. Create new package versions (v2, v3) for breaking changes; never alter field numbers.
34
+ - **[HIGH]** Business logic in gRPC server handler methods instead of a service layer → handlers become untestable monoliths. Extract domain logic into service types and call them from thin handler methods.
35
+ - **[MEDIUM]** Not using interceptors for logging, tracing, and metrics → observability data absent, making production debugging difficult. Add unary and streaming interceptors for structured logging, OpenTelemetry tracing, and Prometheus metrics.
36
+ - **[MEDIUM]** Proto-generated code committed to the repository instead of generated in CI → generated code drifts from proto definitions when developers forget to regenerate. Run protoc as a CI step and check for uncommitted changes.
37
+
38
+ ---
39
+
40
+ ## Code Quality
41
+ - **[MEDIUM]** Generated proto code committed to repo instead of generated in CI → generated files drift from proto source when developers forget to regenerate. Add proto compilation to CI and fail the build on uncommitted generated changes.
42
+ - **[HIGH]** Missing protoc-gen-validate or protovalidate for field-level validation → business logic receives invalid field values (empty required strings, out-of-range numbers). Add validation annotations to proto files and enforce them at the RPC boundary.
43
+ - **[MEDIUM]** gRPC status codes not semantically correct (e.g., INTERNAL returned for NOT_FOUND) → clients cannot distinguish error categories to implement correct retry or fallback logic. Map domain errors to appropriate gRPC status codes (NOT_FOUND, INVALID_ARGUMENT, etc.).
44
+ - **[LOW]** Not documenting proto service and message fields with comments → API consumers cannot understand expected values or semantics without reading source code. Add proto comment annotations; use buf.build or similar for generated API docs.
45
+ - **[MEDIUM]** Not using well-known types (google.protobuf.Timestamp, google.protobuf.Duration) for time fields → custom time representations lead to parsing bugs across language implementations. Use official well-known proto types for temporal data.
46
+ - **[MEDIUM]** Service definitions not following proto naming conventions → inconsistent naming confuses consumers and makes tooling harder. Follow Google API design guide naming conventions for RPCs, fields, and enums.
47
+
48
+ ---
49
+
50
+ ## Common Bugs & Pitfalls
51
+ - **[HIGH]** Deadline not propagated from the incoming parent context to downstream RPC calls → child calls run past the parent deadline, consuming resources after the client has given up. Always derive child contexts from the incoming request context.
52
+ - **[HIGH]** ClientConn not closed after use → goroutines and TCP connections leak indefinitely. Always defer conn.Close() after creating a gRPC client connection.
53
+ - **[MEDIUM]** Streaming server not sending an error status before closing the stream → client receives an EOF with no error context, making debugging difficult. Send a non-OK status via stream.SendMsg or return an error from the handler before returning.
54
+ - **[MEDIUM]** Proto oneof fields not handled exhaustively in switch statements → new oneof variants introduced in future proto versions silently fall through to a default case. Add a default branch that logs an unknown variant warning.
55
+ - **[HIGH]** Not handling stream context cancellation in server-streaming handlers → handlers continue sending after the client disconnects, wasting server resources. Check stream.Context().Done() in the streaming loop and exit cleanly.
56
+ - **[MEDIUM]** Reusing proto message structs across goroutines without copying → concurrent mutation of proto messages causes data races. Clone proto messages before passing to goroutines using proto.Clone().
@@ -0,0 +1,48 @@
1
+ # Haskell — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.hs`, `import Control.`, `import Data.`, `module `, `where`, `do`, `IO ()`, `cabal.project`, `stack.yaml`, `ghc`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** `unsafePerformIO` used in ostensibly pure code → violates referential transparency and can introduce data races when the IO action is shared across threads. Replace with properly threaded `IO` or use `IORef`/`MVar` for shared mutable state.
10
+ - **[HIGH]** `read` called on untrusted input → throws an exception (partial function) on any parse failure, crashing the thread. Use `readMaybe` from `Text.Read` and handle the `Nothing` case explicitly.
11
+ - **[MEDIUM]** Lazy IO via `readFile` / `hGetContents` → file handle not closed until the lazy string is fully consumed; if evaluation is deferred, handle leaks occur. Use `withFile` + strict `Data.ByteString` / `Data.Text` IO or the `conduit`/`pipes` streaming library.
12
+ - **[MEDIUM]** Cryptographic operations using unmaintained or unaudited libraries → known vulnerabilities unpatched. Use `cryptonite` or `botan-bindings` and pin exact versions; review library update history before adoption.
13
+
14
+ ---
15
+
16
+ ## Performance
17
+ - **[HIGH]** Lazy evaluation causing space leaks — thunks accumulate in long-running folds or accumulator patterns → process RSS grows unboundedly. Force strict evaluation with `seq`, `deepseq`, `BangPatterns`, or strict data fields (`{-# LANGUAGE StrictData #-}`).
18
+ - **[HIGH]** `String` (linked list of `Char`) used for text processing → 5–20× memory overhead and poor cache performance compared to `Text`. Use `Data.Text` (UTF-16 packed) or `Data.ByteString` for all string-heavy code.
19
+ - **[HIGH]** `Data.List` operations (`!!`, `length`) on large lists → O(n) traversal. Use `Data.Sequence` for O(log n) indexed access or `Data.Vector` for O(1) arrays.
20
+ - **[MEDIUM]** Accumulator in recursive function not forced with `!` (BangPattern) → thunk chain of size n built before evaluation begins, consuming O(n) stack/heap. Add `BangPatterns` or use `foldl'` (strict fold from `Data.List`).
21
+ - **[MEDIUM]** No profiling performed with GHC's `+RTS -p -s` runtime flags → space leaks and hot spots remain undetected until production. Run with `-prof -fprof-auto` during development to generate heap profiles.
22
+
23
+ ---
24
+
25
+ ## Architecture
26
+ - **[HIGH]** `IO` actions scattered throughout pure business logic → untestable without executing real effects. Separate pure logic from effects using the `ReaderT` pattern, `MTL` type classes, or an algebraic effects library (`effectful`, `polysemy`).
27
+ - **[HIGH]** Partial functions (`head`, `tail`, `fromJust`, `!!`) used in production code → `Exception` thrown on empty list or `Nothing`. Replace with total alternatives: `listToMaybe`, `maybe`, pattern match with an explicit empty case.
28
+ - **[MEDIUM]** Not using the `ReaderT` pattern for passing configuration and dependencies → functions take many explicit arguments or rely on global `IORef`s. Thread a `Env` record through `ReaderT Env IO` for implicit dependency injection.
29
+ - **[MEDIUM]** `State` monad overused for logic that is actually a pure fold → unnecessary monad overhead. Prefer `foldl'` or explicit accumulator arguments for simple stateful transformations.
30
+ - **[LOW]** Library and executable sources not separated in the Cabal file → internal modules exposed inadvertently; slower test compilation. Define a `library` stanza with the `exposed-modules` list and have the `executable` depend on it.
31
+
32
+ ---
33
+
34
+ ## Code Quality
35
+ - **[HIGH]** Partial functions in production: `head []`, `fromJust Nothing`, `arr !! outOfBounds` → runtime `Exception` with no meaningful error site. Use `listToMaybe`, `maybe default id`, and bounds-checked indexing; compile with `-Wall -Werror` to catch incomplete patterns.
36
+ - **[HIGH]** `error "TODO"` or `undefined` left in non-test code → crashes at runtime when the code path is reached. Replace with proper `Either`/`Maybe` returns or typed not-implemented errors before merging.
37
+ - **[MEDIUM]** Not running `hlint` and `ormolu`/`fourmolu` in CI → stylistic inconsistencies and common anti-patterns accumulate. Add `hlint` and formatter checks as CI steps; fail on any hint.
38
+ - **[MEDIUM]** Type signatures missing on top-level functions → GHC infers types but they may be more general than intended, causing subtle bugs or confusing error messages elsewhere. Add explicit type signatures to all top-level and exported functions.
39
+ - **[LOW]** Pattern matching not exhaustive with `-Wall` suppressed → `Non-exhaustive patterns` warning hidden, crashes in production. Compile with `-Wall -Wexhaustive-fields` and treat warnings as errors in CI.
40
+
41
+ ---
42
+
43
+ ## Common Bugs & Pitfalls
44
+ - **[HIGH]** Lazy `foldl` instead of strict `foldl'` for summation or accumulation → O(n) thunk chain causes stack overflow on large inputs. Always use `Data.List.foldl'` or `Data.Foldable.foldl'`; never use `foldl` on a strict result.
45
+ - **[HIGH]** `show` / `read` round-trip assumed for all types → `read (show x) /= x` for types like `Double` (NaN, Infinity) or custom `Show` instances. Use explicit serialization (Aeson, binary) for persistence rather than `show`/`read`.
46
+ - **[MEDIUM]** Monad transformer stack order not carefully chosen → `StateT s (ExceptT e IO)` (state lost on error) vs `ExceptT e (StateT s IO)` (state preserved on error) have different semantics. Document the intended error/state interaction and encode it in the type stack order.
47
+ - **[MEDIUM]** `unsafeCoerce` used to work around a type-checker error → type safety voided, potential runtime crash or memory corruption. Fix the underlying type mismatch; use `Data.Coerce.coerce` only for `newtype` coercions where it is guaranteed safe.
48
+ - **[LOW]** `deriving (Eq, Ord)` field order determines comparison semantics → adding a field changes the `Ord` instance, breaking `Map`/`Set` ordering. Document the intended comparison key and consider a manual `Ord` instance or `newtype` wrapper for maps.
@@ -0,0 +1,54 @@
1
+ # Helm — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `Chart.yaml`, `values.yaml`, `templates/`, `helm`, `{{ .Values.`, `{{ include "`, `helmfile`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Secrets committed to `values.yaml` in plain text → credentials in version control. Use External Secrets Operator, Sealed Secrets, or Vault Agent to inject secrets at deploy time.
10
+ - **[HIGH]** `hostNetwork: true` or `hostPID: true` in pod spec → container can access host network stack or process list. Remove unless explicitly required and documented.
11
+ - **[HIGH]** Containers running without `runAsNonRoot: true` in `securityContext` → process runs as root inside container. Set `runAsNonRoot: true` and `runAsUser` to a non-zero UID.
12
+ - **[HIGH]** Missing `readOnlyRootFilesystem: true` in container `securityContext` → container can write to its filesystem. Enable unless the app explicitly requires writes.
13
+ - **[HIGH]** `privileged: true` set in container security context → full host privilege escalation. Remove unless the workload is a node-level agent with documented justification.
14
+ - **[MEDIUM]** Default `values.yaml` uses production-scale resource limits that operators copy without review → accidental over-provisioning. Provide conservative defaults with comments showing production ranges.
15
+ - **[MEDIUM]** RBAC `ClusterRole` with broad resource/verb coverage instead of namespaced `Role` → unnecessary cluster-wide permissions. Scope to the minimum required namespace and verbs.
16
+
17
+ ---
18
+
19
+ ## Performance
20
+ - **[HIGH]** Resource `requests` and `limits` not defined for containers → noisy neighbour resource contention and OOM kills. Set CPU requests conservatively and memory limits firmly.
21
+ - **[HIGH]** `readinessProbe` not configured → Kubernetes sends traffic to pods that have not finished startup. Define a `readinessProbe` matching the application health endpoint.
22
+ - **[MEDIUM]** `strategy.type: Recreate` used for stateless deployments → causes full downtime during updates. Switch to `RollingUpdate` with appropriate `maxUnavailable` and `maxSurge`.
23
+ - **[MEDIUM]** HPA not configured for workloads with variable traffic → pods either over- or under-provisioned. Add a `HorizontalPodAutoscaler` resource keyed to CPU or custom metrics.
24
+ - **[MEDIUM]** `livenessProbe` configured identically to `readinessProbe` with a very short timeout → pod restart loops under temporary load. Tune liveness thresholds to be more lenient than readiness.
25
+ - **[LOW]** `topologySpreadConstraints` not set → all pods may schedule onto the same node. Add spread constraints to distribute replicas across zones.
26
+
27
+ ---
28
+
29
+ ## Architecture
30
+ - **[HIGH]** Business logic or environment-specific conditionals embedded directly in templates → hard to maintain across environments. Extract reusable snippets to `_helpers.tpl` and parameterize via values.
31
+ - **[HIGH]** `_helpers.tpl` not used for shared template fragments → duplication across templates causing drift. Define named templates in `_helpers.tpl` and call with `{{ include }}`.
32
+ - **[MEDIUM]** Chart not parameterized for environment differences → copy-paste charts per environment. Use a single chart with environment-specific `values-{env}.yaml` overrides.
33
+ - **[MEDIUM]** Subchart values not namespaced under the subchart key → values silently ignored or bleed into wrong scope. Always scope subchart overrides under the subchart alias key.
34
+ - **[MEDIUM]** No `NetworkPolicy` resources in chart → all pods can communicate unrestricted. Add default-deny ingress/egress policies and explicitly allow required traffic.
35
+ - **[LOW]** Chart `version` in `Chart.yaml` not incremented after template changes → `helm diff` shows no change when change exists. Bump `version` on every chart change.
36
+
37
+ ---
38
+
39
+ ## Code Quality
40
+ - **[HIGH]** `NOTES.txt` absent → users get no post-install instructions on how to reach the application. Add `NOTES.txt` with access instructions, default credentials note, and next steps.
41
+ - **[MEDIUM]** `required` function not used for mandatory values → chart renders with empty strings and fails at runtime with a cryptic error. Wrap mandatory values with `{{ required "message" .Values.key }}`.
42
+ - **[MEDIUM]** Chart not linted in CI with `helm lint` → syntax and structural errors ship. Add `helm lint .` as a required CI step before packaging.
43
+ - **[MEDIUM]** Labels not consistent across all resources → `kubectl` selectors and tooling break. Use the standard `helm.sh/chart`, `app.kubernetes.io/name` labels via `_helpers.tpl`.
44
+ - **[LOW]** `appVersion` in `Chart.yaml` not updated alongside application version → version mismatch in `helm list` output. Keep `appVersion` in sync with the container image tag default.
45
+
46
+ ---
47
+
48
+ ## Common Bugs & Pitfalls
49
+ - **[HIGH]** Image tag value not quoted: `tag: {{ .Values.image.tag }}` → numeric tags like `1.0` are parsed as a float and produce `1` in the manifest. Always use `| quote` for tag values.
50
+ - **[HIGH]** YAML indentation error in templates → produces silently wrong structure that Kubernetes accepts but behaves incorrectly. Use `helm template` + `kubeval` or `kubeconform` in CI.
51
+ - **[MEDIUM]** `helm upgrade --install` run without `--atomic` → failed release left in a broken partial state. Add `--atomic` to auto-rollback on failure, or `--cleanup-on-fail`.
52
+ - **[MEDIUM]** ConfigMap or Secret change not triggering pod restart → application continues using stale config. Add a checksum annotation: `checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}`.
53
+ - **[MEDIUM]** `with` block used where `range` is needed for maps → iteration skipped silently. Understand the difference: `range` for iteration, `with` for scope change on a single value.
54
+ - **[LOW]** `range` loop variable `$` scope not captured before entering loop → outer context values inaccessible inside loop. Capture with `{{- $root := . }}` before the `range` block.
@@ -0,0 +1,54 @@
1
+ # Hono — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: from 'hono', new Hono(), app.get(, app.use(, c.json(, c.req, Cloudflare Workers / Deno / Bun deployment
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Missing authentication middleware before protected routes → unauthenticated users access private resources. Apply an auth middleware via `app.use()` scoped to protected route groups before handler registration.
10
+ - **[HIGH]** No rate limiting on public endpoints → brute-force and DoS attacks succeed without throttling. Integrate a rate-limiting middleware or use platform-native throttling (e.g., Cloudflare rate limiting rules).
11
+ - **[HIGH]** `c.req.raw` body parsed without a size limit → large payloads exhaust memory on edge runtimes with limited heap. Apply a body-size check before parsing or configure platform limits.
12
+ - **[HIGH]** CORS wildcard `*` used for credentialed requests → cookies and auth headers accepted from any origin. Set specific allowed origins when `credentials: true` is needed.
13
+ - **[HIGH]** Environment secrets from `c.env` returned in error responses or logs → sensitive keys exposed to clients. Never include `c.env` values in response bodies; use structured error messages.
14
+ - **[MEDIUM]** Missing CSRF protection on state-mutating routes (POST/PUT/DELETE) → cross-site form submissions accepted from attacker-controlled pages. Implement CSRF token validation or use `SameSite=Strict` cookies.
15
+ - **[HIGH]** Path params and query strings used without validation → injection or unexpected behavior in downstream services. Validate all inputs with `@hono/zod-validator` or `zod-openapi`.
16
+ - **[MEDIUM]** Error handler exposing internal stack traces to clients → implementation details aid attackers. Register `app.onError()` to return sanitized error responses.
17
+
18
+ ---
19
+
20
+ ## Performance
21
+ - **[MEDIUM]** Not using `hono/cache` for cacheable GET responses → repeated requests hit origin unnecessarily, increasing latency and cost on edge deployments. Apply cache middleware with appropriate TTLs.
22
+ - **[HIGH]** Streaming not used for large response bodies → entire response buffered in memory before sending, causing high memory pressure. Use `c.stream()` or `streamText()` for large payloads.
23
+ - **[MEDIUM]** Middleware registered globally running on all routes including static asset paths → unnecessary processing overhead on every request. Scope middleware to specific route groups.
24
+ - **[LOW]** Not using `hono/compress` for response compression → larger payloads increase bandwidth costs and client load times. Add compression middleware for JSON and HTML responses.
25
+ - **[HIGH]** Synchronous or blocking operations inside route handlers on edge runtimes → stalls the single-threaded runtime and blocks other requests. Ensure all I/O uses async/await and avoid CPU-heavy work.
26
+ - **[MEDIUM]** Not leveraging edge-native caching (e.g., Cloudflare Cache API) for repeated external fetches → latency and cost increase with each cache miss. Cache external API responses at the edge.
27
+
28
+ ---
29
+
30
+ ## Architecture
31
+ - **[MEDIUM]** Not using Hono RPC mode (`hc()` client) for end-to-end type safety → API contract drift between server and client goes undetected at compile time. Define typed routes and consume via the Hono RPC client.
32
+ - **[HIGH]** Business logic implemented directly in route handlers → handlers become hard to test and reuse. Extract domain logic into service functions injected into handlers as dependencies.
33
+ - **[MEDIUM]** Related routes not grouped with sub-app instances → routing structure becomes flat and hard to navigate in large codebases. Use `new Hono()` sub-apps mounted with `app.route(prefix, subApp)`.
34
+ - **[HIGH]** `c.env` bindings not typed with the `Env` generic parameter → environment variables accessed as `any`, hiding missing binding errors until runtime. Always type the app as `new Hono<{ Bindings: Env }>()`.
35
+ - **[MEDIUM]** Middleware side effects not cleaned up after request → resource leaks accumulate across requests on long-lived edge workers. Ensure middleware releases resources before returning.
36
+
37
+ ---
38
+
39
+ ## Code Quality
40
+ - **[HIGH]** Missing `@hono/zod-validator` or `zod-openapi` for input validation → route handlers receive unvalidated user input, leading to runtime errors or security issues. Wrap all route inputs with Zod validation middleware.
41
+ - **[MEDIUM]** Error handling not centralized via `app.onError()` → inconsistent error formats returned from different routes confuse API consumers. Register a single global error handler with a consistent error envelope.
42
+ - **[MEDIUM]** Response types not annotated with `c.json<T>()` → response shape is untyped, allowing contract drift to go undetected. Use the generic overload of `c.json<T>()` to enforce response types.
43
+ - **[LOW]** Not using `hono/logger` middleware for request logging → requests and errors are not tracked, making production debugging difficult. Add the built-in logger or a custom structured logging middleware.
44
+ - **[MEDIUM]** Route definitions not co-located with their validation schemas → contract information scattered across files. Keep schema, types, and handler together in domain-scoped route modules.
45
+
46
+ ---
47
+
48
+ ## Common Bugs & Pitfalls
49
+ - **[HIGH]** `await c.req.json()` called more than once in a handler or middleware chain → the request body stream is consumed on the first read, returning empty or throwing on subsequent calls. Parse the body once and pass the result forward.
50
+ - **[MEDIUM]** `c.env` is undefined when running outside of edge environments (e.g., in unit tests or Node.js) → environment bindings missing causes runtime crashes. Mock `c.env` in tests and guard access with environment checks.
51
+ - **[CRITICAL]** Middleware `next()` not awaited → response is sent before downstream middleware and handlers execute, producing incorrect or empty responses. Always `await next()` inside Hono middleware.
52
+ - **[MEDIUM]** Path parameter names mismatched between route definition and `c.req.param()` calls → parameter returns undefined silently. Ensure param names in the route pattern exactly match the keys used in handlers.
53
+ - **[HIGH]** Not handling `app.notFound()` → unmatched routes return Hono default plain-text 404, inconsistent with the API error format. Register a custom not-found handler to return a structured error.
54
+ - **[MEDIUM]** Using `c.header()` after `c.json()` or `c.text()` → headers set after response finalization are silently ignored. Set all headers before calling the response method.
@@ -0,0 +1,38 @@
1
+ # HTMX — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `htmx.min.js` or `htmx.org` CDN · `hx-get` / `hx-post` / `hx-put` / `hx-delete` in HTML templates · `hx-swap` · `hx-trigger` · `hx-target`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** HTMX endpoints not validating CSRF token → HTMX uses standard HTTP requests; CSRF protections must be explicitly implemented server-side (SameSite cookies, token header, or HTMX's `htmx:configRequest` event).
11
+ - **[HIGH]** Server returning HTML fragments containing unsanitized user input → XSS via `hx-swap` directly injecting attacker-controlled HTML into the DOM. Sanitize all user data server-side before rendering.
12
+ - **[HIGH]** `hx-get` / `hx-post` URL constructed from user-provided query parameters without validation → SSRF or open redirect if the server makes additional requests based on the URL.
13
+ - **[MEDIUM]** Missing `Content-Security-Policy` header → XSS impact amplified by HTMX's DOM manipulation capabilities. Set restrictive CSP, including `script-src`.
14
+
15
+ ---
16
+
17
+ ## Performance
18
+
19
+ - **[MEDIUM]** No loading indicator (`hx-indicator`) on slow requests → poor UX; user may click the trigger multiple times, sending duplicate requests. Add a spinner with `hx-indicator`.
20
+ - **[MEDIUM]** `hx-trigger="every 1s"` for non-critical polling → continuous server load. Prefer Server-Sent Events (`hx-ext="sse"`) or WebSockets for real-time updates.
21
+ - **[LOW]** Large HTML fragments swapped on every request → send only the changed portion (fine-grained `hx-target`) to minimize re-render cost.
22
+
23
+ ---
24
+
25
+ ## Architecture
26
+
27
+ - **[HIGH]** Business logic embedded in server-side HTML fragment templates instead of controllers/services → templates become God templates. Keep templates as thin views; move logic to server handlers.
28
+ - **[MEDIUM]** Not using `hx-boost` on standard `<a>` and `<form>` elements → full page navigations where AJAX partial updates would work. `hx-boost` progressively enhances existing links.
29
+ - **[LOW]** `hx-target` pointing to a distant ancestor element by ID → fragile; layout changes break targeting. Prefer relative targets (`closest`, `next`, `previous`) or consistent ID conventions.
30
+
31
+ ---
32
+
33
+ ## Common Bugs & Pitfalls
34
+
35
+ - **[HIGH]** `hx-swap="outerHTML"` replacing the element that carries the `hx-*` attributes → after swap, the new HTML from the server must re-include `hx-*` attributes, or HTMX handlers are lost.
36
+ - **[HIGH]** `hx-trigger="load"` in a fragment returned by an HTMX swap → the fragment is loaded, triggers immediately, returns another fragment with `hx-trigger="load"` → infinite request loop.
37
+ - **[MEDIUM]** `hx-confirm` missing on destructive actions (delete, archive) → one misclick causes irreversible data loss. Add `hx-confirm="Are you sure?"`.
38
+ - **[LOW]** Missing `hx-push-url` on navigation-level swaps → browser back button does not restore previous state; breaks expected SPA-like navigation.
@@ -0,0 +1,87 @@
1
+ # Java — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.java` files · `public class` · `import java.` · without Spring Boot signals — for Spring Boot see `spring-boot.md`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** JDBC query with string concatenation: `"SELECT * WHERE id = " + id` → SQL injection. Use `PreparedStatement` with `?`.
11
+ - **[CRITICAL]** `Runtime.getRuntime().exec(userInput)` with shell string → command injection. Use argument array.
12
+ - **[CRITICAL]** `ObjectInputStream.readObject()` on untrusted data → arbitrary code execution (gadget chain). Filter with `ObjectInputFilter`.
13
+ - **[CRITICAL]** `XMLDecoder.readObject()` on untrusted XML → arbitrary Java object construction, effectively RCE.
14
+ - **[HIGH]** Deserializing JSON with `@JsonTypeInfo` and `enableDefaultTyping` → polymorphic deserialization attack.
15
+ - **[HIGH]** `File` operations with user-controlled paths without canonicalization → path traversal. Use `Path.normalize()` + prefix check.
16
+ - **[HIGH]** LDAP injection via string-concatenated LDAP queries with user input.
17
+ - **[HIGH]** XXE via `DocumentBuilderFactory` without disabling external entities → SSRF or file read.
18
+ - **[MEDIUM]** `Math.random()` for security tokens, nonces, session IDs → use `SecureRandom`.
19
+ - **[MEDIUM]** Sensitive data (passwords, keys) stored in `String` → immutable, interned, persists in memory. Use `char[]`.
20
+ - **[MEDIUM]** Log4j / SLF4J logging user input without sanitization → log injection (historically log4shell vector).
21
+ - **[LOW]** Sensitive data in Java heap dumps or thread dumps if not cleared.
22
+
23
+ ---
24
+
25
+ ## Performance
26
+
27
+ - **[HIGH]** `String +=` in loop → O(n²). Use `StringBuilder` or `String.join()`.
28
+ - **[HIGH]** `synchronized` on entire method when only small section needs it → unnecessary contention.
29
+ - **[HIGH]** `Connection` / `Statement` / `ResultSet` not closed → DB connection pool exhaustion. Use try-with-resources.
30
+ - **[HIGH]** N+1 queries in JPA — loading associations via lazy loading in loop → use `JOIN FETCH` or `EntityGraph`.
31
+ - **[HIGH]** Autoboxing `Integer`/`Long` in tight loops → heap allocation per operation. Use primitives.
32
+ - **[HIGH]** Virtual threads (Java 21+) blocked on synchronized → pin carrier thread. Use `ReentrantLock` instead.
33
+ - **[HIGH]** `Stream.parallel()` used for I/O-bound tasks → wrong executor, thread starvation.
34
+ - **[MEDIUM]** `List.contains()` called in loop on large `ArrayList` → O(n²). Use `HashSet`.
35
+ - **[MEDIUM]** Returning mutable collections from public API → caller can modify internal state. Return `Collections.unmodifiableList()` or `List.copyOf()`.
36
+ - **[MEDIUM]** `HashMap` without initial capacity for known large size → multiple rehashes.
37
+ - **[MEDIUM]** Unnecessary object creation inside loop (`new StringBuilder()` etc.).
38
+ - **[LOW]** `Iterator.remove()` not used when removing during iteration → `ConcurrentModificationException`.
39
+ - **[LOW]** Primitive array vs collection for large numeric data → boxing overhead.
40
+
41
+ ---
42
+
43
+ ## Architecture
44
+
45
+ - **[HIGH]** `static` mutable fields → shared global state, not thread-safe, complicates testing.
46
+ - **[HIGH]** Exception swallowed: `catch (Exception e) {}` or `e.printStackTrace()` → silent failure.
47
+ - **[HIGH]** `throws Exception` too broad → forces callers to handle `Exception`. Declare specific checked exceptions.
48
+ - **[HIGH]** Not using try-with-resources for `AutoCloseable` → resource leak on exception.
49
+ - **[HIGH]** Checked exceptions overused for recoverable business conditions → use result types or unchecked.
50
+ - **[MEDIUM]** Not using `Optional<T>` for nullable return values → NullPointerException propagation.
51
+ - **[MEDIUM]** God class >300 lines → decompose by responsibility (SRP).
52
+ - **[MEDIUM]** Concrete class dependencies instead of interface → hard to mock in tests.
53
+ - **[MEDIUM]** Not using `record` (Java 16+) for data carrier classes → verbose POJO boilerplate.
54
+ - **[MEDIUM]** Not using sealed classes (Java 17+) for ADT patterns → unchecked `instanceof` chains.
55
+ - **[LOW]** Method >50 lines → decompose.
56
+ - **[LOW]** Not using `var` (Java 10+) where type obvious → verbose.
57
+
58
+ ---
59
+
60
+ ## Code Quality
61
+
62
+ - **[HIGH]** `==` for `String` comparison → reference equality not value. Use `String.equals()` or `Objects.equals()`.
63
+ - **[HIGH]** NPE risk: no null checks on external/user data → use `Objects.requireNonNull()` or `Optional`.
64
+ - **[HIGH]** Not overriding `hashCode()` when overriding `equals()` → breaks HashMap/HashSet behavior.
65
+ - **[HIGH]** `instanceof` check without pattern matching (Java 16+) → redundant cast.
66
+ - **[MEDIUM]** Raw generic types: `List list` instead of `List<String>` → unchecked cast warnings, `ClassCastException`.
67
+ - **[MEDIUM]** Not using `@Override` on overridden methods → if base signature changes, override silently becomes new method.
68
+ - **[MEDIUM]** Not using `Collections.emptyList()` instead of `null` for empty collection returns.
69
+ - **[MEDIUM]** Mutable object stored in `final` field without defensive copy → field reference immutable but content mutable.
70
+ - **[LOW]** Not using `Stream` API for collection transformations → verbose `for` loops.
71
+ - **[LOW]** `System.out.println` for logging in production → use SLF4J.
72
+
73
+ ---
74
+
75
+ ## Common Bugs & Pitfalls
76
+
77
+ - **[HIGH]** `Integer` autoboxing comparison: `Integer a = 200; a == 200` → false outside cache (-128 to 127). Use `.equals()`.
78
+ - **[HIGH]** `java.util.Date`/`Calendar` mutability and timezone handling → use `java.time` (`Instant`, `ZonedDateTime`).
79
+ - **[HIGH]** `ConcurrentModificationException` from modifying collection during enhanced for-each → use `Iterator.remove()` or `removeIf()`.
80
+ - **[HIGH]** `HashMap` not thread-safe under concurrent writes → use `ConcurrentHashMap`.
81
+ - **[HIGH]** `Optional.get()` without `isPresent()` check → `NoSuchElementException`.
82
+ - **[MEDIUM]** `Arrays.asList()` returns fixed-size list → `UnsupportedOperationException` on `add()`/`remove()`.
83
+ - **[MEDIUM]** `List.of()` / `Map.of()` (Java 9+) are null-hostile and unmodifiable → don't pass null.
84
+ - **[MEDIUM]** `ThreadLocal` not removed in thread pool → stale data in reused threads.
85
+ - **[MEDIUM]** `SimpleDateFormat` not thread-safe → use `DateTimeFormatter` (thread-safe).
86
+ - **[LOW]** `finalize()` overridden → not guaranteed to run, removed Java 18. Use `Cleaner` or try-with-resources.
87
+ - **[LOW]** `instanceof` + cast without pattern matching → verbose, duplicates the type check.
@@ -0,0 +1,87 @@
1
+ # Jest / Vitest Stack Rules
2
+
3
+ Detection signals: `jest.config.*`, `vitest.config.*`, `*.test.ts/js`, `*.spec.ts/js`, `describe(`, `it(`, `test(`, `expect(`, `vi.fn()`, `jest.fn()`, `@jest/globals`, `vitest`
4
+
5
+ ---
6
+
7
+ ## Security
8
+
9
+ - **[MEDIUM]** Snapshot files containing hardcoded secrets or tokens committed to VCS → secrets leak in public or team-visible snapshot files. Sanitize sensitive values before serializing, or use a custom serializer that redacts known patterns.
10
+ - **[MEDIUM]** Test setup files importing real credentials or production config files → tests may inadvertently exfiltrate data or connect to live systems. Use mock credentials and dedicated test environment variables; never import `.env.production` in tests.
11
+ - **[MEDIUM]** Using real encryption keys, JWTs, or signed tokens as test fixtures → valid credentials in VCS are a secret leak. Generate synthetic, non-functional tokens for all test fixtures.
12
+ - **[MEDIUM]** Tests that write to the real filesystem without cleanup → leftover files may contain sensitive test payloads. Use `os.tmpdir()` and always delete in `afterEach`; or mock `fs` with `memfs`.
13
+ - **[MEDIUM]** Database tests connecting to shared or staging environments → test mutations affect real data. Use a dedicated test database, Docker container, or in-memory alternative per CI run.
14
+ - **[LOW]** `vi.mock()` / `jest.mock()` bypassing security middleware or auth guards in integration tests → tests verify code paths that would be blocked in production. Thread auth through proper test interfaces; use authenticated test clients.
15
+ - **[LOW]** `process.env` values from CI leaked via verbose test reporters → environment dumps in logs expose secrets. Suppress full environment output; use the `--silent` flag in CI.
16
+ - **[LOW]** Coverage reports uploaded to public artifact stores containing source snippets → source code in coverage HTML exposes logic. Restrict artifact access in CI settings.
17
+ - **[LOW]** Mocked network responses containing real PII from recorded fixtures (e.g., VCR-style recordings) → personal data in VCS. Anonymize fixtures before committing.
18
+ - **[LOW]** Tests importing from `src/config` that reads from `.env` at import time → production config leaks into test scope. Use dependency injection or mock the config module.
19
+
20
+ ---
21
+
22
+ ## Performance
23
+
24
+ - **[HIGH]** Real timers (`setTimeout`, `setInterval`, `Date.now`) in tests without `vi.useFakeTimers()` / `jest.useFakeTimers()` → tests wait real wall-clock time, making the suite slow and flaky. Call fake timers in `beforeEach` and restore in `afterEach`.
25
+ - **[HIGH]** Real HTTP calls in unit tests → tests depend on network availability, are slow, and non-deterministic. Mock with `msw` (Mock Service Worker) for realistic interception or `vi.mock` for simple cases.
26
+ - **[HIGH]** Heavy or async setup in `beforeAll` shared across unrelated test groups → test isolation breaks and suites cannot be parallelised independently. Use `beforeEach` for per-test setup; reserve `beforeAll` for truly immutable shared resources.
27
+ - **[HIGH]** Not isolating the module registry between tests → module-level state bleeds across tests within the same file. Call `vi.resetModules()` or `jest.resetModules()` in `beforeEach` when modules hold singleton state.
28
+ - **[HIGH]** Not using `--testPathPattern` or `test.only` during development → entire suite runs on every local change, slowing feedback. Use `--watch` with pattern filtering; use `test.only` locally (but never commit it).
29
+ - **[MEDIUM]** Large fixture files loaded entirely into memory for every test → memory pressure spikes. Load only the required subset per test or stream large fixtures.
30
+ - **[MEDIUM]** Missing parallelism configuration in Vitest → default pool settings may not saturate CPU cores. Configure `pool: forks` or `pool: threads` and set `poolOptions.maxForks` to match available cores.
31
+ - **[MEDIUM]** Missing `--coverage --coverageThreshold` enforcement in CI → coverage degrades silently over time. Add thresholds in `jest.config` / `vitest.config` and fail CI when they drop.
32
+ - **[MEDIUM]** Importing from barrel files (`src/index.ts`) in tests → pulls in the entire module graph, inflating startup time. Import directly from the source module that contains the code under test.
33
+ - **[MEDIUM]** Not using `test.each` for parameterized inputs → duplicated test bodies are slower to write and maintain. Use `test.each([...])` with a tagged template or array of tuples.
34
+ - **[LOW]** Running the full test suite locally instead of affected-only → slow feedback loop on large repos. Use `--changed` (Jest) or Vitests `--related` flag to run only tests affected by modified files.
35
+ - **[LOW]** Generating large coverage reports (LCOV + HTML + JSON) on every local run → unnecessary disk I/O. Restrict full report generation to CI; use `--reporter=dot` locally.
36
+
37
+ ---
38
+
39
+ ## Architecture
40
+
41
+ - **[HIGH]** Testing implementation details -- calling private methods, asserting internal state, spying on module-internal functions → tests break on safe refactors with no behavior change. Test only public API and observable outcomes.
42
+ - **[HIGH]** Tests depending on another tests side effects -- shared mutable state, relying on execution order → flaky suite that fails when run in isolation or in parallel. Use `beforeEach` to reset all shared state; each test must arrange its own preconditions.
43
+ - **[HIGH]** Mocking the module under test itself → the test validates the mock, not the real code. Mock only external dependencies; never mock the system under test.
44
+ - **[HIGH]** Over-mocking -- replacing things that could be tested with in-memory fakes (in-memory SQLite, fake queue, stub service) → low-confidence tests that do not catch integration bugs. Prefer real or realistic in-memory implementations over mocks where feasible.
45
+ - **[HIGH]** No test coverage for error paths, edge cases, empty collections, null/undefined inputs, and boundary values → bugs hidden in untested code paths. Enumerate edge cases explicitly; use code coverage to identify gaps.
46
+ - **[MEDIUM]** Single test file exceeding 500 lines → hard to navigate and review. Split by feature, component, or scenario into focused files.
47
+ - **[MEDIUM]** Single `it` / `test` block containing more than 10-15 assertions → unclear which assertion failed and why the test exists. Split into focused tests each verifying one behavior.
48
+ - **[MEDIUM]** Test names using vague descriptions such as `it('works')` or `test('test1')` → intent is invisible in failure reports. Use Given/When/Then or should-behavior-when-condition naming.
49
+ - **[MEDIUM]** No test isolation for database-touching integration tests → cross-test contamination corrupts later tests. Wrap each test in a transaction rolled back in `afterEach`, or reset with a seed script.
50
+ - **[MEDIUM]** Unit tests mixed with integration tests in the same file and same test run → slow integration tests pollute fast unit feedback. Separate with different file patterns and distinct npm scripts.
51
+ - **[LOW]** No `describe` block grouping in large test files → flat list of tests is hard to scan. Group by method, scenario, or component section.
52
+ - **[LOW]** Missing `afterEach` cleanup for tests that manipulate the DOM, global objects, or module-level singletons → stale state leaks into later tests.
53
+
54
+ ---
55
+
56
+ ## Code Quality
57
+
58
+ - **[CRITICAL]** `expect.assertions(n)` missing in async tests → if the async code throws before reaching `expect`, the test silently passes with zero assertions. Always declare the expected assertion count at the top of async tests.
59
+ - **[HIGH]** Using the `done` callback in async tests without calling it on every code path → test hangs on the timeout or silently passes. Migrate to `async/await`; avoid `done` entirely in modern Jest/Vitest.
60
+ - **[HIGH]** `toBe` used for object or array equality → compares by reference, so two structurally identical objects always fail. Use `toEqual` for deep equality or `toStrictEqual` to also check `undefined` properties.
61
+ - **[HIGH]** Async test body missing `await` on the expression under test → assertions run before the promise resolves, producing false positives. Always `await` async calls; use `return` as a fallback.
62
+ - **[HIGH]** Mocks not reset between tests -- missing `jest.clearAllMocks()` / `vi.clearAllMocks()` in `afterEach` or config → mock call counts and return values bleed across tests causing order-dependent failures. Enable `clearMocks: true` globally in config.
63
+ - **[MEDIUM]** `jest.mock()` / `vi.mock()` not placed at the module top level → hoisting may silently fail, leaving the real module in place. Always declare mocks before any imports that depend on them.
64
+ - **[MEDIUM]** `console.log` / `console.error` left in test files → noisy CI output obscures real failures. Remove debug logs or spy on console and assert intentionally.
65
+ - **[MEDIUM]** `toThrow()` used without specifying expected error type or message → any thrown error passes the assertion. Always specify: `toThrow(ValidationError)` or `toThrow('expected message')`.
66
+ - **[MEDIUM]** External snapshot files for tiny outputs → adds VCS churn for small strings. Use `toMatchInlineSnapshot()` for outputs that fit on one or two lines.
67
+ - **[MEDIUM]** Overuse of `vi.spyOn` to assert internal call counts rather than observable behavior → couples tests to implementation. Assert state or return values; spy on calls only when side-effect verification is the explicit goal.
68
+ - **[LOW]** `test.only` / `it.only` / `describe.only` committed to the repository → all other tests are silently skipped in CI, creating a false green. Add a lint rule (`eslint-plugin-jest` or `eslint-plugin-vitest`) to forbid `.only` in CI.
69
+ - **[LOW]** `test.skip` without a comment explaining the reason and a tracking ticket → forgotten skipped tests accumulate. Always add: `// TODO(#1234): unskip after fixing X`.
70
+ - **[LOW]** Using `vi.mock` to replace an entire module when only one function needs stubbing → replaces functions that should remain real. Use `vi.spyOn(module, methodName)` for partial mocking.
71
+
72
+ ---
73
+
74
+ ## Common Bugs & Pitfalls
75
+
76
+ - **[CRITICAL]** Async test that neither awaits nor returns the promise under test → test completes synchronously before any assertion runs, producing a false pass. Always `await` or `return` the promise; pair with `expect.assertions(n)`.
77
+ - **[HIGH]** Confusing `mockReturnValue(promise)` with `mockResolvedValue(value)` → `mockReturnValue(x)` for an async function returns the raw value rather than a resolved promise, causing `.then` to throw. Always use `mockResolvedValue` / `mockRejectedValue` for async mocks.
78
+ - **[HIGH]** `vi.mock` / `jest.mock` factory function referencing variables declared outside it before initialization → hoisting moves the mock call above imports, so the outer variable is `undefined`. Use the factory pattern: `vi.mock('./module', () => ({ fn: vi.fn() }))`.
79
+ - **[HIGH]** `beforeAll` async setup without `await` → setup is not complete when the first test runs, causing intermittent failures. All async hooks must `await` their promises or return them.
80
+ - **[HIGH]** Asserting on the wrong level of the component tree in React Testing Library -- finding elements by `container.querySelector` instead of user-facing queries → brittle tests that break on DOM restructuring. Use `getByRole`, `getByLabelText`, `getByText`.
81
+ - **[MEDIUM]** Updating snapshots with `--updateSnapshot` without reviewing the diff → broken behavior is silently accepted as the new truth. Always review snapshot diffs in the PR; treat them like code changes.
82
+ - **[MEDIUM]** `Date.now()` or `new Date()` called inside the module under test without mocking time → non-deterministic timestamps cause intermittent assertion failures. Use `vi.setSystemTime()` / `jest.setSystemTime()` and restore with `vi.useRealTimers()` in `afterEach`.
83
+ - **[MEDIUM]** React component tests missing `act()` wrapper around async state updates → stale state in assertions and React warning spam in output. Use RTLs `waitFor` or `findBy*` queries which wrap `act` internally.
84
+ - **[MEDIUM]** `jest.setTimeout` / `vi.setConfig({ testTimeout })` set globally too high → slow-failing tests occupy the maximum timeout before reporting. Set the shortest timeout that still allows realistic async operations to complete.
85
+ - **[MEDIUM]** Mock implementation returning `undefined` for a function that the code under test chains off of → `TypeError: cannot read property of undefined` masks the real bug. Always return a value from mocks that matches the shape the caller expects.
86
+ - **[LOW]** Not using `test.each` / `it.each` for parameterized cases → copy-pasted test bodies diverge silently over time. Refactor to `test.each([[input, expected], ...])`.
87
+ - **[LOW]** Test file importing a module with `import * as mod from './foo'` and then reassigning a property for mocking → only works in CommonJS; in ESM this throws. Use `vi.spyOn` or restructure exports to allow injection.
@@ -0,0 +1,50 @@
1
+ # jQuery — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `jquery`, `from 'jquery'`, `$.ajax`, `$(document).ready`, `$('#`, `jQuery` global, `<script src="jquery`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** `$(userInput)` used as a selector with user-controlled string → HTML injection / XSS if input contains tags. Treat user input as a string literal, never pass it to `$()` as a selector.
10
+ - **[CRITICAL]** `.html(userContent)` called with unsanitized user data → XSS allowing arbitrary script execution. Use `.text()` for plain content; sanitize with DOMPurify before calling `.html()`.
11
+ - **[CRITICAL]** `$.ajax` with `dataType: 'script'` loading a user-controlled URL → remote code execution. Never use `dataType: 'script'` with dynamic URLs; validate and whitelist all script sources.
12
+ - **[HIGH]** `$.ajax` response inserted into DOM via `.html()` without sanitization → stored XSS from server-returned HTML. Sanitize server responses before DOM insertion or use structured data (JSON) instead.
13
+ - **[HIGH]** CSRF token not included in `$.ajax` headers for state-changing requests → cross-site request forgery. Add CSRF token in `$.ajaxSetup` headers or per-request `headers` option.
14
+ - **[HIGH]** `eval()` or `new Function()` used inside jQuery callbacks with server data → code injection. Remove all dynamic code execution; parse JSON with `JSON.parse()` instead.
15
+
16
+ ---
17
+
18
+ ## Performance
19
+ - **[HIGH]** `$('.item')` queried repeatedly inside loops → O(n) DOM traversal per iteration. Cache the jQuery object in a variable before the loop: `const $items = $('.item')`.
20
+ - **[HIGH]** Event listeners attached to every element instead of using delegation → O(n) listeners for dynamic content. Use `.on('click', '.selector', handler)` on a stable parent for delegated events.
21
+ - **[HIGH]** Animations implemented with `setInterval`/`setTimeout` instead of CSS transitions or `requestAnimationFrame` → janky, CPU-heavy animation. Use CSS transitions or jQuery's `.animate()` which uses `requestAnimationFrame` internally.
22
+ - **[MEDIUM]** `$(document).ready` loading all JavaScript synchronously in `<head>` → render-blocking scripts. Move scripts to end of `<body>` or use `defer`/`async` attributes.
23
+ - **[MEDIUM]** `$.ajax` success callbacks deeply nested (callback hell) instead of `.then()` chaining → unmaintainable async flow. Chain `.then()` / `.done()` or convert to `async/await` with `fetch`.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+ - **[HIGH]** Global `$` / `jQuery` variable used alongside another library that also defines `$` → namespace collision. Use `jQuery.noConflict()` and alias: `const $j = jQuery.noConflict()`.
29
+ - **[HIGH]** Business logic (data transformation, validation) mixed directly into DOM manipulation callbacks → untestable, tightly coupled code. Extract logic into pure functions and call from callbacks.
30
+ - **[HIGH]** JS tightly coupled to DOM structure via deep selectors (`$('.page .sidebar ul li a')`) → breaks on any markup change. Use data attributes (`data-action="submit"`) as JS hooks instead of structural selectors.
31
+ - **[MEDIUM]** jQuery plugins added to `$.fn` without namespacing → risk of overwriting existing plugin. Namespace plugins: `$.fn.myAppPlugin = function() {}`.
32
+ - **[HIGH]** All code in global scope without module pattern → variable collisions and no encapsulation. Wrap in IIFE `(function($) { ... })(jQuery)` or use ES modules.
33
+
34
+ ---
35
+
36
+ ## Code Quality
37
+ - **[HIGH]** `$.ajax` calls without `.fail()` / `.catch()` error handler → silent failures, no user feedback. Always attach `.fail(function(jqXHR, status, error) { ... })` to every Ajax call.
38
+ - **[HIGH]** Undeclared variables inside jQuery callbacks → implicit globals polluting `window`. Always declare variables with `var`/`let`/`const`; enable `'use strict'`.
39
+ - **[MEDIUM]** Mixing `$.Deferred` with native `Promise` inconsistently → interop bugs (`.catch()` not available on Deferred). Standardize on native `Promise` / `fetch`; avoid `$.Deferred` in new code.
40
+ - **[MEDIUM]** Hardcoded DOM IDs with dynamic data (`#user-123`) as selectors → fragile, non-reusable code. Store references in data attributes and retrieve with `.data('id')`.
41
+ - **[LOW]** Deprecated jQuery APIs used (`.live()`, `.die()`, `.size()`, `.success()`) → runtime errors in jQuery 3+. Replace with modern equivalents: `.on()`, `.off()`, `.length`, `.done()`.
42
+
43
+ ---
44
+
45
+ ## Common Bugs & Pitfalls
46
+ - **[HIGH]** `.on()` handler attached inside a function called multiple times (e.g. on AJAX refresh) → handler fires multiple times per event. Use `.off('click').on('click', ...)` or attach handlers once on a stable parent.
47
+ - **[HIGH]** `$(this)` used inside an arrow function callback → `this` is lexically bound, not the jQuery element. Use `function()` keyword for jQuery callbacks that need `this`, or cache `$(event.currentTarget)`.
48
+ - **[MEDIUM]** `$(document).ready` nested inside another `$(document).ready` → double-wrapped handlers, potential double execution. Use a single top-level `$(document).ready` or `$(function() { })`.
49
+ - **[MEDIUM]** `.val()` vs `.text()` vs `.html()` confused for reading input values → wrong value or empty string returned. Use `.val()` for form inputs, `.text()` for element text content, `.html()` for inner HTML.
50
+ - **[MEDIUM]** Detached DOM nodes holding references via jQuery's internal data store → memory leak in single-page flows. Call `.remove()` (not `.detach()`) for nodes that won't be re-attached, or manually call `.off()` and `$.removeData()`.
@@ -0,0 +1,53 @@
1
+ # JUnit — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `junit`, `@Test`, `@BeforeEach`, `@AfterEach`, `import org.junit`, `@ExtendWith`, `MockitoExtension`, `@SpringBootTest`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[HIGH]** Real credentials or API keys in test configuration files (`application-test.yml`, `application.properties`) committed to the repository → secrets in version control. Use Spring Boot test property overrides with environment variables: `@Value("${API_KEY:default}")` and inject via CI.
10
+ - **[HIGH]** Tests making real HTTP calls to external services → external data returned; sensitive requests logged; tests fail when services are unavailable. Mock all external HTTP with `WireMock`, `MockWebServer`, or `@MockBean` on HTTP client beans.
11
+ - **[MEDIUM]** Test data containing PII (real email addresses, names, IDs) not cleaned from the test database → PII retained in staging DB indefinitely. Use generated fake data (`Faker`) and truncate test tables in `@AfterEach` or use `@Transactional` on the test class to auto-rollback.
12
+ - **[MEDIUM]** `@SpringBootTest` loading full application context including production beans (email sender, payment client) during integration tests → accidental real side effects triggered in test runs. Override production beans with `@MockBean` or use `@TestConfiguration` to provide stub implementations.
13
+ - **[LOW]** Test logs not suppressed for verbose beans → sensitive data from request/response logging appears in CI output. Configure `logging.level.root=WARN` in `application-test.properties` to suppress verbose logging during tests.
14
+
15
+ ---
16
+
17
+ ## Performance
18
+ - **[HIGH]** `@SpringBootTest` used for simple unit tests that do not require the full application context → Spring context startup adds 5-30 seconds per test class. Use `@WebMvcTest` for controller tests, `@DataJpaTest` for repository tests, and plain JUnit for service logic.
19
+ - **[HIGH]** No test parallelization configured in Maven Surefire or Gradle test task → large test suites run sequentially, blocking CI pipelines for minutes. Configure `<forkCount>` in Surefire or `maxParallelForks` in Gradle; ensure tests are stateless first.
20
+ - **[HIGH]** Database not rolled back between tests → test order dependency and state pollution cause intermittent failures. Annotate test classes with `@Transactional` to roll back after each test, or use an embedded H2 database that is re-seeded for each run.
21
+ - **[MEDIUM]** Heavy Mockito setup repeated in every `@Test` method instead of shared `@BeforeEach` → boilerplate inflates test methods and slows reading. Move common mock setup to `@BeforeEach` and assert specific behaviors per test.
22
+ - **[MEDIUM]** Test method execution order not defined with `@TestMethodOrder` when tests are order-dependent → test order is non-deterministic across JVM runs. Either make tests order-independent (preferred) or explicitly annotate with `@TestMethodOrder(MethodOrderer.OrderAnnotation.class)`.
23
+ - **[LOW]** Spring application context not cached across test classes → context restarted for each test class that uses a different configuration. Keep test configurations consistent; use `@DirtiesContext` only when the context genuinely needs to be reset.
24
+
25
+ ---
26
+
27
+ ## Architecture
28
+ - **[HIGH]** Tests not following Given-When-Then (or Arrange-Act-Assert) pattern → test intent is unclear; reviewers cannot tell what behavior is verified. Structure test methods: given (setup), when (invoke), then (assert) with blank line separation or comments.
29
+ - **[HIGH]** Single test method testing multiple independent behaviors → a failure does not isolate which behavior broke; other assertions not reached after first failure. Write one assertion per test method (or one logical behavior); use `@ParameterizedTest` for multiple inputs.
30
+ - **[MEDIUM]** No separation of unit, integration, and end-to-end tests via Maven profiles or Gradle source sets → slow integration tests run on every build; developers skip running them locally. Configure separate profiles: `unit` (always), `integration` (CI only), `e2e` (nightly).
31
+ - **[MEDIUM]** Shared mutable test fixtures causing test interdependence → tests pass when run in order but fail individually. Replace shared mutable state with immutable test data created fresh in `@BeforeEach`.
32
+ - **[MEDIUM]** Integration tests not using a containerized database (Testcontainers) → tests rely on a pre-existing local DB; environment drift causes flakiness. Use `@Testcontainers` with `@Container` to spin up a real database in Docker for integration tests.
33
+ - **[LOW]** Test classes not organized to mirror the production source structure → locating tests for a given class requires searching. Place test classes in the same package as the production class: `com.example.service.UserServiceTest` for `com.example.service.UserService`.
34
+
35
+ ---
36
+
37
+ ## Code Quality
38
+ - **[HIGH]** `assertTrue(result != null)` instead of `assertNotNull(result)` → failure message says "expected true but was false" with no context. Use specific assertion methods: `assertNotNull`, `assertEquals`, `assertThrows`, `assertIterableEquals`.
39
+ - **[HIGH]** Empty catch blocks in tests swallowing failures (`try { ... } catch (Exception e) {}`) → exceptions silently ignored; test passes when it should fail. Remove try/catch from test bodies unless explicitly testing exception behavior; use `assertThrows` instead.
40
+ - **[MEDIUM]** `@ParameterizedTest` not used for data-driven test cases → multiple nearly identical test methods for slight input variations. Replace with `@ParameterizedTest` and `@MethodSource` or `@CsvSource` to consolidate.
41
+ - **[MEDIUM]** Assertions missing a descriptive failure message → failure output shows no context about what was expected. Pass a message as the first argument: `assertEquals(expected, actual, "User ID should match after creation")`.
42
+ - **[MEDIUM]** Not using AssertJ or Hamcrest for fluent assertions → JUnit 5 built-in assertions have limited expressiveness; complex assertions are verbose. Add AssertJ: `assertThat(result).isNotNull().hasSize(3).containsExactly(...)`.
43
+ - **[LOW]** Test class visibility not public in JUnit 4 → test methods not discovered by the JUnit 4 runner. Ensure all JUnit 4 test classes are `public`; JUnit 5 relaxes this requirement but consistency is preferred.
44
+
45
+ ---
46
+
47
+ ## Common Bugs & Pitfalls
48
+ - **[HIGH]** `@BeforeAll` instance method without `static` modifier in JUnit 5 → JUnit 5 throws a runtime exception: "method must be static". Either make the method `static` or annotate the class with `@TestInstance(Lifecycle.PER_CLASS)`.
49
+ - **[HIGH]** `Mockito.verify()` not called after interactions that should be asserted → mock interactions go unchecked; test passes even if the expected method was never called. Add `verify(mock, times(1)).methodName(expectedArg)` for every interaction the test intends to assert.
50
+ - **[MEDIUM]** `@Transactional` on a test class rolling back after each test → the rollback means no actual database commit behavior is tested; bugs in commit-time constraints missed. Add a separate integration test without `@Transactional` for commit-path behavior.
51
+ - **[MEDIUM]** `@MockBean` vs `@Mock` confusion in Spring tests → `@Mock` creates a Mockito mock but does not inject it into the Spring context; `@MockBean` replaces the Spring bean. Use `@MockBean` in `@SpringBootTest` or `@WebMvcTest` tests; use `@Mock` with `@InjectMocks` in plain unit tests.
52
+ - **[MEDIUM]** Static utility methods not mockable with standard Mockito → tests require Mockito-inline or PowerMock dependencies; test complexity increases. Refactor static utility calls to instance methods injected as dependencies; test via the interface.
53
+ - **[LOW]** Test class not annotated with `@ExtendWith(MockitoExtension.class)` in JUnit 5 → `@Mock` annotations not processed; fields remain null causing NullPointerExceptions. Add `@ExtendWith(MockitoExtension.class)` to every test class that uses Mockito annotations.