Document the optional integration modules roadmap
This commit is contained in:
261
docs/roadmap/modules.md
Normal file
261
docs/roadmap/modules.md
Normal file
@@ -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.
|
||||
Reference in New Issue
Block a user