Skip to the content.

ADR 0015: Descope v1.0 to standalone CLI; plugins to v1.x; TUI to v2.0

Status: Accepted Date: 2026-05-04 Amends: ADR-0014

Context

The current v1.0 plan (ROADMAP as of 2026-05-04, before this ADR) ships three entry points:

  1. Standalone CLI binary (gem-contribute) — bare invocation launches the Rooibos TUI
  2. Bundler plugin (bundle contribute) — CLI-only
  3. RubyGems plugin (gem contribute) — CLI-only

ADR-0014 (2026-05-03) committed to that scope. It amended ADR-0006’s “no Bundler plugin” decision and ADR-0012’s “three separate gems” sketch. The reasoning was sound: workshop is over, the plugin shims are small, one gem with three entry points is cheap to maintain.

What ADR-0014 didn’t examine is shipping order. It treated all three entry points as v1.0 prerequisites because that was the existing v1 frame. Phases 3 (TUI), 4 (Bundler plugin), and 5 (RubyGems plugin) on the ROADMAP all sit between “service layer done” and “v1.0 ships.”

Two facts shift the calculus on shipping order:

  1. Phase 3 (TUI) is the single biggest piece of remaining work. Five fragments, an auto-launch wiring change, snapshot tests, and a Rooibos pin verification. Realistically months of work for a solo project that doesn’t have it started. Holding 1.0 behind it means the gem stays unpublished while design assumptions about TUI fragments accumulate without real-user contact.

  2. Phases 4–5 (plugins) are thin shims. Their architecture is already locked in by ADR-0014 (single gem, dispatch table is the source of truth). The remaining design questions — default verb for bundle contribute (per OPEN_QUESTIONS Q3a), error/output styling, where the plugin install smoke test sits — are exactly the kind of UX questions that benefit from “what do real CLI users actually do.” Building plugin UX on assumptions before any rubygems user exists is a worse trade than shipping the CLI, watching usage, then committing to plugin shape with information.

The Blue Ridge Ruby workshop concluded 2026-05-02 (the same context that drove ADR-0013 and ADR-0014). Workshop-era decisions about scope are revisitable.

Decision

v1.0 ships the standalone CLI alone. Three entry points become a release sequence rather than a launch bundle:

The “single gem with three entry points” architecture decision in ADR-0014 is preserved. Plugins still ship inside the gem-contribute gem; they don’t become separate gems. What changes is when, not what.

Reasoning

Real users beat planned roadmap. Every month before the gem hits rubygems.org is a month of design assumptions about TUI fragments, plugin defaults, and edge cases that no real user has stress-tested. Shipping a CLI 1.0 in days converts that uncertainty into evidence. The TUI design that ships in 2.0 will be informed by what real users actually do; the plugin shape that ships in 1.x will be informed by what CLI patterns turn out to matter.

ADR-0014’s architectural decision survives intact. The v1 commitment to “plugins live inside gem-contribute, not as separate gems” was the load-bearing call. Whether they ship at v1.0, v1.1, or v1.2 doesn’t affect the architecture — the dispatch table is already the single source of truth, the plugin entry-point files (plugins.rb, rubygems_plugin.rb) are tiny additions when the time comes. Deferring is purely sequencing.

TUI as 2.0 reflects the actual size of the change. A TUI is not a polish layer; it’s a different interaction model. Treating it as a major-version event matches the user-visible weight: bare-invocation behavior changes, dependencies grow (rooibos, ratatui_ruby move from optional to default), terminal-capability assumptions enter the install path. SemVer-clean.

Plugins as 1.x because the CLI surface stays compatible. bundle contribute and gem contribute are additive — they expose the existing CLI verbs through new entry points. No breaking change for users on gem-contribute directly. SemVer-minor fits.

Repo adapters as 1.x because they extend reach without changing existing behavior. GitLab and gem.coop adapters expand which gems are scannable; they don’t change how scanning works for github.com gems. SemVer-minor fits.

Alternatives considered

Consequences

On the v1 statement at the top of docs/ROADMAP.md (line 3-9 currently): rewrite. The “single gem, three entry points” framing moves to 2.0; v1.0 is a CLI-on-rubygems release.

On phase numbering and labels:

On ADR-0014: add an “Amended by ADR-0015” header note. The body of ADR-0014 stays valid — the architectural commitment to “single gem, plugins-not-separate-gems” is unchanged. Only the implicit “all three entry points at v1.0” assumption is amended.

On README.md (#46 rewrite): the v1 audience messaging frames the gem as a CLI tool. TUI gets a “coming in v2” mention; plugins get a “coming in v1.x.” Avoids over-promising what 1.0 actually delivers.

On OPEN_QUESTIONS.md: Q3a (default verb for bundle contribute) becomes a v1.x decision. Doesn’t block 1.0.

On MAINTAINER.md: the per-release checklist applies identically to 1.x point releases as to 1.0. No changes needed.

On the existing PR queue: PR #51 (Phase 2) and PR #55 (release infra + 0.3.1) are both unaffected — their content is in v1.0 either way. No re-scoping needed for in-flight PRs.

On polish issues:

What this doesn’t change