neon_sakura 0.1.4

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 (251) hide show
  1. checksums.yaml +7 -0
  2. data/.ai-reviewer/README.md +182 -0
  3. data/.ai-reviewer/ai-reviewer.sh +56 -0
  4. data/.ai-reviewer/build-system-prompt.sh +136 -0
  5. data/.ai-reviewer/extract-claude-sections.sh +32 -0
  6. data/.ai-reviewer/test-ai-reviewer.sh +40 -0
  7. data/.ai-reviewer-config.yml +190 -0
  8. data/.github/dependabot.yml +12 -0
  9. data/.github/settings.yml +70 -0
  10. data/.github/workflows/ai-pr-review-on-comment.yml +384 -0
  11. data/.github/workflows/ai-pr-review.yml +328 -0
  12. data/.github/workflows/license-check.yml +78 -0
  13. data/.github/workflows/lint.yml +79 -0
  14. data/.github/workflows/security.yml +131 -0
  15. data/.github/workflows/semgrep.yml +26 -0
  16. data/.github/workflows/test.yml +44 -0
  17. data/.gitignore +75 -0
  18. data/.rubocop.yml +33 -0
  19. data/.ruby-version +1 -0
  20. data/.simplecov +14 -0
  21. data/.stylelintignore +10 -0
  22. data/.stylelintrc.json +37 -0
  23. data/AGENTS.md +51 -0
  24. data/CHANGELOG.md +568 -0
  25. data/CLAUDE.md +632 -0
  26. data/Gemfile +8 -0
  27. data/Gemfile.lock +327 -0
  28. data/LICENSE +21 -0
  29. data/README.md +1209 -0
  30. data/Rakefile +25 -0
  31. data/app/assets/images/cherry_blossom.svg +1525 -0
  32. data/app/assets/images/cherry_blossom_tree.png +0 -0
  33. data/app/assets/images/prysm-icon.png +0 -0
  34. data/app/assets/stylesheets/base.css +29 -0
  35. data/app/assets/stylesheets/components.css +1652 -0
  36. data/app/assets/stylesheets/forms.css +152 -0
  37. data/app/assets/stylesheets/loading.css +145 -0
  38. data/app/assets/stylesheets/neon_sakura.css +40 -0
  39. data/app/assets/stylesheets/pagy-tailwind.css +120 -0
  40. data/app/assets/stylesheets/theme-default.css +40 -0
  41. data/app/assets/stylesheets/theme-green.css +84 -0
  42. data/app/assets/stylesheets/theme-purple.css +94 -0
  43. data/app/assets/stylesheets/theme-red.css +84 -0
  44. data/app/assets/stylesheets/utility-borders.css +29 -0
  45. data/app/assets/stylesheets/utility-colors.css +185 -0
  46. data/app/assets/stylesheets/utility-effects.css +123 -0
  47. data/app/assets/stylesheets/utility-gradients.css +158 -0
  48. data/app/assets/stylesheets/utility-layout.css +132 -0
  49. data/app/assets/stylesheets/utility-reset.css +13 -0
  50. data/app/assets/stylesheets/utility-responsive.css +145 -0
  51. data/app/assets/stylesheets/utility-sizing.css +99 -0
  52. data/app/assets/stylesheets/utility-spacing.css +174 -0
  53. data/app/assets/stylesheets/utility-typography.css +97 -0
  54. data/app/controllers/errors_controller.rb +120 -0
  55. data/app/controllers/style_guide_controller.rb +117 -0
  56. data/app/helpers/errors_helper.rb +12 -0
  57. data/app/helpers/neon_sakura/navbar_helper.rb +43 -0
  58. data/app/helpers/style_guide_helper.rb +36 -0
  59. data/app/javascript/neon_sakura/dropdown.js +22 -0
  60. data/app/javascript/neon_sakura/navbar.js +71 -0
  61. data/app/javascript/neon_sakura/theme_switcher.js +187 -0
  62. data/app/views/errors/show.html.erb +105 -0
  63. data/app/views/layouts/error.html.erb +19 -0
  64. data/app/views/layouts/mission_control/jobs/_application_selection.html.erb +14 -0
  65. data/app/views/layouts/mission_control/jobs/_navigation.html.erb +21 -0
  66. data/app/views/layouts/mission_control/jobs/application.html.erb +453 -0
  67. data/app/views/layouts/style_guide.html.erb +416 -0
  68. data/app/views/shared/_file_upload.html.erb +184 -0
  69. data/app/views/shared/_footer.html.erb +23 -0
  70. data/app/views/shared/_header.html.erb +42 -0
  71. data/app/views/shared/_navbar.html.erb +306 -0
  72. data/app/views/shared/_profile_image_selector.html.erb +165 -0
  73. data/app/views/shared/_theme_switcher.html.erb +64 -0
  74. data/app/views/shared/icons/_adjustments.html.erb +10 -0
  75. data/app/views/shared/icons/_alert_circle.html.erb +3 -0
  76. data/app/views/shared/icons/_alert_triangle.html.erb +3 -0
  77. data/app/views/shared/icons/_archive.html.erb +3 -0
  78. data/app/views/shared/icons/_arrow_down.html.erb +3 -0
  79. data/app/views/shared/icons/_arrow_left.html.erb +3 -0
  80. data/app/views/shared/icons/_arrow_up.html.erb +3 -0
  81. data/app/views/shared/icons/_arrows_pointing_in.html.erb +10 -0
  82. data/app/views/shared/icons/_arrows_pointing_out.html.erb +10 -0
  83. data/app/views/shared/icons/_artemis_logo.html.erb +26 -0
  84. data/app/views/shared/icons/_auth_banner.html.erb +1 -0
  85. data/app/views/shared/icons/_bars.html.erb +10 -0
  86. data/app/views/shared/icons/_bell.html.erb +3 -0
  87. data/app/views/shared/icons/_book.html.erb +3 -0
  88. data/app/views/shared/icons/_bookmark.html.erb +3 -0
  89. data/app/views/shared/icons/_box.html.erb +3 -0
  90. data/app/views/shared/icons/_brain.html.erb +3 -0
  91. data/app/views/shared/icons/_briefcase.html.erb +3 -0
  92. data/app/views/shared/icons/_calendar.html.erb +3 -0
  93. data/app/views/shared/icons/_camera.html.erb +4 -0
  94. data/app/views/shared/icons/_chart_bar.html.erb +3 -0
  95. data/app/views/shared/icons/_chart_line.html.erb +10 -0
  96. data/app/views/shared/icons/_chart_pie.html.erb +11 -0
  97. data/app/views/shared/icons/_chat.html.erb +3 -0
  98. data/app/views/shared/icons/_check.html.erb +3 -0
  99. data/app/views/shared/icons/_check_circle.html.erb +3 -0
  100. data/app/views/shared/icons/_cherry_blossom.html.erb +1516 -0
  101. data/app/views/shared/icons/_cherry_blossom_silhouette.html.erb +1016 -0
  102. data/app/views/shared/icons/_cherry_blossom_single_flower.html.erb +1125 -0
  103. data/app/views/shared/icons/_cherry_blossom_tree.html.erb +159 -0
  104. data/app/views/shared/icons/_chevron_down.html.erb +3 -0
  105. data/app/views/shared/icons/_chevron_right.html.erb +9 -0
  106. data/app/views/shared/icons/_clipboard.html.erb +3 -0
  107. data/app/views/shared/icons/_clock.html.erb +3 -0
  108. data/app/views/shared/icons/_close.html.erb +3 -0
  109. data/app/views/shared/icons/_cog.html.erb +4 -0
  110. data/app/views/shared/icons/_crop.html.erb +10 -0
  111. data/app/views/shared/icons/_crown.html.erb +3 -0
  112. data/app/views/shared/icons/_disc.html.erb +3 -0
  113. data/app/views/shared/icons/_download.html.erb +3 -0
  114. data/app/views/shared/icons/_dragonfly.html.erb +58 -0
  115. data/app/views/shared/icons/_duplicate.html.erb +4 -0
  116. data/app/views/shared/icons/_edit.html.erb +3 -0
  117. data/app/views/shared/icons/_envelope.html.erb +3 -0
  118. data/app/views/shared/icons/_eraser.html.erb +10 -0
  119. data/app/views/shared/icons/_external_link.html.erb +3 -0
  120. data/app/views/shared/icons/_eye.html.erb +4 -0
  121. data/app/views/shared/icons/_file_csv.html.erb +10 -0
  122. data/app/views/shared/icons/_file_export.html.erb +10 -0
  123. data/app/views/shared/icons/_file_image.html.erb +10 -0
  124. data/app/views/shared/icons/_file_import.html.erb +10 -0
  125. data/app/views/shared/icons/_file_question.html.erb +6 -0
  126. data/app/views/shared/icons/_film.html.erb +3 -0
  127. data/app/views/shared/icons/_filter.html.erb +3 -0
  128. data/app/views/shared/icons/_folder.html.erb +3 -0
  129. data/app/views/shared/icons/_folder_open.html.erb +3 -0
  130. data/app/views/shared/icons/_folder_plus.html.erb +3 -0
  131. data/app/views/shared/icons/_globe.html.erb +3 -0
  132. data/app/views/shared/icons/_google.html.erb +11 -0
  133. data/app/views/shared/icons/_heart.html.erb +3 -0
  134. data/app/views/shared/icons/_heart_broken.html.erb +11 -0
  135. data/app/views/shared/icons/_heart_pulse.html.erb +4 -0
  136. data/app/views/shared/icons/_history.html.erb +11 -0
  137. data/app/views/shared/icons/_home.html.erb +10 -0
  138. data/app/views/shared/icons/_image.html.erb +3 -0
  139. data/app/views/shared/icons/_inbox.html.erb +3 -0
  140. data/app/views/shared/icons/_info_circle.html.erb +10 -0
  141. data/app/views/shared/icons/_key.html.erb +3 -0
  142. data/app/views/shared/icons/_layers.html.erb +10 -0
  143. data/app/views/shared/icons/_lightbulb.html.erb +10 -0
  144. data/app/views/shared/icons/_lightning.html.erb +3 -0
  145. data/app/views/shared/icons/_list.html.erb +3 -0
  146. data/app/views/shared/icons/_lock.html.erb +3 -0
  147. data/app/views/shared/icons/_logout.html.erb +3 -0
  148. data/app/views/shared/icons/_magazine.html.erb +3 -0
  149. data/app/views/shared/icons/_magic.html.erb +3 -0
  150. data/app/views/shared/icons/_minus.html.erb +10 -0
  151. data/app/views/shared/icons/_mobile.html.erb +10 -0
  152. data/app/views/shared/icons/_moon.html.erb +3 -0
  153. data/app/views/shared/icons/_network.html.erb +10 -0
  154. data/app/views/shared/icons/_new_item_banner.html.erb +1 -0
  155. data/app/views/shared/icons/_ouroboros.html.erb +24 -0
  156. data/app/views/shared/icons/_package.html.erb +3 -0
  157. data/app/views/shared/icons/_palette.html.erb +3 -0
  158. data/app/views/shared/icons/_paper_plane.html.erb +10 -0
  159. data/app/views/shared/icons/_photo.html.erb +10 -0
  160. data/app/views/shared/icons/_play.html.erb +4 -0
  161. data/app/views/shared/icons/_plus.html.erb +3 -0
  162. data/app/views/shared/icons/_pocket.html.erb +11 -0
  163. data/app/views/shared/icons/_prysm-icon.html.erb +34 -0
  164. data/app/views/shared/icons/_prysm.html.erb +13 -0
  165. data/app/views/shared/icons/_pushbullet-1.html.erb +29 -0
  166. data/app/views/shared/icons/_pushbullet-2.html.erb +2 -0
  167. data/app/views/shared/icons/_puzzle.html.erb +10 -0
  168. data/app/views/shared/icons/_qrcode.html.erb +3 -0
  169. data/app/views/shared/icons/_question.html.erb +3 -0
  170. data/app/views/shared/icons/_receipt.html.erb +10 -0
  171. data/app/views/shared/icons/_redo.html.erb +3 -0
  172. data/app/views/shared/icons/_refresh.html.erb +3 -0
  173. data/app/views/shared/icons/_rocket.html.erb +10 -0
  174. data/app/views/shared/icons/_rss.html.erb +3 -0
  175. data/app/views/shared/icons/_save.html.erb +3 -0
  176. data/app/views/shared/icons/_search.html.erb +3 -0
  177. data/app/views/shared/icons/_search_minus.html.erb +10 -0
  178. data/app/views/shared/icons/_search_plus.html.erb +10 -0
  179. data/app/views/shared/icons/_server_error.html.erb +6 -0
  180. data/app/views/shared/icons/_share.html.erb +3 -0
  181. data/app/views/shared/icons/_shield_check.html.erb +3 -0
  182. data/app/views/shared/icons/_sign_in.html.erb +3 -0
  183. data/app/views/shared/icons/_spinner.html.erb +4 -0
  184. data/app/views/shared/icons/_star.html.erb +3 -0
  185. data/app/views/shared/icons/_store.html.erb +10 -0
  186. data/app/views/shared/icons/_sun.html.erb +3 -0
  187. data/app/views/shared/icons/_sync.html.erb +3 -0
  188. data/app/views/shared/icons/_table.html.erb +3 -0
  189. data/app/views/shared/icons/_tag.html.erb +3 -0
  190. data/app/views/shared/icons/_tags.html.erb +11 -0
  191. data/app/views/shared/icons/_tools.html.erb +4 -0
  192. data/app/views/shared/icons/_trash.html.erb +3 -0
  193. data/app/views/shared/icons/_undo.html.erb +3 -0
  194. data/app/views/shared/icons/_unlock.html.erb +3 -0
  195. data/app/views/shared/icons/_upload.html.erb +3 -0
  196. data/app/views/shared/icons/_user.html.erb +3 -0
  197. data/app/views/shared/icons/_user_circle.html.erb +10 -0
  198. data/app/views/shared/icons/_user_plus.html.erb +10 -0
  199. data/app/views/shared/icons/_video.html.erb +3 -0
  200. data/app/views/shared/icons/_wrench.html.erb +11 -0
  201. data/app/views/style_guide/index.html.erb +77 -0
  202. data/app/views/style_guide/sections/_alerts.html.erb +114 -0
  203. data/app/views/style_guide/sections/_badges.html.erb +78 -0
  204. data/app/views/style_guide/sections/_buttons.html.erb +130 -0
  205. data/app/views/style_guide/sections/_cards.html.erb +84 -0
  206. data/app/views/style_guide/sections/_colors.html.erb +106 -0
  207. data/app/views/style_guide/sections/_file_upload.html.erb +135 -0
  208. data/app/views/style_guide/sections/_forms.html.erb +129 -0
  209. data/app/views/style_guide/sections/_gradients.html.erb +253 -0
  210. data/app/views/style_guide/sections/_header.html.erb +12 -0
  211. data/app/views/style_guide/sections/_icons.html.erb +55 -0
  212. data/app/views/style_guide/sections/_images.html.erb +40 -0
  213. data/app/views/style_guide/sections/_loading.html.erb +242 -0
  214. data/app/views/style_guide/sections/_pagination.html.erb +212 -0
  215. data/app/views/style_guide/sections/_profile_components.html.erb +203 -0
  216. data/app/views/style_guide/sections/_theme_switcher.html.erb +72 -0
  217. data/app/views/style_guide/sections/_typography.html.erb +65 -0
  218. data/bin/ai-optimize-claude-md +540 -0
  219. data/bin/ai-review-local +345 -0
  220. data/bin/ai-security-review +585 -0
  221. data/bin/brakeman +9 -0
  222. data/bin/install-hooks +57 -0
  223. data/bin/rake +7 -0
  224. data/bin/rubocop +10 -0
  225. data/bin/verify_setup.rb +31 -0
  226. data/config/brakeman.ignore +28 -0
  227. data/config/initializers/neon_sakura.rb +15 -0
  228. data/config/license_overrides.yml +13 -0
  229. data/config/routes.rb +21 -0
  230. data/config/theme_mappings.yml +61 -0
  231. data/docs/PRYSM_ASSETS.md +210 -0
  232. data/docs/plans/extract_ai_reviewer_plan.md +151 -0
  233. data/docs/plans/neon_sakura_gem_plan.md +138 -0
  234. data/lib/neon_sakura/configuration.rb +94 -0
  235. data/lib/neon_sakura/engine.rb +48 -0
  236. data/lib/neon_sakura/icon_helper.rb +54 -0
  237. data/lib/neon_sakura/profile_helper.rb +24 -0
  238. data/lib/neon_sakura/stylesheet_helper.rb +40 -0
  239. data/lib/neon_sakura/theme_helper.rb +63 -0
  240. data/lib/neon_sakura/theme_importer.rb +112 -0
  241. data/lib/neon_sakura/version.rb +5 -0
  242. data/lib/neon_sakura.rb +13 -0
  243. data/neon_sakura.gemspec +50 -0
  244. data/package.json +18 -0
  245. data/scripts/git-hooks/post-merge +132 -0
  246. data/scripts/git-hooks/pre-commit +123 -0
  247. data/scripts/git-hooks/pre-push +127 -0
  248. data/scripts/license-check.rb +587 -0
  249. data/settings.local.json +12 -0
  250. data/yarn.lock +778 -0
  251. metadata +503 -0
