agent-notes 2.0.4__py3-none-any.whl

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 (162) hide show
  1. agent_notes/VERSION +1 -0
  2. agent_notes/__init__.py +1 -0
  3. agent_notes/__main__.py +4 -0
  4. agent_notes/cli.py +348 -0
  5. agent_notes/commands/__init__.py +27 -0
  6. agent_notes/commands/_install_helpers.py +262 -0
  7. agent_notes/commands/build.py +170 -0
  8. agent_notes/commands/doctor.py +112 -0
  9. agent_notes/commands/info.py +95 -0
  10. agent_notes/commands/install.py +99 -0
  11. agent_notes/commands/list.py +169 -0
  12. agent_notes/commands/memory.py +430 -0
  13. agent_notes/commands/regenerate.py +152 -0
  14. agent_notes/commands/set_role.py +143 -0
  15. agent_notes/commands/uninstall.py +26 -0
  16. agent_notes/commands/update.py +169 -0
  17. agent_notes/commands/validate.py +199 -0
  18. agent_notes/commands/wizard.py +720 -0
  19. agent_notes/config.py +154 -0
  20. agent_notes/data/agents/agents.yaml +352 -0
  21. agent_notes/data/agents/analyst.md +45 -0
  22. agent_notes/data/agents/api-reviewer.md +47 -0
  23. agent_notes/data/agents/architect.md +46 -0
  24. agent_notes/data/agents/coder.md +28 -0
  25. agent_notes/data/agents/database-specialist.md +45 -0
  26. agent_notes/data/agents/debugger.md +47 -0
  27. agent_notes/data/agents/devil.md +47 -0
  28. agent_notes/data/agents/devops.md +38 -0
  29. agent_notes/data/agents/explorer.md +23 -0
  30. agent_notes/data/agents/integrations.md +44 -0
  31. agent_notes/data/agents/lead.md +216 -0
  32. agent_notes/data/agents/performance-profiler.md +44 -0
  33. agent_notes/data/agents/refactorer.md +48 -0
  34. agent_notes/data/agents/reviewer.md +44 -0
  35. agent_notes/data/agents/security-auditor.md +44 -0
  36. agent_notes/data/agents/system-auditor.md +38 -0
  37. agent_notes/data/agents/tech-writer.md +32 -0
  38. agent_notes/data/agents/test-runner.md +36 -0
  39. agent_notes/data/agents/test-writer.md +39 -0
  40. agent_notes/data/cli/claude.yaml +25 -0
  41. agent_notes/data/cli/copilot.yaml +18 -0
  42. agent_notes/data/cli/opencode.yaml +22 -0
  43. agent_notes/data/commands/brainstorm.md +8 -0
  44. agent_notes/data/commands/debug.md +9 -0
  45. agent_notes/data/commands/review.md +10 -0
  46. agent_notes/data/global-claude.md +290 -0
  47. agent_notes/data/global-copilot.md +27 -0
  48. agent_notes/data/global-opencode.md +40 -0
  49. agent_notes/data/hooks/session-context.md.tpl +19 -0
  50. agent_notes/data/models/claude-haiku-4-5.yaml +15 -0
  51. agent_notes/data/models/claude-opus-4-1.yaml +16 -0
  52. agent_notes/data/models/claude-opus-4-5.yaml +16 -0
  53. agent_notes/data/models/claude-opus-4-6.yaml +16 -0
  54. agent_notes/data/models/claude-opus-4-7.yaml +15 -0
  55. agent_notes/data/models/claude-sonnet-4-5.yaml +16 -0
  56. agent_notes/data/models/claude-sonnet-4-6.yaml +15 -0
  57. agent_notes/data/models/claude-sonnet-4.yaml +16 -0
  58. agent_notes/data/pricing.yaml +33 -0
  59. agent_notes/data/roles/orchestrator.yaml +5 -0
  60. agent_notes/data/roles/reasoner.yaml +5 -0
  61. agent_notes/data/roles/scout.yaml +5 -0
  62. agent_notes/data/roles/worker.yaml +5 -0
  63. agent_notes/data/rules/code-quality.md +9 -0
  64. agent_notes/data/rules/safety.md +10 -0
  65. agent_notes/data/scripts/cost-report +211 -0
  66. agent_notes/data/skills/brainstorming/SKILL.md +57 -0
  67. agent_notes/data/skills/code-review/SKILL.md +64 -0
  68. agent_notes/data/skills/debugging-protocol/SKILL.md +51 -0
  69. agent_notes/data/skills/docker-compose/SKILL.md +318 -0
  70. agent_notes/data/skills/docker-compose-advanced/SKILL.md +575 -0
  71. agent_notes/data/skills/docker-dockerfile/SKILL.md +385 -0
  72. agent_notes/data/skills/docker-dockerfile-languages/SKILL.md +293 -0
  73. agent_notes/data/skills/git/SKILL.md +87 -0
  74. agent_notes/data/skills/rails-active-storage/SKILL.md +321 -0
  75. agent_notes/data/skills/rails-broadcasting/SKILL.md +374 -0
  76. agent_notes/data/skills/rails-concerns/SKILL.md +806 -0
  77. agent_notes/data/skills/rails-controllers/SKILL.md +510 -0
  78. agent_notes/data/skills/rails-controllers-advanced/SKILL.md +441 -0
  79. agent_notes/data/skills/rails-helpers/SKILL.md +677 -0
  80. agent_notes/data/skills/rails-initializers/SKILL.md +79 -0
  81. agent_notes/data/skills/rails-javascript/SKILL.md +567 -0
  82. agent_notes/data/skills/rails-jobs/SKILL.md +700 -0
  83. agent_notes/data/skills/rails-kamal/SKILL.md +483 -0
  84. agent_notes/data/skills/rails-lib/SKILL.md +101 -0
  85. agent_notes/data/skills/rails-mailers/SKILL.md +321 -0
  86. agent_notes/data/skills/rails-migrations/SKILL.md +268 -0
  87. agent_notes/data/skills/rails-models/SKILL.md +459 -0
  88. agent_notes/data/skills/rails-models-advanced/SKILL.md +398 -0
  89. agent_notes/data/skills/rails-routes/SKILL.md +804 -0
  90. agent_notes/data/skills/rails-style/SKILL.md +538 -0
  91. agent_notes/data/skills/rails-testing-controllers/SKILL.md +343 -0
  92. agent_notes/data/skills/rails-testing-models/SKILL.md +296 -0
  93. agent_notes/data/skills/rails-testing-system/SKILL.md +375 -0
  94. agent_notes/data/skills/rails-validations/SKILL.md +108 -0
  95. agent_notes/data/skills/rails-view-components/SKILL.md +511 -0
  96. agent_notes/data/skills/rails-view-components-advanced/SKILL.md +376 -0
  97. agent_notes/data/skills/rails-views/SKILL.md +413 -0
  98. agent_notes/data/skills/rails-views-advanced/SKILL.md +450 -0
  99. agent_notes/data/skills/refactoring-protocol/SKILL.md +64 -0
  100. agent_notes/data/skills/tdd/SKILL.md +57 -0
  101. agent_notes/data/templates/__init__.py +1 -0
  102. agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
  103. agent_notes/data/templates/frontmatter/__init__.py +1 -0
  104. agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
  105. agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
  106. agent_notes/data/templates/frontmatter/__pycache__/cursor.cpython-314.pyc +0 -0
  107. agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
  108. agent_notes/data/templates/frontmatter/claude.py +44 -0
  109. agent_notes/data/templates/frontmatter/opencode.py +104 -0
  110. agent_notes/doctor_checks.py +189 -0
  111. agent_notes/domain/__init__.py +17 -0
  112. agent_notes/domain/agent.py +34 -0
  113. agent_notes/domain/cli_backend.py +40 -0
  114. agent_notes/domain/diagnostics.py +29 -0
  115. agent_notes/domain/diff.py +44 -0
  116. agent_notes/domain/model.py +27 -0
  117. agent_notes/domain/role.py +13 -0
  118. agent_notes/domain/rule.py +13 -0
  119. agent_notes/domain/skill.py +15 -0
  120. agent_notes/domain/state.py +46 -0
  121. agent_notes/install_state.py +11 -0
  122. agent_notes/registries/__init__.py +16 -0
  123. agent_notes/registries/_base.py +46 -0
  124. agent_notes/registries/agent_registry.py +107 -0
  125. agent_notes/registries/cli_registry.py +89 -0
  126. agent_notes/registries/model_registry.py +85 -0
  127. agent_notes/registries/role_registry.py +64 -0
  128. agent_notes/registries/rule_registry.py +80 -0
  129. agent_notes/registries/skill_registry.py +141 -0
  130. agent_notes/services/__init__.py +8 -0
  131. agent_notes/services/diagnostics/__init__.py +47 -0
  132. agent_notes/services/diagnostics/_checks.py +272 -0
  133. agent_notes/services/diagnostics/_display.py +346 -0
  134. agent_notes/services/diagnostics/_fix.py +169 -0
  135. agent_notes/services/diff.py +349 -0
  136. agent_notes/services/fs.py +195 -0
  137. agent_notes/services/install_state_builder.py +210 -0
  138. agent_notes/services/installer.py +293 -0
  139. agent_notes/services/memory_backend.py +155 -0
  140. agent_notes/services/rendering.py +329 -0
  141. agent_notes/services/session_context.py +23 -0
  142. agent_notes/services/settings_writer.py +79 -0
  143. agent_notes/services/state_store.py +249 -0
  144. agent_notes/services/ui.py +419 -0
  145. agent_notes/services/user_config.py +62 -0
  146. agent_notes/services/validation.py +67 -0
  147. agent_notes/state.py +21 -0
  148. agent_notes-2.0.4.dist-info/METADATA +14 -0
  149. agent_notes-2.0.4.dist-info/RECORD +162 -0
  150. agent_notes-2.0.4.dist-info/WHEEL +5 -0
  151. agent_notes-2.0.4.dist-info/entry_points.txt +2 -0
  152. agent_notes-2.0.4.dist-info/licenses/LICENSE +21 -0
  153. agent_notes-2.0.4.dist-info/top_level.txt +2 -0
  154. tests/conftest.py +20 -0
  155. tests/functional/__init__.py +0 -0
  156. tests/functional/test_build_commands.py +88 -0
  157. tests/functional/test_registries.py +128 -0
  158. tests/integration/__init__.py +0 -0
  159. tests/integration/test_build_output.py +129 -0
  160. tests/plugins/__init__.py +0 -0
  161. tests/plugins/test_agents.py +93 -0
  162. tests/plugins/test_skills.py +77 -0
