Settle PromptKit roadmap API and presentation decisions

This commit is contained in:
2026-10-12 01:22:50 +00:00
parent 603b6b3758
commit 20e19b9569

View File

@@ -1,8 +1,7 @@
# 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](#open-decisions).
Status: accepted feature end state; implementation has not started. Scope,
ownership, catalog API, and initial presentation choices are settled.
## Purpose and authority
@@ -31,15 +30,17 @@ and [ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md) govern captu
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.
This roadmap defines the selected end state. A later implementation plan should
sequence the work. The present pass updates only this roadmap.
## Current baseline
Baseline: CommandKit commit `ab270e2`.
CommandKit is a prerelease alpha codebase with no existing consumers. The
maintained consumer examples demonstrate intended usage; this adoption needs no
consumer migration plan.
| 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. |
@@ -178,10 +179,9 @@ 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.
new configuration-scope selector. Catalogs use the initial YAML presentation
defined 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
@@ -191,18 +191,27 @@ 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
Successful empty catalogs render as `[]`. Both nil and allocated empty slices
returned by a successful provider represent an empty inventory. 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.
Add independently optional catalog providers to `ckprompt.Suite[I, S]` with these
signatures:
```go
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 standard
selection data fits `ckconfig.Selection`; domain values belong in `I`. Direct
selection input matches the engine loader and existing `Suite.CheckInput`
contract. A separate catalog request wrapper would add no information today.
Results reuse meaningful upstream public types.
`FromEngine(loadEngine)` supplies both catalog callbacks alongside the existing
named-inspection callbacks. It acquires an engine only when the selected catalog
@@ -214,6 +223,10 @@ 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.
Emit each intermediate group only when it has supplied operations: a catalog-only
suite has no `show` group, and a show-only suite has no `list` group, including in
help output.
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
@@ -228,6 +241,52 @@ 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.
### Selecting capabilities
The bundled adapters supply all supported operations: `FromEngine` supplies both
catalogs and both named inspections, and `ConfigScope` includes comparison.
Applications can narrow these declarations before passing them to `Command`.
For example, given an application engine loader `loadEngine`, a show-only
definition suite and a configuration scope limited to show and validate are:
```go
definitions := ckprompt.FromEngine(loadEngine)
definitions.ListPrompts = nil
definitions.ListProfiles = nil
scope := ckprompt.ConfigScope(loadEngine)
scope.Operations = []ckconfig.Operation{ckconfig.Show, ckconfig.Validate}
```
### Initial catalog presentation
Deliver YAML only, default to YAML, and accept explicit `--format yaml`. Catalog
sequences are readable for operators and directly usable by automation. YAML
preserves arbitrary identity strings without a separate text escaping convention.
These are initial catalog presentation choices; additional formats can follow
operator needs. Existing named-show formats remain available.
Emit one bare sequence per invocation. Prompt entries have explicit `id` and
`version` string fields; profile entries are strings. For example:
```yaml
- id: briefing
version: "1"
- id: briefing
version: "2"
```
```yaml
- autumn
- spring
```
The command path identifies the resource, so a bare collection is simple to
consume without an envelope for unused metadata. Preserve provider order and
exact strings; quote through the YAML encoder rather than interpreting
numeric-looking versions. CommandKit defines these report fields explicitly;
serialization of an upstream Go struct does not define the CLI schema.
## Work needed from the baseline
### Dependencies and distribution
@@ -251,12 +310,16 @@ diagnostic delivery, cancellation boundaries, and write-failure handling.
- Extend `ConfigScope` with the native PromptKit comparison provider, retaining
ordinary acquisition and appropriate side diagnostics. Route results through
the existing ckconfig comparison implementation.
- Adapt diagnostic acquisition for comparison deliberately. The current
`loadPromptKitEngine` helper uses a single `promptkit` scope label and can
return on cancellation before collecting inspection diagnostics. Account for
side labels, source legends, and retained diagnostics at failure and
cancellation boundaries when reusing or adjusting it.
- 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.
- Implement the selected catalog YAML presentation, including `[]` for both nil
and allocated empty successful results.
- 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.
@@ -268,16 +331,18 @@ diagnostic delivery, cancellation boundaries, and write-failure handling.
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
module README, and internal overview. Document the bundled adapters' complete
operation sets and how to narrow them. 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.
callback-free help with absent intermediate groups omitted, input/state timing,
exact identities and versions, nil and allocated 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
@@ -303,79 +368,5 @@ 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:
```go
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:
```yaml
- id: briefing
version: "1"
- id: briefing
version: "2"
```
```yaml
- 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.
notices, docs, examples, and boundary validation. The decisions needed for an
implementation plan are settled.