@@ -0,0 +1,345 @@
1
+ #!/usr/bin/env bash
2
+ # Local AI code review using Ollama
3
+ # Uses the same prompts and logic as GitHub Actions workflows
4
+ #
5
+ # Usage:
6
+ # bin/ai-review-local [OPTIONS] [BASE_BRANCH] [OLLAMA_URL]
7
+ # bin/ai-review-local --help | -h
8
+ #
9
+ # Options:
10
+ # -m, --model MODEL Specify the model to use (default: codestral:latest)
11
+ # -i, --interactive Interactively select model from available models
12
+ # -f, --full-review Review all tracked files in current branch (no comparison)
13
+ # --help, -h Show this help message
14
+ #
15
+ # Arguments:
16
+ # BASE_BRANCH - Branch to compare against (default: main or master, ignored with -f)
17
+ # OLLAMA_URL - Ollama server URL (default: $OLLAMA_URL env var or http://localhost:11434)
18
+ #
19
+ # Examples:
20
+ # bin/ai-review-local # Compare current branch to main
21
+ # bin/ai-review-local develop # Compare to develop branch
22
+ # bin/ai-review-local main http://server:11434 # Use remote Ollama server
23
+ # bin/ai-review-local -i # Interactively select model
24
+ # bin/ai-review-local -m llama3:latest # Use specific model
25
+ # bin/ai-review-local -f # Review entire current branch
26
+ # bin/ai-review-local --help # Show this help message
27
+
28
+ # Load shared library
29
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
30
+ if [ -f "$SCRIPT_DIR/../lib/ai-script-base.sh" ]; then
31
+ # shellcheck source=../lib/ai-script-base.sh
32
+ source "$SCRIPT_DIR/../lib/ai-script-base.sh"
33
+ else
34
+ echo "Error: Shared library not found at $SCRIPT_DIR/../lib/ai-script-base.sh"
35
+ exit 1
36
+ fi
37
+
38
+ # Show help
39
+ show_help() {
40
+ cat << EOF
41
+ Local AI Code Review - Offline code reviews using Ollama
42
+
43
+ USAGE:
44
+ bin/ai-review-local [OPTIONS] [BASE_BRANCH] [OLLAMA_URL]
45
+ bin/ai-review-local --help | -h
46
+
47
+ OPTIONS:
48
+ -m, --model MODEL Specify the model to use (default: codestral:latest)
49
+ -i, --interactive Interactively select model from available models
50
+ -f, --full-review Review all tracked files in current branch (no comparison)
51
+ --help, -h Show this help message
52
+
53
+ ARGUMENTS:
54
+ BASE_BRANCH Branch to compare against (default: auto-detect main/master)
55
+ Ignored when using -f/--full-review
56
+ OLLAMA_URL Ollama server URL (default: \$OLLAMA_URL env var or http://localhost:11434)
57
+
58
+ EXAMPLES:
59
+ # Compare current branch to main
60
+ bin/ai-review-local
61
+
62
+ # Compare to develop branch
63
+ bin/ai-review-local develop
64
+
65
+ # Use remote Ollama server
66
+ bin/ai-review-local main http://server:11434
67
+
68
+ # Interactively select model
69
+ bin/ai-review-local -i
70
+
71
+ # Use specific model
72
+ bin/ai-review-local -m llama3:latest
73
+
74
+ # Review entire current branch (useful for main branch review)
75
+ bin/ai-review-local -f
76
+
77
+ # Combine options
78
+ bin/ai-review-local -m mistral:latest develop
79
+
80
+ # Show help
81
+ bin/ai-review-local --help
82
+
83
+ REQUIREMENTS:
84
+ - Ollama installed and running (https://ollama.ai)
85
+ - At least one model pulled (e.g., ollama pull codestral:latest)
86
+ - Git repository with commits to review
87
+
88
+ ENVIRONMENT VARIABLES:
89
+ OLLAMA_URL Ollama server URL (overridden by command line argument)
90
+ Example: export OLLAMA_URL=http://192.168.1.100:11434
91
+
92
+ OUTPUT:
93
+ Reviews are saved to: docs/ai-reviews/ai-review-YYYYMMDD-HHMMSS.md
94
+
95
+ MORE INFO:
96
+ See docs/AI_PR_REVIEWER.md for full documentation
97
+ EOF
98
+ exit 0
99
+ }
100
+
101
+ # Parse options
102
+ INTERACTIVE_MODE=false
103
+ FULL_REVIEW=false
104
+ MODEL_NAME="codestral:latest"
105
+ BASE_BRANCH=""
106
+ OLLAMA_URL=""
107
+
108
+ while [[ $# -gt 0 ]]; do
109
+ case $1 in
110
+ --help|-h)
111
+ show_help
112
+ ;;
113
+ -i|--interactive)
114
+ INTERACTIVE_MODE=true
115
+ shift
116
+ ;;
117
+ -f|--full-review)
118
+ FULL_REVIEW=true
119
+ shift
120
+ ;;
121
+ -m|--model)
122
+ if [ -z "${2:-}" ]; then
123
+ log_error "Option -m/--model requires a model name"
124
+ exit 1
125
+ fi
126
+ MODEL_NAME="$2"
127
+ shift 2
128
+ ;;
129
+ *)
130
+ # Positional arguments
131
+ if [ -z "$BASE_BRANCH" ]; then
132
+ BASE_BRANCH="$1"
133
+ elif [ -z "$OLLAMA_URL" ]; then
134
+ OLLAMA_URL="$1"
135
+ else
136
+ log_error "Unknown argument: $1"
137
+ echo "Run 'bin/ai-review-local --help' for usage information"
138
+ exit 1
139
+ fi
140
+ shift
141
+ ;;
142
+ esac
143
+ done
144
+
145
+ # Set defaults for positional arguments
146
+ OLLAMA_URL=$(get_ollama_url "$OLLAMA_URL")
147
+ if [ "$FULL_REVIEW" = false ]; then
148
+ BASE_BRANCH=$(determine_base_branch "$BASE_BRANCH")
149
+ fi
150
+
151
+ # Create temp directory
152
+ TEMP_DIR=$(create_temp_dir)
153
+
154
+ log_info "Starting AI code review..."
155
+ if [ "$FULL_REVIEW" = true ]; then
156
+ log_info "Mode: ${CYAN}Full review (all tracked files)${NC}"
157
+ else
158
+ log_info "Base branch: ${CYAN}$BASE_BRANCH${NC}"
159
+ fi
160
+ log_info "Ollama server: ${CYAN}$OLLAMA_URL${NC}"
161
+ echo ""
162
+
163
+ # Check if Ollama is accessible
164
+ check_ollama_server "$OLLAMA_URL" || exit 1
165
+ echo ""
166
+
167
+ # Interactive model selection if requested
168
+ if [ "$INTERACTIVE_MODE" = true ]; then
169
+ MODEL_NAME=$(select_ollama_model "$OLLAMA_URL" "$MODEL_NAME")
170
+ echo ""
171
+ log_info "Selected model: ${CYAN}$MODEL_NAME${NC}"
172
+ echo ""
173
+ fi
174
+
175
+ # Ensure model is available
176
+ ensure_ollama_model "$OLLAMA_URL" "$MODEL_NAME" || exit 1
177
+ echo ""
178
+
179
+ # Get current branch name
180
+ CURRENT_BRANCH=$(get_current_branch)
181
+ log_info "Current branch: ${CYAN}$CURRENT_BRANCH${NC}"
182
+
183
+ # Get content based on review mode
184
+ if [ "$FULL_REVIEW" = true ]; then
185
+ # Full review: get important files from current branch
186
+ log_info "Getting tracked files for full review..."
187
+
188
+ # Get list of key files (exclude tests, vendor, node_modules, etc.)
189
+ CHANGED_FILES=$(git ls-files | grep -E '\.(rb|yml|yaml|js|css|erb|rake)$' | \
190
+ grep -v -E '^(test/|spec/|vendor/|node_modules/|tmp/|log/)' | \
191
+ head -50)
192
+ CHANGED_FILES_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ')
193
+
194
+ log_success "Found $CHANGED_FILES_COUNT files to review"
195
+
196
+ # Build a summary diff from key files (first 100 lines of each)
197
+ log_info "Building file summaries..."
198
+ DIFF=""
199
+ for file in $CHANGED_FILES; do
200
+ if [ -f "$file" ]; then
201
+ DIFF+="
202
+ === $file ===
203
+ $(head -100 "$file")
204
+ "
205
+ fi
206
+ done
207
+
208
+ DIFF_LENGTH=${#DIFF}
209
+ DIFF=$(truncate_diff "$DIFF" 15000)
210
+ log_success "File summaries generated (${DIFF_LENGTH} chars)"
211
+
212
+ COMMIT_MESSAGES="Full review mode - reviewing current state of $CURRENT_BRANCH"
213
+ echo ""
214
+ else
215
+ # Comparison mode: get diff
216
+ # Get the diff
217
+ DIFF=$(get_branch_diff "$BASE_BRANCH")
218
+
219
+ # Filter out ignored sections
220
+ DIFF=$(filter_ignored_sections "$DIFF")
221
+
222
+ # Truncate if too large
223
+ DIFF_LENGTH=${#DIFF}
224
+ DIFF=$(truncate_diff "$DIFF" 15000)
225
+
226
+ log_success "Diff generated (${DIFF_LENGTH} chars)"
227
+ echo ""
228
+
229
+ # Get changed files list
230
+ log_info "Getting changed files..."
231
+ CHANGED_FILES=$(get_changed_files "$BASE_BRANCH")
232
+ CHANGED_FILES_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ')
233
+ log_success "Found $CHANGED_FILES_COUNT changed files"
234
+ echo ""
235
+
236
+ # Get commit messages
237
+ log_info "Getting commit messages..."
238
+ COMMIT_MESSAGES=$(get_commit_messages "$BASE_BRANCH")
239
+ echo ""
240
+ fi
241
+
242
+ # Build system prompt using shared script
243
+ log_info "Building system prompt..."
244
+ SYSTEM_PROMPT=$(build_system_prompt)
245
+ log_success "System prompt built"
246
+ echo ""
247
+
248
+ # Extract CLAUDE.md sections
249
+ log_info "Extracting project guidelines..."
250
+ CLAUDE_MD=$(extract_claude_sections)
251
+ if [ -n "$CLAUDE_MD" ]; then
252
+ log_success "Guidelines extracted"
253
+ else
254
+ log_warning "Guidelines not found, proceeding without them"
255
+ fi
256
+ echo ""
257
+
258
+ # Build user prompt
259
+ log_info "Building review prompt..."
260
+ if [ "$FULL_REVIEW" = true ]; then
261
+ cat > "$TEMP_DIR/user.txt" <<USEREND
262
+ **Branch:** $CURRENT_BRANCH (full review - all key files)
263
+
264
+ **Review Mode:** Full codebase review
265
+
266
+ **Files Reviewed:**
267
+ $CHANGED_FILES
268
+
269
+ **File Contents (first 100 lines each):**
270
+ \`\`\`
271
+ $DIFF
272
+ \`\`\`
273
+
274
+ **Focus Areas:**
275
+ - Overall code quality and patterns
276
+ - Security best practices
277
+ - Rails conventions
278
+ - Potential improvements
279
+ USEREND
280
+ else
281
+ cat > "$TEMP_DIR/user.txt" <<USEREND
282
+ **Branch:** $CURRENT_BRANCH (comparing against $BASE_BRANCH)
283
+
284
+ **Commits:**
285
+ $COMMIT_MESSAGES
286
+
287
+ **Changed Files:**
288
+ $CHANGED_FILES
289
+
290
+ **Diff:**
291
+ \`\`\`diff
292
+ $DIFF
293
+ \`\`\`
294
+ USEREND
295
+ fi
296
+
297
+ if [ -n "$CLAUDE_MD" ]; then
298
+ cat >> "$TEMP_DIR/user.txt" <<USEREND
299
+
300
+ **Project Guidelines (CLAUDE.md):**
301
+ $CLAUDE_MD
302
+ USEREND
303
+ fi
304
+
305
+ USER_PROMPT=$(cat "$TEMP_DIR/user.txt")
306
+ log_success "Review prompt built"
307
+ echo ""
308
+
309
+ # Call Ollama API
310
+ log_info "Calling Ollama API for review..."
311
+ echo -e "${CYAN}This may take a minute or two...${NC}"
312
+ echo ""
313
+
314
+ REVIEW=$(call_ollama_chat "$OLLAMA_URL" "$MODEL_NAME" "$SYSTEM_PROMPT" "$USER_PROMPT")
315
+
316
+ # Smart deduplication
317
+ REVIEW=$(deduplicate_review "$REVIEW")
318
+
319
+ # Truncate if too long
320
+ REVIEW=$(truncate_review "$REVIEW" 100)
321
+
322
+ # Display the review
323
+ if [ "$FULL_REVIEW" = true ]; then
324
+ ADDITIONAL_INFO="${CYAN}Branch:${NC} $CURRENT_BRANCH (full review)
325
+ ${CYAN}Files reviewed:${NC} $CHANGED_FILES_COUNT
326
+ ${CYAN}Content size:${NC} $DIFF_LENGTH chars"
327
+ else
328
+ ADDITIONAL_INFO="${CYAN}Branch:${NC} $CURRENT_BRANCH (compared to $BASE_BRANCH)
329
+ ${CYAN}Changed files:${NC} $CHANGED_FILES_COUNT
330
+ ${CYAN}Diff size:${NC} $DIFF_LENGTH chars"
331
+ fi
332
+
333
+ display_review "$REVIEW" "AI Code Review - Local" "$MODEL_NAME" "$ADDITIONAL_INFO"
334
+
335
+ # Save review to file
336
+ REVIEW_FILE=$(save_review "$REVIEW" "docs/ai-reviews" "ai-review")
337
+ log_success "Review saved to: ${CYAN}$REVIEW_FILE${NC}"
338
+ echo ""
339
+
340
+ # Check for critical issues
341
+ if check_critical_issues "$REVIEW"; then
342
+ exit 0
343
+ else
344
+ exit 1
345
+ fi