Files
commandkit/docs/roadmap/modules.md

300 lines
18 KiB
Markdown

# Optional integration modules
Status: module boundary accepted in ADR 0010; consumer API and internal backend
design finalized, with both composition questions resolved. The
[staged implementation plan](implementation.md) is complete; no module extraction
has begun. ReleaseKit v0.4.0 provides module-release support; CommandKit adoption
is pending.
## 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, selected module layout, and
delivery boundaries. The [implementation plan](implementation.md) owns the ordered
steps and validation needed to reach this target. The finalized
[registration API](registration-api.md) owns the
selected declarations, installation semantics, and representative consumer
examples. The finalized [registration backend design](registration-backend.md)
owns internal structure, shared installation/execution mechanics, and the resolved
composition decisions. These documents describe the implementation target.
[ADR 0010](../adr/0010-optional-integration-modules.md) owns the accepted module
boundary and convenient registration principles; it partially supersedes
[ADR 0003](../adr/0003-public-facade.md), whose remaining principles still apply.
[ADR 0011](../adr/0011-captured-declarations-and-installation.md) records the
finalized registration and invocation-lifetime decisions. The
[architecture policy](../policy/architecture.md) is aligned with those decisions.
GoDoc, the [CLI reference](../cli.md), and the [consumer guide](../consumers/guide.md) describe the prototype baseline; they do
not make its incidental API shapes compatibility requirements for this sprint.
## Organizing principle: design the final API
Give the existing prototype implementation zero deference when selecting the
final API, as directed for this transition. Core `v0.1.0` has since been published;
preserve that release and prepare the incompatible replacement as a fresh minor
release under the release policy. Publication does not change the selected API
or require compatibility wrappers for this sprint. The goal is
the best, simplest, most coherent API for the accepted responsibilities and
representative consumers, not the smallest diff or a mechanically relocated
prototype. Accepted architectural decisions and explicitly selected behavior
remain requirements; prototype declarations, helpers, bookkeeping, and tests do
not independently establish contracts.
Complete the transition in one sprint. No backward-compatibility wrappers,
deprecation period, or migration bridge is needed. Intermediate commits need not
build or pass tests; do not add temporary machinery merely to make them do so.
Validate the complete target state before release. Reuse existing code where it
serves that design, and refactor, replace, or remove it where it does not.
## 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.
- Core `Diagnostic.Severity` currently uses ConfigKit's public severity type;
moving inspection handlers alone will not remove that dependency.
- `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 in this repository with dependencies directed
toward the core. Keep the core at `gitea.maximumdirect.net/eric/CommandKit` and
give each integration its own `go.mod`:
| Directory | Module path | Package name |
| --- | --- | --- |
| Repository root | `gitea.maximumdirect.net/eric/CommandKit` | `commandkit` |
| `integrations/ckconfig` | `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig` | `ckconfig` |
| `integrations/ckprompt` | `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt` | `ckprompt` |
The `integrations/` grouping keeps optional modules together as their number
grows; the anticipated three to ten integrations are planning context, not a
limit or delivery commitment. Distinct package names avoid requiring local
aliases when these integrations are imported alongside ConfigKit and PromptKit.
Separate module files establish dependency isolation; directory naming alone
does not. The shared repository requires explicit multi-module testing and
publication orchestration.
| Module | Responsibility | Integration dependencies |
| --- | --- | --- |
| Core | Application construction, command/group registration, typed bindings, dispatch, help/version, common grammar, outcomes, and diagnostics | Neither ConfigKit nor PromptKit |
| ConfigKit 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 ConfigKit integration |
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 selected configuration boundary moves the existing ConfigKit-shaped
contracts with their handlers into the ConfigKit integration. Only ConfigKit
support is needed for now; a generic configuration interface is outside this
migration. The PromptKit integration may depend on the ConfigKit integration,
consistent with PromptKit's own ConfigKit dependency. Document that relationship
in consumer guidance: `ckprompt` depends on `ckconfig`.
This boundary 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 explicitly selected operator behavior: command vocabulary, selection
and scope semantics, native reports, diagnostics, error identity, outcomes, and
help without provider acquisition. Identify and decide any changes to selected
CLI behavior separately. Do not preserve accidental prototype behavior or Go API
shapes merely because they already exist.
### Selected API and release principles
- Use the finalized [uniform registration API](registration-api.md#declaration-and-installation).
Applications and integrations produce captured core command declarations and
install them through core `New` or `App.Register`; construction errors are
retained for installation-time validation. Integration factories provide
complete families and focused conveniences. The API document owns exact
signatures and the [input/shared-state separation](registration-api.md#why-inputs-and-shared-state-have-separate-types).
- Follow the selected [namespace lifetime and reconciliation requirements](registration-api.md#namespace-reconciliation-and-implementation-handoff).
Built-in help/version remain reserved; optional integration roots are owned
when their real family is installed. ADR 0011 and the architecture policy now
record that lifetime; implementation remains pending.
- Use the finalized [internal registration and execution design](registration-backend.md).
Built-ins, application commands, and integration families share one
[installation path](registration-backend.md#one-installation-path-for-every-command)
and typed compiler. Captured metadata and invocation state have distinct owners;
the backend document defines the capture, binding, routing, and presentation
mechanics without adding another integration installation API.
- Apply the resolved [unused-binding validation boundary](registration-backend.md#resolved-unused-binding-validation-oq-1)
and [scope-error handoff](registration-backend.md#resolved-scope-error-handoff-oq-2).
The registration API incorporates the selected runnable-parent and scope-error
attachment declarations. No absence-validation overload is selected.
- Core diagnostics use a small CommandKit-owned severity type. Upstream
diagnostic conversion belongs in the integrations, preserving selected
classification, delivery, and error semantics without copying ConfigKit's
wider data model into the core.
- Version the modules independently according to their own changes and the
[release policy](../policy/release.md#versioning-and-compatibility). Do not
require integration version numbers to match either the core or upstream
dependency versions. Record selected dependencies in `go.mod` and explain
relevant upstream adoption in module release notes. Coordinate publication
when changes span modules; independent versions do not imply an exhaustive
compatibility matrix.
### Selected multi-module release approach
Adopt ReleaseKit v0.4.0 with module-release support. This is a planned tooling
upgrade from the current v0.3.0 baseline, not an implemented CommandKit capability.
Use ReleaseKit's public contracts for checking and
publishing one explicitly selected module per invocation; do not build a separate
CommandKit publication engine or temporary compatibility path.
Use one shared launcher with small per-module profiles. Each profile selects its
repository-relative module directory and product identity; each invocation
supplies that module's independently selected semantic version. ReleaseKit owns
module-tag derivation, selected-module validation, repository publication guards,
and publication outcomes. Root releases use unprefixed tags. Nested releases use
their Go module-subdirectory prefixes, and notes belong at
`<module-directory>/docs/releases/<version>.md`. Source and licensing links use
the complete Git tag, while note titles identify the product and semantic version.
Run the selected module's standard suite once with workspace mode disabled and
prepared dependencies. Repository cleanliness, branch, candidate commit, and
endpoint guards remain repository-wide. A root-module release does not implicitly
validate independently released nested modules; composition checks are selected
deliberately where needed. Keep successful source-tag publication as completion,
without CI, hosted delivery, proxy-availability, or installation gates.
CommandKit's preferred shared file inputs are repository-root `COPYRIGHT`,
`LICENSE`, and `docs/oss/attribution.md`, when present, rather than the entire
root `docs/` tree. Use v0.4.0's `validation.shared_files` field to select those
three files explicitly, as documented by ReleaseKit. Shared inputs affect enabled
file checks, not Go suite scope; resolving references does not add surrounding
directories to the inputs.
Keep module selection and profile lookup repository-relative, module-owned
validation settings and product-command execution module-relative, and diagnostic
paths repository-relative. Use the provided repository context for shared scripts.
The released [profile](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/config.md)
and [CLI](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/cli.md)
contracts govern profile fields, command syntax, module context, and shared-file
selection. The implementation plan specifies their adoption; no separate
publication engine is needed.
Nested-module artifact builds, hosted delivery, and batch publication are not
needed for CommandKit's source-only releases.
## Consumer examples and validation target
Three maintained public consumers demonstrate the final API:
| Adoption path | Example home | Required evidence |
| --- | --- | --- |
| Core only | `examples/core` | Typed commands/groups, presence, help/version; no optional-library imports or module requirements |
| ConfigKit only | `integrations/ckconfig/examples/simple` | Focused `AppCommand` convenience and standard config reports; no PromptKit imports or module requirements |
| ConfigKit and PromptKit | `integrations/ckprompt/examples/composed` | Combined configuration scopes, typed applicable selectors, independent scope inputs, shared state, named definition inspection, and an application-owned command |
Tests, fixtures, and benchmarks belong to the module owning their contracts.
Mixed suites are split by responsibility; root tests and examples cannot
reintroduce optional integration dependencies. Public composition checks belong
in the PromptKit integration. Relevant existing coverage is retained or rewritten
for selected behavior rather than incidental prototype API shapes.
Validation addresses package imports and each independently selected module
graph, including transitive and tool requirements. Core-only consumers exclude
both owning libraries and integrations; ConfigKit-only consumers exclude
PromptKit and its integration. Root `go test ./...` alone cannot validate nested
modules. The three modules' suites and representative public consumers provide
composition evidence without an exhaustive historical compatibility matrix.
Local workspace composition supports development; distributed manifests contain
versioned inter-module requirements, without filesystem replacements or committed
workspace files. Workspace-off prepublication checks against local intended
source establish wiring and isolation, not published-version availability.
Released consumers resolve actual independently released versions without
adjacent checkouts or consumer replacements. The implementation plan defines the
prepublication checks and ordered release handoff.
## Documentation and distribution target
Implemented GoDoc owns exact exports and error/lifetime semantics. The consumer
guide and READMEs present the final imports and optional-module selection directly;
maintained examples demonstrate it. The CLI reference retains selected operator
behavior, with registration/ownership prose matching the implemented API. Internal
inventory and contributor navigation describe implemented owners and validation.
No separate downstream prototype migration guide is required.
Each integration distributes a module-local README, project grant, complete
license texts, applicable attribution and required notices, and module-local
release notes. Required licensing material remains available in that module's Go
source distribution rather than only through an outside-module local link. The
existing grant and separately licensed material retain their terms. Repository
attribution can retain factual entries for integration material while module-local
notices identify applicable components.
Modules use independent versions. The planned core replacement is `v0.2.0`;
ckconfig and ckprompt initially use `v0.1.0`. Their dependency requirements express
that relationship explicitly. The already published root `v0.1.0` and its note
remain intact. If a planned version is occupied before preparation, select a
fresh appropriate version under the release policy. Core publication precedes
ckconfig, which precedes ckprompt; actual released dependencies and corresponding
sums are prepared for each candidate. Source-only publication still completes at
successful tag publication, without proxy-availability or installation gates.
The release procedure and CommandKit-specific release-policy adaptations describe
selected-module publication, independent versions, semantic-version note paths,
full-tag links and recovery identity, and the root shared-file selection. Release
profiles and launcher use released ReleaseKit contracts; additional delivery
services and permanent migration gates are outside the target.
## Implementation status
ADR/architecture alignment, public API design, and internal backend design are
complete. Module extraction, code refactoring, maintained consumers, validation,
current documentation, and multi-module tooling adoption are not implemented.
The [16-stage implementation plan](implementation.md) owns the sequence and
completion evidence. Earlier accepted ADR decision text remains intact.
## 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.