From 06859b1b093427dabd8115dadb7c774f97ad4339 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Fri, 9 Oct 2026 12:54:28 +0000 Subject: [PATCH] Document the optional integration modules roadmap --- docs/roadmap/modules.md | 261 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 docs/roadmap/modules.md diff --git a/docs/roadmap/modules.md b/docs/roadmap/modules.md new file mode 100644 index 0000000..723be6c --- /dev/null +++ b/docs/roadmap/modules.md @@ -0,0 +1,261 @@ +# Optional integration modules + +Status: proposed implementation roadmap; no module extraction has begun. + +## Purpose and authority + +Make CommandKit useful to consumers that use both ConfigKit and PromptKit, +ConfigKit alone, or neither library. Consumers using only CommandKit's core +should acquire neither ConfigKit nor PromptKit through CommandKit's package or +module dependencies. ConfigKit-only consumers should not acquire PromptKit. + +This roadmap records the targeted end state and migration work. Module names, +repository layout, and other recommendations under [Open Decisions](#open-decisions) +remain proposals. It does not supersede accepted ADRs or describe these changes +as implemented. The [architecture policy](../policy/architecture.md) and +[ADR 0003](../adr/0003-public-facade.md) govern the current boundary; an accepted +successor decision is needed before changing it. Current contracts remain in +GoDoc, the [CLI reference](../cli.md), and the +[consumer guide](../consumers/guide.md). + +## Current baseline + +At the start of this roadmap, CommandKit has one Go module and one supported +public root package. It requires ConfigKit v0.5.0 and PromptKit v0.12.0 and +declares Go 1.26.0. Its internal Cobra adapter implements routing and parsing. + +The root combines core command infrastructure with configuration and PromptKit +inspection. Coupling extends beyond constructors: + +- `NewConfigKitScope` accepts ConfigKit results and maps their diagnostics. +- `SourceReader` returns ConfigKit source records; `ExplanationReader` accepts + ConfigKit paths and returns ConfigKit explanations. +- `PromptKitSuite` callbacks return PromptKit inspection types. +- `NewPromptKitScope` adapts engine configuration into the configuration suite. +- Standard handlers share root-private helpers and state. For example, + configuration registration accesses the application's registry and records + whether the suite has already been installed. + +The [internal overview](../internal/overview.md) describes the implemented +inventory. The maintained examples and integration tests currently belong to the +root module. ReleaseKit v0.3.0 is also selected there as a Go tool dependency; +the [release procedure](../release.md) assumes one module and one version tag. + +Optional command registration currently controls behavior, not dependencies. +Moving integration code into packages sharing the root `go.mod` would separate +compiled imports but retain integration requirements in the module graph. +Go's [module graph rules](https://go.dev/ref/mod#module-graph-pruning) explain +that distinction. + +## Targeted end state + +Provide three consumer modules with dependencies directed toward the core. +Names below identify responsibilities rather than final import paths. + +| Module | Responsibility | Integration dependencies | +| --- | --- | --- | +| Core | Application construction, command/group registration, typed bindings, dispatch, help/version, common grammar, outcomes, and diagnostics | Neither ConfigKit nor PromptKit | +| Configuration integration | Standard configuration family, scope composition, reports, and ConfigKit adapters | Core and ConfigKit; no PromptKit | +| PromptKit integration | Named prompt/profile inspection and the PromptKit configuration-scope adapter | Core, PromptKit, and the configuration integration where needed for scope composition | + +The core remains an opinionated command library with its existing internal +Cobra boundary. The dependency goal is independence from ConfigKit and PromptKit, +not a standard-library-only implementation. + +Integrations remain maintained parts of CommandKit. They install commands into +the same application through supported public core operations and follow its +grammar, help, invocation, and outcome conventions. Applications retain domain +commands, acquisition, runtime construction, streams, and process exit. + +The recommended configuration boundary moves the existing ConfigKit-shaped +contracts with their handlers. It preserves one configuration suite into which +applications compose `app`, `promptkit`, and other supported scopes. PromptKit +configuration inspection and named-definition inspection remain independently +selectable. A module dependency does not automatically install a command family. + +Core public signatures and implementation imports contain no ConfigKit or +PromptKit types. Integration-specific types and helpers move to their owning +modules. Do not retain root forwarding wrappers that restore those imports. +Shared helpers stay private unless a concrete cross-module interaction needs a +supported contract; extraction is not a reason to expose every existing helper. + +Preserve current operator behavior during extraction: command vocabulary, +selection and scope semantics, native reports, diagnostics, error identity, +outcomes, and help without provider acquisition. Any necessary CLI change must +be identified and decided separately. Public Go import and symbol relocation +is an intentional consumer migration. + +## Work sequence + +### 1. Settle boundaries and record the decision + +- Resolve the significant choices under Open Decisions and select module paths + and package names before moving public symbols. +- Create a successor ADR for the changed facade/module boundary and mark + ADR 0003 superseded according to the + [documentation policy](../policy/documentation.md#architecture-decision-records). + Preserve its decision history. Align the architecture policy and review other + ADRs for affected ownership statements without reopening unrelated decisions. +- Inventory root exports, imports, private helper use, and family registration + behavior. Assign each to core or an integration; document the consumer-facing + old-to-new API mapping rather than freezing a full inventory in this roadmap. +- Sketch three representative consumers: core only, ConfigKit only, and both + libraries. Confirm that combined configuration scopes remain straightforward + and that moving code does not replace removed boilerplate with new plumbing. + +Completion: the dependency direction, public migration, and registration approach +are concrete enough to implement without inventing a general plugin framework. + +### 2. Extract the integrations and isolate the core + +- Establish the selected module layout. Keep the existing root import path for + the core under the recommended layout. +- Move configuration declarations, registration, handlers, reports, and + ConfigKit adapters together. Move PromptKit declarations, handlers, reports, + and its configuration-scope adapter into the PromptKit integration. +- Replace access to root-private registry state and helpers with the smallest + supported interactions needed by those integrations. Preserve duplicate + registration handling and standard-family ownership; audit these boundaries + rather than assuming package relocation preserves them automatically. +- Keep core outcomes, diagnostics, bindings, and command declarations as shared + contracts. Place report encoding and upstream diagnostic conversion with their + owners. Avoid copying ConfigKit's data model into the core merely to remove + imports. +- Remove integration dependencies from the core module, including dependencies + reintroduced by its tests, examples, tools, or remaining public declarations. + Review tool dependencies for that specific objective; broad removal of all + maintainer dependencies is not a prerequisite. +- Use released inter-module requirements for consumer builds. Local workspace + composition may support development, but published modules must not depend + on sibling checkouts or consumer-applied `replace` directives. + +Completion: core-only and ConfigKit-only consumers have the intended dependency +boundaries, while the composed consumer retains the existing standard commands. + +### 3. Move examples and validate the consumer boundaries + +- Keep a genuine core-only example with no configuration-library imports. Place + ConfigKit and composed examples, fixtures, and integration tests in modules + that can legitimately depend on those integrations. Choose their exact home + with the module layout; examples in the root module must not defeat isolation. +- Move existing behavioral tests with their owners. Retain coverage for typed + presence, repeated invocations, registration collisions, provider errors, + report delivery, and preserved CLI behavior without duplicating every suite. +- Add focused consumer checks for the three adoption paths. Verify both package + dependencies and the selected module graph, including transitive requirements. + Core-only checks exclude both libraries; ConfigKit-only checks exclude + PromptKit. Merely observing a smaller executable is insufficient. +- Exercise combined `app` and `promptkit` configuration scopes and independent + installation of named PromptKit inspection through public APIs. +- Run each module's relevant suite. Verify ordinary module consumption with + workspace mode disabled so local workspace resolution cannot hide missing + requirements. Root `go test ./...` alone will not cover nested modules. + +Completion: representative public consumers demonstrate isolation and retained +composition. These checks protect the selected boundary without requiring an +exhaustive matrix of historical dependency versions. + +### 4. Prepare migration documentation and module releases + +- Update GoDoc, the consumer guide, maintained examples, README, internal + inventory, and contributor reading guide as the implementation lands. Keep + the CLI reference unchanged except where actual behavior or relevant ownership + changes require an update. Link this roadmap from contributor navigation when + integrating it into the implementation workflow. +- Explain moved imports and constructors and the selection of optional modules. + Release the incompatible root API change according to the + [release policy](../policy/release.md#versioning-and-compatibility); do not + publish it as a compatible patch. Inspect actual publication state when + selecting versions and preserve existing published tags and notes. +- Adapt release profiles, module discovery, validation, note locations, version + reporting, and publication commands to the selected release model. Verify + ReleaseKit's supported capabilities before choosing the mechanics; the current + single-module profile is not evidence of multi-module support. +- For nested modules, use Go's module-subdirectory tag prefixes and make + release-note paths and immutable links unambiguous. Review licensing and + attribution visibility in each distributed module under the + [OSS policy](../policy/oss.md). +- Establish publication order from module dependencies and record compatible + requirements explicitly. Published consumers must resolve actual released + versions. A local workspace is not a substitute for that release sequence. + Preserve the existing successful-source-publication completion model. + +Completion: every consumer module can be released and consumed independently of +local workspace state, with a documented migration from the combined API. + +## Scope and follow-up + +This work changes packaging and integration boundaries. It does not select a +new backend, concurrent-dispatch contract, dynamic plugin system, or replacement +configuration engine. It does not lower the existing Go minimum. + +Keep the PromptKit v0.13.0 and ConfigKit v0.6.0 adoption identifiable as a separate +change after extraction unless an implementation dependency justifies combining +them. Catalogs and requirement discovery are subsequent integration features. +Semantic comparison retains the upstream-contract dependency recorded in +[deferred work](deferred.md). None is needed to demonstrate module isolation. + +## Open Decisions + +### Repository layout and module paths + +**Recommendation:** keep the core at the existing repository root and create +nested integration modules in this repository, for example under +`integrations/configkit` and `integrations/promptkit`. These paths are proposals. +One repository makes coordinated API changes and shared maintenance convenient +while separate `go.mod` files provide consumer dependency isolation. The cost is +explicit multi-module testing, prefixed tags, and release orchestration. + +**Alternative:** publish the integrations from separate repositories. Each can +use a simpler single-module release procedure and evolve independently. This is +viable if ReleaseKit or maintainer preferences make nested-module publication +awkward, but coordinated changes, examples, and documentation require more +cross-repository work. Settle this before publishing integration import paths. + +### Ownership of the configuration family + +**Recommendation:** place the existing configuration family and its +ConfigKit-shaped provider contracts in the configuration integration. Let the +PromptKit integration depend on it to supply a compatible scope. This follows +the current code and avoids a speculative common data model. The tradeoff is +that non-ConfigKit providers using that suite still depend on ConfigKit contracts; +core-only custom commands remain available without them. + +**Alternative:** define library-independent configuration reports and provider +contracts in core or a separate configuration module, then adapt both owning +libraries. This could benefit consumers wanting standard configuration commands +over unrelated libraries. It adds conversion, public contract ownership, and +possibly another module before such a consumer has demonstrated the need. +Select it only if representative usage justifies those costs and preserves native +inspection semantics. + +### Registration across the new public boundary + +**Recommendation:** first reuse public command/group registration and duplicate +path checks. Add only a narrow core registration capability if preserving the +existing standard-family ownership contract requires it. This keeps integrations +ordinary Go libraries and avoids exporting root-private state. Its suitability +must be checked against reserved paths and registration atomicity during the API +inventory. + +**Alternative:** introduce an explicit public family declaration and installation +API for all standard suites. This can give ownership and collision handling a +clear shared representation if ordinary registration proves insufficient. It +also creates a new long-lived abstraction that may duplicate command groups; +prefer it only when the concrete extraction shows a distinct responsibility. + +### Versioning and publication cadence + +**Recommendation:** version modules independently, declare their supported +minimum dependency versions through ordinary module requirements, and coordinate +releases when changes span modules. Core-only consumers then avoid unrelated +integration releases. This requires clear per-module notes and publication +ordering; exact tooling and note placement need verification before adoption. + +**Alternative:** release all three modules with matching version numbers on a +coordinated cadence. A single documented release set simplifies communication +and initial testing, while still retaining separate dependency graphs. It causes +unchanged modules to receive releases and still needs distinct Go tags and +inter-module dependency ordering; matching numbers alone do not enforce +compatibility. Neither choice implies support for every possible version +combination.