gempilot 0.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 (69) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/skills/using-command-kit/SKILL.md +119 -0
  3. data/.claude/skills/using-command-kit/cli-example.rb +84 -0
  4. data/.claude/skills/using-command-kit/generator-pattern.rb +62 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +281 -0
  7. data/.ruby-version +1 -0
  8. data/CLAUDE.md +45 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +140 -0
  11. data/Rakefile +44 -0
  12. data/data/templates/gem/Gemfile.erb +23 -0
  13. data/data/templates/gem/LICENSE.txt.erb +21 -0
  14. data/data/templates/gem/README.md.erb +25 -0
  15. data/data/templates/gem/Rakefile.erb +36 -0
  16. data/data/templates/gem/bin/console.erb +7 -0
  17. data/data/templates/gem/bin/setup.erb +5 -0
  18. data/data/templates/gem/dotfiles/github/workflows/ci.yml.erb +33 -0
  19. data/data/templates/gem/dotfiles/gitignore +11 -0
  20. data/data/templates/gem/dotfiles/rubocop.yml.erb +209 -0
  21. data/data/templates/gem/dotfiles/ruby-version.erb +1 -0
  22. data/data/templates/gem/exe/gem_name.erb +3 -0
  23. data/data/templates/gem/gemspec.erb +27 -0
  24. data/data/templates/gem/lib/gem_name/version.rb.erb +7 -0
  25. data/data/templates/gem/lib/gem_name.rb.erb +16 -0
  26. data/data/templates/gem/lib/gem_name_extension.rb.erb +20 -0
  27. data/data/templates/gem/rspec.erb +3 -0
  28. data/data/templates/gem/spec/gem_name_spec.rb.erb +5 -0
  29. data/data/templates/gem/spec/spec_helper.rb.erb +10 -0
  30. data/data/templates/gem/spec/zeitwerk_spec.rb.erb +5 -0
  31. data/data/templates/gem/test/gem_name_test.rb.erb +7 -0
  32. data/data/templates/gem/test/test_helper.rb.erb +7 -0
  33. data/data/templates/gem/test/zeitwerk_test.rb.erb +9 -0
  34. data/data/templates/new/.keep +0 -0
  35. data/data/templates/new/command.rb.erb +15 -0
  36. data/docs/command_kit_comparison.md +249 -0
  37. data/docs/command_kit_reference.md +517 -0
  38. data/docs/plans/2026-02-18-gempilot-add-command.md +718 -0
  39. data/docs/superpowers/plans/2026-04-01-rubocop-new-config.md +838 -0
  40. data/docs/superpowers/plans/2026-04-06-dogfood-inflectable.md +659 -0
  41. data/docs/superpowers/plans/2026-04-06-inflection-tests-and-erb-rename.md +166 -0
  42. data/docs/superpowers/plans/2026-04-06-integrate-version-tools.md +162 -0
  43. data/docs/superpowers/plans/2026-04-06-new-readme.md +185 -0
  44. data/docs/version-management-redesign.md +44 -0
  45. data/exe/gempilot +12 -0
  46. data/issues.rec +77 -0
  47. data/lib/core_ext/string/inflection_methods.rb +68 -0
  48. data/lib/core_ext/string/refinements/inflectable.rb +15 -0
  49. data/lib/gempilot/cli/command.rb +17 -0
  50. data/lib/gempilot/cli/commands/bump.rb +49 -0
  51. data/lib/gempilot/cli/commands/console.rb +38 -0
  52. data/lib/gempilot/cli/commands/create.rb +183 -0
  53. data/lib/gempilot/cli/commands/destroy.rb +136 -0
  54. data/lib/gempilot/cli/commands/new.rb +226 -0
  55. data/lib/gempilot/cli/commands/release.rb +40 -0
  56. data/lib/gempilot/cli/gem_builder.rb +105 -0
  57. data/lib/gempilot/cli/gem_context.rb +40 -0
  58. data/lib/gempilot/cli/generator.rb +90 -0
  59. data/lib/gempilot/cli.rb +19 -0
  60. data/lib/gempilot/github_release.rb +30 -0
  61. data/lib/gempilot/project/version.rb +39 -0
  62. data/lib/gempilot/project.rb +111 -0
  63. data/lib/gempilot/strict_shell.rb +18 -0
  64. data/lib/gempilot/version.rb +3 -0
  65. data/lib/gempilot/version_tag.rb +53 -0
  66. data/lib/gempilot/version_task.rb +108 -0
  67. data/lib/gempilot.rb +17 -0
  68. data/notes.md +31 -0
  69. metadata +165 -0
