Organize the ConfigKit roadmap around the selected end state

This commit is contained in:
2026-10-11 18:28:14 +00:00
parent f67ee235d7
commit fbee871731

View File

@@ -1,9 +1,8 @@
# Adopt ConfigKit v0.7.1 and expose native configuration comparison # Adopt ConfigKit v0.7.1 and expose native configuration comparison
Status: proposed feature roadmap; dependency adoption and `config diff` are not Status: end-state decisions selected; dependency adoption and `config diff` are
implemented. The targeted delivery includes both, as requested by the user. not implemented. This roadmap brings the decisions and remaining work together;
This document defines the selected end state; a subsequent staged a subsequent staged implementation plan will define execution order.
implementation plan will define execution order.
## Purpose and authority ## Purpose and authority
@@ -38,7 +37,7 @@ disclosure; CommandKit owns selection, coordination, adaptation, and presentatio
| Core module | Go 1.26.0; captured commands, typed bindings, dispatch, outcomes, help, and version. No ConfigKit dependency. ReleaseKit v0.4.0 is the declared maintainer tool. | | Core module | Go 1.26.0; captured commands, typed bindings, dispatch, outcomes, help, and version. No ConfigKit dependency. ReleaseKit v0.4.0 is the declared maintainer tool. |
| `integrations/ckconfig` | Requires ConfigKit v0.5.0. `Scope`, `Suite`, `FromConfigKit`, and `AppCommand` expose scopes/validate/show/sources/explain. No comparison operation or provider exists. | | `integrations/ckconfig` | Requires ConfigKit v0.5.0. `Scope`, `Suite`, `FromConfigKit`, and `AppCommand` expose scopes/validate/show/sources/explain. No comparison operation or provider exists. |
| `integrations/ckprompt` | Directly requires ConfigKit v0.5.0 and PromptKit v0.12.0. Depends on ckconfig's public scope contracts and adapts engine configuration plus named definitions. | | `integrations/ckprompt` | Directly requires ConfigKit v0.5.0 and PromptKit v0.12.0. Depends on ckconfig's public scope contracts and adapts engine configuration plus named definitions. |
| Deferred comparison | [DIFF-01](deferred.md#diff-01-semantic-configuration-comparison) records the target. Native semantics, selection syntax (OD-1), provider representation (OD-2), and the YAML-only report (OD-3) are accepted. | | Deferred comparison | [DIFF-01](deferred.md#diff-01-semantic-configuration-comparison) records the target. Native semantics, selection syntax, provider representation, and the YAML-only report are selected; implementation remains pending. |
The existing ConfigKit adapter acquires a typed `*configkit.Result[T]` and exposes The existing ConfigKit adapter acquires a typed `*configkit.Result[T]` and exposes
its effective, source, and explanation facets through `View`. That generic its effective, source, and explanation facets through `View`. That generic
@@ -61,9 +60,7 @@ evidence, not a completed upgrade validation. See the pinned
[release notes](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/releases/v0.7.1.md) [release notes](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/releases/v0.7.1.md)
and [comparison contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/config.md#effective-configuration-diffs). and [comparison contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/config.md#effective-configuration-diffs).
## Targeted end state ## Dependency adoption and ownership
### Dependencies and module boundaries
Both integration modules select ConfigKit v0.7.1 and carry normal dependency Both integration modules select ConfigKit v0.7.1 and carry normal dependency
metadata for their actual graphs. Consumer Go minimums remain 1.26.0, the selected metadata for their actual graphs. Consumer Go minimums remain 1.26.0, the selected
@@ -81,7 +78,7 @@ Independent module versions remain independent of upstream ConfigKit's version.
Release preparation uses appropriate unused versions under the existing policy, Release preparation uses appropriate unused versions under the existing policy,
without moving tags or claiming unpublished dependencies are available. without moving tags or claiming unpublished dependencies are available.
### Ownership ### Responsibility boundaries
| Owner | Target responsibility | | Owner | Target responsibility |
| --- | --- | | --- | --- |
@@ -91,7 +88,9 @@ without moving tags or claiming unpublished dependencies are available.
| ckprompt | Continue existing integration behavior with the upgraded shared dependency and ckconfig API. Do not claim native PromptKit comparison support through this upgrade. | | ckprompt | Continue existing integration behavior with the upgraded shared dependency and ckconfig API. Do not claim native PromptKit comparison support through this upgrade. |
| Consuming application | Configuration definitions, acquisition callback internals, loader/cache choices, domain interpretation, startup, and process exit. | | Consuming application | Configuration definitions, acquisition callback internals, loader/cache choices, domain interpretation, startup, and process exit. |
### ConfigKit-backed comparison ## Operator behavior
### Availability and scope selection
The `config` family exposes `diff` when at least one scope declares the capability. The `config` family exposes `diff` when at least one scope declares the capability.
Help and `config scopes` report actual availability. A scope can support comparison Help and `config scopes` report actual availability. A scope can support comparison
@@ -102,33 +101,52 @@ acquisition.
`config diff` selects one scope, defaults to `app`, and does not accept `config diff` selects one scope, defaults to `app`, and does not accept
`--scope all`, as selected by ADR 0009. It compares earlier/left and later/right `--scope all`, as selected by ADR 0009. It compares earlier/left and later/right
effective configurations. Both file comparison and base-versus-overlay comparison effective configurations. Both file comparison and base-versus-overlay comparison
are supported through ordinary application loading choices. Exact side selection use the providers' ordinary application-loading contracts.
and inheritance rules are accepted in OD-1 below.
ConfigKit-backed adapters use the same supplied typed loader for existing ### Left and right selections
inspection and both comparison selections. They delegate equality and paired
disclosure to `configkit.Diff`; no rendered-YAML comparison or assertion on
mutable `Result.Config` is introduced. Convenience wiring remains simple:
`AppCommand` and `FromConfigKit` should provide native comparison alongside their
existing supported operations, with ordinary capability narrowing available.
The provider representation is accepted in OD-2.
Declaration capture, metadata discovery, and help leave suite factories and Use existing `--config` and `--overlay` for the left side and add
acquisition/comparison callbacks uninvoked. Invocation preparation uses original `--against-config` and `--against-overlay` overrides for the right side.
typed binding identities and converted values, preserving explicit empty, false, Omitted right fields inherit the left field, including its supplied state;
and zero selections. Supplied values are converted through core once, including explicit right values, including an empty string, replace it. Use the scope's
help paths; applying a value to both comparison inputs does not parse it twice. applicable typed domain selectors on both sides. This supports two files and
Input/state timing for the pair is part of OD-2, rather than an implicit extension base-versus-overlay comparison while reusing familiar syntax and preserving
of the existing one-selection lifecycle. provider-owned defaults. Allow equal selections; they can produce a legitimate
empty diff without an invented requirement that an override be supplied. Do not
short-circuit acquisition merely because the selections are equal: caller-owned
loading may produce different effective results.
For example, these show the accepted target syntax, not current commands:
```text
app config diff --config before.yml --against-config after.yml
app config diff --config base.yml --against-overlay candidate
app config diff --config base.yml --overlay current --against-overlay ""
```
Right-side inheritance is field-by-field. Overriding only the configuration still
inherits the left overlay. For either selection field:
| Left field | Right override | Effective right field |
| --- | --- | --- |
| Omitted | Omitted | Omitted, preserving provider defaults |
| Supplied value | Omitted | Same value and supplied state as left |
| Explicit empty string | Omitted | Explicit empty string, still supplied |
| Any value/state | Supplied value | Right value, supplied |
| Any value/state | Explicit empty string | Empty string, supplied |
The provider continues to interpret an explicitly empty overlay through its
ordinary loading contract; CommandKit does not define empty as disabling overlays.
Domain selector values are shared between sides in this delivery; independent
per-side domain selectors can be considered for a concrete consumer need.
### Comparison meaning and disclosure ### Comparison meaning and disclosure
Retain ConfigKit's native changed-region records at the provider boundary, including Retain ConfigKit's native changed-region records at the provider boundary, including
semantic paths, left/right `Present` and `Redacted` states, safe YAML values, and semantic paths, left/right `Present` and `Redacted` states, safe YAML values, and
`HiddenChanged`. The default report deliberately presents a reduced view under `HiddenChanged`. The YAML report deliberately presents a reduced view rather than
OD-3 rather than exposing all native metadata. exposing all native metadata. The native contract owns detailed comparison
The native contract owns detailed comparison semantics; the important operator semantics; the important operator consequences are:
consequences are:
- Changes reflect frozen effective load values, including defaults and recorded - Changes reflect frozen effective load values, including defaults and recorded
domain resolution. Provenance or source-layout differences alone are not domain resolution. Provenance or source-layout differences alone are not
@@ -152,103 +170,11 @@ upstream disclosure, or adding separately rendered full configurations as if the
had received paired protection. Full paired document context and a sensitivity had received paired protection. Full paired document context and a sensitivity
audit are separate potential capabilities, not prerequisites here. audit are separate potential capabilities, not prerequisites here.
### Reports, diagnostics, and outcomes ### YAML report
Default `config diff` to one YAML document with `additions`, `changes`, and `config diff` emits one YAML document through the existing output streams. YAML
`deletions`, as selected in OD-3. Use existing output streams. YAML is the only is the only report format for this delivery; explicit `--format yaml` is accepted.
supported report format, with explicit `--format yaml` accepted. The Always include the three keys `additions`, `changes`, and `deletions` in that order.
view distinguishes deletion from null but omits separate redaction and concealed-
change metadata. Move the implemented report contract to the CLI reference.
ADR 0008 records this reduced view while retaining native metadata at the
provider boundary. Other commands retain their existing format defaults.
Successful comparisons return success whether they find differences, concealed
changes, or none. No assertion status or separate exit code is added. Load and
comparison failures retain operational classification and supported error
identity; selection/input errors retain usage classification. Output failures
use existing delivery and incomplete-report semantics.
The ConfigKit adapter retains diagnostics from the acquired results, including
warnings and any load failure encountered. Present them through existing core
diagnostic delivery; preserve meaningful left/right context when needed to
identify the failing selection without losing wrapped error identity. Retain
left-side warnings if the right load fails, and diagnostics from both successful
loads if native comparison fails. Finish acquisition and native comparison before
writing a successful diff report. Cancellation is checked at ordinary operation
boundaries; do not promise interruption inside a synchronous upstream call.
## Work needed from the baseline
These are work areas, not numbered implementation stages. Use the accepted
choices below to write the staged implementation plan.
- **Dependency adoption:** upgrade both integration requirements, reconcile sums
and indirect/tool dependencies, and assess PromptKit v0.12.0 against the newly
selected ConfigKit version. Preserve distributed manifests without sibling
replacements or committed workspace files.
- **Capability and provider API:** extend ckconfig's operation/capture/validation
model for the selected comparison provider. Preserve retained adapter errors,
capability narrowing, metadata-only scopes, and validation only of bindings
used by generated commands. Do not require an ordinary acquisition provider
for a comparison-only scope if its selected pair provider is sufficient.
- **Typed preparation:** capture comparison selection metadata and applicable
selector lists once. Prepare/check the selected pair through core bindings,
with state and callback timing from the chosen lifecycle. Keep caller-owned
objects and aliases under existing ownership rules.
- **Native adaptation:** extend the typed ConfigKit adapter/convenience factory
to load the selected pair and call `configkit.Diff`. Reuse diagnostic adaptation
and ordinary error handling without introducing a generic provider framework,
global cache, or untyped result transport.
- **Command and reports:** generate the conditional `config diff` declaration,
integrate it with discovery/help, and render the chosen report contract using
native safe values. Preserve existing operation/report behavior.
- **Documentation and distribution:** update GoDoc, CLI/consumer guidance,
maintained examples, affected module notices and pinned ConfigKit links, and
relevant release notes as implementation lands. Include a maintained comparison
example that loads genuinely different selections through shared state, with
cache keys accounting for the selection and typed-input values used by its
loader. Review transitive tool notices
for the actual graph. Move DIFF-01's implemented portion out of deferred work;
retain unresolved future PromptKit comparison and unrelated proposals.
- **Validation evidence:** run each affected module's deterministic offline suite
and representative consumers. Check module/package boundaries independently
with workspace mode off. If CommandKit prerequisite versions remain unpublished,
use disposable alternate module files for local-source wiring evidence, as
described in the [development guide](../development.md#documentation-validation).
Do not fabricate future checksums or turn migration checks into permanent gates.
Focused comparison coverage should protect the CommandKit boundary: capability
availability before callbacks, side selection/presence, chosen input/state
lifetime, native public and concealed changes, absent versus null values, and
empty successful comparisons. Include representative load/comparison errors,
diagnostics, cancellation, and output failure. Specifically cover left-side
warnings followed by a right-side load failure, and diagnostics from both loads
followed by a comparison failure. Verify that selection-aware caching does not
return the left result for the right selection. Include the three report
categories, explicit null versus deletion, concealed-only changes, and an
unchanged masked value inside a changed sequence. Existing inspection and composed
PromptKit behavior must continue to work. Reuse native collaborators and test
CommandKit's adaptation/reporting; do not duplicate ConfigKit's entire comparator
suite or impose performance thresholds.
## Scope limits and completion
This work delivers ConfigKit adoption and ConfigKit-backed `config diff`.
PromptKit upgrade/comparison/catalogs, JSON reports, per-element sequence matching,
resolved credential comparison, full paired document context, assertion mode,
provider caching, and core backend changes are outside this target.
Completion means upgraded integration dependencies, usable native comparison
through declared scopes and convenience wiring, selected public API/CLI/report
contracts in their current owners, relevant maintained examples, accurate notices,
and sufficient boundary validation. No open choices may be silently converted into
contracts by implementation. Publication follows the existing release procedure
and is not performed by this planning pass.
## Selected report design (OD-3)
**Selected:** the default operator-facing output of `config diff` is a single YAML
document with three primary keys: `additions`, `changes`, and `deletions`.
Additions and changes preserve configuration hierarchy and contain only safe Additions and changes preserve configuration hierarchy and contain only safe
right-side values; deletions are canonical JSON Pointer paths. For example: right-side values; deletions are canonical JSON Pointer paths. For example:
@@ -288,17 +214,14 @@ The default report intentionally does not expose every distinction available in
the native records. A detailed metadata format can be considered separately if the native records. A detailed metadata format can be considered separately if
needed; it is not required for this delivery. needed; it is not required for this delivery.
**Accepted edge-case treatment:** when a nonempty root mapping becomes an empty When a nonempty root mapping becomes an empty mapping, report the native
mapping, report the native removed-key paths under `deletions`. The reduced report removed-key paths under `deletions`. The reduced report
need not add special metadata or a separate envelope solely to distinguish need not add special metadata or a separate envelope solely to distinguish
exceptional whole-root empty/null transitions from an empty comparison. Ambiguity exceptional whole-root empty/null transitions from an empty comparison. That
in that case is acceptable to the user and is not a planning blocker. Native ambiguity is an accepted limit of this reduced report. Native comparison records
comparison records retain their distinctions; ordinary field-level null values retain their distinctions; ordinary field-level null values and deletions retain
and deletions retain the selected reporting rules. the selected reporting rules.
**Accepted format and empty-category treatment:** YAML is the only report format
for this delivery; a separate plain text report adds no needed operator value.
Always include all three keys in the order `additions`, `changes`, `deletions`.
Empty additions and changes render as `{}`; empty deletions render as `[]`. An Empty additions and changes render as `{}`; empty deletions render as `[]`. An
empty comparison therefore produces: empty comparison therefore produces:
@@ -312,75 +235,30 @@ This stable shape supports automated consumption without missing-key handling
and retains the accepted tolerance for exceptional whole-root ambiguity. Other and retains the accepted tolerance for exceptional whole-root ambiguity. Other
commands keep their existing formats. commands keep their existing formats.
ADR 0008 records this selected presentation. Selection syntax and provider shape ### Diagnostics and outcomes
are accepted below. No significant open decisions remain for this roadmap.
**Alternatives considered:** a full difference envelope with left/right snapshots Successful comparisons return success whether they find differences, concealed
and explicit presence, redaction, and hidden-change fields preserves all native changes, or none. No assertion status or separate exit code is added. Load and
metadata, but is more verbose than the chosen operator view. Embedding parsed comparison failures retain operational classification and supported error
values in that envelope avoids YAML strings but retains the record-oriented identity; selection/input errors retain usage classification. Output failures
layout. A right-side-only view without deletion paths cannot represent removals use existing delivery and incomplete-report semantics.
unambiguously. The selected three-category document balances configuration-shaped
output with explicit removal reporting.
Omitting empty categories would shorten the report but require consumers to The ConfigKit adapter retains diagnostics from the acquired results, including
handle missing keys. A separate text report could label changes by path or group warnings and any load failure encountered. Present them through existing core
them into sections, but YAML already provides readable operator output; another diagnostic delivery; preserve meaningful left/right context when needed to
renderer and presentation contract are unnecessary for this delivery. identify the failing selection without losing wrapped error identity. Retain
left-side warnings if the right load fails, and diagnostics from both successful
loads if native comparison fails. Finish acquisition and native comparison before
writing a successful diff report. Cancellation is checked at ordinary operation
boundaries; do not promise interruption inside a synchronous upstream call.
## Accepted Decisions ## Consumer API and execution lifecycle
### OD-1: How operators select the two sides ### Comparison provider and ConfigKit adapters
**Accepted:** use existing `--config` and `--overlay` for the left side and Add a narrow optional comparison callback to `ckconfig.Scope[I, S]`. Its request
add `--against-config` and `--against-overlay` overrides for the right side. groups each side's selection with its separately prepared typed input and supplies
Omitted right fields inherit the left field, including its supplied state; one shared state value separately. Return
explicit right values, including an empty string, replace it. Use the scope's
applicable typed domain selectors on both sides. This supports two files and
base-versus-overlay comparison while reusing familiar syntax and preserving
provider-owned defaults. Allow equal selections; they can produce a legitimate
empty diff without an invented requirement that an override be supplied. Do not
short-circuit acquisition merely because the selections are equal: caller-owned
loading may produce different effective results.
For example, these show the accepted target syntax, not current commands:
```text
app config diff --config before.yml --against-config after.yml
app config diff --config base.yml --against-overlay candidate
app config diff --config base.yml --overlay current --against-overlay ""
```
Right-side inheritance is field-by-field. Overriding only the configuration still
inherits the left overlay. For either selection field:
| Left field | Right override | Effective right field |
| --- | --- | --- |
| Omitted | Omitted | Omitted, preserving provider defaults |
| Supplied value | Omitted | Same value and supplied state as left |
| Explicit empty string | Omitted | Explicit empty string, still supplied |
| Any value/state | Supplied value | Right value, supplied |
| Any value/state | Explicit empty string | Empty string, supplied |
The provider continues to interpret an explicitly empty overlay through its
ordinary loading contract; CommandKit does not define empty as disabling overlays.
Shared domain selector values are the initial scope;
independent per-side domain selectors can be considered with a concrete consumer
need, without precluding them as future API work.
**Alternative considered:** expose symmetric `--left-config`/`--right-config` and
`--left-overlay`/`--right-overlay` selections, resolving each side independently.
This makes two independent selections explicit and avoids inheritance rules. It
adds vocabulary beside existing configuration selectors and repeats flags for
the common single-base overlay workflow. It remains viable if symmetry is valued
more than reuse of familiar inspection syntax.
### OD-2: Comparison provider and input/state lifetime
**Accepted:** add a narrow optional scope comparison callback receiving
the pair's selections, separately prepared left/right typed inputs, and one
shared state value. Group each side's selection and input in a request value to
avoid several positional left/right arguments. Return
`commandkit.Acquired[[]configkit.Difference]` plus an error, following the existing `commandkit.Acquired[[]configkit.Difference]` plus an error, following the existing
acquisition convention. Reuse upstream public record types rather than duplicate acquisition convention. Reuse upstream public record types rather than duplicate
them solely to rename fields. The selected target shape in ckconfig is: them solely to rename fields. The selected target shape in ckconfig is:
@@ -404,35 +282,132 @@ These names and the callback shape are selected for implementation; they are not
implemented exports. ADR 0012 records paired provider ownership and input/state implemented exports. ADR 0012 records paired provider ownership and input/state
lifetimes; this roadmap owns the target declarations until the Go API is implemented. lifetimes; this roadmap owns the target declarations until the Go API is implemented.
The typed `FromConfigKit` adapter can retain its `T`, invoke the supplied loader `AppCommand` and `FromConfigKit` provide native comparison alongside their existing
for each reached side, and call `configkit.Diff`. Existing single-view acquisition supported operations, with ordinary capability narrowing available. They use the
remains responsible for ordinary operations. A comparison-only scope can supply same supplied typed loader for ordinary inspection and both comparison sides,
the pair callback without an unrelated `Acquire` callback. Declared capabilities retaining `T` inside the adapter and passing successful results to `configkit.Diff`.
determine which callbacks must be wired. Do not compare rendered YAML or mutable `Result.Config`.
Existing single-view acquisition remains responsible for ordinary operations.
A comparison-only scope can supply the pair callback without an unrelated
`Acquire` callback. Declared capabilities determine which callbacks must be wired.
### Input preparation and acquisition lifecycle
Use original typed binding identities and converted values, preserving explicit
empty, false, and zero selections. Convert supplied values through core once,
including help paths; applying values to both inputs does not parse them twice.
For a reached comparison, initialize each selection's `I` separately, apply the For a reached comparison, initialize each selection's `I` separately, apply the
same applicable captured selector values, and check it with that side's same applicable captured selector values, and check it with that side's
`Selection`. Finish both input checks before initializing `S` once and invoking `Selection`. Finish both input checks before initializing `S` once and invoking
the pair provider. Omitted factories still supply zero values, including nil the pair provider. Omitted factories still supply zero values, including nil
pointers; separate calls do not guarantee distinct caller objects. Later factories pointers; separate calls do not guarantee distinct caller objects. Later factories
or loads need not run after failure. Help/discovery remain free of these calls. or loads need not run after failure. Declaration construction, installation, help,
version, and scope discovery leave input/state factories and acquisition/comparison
callbacks uninvoked.
ADR 0012 records this two-selection specialization of ADR 0011's suite lifecycle, ADR 0012 records this two-selection specialization of ADR 0011's suite lifecycle,
and the architecture policy reflects it. Document the exact implemented API and the architecture policy reflects it. Document the exact implemented API
contract in Go declarations and GoDoc when it lands. contract in Go declarations and GoDoc when it lands.
This keeps generic result handling inside the owning adapter and preserves ### Application-owned state and caches
typed binding composition without reflection, private-core access, or result
type assertions. Shared state supports consumer caches whose keys distinguish Generic result handling stays inside the owning adapter, without reflection,
the effective selections and any typed-input values that affect loading. A cache private-core access, or result type assertions. Shared state supports consumer
caches whose keys distinguish the effective selections and any typed-input values
that affect loading. A cache
that stores only one configuration can incorrectly reuse the left result for the that stores only one configuration can incorrectly reuse the left result for the
right and report equality. Demonstrate correct keys in the maintained example; right and report equality. Demonstrate correct keys in the maintained example;
CommandKit neither supplies nor repairs application caches. Cache policy and CommandKit neither supplies nor repairs application caches. Cache policy and
factory objects remain caller-owned. factory objects remain caller-owned.
**Alternative considered:** acquire a comparison-capable facet with each ordinary `View`, ## Design tradeoffs
then compare the two acquired facets. This shares single-side acquisition between
all operations and may suit providers already retaining typed results behind a The chosen selection flags reuse existing configuration vocabulary and reduce
stable comparison handle. It requires a public way to establish compatibility repetition for base-versus-overlay comparison. Symmetric `--left-config` /
between two heterogeneous facets, and can lead to type assertions or extra `--right-config` and `--left-overlay` / `--right-overlay` flags would make each side
opaque-handle machinery. Consider it if representative non-ConfigKit consumers independent but add vocabulary and repetition. Independent per-side domain
demonstrate enough benefit to justify that additional contract. selectors remain possible future work for a concrete consumer need.
A comparison-capable facet on each ordinary `View` could share acquisition across
operations, but would require a compatibility contract between heterogeneous
facets and additional handle or type-assertion machinery. The typed pair provider
keeps both results inside their owning adapter and avoids that extra framework.
A full difference envelope could expose both snapshots and all native metadata,
using YAML strings or parsed values. It would be more verbose than the selected
operator view. The three-category report retains configuration-shaped right-side
values while representing removals explicitly. Omitting empty categories would
shorten output but require missing-key handling; a separate text renderer adds no
needed operator value for this delivery.
## Work needed from the baseline
These work areas close the gap from the current implementation to the selected
end state above. A subsequent staged plan will define their execution order.
- **Dependency adoption:** upgrade both integration requirements, reconcile sums
and indirect/tool dependencies, and assess PromptKit v0.12.0 against the newly
selected ConfigKit version. Preserve distributed manifests without sibling
replacements or committed workspace files.
- **Capability and provider API:** extend ckconfig's operation/capture/validation
model for the selected comparison provider. Preserve retained adapter errors,
capability narrowing, metadata-only scopes, and validation only of bindings
used by generated commands. Do not require an ordinary acquisition provider
for a comparison-only scope if its selected pair provider is sufficient.
- **Typed preparation:** capture comparison selection metadata and applicable
selector lists once. Prepare/check the selected pair through core bindings,
with state and callback timing from the chosen lifecycle. Keep caller-owned
objects and aliases under existing ownership rules.
- **Native adaptation:** extend the typed ConfigKit adapter/convenience factory
to load the selected pair and call `configkit.Diff`. Reuse diagnostic adaptation
and ordinary error handling without introducing a generic provider framework,
global cache, or untyped result transport.
- **Command and reports:** generate the conditional `config diff` declaration,
integrate it with discovery/help, and render the chosen report contract using
native safe values. Preserve existing operation/report behavior.
- **Documentation and distribution:** update GoDoc, CLI/consumer guidance,
maintained examples, affected module notices and pinned ConfigKit links, and
relevant release notes as implementation lands. Include a maintained comparison
example that loads genuinely different selections through shared state, with
cache keys accounting for the selection and typed-input values used by its
loader. Review transitive tool notices for the actual graph. Move DIFF-01's
implemented portion out of deferred work; retain unresolved future PromptKit
comparison and unrelated proposals.
- **Validation evidence:** run each affected module's deterministic offline suite
and representative consumers. Check module/package boundaries independently
with workspace mode off. If CommandKit prerequisite versions remain unpublished,
use disposable alternate module files for local-source wiring evidence, as
described in the [development guide](../development.md#documentation-validation).
Do not fabricate future checksums or turn migration checks into permanent gates.
### Focused behavioral evidence
Focused comparison coverage should protect the CommandKit boundary: capability
availability before callbacks, side selection/presence, chosen input/state
lifetime, native public and concealed changes, absent versus null values, and
empty successful comparisons. Include representative load/comparison errors,
diagnostics, cancellation, and output failure. Specifically cover left-side
warnings followed by a right-side load failure, and diagnostics from both loads
followed by a comparison failure. Verify that selection-aware caching does not
return the left result for the right selection. Include the three report
categories, explicit null versus deletion, concealed-only changes, and an
unchanged masked value inside a changed sequence. Existing inspection and composed
PromptKit behavior must continue to work. Reuse native collaborators and test
CommandKit's adaptation/reporting; do not duplicate ConfigKit's entire comparator
suite or impose performance thresholds.
## Scope limits and completion
This work delivers ConfigKit adoption and ConfigKit-backed `config diff`.
PromptKit upgrade/comparison/catalogs, JSON reports, per-element sequence matching,
resolved credential comparison, full paired document context, assertion mode,
provider caching, and core backend changes are outside this target.
Completion means upgraded integration dependencies, usable native comparison
through declared scopes and convenience wiring, selected public API/CLI/report
contracts in their current owners, relevant maintained examples, accurate notices,
and sufficient boundary validation. No significant open decisions remain.
Implementation must not silently add contracts beyond this selected scope.
Publication follows the existing release procedure and is not performed by this
planning pass.