Organize the ConfigKit roadmap around the selected end state
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
# Adopt ConfigKit v0.7.1 and expose native configuration comparison
|
||||
|
||||
Status: proposed feature roadmap; dependency adoption and `config diff` are not
|
||||
implemented. The targeted delivery includes both, as requested by the user.
|
||||
This document defines the selected end state; a subsequent staged
|
||||
implementation plan will define execution order.
|
||||
Status: end-state decisions selected; dependency adoption and `config diff` are
|
||||
not implemented. This roadmap brings the decisions and remaining work together;
|
||||
a subsequent staged implementation plan will define execution order.
|
||||
|
||||
## 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. |
|
||||
| `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. |
|
||||
| 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
|
||||
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)
|
||||
and [comparison contract](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/6fffde4af8f31f99d3ee295c426eb3234cb0fb77/docs/config.md#effective-configuration-diffs).
|
||||
|
||||
## Targeted end state
|
||||
|
||||
### Dependencies and module boundaries
|
||||
## Dependency adoption and ownership
|
||||
|
||||
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
|
||||
@@ -81,7 +78,7 @@ Independent module versions remain independent of upstream ConfigKit's version.
|
||||
Release preparation uses appropriate unused versions under the existing policy,
|
||||
without moving tags or claiming unpublished dependencies are available.
|
||||
|
||||
### Ownership
|
||||
### Responsibility boundaries
|
||||
|
||||
| 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. |
|
||||
| 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.
|
||||
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
|
||||
`--scope all`, as selected by ADR 0009. It compares earlier/left and later/right
|
||||
effective configurations. Both file comparison and base-versus-overlay comparison
|
||||
are supported through ordinary application loading choices. Exact side selection
|
||||
and inheritance rules are accepted in OD-1 below.
|
||||
use the providers' ordinary application-loading contracts.
|
||||
|
||||
ConfigKit-backed adapters use the same supplied typed loader for existing
|
||||
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.
|
||||
### Left and right selections
|
||||
|
||||
Declaration capture, metadata discovery, and help leave suite factories and
|
||||
acquisition/comparison callbacks uninvoked. Invocation preparation uses original
|
||||
typed binding identities and converted values, preserving explicit empty, false,
|
||||
and zero selections. Supplied values are converted through core once, including
|
||||
help paths; applying a value to both comparison inputs does not parse it twice.
|
||||
Input/state timing for the pair is part of OD-2, rather than an implicit extension
|
||||
of the existing one-selection lifecycle.
|
||||
Use existing `--config` and `--overlay` for the left side and add
|
||||
`--against-config` and `--against-overlay` overrides for the right side.
|
||||
Omitted right fields inherit the left field, including its supplied state;
|
||||
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.
|
||||
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
|
||||
|
||||
Retain ConfigKit's native changed-region records at the provider boundary, including
|
||||
semantic paths, left/right `Present` and `Redacted` states, safe YAML values, and
|
||||
`HiddenChanged`. The default report deliberately presents a reduced view under
|
||||
OD-3 rather than exposing all native metadata.
|
||||
The native contract owns detailed comparison semantics; the important operator
|
||||
consequences are:
|
||||
`HiddenChanged`. The YAML report deliberately presents a reduced view rather than
|
||||
exposing all native metadata. The native contract owns detailed comparison
|
||||
semantics; the important operator consequences are:
|
||||
|
||||
- Changes reflect frozen effective load values, including defaults and recorded
|
||||
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
|
||||
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
|
||||
`deletions`, as selected in OD-3. Use existing output streams. YAML is the only
|
||||
supported report format, with explicit `--format yaml` accepted. The
|
||||
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`.
|
||||
`config diff` emits one YAML document through the existing output streams. YAML
|
||||
is the only report format for this delivery; explicit `--format yaml` is accepted.
|
||||
Always include the three keys `additions`, `changes`, and `deletions` in that order.
|
||||
Additions and changes preserve configuration hierarchy and contain only safe
|
||||
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
|
||||
needed; it is not required for this delivery.
|
||||
|
||||
**Accepted edge-case treatment:** when a nonempty root mapping becomes an empty
|
||||
mapping, report the native removed-key paths under `deletions`. The reduced report
|
||||
When a nonempty root mapping becomes an empty mapping, report the native
|
||||
removed-key paths under `deletions`. The reduced report
|
||||
need not add special metadata or a separate envelope solely to distinguish
|
||||
exceptional whole-root empty/null transitions from an empty comparison. Ambiguity
|
||||
in that case is acceptable to the user and is not a planning blocker. Native
|
||||
comparison records retain their distinctions; ordinary field-level null values
|
||||
and deletions retain the selected reporting rules.
|
||||
exceptional whole-root empty/null transitions from an empty comparison. That
|
||||
ambiguity is an accepted limit of this reduced report. Native comparison records
|
||||
retain their distinctions; ordinary field-level null values and deletions retain
|
||||
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 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
|
||||
commands keep their existing formats.
|
||||
|
||||
ADR 0008 records this selected presentation. Selection syntax and provider shape
|
||||
are accepted below. No significant open decisions remain for this roadmap.
|
||||
### Diagnostics and outcomes
|
||||
|
||||
**Alternatives considered:** a full difference envelope with left/right snapshots
|
||||
and explicit presence, redaction, and hidden-change fields preserves all native
|
||||
metadata, but is more verbose than the chosen operator view. Embedding parsed
|
||||
values in that envelope avoids YAML strings but retains the record-oriented
|
||||
layout. A right-side-only view without deletion paths cannot represent removals
|
||||
unambiguously. The selected three-category document balances configuration-shaped
|
||||
output with explicit removal reporting.
|
||||
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.
|
||||
|
||||
Omitting empty categories would shorten the report but require consumers to
|
||||
handle missing keys. A separate text report could label changes by path or group
|
||||
them into sections, but YAML already provides readable operator output; another
|
||||
renderer and presentation contract are unnecessary for this delivery.
|
||||
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.
|
||||
|
||||
## 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 `--against-config` and `--against-overlay` overrides for the right side.
|
||||
Omitted right fields inherit the left field, including its supplied state;
|
||||
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
|
||||
Add a narrow optional comparison callback to `ckconfig.Scope[I, S]`. Its request
|
||||
groups each side's selection with its separately prepared typed input and supplies
|
||||
one shared state value separately. Return
|
||||
`commandkit.Acquired[[]configkit.Difference]` plus an error, following the existing
|
||||
acquisition convention. Reuse upstream public record types rather than duplicate
|
||||
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
|
||||
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
|
||||
for each reached side, and call `configkit.Diff`. 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.
|
||||
`AppCommand` and `FromConfigKit` provide native comparison alongside their existing
|
||||
supported operations, with ordinary capability narrowing available. They use the
|
||||
same supplied typed loader for ordinary inspection and both comparison sides,
|
||||
retaining `T` inside the adapter and passing successful results to `configkit.Diff`.
|
||||
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
|
||||
same applicable captured selector values, and check it with that side's
|
||||
`Selection`. Finish both input checks before initializing `S` once and invoking
|
||||
the pair provider. Omitted factories still supply zero values, including nil
|
||||
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,
|
||||
and the architecture policy reflects it. Document the exact implemented API
|
||||
contract in Go declarations and GoDoc when it lands.
|
||||
|
||||
This keeps generic result handling inside the owning adapter and preserves
|
||||
typed binding composition without reflection, 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
|
||||
### Application-owned state and caches
|
||||
|
||||
Generic result handling stays inside the owning adapter, without reflection,
|
||||
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
|
||||
right and report equality. Demonstrate correct keys in the maintained example;
|
||||
CommandKit neither supplies nor repairs application caches. Cache policy and
|
||||
factory objects remain caller-owned.
|
||||
|
||||
**Alternative considered:** acquire a comparison-capable facet with each ordinary `View`,
|
||||
then compare the two acquired facets. This shares single-side acquisition between
|
||||
all operations and may suit providers already retaining typed results behind a
|
||||
stable comparison handle. It requires a public way to establish compatibility
|
||||
between two heterogeneous facets, and can lead to type assertions or extra
|
||||
opaque-handle machinery. Consider it if representative non-ConfigKit consumers
|
||||
demonstrate enough benefit to justify that additional contract.
|
||||
## Design tradeoffs
|
||||
|
||||
The chosen selection flags reuse existing configuration vocabulary and reduce
|
||||
repetition for base-versus-overlay comparison. Symmetric `--left-config` /
|
||||
`--right-config` and `--left-overlay` / `--right-overlay` flags would make each side
|
||||
independent but add vocabulary and repetition. Independent per-side domain
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user