Files
commandkit/docs/roadmap/promptkit.md

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, and Engine.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 ConfigScope with 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.