gempilot 0.3.0 → 0.3.2

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.
@@ -0,0 +1,163 @@
1
+ # Dev version bump semantics — design
2
+
3
+ **Issue:** `2360FFA4-9388-11F1-8474-FE6CB9572C2F` — "rake version:bump[dev] goes backward rather than forward"
4
+
5
+ **Date:** 2026-08-09
6
+
7
+ ## Problem
8
+
9
+ `Gempilot::Project::Version#bump(:dev)` appends `.dev1` to the *current* version
10
+ (`0.2.0` → `0.2.0.dev1`). RubyGems treats any version with a letter segment as a
11
+ **prerelease of the version it names** (`Gem::Version` rdoc: "Prereleases sort
12
+ between real releases (newest to oldest): 1.0 > 1.0.b1 > 1.0.a.2 > 0.9"), so
13
+ `0.2.0.dev1 < 0.2.0` — the bump moves the project *backward*. Two related gaps:
14
+
15
+ 1. `bump(:patch)` from `X.Y.Z.devN` produces `X.Y.(Z+1)`, overshooting the
16
+ `X.Y.Z` the dev cycle was working toward.
17
+ 2. There is no way to bump a fourth integer (`0.2.0` → `0.2.0.1`), the
18
+ rubygems-legal *non-prerelease* shape for tiny follow-up fixes on a released
19
+ version (the Rails security-release pattern, `6.0.3.1`).
20
+
21
+ ## Decisions
22
+
23
+ - **Dev versions preview the next patch.** `bump(:dev)` from a release version
24
+ yields the next patch's first dev prerelease (`0.2.0` → `0.2.1.dev1`); from a
25
+ dev version it increments the counter (`0.2.1.dev1` → `0.2.1.dev2`). This is
26
+ the only reading consistent with rubygems ordering, and matches ecosystem
27
+ practice (Rails `7.1.0.beta1` precedes `7.1.0`; Bundler's in-repo `.dev`).
28
+ - **One rule governs every bump: move to the smallest version of the requested
29
+ shape that is strictly greater than the current version.** Consequences:
30
+ numeric bumps from a dev version *finalize* the cycle (`0.2.1.dev3` +
31
+ `patch` → `0.2.1`, not `0.2.2`), and `minor`/`major` redirect it
32
+ (`0.2.1.dev3` + `minor` → `0.3.0`).
33
+ - **New `tiny` segment for the fourth integer.** `bump(:tiny)`: `0.2.0` →
34
+ `0.2.0.1` → `0.2.0.2`. Name chosen by elimination: semver's "build metadata"
35
+ is precedence-ignored (and the `Gem::Version` rdoc uses "build" for the third
36
+ integer); `micro` is Python's third digit; `patchlevel` is Ruby-historical but
37
+ long and confusable with `patch`. `tiny` reads as "smaller than patch", which
38
+ is where it sorts. (Old Rails used TINY for the third digit; accepted.)
39
+ - **No dev target argument** (`bump[dev,minor]` → `0.3.0.dev1`) — YAGNI. The
40
+ shape rule already finalizes hand-edited `M.m.0.devN` / `M.0.0.devN` states
41
+ correctly, so a targeted form can be layered on later without breaking
42
+ anything.
43
+ - **Dev GitHub releases are prereleases.** `release:github` passes
44
+ `--prerelease` to `gh release create` when the tag names a prerelease
45
+ version, so `v0.2.1.dev2` does not become the repo's "Latest" release.
46
+ - **Strict version parsing.** `Version#bump` recognizes exactly three forms —
47
+ `M.m.p`, `M.m.p.N`, `M.m.p.devN` — and raises `ArgumentError` for anything
48
+ else, instead of today's silent first-three-integers coercion.
49
+
50
+ ## Semantics
51
+
52
+ Accepted version forms: release `M.m.p`, tiny release `M.m.p.N`, dev prerelease
53
+ `M.m.p.devN` (parse: `/\A(\d+)\.(\d+)\.(\d+)(?:\.(\d+)|\.dev(\d+))?\z/`).
54
+
55
+ Full transition table (rows marked * arise only by hand-editing; the rule is
56
+ total over all three forms regardless of how the version got there):
57
+
58
+ | from ↓ bump → | `major` | `minor` | `patch` | `tiny` | `dev` |
59
+ | ------------- | ------- | ------- | ------- | --------- | ------------ |
60
+ | `1.2.3` | `2.0.0` | `1.3.0` | `1.2.4` | `1.2.3.1` | `1.2.4.dev1` |
61
+ | `1.2.3.1` | `2.0.0` | `1.3.0` | `1.2.4` | `1.2.3.2` | `1.2.4.dev1` |
62
+ | `1.2.4.dev2` | `2.0.0` | `1.3.0` | `1.2.4` | `1.2.4.1` | `1.2.4.dev3` |
63
+ | `1.3.0.dev2`* | `2.0.0` | `1.3.0` | `1.3.0` | `1.3.0.1` | `1.3.0.dev3` |
64
+ | `2.0.0.dev2`* | `2.0.0` | `2.0.0` | `2.0.0` | `2.0.0.1` | `2.0.0.dev3` |
65
+
66
+ All 25 transitions verified strictly increasing under `Gem::Version` (checked
67
+ 2026-08-09 against ruby's installed rubygems).
68
+
69
+ Branch logic per segment, where the numeric core is `M.m.p` and `dev?` means
70
+ the current version is a dev prerelease:
71
+
72
+ - `major`: `dev? && m == 0 && p == 0` → `M.0.0` (finalize); else `(M+1).0.0`
73
+ - `minor`: `dev? && p == 0` → `M.m.0` (finalize); else `M.(m+1).0`
74
+ - `patch`: `dev?` → `M.m.p` (finalize); else `M.m.(p+1)`
75
+ - `tiny`: `M.m.p.(N+1)` where `N` is the current fourth integer, else 0.
76
+ (From a dev version this yields `M.m.p.1` — it implicitly finalizes the
77
+ target and adds a tiny level; forward-moving, documented edge case.)
78
+ - `dev`: `dev?` → `M.m.p.dev(N+1)`; else `M.m.(p+1).dev1`
79
+
80
+ ## Components
81
+
82
+ ### `Gempilot::Project::Version` (modified — `lib/gempilot/project/version.rb`)
83
+
84
+ - Stays `Data.define(:path, :value)` — `write_version!`, `VersionTag`, and all
85
+ call sites are untouched. Parsing is internal to `bump`.
86
+ - `bump(segment)` accepts `:major, :minor, :patch, :tiny, :dev` (symbol or
87
+ string), implements the table above. Unknown segment → `ArgumentError`
88
+ naming the valid segments (as today, plus `tiny`). Unparseable value →
89
+ `ArgumentError` naming the value.
90
+ - `next_version` alias retained; its behavior follows the new `patch` default
91
+ (`0.0.4.dev3` → `0.0.4`, previously `0.0.5`).
92
+
93
+ ### `Gempilot::GithubRelease` (modified — `lib/gempilot/github_release.rb`)
94
+
95
+ - `#create` appends `--prerelease` when the tag (sans leading `v`) parses as a
96
+ prerelease per `Gem::Version#prerelease?`. Self-contained — the
97
+ `initialize(tag)` signature and all call sites are unchanged. `#destroy` /
98
+ `#list` untouched.
99
+
100
+ ### `Gempilot::VersionTask` (modified — `lib/gempilot/version_task.rb`)
101
+
102
+ - Behavior unchanged (it forwards the segment). Only the `version:bump` desc
103
+ string updates: "Bump version (patch default; segments: major, minor, patch,
104
+ tiny, dev)".
105
+
106
+ ### `Gempilot::CLI::Commands::Bump` (modified — `lib/gempilot/cli/commands/bump.rb`)
107
+
108
+ - Allowed segments become `%w[patch minor major tiny dev]`; error message,
109
+ argument desc, command description, and `examples` updated to match.
110
+
111
+ ## Testing (TDD — written before implementation)
112
+
113
+ **`spec/gempilot/project/version_spec.rb` (rewritten)**
114
+
115
+ - The full 5×5 transition table above, each cell an example.
116
+ - A monotonicity property spec: for every table cell,
117
+ `Gem::Version.new(new) > Gem::Version.new(old)` — the direct regression spec
118
+ for this issue.
119
+ - Segment as string; unknown segment `ArgumentError`; unparseable value
120
+ (`"1.2"`, `"1.2.3.beta1"`) `ArgumentError`; `next_version` follows patch
121
+ semantics (`0.0.4.dev3` → `0.0.4`).
122
+
123
+ **`spec/gempilot/version_task_spec.rb` (expectations updated)**
124
+
125
+ Fixture starts at `1.0.0.dev3`:
126
+ - `version:bump` (default patch) → `1.0.0` (finalize; was `1.0.1`).
127
+ - `version:bump[dev]` → `1.0.0.dev4` (unchanged).
128
+ - `version:bump[tiny]` → `1.0.0.1` (new example).
129
+ - `version:release[dev]` → commit "Bump version to 1.0.0.dev4", tag
130
+ `v1.0.0.dev4` (unchanged).
131
+
132
+ **`spec/gempilot/github_release_spec.rb` (extended)**
133
+
134
+ - `create` with `v1.2.4.dev1` includes `--prerelease`; with `v1.2.4` and
135
+ `v1.2.3.1` it does not.
136
+
137
+ **`test/gempilot/cli/bump_command_test.rb` (extended)**
138
+
139
+ - `tiny` accepted as a segment; unknown-segment error message lists it.
140
+
141
+ ## Docs
142
+
143
+ - `README.md` — `gempilot bump` section gains `tiny` and `dev` examples with a
144
+ one-line explanation of dev semantics; the rake tasks table row for
145
+ `version:bump` mentions the segments.
146
+ - `CLAUDE.md` — version lifecycle bullet: "(patch default, or
147
+ minor/major/tiny/dev)".
148
+
149
+ ## Migration
150
+
151
+ A repo sitting on an old-style dev version (e.g. `0.2.0.dev1` created *after*
152
+ `0.2.0` shipped) is already in the broken state this fixes; `bump(:patch)`
153
+ would finalize to the already-released `0.2.0` (and `version:tag` would then
154
+ fail on the existing tag). Recovery is a one-time hand edit of `version.rb`
155
+ past the last published version. Noted in the README dev-example line.
156
+
157
+ ## Out of scope
158
+
159
+ - Targeted dev cycles (`bump[dev,minor]`) — compatible later extension.
160
+ - Other prerelease markers (`pre`, `rc`, `beta`) — `dev` sorts before all of
161
+ them, so they remain addable later.
162
+ - RubyGems prerelease yanking; `data/templates/gem/Rakefile.erb` (no change
163
+ needed — it just instantiates `Gempilot::VersionTask`).
data/issues.rec CHANGED
@@ -110,8 +110,8 @@ Description: e.g.
110
110
  + Zeitwerk::Loader.for_gem.tap do |l|
111
111
  + l.setup
112
112
  + end
113
- +
114
- +
113
+ +
114
+ +
115
115
  Status: closed
116
116
 
117
117
  Id: 5618BB20-4325-11F1-BF5A-FE6CB9572C2F
@@ -212,3 +212,108 @@ Description: the github release related tasks are invoked as follows:
212
212
  +
213
213
  + Also, there is an issue that prevents github releasing from working at all via the old tasks. I get an error every time saying that "tags have already been pushed" or something along those lines. Ensure that is fixed as well
214
214
  Status: closed
215
+
216
+ Id: 986E0100-88F4-11F1-B718-FE6CB9572C2D
217
+ Updated: Sun, 26 Jul 2026 09:19:13 -0400
218
+ Title: Make rbs and the other gems GP installs mri only
219
+ Description: This tool is also used with jruby, and it fails irb install due to rbs
220
+ Status: open
221
+
222
+ Id: 3FFE7616-88F5-11F1-8D3B-FE6CB9572C2D
223
+ Updated: Sun, 26 Jul 2026 09:23:54 -0400
224
+ Title: Add betterleaks to gem setup
225
+ Description: Ensure betterleaks is integrated into the commit and build pipelines, via commit hooks, rake tasks, and/or whatever the idiomatic way is to integrate betterleaks into a rubyproject
226
+ Status: open
227
+
228
+ Id: F6C6EB04-8DA4-11F1-91EF-FA41C3164F3A
229
+ Updated: Sat, 01 Aug 2026 12:31:47 +0000
230
+ Title: release:rubygem_push only handles one gem per version
231
+ Description: rake release:rubygems can publish only one gem per version. A project that publishes several -- platform gems each carrying a compiled executable, say -- either publishes one of them and silently leaves the rest, or, once it replaces the push task with a pkg glob, tries to re-push versions already on rubygems and stops halfway through the release.
232
+ +
233
+ + MECHANISM
234
+ +
235
+ + gempilot, lib/gempilot/release_tasks.rb: ReleaseTasks#define_rubygems_release wires release:rubygems to [build, release:guard_clean, release:source_control_push, release:rubygem_push], and, as the module's own rdoc says, expects bundler/gem_tasks to have supplied build, release:guard_clean and release:rubygem_push.
236
+ +
237
+ + bundler 4.0.17, lib/bundler/gem_helper.rb: GemHelper#install_tasks defines
238
+ +
239
+ + task "release:rubygem_push" => "build" do
240
+ + rubygem_push(built_gem_path) if gem_push?
241
+ + end
242
+ +
243
+ + built_gem_path is the single .gem that #build_gem produced. One build, one gem, one push. Nothing in that chain can carry a second gem, so a project publishing more than one has to replace both build and release:rubygem_push itself.
244
+ +
245
+ + There is no glob in gempilot's own source to go looking for. The glob is what a downstream project ends up writing once it takes over the push, and it is wrong in a way gempilot's own version:bump triggers.
246
+ +
247
+ + REPRODUCE
248
+ +
249
+ + 1. A gem publishing more than one gem per version. aws-session-manager on gempilot 0.3.0 publishes five: x86_64-linux, aarch64-linux, x86_64-darwin and arm64-darwin, each carrying a compiled session-manager-plugin executable, plus the plain ruby gem.
250
+ + 2. It replaces build, and replaces the push with the obvious implementation:
251
+ + task(:rubygem_push) { PACKAGES.glob("*.gem").each { sh "gem", "push", it.to_s } }
252
+ + 3. rake build && rake release:rubygems -- 0.0.1 publishes.
253
+ + 4. rake version:bump && rake build -- pkg/ now holds both 0.0.1 and 0.0.2 gems. Nothing empties pkg/ between versions; bundler never has, and gempilot's version tasks do not either.
254
+ + 5. rake release:rubygems -- gem push rejects the 0.0.1 gems ("Repushing of gem versions is not allowed"), sh raises on the non-zero status, and the release aborts with part of 0.0.2 published and the rest not. Re-running repeats the failure, because the stale gems are still there.
255
+ +
256
+ + FIX APPLIED DOWNSTREAM
257
+ +
258
+ + aws-session-manager stopped globbing and took the list from the specifications its build packages, so that gem:build and the push share one source of truth:
259
+ +
260
+ + PACKAGED = [*BUILDS.map { it.package.to_s }, GENERIC_PACKAGE].freeze
261
+ +
262
+ + namespace :gem do
263
+ + task build: PACKAGED
264
+ + end
265
+ +
266
+ + namespace :release do
267
+ + task(:rubygem_push) { PACKAGED.each { sh "gem", "push", it } }
268
+ + end
269
+ +
270
+ + FIX SUGGESTED HERE
271
+ +
272
+ + gempilot should own release:rubygem_push rather than inherit bundler's, and push every gem in pkg belonging to the version being released. It cannot know how a project builds, but it knows the name and the version, which is enough:
273
+ +
274
+ + def define_rubygem_push(project)
275
+ + clear_task "release:rubygem_push"
276
+ + task "release:rubygem_push" => "build" do
277
+ + packages(project).each { sh "gem", "push", it.to_s }
278
+ + end
279
+ + end
280
+ +
281
+ + def packages(project)
282
+ + stem = "#{project.name}-#{project.version_value}"
283
+ + project.root.glob("pkg/{#{stem}.gem,#{stem}-*.gem}")
284
+ + end
285
+ +
286
+ + Project#name, #version_value and #root already exist in lib/gempilot/project.rb.
287
+ +
288
+ + Two details worth keeping:
289
+ +
290
+ + - The brace glob matches gempilot-0.3.0.gem and gempilot-0.3.0-x86_64-linux.gem, and does not match gempilot-0.3.10.gem. A bare "#{stem}*.gem" would match the latter and push the wrong version.
291
+ + - An empty result should abort. Otherwise a project whose build writes gems elsewhere gets a release that reports success having published nothing, which is worse than the bug being fixed.
292
+ +
293
+ + Single-gem projects are unaffected: pkg holds one gem for the current version, and it gets pushed, as today. Multi-gem projects stop having to reinvent the push.
294
+ +
295
+ + If gempilot would rather not own the task, then the ReleaseTasks rdoc should state the contract instead: a project that replaces build must also replace release:rubygem_push, and must scope the push to the version being released rather than globbing pkg.
296
+ Status: open
297
+
298
+ Id: 2360FFA4-9388-11F1-8474-FE6CB9572C2F
299
+ Updated: Wed, 23 Sep 2026 02:07:20 +0000
300
+ Title: rake version:bump[dev] goes backward rather than forward
301
+ Description: rubygems treats 0.2.0.dev as an *older* version than 0.2.0. The way gempilot handles dev version needs to be rethought. Additionally, how does a user trigger a bump on the fourth integer, e.g. 0.2.0.1?
302
+ Status: closed
303
+
304
+ Id: 69816386-9F7F-11F1-8629-FE6CB9572C2F
305
+ Updated: Mon, 24 Aug 2026 01:48:20 -0400
306
+ Title: Command generation is incomplete
307
+ Description: it adds a "command" that is useless. It should:
308
+ + 1. at the very least, chmod +x the "exe" in exe
309
+ + 2. install command_kit
310
+ + 3. bootstrap a command_kit setup
311
+ Status: open
312
+
313
+ Id: 93D7E88E-B6EB-11F1-8AF9-FE6CB9572C2E
314
+ Updated: Tue, 22 Sep 2026 21:10:33 -0400
315
+ Title: Problems with zeitwerk_task.rb
316
+ Description: 1. Documentation is improperly formatted. sizing is all over the place. 2. The task is broken for projects that use an inflector, like ECS. The task looks for "Ecs" instead, despite having it set up in the zeitwerk config.
317
+ +
318
+ + Fixing this should rely on idiomatic zeitwerk & zeitwerk inflector usage, and thoroughly thinking through how to fit this into user's loader. DO NOT rely on regexes of any kind to handle this.
319
+ Status: open
@@ -11,7 +11,7 @@ module Gempilot
11
11
  include CommandKit::Interactive
12
12
  include CommandKit::BugReport
13
13
 
14
- bug_report_url "https://github.com/dgillis/gempilot/issues/new"
14
+ bug_report_url "https://github.com/gillisd/gempilot/issues/new"
15
15
  end
16
16
  end
17
17
  end
@@ -8,18 +8,19 @@ module Gempilot
8
8
  include GemContext
9
9
 
10
10
  usage "[options] [SEGMENT]"
11
- description "Bump the gem version (patch by default, or minor/major/dev)"
11
+ description "Bump the gem version (patch by default, or minor/major/tiny/dev)"
12
12
 
13
13
  examples [
14
14
  "",
15
15
  "patch",
16
16
  "minor",
17
17
  "major",
18
+ "tiny",
18
19
  "dev",
19
20
  ]
20
21
 
21
22
  argument :segment, required: false,
22
- desc: "Version segment to bump: patch (default), minor, major, or dev"
23
+ desc: "Version segment to bump: patch (default), minor, major, tiny, or dev"
23
24
 
24
25
  def run(segment = "patch")
25
26
  detect_gem_context
@@ -31,9 +32,9 @@ module Gempilot
31
32
 
32
33
  def validate_segment(segment)
33
34
  segment = segment.downcase
34
- return segment if %w[patch minor major dev].include?(segment)
35
+ return segment if %w[patch minor major tiny dev].include?(segment)
35
36
 
36
- puts colors.red("Unknown segment '#{segment}'. Use patch, minor, major, or dev.")
37
+ puts colors.red("Unknown segment '#{segment}'. Use patch, minor, major, tiny, or dev.")
37
38
  exit 1
38
39
  end
39
40
 
@@ -1,5 +1,6 @@
1
1
  module Gempilot
2
- ## Manages GitHub releases for a version tag.
2
+ ## Manages GitHub releases for a version tag. Tags naming a prerelease
3
+ ## version (e.g. +v1.2.4.dev1+) are created as GitHub prereleases.
3
4
  class GithubRelease
4
5
  include StrictShell
5
6
 
@@ -12,6 +13,7 @@ module Gempilot
12
13
  def create
13
14
  sh "gh", "release", "create",
14
15
  "--generate-notes", "--fail-on-no-commits",
16
+ *prerelease_flag,
15
17
  tag
16
18
  end
17
19
 
@@ -24,5 +26,11 @@ module Gempilot
24
26
  def list
25
27
  sh "gh", "release", "list"
26
28
  end
29
+
30
+ private
31
+
32
+ def prerelease_flag
33
+ Gem::Version.new(tag.delete_prefix("v")).prerelease? ? ["--prerelease"] : []
34
+ end
27
35
  end
28
36
  end
@@ -1,36 +1,15 @@
1
1
  module Gempilot
2
2
  class Project
3
+ ## The project's version file (+path+) and value. Bump arithmetic
4
+ ## delegates to SegmentedVersion, so every bump moves strictly forward
5
+ ## under RubyGems ordering.
3
6
  Version = Data.define(:path, :value) do
4
7
  def tag
5
8
  "v#{value}"
6
9
  end
7
10
 
8
11
  def bump(segment = :patch)
9
- case segment.to_sym
10
- when :major, :minor, :patch then bump_semver(segment)
11
- when :dev then bump_dev
12
- else raise ArgumentError, "Unknown segment #{segment.inspect}. Use :major, :minor, :patch, or :dev"
13
- end
14
- end
15
-
16
- private
17
-
18
- def bump_semver(segment)
19
- major, minor, patch = value.split(".").first(3).map(&:to_i)
20
- new_value = case segment.to_sym
21
- when :major then "#{major + 1}.0.0"
22
- when :minor then "#{major}.#{minor + 1}.0"
23
- when :patch then "#{major}.#{minor}.#{patch + 1}"
24
- end
25
- with(value: new_value)
26
- end
27
-
28
- def bump_dev
29
- if value.match?(/\.dev\d+\z/)
30
- with(value: value.sub(/\d+\z/) { it.to_i + 1 })
31
- else
32
- with(value: "#{value}.dev1")
33
- end
12
+ with(value: SegmentedVersion.parse(value).bump(segment).to_s)
34
13
  end
35
14
 
36
15
  alias_method :next_version, :bump
@@ -0,0 +1,64 @@
1
+ module Gempilot
2
+ ## Arithmetic over the three version shapes gempilot accepts: release
3
+ ## (+1.2.3+), tiny release (+1.2.3.1+), and dev prerelease (+1.2.3.dev1+).
4
+ ##
5
+ ## Every bump returns the smallest version of the requested shape that is
6
+ ## strictly greater than the current version under RubyGems ordering, so
7
+ ## bumping always moves a project forward: a dev bump previews the next
8
+ ## patch (+1.2.3+ to +1.2.4.dev1+) and numeric bumps finalize a dev cycle
9
+ ## (+1.2.4.dev2+ to +1.2.4+ for +:patch+).
10
+ SegmentedVersion = Data.define(:major, :minor, :patch, :tiny, :dev) do
11
+ def self.parse(string)
12
+ format = /\A(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:\.(?<tiny>\d+)|\.dev(?<dev>\d+))?\z/
13
+ match = format.match(string)
14
+ raise ArgumentError, "cannot parse version: #{string.inspect}" unless match
15
+
16
+ new(**match.named_captures.to_h { |name, digits| [name.to_sym, digits&.to_i] })
17
+ end
18
+
19
+ def bump(segment)
20
+ case segment.to_sym
21
+ when :major then bump_major
22
+ when :minor then bump_minor
23
+ when :patch then bump_patch
24
+ when :tiny then bump_tiny
25
+ when :dev then bump_dev
26
+ else raise ArgumentError, "Unknown segment #{segment.inspect}. Use :major, :minor, :patch, :tiny, or :dev"
27
+ end
28
+ end
29
+
30
+ def to_s
31
+ [major, minor, patch, tiny, ("dev#{dev}" if dev)].compact.join(".")
32
+ end
33
+
34
+ private
35
+
36
+ def bump_major
37
+ return finalize if dev && minor.zero? && patch.zero?
38
+
39
+ with(major: major + 1, minor: 0, patch: 0, tiny: nil, dev: nil)
40
+ end
41
+
42
+ def bump_minor
43
+ return finalize if dev && patch.zero?
44
+
45
+ with(minor: minor + 1, patch: 0, tiny: nil, dev: nil)
46
+ end
47
+
48
+ def bump_patch
49
+ dev ? finalize : with(patch: patch + 1, tiny: nil)
50
+ end
51
+
52
+ def bump_tiny
53
+ with(tiny: (tiny || 0) + 1, dev: nil)
54
+ end
55
+
56
+ def bump_dev
57
+ dev ? with(dev: dev + 1) : with(patch: patch + 1, tiny: nil, dev: 1)
58
+ end
59
+
60
+ def finalize
61
+ with(tiny: nil, dev: nil)
62
+ end
63
+ end.freeze
64
+ end
@@ -1,3 +1,3 @@
1
1
  module Gempilot
2
- VERSION = "0.3.0".freeze
2
+ VERSION = "0.3.2".freeze
3
3
  end
@@ -50,7 +50,7 @@ module Gempilot
50
50
  end
51
51
 
52
52
  def define_bump_task(project)
53
- desc "Bump version (patch default, or rake version:bump[minor])"
53
+ desc "Bump version (patch default; segments: major, minor, patch, tiny, dev)"
54
54
  task :bump, [:segment] do |_t, args|
55
55
  segment = (args[:segment] || :patch).to_sym
56
56
  old_version = project.version
data/vendor/vendored.gemv CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gempilot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Gillis
@@ -72,6 +72,8 @@ executables:
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
+ - ".claude/memory/be-decisive-not-menus.md"
76
+ - ".claude/memory/flagship-shared-rubocop-config-state.md"
75
77
  - ".claude/skills/using-command-kit/SKILL.md"
76
78
  - ".claude/skills/using-command-kit/cli-example.rb"
77
79
  - ".claude/skills/using-command-kit/generator-pattern.rb"
@@ -107,7 +109,13 @@ files:
107
109
  - data/templates/new/.keep
108
110
  - data/templates/new/command.rb.erb
109
111
  - docs/superpowers/plans/2026-07-20-release-task-hierarchy.md
112
+ - docs/superpowers/plans/2026-08-09-dev-version-bump.md
113
+ - docs/superpowers/plans/2026-09-23-command-generation-bootstrap.md
114
+ - docs/superpowers/plans/2026-09-23-land-betterleaks-jruby.md
115
+ - docs/superpowers/plans/2026-09-23-multi-gem-rubygems-push.md
116
+ - docs/superpowers/plans/2026-09-23-zeitwerk-task-inflector.md
110
117
  - docs/superpowers/specs/2026-07-20-release-task-hierarchy-design.md
118
+ - docs/superpowers/specs/2026-08-09-dev-version-bump-design.md
111
119
  - exe/gempilot
112
120
  - issues.rec
113
121
  - lib/core_ext/string/inflection_methods.rb
@@ -130,6 +138,7 @@ files:
130
138
  - lib/gempilot/project.rb
131
139
  - lib/gempilot/project/version.rb
132
140
  - lib/gempilot/release_tasks.rb
141
+ - lib/gempilot/segmented_version.rb
133
142
  - lib/gempilot/strict_shell.rb
134
143
  - lib/gempilot/version.rb
135
144
  - lib/gempilot/version_tag.rb
@@ -156,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
165
  - !ruby/object:Gem::Version
157
166
  version: '0'
158
167
  requirements: []
159
- rubygems_version: 4.0.16
168
+ rubygems_version: 4.0.22
160
169
  specification_version: 4
161
170
  summary: A toolkit for creating, managing, and releasing your own rubygems
162
171
  test_files: []