diff --git a/docs/adr/0003-public-facade.md b/docs/adr/0003-public-facade.md index 0443569..acf5928 100644 --- a/docs/adr/0003-public-facade.md +++ b/docs/adr/0003-public-facade.md @@ -2,7 +2,11 @@ ## Status -Accepted. +Partially superseded by [ADR 0010](0010-optional-integration-modules.md). + +ADR 0010 narrows the root facade and public-type ownership decision to the core +module and places optional library dependencies in integration modules. The +remaining principles continue to apply; this record's decision text is retained. ## Date diff --git a/docs/adr/0010-optional-integration-modules.md b/docs/adr/0010-optional-integration-modules.md new file mode 100644 index 0000000..e0c51dc --- /dev/null +++ b/docs/adr/0010-optional-integration-modules.md @@ -0,0 +1,94 @@ +# ADR 0010: Separate the core facade from optional integration modules + +## Status + +Accepted. Partially supersedes +[ADR 0003](0003-public-facade.md) as described below. + +## Date + +2026-10-09 + +## Context + +CommandKit serves consumers that need its command infrastructure with different +combinations of library integrations, including none. A consumer using only the +core should not acquire dependencies belonging to optional integrations. + +ADR 0003 establishes deliberate public contracts and an internal CLI backend +boundary. Those principles remain appropriate. Its initial single root facade, +however, combines core and integration responsibilities. Separate packages within +one module would separate imports while retaining shared module requirements. + +## Decision + +Retain the root `commandkit` package as the core module's public facade. It owns +core command declarations, registration, typed inputs, dispatch, help/version, +shared syntax, diagnostics, and invocation outcomes. + +Provide optional library integrations as separate Go modules with their own +public package contracts. Each integration owns the standard command handlers, +provider contracts, reports, and adapters appropriate to its responsibility. +Applications select integrations and explicitly register their commands; importing +an integration does not install a command family. + +Integrations provide convenient registration of their standard command families, +with standard declarations and handlers supplied by the integration. Applications +provide acquisition and domain-specific context without assembling individual +standard commands or repeating adapter plumbing. More specialized composition +remains available where concrete consumer needs justify it. + +Dependencies point from integrations toward the core. The core's public API, +implementation, and module requirements remain independent of optional +integration libraries. An integration may depend on another integration when +its responsibility requires that relationship. Document such dependencies so +consumers can understand the modules they select. + +Integrations compose through supported public core contracts and preserve +CommandKit's standard grammar, command ownership, help, and outcome conventions. +They do not access private core state or backend structures. Add public contracts +where concrete integration needs justify them, without requiring a general plugin +or backend-selection framework. + +### Relationship to ADR 0003 + +The root-facade and public-type ownership provisions of ADR 0003 now apply to +the core module. Integration-owned public types and operations belong in their +respective public packages. The permission to expose deliberately selected +upstream library types applies within the integrations that depend on them; +it does not justify optional integration dependencies in the core. + +ADR 0003's remaining principles continue to apply across the core and +integrations: deliberate exports, private implementation state, proportionate +internal layering, no exposure of internal or backend types, and preservation of +documented ownership, presence, callback lifetime, and error semantics. Application +input types and caller-supplied values and errors retain their existing handling. +Cobra/pflag remain behind the core's internal adapter. + +This decision changes the scope of the single-facade decision rather than +replacing its contract discipline. ADR 0003 is partially superseded and its +original decision text remains intact. + +## Alternatives considered + +| Alternative | Analysis | +| --- | --- | +| Keep integrations in the root package | Preserves existing imports and simplifies releases, but core consumers acquire optional library dependencies. | +| Use separate packages within one module | Separates compiled imports and retains one release unit, but keeps integration requirements in the shared module graph. | +| Have applications implement integration handlers | Keeps the core independent, but recreates duplicated inspection commands and weakens consistent operator behavior. | +| Introduce universal provider contracts in the core | Could support several libraries through a common model, but adds abstractions and conversion obligations before concrete needs justify them. | + +## Consequences + +Consumers can adopt the core independently and add supported integrations as +needed. Integrations remain maintained parts of CommandKit, with shared CLI +conventions and owning-library semantics. Dependency independence does not mean +the core has no external implementation dependencies. + +Moving existing integration APIs requires a documented consumer migration. +Integration modules add module-specific dependency, validation, and release work. +Core tests, examples, and tools must not reintroduce the optional dependencies +that this boundary removes. + +Exact registration mechanics and release cadence are not selected here. +Current GoDoc and CLI contracts continue to own implemented behavior. diff --git a/docs/roadmap/modules.md b/docs/roadmap/modules.md index e5cdd85..ca65034 100644 --- a/docs/roadmap/modules.md +++ b/docs/roadmap/modules.md @@ -1,6 +1,7 @@ # Optional integration modules -Status: proposed implementation roadmap; no module extraction has begun. +Status: module boundary accepted in ADR 0010; implementation planning remains +in progress and no module extraction has begun. ## Purpose and authority @@ -11,11 +12,13 @@ module dependencies. ConfigKit-only consumers should not acquire PromptKit. This roadmap records the targeted end state, selected module layout, and migration work. 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 +proposals. It does not describe these changes as implemented. +[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. +Alignment of the [architecture policy](../policy/architecture.md) remains part of +the work below. Current implemented contracts remain in GoDoc, the +[CLI reference](../cli.md), and the [consumer guide](../consumers/guide.md). ## Current baseline @@ -108,21 +111,24 @@ is an intentional consumer migration. ## Work sequence -### 1. Settle boundaries and record the decision +### 1. Align policy and settle implementation boundaries + +Completed: ADR 0010 is accepted and ADR 0003 is marked partially superseded, +with its decision text preserved. The partial status follows the explicitly +authorized exception to the documentation policy for this decision. - Resolve the remaining choices under Open Decisions before moving public symbols, using the selected module paths and package names above. -- 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 +- Align the architecture policy with ADR 0010 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. + and that registration meets ADR 0010's convenience principle without replacing + removed boilerplate with new plumbing. Use these examples to evaluate the + registration API; no fixed call count or particular options pattern is selected. Completion: the dependency direction, public migration, and registration approach are concrete enough to implement without inventing a general plugin framework. @@ -220,6 +226,10 @@ Semantic comparison retains the upstream-contract dependency recorded in ### Registration across the new public boundary +ADR 0010 selects convenient family registration with specialized composition +where needed. The remaining decision is how to support it across module +boundaries. + **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