22 KiB
Adopt PromptKit v0.14.0 and expose comparison and catalogs
Status: proposed feature end state; implementation has not started. The scope and ownership direction are agreed. Catalog API and presentation choices remain under Open Decisions.
Purpose and authority
CommandKit provides useful, consistent access to capabilities owned elsewhere.
Adopt PromptKit v0.14.0 and expose its native configuration comparison and
definition catalogs without requiring applications to duplicate command
infrastructure. Defer a standard command for Engine.InspectRequirements to
the next pass.
CommandKit owns command vocabulary, registration, selection, coordination, presentation, and invocation outcomes. PromptKit owns the meaning of its configuration inspection and catalogs, including which effective definitions exist and the comparison capability it exposes. PromptKit delegates its native comparison to ConfigKit. The adopted upstream public contracts remain authoritative; this roadmap does not establish a second CommandKit definition of their semantics or disclosure rules.
The architecture policy controls dependency direction and ownership. ADR 0004 already selects the standard catalog commands; ADR 0008 governs native comparison, ADR 0009 governs independent scope capabilities, and ADR 0010 governs optional modules. ADR 0011 and ADR 0012 govern captured declarations and input/state lifetimes. Existing deliberately selected contracts control; prototype implementation shapes receive no compatibility preference.
This is a feature roadmap, not a staged coding assignment. A later implementation plan should sequence the work after the open decisions are resolved. Only this roadmap is added in the present pass; it does not upgrade dependencies, revise ADRs, change current behavior documentation, or run Go tests.
Current baseline
Baseline: CommandKit commit ab270e2.
| Owner | Current state |
|---|---|
| Core | Go 1.26.0; declarations, registration, typed bindings, dispatch, help/version, diagnostics, and outcomes. Cobra/pflag remain internal. No optional owning-library dependency. ReleaseKit v0.4.0 is the declared maintainer tool. |
integrations/ckconfig |
ConfigKit v0.7.1; independent validate/show/sources/explain/diff capabilities, paired selection/input preparation, and the shared YAML comparison report and delivery path. Report placement uses a report-local mapping index. |
integrations/ckprompt |
PromptKit v0.12.0 and ConfigKit v0.7.1. ConfigScope exposes validate/show/sources/explain, without comparison. Suite and FromEngine expose named prompt/profile inspection; Command generates only promptkit show children. |
| Maintained composed consumer | Demonstrates both configuration scopes, app configuration comparison, named prompt/profile inspection, and an application-owned session command. Application configuration caching distinguishes selections and supplied campaign inputs. |
| Deferred work | PromptKit comparison and catalogs are recorded as future capabilities in deferred.md. They are targets of this adoption; requirement inspection is deferred separately. |
The existing ckprompt contracts and adapters and command assembly are the starting points. ckprompt already depends on ckconfig's public scope contracts; no new module or dependency reversal is needed.
Upstream adoption
Target PromptKit v0.14.0, source commit
143c6e9b3a675872117b0471e2ff8bcb25055a54. Relevant pinned sources are its
v0.13.0 release notes,
v0.14.0 release notes,
configuration inspection API,
and listing API.
Relative to CommandKit's selected v0.12.0:
- v0.13.0 adds
Engine.ListPrompts,Engine.ListProfiles, andEngine.InspectRequirements, plus allocation and inspection improvements. - v0.14.0 adds
ConfigurationInspection.Diff, returning ConfigKit's public difference records from two captured configuration inspections. - The Go consumer minimum becomes 1.26.0, already met by all CommandKit modules. ConfigKit v0.7.1 and the YAML version also match CommandKit's current selection.
- PromptKit selects ReleaseKit v0.4.1 as its maintainer tool. That version is already selected through ConfigKit in the integration graphs. Adoption does not itself change core's separately declared release tool or launcher.
The reviewed existing public inspection and construction signatures remain available. Adoption must still check CommandKit's existing reports and error handling against the upgraded implementation; a source review is not evidence that the upgraded integration suites have passed. No upstream feature addition is needed for the selected comparison and catalog goals.
Target ownership and package shape
| Owner | Target responsibility |
|---|---|
| PromptKit | Supported configuration comparison and catalog APIs, effective membership, identity/version interpretation, native results, ownership, and disclosure contracts. |
| ConfigKit | Native effective-value comparison and paired safe snapshots used by PromptKit. |
| ckprompt | PromptKit adapters; engine acquisition and diagnostic adaptation; declaring comparison on its configuration scope; catalog callbacks, standard list handlers, and catalog presentation. |
| ckconfig | The existing config family, capability preflight, selection inheritance, paired typed inputs, shared-state coordination, comparison YAML rendering, and report delivery. |
| Core | Existing captured declarations, binding conversion/presence, installation, dispatch, help/version, and outcomes. No PromptKit-specific model. |
| Application | Source definitions, domain selector interpretation, loaders and caches, callback effects, runtime operations, stream selection, and process exit. |
Dependencies continue to point from ckprompt to ckconfig and core. ckconfig does not import or require ckprompt or PromptKit; core remains independent of both integrations. Reuse ckconfig's public contracts and installed command paths. No duplicate comparison renderer, core provider registry, comparison facet, backend change, sibling-internal import, or general plugin framework is needed. Private helper organization remains an implementation choice.
PromptKit configuration comparison
Operator end state
ckprompt.ConfigScope(loadEngine) declares ckconfig.Diff alongside its existing
operations. Installing that scope through ckconfig.Command makes these
invocations available:
app config diff --scope promptkit --config before.yml --against-config after.yml
app config diff --scope promptkit --config base.yml --against-overlay candidate
These are target invocations, not currently implemented PromptKit comparisons.
They use the existing comparison CLI contract:
one scope, left selectors and inherited right overrides, shared applicable domain
selector values, YAML-only additions/changes/deletions presentation, and success
for completed comparisons regardless of whether differences exist. There is no
new promptkit diff command, scope aggregation, report envelope, or exit status.
Help and config scopes reflect the actual declared capability. Other scopes
remain free to support their own operation subsets.
Adapter end state
The scope's Compare callback consumes the existing
ckconfig.ComparisonRequest[I] and shared S. ckconfig prepares and checks each
reached side's typed input, then initializes shared state once. The bundled
PromptKit adapter invokes the supplied engine loader for left and then right,
using each side's selection/input and that same state, obtains each engine's
InspectConfiguration view, and calls left.Diff(right).
Return commandkit.Acquired[[]configkit.Difference] with accumulated diagnostics
and supported error identity preserved. The existing ckconfig report path
consumes those records. Ordinary operations continue through Acquire and the
existing inspection facets. A caller may narrow the scope's capabilities or
supply its own pair provider under the existing scope contract; original adapter
construction errors remain attached when capabilities are narrowed.
For the bundled adapter, retain diagnostics from each reached load or inspection, identify left/right context and native source legends, keep left diagnostics if right acquisition fails, and keep both sides' diagnostics if comparison fails. Use existing cancellation checks at operation boundaries and finish report preparation before delivery. The upstream Diff method is synchronous and takes no context; do not promise interruption inside it or transactional writer output.
Equal selections alone do not skip the pair provider or the bundled adapter's reached loader calls. Application caches determine whether calls construct new engines or reuse captured ones. CommandKit does not supply, inspect, or repair those caches or promise physical source reloads or distinct factory objects.
Meaning and presentation
Delegate to PromptKit's adopted comparison contract. Its current API compares captured effective configurations through ConfigKit, rather than source-history text, referenced file contents, resolved credentials, or later request-specific execution state. These are upstream semantics, not independently frozen CommandKit guarantees. An empty configuration comparison does not establish equivalent execution.
Preserve native record evidence at the provider boundary and use the existing safe right-side YAML presentation. Follow the adopted upstream classification; do not add blanket masking of provider parameters or infer metadata from mask text. Ordinary prompt/provider content can remain application data. Applications retain their disclosure choices and callback effects.
Prompt and profile catalogs
Operator end state
Extend the optional promptkit family with the command paths already selected
by ADR 0004:
app promptkit list prompts
app promptkit list profiles
Each command accepts configuration/overlay selection and the applicable existing suite domain selectors, without requiring a definition ID or exact-version operand. These commands use the namespace's engine selection, rather than a new configuration-scope selector. Catalog report formats and YAML shape remain the presentation decisions below. No filtering, pagination, version-priority rule, requirement discovery, or per-definition readiness check is added in this delivery.
The bundled adapter obtains prompt ID/version pairs with Engine.ListPrompts
and profile IDs with Engine.ListProfiles. It preserves returned identities
and order without reconstructing catalogs from configuration YAML or invoking
named inspection for each entry. PromptKit's current lists describe effective
membership, include maintained definitions that remain effective, and order
identities lexically; prompt versions are not ranked semantically. Upstream
remains authoritative if its adopted contract evolves.
Successful empty catalogs produce an empty collection under the selected format. They do not fail because there are no definitions. Membership does not prove execution readiness. Identifiers retain their exact values, including values that require YAML quoting; CommandKit does not normalize identifiers or promise that catalog data is safe for arbitrary public disclosure.
Consumer and invocation end state
Add independently optional catalog providers to ckprompt.Suite[I, S], using
commandkit.Acquired[[]promptkit.PromptIdentity] and
commandkit.Acquired[[]string] as their results. Reuse meaningful upstream public
types. The request shape recommendation is under OD-1.
FromEngine(loadEngine) supplies both catalog callbacks alongside the existing
named-inspection callbacks. It acquires an engine only when the selected catalog
operation is reached, calls the corresponding native listing API, and returns
adapted load diagnostics with the result or error. Listing itself does not
execute prompts or contact model providers; application loaders and custom
callbacks retain their own effects.
Command(suite) captures metadata, bindings, and callback references and emits
only supplied operations. Listing can be installed without either named-show
callback; named-show operations can remain installed without catalog callbacks.
An entirely absent suite contributes no namespace or commands, while attached
construction errors are still reported. A nonempty family remains root-only and
owns its namespace under the existing installation contract. Importing ckprompt
does not install a family; configuration-scope and definition-family installation
remain independent.
For one reached catalog invocation, prepare one I, apply the captured converted
selectors, complete existing input checks, initialize S once, and invoke the
selected provider. Preserve supplied empty/false/zero values, original binding
identity, nil-factory zero values, and caller ownership. Installation, help, and
version invoke neither suite factories nor providers; operator-requested listing
does acquire its selected inventory. Use existing usage/operational outcomes,
diagnostic delivery, cancellation boundaries, and write-failure handling.
Work needed from the baseline
Dependencies and distribution
- Upgrade ckprompt's PromptKit requirement from v0.12.0 to v0.14.0 and reconcile real module-local checksums and legitimate indirect requirements. Retain ConfigKit v0.7.1, Go 1.26.0, and the existing core/ckconfig versioning policy.
- Preserve ignored development workspace wiring. Distributed manifests must not acquire sibling replacements or invented checksums for unpublished CommandKit modules. Reuse the existing isolated-module validation approach where needed.
- Update PromptKit's module-local attribution and source-pinned license/notice links under the OSS policy. Review actual selected graphs; do not copy workspace-selected tool versions into core's declaration/notices.
- Reconcile prepared integration release notes with the delivered capabilities under the release policy. Publication, tag selection, and independent module release ordering remain with the release procedure; this adoption does not publish a release.
Adapters and command assembly
- Extend
ConfigScopewith the native PromptKit comparison provider, retaining ordinary acquisition and appropriate side diagnostics. Route results through the existing ckconfig comparison implementation. - Extend
Suite,FromEngine, and family assembly for independent prompt/profile catalog providers. Use core declarations and typed binding composition for selection and input preparation; add no second parser. - Implement catalog presentation after OD-2 and OD-3 are resolved. Define CommandKit-owned report fields explicitly instead of treating serialization of an upstream Go struct as a permanent CLI schema. Preserve upstream values.
- Keep implementation proportionate. Reuse existing acquisition, preparation, diagnostic, YAML, and outcome helpers where they fit; introduce only the concrete helper changes needed for the new operations.
Examples, documentation, and behavioral evidence
- Extend the maintained composed consumer with PromptKit-scope comparison and both catalog commands. Reuse its selection-aware application loading so two configurations yield meaningfully different engine inspections. Its cache choices remain example choices, not policy for consumers.
- When behavior lands, update owning GoDoc, the CLI reference, consumer guidance, module README, and internal overview. Replace claims that PromptKit comparison and catalogs are unavailable. Reconcile the completed ConfigKit roadmap's PromptKit status and the deferred-work record; retain requirement inspection as explicitly deferred without inventing its future syntax.
- Validate existing show/validate/sources/explain behavior, named prompt/profile reports, app comparison, and the composed domain command against the upgraded dependency. Add focused evidence for catalog-only and mixed capabilities, callback-free help, input/state timing, exact identities and versions, empty inventories, native comparison, diagnostics retained across side failures, cancellation, and report delivery failures.
- Prefer assembled behavior and real fast native collaborators. Reuse ckconfig's existing report/lifecycle coverage; do not duplicate ConfigKit's comparator or PromptKit's full catalog suite, freeze private layout or polling counts, or introduce performance, concurrency, or release gates through tests.
- Establish compatibility through relevant module suites, maintained consumers, and workspace-off dependency/import checks. Local replacements for unpublished CommandKit prerequisites prove local-source compatibility, not availability of future tags. These checks belong to implementation, not this prose-only pass.
Scope limits and completion
The target is PromptKit v0.14.0 adoption, usable PromptKit-scope configuration comparison, and independently selectable prompt/profile catalog commands with current API/CLI documentation and representative consumer evidence. Existing ADRs cover this direction; exact catalog signatures and report shapes belong in their canonical owners when implemented.
Engine.InspectRequirements is available through the upgraded dependency, but a
standard CLI command for it is deferred to the next pass. It is not integrated
into configuration validation or ordinary prompt display here. Execution,
preparation, rendering, credential probing, mutation, independent per-side domain
selectors, assertion statuses, JSON output, new scope aggregation, and backend
changes remain outside this delivery.
Completion requires all selected capabilities and relevant dependency metadata, notices, docs, examples, and boundary validation. Resolve the open decisions before producing a decision-complete implementation plan. Recommendations below are proposals, not already accepted CLI or Go contracts.
Open Decisions
OD-1: Catalog callback request shape
Recommendation: Add ListPrompts and ListProfiles fields with direct
ckconfig.Selection input, separate I and S, and the existing acquisition
convention. The proposed signatures are:
ListPrompts func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]promptkit.PromptIdentity], error)
ListProfiles func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]string], error)
Catalog commands have no selected definition ID or version. Their only standard
selection data is already represented by ckconfig.Selection; domain values
belong in I. This keeps the API small and matches the existing engine-loader
shape without adding a request wrapper solely for speculative future fields.
Alternative: Introduce a ckprompt-owned CatalogRequest containing
Selection, and use it for both callbacks. This matches the request-object
style of existing named-inspection providers and creates a place for future
catalog-specific options. It is viable, but adds a public type with no additional
information today. Choose it if that consistent provider shape is judged more
valuable than the narrower current surface; neither choice requires a core API
change.
OD-2: Catalog report formats and default
Recommendation: Deliver YAML only, default to YAML, and accept explicit
--format yaml. Catalog sequences are readable for operators and directly
usable by automation. This keeps one presentation path, preserves arbitrary
identity strings without designing a separate escaping convention, and follows
the recent comparison report's deliberately small format scope. This is a
recommendation for these new commands, not a policy that all families must use
the same formats.
Alternative: Support text and YAML, defaulting to text as existing
promptkit show commands do. One profile per line and prompt ID/version columns
are convenient for terminal use and keep the namespace's format defaults more
uniform. The cost is a second renderer and a decision about unambiguous display
of identities containing whitespace or line breaks. YAML-only listings can still
coexist with the established show-command formats without changing them.
OD-3: YAML catalog document shape
Recommendation: Emit one bare sequence per invocation. Prompt entries have
explicit id and version string fields; profile entries are strings. For
example:
- id: briefing
version: "1"
- id: briefing
version: "2"
- autumn
- spring
An empty inventory renders as []. The command path already identifies the
resource, so a bare collection is simple to consume and does not add an unused
metadata framework. Preserve provider order and exact strings; quote through
the YAML encoder rather than interpreting numeric-looking versions.
Alternative: Wrap the collections under prompts: and profiles: keys.
This gives each report a self-describing resource label and leaves room for
later metadata without changing the root type. It is a reasonable choice if
reports will routinely be stored without their command context. It also adds
nesting and anticipates metadata this delivery does not need; an empty report
would be prompts: [] or profiles: [] instead of a bare empty sequence.