@@ -0,0 +1,538 @@
1
+ ---
2
+ name: rails-style
3
+ description: "Rails code style: conditionals, method ordering, bang methods, visibility, and naming conventions"
4
+ group: rails
5
+ ---
6
+
7
+ # Code Style Guide
8
+
9
+ Comprehensive guide for Rails code style and conventions.
10
+
11
+ > **Note**: This guide represents opinionated coding style based on Basecamp/37signals practices. While strongly aligned with Rails philosophy and conventions, some preferences (such as favoring expanded conditionals over guard clauses, and the `_later`/`_now` naming pattern) differ from broader Rails community norms. These are battle-tested patterns from production codebases, not universal standards. Adapt these guidelines to match your team's preferences and project needs.
12
+
13
+ ---
14
+
15
+ ## Philosophy
16
+
17
+ Write code that is a pleasure to read. Code style matters because:
18
+ - **Readability** - Code is read more often than written
19
+ - **Consistency** - Predictable patterns reduce cognitive load
20
+ - **Maintainability** - Clear code is easier to modify
21
+ - **Collaboration** - Shared conventions improve team velocity
22
+
23
+ ---
24
+
25
+ ## Conditional Returns
26
+
27
+ ### Prefer Expanded Conditionals
28
+
29
+ **Prefer expanded if/else over guard clauses:**
30
+
31
+ ```ruby
32
+ # ❌ Bad - Guard clause
33
+ def todos_for_new_group
34
+ ids = params.require(:todolist)[:todo_ids]
35
+ return [] unless ids
36
+ @bucket.recordings.todos.find(ids.split(","))
37
+ end
38
+
39
+ # ✅ Good - Expanded conditional
40
+ def todos_for_new_group
41
+ if ids = params.require(:todolist)[:todo_ids]
42
+ @bucket.recordings.todos.find(ids.split(","))
43
+ else
44
+ []
45
+ end
46
+ end
47
+ ```
48
+
49
+ **Why:** Guard clauses can be hard to read, especially when nested.
50
+
51
+ ### Exception: Early Returns
52
+
53
+ Guard clauses are acceptable when:
54
+ 1. The return is right at the beginning of the method
55
+ 2. The main method body is non-trivial (several lines)
56
+
57
+ ```ruby
58
+ # ✅ Acceptable - Early return for clarity
59
+ def after_recorded_as_commit(recording)
60
+ return if recording.parent.was_created?
61
+
62
+ if recording.was_created?
63
+ broadcast_new_column(recording)
64
+ else
65
+ broadcast_column_change(recording)
66
+ end
67
+ end
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Methods Ordering
73
+
74
+ ### Class-Level Organization
75
+
76
+ Order methods in classes:
77
+
78
+ 1. **Class methods**
79
+ 2. **Public methods** (with `initialize` first if present)
80
+ 3. **Private methods**
81
+
82
+ ```ruby
83
+ class Card < ApplicationRecord
84
+ # 1. Class methods
85
+ def self.find_stale
86
+ where(last_active_at: ..1.month.ago)
87
+ end
88
+
89
+ # 2. Public methods
90
+ def initialize(*args)
91
+ super
92
+ @initialized = true
93
+ end
94
+
95
+ def close
96
+ create_closure!
97
+ end
98
+
99
+ def reopen
100
+ closure.destroy
101
+ end
102
+
103
+ # 3. Private methods
104
+ private
105
+ def validate_state
106
+ # ...
107
+ end
108
+ end
109
+ ```
110
+
111
+ ### Invocation Order (Vertical Reading)
112
+
113
+ Order methods based on their invocation order. This helps understand code flow:
114
+
115
+ ```ruby
116
+ class SomeClass
117
+ def process
118
+ step_one
119
+ step_two
120
+ end
121
+
122
+ private
123
+ # Step one and its sub-methods
124
+ def step_one
125
+ step_one_a
126
+ step_one_b
127
+ end
128
+
129
+ def step_one_a
130
+ # Implementation
131
+ end
132
+
133
+ def step_one_b
134
+ # Implementation
135
+ end
136
+
137
+ # Step two and its sub-methods
138
+ def step_two
139
+ step_two_a
140
+ step_two_b
141
+ end
142
+
143
+ def step_two_a
144
+ # Implementation
145
+ end
146
+
147
+ def step_two_b
148
+ # Implementation
149
+ end
150
+ end
151
+ ```
152
+
153
+ **Why:** Reading top-to-bottom mirrors execution flow.
154
+
155
+ ---
156
+
157
+ ## Bang Methods (!)
158
+
159
+ ### Only Use ! When Non-Bang Version Exists
160
+
161
+ **Rule:** Only use `!` for methods that have a corresponding version without `!`.
162
+
163
+ ```ruby
164
+ # ✅ Good - Has save counterpart
165
+ def save!
166
+ raise unless save
167
+ end
168
+
169
+ # ❌ Bad - No close counterpart
170
+ def close!
171
+ create_closure!
172
+ end
173
+
174
+ # ✅ Good - Just use close
175
+ def close
176
+ create_closure!
177
+ end
178
+ ```
179
+
180
+ **Why:** We don't use `!` to flag destructive actions. Many destructive methods in Ruby and Rails don't end with `!` (`destroy`, `delete`, `update`, etc.).
181
+
182
+ **Examples of correct usage:**
183
+ - `save` / `save!`
184
+ - `create` / `create!`
185
+ - `update` / `update!`
186
+ - `destroy` / `destroy!`
187
+
188
+ ---
189
+
190
+ ## Visibility Modifiers
191
+
192
+ ### No Newline Under Modifier, Indent Content
193
+
194
+ ```ruby
195
+ # ✅ Good
196
+ class SomeClass
197
+ def public_method
198
+ # Implementation
199
+ end
200
+
201
+ private
202
+ def private_method_1
203
+ # Implementation
204
+ end
205
+
206
+ def private_method_2
207
+ # Implementation
208
+ end
209
+ end
210
+ ```
211
+
212
+ ```ruby
213
+ # ❌ Bad - Extra newline, no indentation
214
+ class SomeClass
215
+ def public_method
216
+ end
217
+
218
+ private
219
+
220
+ def private_method
221
+ end
222
+ end
223
+ ```
224
+
225
+ ### Module with Only Private Methods
226
+
227
+ If a module has only private methods, mark `private` at the top with an extra newline but don't indent:
228
+
229
+ ```ruby
230
+ # ✅ Good - Module with only private methods
231
+ module SomeModule
232
+ private
233
+
234
+ def some_private_method
235
+ # Implementation
236
+ end
237
+
238
+ def another_private_method
239
+ # Implementation
240
+ end
241
+ end
242
+ ```
243
+
244
+ ---
245
+
246
+ ## CRUD Controllers
247
+
248
+ ### Model Actions as Resources
249
+
250
+ Model web endpoints as CRUD operations on resources (REST). When an action doesn't map to a standard CRUD verb, introduce a new resource:
251
+
252
+ ```ruby
253
+ # ❌ Bad - Custom actions
254
+ resources :cards do
255
+ post :close
256
+ post :reopen
257
+ post :gild
258
+ end
259
+
260
+ # ✅ Good - Actions as resources
261
+ resources :cards do
262
+ resource :closure # POST = close, DELETE = reopen
263
+ resource :goldness # POST = gild, DELETE = ungild
264
+ end
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Controller and Model Interactions
270
+
271
+ ### Vanilla Rails Approach
272
+
273
+ Favor thin controllers directly invoking a rich domain model. Don't use services or other artifacts to connect the two unless necessary.
274
+
275
+ ### Simple Operations
276
+
277
+ Invoking plain Active Record operations is totally fine:
278
+
279
+ ```ruby
280
+ # ✅ Good - Direct Active Record
281
+ class Cards::CommentsController < ApplicationController
282
+ def create
283
+ @comment = @card.comments.create!(comment_params)
284
+ end
285
+ end
286
+ ```
287
+
288
+ ### Complex Operations
289
+
290
+ For complex behavior, prefer clear, intention-revealing model APIs:
291
+
292
+ ```ruby
293
+ # ✅ Good - Intention-revealing model method
294
+ class Cards::GoldnessesController < ApplicationController
295
+ def create
296
+ @card.gild
297
+ end
298
+ end
299
+
300
+ # In model
301
+ class Card < ApplicationRecord
302
+ def gild
303
+ transaction do
304
+ create_goldness!
305
+ track_event :gilded
306
+ end
307
+ end
308
+ end
309
+ ```
310
+
311
+ ### Services (When Justified)
312
+
313
+ When justified, it's fine to use services or form objects, but don't treat them as special artifacts:
314
+
315
+ ```ruby
316
+ # ✅ Acceptable when complexity warrants it
317
+ class SignupsController < ApplicationController
318
+ def create
319
+ Signup.new(email_address: params[:email]).create_identity
320
+ end
321
+ end
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Async Operations in Jobs
327
+
328
+ ### Shallow Jobs That Delegate
329
+
330
+ Write shallow job classes that delegate logic to domain models:
331
+
332
+ **Naming convention:**
333
+ - Use `_later` suffix for methods that enqueue a job
334
+ - Use `_now` suffix for the synchronous version
335
+
336
+ ```ruby
337
+ # Model concern
338
+ module Event::Relaying
339
+ extend ActiveSupport::Concern
340
+
341
+ included do
342
+ after_create_commit :relay_later
343
+ end
344
+
345
+ def relay_later
346
+ Event::RelayJob.perform_later(self)
347
+ end
348
+
349
+ def relay_now
350
+ webhooks.active.each { |webhook| webhook.trigger(self) }
351
+ end
352
+ end
353
+
354
+ # Job delegates to model
355
+ class Event::RelayJob < ApplicationJob
356
+ def perform(event)
357
+ event.relay_now
358
+ end
359
+ end
360
+ ```
361
+
362
+ **Why:** Keeps jobs thin and testable. Business logic stays in models.
363
+
364
+ ---
365
+
366
+ ## General Code Style
367
+
368
+ ### Whitespace
369
+
370
+ ```ruby
371
+ # ✅ Good - One space around operators
372
+ x = 1 + 2
373
+ hash = { key: value }
374
+ array = [1, 2, 3]
375
+
376
+ # ❌ Bad
377
+ x=1+2
378
+ hash={key:value}
379
+ ```
380
+
381
+ ### Line Length
382
+
383
+ - Keep lines under 120 characters when possible
384
+ - Break long lines logically
385
+
386
+ ```ruby
387
+ # ✅ Good - Broken at logical points
388
+ User.where(active: true)
389
+ .where(verified: true)
390
+ .order(created_at: :desc)
391
+
392
+ # ❌ Bad - One long line
393
+ User.where(active: true).where(verified: true).order(created_at: :desc).limit(10).offset(20)
394
+ ```
395
+
396
+ ### String Literals
397
+
398
+ ```ruby
399
+ # ✅ Prefer double quotes for strings
400
+ message = "Hello, world!"
401
+
402
+ # ✅ Single quotes for strings that don't need interpolation or escaping
403
+ sql = 'SELECT * FROM users WHERE id = ?'
404
+ ```
405
+
406
+ ### Hash Syntax
407
+
408
+ ```ruby
409
+ # ✅ Good - New hash syntax for symbol keys
410
+ user = { name: "Alice", email: "alice@example.com" }
411
+
412
+ # ✅ Old syntax when keys are not symbols
413
+ config = { "Content-Type" => "application/json" }
414
+ ```
415
+
416
+ ---
417
+
418
+ ## Code Organization Principles
419
+
420
+ ### 1. Extract Complex Conditionals
421
+
422
+ ```ruby
423
+ # ❌ Bad - Complex inline conditional
424
+ if user.admin? && (user.verified? || user.trusted?) && user.active?
425
+ grant_access
426
+ end
427
+
428
+ # ✅ Good - Extracted to method
429
+ def can_access?
430
+ user.admin? && (user.verified? || user.trusted?) && user.active?
431
+ end
432
+
433
+ if can_access?
434
+ grant_access
435
+ end
436
+
437
+ # ✅ Even better - Method on user
438
+ if user.can_access?
439
+ grant_access
440
+ end
441
+ ```
442
+
443
+ ### 2. Single Responsibility
444
+
445
+ Each method should have one clear purpose:
446
+
447
+ ```ruby
448
+ # ❌ Bad - Multiple responsibilities
449
+ def process_user
450
+ user.verify_email
451
+ user.send_welcome_email
452
+ user.subscribe_to_newsletter
453
+ user.create_default_settings
454
+ end
455
+
456
+ # ✅ Good - Separate concerns
457
+ def process_user
458
+ verify_user
459
+ welcome_user
460
+ setup_user_account
461
+ end
462
+
463
+ private
464
+ def verify_user
465
+ user.verify_email
466
+ end
467
+
468
+ def welcome_user
469
+ user.send_welcome_email
470
+ end
471
+
472
+ def setup_user_account
473
+ user.subscribe_to_newsletter
474
+ user.create_default_settings
475
+ end
476
+ ```
477
+
478
+ ### 3. Intention-Revealing Names
479
+
480
+ Use clear, descriptive names:
481
+
482
+ ```ruby
483
+ # ❌ Bad - Unclear names
484
+ def process
485
+ data = fetch
486
+ x = transform(data)
487
+ save(x)
488
+ end
489
+
490
+ # ✅ Good - Clear names
491
+ def import_users
492
+ csv_data = fetch_csv_from_api
493
+ user_records = parse_csv_to_users(csv_data)
494
+ save_users_to_database(user_records)
495
+ end
496
+ ```
497
+
498
+ ---
499
+
500
+ ## Best Practices Summary
501
+
502
+ ### ✅ DO
503
+
504
+ 1. **Expanded conditionals** over guard clauses (except early returns)
505
+ 2. **Order methods** by invocation flow
506
+ 3. **Indent under visibility modifiers** (no extra newline)
507
+ 4. **Only use !** when non-bang version exists
508
+ 5. **Model actions as resources** in routes
509
+ 6. **Thin controllers** that delegate to models
510
+ 7. **Shallow jobs** with `_later` / `_now` pattern
511
+ 8. **Intention-revealing names** for methods and variables
512
+ 9. **Extract complex conditionals** to methods
513
+ 10. **One responsibility per method**
514
+
515
+ ### ❌ DON'T
516
+
517
+ 1. **Guard clauses everywhere** - Use expanded conditionals
518
+ 2. **Random method order** - Follow invocation order
519
+ 3. **Extra newlines after private** - Keep it clean
520
+ 4. **Bang methods without counterparts** - Just use regular names
521
+ 5. **Custom controller actions** - Use resources
522
+ 6. **Fat controllers** - Delegate to models
523
+ 7. **Business logic in jobs** - Keep jobs thin
524
+ 8. **Cryptic variable names** - Be descriptive
525
+ 9. **Complex inline conditionals** - Extract to methods
526
+ 10. **Multiple responsibilities** - Keep focused
527
+
528
+ ---
529
+
530
+ ## Summary
531
+
532
+ - **Conditionals**: Expanded over guards (except early returns)
533
+ - **Methods**: Ordered by invocation, clear names
534
+ - **Visibility**: Indent under modifiers, no extra newlines
535
+ - **Bang**: Only when non-bang version exists
536
+ - **Controllers**: Thin, RESTful, resource-oriented
537
+ - **Jobs**: Shallow, delegate to models, use `_later`/`_now`
538
+ - **Organization**: Single responsibility, intention-revealing names