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.
- checksums.yaml +7 -0
- data/.claude/skills/using-command-kit/SKILL.md +119 -0
- data/.claude/skills/using-command-kit/cli-example.rb +84 -0
- data/.claude/skills/using-command-kit/generator-pattern.rb +62 -0
- data/.rspec +3 -0
- data/.rubocop.yml +281 -0
- data/.ruby-version +1 -0
- data/CLAUDE.md +45 -0
- data/LICENSE.txt +21 -0
- data/README.md +140 -0
- data/Rakefile +44 -0
- data/data/templates/gem/Gemfile.erb +23 -0
- data/data/templates/gem/LICENSE.txt.erb +21 -0
- data/data/templates/gem/README.md.erb +25 -0
- data/data/templates/gem/Rakefile.erb +36 -0
- data/data/templates/gem/bin/console.erb +7 -0
- data/data/templates/gem/bin/setup.erb +5 -0
- data/data/templates/gem/dotfiles/github/workflows/ci.yml.erb +33 -0
- data/data/templates/gem/dotfiles/gitignore +11 -0
- data/data/templates/gem/dotfiles/rubocop.yml.erb +209 -0
- data/data/templates/gem/dotfiles/ruby-version.erb +1 -0
- data/data/templates/gem/exe/gem_name.erb +3 -0
- data/data/templates/gem/gemspec.erb +27 -0
- data/data/templates/gem/lib/gem_name/version.rb.erb +7 -0
- data/data/templates/gem/lib/gem_name.rb.erb +16 -0
- data/data/templates/gem/lib/gem_name_extension.rb.erb +20 -0
- data/data/templates/gem/rspec.erb +3 -0
- data/data/templates/gem/spec/gem_name_spec.rb.erb +5 -0
- data/data/templates/gem/spec/spec_helper.rb.erb +10 -0
- data/data/templates/gem/spec/zeitwerk_spec.rb.erb +5 -0
- data/data/templates/gem/test/gem_name_test.rb.erb +7 -0
- data/data/templates/gem/test/test_helper.rb.erb +7 -0
- data/data/templates/gem/test/zeitwerk_test.rb.erb +9 -0
- data/data/templates/new/.keep +0 -0
- data/data/templates/new/command.rb.erb +15 -0
- data/docs/command_kit_comparison.md +249 -0
- data/docs/command_kit_reference.md +517 -0
- data/docs/plans/2026-02-18-gempilot-add-command.md +718 -0
- data/docs/superpowers/plans/2026-04-01-rubocop-new-config.md +838 -0
- data/docs/superpowers/plans/2026-04-06-dogfood-inflectable.md +659 -0
- data/docs/superpowers/plans/2026-04-06-inflection-tests-and-erb-rename.md +166 -0
- data/docs/superpowers/plans/2026-04-06-integrate-version-tools.md +162 -0
- data/docs/superpowers/plans/2026-04-06-new-readme.md +185 -0
- data/docs/version-management-redesign.md +44 -0
- data/exe/gempilot +12 -0
- data/issues.rec +77 -0
- data/lib/core_ext/string/inflection_methods.rb +68 -0
- data/lib/core_ext/string/refinements/inflectable.rb +15 -0
- data/lib/gempilot/cli/command.rb +17 -0
- data/lib/gempilot/cli/commands/bump.rb +49 -0
- data/lib/gempilot/cli/commands/console.rb +38 -0
- data/lib/gempilot/cli/commands/create.rb +183 -0
- data/lib/gempilot/cli/commands/destroy.rb +136 -0
- data/lib/gempilot/cli/commands/new.rb +226 -0
- data/lib/gempilot/cli/commands/release.rb +40 -0
- data/lib/gempilot/cli/gem_builder.rb +105 -0
- data/lib/gempilot/cli/gem_context.rb +40 -0
- data/lib/gempilot/cli/generator.rb +90 -0
- data/lib/gempilot/cli.rb +19 -0
- data/lib/gempilot/github_release.rb +30 -0
- data/lib/gempilot/project/version.rb +39 -0
- data/lib/gempilot/project.rb +111 -0
- data/lib/gempilot/strict_shell.rb +18 -0
- data/lib/gempilot/version.rb +3 -0
- data/lib/gempilot/version_tag.rb +53 -0
- data/lib/gempilot/version_task.rb +108 -0
- data/lib/gempilot.rb +17 -0
- data/notes.md +31 -0
- metadata +165 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Inflection Tests and ERB Rename 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:** Add unit tests for `String::Inflectable` and rename `version.rake.erb` to `version.rake` since it no longer contains ERB tags.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Two independent tasks. Task 1 adds an RSpec spec for the inflection refinement covering `camelize`, `underscore`, and `dasherize` with edge cases. Task 2 renames the template file and switches `gem_builder.rb` from `erb` to `cp`.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Ruby, RSpec
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## File Structure
|
|
14
|
+
|
|
15
|
+
| Action | Path | Responsibility |
|
|
16
|
+
|--------|------|----------------|
|
|
17
|
+
| Create | `spec/core_ext/string/inflectable_spec.rb` | Unit tests for inflection refinement |
|
|
18
|
+
| Rename | `data/templates/gem/rakelib/version.rake.erb` → `data/templates/gem/rakelib/version.rake` | Remove misleading ERB extension |
|
|
19
|
+
| Modify | `lib/gempilot/cli/gem_builder.rb:48` | Switch from `erb` to `cp` for version.rake |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
### Task 1: Add inflection unit tests
|
|
24
|
+
|
|
25
|
+
**Files:**
|
|
26
|
+
- Create: `spec/core_ext/string/inflectable_spec.rb`
|
|
27
|
+
|
|
28
|
+
- [ ] **Step 1: Write the spec**
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
require_relative "../../lib/core_ext/string/refinements/inflectable"
|
|
32
|
+
|
|
33
|
+
using String::Inflectable
|
|
34
|
+
|
|
35
|
+
RSpec.describe String::Inflectable do
|
|
36
|
+
describe "#camelize" do
|
|
37
|
+
it "camelizes a snake_case string" do
|
|
38
|
+
expect("my_gem".camelize).to eq("MyGem")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "camelizes a path with slashes into namespaces" do
|
|
42
|
+
expect("my/gem".camelize).to eq("My::Gem")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "handles a single word" do
|
|
46
|
+
expect("gem".camelize).to eq("Gem")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "handles a hyphenated string" do
|
|
50
|
+
expect("my-gem".camelize).to eq("MyGem")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "preserves numeric segments" do
|
|
54
|
+
expect("v_2".camelize).to eq("V_2")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#underscore" do
|
|
59
|
+
it "underscores a CamelCase string" do
|
|
60
|
+
expect("MyGem".underscore).to eq("my_gem")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "underscores consecutive capitals" do
|
|
64
|
+
expect("CLI".underscore).to eq("cli")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "underscores mixed case with acronyms" do
|
|
68
|
+
expect("HTTPClient".underscore).to eq("http_client")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "preserves existing underscores" do
|
|
72
|
+
expect("my_gem".underscore).to eq("my_gem")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "converts hyphens to underscores" do
|
|
76
|
+
expect("my-gem".underscore).to eq("my_gem")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe "#dasherize" do
|
|
81
|
+
it "converts underscores to hyphens" do
|
|
82
|
+
expect("my_gem".dasherize).to eq("my-gem")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "leaves non-underscored strings alone" do
|
|
86
|
+
expect("mygem".dasherize).to eq("mygem")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe "class method form" do
|
|
91
|
+
it "camelizes via String.camelize" do
|
|
92
|
+
expect(String.camelize("my_gem")).to eq("MyGem")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "underscores via String.underscore" do
|
|
96
|
+
expect(String.underscore("MyGem")).to eq("my_gem")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "dasherizes via String.dasherize" do
|
|
100
|
+
expect(String.dasherize("my_gem")).to eq("my-gem")
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- [ ] **Step 2: Run the spec**
|
|
107
|
+
|
|
108
|
+
Run: `bundle exec rspec spec/core_ext/string/inflectable_spec.rb --format documentation`
|
|
109
|
+
Expected: All examples pass
|
|
110
|
+
|
|
111
|
+
- [ ] **Step 3: Run rubocop**
|
|
112
|
+
|
|
113
|
+
Run: `bundle exec rubocop spec/core_ext/string/inflectable_spec.rb`
|
|
114
|
+
Expected: No offenses
|
|
115
|
+
|
|
116
|
+
- [ ] **Step 4: Commit**
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
git add spec/core_ext/string/inflectable_spec.rb
|
|
120
|
+
git commit -m "Add unit tests for String::Inflectable refinement"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### Task 2: Rename version.rake.erb to version.rake
|
|
126
|
+
|
|
127
|
+
**Files:**
|
|
128
|
+
- Rename: `data/templates/gem/rakelib/version.rake.erb` → `data/templates/gem/rakelib/version.rake`
|
|
129
|
+
- Modify: `lib/gempilot/cli/gem_builder.rb:48`
|
|
130
|
+
|
|
131
|
+
- [ ] **Step 1: Rename the template file**
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git mv data/templates/gem/rakelib/version.rake.erb data/templates/gem/rakelib/version.rake
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- [ ] **Step 2: Update `gem_builder.rb`**
|
|
138
|
+
|
|
139
|
+
In `lib/gempilot/cli/gem_builder.rb` line 48, change:
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
erb "rakelib/version.rake.erb", "#{@gem_name}/rakelib/version.rake"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
To:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
cp "rakelib/version.rake", "#{@gem_name}/rakelib/version.rake"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- [ ] **Step 3: Run tests**
|
|
152
|
+
|
|
153
|
+
Run: `bundle exec rake test spec`
|
|
154
|
+
Expected: All pass
|
|
155
|
+
|
|
156
|
+
- [ ] **Step 4: Run rubocop**
|
|
157
|
+
|
|
158
|
+
Run: `bundle exec rubocop`
|
|
159
|
+
Expected: No offenses
|
|
160
|
+
|
|
161
|
+
- [ ] **Step 5: Commit**
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
git add data/templates/gem/rakelib/version.rake lib/gempilot/cli/gem_builder.rb
|
|
165
|
+
git commit -m "Rename version.rake.erb to version.rake — no ERB tags remain"
|
|
166
|
+
```
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Package Version Tools as Gem Dependency
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
Generated gems currently get 8 files copied into them (rakelib support classes + core_ext inflection files). This creates maintenance burden — files diverge, every gem carries duplicate code, updates require regenerating. The CLI `bump` command also reimplements version logic that `Project` already provides.
|
|
6
|
+
|
|
7
|
+
Instead: the domain model (`Project`, `Project::Version`, `VersionTag`, `GithubRelease`) lives in `lib/gempilot/` as first-class autoloaded classes. A `VersionTasks` class provides the rake integration. Generated gems add `gem "gempilot"` and `require "gempilot/version_tasks"`. The CLI `bump` command delegates to `rake version:bump` like `release` already delegates to `rake release`.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
lib/gempilot/
|
|
13
|
+
project.rb — Gempilot::Project (gem introspection)
|
|
14
|
+
project/
|
|
15
|
+
version.rb — Gempilot::Project::Version (semver value object)
|
|
16
|
+
version_tag.rb — Gempilot::VersionTag (git release ops)
|
|
17
|
+
github_release.rb — Gempilot::GithubRelease (github release ops)
|
|
18
|
+
strict_shell.rb — Gempilot::StrictShell (shared shell mixin)
|
|
19
|
+
version_tasks.rb — Gempilot::VersionTasks < Rake::TaskLib (entry point)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Only `VersionTasks` depends on Rake. The rest are plain Ruby domain objects that Zeitwerk autoloads normally. `VersionTasks` is ignored by Zeitwerk (requires Rake as a side effect) and loaded via explicit `require "gempilot/version_tasks"`.
|
|
23
|
+
|
|
24
|
+
## Files
|
|
25
|
+
|
|
26
|
+
### Create
|
|
27
|
+
| Path | Class |
|
|
28
|
+
|------|-------|
|
|
29
|
+
| `lib/gempilot/strict_shell.rb` | `Gempilot::StrictShell` |
|
|
30
|
+
| `lib/gempilot/project.rb` | `Gempilot::Project` |
|
|
31
|
+
| `lib/gempilot/project/version.rb` | `Gempilot::Project::Version` |
|
|
32
|
+
| `lib/gempilot/version_tag.rb` | `Gempilot::VersionTag` |
|
|
33
|
+
| `lib/gempilot/github_release.rb` | `Gempilot::GithubRelease` |
|
|
34
|
+
| `lib/gempilot/version_tasks.rb` | `Gempilot::VersionTasks` |
|
|
35
|
+
|
|
36
|
+
### Delete
|
|
37
|
+
| Path | Reason |
|
|
38
|
+
|------|--------|
|
|
39
|
+
| `rakelib/project.rb` | Moved to lib/gempilot/ |
|
|
40
|
+
| `rakelib/project_version.rb` | Moved to lib/gempilot/project/version.rb |
|
|
41
|
+
| `rakelib/version_tag.rb` | Moved to lib/gempilot/ |
|
|
42
|
+
| `rakelib/github_release.rb` | Moved to lib/gempilot/ |
|
|
43
|
+
| `rakelib/strict_shell.rb` | Moved to lib/gempilot/ |
|
|
44
|
+
| `rakelib/version.rake` | Replaced by VersionTasks |
|
|
45
|
+
| `data/templates/gem/rakelib/` | Entire directory (6 symlinks) |
|
|
46
|
+
| `data/templates/gem/lib/core_ext/` | Entire directory (2 symlinks) |
|
|
47
|
+
|
|
48
|
+
### Modify
|
|
49
|
+
| Path | Change |
|
|
50
|
+
|------|--------|
|
|
51
|
+
| `lib/gempilot.rb` | Add `LOADER.ignore` for `version_tasks.rb` |
|
|
52
|
+
| `gempilot.gemspec` | Add `warning` runtime dep, fix fallback glob |
|
|
53
|
+
| `Gemfile` | Remove `gem "warning"` |
|
|
54
|
+
| `Rakefile` | Use `require "gempilot/version_tasks"` + `Gempilot::VersionTasks.new` |
|
|
55
|
+
| `lib/gempilot/cli/commands/bump.rb` | Delegate to `rake version:bump[SEGMENT]` |
|
|
56
|
+
| `lib/gempilot/cli/commands/release.rb` | Delegate to `rake version:release` (already similar) |
|
|
57
|
+
| `data/templates/gem/Rakefile.erb` | Add require + VersionTasks.new |
|
|
58
|
+
| `data/templates/gem/Gemfile.erb` | Add `gem "gempilot", require: false` |
|
|
59
|
+
| `data/templates/gem/gemspec.erb` | Change fallback glob `{lib,exe,rakelib}` → `{lib,exe}` |
|
|
60
|
+
| `data/templates/gem/lib/gem_name.rb.erb` | Remove `LOADER.ignore("#{__dir__}/core_ext")` |
|
|
61
|
+
| `lib/gempilot/cli/gem_builder.rb` | Remove `render_version_rake`, `render_core_ext` + calls |
|
|
62
|
+
| Specs | Update require paths + class references |
|
|
63
|
+
| `test/gempilot/cli/create_command_test.rb` | Update assertions for new generated gem structure |
|
|
64
|
+
|
|
65
|
+
## Domain Model Changes
|
|
66
|
+
|
|
67
|
+
### `Project::Version#bump(segment)` — add segment support
|
|
68
|
+
|
|
69
|
+
Currently `next_version` only increments the last segment. Add `bump(segment = :patch)`:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
def bump(segment = :patch)
|
|
73
|
+
major, minor, patch = value.split(".").map(&:to_i)
|
|
74
|
+
new_value = case segment.to_sym
|
|
75
|
+
when :major then "#{major + 1}.0.0"
|
|
76
|
+
when :minor then "#{major}.#{minor + 1}.0"
|
|
77
|
+
when :patch then "#{major}.#{minor}.#{patch + 1}"
|
|
78
|
+
end
|
|
79
|
+
with(value: new_value)
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`next_version` stays as an alias for `bump(:patch)` for backwards compatibility with the existing specs.
|
|
84
|
+
|
|
85
|
+
### `version:bump` rake task — accept segment argument
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
desc "Bump version (patch default, or rake version:bump[minor])"
|
|
89
|
+
task :bump, [:segment] do |_t, args|
|
|
90
|
+
segment = (args[:segment] || :patch).to_sym
|
|
91
|
+
old_version = project.version
|
|
92
|
+
new_version = old_version.bump(segment)
|
|
93
|
+
project.write_version!(old_version, new_version)
|
|
94
|
+
project.refresh_version!
|
|
95
|
+
puts "Version bumped from #{old_version.value} to #{project.version_value}"
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### `Bump` CLI command — delegate to rake
|
|
100
|
+
|
|
101
|
+
Replace the 104-line implementation with a thin rake delegation (same pattern as `Release`):
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
def run(segment = "patch")
|
|
105
|
+
detect_gem_context
|
|
106
|
+
validate_segment(segment)
|
|
107
|
+
run_rake_bump(segment)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def run_rake_bump(segment)
|
|
113
|
+
success = Bundler.with_unbundled_env do
|
|
114
|
+
system("bundle", "exec", "rake", "version:bump[#{segment}]")
|
|
115
|
+
end
|
|
116
|
+
exit 1 unless success
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Tasks
|
|
121
|
+
|
|
122
|
+
### Task 1: Create domain classes in lib/gempilot/
|
|
123
|
+
|
|
124
|
+
Move and namespace the 5 domain classes + create `VersionTasks`. Each is a mechanical translation wrapping in `module Gempilot`. Add `Version#bump(segment)` method. Add `LOADER.ignore` for `version_tasks.rb` only (the rest autoload normally). Add `warning` to gemspec runtime deps.
|
|
125
|
+
|
|
126
|
+
### Task 2: Dogfood — switch gempilot's Rakefile
|
|
127
|
+
|
|
128
|
+
Add `require "gempilot/version_tasks"` + `Gempilot::VersionTasks.new`. Delete all 6 `rakelib/` files. Verify `rake -T version` and `rake version:current`.
|
|
129
|
+
|
|
130
|
+
### Task 3: Update specs
|
|
131
|
+
|
|
132
|
+
Change require paths and class references in all rakelib specs. Add spec for `Version#bump(:minor)` and `Version#bump(:major)`. Run specs.
|
|
133
|
+
|
|
134
|
+
### Task 4: Simplify CLI Bump command
|
|
135
|
+
|
|
136
|
+
Replace the 104-line implementation with rake delegation. Keep `validate_segment` for the CLI-side error message. Remove duplicate `VERSION_PATTERN`, `read_current_version`, `write_new_version`, `increment` methods.
|
|
137
|
+
|
|
138
|
+
### Task 5: Update templates + generator
|
|
139
|
+
|
|
140
|
+
- `Rakefile.erb`: add `require "gempilot/version_tasks"` + `Gempilot::VersionTasks.new`
|
|
141
|
+
- `Gemfile.erb`: add `gem "gempilot", require: false`
|
|
142
|
+
- `gemspec.erb`: change fallback glob to `{lib,exe}`
|
|
143
|
+
- `gem_name.rb.erb`: remove `LOADER.ignore("#{__dir__}/core_ext")`
|
|
144
|
+
- `gem_builder.rb`: remove `render_version_rake`, `render_core_ext` + calls
|
|
145
|
+
- Delete `data/templates/gem/rakelib/` and `data/templates/gem/lib/core_ext/`
|
|
146
|
+
|
|
147
|
+
### Task 6: Update create_command_test.rb
|
|
148
|
+
|
|
149
|
+
Remove assertions about rakelib/core_ext files in generated gems. Add assertions for Gemfile containing `gempilot` and Rakefile containing `VersionTasks`.
|
|
150
|
+
|
|
151
|
+
### Task 7: Integration test
|
|
152
|
+
|
|
153
|
+
Generate a test gem. Verify: no `rakelib/` support files, no `lib/core_ext/`, `gem "gempilot"` in Gemfile, `rake -T version` lists 12 tasks, `rake version:current` works, `bundle exec rake` passes.
|
|
154
|
+
|
|
155
|
+
## Verification
|
|
156
|
+
|
|
157
|
+
1. `bundle exec rake test spec` — gempilot suite passes
|
|
158
|
+
2. `bundle exec rubocop` — 0 offenses
|
|
159
|
+
3. `bundle exec rake -T version` — 12 tasks via the new require
|
|
160
|
+
4. `bundle exec rake version:bump[minor]` — segment argument works
|
|
161
|
+
5. `gempilot bump minor` — CLI delegates to rake
|
|
162
|
+
6. Generate a test gem — works end-to-end with gempilot as a Gemfile dependency
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# New README 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 default bundler scaffold README with a real project README documenting gempilot's commands, generated gem features, and version management tasks.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Single file rewrite. Content sourced from command implementations in `lib/gempilot/cli/commands/`, template files in `data/templates/gem/`, and the CLAUDE.md project notes.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Markdown
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## File Structure
|
|
14
|
+
|
|
15
|
+
| Action | Path | Responsibility |
|
|
16
|
+
|--------|------|----------------|
|
|
17
|
+
| Rewrite | `README.md` | Project documentation |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
### Task 1: Write the README
|
|
22
|
+
|
|
23
|
+
**Files:**
|
|
24
|
+
- Rewrite: `README.md`
|
|
25
|
+
|
|
26
|
+
- [ ] **Step 1: Write `README.md`**
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
# Gempilot
|
|
30
|
+
|
|
31
|
+
A CLI toolkit for creating and managing Ruby gems with modern conventions.
|
|
32
|
+
|
|
33
|
+
Gempilot scaffolds production-ready gems with Zeitwerk autoloading, RuboCop,
|
|
34
|
+
GitHub Actions CI, and integrated version management. It also generates
|
|
35
|
+
classes, modules, and commands within existing gems.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gem install gempilot
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Requires Ruby >= 3.4.
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
gempilot create my_gem
|
|
49
|
+
cd my_gem
|
|
50
|
+
bundle exec rake
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This creates a fully configured gem with tests, linting, CI, and version
|
|
54
|
+
management — ready to develop.
|
|
55
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
### `gempilot create`
|
|
59
|
+
|
|
60
|
+
Scaffold a new gem.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
gempilot create my_gem
|
|
64
|
+
gempilot create --test rspec --exe my_gem
|
|
65
|
+
gempilot create --test minitest --no-git my_gem
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Options:
|
|
69
|
+
|
|
70
|
+
| Option | Description | Default |
|
|
71
|
+
|--------|-------------|---------|
|
|
72
|
+
| `--test {minitest\|rspec}` | Test framework | prompted |
|
|
73
|
+
| `--[no-]exe` | Create executable in `exe/` | prompted |
|
|
74
|
+
| `--[no-]git` | Initialize git repo | prompted |
|
|
75
|
+
| `--branch NAME` | Git branch name | `master` |
|
|
76
|
+
| `--summary TEXT` | One-line gem description | prompted |
|
|
77
|
+
| `--author NAME` | Author name | `git config user.name` |
|
|
78
|
+
| `--email EMAIL` | Author email | `git config user.email` |
|
|
79
|
+
| `--ruby-version VER` | Minimum Ruby version | current Ruby |
|
|
80
|
+
|
|
81
|
+
All options are prompted interactively if omitted.
|
|
82
|
+
|
|
83
|
+
### `gempilot new`
|
|
84
|
+
|
|
85
|
+
Generate a class, module, or command in an existing gem. Run from the gem root.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
gempilot new class MyGem::Services::Authentication
|
|
89
|
+
gempilot new module MyGem::Middleware
|
|
90
|
+
gempilot new command deploy
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Creates the source file under `lib/` and a corresponding test file. For
|
|
94
|
+
commands, generates a CommandKit command class in `lib/<gem>/cli/commands/`.
|
|
95
|
+
|
|
96
|
+
### `gempilot destroy`
|
|
97
|
+
|
|
98
|
+
Remove a class, module, or command. Cleans up empty parent directories.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
gempilot destroy class MyGem::Services::Authentication
|
|
102
|
+
gempilot destroy command deploy
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### `gempilot bump`
|
|
106
|
+
|
|
107
|
+
Bump the version in `lib/<gem>/version.rb`.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
gempilot bump # patch (default)
|
|
111
|
+
gempilot bump minor
|
|
112
|
+
gempilot bump major
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `gempilot release`
|
|
116
|
+
|
|
117
|
+
Delegates to `rake release` to build and push the gem.
|
|
118
|
+
|
|
119
|
+
### `gempilot console`
|
|
120
|
+
|
|
121
|
+
Delegates to `bin/console` for an interactive IRB session with the gem loaded.
|
|
122
|
+
|
|
123
|
+
## Generated Gem Features
|
|
124
|
+
|
|
125
|
+
Every gem scaffolded by `gempilot create` includes:
|
|
126
|
+
|
|
127
|
+
- **Zeitwerk autoloading** with `LOADER` constant and `rake zeitwerk:validate`
|
|
128
|
+
- **Test framework** — Minitest or RSpec, with a Zeitwerk eager-load test
|
|
129
|
+
- **RuboCop** with `rubocop-claude`, `rubocop-performance`, `rubocop-rake`, and
|
|
130
|
+
framework-specific plugins (`rubocop-minitest` or `rubocop-rspec`)
|
|
131
|
+
- **GitHub Actions CI** running tests and RuboCop
|
|
132
|
+
- **Version management** rake tasks (see below)
|
|
133
|
+
- **`bin/console`** and **`bin/setup`** scripts
|
|
134
|
+
- **Gemspec** with `git ls-files` and glob fallback, MFA required for RubyGems
|
|
135
|
+
|
|
136
|
+
### Version Management Tasks
|
|
137
|
+
|
|
138
|
+
Generated gems include rake tasks for the full version lifecycle:
|
|
139
|
+
|
|
140
|
+
| Task | Description |
|
|
141
|
+
|------|-------------|
|
|
142
|
+
| `rake version:current` | Display the current version |
|
|
143
|
+
| `rake version:bump` | Increment the patch version |
|
|
144
|
+
| `rake version:commit` | Commit the version file change |
|
|
145
|
+
| `rake version:tag` | Create a git tag for the version |
|
|
146
|
+
| `rake version:untag` | Delete the version git tag |
|
|
147
|
+
| `rake version:reset` | Reset the version bump commit |
|
|
148
|
+
| `rake version:revert` | Revert the version bump commit |
|
|
149
|
+
| `rake version:release` | Bump, commit, and tag (combined) |
|
|
150
|
+
| `rake version:unrelease` | Untag and reset (combined) |
|
|
151
|
+
| `rake version:github:release` | Push and create a GitHub release |
|
|
152
|
+
| `rake version:github:unrelease` | Delete the GitHub release |
|
|
153
|
+
| `rake version:github:list` | List GitHub releases |
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
git clone https://github.com/gillisd/gempilot.git
|
|
159
|
+
cd gempilot
|
|
160
|
+
bundle install
|
|
161
|
+
bundle exec rake
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`rake` runs the Minitest suite, RSpec suite, and RuboCop.
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT License. See [LICENSE.txt](LICENSE.txt).
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- [ ] **Step 2: Review for accuracy**
|
|
172
|
+
|
|
173
|
+
Cross-check against:
|
|
174
|
+
- `lib/gempilot/cli/commands/create.rb` — verify all `--options` are listed
|
|
175
|
+
- `lib/gempilot/cli/commands/new.rb` — verify types (class, module, command)
|
|
176
|
+
- `lib/gempilot/cli/commands/bump.rb` — verify patch/minor/major
|
|
177
|
+
- `rakelib/version.rake` — verify all 12 task names match
|
|
178
|
+
- `gempilot.gemspec` — verify Ruby version requirement
|
|
179
|
+
|
|
180
|
+
- [ ] **Step 3: Commit**
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
git add README.md
|
|
184
|
+
git commit -m "Replace scaffold README with project documentation"
|
|
185
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Version Management Redesign
|
|
2
|
+
|
|
3
|
+
Review notes for `new_version_utils.patch`. To be addressed in a follow-up PR.
|
|
4
|
+
|
|
5
|
+
## Patch summary
|
|
6
|
+
|
|
7
|
+
Replaces inline rake task logic (including the `ActiveVersion` delegator) with
|
|
8
|
+
proper domain objects: `Project`, `Project::Version`, `VersionTag`,
|
|
9
|
+
`GithubRelease`, and `StrictShell`. Fixes the stale `require_relative` bug by
|
|
10
|
+
using `load` + `refresh_version!` to re-read from disk after mutations.
|
|
11
|
+
|
|
12
|
+
## What works well
|
|
13
|
+
|
|
14
|
+
- Clean domain decomposition with single-responsibility classes
|
|
15
|
+
- `Version` as a `Data.define` value object with `tag` and `next_version`
|
|
16
|
+
- Symmetric `version:release` / `version:unrelease` task pairs
|
|
17
|
+
- Array-form `sh` calls throughout (no shell interpolation risk)
|
|
18
|
+
- `VersionTag` depends on a version object, not the full project
|
|
19
|
+
|
|
20
|
+
## Open items
|
|
21
|
+
|
|
22
|
+
1. **`release_full_spec.rb` is stale** -- matches `task full: ["version:bump",
|
|
23
|
+
"version:commit", :release]` but the new rake file has
|
|
24
|
+
`task release: ["version:bump", "version:commit", "version:tag"]`.
|
|
25
|
+
|
|
26
|
+
2. **rakelib couples to lib** -- `Project` requires
|
|
27
|
+
`lib/core_ext/string/refinements/inflectable`. Generated gems using this
|
|
28
|
+
rakelib pattern would need that refinement at that exact path.
|
|
29
|
+
|
|
30
|
+
3. **`Project#klass` loads the gem module** -- `Object.const_get(name.camelize)`
|
|
31
|
+
combined with `load` in `fetch_version` means the gem must be loadable from
|
|
32
|
+
the rake context. Gems with load-time side effects could behave unexpectedly.
|
|
33
|
+
|
|
34
|
+
4. **`Project` has two responsibilities** -- structure discovery (name, lib path,
|
|
35
|
+
module) and version lifecycle (increment, write, refresh). Cohesive enough for
|
|
36
|
+
now, but the seam is visible if either grows.
|
|
37
|
+
|
|
38
|
+
5. **`warning` gem dependency** -- `Project` requires the `warning` gem. Needs to
|
|
39
|
+
be a development dependency in the gemspec (and in generated gem templates).
|
|
40
|
+
|
|
41
|
+
6. **Template expansion** -- If this rakelib replaces `version.rake.erb`, the
|
|
42
|
+
template needs to generate all five support files (`project.rb`,
|
|
43
|
+
`project_version.rb`, `version_tag.rb`, `github_release.rb`,
|
|
44
|
+
`strict_shell.rb`), significantly expanding the scaffold.
|
data/exe/gempilot
ADDED
data/issues.rec
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
%rec: Issue
|
|
2
|
+
%key: Id
|
|
3
|
+
%typedef: text_t regexp /.*/
|
|
4
|
+
%typedef: Status_t enum open in_progress closed
|
|
5
|
+
%type: Id uuid
|
|
6
|
+
%type: Title line
|
|
7
|
+
%type: Description text_t
|
|
8
|
+
%type: Updated date
|
|
9
|
+
%type: Status Status_t
|
|
10
|
+
%auto: Id Updated
|
|
11
|
+
%mandatory: Title Description
|
|
12
|
+
|
|
13
|
+
Id: 6F683910-2EFA-4356-B1FE-3E4FE3E20A38
|
|
14
|
+
Updated: Mon, 02 Mar 2026 10:31:07 -0500
|
|
15
|
+
Title: Rake build triggers gem to be built twice?
|
|
16
|
+
Description: Why am I seeing 2 messages about gempilot being built to pkg/gempilot-0.1.0.gem
|
|
17
|
+
Status: open
|
|
18
|
+
|
|
19
|
+
Id: 011FB117-BC52-453F-A8E8-6955FE3EBCE8
|
|
20
|
+
Updated: Mon, 02 Mar 2026 10:31:39 -0500
|
|
21
|
+
Title: rubocop-rake is not active
|
|
22
|
+
Description: It should be active for this project
|
|
23
|
+
Status: open
|
|
24
|
+
|
|
25
|
+
Id: F0833E66-A35C-4054-884B-F90C81F08838
|
|
26
|
+
Updated: Mon, 02 Mar 2026 10:37:33 -0500
|
|
27
|
+
Title: Error handling should be graceful
|
|
28
|
+
Description: I did "gempilot create", and entered "A foo" as the title, and it crashed horrifically. This particular example should have validation at the minimum. Need to also use command kit's error bubbling/handling mechanism to swallow errors and print message to user. Can always use verbose or debug mode to see full trace.
|
|
29
|
+
Status: open
|
|
30
|
+
|
|
31
|
+
Id: 741FFD05-9BD7-44EB-BB99-E7D705F12681
|
|
32
|
+
Updated: Mon, 02 Mar 2026 11:25:24 -0500
|
|
33
|
+
Title: Reduce dependencies
|
|
34
|
+
Description:
|
|
35
|
+
Status: open
|
|
36
|
+
|
|
37
|
+
Id: 131EA3CE-2F3D-4E37-9D9B-A25E0A651F1B
|
|
38
|
+
Updated: Tue, 10 Mar 2026 17:40:50 -0400
|
|
39
|
+
Title: irb is required now as a gem
|
|
40
|
+
Description: Needs to go in template gemfile
|
|
41
|
+
Status: open
|
|
42
|
+
|
|
43
|
+
Id: 3178AC5C-09A9-44A9-ACE1-11BED0BA7276
|
|
44
|
+
Updated: Mon, 06 Apr 2026 00:00:00 -0400
|
|
45
|
+
Title: Add a version:* rake task that supports just bumping and committing
|
|
46
|
+
Description: Right now the only "combo" rake task for bumping version is the one that releases in full. Should make a composite one for more generalized purposes
|
|
47
|
+
Status: closed
|
|
48
|
+
|
|
49
|
+
Id: E6EB289D-BE84-4872-8012-D936707989B1
|
|
50
|
+
Updated: Mon, 06 Apr 2026 00:00:00 -0400
|
|
51
|
+
Title: Rake task version:commit should add version tag to commit
|
|
52
|
+
Description: The commit should be tagged with git tag upon committing, as this is a key part of releasing
|
|
53
|
+
Status: closed
|
|
54
|
+
|
|
55
|
+
Id: 7825507C-ABD2-4618-A591-BCDB54152C6B
|
|
56
|
+
Updated: Sat, 28 Mar 2026 12:48:05 -0400
|
|
57
|
+
Title: Rake task version:bump should support "dev increments", like "0.2.1.dev3". Perhaps a task like "version:bump:dev" is created to allow for this
|
|
58
|
+
Description: open
|
|
59
|
+
Status: open
|
|
60
|
+
|
|
61
|
+
Id: 5E4D51AB-F9BF-4C72-8165-F1B900799FA7
|
|
62
|
+
Updated: Sat, 28 Mar 2026 12:55:14 -0400
|
|
63
|
+
Title: Hundreds of rubocop failures exist
|
|
64
|
+
Description: These need to be addressed
|
|
65
|
+
Status: open
|
|
66
|
+
|
|
67
|
+
Id: 74D0FD90-0421-4452-8591-2798EE6FD23E
|
|
68
|
+
Updated: Sat, 28 Mar 2026 12:59:40 -0400
|
|
69
|
+
Title: Publish gem
|
|
70
|
+
Description: At some point the repo should be moved to public viz, and the gem should be published.
|
|
71
|
+
Status: open
|
|
72
|
+
|
|
73
|
+
Id: 8C356024-3122-11F1-89F3-FE6CB9572C2F
|
|
74
|
+
Updated: Mon, 06 Apr 2026 00:00:00 -0400
|
|
75
|
+
Title: Replace 4.0.1 with 3.4.8
|
|
76
|
+
Description: Need to move ruby version down to 3.4.8
|
|
77
|
+
Status: closed
|