prr-kit 1.1.2 → 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 +33 -165
  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
@@ -1,45 +1,65 @@
1
- agent:
2
- metadata:
3
- id: "_prr/prr/agents/performance-reviewer.md"
4
- name: "Petra"
5
- title: "Performance Code Reviewer"
6
- icon: "⚡"
7
- module: prr
8
- capabilities: "N+1 query detection, memory leak analysis, async/await patterns, bundle size, caching strategies, database query optimization"
9
- hasSidecar: false
10
- no_launcher: true
11
-
12
- persona:
13
- role: "Senior Performance Engineer specializing in application performance code review"
14
- identity: "12+ years optimizing web applications. Has profiled everything from database queries to JavaScript bundle sizes. Knows that premature optimization is evil, but also that ignoring obvious performance anti-patterns is worse."
15
- communication_style: "Data-driven and pragmatic. For every performance issue: estimates the impact (milliseconds, memory MB, request count) when possible. Distinguishes between micro-optimizations (skip) and impactful fixes (flag)."
16
- principles: |
17
- - Focus on impactful performance issues, not micro-optimizations
18
- - For database: look for N+1 queries, missing indexes, unneeded SELECT *
19
- - For frontend: bundle size, unnecessary re-renders, blocking operations
20
- - For async: proper error handling, avoiding callback hell, unnecessary await in loops
21
- - For memory: object references, event listener cleanup, large in-memory caches
22
- - Quantify impact when possible: "this could add Xms per request" or "X MB memory per user session"
23
- - Always suggest the fix, not just the problem
24
-
25
- critical_actions:
26
- - "For database operations: always check for N+1 query patterns (loop with DB call inside)"
27
- - "For async/await: check for unnecessary sequential awaits that could be parallelized"
28
- - "Quantify performance impact when possible — avoids review fatigue on trivial issues"
29
-
30
- menu:
31
- - trigger: "SP or fuzzy match on select-pr"
32
- exec: "{project-root}/_prr/prr/workflows/1-discover/select-pr/workflow.md"
33
- description: "[SP] Select PR to review"
34
-
35
- - trigger: "PR or fuzzy match on performance-review"
36
- workflow: "{project-root}/_prr/prr/workflows/3-review/performance-review/workflow.yaml"
37
- description: "[PR] Performance Review: N+1, memory, async, bundle size analysis"
38
-
39
- - trigger: "IC or fuzzy match on improve-code"
40
- workflow: "{project-root}/_prr/prr/workflows/4-improve/improve-code/workflow.yaml"
41
- description: "[IC] Improve Code: Performance-focused code improvements"
42
-
43
- - trigger: "RR or fuzzy match on generate-report"
44
- exec: "{project-root}/_prr/prr/workflows/6-report/generate-report/workflow.md"
45
- description: "[RR] Generate Report"
1
+ agent:
2
+ metadata:
3
+ id: "_prr/prr/agents/performance-reviewer.md"
4
+ name: "Petra"
5
+ title: "Performance Code Reviewer"
6
+ icon: "⚡"
7
+ module: prr
8
+ capabilities: "N+1 query detection, memory leak analysis, async/await patterns, bundle size, caching strategies, database query optimization"
9
+ hasSidecar: false
10
+ no_launcher: true
11
+
12
+ persona:
13
+ role: "Senior Performance Engineer specializing in application performance code review"
14
+ identity: "12+ years optimizing web applications. Has profiled everything from database queries to JavaScript bundle sizes. Knows that premature optimization is evil, but also that ignoring obvious performance anti-patterns is worse."
15
+ communication_style: "Data-driven and pragmatic. For every performance issue: estimates the impact (milliseconds, memory MB, request count) when possible. Distinguishes between micro-optimizations (skip) and impactful fixes (flag)."
16
+ principles: |
17
+ - Focus on impactful performance issues, not micro-optimizations
18
+ - For database: look for N+1 queries, missing indexes, unneeded SELECT *
19
+ - For frontend: bundle size, unnecessary re-renders, blocking operations
20
+ - For async: proper error handling, avoiding callback hell, unnecessary await in loops
21
+ - For memory: object references, event listener cleanup, large in-memory caches
22
+ - Quantify impact when possible: "this could add Xms per request" or "X MB memory per user session"
23
+ - Always suggest the fix, not just the problem
24
+
25
+ critical_actions:
26
+ - "For database operations: always check for N+1 query patterns (loop with DB call inside)"
27
+ - "For async/await: check for unnecessary sequential awaits that could be parallelized"
28
+ - "Quantify performance impact when possible — avoids review fatigue on trivial issues"
29
+
30
+ menu:
31
+ - trigger: "SP or fuzzy match on select-pr"
32
+ exec: "{project-root}/_prr/prr/workflows/1-discover/select-pr/workflow.md"
33
+ description: "[SP] Select PR: Fetch latest and select PR to review"
34
+
35
+ - trigger: "DP or fuzzy match on describe-pr"
36
+ exec: "{project-root}/_prr/prr/workflows/2-analyze/describe-pr/workflow.md"
37
+ description: "[DP] Describe PR: Understand PR scope before reviewing"
38
+
39
+ - trigger: "PR or fuzzy match on performance-review"
40
+ workflow: "{project-root}/_prr/prr/workflows/3-review/performance-review/workflow.yaml"
41
+ description: "[PR] Performance Review: N+1, memory, async, bundle size analysis"
42
+
43
+ - trigger: "IC or fuzzy match on improve-code"
44
+ workflow: "{project-root}/_prr/prr/workflows/4-improve/improve-code/workflow.yaml"
45
+ description: "[IC] Improve Code: Concrete inline code improvements with before/after suggestions"
46
+
47
+ - trigger: "AK or fuzzy match on ask-code"
48
+ exec: "{project-root}/_prr/prr/workflows/5-ask/ask-code/workflow.md"
49
+ description: "[AK] Ask: Interactive Q&A about specific code changes in this PR"
50
+
51
+ - trigger: "RR or fuzzy match on generate-report"
52
+ exec: "{project-root}/_prr/prr/workflows/6-report/generate-report/workflow.md"
53
+ description: "[RR] Generate Report: Compile performance findings into report"
54
+
55
+ - trigger: "PC or fuzzy match on post-comments"
56
+ exec: "{project-root}/_prr/prr/workflows/6-report/post-comments/workflow.md"
57
+ description: "[PC] Post Comments: Post inline review comments to GitHub/GitLab/Azure/Bitbucket PR"
58
+
59
+ - trigger: "HH or fuzzy match on help"
60
+ exec: "{project-root}/_prr/core/tasks/help.md"
61
+ description: "[HH] Help: Show review workflow guide and available commands"
62
+
63
+ - trigger: "CL or fuzzy match on clear or clean or reset"
64
+ exec: "{project-root}/_prr/core/tasks/clear.md"
65
+ description: "[CL] Clear: Remove context files and/or review reports from output folder"
@@ -1,43 +1,67 @@
1
- agent:
2
- metadata:
3
- id: "_prr/prr/agents/security-reviewer.md"
4
- name: "Sam"
5
- title: "Security Code Reviewer"
6
- icon: "🔒"
7
- module: prr
8
- capabilities: "OWASP top 10, SQL injection, XSS, auth vulnerabilities, API key exposure, dependency vulnerabilities, cryptography misuse"
9
- hasSidecar: false
10
- no_launcher: true
11
-
12
- persona:
13
- role: "Senior Security Engineer specializing in application security code review"
14
- identity: "8+ years in application security and penetration testing. Thinks like an attacker to find vulnerabilities before they do. Familiar with OWASP, NIST, and CWE standards. Never dismisses a potential vulnerability as 'low risk' without evidence."
15
- communication_style: "Precise and risk-focused. Always states: WHAT the vulnerability is, WHERE it is (file+line), HOW it could be exploited, and HOW to fix it. Uses severity: Critical/High/Medium/Low/Info instead of the standard severity emojis when appropriate."
16
- principles: |
17
- - Check OWASP Top 10 for every review: A01-A10
18
- - Look for hardcoded secrets, API keys, passwords in code and config files
19
- - Check authentication and authorization logic carefully
20
- - Validate all user inputs: injection (SQL, XSS, command), path traversal
21
- - Check error handling: stack traces and sensitive data must not reach users
22
- - Review dependency versions for known CVEs
23
- - Check rate limiting on authentication endpoints
24
- - For every finding: state impact if exploited
25
-
26
- critical_actions:
27
- - "Check for hardcoded secrets in EVERY review — API keys, passwords, tokens"
28
- - "Check ALL user input handling for injection vulnerabilities"
29
- - "For auth-related code: verify both authentication AND authorization logic"
30
- - "State the IMPACT for every finding: what could an attacker do if this is exploited?"
31
-
32
- menu:
33
- - trigger: "SP or fuzzy match on select-pr"
34
- exec: "{project-root}/_prr/prr/workflows/1-discover/select-pr/workflow.md"
35
- description: "[SP] Select PR: Fetch latest and select PR to review"
36
-
37
- - trigger: "SR or fuzzy match on security-review"
38
- workflow: "{project-root}/_prr/prr/workflows/3-review/security-review/workflow.yaml"
39
- description: "[SR] Security Review: Full OWASP-based security analysis"
40
-
41
- - trigger: "RR or fuzzy match on generate-report"
42
- exec: "{project-root}/_prr/prr/workflows/6-report/generate-report/workflow.md"
43
- description: "[RR] Generate Report: Compile security findings into report"
1
+ agent:
2
+ metadata:
3
+ id: "_prr/prr/agents/security-reviewer.md"
4
+ name: "Sam"
5
+ title: "Security Code Reviewer"
6
+ icon: "🔒"
7
+ module: prr
8
+ capabilities: "OWASP top 10, SQL injection, XSS, auth vulnerabilities, API key exposure, dependency vulnerabilities, cryptography misuse"
9
+ hasSidecar: false
10
+ no_launcher: true
11
+
12
+ persona:
13
+ role: "Senior Security Engineer specializing in application security code review"
14
+ identity: "8+ years in application security and penetration testing. Thinks like an attacker to find vulnerabilities before they do. Familiar with OWASP, NIST, and CWE standards. Never dismisses a potential vulnerability as 'low risk' without evidence."
15
+ communication_style: "Precise and risk-focused. Always states: WHAT the vulnerability is, WHERE it is (file+line), HOW it could be exploited, and HOW to fix it. Uses severity: Critical/High/Medium/Low/Info instead of the standard severity emojis when appropriate."
16
+ principles: |
17
+ - Check OWASP Top 10 for every review: A01-A10
18
+ - Look for hardcoded secrets, API keys, passwords in code and config files
19
+ - Check authentication and authorization logic carefully
20
+ - Validate all user inputs: injection (SQL, XSS, command), path traversal
21
+ - Check error handling: stack traces and sensitive data must not reach users
22
+ - Review dependency versions for known CVEs
23
+ - Check rate limiting on authentication endpoints
24
+ - For every finding: state impact if exploited
25
+
26
+ critical_actions:
27
+ - "Check for hardcoded secrets in EVERY review — API keys, passwords, tokens"
28
+ - "Check ALL user input handling for injection vulnerabilities"
29
+ - "For auth-related code: verify both authentication AND authorization logic"
30
+ - "State the IMPACT for every finding: what could an attacker do if this is exploited?"
31
+
32
+ menu:
33
+ - trigger: "SP or fuzzy match on select-pr"
34
+ exec: "{project-root}/_prr/prr/workflows/1-discover/select-pr/workflow.md"
35
+ description: "[SP] Select PR: Fetch latest and select PR to review"
36
+
37
+ - trigger: "DP or fuzzy match on describe-pr"
38
+ exec: "{project-root}/_prr/prr/workflows/2-analyze/describe-pr/workflow.md"
39
+ description: "[DP] Describe PR: Understand PR scope before reviewing"
40
+
41
+ - trigger: "SR or fuzzy match on security-review"
42
+ workflow: "{project-root}/_prr/prr/workflows/3-review/security-review/workflow.yaml"
43
+ description: "[SR] Security Review: Full OWASP-based security analysis"
44
+
45
+ - trigger: "IC or fuzzy match on improve-code"
46
+ workflow: "{project-root}/_prr/prr/workflows/4-improve/improve-code/workflow.yaml"
47
+ description: "[IC] Improve Code: Concrete inline code improvements with before/after suggestions"
48
+
49
+ - trigger: "AK or fuzzy match on ask-code"
50
+ exec: "{project-root}/_prr/prr/workflows/5-ask/ask-code/workflow.md"
51
+ description: "[AK] Ask: Interactive Q&A about specific code changes in this PR"
52
+
53
+ - trigger: "RR or fuzzy match on generate-report"
54
+ exec: "{project-root}/_prr/prr/workflows/6-report/generate-report/workflow.md"
55
+ description: "[RR] Generate Report: Compile security findings into report"
56
+
57
+ - trigger: "PC or fuzzy match on post-comments"
58
+ exec: "{project-root}/_prr/prr/workflows/6-report/post-comments/workflow.md"
59
+ description: "[PC] Post Comments: Post inline review comments to GitHub/GitLab/Azure/Bitbucket PR"
60
+
61
+ - trigger: "HH or fuzzy match on help"
62
+ exec: "{project-root}/_prr/core/tasks/help.md"
63
+ description: "[HH] Help: Show review workflow guide and available commands"
64
+
65
+ - trigger: "CL or fuzzy match on clear or clean or reset"
66
+ exec: "{project-root}/_prr/core/tasks/clear.md"
67
+ description: "[CL] Clear: Remove context files and/or review reports from output folder"
@@ -0,0 +1,97 @@
1
+ # prr-kit Configuration Template
2
+ # Copy this file to your project: _prr/prr/config.yaml
3
+
4
+ # ─── Identity ──────────────────────────────────────────────────────────────
5
+ user_name: YourName
6
+ communication_language: English # Language for all review output
7
+
8
+ # ─── Project ───────────────────────────────────────────────────────────────
9
+ project_name: my-project
10
+ target_repo: . # Path to git repo (. = current directory)
11
+
12
+ # ─── Platform ──────────────────────────────────────────────────────────────
13
+ platform: github # auto | github | gitlab | azure | bitbucket | none
14
+ platform_repo: "org/repo-name" # Used for gh pr list, gh pr view, etc.
15
+
16
+ # ─── Output ────────────────────────────────────────────────────────────────
17
+ review_output: ./_prr-output/reviews # Where review reports are written
18
+ auto_post_comment: false # Set to true to auto-post findings to GitHub/GitLab/Azure/Bitbucket after every review
19
+ # (skips the "PC" prompt in quick workflow)
20
+
21
+ # ─── Context Collection ────────────────────────────────────────────────────
22
+ context_collection:
23
+ enabled: true
24
+ mode: pr-specific # Always fresh, never cached
25
+
26
+ # Local primary sources (read if file exists)
27
+ primary_sources:
28
+ - CLAUDE.md
29
+ - AGENTS.md
30
+ - .github/CLAUDE_CODE_RULES.md
31
+ - .clauderules
32
+
33
+ # Config files (matched to file types changed in PR)
34
+ config_files:
35
+ - .eslintrc*
36
+ - .prettierrc*
37
+ - tsconfig.json
38
+ - vite.config.*
39
+ - webpack.config.*
40
+ - pyproject.toml
41
+ - .flake8
42
+
43
+ # Standards docs (read relevant sections based on PR domains)
44
+ standards_docs:
45
+ - CONTRIBUTING.md
46
+ - ARCHITECTURE.md
47
+ - docs/**/*.md
48
+
49
+ # Inline code annotations extracted from changed files
50
+ inline_annotations:
51
+ enabled: true
52
+ patterns:
53
+ - "@context:"
54
+ - "@security:"
55
+ - "@pattern:"
56
+ - "@rule:"
57
+
58
+ # ─── External Sources ──────────────────────────────────────────────────────
59
+ # Enable to allow prr-kit to use MCP tools and RAG systems available in
60
+ # your Claude Code session. No schema required per-tool — Claude auto-discovers
61
+ # what tools are available and maps them to the intents declared below.
62
+ external_sources:
63
+ enabled: false # Set to true to activate
64
+
65
+ mcp:
66
+ enabled: true
67
+ # Declare what kinds of context you want from MCP tools.
68
+ # The agent will discover available tools and use them accordingly.
69
+ # Remove intents you don't need.
70
+ intents:
71
+ - knowledge_base # Confluence, Notion → team standards, ADRs
72
+ - project_management # Jira, Linear → linked issue + acceptance criteria
73
+ - design # Figma, Zeplin → design specs (UI PRs only)
74
+ # - code_intelligence # Sourcegraph → similar patterns (uncomment if needed)
75
+
76
+ hints:
77
+ branch_issue_pattern: "([A-Z]+-\\d+)" # Regex to extract issue key from branch name
78
+ # e.g. feature/ENG-123-auth → ENG-123
79
+
80
+ rag:
81
+ enabled: false # Set to true if you have RAG tools configured
82
+ # Intents tell the agent what to query for in the RAG system
83
+ intents:
84
+ - similar_patterns # Find similar code in the codebase
85
+ - past_decisions # Previous review decisions for similar code
86
+ # - architecture_examples # Embedded architecture docs (uncomment if needed)
87
+
88
+ # Plain URL sources — fetched via WebFetch regardless of MCP availability
89
+ sources: []
90
+ # Example:
91
+ # sources:
92
+ # - type: url
93
+ # name: Shared ESLint config
94
+ # url: https://raw.githubusercontent.com/org/standards/main/eslint.md
95
+ # - type: url
96
+ # name: Security guidelines
97
+ # url: https://wiki.company.com/public/security-standards
@@ -0,0 +1,55 @@
1
+ # Actix-Web — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: actix-web, HttpServer::new, web::get(), web::post(), App::new(), HttpResponse, #[get(, #[post(
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Missing authentication middleware on protected routes → unauthenticated requests reach sensitive handlers. Wrap protected resource factories in an authentication middleware that validates session/JWT before dispatching.
10
+ - **[CRITICAL]** Shared state in `web::Data<Mutex<T>>` used incorrectly (e.g., holding the lock across await points) → deadlock or starvation under concurrent load. Use `RwLock` for read-heavy state and release locks before any await.
11
+ - **[CRITICAL]** SQL injection in raw query strings built with string formatting → attacker-controlled input alters query structure. Always use parameterized queries via sqlx, diesel, or SeaORM.
12
+ - **[HIGH]** CORS not configured via `actix-cors` → default behavior may reject legitimate cross-origin requests or accept all origins depending on config. Explicitly configure allowed origins and methods.
13
+ - **[HIGH]** No rate limiting → brute-force and DoS attacks succeed without throttling. Integrate a rate-limiting middleware at the `App::wrap()` level.
14
+ - **[HIGH]** User input in file paths without sanitization → path traversal allows reading or overwriting arbitrary files on the server. Canonicalize and validate paths, rejecting any that escape the intended directory.
15
+ - **[MEDIUM]** Sensitive data returned in error responses → internal paths, DB errors, or stack traces exposed to clients. Return generic error messages externally and log details internally.
16
+ - **[MEDIUM]** JWT not validated for expiry, signature, and audience claims → expired or forged tokens accepted. Use a well-tested JWT crate and validate all claims on every request.
17
+
18
+ ---
19
+
20
+ ## Performance
21
+ - **[CRITICAL]** Blocking operations (synchronous I/O, CPU-heavy computation) in async handlers → Actix-web worker threads stall, degrading all concurrent requests. Use `web::block()` to run blocking work on a dedicated thread pool.
22
+ - **[HIGH]** `Mutex` contention on `web::Data<Mutex<T>>` under load → high-concurrency requests queue waiting for the lock, serializing throughput. Use `RwLock` for read-heavy data or a lock-free structure.
23
+ - **[HIGH]** Large request bodies not streamed with `Payload` → entire body loaded into memory before processing, causing high memory pressure. Process large uploads as a stream using the `Payload` extractor.
24
+ - **[HIGH]** Not using connection pooling (e.g., sqlx `PgPool`, bb8) → a new DB connection established per request, causing latency spikes and exhausting server resources. Configure and share a connection pool via `web::Data`.
25
+ - **[MEDIUM]** Serializing large response structs without streaming → full response buffered in memory before sending. Implement chunked or streaming responses for large datasets.
26
+ - **[MEDIUM]** Not configuring worker thread count and async executor appropriately → default settings may not match workload characteristics. Tune `HttpServer::workers()` and consider async vs CPU-bound workload split.
27
+
28
+ ---
29
+
30
+ ## Architecture
31
+ - **[HIGH]** Business logic implemented in handler functions → handlers become large, untestable, and tightly coupled to HTTP concerns. Extract logic into service structs and inject them via `web::Data`.
32
+ - **[MEDIUM]** Not using `ServiceConfig` for modular route registration → all routes defined in one place, making the app configuration unmanageable. Use `cfg.service()` in per-domain configure functions.
33
+ - **[HIGH]** Error types not implementing `ResponseError` → all errors become opaque 500 responses with manual error handling in every handler. Define a custom error type implementing `ResponseError` with appropriate status codes.
34
+ - **[MEDIUM]** Using deprecated `App::data()` instead of `App::app_data()` → data registered with the old API may not be accessible in newer middleware. Migrate all state registration to `App::app_data()`.
35
+ - **[MEDIUM]** Middleware not reusing allocations across requests → per-request allocations in middleware increase GC pressure under load. Use `Arc` and pre-allocated buffers in middleware implementations.
36
+
37
+ ---
38
+
39
+ ## Code Quality
40
+ - **[CRITICAL]** `unwrap()` in handler functions → a panic crashes the Actix worker thread, returning a 500 to all requests on that thread. Replace with proper error propagation using `?` and the `ResponseError` trait.
41
+ - **[MEDIUM]** Not using `actix_web::test` utilities for handler testing → tests spin up a real HTTP server, making them slow and fragile. Use `test::init_service` and `test::call_service` for fast in-process handler testing.
42
+ - **[MEDIUM]** Missing request logging middleware → requests and errors go untracked in production, making debugging difficult. Add `actix-web::middleware::Logger` or a structured logging middleware.
43
+ - **[MEDIUM]** Not validating Content-Type before parsing request body → unexpected content types return a confusing 400 without a clear message. Check the Content-Type header early and return a structured error on mismatch.
44
+ - **[LOW]** Not setting keep-alive or connection timeout in server config → idle connections held open indefinitely waste file descriptors. Configure `HttpServer::keep_alive()` appropriately for the workload.
45
+ - **[MEDIUM]** Using panic-based error handling (`expect("msg")`) for expected failure modes → panics crash worker threads for recoverable errors. Reserve panics for truly unrecoverable states; use `Result` for expected failures.
46
+
47
+ ---
48
+
49
+ ## Common Bugs & Pitfalls
50
+ - **[HIGH]** `web::Data<T>` not registered before handler requires it → every request returns a 500 with "App data is not configured". Register all `web::Data` in the `App::app_data()` call before defining routes.
51
+ - **[MEDIUM]** `HttpResponse::Ok()` not finalized with `.finish()` or `.json()` → an empty or incomplete response is sent to the client. Always terminate the response builder with a body method.
52
+ - **[HIGH]** Multipart form parsing not handling the field stream correctly with `while let Some(field) = payload.next()` → fields skipped or processing stops at first error. Handle each field in the async loop and propagate errors.
53
+ - **[MEDIUM]** `actix::System` blocking calls used inside an async actix-web context → deadlock or panic from nested runtime invocations. Avoid Actix actor system calls inside async web handlers; use async messaging instead.
54
+ - **[HIGH]** Not implementing graceful shutdown → in-flight requests dropped when the process receives SIGTERM. Register a signal handler and call `server.stop()` to drain active connections before exiting.
55
+ - **[MEDIUM]** Cloning `web::Data<T>` repeatedly in hot paths → unnecessary `Arc` clone overhead accumulates. Store the inner reference where repeated access is needed within a single handler execution.
@@ -0,0 +1,47 @@
1
+ # Alpine.js — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `alpinejs`, `x-data`, `x-bind`, `x-on`, `x-model`, `from 'alpinejs'`, `Alpine.data()`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** `x-html` directive used with user-controlled content → XSS allowing arbitrary script execution. Replace `x-html` with `x-text` for user content; sanitize with DOMPurify if HTML rendering is required.
10
+ - **[CRITICAL]** `$el.innerHTML = userInput` written inside an Alpine component method → XSS bypassing Alpine's safe interpolation. Use `$el.textContent` for text or create elements via `document.createElement`.
11
+ - **[CRITICAL]** `Alpine.evaluate(el, userInput)` called with user-controlled expression string → arbitrary JavaScript code injection. Never evaluate user-supplied strings as Alpine expressions; use data-driven rendering instead.
12
+ - **[HIGH]** `fetch` calls inside Alpine components missing CSRF token → state-changing requests forgeable. Include CSRF token from a meta tag in all non-GET fetch requests: `headers: { 'X-CSRF-Token': token }`.
13
+ - **[MEDIUM]** Sensitive data (auth tokens, PII) stored in `x-data` object → visible in DOM via browser DevTools and queryable by any script. Store secrets server-side; reference only non-sensitive display state in `x-data`.
14
+
15
+ ---
16
+
17
+ ## Performance
18
+ - **[HIGH]** Large `x-data` object on the root `<body>` or `<main>` element → Alpine tracks reactivity for the entire page subtree on every change. Scope `x-data` to the smallest possible DOM subtree that needs reactivity.
19
+ - **[HIGH]** `x-for` without `:key` binding on dynamically changing lists → full DOM re-creation on every list mutation. Always add `:key="item.id"` to the `x-for` template element for efficient keyed diffing.
20
+ - **[MEDIUM]** Heavy computation or synchronous API calls inside `x-init` → blocks initial render, causing visible delay. Move slow work to `$nextTick` callbacks or use `fetch` with loading state toggling.
21
+ - **[MEDIUM]** `$watch` on a deeply nested object reference → Alpine observes the entire object tree, causing wide re-evaluation. Watch primitive signals or specific dotted paths; flatten state shape when possible.
22
+ - **[LOW]** Missing `x-cloak` with corresponding CSS `[x-cloak] { display: none }` → flash of un-initialized template markup before Alpine loads. Add `x-cloak` to elements that should be hidden until Alpine initializes.
23
+
24
+ ---
25
+
26
+ ## Architecture
27
+ - **[HIGH]** Complex business logic written as inline `x-on:click="..."` expression strings → untestable, hard to read, limited to expression length. Extract logic into `x-data` methods or `Alpine.data()` component definitions.
28
+ - **[HIGH]** Identical `x-data` object literals duplicated across multiple elements instead of `Alpine.data()` → no single source of truth, maintenance burden. Register reusable components with `Alpine.data('componentName', () => ({ ... }))`.
29
+ - **[HIGH]** Alpine components mixed with direct jQuery or vanilla DOM manipulation on the same elements → state conflicts between Alpine's reactive model and imperative DOM changes. Choose one paradigm per element; avoid external DOM mutations on Alpine-managed elements.
30
+ - **[MEDIUM]** Complex shared state not using `Alpine.store()` → prop threading or duplicated state across sibling components. Define global stores with `Alpine.store('storeName', { ... })` and access via `$store.storeName`.
31
+
32
+ ---
33
+
34
+ ## Code Quality
35
+ - **[CRITICAL]** `x-data="{}"` as an object literal on a template element cloned by `x-for` → all cloned instances share the same object reference, mutations affect all items. Use `x-data="() => ({ ... })"` (function form) to get a fresh object per instance.
36
+ - **[MEDIUM]** `$store`, `$dispatch`, `$refs` magic properties used without understanding their reactivity scope → unexpected behavior when accessing across component boundaries. Review Alpine's magic property documentation; `$refs` is local, `$store` is global, `$dispatch` bubbles DOM events.
37
+ - **[MEDIUM]** `x-data` expressions longer than a few tokens written inline → readability collapses, no syntax highlighting. Move all but the simplest initializations to `Alpine.data()` or a `<script>` block.
38
+ - **[LOW]** Alpine version loaded from CDN without a pinned version tag (`@latest`) → breaking changes auto-applied on next CDN cache miss. Pin to a specific semver: `alpinejs@3.13.5`.
39
+
40
+ ---
41
+
42
+ ## Common Bugs & Pitfalls
43
+ - **[CRITICAL]** `x-data="{}"` (plain object) on repeated elements → object is shared, all instances mutate the same state. Always use the function form `x-data="() => ({})"` to create independent state per element.
44
+ - **[HIGH]** `x-model` applied to a non-input element (div, span) without defining a custom getter/setter → model binding silently does nothing. Use `x-model` only on form controls; for custom elements define `x-modelable`.
45
+ - **[MEDIUM]** `x-show` used where `x-if` is needed (and vice versa) → `x-show` toggles `display` (element stays in DOM), `x-if` fully adds/removes. Use `x-if` for conditionally rendered heavy components; use `x-show` for simple visibility toggling.
46
+ - **[MEDIUM]** DOM reads immediately after state mutation without `$nextTick` → reading stale DOM before Alpine has flushed reactive updates. Wrap post-mutation DOM reads in `this.$nextTick(() => { ... })`.
47
+ - **[LOW]** `x-transition` classes conflicting with Tailwind's transition utilities applied to the same element → competing transition durations causing visual glitches. Use either `x-transition` directives or Tailwind transition classes on an element, not both.
@@ -0,0 +1,53 @@
1
+ # Android — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.kt` or `*.java` in Android project, `AndroidManifest.xml`, `build.gradle` with `com.android.application`, `Activity`, `Fragment`, `ViewModel`, `Compose`
5
+
6
+ ---
7
+
8
+ ## Security
9
+ - **[CRITICAL]** Sensitive data (tokens, PII, credentials) stored in `SharedPreferences` unencrypted → readable by root or backup extraction. Replace with `EncryptedSharedPreferences` from Jetpack Security library.
10
+ - **[HIGH]** `WebView.setJavaScriptEnabled(true)` combined with `addJavascriptInterface` → XSS in the loaded page can call exposed Java/Kotlin methods and execute native code. Validate all URLs loaded in WebView; use `@JavascriptInterface` only on methods that are safe to call from web content.
11
+ - **[HIGH]** `Activity`, `Service`, or `BroadcastReceiver` exported in `AndroidManifest.xml` without `android:permission` → any installed app can launch or send intents. Add `android:exported="false"` or a custom `android:permission` to all components not intended for external access.
12
+ - **[HIGH]** API keys, OAuth secrets, or endpoints hardcoded in `BuildConfig` fields or `res/values/strings.xml` → extracted from APK with `apktool` in seconds. Store secrets server-side and fetch at runtime; use Android Keystore for keys that must live on device.
13
+ - **[HIGH]** SQL injection via `rawQuery(userInput, null)` in SQLite → database manipulation or data exfiltration. Always use parameterized queries: `rawQuery("SELECT ... WHERE id = ?", arrayOf(id))` or Room's `@Query` with bound parameters.
14
+ - **[HIGH]** `FileProvider` paths configured too broadly (e.g., root `/`) → any file in the app sandbox shared with external apps. Restrict `<paths>` in the FileProvider XML to the minimum required directory.
15
+ - **[MEDIUM]** SSL certificate validation disabled by overriding `TrustManager` to accept all certs → undetectable MITM on all HTTPS traffic. Use the default `TrustManager`; for testing use a network security config, not production trust-all code.
16
+
17
+ ---
18
+
19
+ ## Performance
20
+ - **[HIGH]** Network requests made on the main thread → `NetworkOnMainThreadException` crash on API 11+. Move all network calls to a coroutine with `Dispatchers.IO` or a background thread.
21
+ - **[HIGH]** Heavy computation or IO performed in `onDraw()` → dropped frames and jank at every draw cycle. Move all computation outside the draw path; `onDraw` should only issue canvas draw calls.
22
+ - **[HIGH]** Activity or Fragment references held by long-lived objects (singletons, callbacks, `companion object`) → memory leak until process death. Use `WeakReference`, `ViewModel` (lifecycle-scoped), or pass context only to short-lived objects.
23
+ - **[HIGH]** `RecyclerView.Adapter.notifyDataSetChanged()` called instead of `DiffUtil` → entire list rebinds and re-draws on any change, causing visible flicker. Use `DiffUtil.calculateDiff()` or `ListAdapter` with `DiffUtil.ItemCallback`.
24
+ - **[MEDIUM]** Full-resolution `Bitmap` loaded into memory for a small `ImageView` → OOM on devices with limited heap. Use Glide or Coil with target size constraints, or manually decode with `BitmapFactory.Options.inSampleSize`.
25
+ - **[MEDIUM]** `ViewModel` not used for UI state → state lost on configuration change (rotation), causing unnecessary re-fetches and blank screens. Hoist all UI state into a `ViewModel` and expose it via `StateFlow` or `LiveData`.
26
+ - **[LOW]** `findViewById()` called repeatedly instead of using `ViewBinding` → minor overhead and null-safety risk. Enable `viewBinding` in `build.gradle` and use generated binding classes.
27
+
28
+ ---
29
+
30
+ ## Architecture
31
+ - **[HIGH]** Business logic placed directly in `Activity` or `Fragment` → untestable without an emulator and tightly coupled to the Android lifecycle. Move logic to `ViewModel` (MVVM) or a `Presenter`/`Store` (MVI); keep UI classes as thin observers.
32
+ - **[HIGH]** `Repository` pattern not used → UI layer directly calls data sources (Room DAO, Retrofit service), making data source swaps and unit testing impossible. Introduce a `Repository` class that abstracts all data access and exposes domain models.
33
+ - **[MEDIUM]** Dependency injection done manually at scale instead of using Hilt or Koin → constructor chains become unmanageable; hard to swap implementations in tests. Adopt Hilt (compile-time DI, recommended by Google) or Koin (runtime DI, simpler setup).
34
+ - **[MEDIUM]** Mixing `LiveData` and `StateFlow`/`SharedFlow` without a clear policy → inconsistent lifecycle handling and confusion about replay behavior. Standardize on `StateFlow`/`SharedFlow` for new code; `LiveData` only where Jetpack libraries require it.
35
+ - **[LOW]** Fragment transactions managed manually instead of using Navigation Component → back-stack fragmentation, inconsistent transitions, and deep-link handling is ad hoc. Adopt Navigation Component with a `NavGraph` for all screen transitions.
36
+
37
+ ---
38
+
39
+ ## Code Quality
40
+ - **[HIGH]** `AsyncTask` used for background work → deprecated in API 30 with known memory leak patterns. Replace with `viewModelScope.launch { withContext(Dispatchers.IO) { ... } }`.
41
+ - **[HIGH]** Non-null assertion operator `!!` used on nullable Kotlin types → `NullPointerException` at runtime when the value is actually null. Use safe call `?.`, `?:` Elvis operator, or explicit null checks.
42
+ - **[MEDIUM]** Coroutines launched with `GlobalScope` or without `lifecycleScope`/`viewModelScope` → coroutine outlives the Activity/Fragment, leaking references and executing after destruction. Use `lifecycleScope` in UI components and `viewModelScope` in `ViewModel`.
43
+ - **[MEDIUM]** Runtime permissions requested without showing rationale when `shouldShowRequestPermissionRationale()` returns true → users denied permission without understanding why, causing silent feature breakage. Show an explanation dialog before re-requesting.
44
+ - **[LOW]** `lint` checks not run in CI → Android-specific issues (missing translations, incorrect resource references, API level violations) undetected until runtime. Add `./gradlew lint` to CI and treat `Error` severity as a build failure.
45
+
46
+ ---
47
+
48
+ ## Common Bugs & Pitfalls
49
+ - **[HIGH]** `Activity` `Context` stored in a singleton or static field → Activity is never garbage collected, leaking the entire view hierarchy. Pass only `Application` context to singletons; use `context.applicationContext` for long-lived objects.
50
+ - **[HIGH]** Fragment added to the back stack multiple times without checking `isAdded` or using `findFragmentByTag` → duplicate fragments stacked on top of each other, causing UI glitches and double event handling. Always check `fragmentManager.findFragmentByTag(tag)` before adding.
51
+ - **[MEDIUM]** `onCreate()` not checking `savedInstanceState` before re-initializing state → data reset and redundant network calls on every rotation or process restore. Guard initialization with `if (savedInstanceState == null) { ... }`.
52
+ - **[MEDIUM]** `startActivityForResult()` / `onActivityResult()` used in new code → deprecated; result delivery unreliable across process death. Use `registerForActivityResult()` with the appropriate `ActivityResultContract`.
53
+ - **[LOW]** Hardcoded pixel sizes used instead of `dp`/`sp` units → UI elements appear too large or too small on different screen densities. Use `dp` for dimensions and `sp` for text sizes; define in `dimens.xml`.
@@ -0,0 +1,96 @@
1
+ # Angular — Stack-Specific Review Rules
2
+
3
+ > Applies to: GR · SR · PR · AR · BR
4
+ > Detection signals: `*.component.ts`, `@Component(`, `@Injectable(`, `@NgModule(`, `angular.json`, `@angular/` in deps, `standalone: true`, `signal(`, `inject(`
5
+
6
+ ---
7
+
8
+ ## Security
9
+
10
+ - **[CRITICAL]** `bypassSecurityTrustHtml()` / `DomSanitizer.bypassSecurityTrust*()` with user-controlled content → XSS. Angular sanitizes by default; bypass only for fully trusted content.
11
+ - **[CRITICAL]** `[innerHTML]` binding with user content without sanitization → XSS.
12
+ - **[HIGH]** Route guard missing on protected routes (`canActivate`, `canActivateChild`, `canMatch`) → unauthenticated access.
13
+ - **[HIGH]** HTTP interceptor not adding auth header on all requests → API calls without credentials.
14
+ - **[HIGH]** `HttpClient` calls made without CSRF token on state-changing requests.
15
+ - **[HIGH]** Template injection via Angular's `templateUrl` loading from user-controlled path (server-rendered).
16
+ - **[HIGH]** Sensitive data stored in `localStorage` via Angular service → accessible to injected scripts.
17
+ - **[HIGH]** `window.location.href` set from route params without validation → open redirect.
18
+ - **[MEDIUM]** CORS configured permissively in Angular proxy config (`angular.json`) left in production.
19
+ - **[MEDIUM]** Error messages from HTTP errors shown directly to user → info disclosure.
20
+ - **[MEDIUM]** JWT stored in memory (signal/service) not cleared on logout → token persists in JS heap.
21
+ - **[LOW]** Angular DevTools enabled in production → component tree exposed.
22
+
23
+ ---
24
+
25
+ ## Performance
26
+
27
+ - **[HIGH]** Component not using `OnPush` change detection for data-heavy components → Angular checks entire tree on every event.
28
+ - **[HIGH]** Subscription not unsubscribed in `ngOnDestroy` (or not using `async` pipe / `takeUntilDestroyed`) → memory leak.
29
+ - **[HIGH]** `trackBy` missing on `*ngFor` / `@for` with large/dynamic lists → full DOM re-render on any change.
30
+ - **[HIGH]** Signal computed function doing expensive work → not memoized correctly if dependencies unstable.
31
+ - **[HIGH]** Multiple HTTP calls made sequentially that could be parallel → use `forkJoin` or `combineLatest`.
32
+ - **[HIGH]** Not using lazy-loaded feature modules / routes for large sections → oversized initial bundle.
33
+ - **[HIGH]** `BehaviorSubject.value` accessed synchronously in template → not reactive, stale value.
34
+ - **[HIGH]** `toSignal()` without `initialValue` causing nullable type complications and unnecessary null checks.
35
+ - **[MEDIUM]** Heavy computation in template expressions → recalculated every CD cycle; use `pipe` (pure) or `computed()`.
36
+ - **[MEDIUM]** `APP_INITIALIZER` doing slow async work → delays app startup; defer non-critical init.
37
+ - **[MEDIUM]** Zone.js detecting changes from unrelated third-party events (analytics, maps) → use `runOutsideAngular`.
38
+ - **[MEDIUM]** Images not using `NgOptimizedImage` → no lazy loading or size optimization.
39
+ - **[MEDIUM]** `ChangeDetectorRef.detectChanges()` called in a loop → manual CD triggering defeats OnPush benefits.
40
+ - **[LOW]** `async` pipe used multiple times on same observable in template → multiple subscriptions; use `as` syntax.
41
+ - **[LOW]** Not using `@defer` blocks (Angular 17+) for below-fold components.
42
+
43
+ ---
44
+
45
+ ## Architecture
46
+
47
+ - **[HIGH]** Business logic in component class → controllers should only handle view concerns; move to injectable service.
48
+ - **[HIGH]** Component directly calling `HttpClient` instead of going through service layer → untestable, tightly coupled.
49
+ - **[HIGH]** Circular dependency between services → Angular DI throws at runtime.
50
+ - **[HIGH]** `inject()` called outside injection context (not in constructor, field initializer, or factory) → runtime error.
51
+ - **[HIGH]** Smart/dumb component boundary violated — presentational component directly injecting services.
52
+ - **[HIGH]** State management done via service with plain properties instead of `BehaviorSubject`/`signal` → no reactivity.
53
+ - **[HIGH]** `NgModule` architecture mixed with standalone components without migration plan → confusion.
54
+ - **[MEDIUM]** Missing `providedIn: 'root'` vs module-scoped provider — wrong scope causes multiple instances.
55
+ - **[MEDIUM]** Using `any` type in component `@Input()`/`@Output()` → loses type safety at component boundary.
56
+ - **[MEDIUM]** `Subject` used where `BehaviorSubject` needed — late subscribers miss current value.
57
+ - **[MEDIUM]** Effects not used for signal-based side effects (Angular 17+) → mixing reactive and imperative.
58
+ - **[MEDIUM]** Route resolver overloading — doing too much data fetching causing slow navigation.
59
+ - **[LOW]** Module not feature-scoped — all declarations in `AppModule` → slow compilation, poor separation.
60
+ - **[LOW]** Not using `InjectionToken` for config values → relying on `string` tokens causing collision.
61
+
62
+ ---
63
+
64
+ ## Code Quality
65
+
66
+ - **[HIGH]** `ngOnInit` subscribing to Observable without `async` pipe or `takeUntilDestroyed` → memory leak.
67
+ - **[HIGH]** `@Input()` not using `required: true` (Angular 16+) for required inputs → runtime undefined with no warning.
68
+ - **[HIGH]** Signal mutations done with `set()` instead of `update()` when new value depends on old → stale value race.
69
+ - **[HIGH]** `EventEmitter` type not specified (`EventEmitter` vs `EventEmitter<string>`) → runtime type mismatch.
70
+ - **[MEDIUM]** Template reference variables (`#ref`) used for logic across complex templates → tight coupling.
71
+ - **[MEDIUM]** `@ViewChild` accessed before `ngAfterViewInit` → undefined access.
72
+ - **[MEDIUM]** `*ngIf` with multiple conditions not extracted to component method → unreadable template.
73
+ - **[MEDIUM]** RxJS operators not used (`switchMap`, `takeUntil`, `shareReplay`) → anti-patterns.
74
+ - **[MEDIUM]** `switchMap` used when `mergeMap` needed (or vice versa) → requests cancelled or duplicated.
75
+ - **[MEDIUM]** Not using Angular's new control flow (`@if`, `@for`, `@switch`) in Angular 17+ projects.
76
+ - **[LOW]** Missing `standalone: true` when upgrading from NgModule-based components (Angular 14+).
77
+ - **[LOW]** `console.log` left in component lifecycle hooks → production noise.
78
+ - **[LOW]** Pipes not used for data transformation in template → inline ternary/method calls everywhere.
79
+
80
+ ---
81
+
82
+ ## Common Bugs & Pitfalls
83
+
84
+ - **[HIGH]** `ExpressionChangedAfterItHasBeenCheckedError` — modifying bound value in `ngAfterViewInit` without `ChangeDetectorRef.detectChanges()`.
85
+ - **[HIGH]** `async` pipe used with cold observable that never completes → subscription held forever.
86
+ - **[HIGH]** `switchMap` in effects cancelling in-flight HTTP requests on rapid emissions → use `exhaustMap` for form submits.
87
+ - **[HIGH]** Signal `effect()` creating infinite loop — reading and writing same signal in effect body.
88
+ - **[HIGH]** `DestroyRef` injection not used with `takeUntilDestroyed()` outside constructor → requires injection context.
89
+ - **[HIGH]** `HttpClient` returning cold observable — not subscribing means request never fires.
90
+ - **[MEDIUM]** `Subject` vs `BehaviorSubject` confusion — using Subject where late subscribers need current value.
91
+ - **[MEDIUM]** Calling `markForCheck()` excessively in OnPush → defeats the purpose.
92
+ - **[MEDIUM]** Route params accessed via `snapshot` inside component that needs to react to param changes → use `paramMap` observable.
93
+ - **[MEDIUM]** Interceptor modifying request without cloning → mutating immutable `HttpRequest`.
94
+ - **[MEDIUM]** `providedIn: 'root'` on service with state meant to be scoped per module → shared state bug.
95
+ - **[LOW]** Forgetting `@Output()` decorator on EventEmitter → event never emits to parent.
96
+ - **[LOW]** `HostListener` not cleaned up — unlike subscriptions, it IS cleaned up by Angular but double-attaching is possible via manual `addEventListener`.