@@ -0,0 +1,838 @@
1
+ # RuboCop New Config Transition Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Replace the legacy rubocop config (copied from the `remap` project) with the new opinionated config from `new_rubocop.yml`, for both gempilot's own `.rubocop.yml` and the generated-gem template at `data/templates/gem/dotfiles/rubocop.yml.erb`.
6
+
7
+ **Architecture:** The new config introduces `rubocop-claude` as a plugin, enforces stricter metrics (method length, block length, ABC size), enables `Style/Documentation`, removes `frozen_string_literal` comments, and adopts pipeline-style Ruby (multiline block chains, braces for functional transforms). The template must conditionally include `rubocop-minitest` or `rubocop-rspec` cops. The project itself uses minitest, so the project config uses `rubocop-minitest`. After swapping configs, we auto-correct what we can and manually fix the rest.
8
+
9
+ **Tech Stack:** RuboCop, rubocop-claude, rubocop-performance, rubocop-minitest/rubocop-rspec
10
+
11
+ ---
12
+
13
+ ## File Map
14
+
15
+ | Action | File | Purpose |
16
+ |--------|------|---------|
17
+ | Modify | `Gemfile` | Add `rubocop-claude`, remove `rubocop-md` |
18
+ | Replace | `.rubocop.yml` | New config adapted for minitest |
19
+ | Replace | `data/templates/gem/dotfiles/rubocop.yml.erb` | New config as ERB with minitest/rspec conditionals |
20
+ | Modify | `data/templates/gem/Gemfile.erb` | Add `rubocop-claude`, remove `rubocop-md` |
21
+ | Delete | `new_rubocop.yml` | Source material, no longer needed once integrated |
22
+ | Modify | `lib/gempilot/cli/commands/bump.rb` | Fix metrics offenses, move constant above `private` |
23
+ | Modify | `lib/gempilot/cli/commands/console.rb` | Fix method length |
24
+ | Modify | `lib/gempilot/cli/commands/create.rb` | Decompose `run` method (112 lines -> extracted helpers) |
25
+ | Modify | `lib/gempilot/cli/commands/destroy.rb` | Fix method length + ABC size |
26
+ | Modify | `lib/gempilot/cli/commands/new.rb` | Fix method length + ABC size |
27
+ | Modify | `lib/gempilot/cli/generator.rb` | Fix `Style/OptionalArguments` |
28
+ | Modify | `lib/gempilot/cli.rb` | Add rdoc class documentation |
29
+ | Modify | `lib/gempilot/cli/command.rb` | Add rdoc class documentation |
30
+ | Modify | `lib/gempilot/cli/gem_context.rb` | Add rdoc module documentation |
31
+ | Modify | `lib/gempilot/cli/generator.rb` | Add rdoc module documentation |
32
+ | Modify | All `lib/gempilot/cli/commands/*.rb` | Add rdoc class documentation |
33
+ | Modify | `test/support/environment.rb` | Fix `Security/Open`, `Naming/PredicateMethod`, `Style/ItAssignment`, method length |
34
+ | Modify | `test/gempilot/cli/create_command_test.rb` | Fix test method length |
35
+ | Modify | `test/gempilot/cli/destroy_command_test.rb` | Fix test method length |
36
+
37
+ ---
38
+
39
+ ## Task 1: Update Gemfile and Install Dependencies
40
+
41
+ **Files:**
42
+ - Modify: `Gemfile`
43
+
44
+ This adds `rubocop-claude` to the project's dependencies and removes `rubocop-md` (the new config doesn't use it). The `rubocop-rake` gem stays since tests need rake tasks.
45
+
46
+ - [ ] **Step 1: Update Gemfile**
47
+
48
+ Replace the rubocop block in `Gemfile` (lines 5-9):
49
+
50
+ ```ruby
51
+ # old
52
+ gem "rubocop"
53
+ gem "rubocop-md"
54
+ gem "rubocop-minitest"
55
+ gem "rubocop-performance"
56
+ gem "rubocop-rake"
57
+ ```
58
+
59
+ with:
60
+
61
+ ```ruby
62
+ gem "rubocop"
63
+ gem "rubocop-claude"
64
+ gem "rubocop-minitest"
65
+ gem "rubocop-performance"
66
+ gem "rubocop-rake"
67
+ ```
68
+
69
+ - [ ] **Step 2: Bundle install**
70
+
71
+ Run: `bundle install`
72
+ Expected: Resolves successfully, `rubocop-claude` appears in `Gemfile.lock`.
73
+
74
+ - [ ] **Step 3: Commit**
75
+
76
+ ```bash
77
+ git add Gemfile Gemfile.lock
78
+ git commit -m "Add rubocop-claude gem, drop rubocop-md"
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Task 2: Replace Project .rubocop.yml
84
+
85
+ **Files:**
86
+ - Replace: `.rubocop.yml`
87
+
88
+ Adapt `new_rubocop.yml` for the project: swap `rubocop-rspec` for `rubocop-minitest`, replace RSpec cops with Minitest equivalents, set `TargetRubyVersion` to the system Ruby minor version, and add project-specific exclusions.
89
+
90
+ - [ ] **Step 1: Write the new `.rubocop.yml`**
91
+
92
+ ```yaml
93
+ # ===========================================================================
94
+ # RuboCop Configuration
95
+ #
96
+ # Base: Stock RuboCop defaults
97
+ # AI guardrails: rubocop-claude plugin (all Claude/ cops + stricter metrics)
98
+ # Performance: rubocop-performance (with chain-hostile cops disabled)
99
+ #
100
+ # Philosophy: idiomatic Ruby, pipeline-style chaining, strict for AI agents,
101
+ # readable for humans.
102
+ # ===========================================================================
103
+
104
+ plugins:
105
+ - rubocop-claude
106
+ - rubocop-minitest
107
+ - rubocop-performance
108
+ - rubocop-rake
109
+
110
+ AllCops:
111
+ NewCops: enable
112
+ TargetRubyVersion: 3.4
113
+ Exclude:
114
+ - bin/*
115
+ - vendor/**/*
116
+ - data/templates/**/*
117
+
118
+ # ===========================================================================
119
+ # Overrides from stock — personal style preferences
120
+ # ===========================================================================
121
+
122
+ # Double quotes everywhere. One less decision to make.
123
+ Style/StringLiterals:
124
+ EnforcedStyle: double_quotes
125
+
126
+ Style/StringLiteralsInInterpolation:
127
+ EnforcedStyle: double_quotes
128
+
129
+ # Frozen string literal is transitional cruft. Ruby 3.4 has chilled strings,
130
+ # full default freeze is coming in a future Ruby.
131
+ Style/FrozenStringLiteralComment:
132
+ EnforcedStyle: never
133
+
134
+ # Pipeline style. Chaining multi-line blocks is the whole point.
135
+ Style/MultilineBlockChain:
136
+ Enabled: false
137
+
138
+ # Block delimiters are a taste call. Pipeline code uses braces for chaining,
139
+ # do/end for side effects. No cop captures this nuance.
140
+ Style/BlockDelimiters:
141
+ Enabled: false
142
+
143
+ # Write arrays like arrays.
144
+ Style/WordArray:
145
+ Enabled: false
146
+
147
+ Style/SymbolArray:
148
+ Enabled: false
149
+
150
+ # Argument indentation: consistent 2-space indent, not aligned to first arg.
151
+ Layout/FirstArgumentIndentation:
152
+ EnforcedStyle: consistent
153
+
154
+ # Dot-aligned chaining. Dots form a visual column.
155
+ Layout/MultilineMethodCallIndentation:
156
+ EnforcedStyle: aligned
157
+
158
+ # ===========================================================================
159
+ # Overrides from rubocop-claude — loosen where pipeline style conflicts
160
+ # ===========================================================================
161
+
162
+ Claude/NoOverlyDefensiveCode:
163
+ MaxSafeNavigationChain: 2
164
+
165
+ Style/SafeNavigation:
166
+ MaxChainLength: 2
167
+
168
+ # Allow `return a, b` for tuple-style returns.
169
+ Style/RedundantReturn:
170
+ AllowMultipleReturnValues: true
171
+
172
+ # ===========================================================================
173
+ # Overrides from rubocop-performance — disable chain-hostile cops
174
+ # ===========================================================================
175
+
176
+ Performance/ChainArrayAllocation:
177
+ Enabled: false
178
+
179
+ Performance/MapMethodChain:
180
+ Enabled: false
181
+
182
+ # ===========================================================================
183
+ # Additional tightening — not set by stock or rubocop-claude
184
+ # ===========================================================================
185
+
186
+ # Short blocks push toward small chained steps instead of fat lambdas.
187
+ Metrics/BlockLength:
188
+ Max: 8
189
+ CountAsOne:
190
+ - array
191
+ - hash
192
+ - heredoc
193
+ - method_call
194
+ AllowedMethods:
195
+ - command
196
+ - describe
197
+ - context
198
+ - shared_examples
199
+ - shared_examples_for
200
+ - shared_context
201
+ Exclude:
202
+ - "test/**/*"
203
+
204
+ # Minitest tests legitimately define many assertions per test method
205
+ # when testing multi-file generators. Default is 3, too tight.
206
+ Minitest/MultipleAssertions:
207
+ Max: 10
208
+
209
+ # Anonymous forwarding (*, **, &) breaks TruffleRuby, JRuby, and
210
+ # Ruby < 3.2. Named args are explicit and portable.
211
+ Style/ArgumentsForwarding:
212
+ Enabled: false
213
+
214
+ # Explicit begin/rescue/end is clearer than implicit method-body rescue.
215
+ Style/RedundantBegin:
216
+ Enabled: false
217
+
218
+ # Classes get rdoc. Run `rake rdoc` and keep it honest.
219
+ Style/Documentation:
220
+ Enabled: true
221
+ Exclude:
222
+ - "test/**/*"
223
+
224
+ # Trailing commas in multiline literals and arguments.
225
+ Style/TrailingCommaInArrayLiteral:
226
+ EnforcedStyleForMultiline: comma
227
+
228
+ Style/TrailingCommaInHashLiteral:
229
+ EnforcedStyleForMultiline: comma
230
+
231
+ Style/TrailingCommaInArguments:
232
+ EnforcedStyleForMultiline: comma
233
+ ```
234
+
235
+ Key adaptations from `new_rubocop.yml`:
236
+ - `rubocop-rspec` -> `rubocop-minitest`
237
+ - Added `rubocop-rake` (project uses it)
238
+ - RSpec cops -> `Minitest/MultipleAssertions: Max: 10`
239
+ - `TargetRubyVersion: 3.4` (project targets 3.4, not 4.0)
240
+ - Added `Exclude: data/templates/**/*` (ERB templates aren't valid Ruby)
241
+ - Added `Exclude: test/**/*` for `Metrics/BlockLength` and `Style/Documentation`
242
+
243
+ - [ ] **Step 2: Run rubocop to verify config loads**
244
+
245
+ Run: `bundle exec rubocop --format offenses`
246
+ Expected: Config loads without errors. Offenses listed (we'll fix them in later tasks).
247
+
248
+ - [ ] **Step 3: Commit**
249
+
250
+ ```bash
251
+ git add .rubocop.yml
252
+ git commit -m "Replace legacy rubocop config with new opinionated config"
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Task 3: Auto-correct Safe Offenses
258
+
259
+ **Files:**
260
+ - All `lib/**/*.rb` and `test/**/*.rb` files
261
+
262
+ Run rubocop auto-correct to fix all the safe+unsafe correctable offenses (trailing commas, string literals, guard clauses, layout, etc.). This handles ~200 of the 280 offenses.
263
+
264
+ - [ ] **Step 1: Run auto-correct**
265
+
266
+ Run: `bundle exec rubocop -A`
267
+ Expected: Many offenses auto-corrected.
268
+
269
+ - [ ] **Step 2: Run tests to verify nothing broke**
270
+
271
+ Run: `bundle exec rake test`
272
+ Expected: All tests pass.
273
+
274
+ - [ ] **Step 3: Run rubocop to see remaining offenses**
275
+
276
+ Run: `bundle exec rubocop --format offenses`
277
+ Expected: Only non-auto-correctable offenses remain (Metrics/*, Style/Documentation, Security/Open, etc.).
278
+
279
+ - [ ] **Step 4: Commit**
280
+
281
+ ```bash
282
+ git add -A
283
+ git commit -m "Auto-correct rubocop offenses under new config"
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Task 4: Add rdoc Documentation to All Classes and Modules
289
+
290
+ **Files:**
291
+ - Modify: `lib/gempilot/cli.rb`
292
+ - Modify: `lib/gempilot/cli/command.rb`
293
+ - Modify: `lib/gempilot/cli/commands/bump.rb`
294
+ - Modify: `lib/gempilot/cli/commands/console.rb`
295
+ - Modify: `lib/gempilot/cli/commands/create.rb`
296
+ - Modify: `lib/gempilot/cli/commands/destroy.rb`
297
+ - Modify: `lib/gempilot/cli/commands/new.rb`
298
+ - Modify: `lib/gempilot/cli/commands/release.rb`
299
+ - Modify: `lib/gempilot/cli/gem_context.rb`
300
+ - Modify: `lib/gempilot/cli/generator.rb`
301
+
302
+ Add `##` rdoc blocks above every class/module that `Style/Documentation` flags. No blank line between the doc block and the `class`/`module` keyword.
303
+
304
+ - [ ] **Step 1: Read each flagged file and add documentation**
305
+
306
+ Use rdoc style (not YARD). Each doc block describes what the class/module represents:
307
+
308
+ For `lib/gempilot/cli.rb`:
309
+ ```ruby
310
+ ##
311
+ # Top-level command router for the gempilot CLI.
312
+ # Uses CommandKit::Commands::AutoLoad to map subcommands
313
+ # from the +commands/+ directory.
314
+ class CLI
315
+ ```
316
+
317
+ For `lib/gempilot/cli/command.rb`:
318
+ ```ruby
319
+ ##
320
+ # Base command class for all gempilot subcommands.
321
+ # Provides color output, interactive prompts, and bug reporting.
322
+ class Command < CommandKit::Command
323
+ ```
324
+
325
+ For `lib/gempilot/cli/commands/bump.rb`:
326
+ ```ruby
327
+ ##
328
+ # Bumps the VERSION constant in an existing gem's +version.rb+.
329
+ # Supports patch (default), minor, and major increments.
330
+ class Bump < Command
331
+ ```
332
+
333
+ For `lib/gempilot/cli/commands/console.rb`:
334
+ ```ruby
335
+ ##
336
+ # Launches an IRB session via the gem's +bin/console+ script.
337
+ class Console < Command
338
+ ```
339
+
340
+ For `lib/gempilot/cli/commands/create.rb`:
341
+ ```ruby
342
+ ##
343
+ # Scaffolds a new gem with Zeitwerk autoloading, test framework,
344
+ # RuboCop config, CI workflow, and version management rake tasks.
345
+ class Create < Command
346
+ ```
347
+
348
+ For `lib/gempilot/cli/commands/destroy.rb`:
349
+ ```ruby
350
+ ##
351
+ # Removes a class, module, or command from an existing gem,
352
+ # including its source file, test file, and empty parent directories.
353
+ class Destroy < Command
354
+ ```
355
+
356
+ For `lib/gempilot/cli/commands/new.rb`:
357
+ ```ruby
358
+ ##
359
+ # Generates a new class, module, or command inside an existing gem.
360
+ # Creates the source file with proper Zeitwerk-compatible nesting
361
+ # and a corresponding test file.
362
+ class New < Command
363
+ ```
364
+
365
+ For `lib/gempilot/cli/commands/release.rb`:
366
+ ```ruby
367
+ ##
368
+ # Delegates to +rake release+ to build and push the gem to RubyGems.
369
+ class Release < Command
370
+ ```
371
+
372
+ For `lib/gempilot/cli/gem_context.rb`:
373
+ ```ruby
374
+ ##
375
+ # Shared context for commands that operate inside an existing gem.
376
+ # Detects the gem root, parses the gemspec for gem and module names,
377
+ # and determines the active test framework.
378
+ module GemContext
379
+ ```
380
+
381
+ For `lib/gempilot/cli/generator.rb`:
382
+ ```ruby
383
+ ##
384
+ # File generation utilities for scaffolding gems and components.
385
+ # Provides +mkdir+, +touch+, +create_file+, +erb+, +sh+, and
386
+ # related helpers used by the Create and New commands.
387
+ module Generator
388
+ ```
389
+
390
+ For `lib/gempilot/cli/generator.rb` (ClassMethods):
391
+ ```ruby
392
+ ##
393
+ # Class-level helpers for Generator, including +template_dir+
394
+ # resolution.
395
+ module ClassMethods
396
+ ```
397
+
398
+ - [ ] **Step 2: Run rubocop to verify Style/Documentation is clean**
399
+
400
+ Run: `bundle exec rubocop --only Style/Documentation`
401
+ Expected: 0 offenses.
402
+
403
+ - [ ] **Step 3: Run tests**
404
+
405
+ Run: `bundle exec rake test`
406
+ Expected: All pass.
407
+
408
+ - [ ] **Step 4: Commit**
409
+
410
+ ```bash
411
+ git add lib/
412
+ git commit -m "Add rdoc documentation to all classes and modules"
413
+ ```
414
+
415
+ ---
416
+
417
+ ## Task 5: Decompose Create#run (112 lines)
418
+
419
+ **Files:**
420
+ - Modify: `lib/gempilot/cli/commands/create.rb`
421
+
422
+ The `run` method in Create is 112 lines -- the single worst offender. Extract logical sections into private helper methods. The method currently does: option collection (interactive prompts), directory creation, template rendering, git init, bundle install. Each becomes its own method.
423
+
424
+ - [ ] **Step 1: Read the current file**
425
+
426
+ Run: Read `lib/gempilot/cli/commands/create.rb`
427
+
428
+ - [ ] **Step 2: Extract helper methods**
429
+
430
+ The `run` method should become an orchestrator that calls:
431
+ - `collect_options` — interactive prompts and option resolution
432
+ - `create_directory_structure` — mkdir calls
433
+ - `render_templates` — ERB rendering calls
434
+ - `render_test_templates` — test-framework-specific templates
435
+ - `initialize_git_repo` — git init + initial commit
436
+ - `run_bundle_install` — bundler setup
437
+
438
+ Each extracted method should be under 10 lines. Keep them `private`.
439
+
440
+ - [ ] **Step 3: Run rubocop on the file**
441
+
442
+ Run: `bundle exec rubocop lib/gempilot/cli/commands/create.rb`
443
+ Expected: No Metrics/MethodLength, Metrics/AbcSize, or Metrics/ClassLength offenses.
444
+
445
+ If ClassLength (100) is still exceeded after extraction, the class likely needs a collaborator object (e.g., `Gempilot::CLI::GemScaffold` or similar). Assess and extract if needed.
446
+
447
+ - [ ] **Step 4: Run tests**
448
+
449
+ Run: `bundle exec rake test`
450
+ Expected: All pass.
451
+
452
+ - [ ] **Step 5: Commit**
453
+
454
+ ```bash
455
+ git add lib/gempilot/cli/commands/create.rb
456
+ git commit -m "Decompose Create#run into focused helper methods"
457
+ ```
458
+
459
+ ---
460
+
461
+ ## Task 6: Fix Remaining Metrics Offenses in Commands
462
+
463
+ **Files:**
464
+ - Modify: `lib/gempilot/cli/commands/bump.rb`
465
+ - Modify: `lib/gempilot/cli/commands/console.rb`
466
+ - Modify: `lib/gempilot/cli/commands/destroy.rb`
467
+ - Modify: `lib/gempilot/cli/commands/new.rb`
468
+
469
+ Each file has 1-3 methods over the 10-line or ABC-size limit. Extract small helpers.
470
+
471
+ - [ ] **Step 1: Read and fix bump.rb**
472
+
473
+ Offenses:
474
+ - `run` (14 lines, ABC 29) — extract version file discovery and version display into helpers
475
+ - `bump_version` (17 lines, ABC 17.5) — extract regex matching into a helper
476
+ - `Lint/UselessConstantScoping` — move `VERSION_PATTERN` above `private`
477
+ - `Metrics/CyclomaticComplexity` and `PerceivedComplexity` on `cli_arg_version` — simplify with a lookup hash
478
+
479
+ - [ ] **Step 2: Read and fix console.rb**
480
+
481
+ Offenses:
482
+ - `run` (11 lines, ABC 22) — minor, extract validation checks
483
+
484
+ - [ ] **Step 3: Read and fix destroy.rb**
485
+
486
+ Offenses:
487
+ - `run` (18 lines, ABC 21.7) — extract prompting and dispatch logic
488
+ - `destroy_class` (13 lines, ABC 21.5) — extract file removal logic
489
+
490
+ - [ ] **Step 4: Read and fix new.rb**
491
+
492
+ Offenses:
493
+ - `run` (18 lines, ABC 21.7) — extract prompting and dispatch logic
494
+ - `build_nested_source` (11 lines, ABC 17.8) — minor, extract if possible
495
+ - `add_class` (11 lines, ABC 25.7) — extract template rendering
496
+ - `add_module` (similar) — extract template rendering
497
+ - `add_command` (12 lines, ABC 22.8) — extract template rendering
498
+ - `add_test_file` (26 lines, ABC 20.5) — split minitest vs rspec paths
499
+
500
+ - [ ] **Step 5: Run rubocop on all command files**
501
+
502
+ Run: `bundle exec rubocop lib/gempilot/cli/commands/`
503
+ Expected: 0 Metrics offenses.
504
+
505
+ - [ ] **Step 6: Run tests**
506
+
507
+ Run: `bundle exec rake test`
508
+ Expected: All pass.
509
+
510
+ - [ ] **Step 7: Commit**
511
+
512
+ ```bash
513
+ git add lib/gempilot/cli/commands/
514
+ git commit -m "Fix metrics offenses in command classes"
515
+ ```
516
+
517
+ ---
518
+
519
+ ## Task 7: Fix Remaining Non-Metrics Offenses
520
+
521
+ **Files:**
522
+ - Modify: `lib/gempilot/cli/generator.rb` — `Style/OptionalArguments`
523
+ - Modify: `test/support/environment.rb` — `Security/Open`, `Naming/PredicateMethod`, `Style/ItAssignment`
524
+
525
+ - [ ] **Step 1: Fix generator.rb**
526
+
527
+ The `Style/OptionalArguments` offense is at line 38. An optional positional argument appears before a required one. Reorder or convert to keyword arguments.
528
+
529
+ - [ ] **Step 2: Fix test/support/environment.rb**
530
+
531
+ - `Security/Open` at line 126: Replace `open(url)` with `URI.open(url)` or `File.open(path)` as appropriate.
532
+ - `Naming/PredicateMethod` at line 226: Rename predicate method to end with `?`.
533
+ - `Style/ItAssignment` at line 89: Rename block parameter from `it` to something else.
534
+
535
+ - [ ] **Step 3: Fix test method length offenses**
536
+
537
+ Read `test/gempilot/cli/create_command_test.rb` and `test/gempilot/cli/destroy_command_test.rb`. Extract shared setup into helper methods or split long test methods into focused assertions.
538
+
539
+ - [ ] **Step 4: Run rubocop**
540
+
541
+ Run: `bundle exec rubocop`
542
+ Expected: 0 offenses, 0 errors.
543
+
544
+ - [ ] **Step 5: Run tests**
545
+
546
+ Run: `bundle exec rake test`
547
+ Expected: All pass.
548
+
549
+ - [ ] **Step 6: Commit**
550
+
551
+ ```bash
552
+ git add lib/gempilot/cli/generator.rb test/
553
+ git commit -m "Fix remaining rubocop offenses (security, naming, test length)"
554
+ ```
555
+
556
+ ---
557
+
558
+ ## Task 8: Replace Template rubocop.yml.erb
559
+
560
+ **Files:**
561
+ - Replace: `data/templates/gem/dotfiles/rubocop.yml.erb`
562
+ - Modify: `data/templates/gem/Gemfile.erb`
563
+
564
+ The template must produce a valid `.rubocop.yml` for both minitest and rspec gems. Use ERB conditionals for test-framework-specific sections.
565
+
566
+ - [ ] **Step 1: Write the new template**
567
+
568
+ ```erb
569
+ # ===========================================================================
570
+ # RuboCop Configuration
571
+ #
572
+ # Base: Stock RuboCop defaults
573
+ # AI guardrails: rubocop-claude plugin (all Claude/ cops + stricter metrics)
574
+ # Performance: rubocop-performance (with chain-hostile cops disabled)
575
+ #
576
+ # Philosophy: idiomatic Ruby, pipeline-style chaining, strict for AI agents,
577
+ # readable for humans.
578
+ # ===========================================================================
579
+
580
+ plugins:
581
+ - rubocop-claude
582
+ <% if @test_framework == :minitest -%>
583
+ - rubocop-minitest
584
+ <% elsif @test_framework == :rspec -%>
585
+ - rubocop-rspec
586
+ <% end -%>
587
+ - rubocop-performance
588
+ - rubocop-rake
589
+
590
+ AllCops:
591
+ NewCops: enable
592
+ TargetRubyVersion: <%= minor_version_for @ruby_version %>
593
+ Exclude:
594
+ - bin/*
595
+ - vendor/**/*
596
+ <% if @hyphenated -%>
597
+ - lib/<%= @gem_name %>.rb
598
+ <% end -%>
599
+
600
+ # ===========================================================================
601
+ # Overrides from stock — personal style preferences
602
+ # ===========================================================================
603
+
604
+ # Double quotes everywhere. One less decision to make.
605
+ Style/StringLiterals:
606
+ EnforcedStyle: double_quotes
607
+
608
+ Style/StringLiteralsInInterpolation:
609
+ EnforcedStyle: double_quotes
610
+
611
+ # Frozen string literal is transitional cruft. Ruby 3.4 has chilled strings,
612
+ # full default freeze is coming in a future Ruby.
613
+ Style/FrozenStringLiteralComment:
614
+ EnforcedStyle: never
615
+
616
+ # Pipeline style. Chaining multi-line blocks is the whole point.
617
+ Style/MultilineBlockChain:
618
+ Enabled: false
619
+
620
+ # Block delimiters are a taste call. Pipeline code uses braces for chaining,
621
+ # do/end for side effects. No cop captures this nuance.
622
+ Style/BlockDelimiters:
623
+ Enabled: false
624
+
625
+ # Write arrays like arrays.
626
+ Style/WordArray:
627
+ Enabled: false
628
+
629
+ Style/SymbolArray:
630
+ Enabled: false
631
+
632
+ # Argument indentation: consistent 2-space indent, not aligned to first arg.
633
+ Layout/FirstArgumentIndentation:
634
+ EnforcedStyle: consistent
635
+
636
+ # Dot-aligned chaining. Dots form a visual column.
637
+ Layout/MultilineMethodCallIndentation:
638
+ EnforcedStyle: aligned
639
+
640
+ # ===========================================================================
641
+ # Overrides from rubocop-claude — loosen where pipeline style conflicts
642
+ # ===========================================================================
643
+
644
+ Claude/NoOverlyDefensiveCode:
645
+ MaxSafeNavigationChain: 2
646
+
647
+ Style/SafeNavigation:
648
+ MaxChainLength: 2
649
+
650
+ # Allow `return a, b` for tuple-style returns.
651
+ Style/RedundantReturn:
652
+ AllowMultipleReturnValues: true
653
+
654
+ # ===========================================================================
655
+ # Overrides from rubocop-performance — disable chain-hostile cops
656
+ # ===========================================================================
657
+
658
+ Performance/ChainArrayAllocation:
659
+ Enabled: false
660
+
661
+ Performance/MapMethodChain:
662
+ Enabled: false
663
+
664
+ # ===========================================================================
665
+ # Additional tightening — not set by stock or rubocop-claude
666
+ # ===========================================================================
667
+
668
+ # Short blocks push toward small chained steps instead of fat lambdas.
669
+ Metrics/BlockLength:
670
+ Max: 8
671
+ CountAsOne:
672
+ - array
673
+ - hash
674
+ - heredoc
675
+ - method_call
676
+ AllowedMethods:
677
+ - command
678
+ <% if @test_framework == :minitest -%>
679
+ - test
680
+ <% elsif @test_framework == :rspec -%>
681
+ - describe
682
+ - context
683
+ - shared_examples
684
+ - shared_examples_for
685
+ - shared_context
686
+ <% end -%>
687
+
688
+ <% if @test_framework == :minitest -%>
689
+ # Minitest tests can legitimately need many assertions per method
690
+ # when verifying multi-step operations.
691
+ Minitest/MultipleAssertions:
692
+ Max: 10
693
+ <% elsif @test_framework == :rspec -%>
694
+ # Shared test contexts legitimately define many helpers.
695
+ RSpec/MultipleMemoizedHelpers:
696
+ Max: 10
697
+ <% end -%>
698
+
699
+ # Anonymous forwarding (*, **, &) breaks TruffleRuby, JRuby, and
700
+ # Ruby < 3.2. Named args are explicit and portable.
701
+ Style/ArgumentsForwarding:
702
+ Enabled: false
703
+
704
+ # Explicit begin/rescue/end is clearer than implicit method-body rescue.
705
+ Style/RedundantBegin:
706
+ Enabled: false
707
+
708
+ # Classes get rdoc.
709
+ Style/Documentation:
710
+ Enabled: true
711
+ Exclude:
712
+ <% if @test_framework == :minitest -%>
713
+ - "test/**/*"
714
+ <% elsif @test_framework == :rspec -%>
715
+ - "spec/**/*"
716
+ <% end -%>
717
+
718
+ # Trailing commas in multiline literals and arguments.
719
+ Style/TrailingCommaInArrayLiteral:
720
+ EnforcedStyleForMultiline: comma
721
+
722
+ Style/TrailingCommaInHashLiteral:
723
+ EnforcedStyleForMultiline: comma
724
+
725
+ Style/TrailingCommaInArguments:
726
+ EnforcedStyleForMultiline: comma
727
+
728
+ <% if @test_framework == :rspec -%>
729
+ # ===========================================================================
730
+ # RSpec — rubocop-rspec overrides
731
+ # ===========================================================================
732
+
733
+ # Not every describe block wraps a class.
734
+ RSpec/DescribeClass:
735
+ Enabled: false
736
+
737
+ # Subject placement is a readability call, not a rule.
738
+ RSpec/LeadingSubject:
739
+ Enabled: false
740
+
741
+ # Block style for expect { }.to change { } reads like a sentence.
742
+ RSpec/ExpectChange:
743
+ EnforcedStyle: block
744
+
745
+ RSpec/NamedSubject:
746
+ Enabled: false
747
+
748
+ # have_file_content matcher accepts a filename string in expect()
749
+ RSpec/ExpectActual:
750
+ Enabled: false
751
+ <% end -%>
752
+ ```
753
+
754
+ - [ ] **Step 2: Update Gemfile.erb**
755
+
756
+ Replace the rubocop section in `data/templates/gem/Gemfile.erb`:
757
+
758
+ ```erb
759
+ gem "rubocop"
760
+ gem "rubocop-claude"
761
+ <% if @test_framework == :minitest -%>
762
+ gem "rubocop-minitest"
763
+ <% end -%>
764
+ gem "rubocop-performance"
765
+ gem "rubocop-rake"
766
+ <% if @test_framework == :rspec -%>
767
+ gem "rubocop-rspec"
768
+ <% end -%>
769
+ ```
770
+
771
+ Note: `rubocop-md` is removed (not in the new config).
772
+
773
+ - [ ] **Step 3: Commit**
774
+
775
+ ```bash
776
+ git add data/templates/gem/dotfiles/rubocop.yml.erb data/templates/gem/Gemfile.erb
777
+ git commit -m "Update gem templates to use new rubocop config with rubocop-claude"
778
+ ```
779
+
780
+ ---
781
+
782
+ ## Task 9: Delete new_rubocop.yml and Verify
783
+
784
+ **Files:**
785
+ - Delete: `new_rubocop.yml`
786
+
787
+ - [ ] **Step 1: Delete the source file**
788
+
789
+ ```bash
790
+ git rm new_rubocop.yml
791
+ ```
792
+
793
+ - [ ] **Step 2: Run full rubocop**
794
+
795
+ Run: `bundle exec rubocop`
796
+ Expected: 0 offenses.
797
+
798
+ - [ ] **Step 3: Run full test suite**
799
+
800
+ Run: `bundle exec rake test`
801
+ Expected: All tests pass.
802
+
803
+ - [ ] **Step 4: Verify a generated gem works with the new template**
804
+
805
+ Run a quick smoke test: generate a test gem with each framework and confirm `rubocop` loads cleanly in each:
806
+
807
+ ```bash
808
+ cd /tmp
809
+ gempilot create --test minitest test_mini_gem
810
+ cd test_mini_gem && bundle install && bundle exec rubocop --format offenses
811
+ cd /tmp
812
+ gempilot create --test rspec test_rspec_gem
813
+ cd test_rspec_gem && bundle install && bundle exec rubocop --format offenses
814
+ ```
815
+
816
+ Expected: Both gems load rubocop config without errors and have 0 offenses on the generated scaffold.
817
+
818
+ - [ ] **Step 5: Commit**
819
+
820
+ ```bash
821
+ git rm new_rubocop.yml
822
+ git commit -m "Remove new_rubocop.yml — fully integrated into project and templates"
823
+ ```
824
+
825
+ ---
826
+
827
+ ## Decision Log
828
+
829
+ | Decision | Rationale |
830
+ |----------|-----------|
831
+ | Drop `rubocop-md` | New config doesn't use it; markdown linting is low-value for this project |
832
+ | Keep `rubocop-rake` | Project and generated gems both define rake tasks |
833
+ | `TargetRubyVersion: 3.4` for project | Gempilot targets Ruby 3.4 per gemspec |
834
+ | `Exclude: data/templates/**/*` | ERB templates contain `<%= %>` tags that aren't valid Ruby |
835
+ | `Exclude: test/**/*` for BlockLength | Test methods naturally exceed 8-line block limits |
836
+ | `Exclude: test/**/*` for Documentation | Test classes don't need rdoc |
837
+ | `Minitest/MultipleAssertions: Max: 10` | Generator tests legitimately assert many file-system outcomes per test |
838
+ | `Metrics/BlockLength` AllowedMethods differ per framework | minitest uses `test`, rspec uses `describe`/`context`/`shared_*` |