Document configuration comparison behavior
This commit is contained in:
57
docs/cli.md
57
docs/cli.md
@@ -230,6 +230,63 @@ environment-variable name; effective and historical secret fragments remain
|
||||
redacted. Empty location, inheritance, history, reason, and dependency lists are
|
||||
serialized as `[]`.
|
||||
|
||||
### Compare configuration selections
|
||||
|
||||
`config diff` compares two independently loaded selections for one scope that
|
||||
declares comparison. The default scope is `app`; `--scope all` is unsupported.
|
||||
The PromptKit engine scope does not currently declare comparison, so selecting
|
||||
`--scope promptkit` is a usage error.
|
||||
`--config` and `--overlay` select the left side. `--against-config` and
|
||||
`--against-overlay` independently override the right side. When a right-side
|
||||
field is omitted, it inherits the corresponding left value and supplied state;
|
||||
an explicit empty string overrides it and remains supplied. Equal selections are
|
||||
allowed and both reached sides are loaded.
|
||||
|
||||
YAML is the only format and the default. Explicit `--format yaml` is accepted;
|
||||
`text` and other formats are usage errors. For example:
|
||||
|
||||
```text
|
||||
example config diff --config before.yml --against-config after.yml
|
||||
example config diff --config base.yml --against-overlay candidate
|
||||
example config diff --config base.yml --overlay current --against-overlay ""
|
||||
```
|
||||
|
||||
ConfigKit compares frozen effective typed values after defaults and resolution;
|
||||
source or provenance differences alone do not create a change. The report is one
|
||||
YAML document with `additions`, `changes`, and `deletions` in that order.
|
||||
Additions and changes preserve semantic paths and contain safe right-side values.
|
||||
Deletions contain canonical JSON Pointer paths. Explicit null is a value; it is
|
||||
not a deletion. Changed sequences and native structural replacement regions stay
|
||||
atomic.
|
||||
|
||||
ConfigKit pairs sensitivity across both loads. A concealed change can therefore
|
||||
appear even when its two safe snapshots are equal. The report omits separate
|
||||
redaction and hidden-change metadata: a reported masked region changed, but that
|
||||
does not mean every member inside it changed. Marker-looking public strings stay
|
||||
ordinary YAML values. An empty comparison succeeds with this shape:
|
||||
|
||||
```yaml
|
||||
additions: {}
|
||||
changes: {}
|
||||
deletions: []
|
||||
```
|
||||
|
||||
The reduced report is a partial safe view, not a reloadable configuration or an
|
||||
automatically applicable patch. Exceptional whole-root empty/null transitions
|
||||
can be ambiguous because the report has no root envelope; ordinary field-level
|
||||
null values and deletions retain their distinction.
|
||||
|
||||
Successful comparisons return status `0`, including concealed or empty results.
|
||||
Unsupported scopes and format errors are usage errors; input checks retain the
|
||||
existing usage/operational classification. Load and native comparison failures
|
||||
are operational and preserve supported error identity. Comparison
|
||||
diagnostics identify their left/right side and source legend. The adapter loads
|
||||
left before right, retains left diagnostics if right loading fails, and gathers
|
||||
both loads' diagnostics before native comparison. The complete report is
|
||||
prepared before writing. Cancellation and preparation failures leave report
|
||||
output empty; an output error or short write uses the existing incomplete-report
|
||||
delivery outcome.
|
||||
|
||||
## PromptKit definition inspection
|
||||
|
||||
Applications can install prompt and profile inspection independently with
|
||||
|
||||
@@ -103,18 +103,21 @@ values.
|
||||
|
||||
Use `ckconfig.Command(ckconfig.Suite[I, S]{...})` when the application needs
|
||||
multiple named scopes, selector flags, scope-aware input checks, or shared
|
||||
acquisition state. Input is initialized separately for each selected scope;
|
||||
state is shared by selected acquisitions. Factory results remain caller-owned,
|
||||
so separate initialization calls do not guarantee distinct objects. See
|
||||
acquisition state or a custom comparison provider. A declared `Diff` capability
|
||||
uses `Scope.Compare`; `ckconfig.FromConfigKit` and `AppCommand` provide the
|
||||
ConfigKit-backed implementation. Each comparison side gets its own initialized
|
||||
and checked input, while state is shared by the invocation. Factory results
|
||||
remain caller-owned, so separate initialization calls do not guarantee distinct
|
||||
objects. See
|
||||
[ckconfig.Suite's GoDoc](../../integrations/ckconfig/contracts.go) for factory
|
||||
timing, omitted-factory zero values (including nil pointers), and ownership.
|
||||
The application owns the state type and what it caches. `ckconfig.FromConfigKit`
|
||||
adapts a typed ConfigKit loader without calling it during construction.
|
||||
|
||||
The `config` family provides scope discovery, validation, native effective YAML,
|
||||
source inventory, and path explanation for the capabilities declared by its
|
||||
scopes. The [CLI reference](../cli.md#configuration-scopes) owns operator
|
||||
syntax and report details.
|
||||
source inventory, path explanation, and ConfigKit-backed comparison for the
|
||||
capabilities declared by its scopes. The [CLI reference](../cli.md#configuration-scopes)
|
||||
owns operator syntax and report details.
|
||||
|
||||
## PromptKit configuration and definitions
|
||||
|
||||
|
||||
@@ -134,7 +134,9 @@ external services:
|
||||
```sh
|
||||
go run ./examples/core workspace greet --count=0 --tag=first --tag second
|
||||
(cd integrations/ckconfig/examples/simple && go run . config show)
|
||||
(cd integrations/ckconfig/examples/simple && go run . config diff --config fixtures/before.yml --against-config fixtures/after.yml)
|
||||
(cd integrations/ckprompt/examples/composed && go run . config validate --scope all --campaign spring --limit=0)
|
||||
(cd integrations/ckprompt/examples/composed && go run . config diff --scope app --config fixtures/before.yml --against-config fixtures/after.yml)
|
||||
(cd integrations/ckprompt/examples/composed && go run . promptkit show prompt briefing --campaign spring --format yaml)
|
||||
(cd integrations/ckprompt/examples/composed && go run . session restore session-42 --campaign spring)
|
||||
```
|
||||
|
||||
@@ -40,10 +40,11 @@ Cobra and pflag imports remain inside this package.
|
||||
## Optional modules
|
||||
|
||||
`integrations/ckconfig` owns ConfigKit adaptation, scope capture, the standard
|
||||
`config` command family, and native validate/show/sources/explain reports. It
|
||||
depends on the public core facade and ConfigKit; it does not depend on PromptKit.
|
||||
Each selected scope receives an independently initialized input, while one
|
||||
suite-owned state value is shared by selected acquisitions in that invocation.
|
||||
`config` command family, and native validate/show/sources/explain/diff behavior.
|
||||
It depends on the public core facade and ConfigKit; it does not depend on
|
||||
PromptKit. Each selected scope or comparison side receives an independently
|
||||
initialized input, while one suite-owned state value is shared by an invocation's
|
||||
acquisitions or comparison callback.
|
||||
|
||||
`integrations/ckprompt` owns PromptKit engine loading, configuration-scope
|
||||
adaptation, and optional named prompt/profile inspection. It uses public core
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Adopt ConfigKit v0.7.1 and expose native configuration comparison
|
||||
|
||||
Status: end-state decisions selected; dependency adoption and `config diff` are
|
||||
not implemented. This roadmap defines the selected target and remaining gap;
|
||||
the [implementation plan](implementation.md) owns stages and execution order.
|
||||
Status: ConfigKit v0.7.1 adoption and ConfigKit-backed `config diff` are
|
||||
implemented. Distribution reconciliation and final validation remain in the
|
||||
[implementation plan](implementation.md), which records the evidence and order.
|
||||
|
||||
## Purpose and authority
|
||||
|
||||
@@ -34,14 +34,15 @@ disclosure; CommandKit owns selection, coordination, adaptation, and presentatio
|
||||
| Owner | Current state |
|
||||
| --- | --- |
|
||||
| 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, provider representation, and the YAML-only report are selected; implementation remains pending. |
|
||||
| `integrations/ckconfig` | Requires ConfigKit v0.7.1. `Scope`, `Suite`, `FromConfigKit`, and `AppCommand` expose independently declared validate/show/sources/explain/diff capabilities. |
|
||||
| `integrations/ckprompt` | Requires ConfigKit v0.7.1 and PromptKit v0.12.0. It depends on ckconfig's public scope contracts and adapts engine configuration plus named definitions; its ConfigKit scope does not declare comparison. |
|
||||
| Comparison status | ConfigKit-backed `config diff` is implemented. The [CLI reference](../cli.md#compare-configuration-selections), integration GoDoc, and [implementation record](implementation.md) own current contracts and evidence. PromptKit comparison remains deferred. |
|
||||
|
||||
The existing ConfigKit adapter acquires a typed `*configkit.Result[T]` and exposes
|
||||
its effective, source, and explanation facets through `View`. That generic
|
||||
adapter is a useful place to retain typed results for comparison. `View` alone
|
||||
does not supply two results of the same `T` to `configkit.Diff`.
|
||||
The ConfigKit adapter acquires typed `*configkit.Result[T]` values and exposes
|
||||
effective, source, and explanation facets through `View` for ordinary operations.
|
||||
Its separate comparison callback retains `T`, loads both prepared selections,
|
||||
and returns the native records from `configkit.Diff` without routing through
|
||||
`View`.
|
||||
|
||||
ConfigKit v0.7.1 identifies source commit
|
||||
`6fffde4af8f31f99d3ee295c426eb3234cb0fb77`. Relative to the selected v0.5.0:
|
||||
@@ -53,15 +54,14 @@ ConfigKit v0.7.1 identifies source commit
|
||||
runtime/API change from v0.7.0.
|
||||
|
||||
The YAML dependency remains `go.yaml.in/yaml/v4 v4.0.0-rc.6`. Existing public
|
||||
loading and inspection signatures are unchanged. The review found no apparent
|
||||
adapter migration requirement for existing operations; that is static review
|
||||
evidence, not a completed upgrade validation. See the pinned
|
||||
loading and inspection signatures are unchanged, and the integration suites pass
|
||||
with the adopted dependency. 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).
|
||||
|
||||
## Dependency adoption and ownership
|
||||
|
||||
Both integration modules select ConfigKit v0.7.1 and carry normal dependency
|
||||
Both integration modules now select ConfigKit v0.7.1 and carry normal dependency
|
||||
metadata for their actual graphs. Consumer Go minimums remain 1.26.0, the selected
|
||||
release toolchain remains 1.26.8, and PromptKit remains v0.12.0 for this work.
|
||||
Core continues to have no ConfigKit or optional-integration dependency.
|
||||
@@ -115,7 +115,7 @@ 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:
|
||||
For example, these are current invocations:
|
||||
|
||||
```text
|
||||
app config diff --config before.yml --against-config after.yml
|
||||
@@ -255,12 +255,12 @@ boundaries; do not promise interruption inside a synchronous upstream call.
|
||||
|
||||
### Comparison provider and ConfigKit adapters
|
||||
|
||||
Add a narrow optional comparison callback to `ckconfig.Scope[I, S]`. Its request
|
||||
`ckconfig.Scope[I, S]` exposes a narrow optional comparison callback. 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:
|
||||
acquisition convention. It reuses upstream public record types rather than
|
||||
duplicating them solely to rename fields. The current API shape is:
|
||||
|
||||
```go
|
||||
type ComparisonSide[I any] struct {
|
||||
@@ -273,13 +273,13 @@ type ComparisonRequest[I any] struct {
|
||||
Right ComparisonSide[I]
|
||||
}
|
||||
|
||||
// Accepted target field on Scope[I, S]:
|
||||
// Current field on Scope[I, S]:
|
||||
// Compare func(context.Context, ComparisonRequest[I], S) (commandkit.Acquired[[]configkit.Difference], error)
|
||||
```
|
||||
|
||||
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.
|
||||
These are the implemented exports in `integrations/ckconfig/contracts.go`.
|
||||
ADR 0012 records paired provider ownership and input/state lifetimes; GoDoc owns
|
||||
the exact public declarations.
|
||||
|
||||
`AppCommand` and `FromConfigKit` provide native comparison alongside their existing
|
||||
supported operations, with ordinary capability narrowing available. They use the
|
||||
@@ -306,19 +306,18 @@ or loads need not run after failure. Declaration construction, installation, hel
|
||||
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.
|
||||
and the architecture policy reflects it. The exact API contract is in the Go
|
||||
declarations and GoDoc.
|
||||
|
||||
### 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.
|
||||
that affect loading. A cache that stores only one configuration can incorrectly
|
||||
reuse the left result for the right and report equality. The composed example
|
||||
demonstrates selection- and input-aware keys; CommandKit neither supplies nor
|
||||
repairs application caches. Cache policy and factory objects remain caller-owned.
|
||||
|
||||
## Design tradeoffs
|
||||
|
||||
@@ -340,46 +339,15 @@ 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
|
||||
## Implementation record
|
||||
|
||||
These work areas close the gap from the current implementation to the selected
|
||||
end state above. The [implementation plan](implementation.md) defines their
|
||||
execution order and completion evidence.
|
||||
|
||||
- **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.
|
||||
Dependency adoption, capability and typed-pair preparation, native adaptation,
|
||||
YAML reporting, end-to-end execution, and both maintained comparison examples
|
||||
are implemented. Current API and operator contracts belong to GoDoc, the
|
||||
[CLI reference](../cli.md#compare-configuration-selections), the
|
||||
[consumer guide](../consumers/guide.md#configkit-scopes), and the example
|
||||
READMEs. The [implementation plan](implementation.md) records stage-by-stage
|
||||
changes and validation; distribution reconciliation and final validation remain.
|
||||
|
||||
### Focused behavioral evidence
|
||||
|
||||
|
||||
@@ -18,29 +18,20 @@ an idea here does not select its syntax, API, priority, or delivery date.
|
||||
|
||||
## Deferred capability targets
|
||||
|
||||
### DIFF-01: semantic configuration comparison
|
||||
### PromptKit configuration comparison
|
||||
|
||||
Expose comparison of two independently resolved selections of one scope using
|
||||
owning-library public comparison APIs. [ADR 0008](../adr/0008-semantic-configuration-diff.md)
|
||||
owns native comparison, paired safe disclosure, and the reduced default report.
|
||||
The target includes a YAML-only report of safe changed regions; completed
|
||||
comparisons succeed whether or not they find differences.
|
||||
ConfigKit-backed `config diff` is implemented by `ckconfig` for scopes that
|
||||
declare that capability. `ckprompt.ConfigScope` does not declare comparison.
|
||||
Reassess PromptKit's supported public comparison capabilities before planning a
|
||||
PromptKit comparison. Do not reach into ConfigKit internals or infer comparison
|
||||
semantics from rendered YAML.
|
||||
|
||||
The initial review of ConfigKit v0.5.0 and PromptKit v0.12.0 did not find the
|
||||
public comparison support needed for that target. ConfigKit v0.7.0 introduced
|
||||
`configkit.Diff`, retained in v0.7.1, which supplies native comparison and paired
|
||||
safe changed-region snapshots. CommandKit still uses ConfigKit v0.5.0; dependency
|
||||
adoption and comparison delivery are targeted by the
|
||||
[ConfigKit roadmap](configkit.md). Assess PromptKit's supported
|
||||
public comparison capabilities separately. Rendered YAML and sibling internals
|
||||
are not substitutes for the owning library's public comparison contract.
|
||||
### Comparison extensions
|
||||
|
||||
The ConfigKit roadmap records accepted selection syntax and the paired provider
|
||||
API, with lifecycle recorded in
|
||||
[ADR 0012](../adr/0012-typed-configuration-comparison-pairs.md). The selected report
|
||||
shape is recorded in that roadmap. Independent per-side domain selectors and
|
||||
an optional assertion mode remain outside that delivery. Add public types and
|
||||
handlers with their implementation rather than exposing placeholders.
|
||||
Independent per-side domain selectors and an optional assertion mode remain
|
||||
unselected extensions to the delivered ConfigKit comparison. Consider them only
|
||||
for a concrete consumer need and a deliberate API/behavior decision under the
|
||||
relevant ADRs.
|
||||
|
||||
### CAT-01: PromptKit catalogs
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Implement ConfigKit adoption and configuration comparison
|
||||
|
||||
Status: implementation in progress; Stages 1–10 are complete.
|
||||
Status: implementation in progress; Stages 1–11 are complete.
|
||||
|
||||
## Scope and authority
|
||||
|
||||
@@ -545,9 +545,20 @@ canonical owners, while future/deferred work stays clearly separate.
|
||||
symbols. Keep accepted ADR decision text unchanged; presentation details
|
||||
remain in CLI/API owners rather than returning to ADRs.
|
||||
|
||||
**Completion evidence:** current operator/API/consumer owners agree with the
|
||||
implemented behavior; no stale four-operation convenience claims, text-diff
|
||||
promises, or deferred markers for delivered ConfigKit comparison.
|
||||
**Completion evidence — complete:** ckconfig GoDoc now describes all five
|
||||
operations, paired input lifetimes, shared state, native records, diagnostics,
|
||||
and supported error identity. The ckconfig README, CLI reference, consumer guide,
|
||||
internal overview, development examples, and maintained example READMEs describe
|
||||
current ConfigKit comparison behavior. The CLI owner covers independent right
|
||||
inheritance and supplied presence, native effective-value semantics, reduced
|
||||
safe YAML categories, null/deletion, concealed regions, empty output, root
|
||||
ambiguity, diagnostics, and outcome delivery. The ConfigKit feature roadmap now
|
||||
records implementation status; the deferred record no longer carries ConfigKit
|
||||
comparison as pending work and retains PromptKit comparison, independent per-side
|
||||
domain selectors, catalogs, and other unselected ideas. The accepted ADRs were
|
||||
left unchanged. Local Markdown targets/fragments and copied commands were
|
||||
reviewed; a local link check and `git diff --check -- '*.md'` passed. `go doc`
|
||||
was inspected for the exported comparison API.
|
||||
|
||||
## Stage 12: Reconcile manifests, notices, and pending integration release notes
|
||||
|
||||
|
||||
@@ -24,9 +24,12 @@ app, err := commandkit.New(identity, ckconfig.AppCommand(loadAppConfig))
|
||||
|
||||
Use `ckconfig.Command(ckconfig.Suite[Input, State]{...})` to define named
|
||||
scopes, selectors, input checks, and state shared by the selected acquisitions
|
||||
in a config invocation. `ckconfig.FromConfigKit` adapts a typed ConfigKit loader.
|
||||
The `config` command family exposes scope discovery and the validate, show,
|
||||
sources, and explain operations supported by the declared scopes.
|
||||
or comparison in a config invocation. `ckconfig.FromConfigKit` adapts a typed
|
||||
ConfigKit loader. The `config` command family exposes scope discovery and the
|
||||
validate, show, sources, explain, and diff operations supported by the declared
|
||||
scopes. Comparison returns ConfigKit's native records to the YAML report path;
|
||||
the [CLI reference](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/cli.md#compare-configuration-selections)
|
||||
owns its operator details.
|
||||
|
||||
The maintained [simple example](examples/simple) shows a complete consumer.
|
||||
The [CommandKit CLI reference](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/cli.md#configuration-scopes)
|
||||
|
||||
@@ -14,9 +14,10 @@ import (
|
||||
// FromConfigKit adapts a typed ConfigKit loader to all five native
|
||||
// configuration operations. The loader receives the operation's explicit
|
||||
// Selection, initialized input, and shared invocation state, and runs only when
|
||||
// an installed operation selects this scope. Construction and help do not call
|
||||
// it. A nil original loader is retained as a construction issue, even if callers
|
||||
// later narrow the scope's operation list.
|
||||
// an installed operation selects this scope. Comparison invokes it separately
|
||||
// for each reached side. Construction and help do not call it. A nil original
|
||||
// loader is retained as a construction issue, even if callers later narrow the
|
||||
// scope's operation list.
|
||||
func FromConfigKit[I, S, T any](
|
||||
name, summary string,
|
||||
load func(context.Context, Selection, I, S) (*configkit.Result[T], error),
|
||||
|
||||
@@ -17,7 +17,7 @@ type Selection struct {
|
||||
Overlay commandkit.Supplied[string]
|
||||
}
|
||||
|
||||
// Operation identifies a supported configuration inspection operation.
|
||||
// Operation identifies a supported standard configuration operation.
|
||||
type Operation string
|
||||
|
||||
const (
|
||||
@@ -42,7 +42,8 @@ type Request struct {
|
||||
}
|
||||
|
||||
// ComparisonSide groups one configuration selection with its independently
|
||||
// prepared typed input.
|
||||
// initialized and checked typed input. The supplied-state fields of Selection
|
||||
// are preserved for the scope's loader.
|
||||
type ComparisonSide[I any] struct {
|
||||
// Selection carries the explicit config and overlay inputs for this side.
|
||||
Selection Selection
|
||||
@@ -51,7 +52,8 @@ type ComparisonSide[I any] struct {
|
||||
}
|
||||
|
||||
// ComparisonRequest carries the earlier and later selections supplied to a
|
||||
// scope's comparison callback.
|
||||
// scope's comparison callback. Each side has a separately prepared input; the
|
||||
// callback receives shared invocation state separately.
|
||||
type ComparisonRequest[I any] struct {
|
||||
// Left is the earlier configuration selection.
|
||||
Left ComparisonSide[I]
|
||||
@@ -99,7 +101,9 @@ type Scope[I, S any] struct {
|
||||
// invocation.
|
||||
Acquire func(context.Context, Request, I, S) (commandkit.Acquired[View], error)
|
||||
// Compare compares two selections for this scope using one shared state.
|
||||
// It is required when Diff is declared in Operations.
|
||||
// Its Acquired result carries native difference records and diagnostics;
|
||||
// returned errors retain their supported cause identity. It is required when
|
||||
// Diff is declared in Operations.
|
||||
Compare func(context.Context, ComparisonRequest[I], S) (commandkit.Acquired[[]configkit.Difference], error)
|
||||
|
||||
issues []error
|
||||
@@ -116,24 +120,28 @@ type Selector[I any] struct {
|
||||
// Suite declares the typed input, shared state, selectors, and configuration
|
||||
// scopes used to assemble configuration commands.
|
||||
//
|
||||
// Input initialization is separate for each selected scope; state is shared
|
||||
// by that invocation's acquisitions. Factory results and callback effects remain
|
||||
// Input initialization is separate for each selected ordinary scope and each
|
||||
// reached comparison side; state is shared by the invocation's acquisitions or
|
||||
// comparison callback. Factory results and callback effects remain
|
||||
// caller-owned: Command does not deep-copy arbitrary objects or repair aliases
|
||||
// returned by factories. Core-owned repeated flag collections are copied when
|
||||
// applied to separate inputs. Factories are not invoked during construction,
|
||||
// installation, help, version, or scope discovery, and need not run after failure.
|
||||
type Suite[I, S any] struct {
|
||||
// NewInput is called once for each selected scope reached after operation
|
||||
// preflight, before applying its selectors and calling CheckInput.
|
||||
// NewInput is called once for each selected ordinary scope, or once for each
|
||||
// reached side of a comparison, after operation preflight and before applying
|
||||
// selectors and calling CheckInput.
|
||||
// If nil, input is the zero value of I, including nil for pointer types.
|
||||
NewInput func() I
|
||||
// NewState is called once when acquisition is reached, after all selected
|
||||
// inputs pass their checks. The result is shared by selected acquisitions.
|
||||
// NewState is called once when provider execution is reached, after all
|
||||
// selected inputs pass their checks. The result is shared by selected
|
||||
// acquisitions or the comparison callback.
|
||||
// If nil, state is the zero value of S, including nil for pointer types.
|
||||
NewState func() S
|
||||
// Selectors declares typed flags and their applicable scopes.
|
||||
Selectors []Selector[I]
|
||||
// CheckInput validates one initialized scope input after applicable values are applied.
|
||||
// CheckInput validates one initialized scope input after applicable values
|
||||
// are applied. Comparison sides are checked separately with their selection.
|
||||
CheckInput func(scope string, selection Selection, input I) error
|
||||
// Scopes declares the configuration scopes assembled by Command.
|
||||
Scopes []Scope[I, S]
|
||||
|
||||
@@ -43,9 +43,10 @@ type preparedSuite[I, S any] struct {
|
||||
// Command eagerly captures a configuration suite as a root-only config family.
|
||||
// It copies suite slices, retains callback references, and returns a reusable
|
||||
// declaration; installation does not invoke factories or providers. During an
|
||||
// inspection, it initializes input separately for each selected scope and
|
||||
// validates those inputs before acquisition. Suite documents factory timing,
|
||||
// zero values, shared state, and caller ownership of returned objects.
|
||||
// inspection, it initializes input separately for each selected scope. A
|
||||
// comparison initializes and checks both sides before creating shared state
|
||||
// and calling the pair provider. Suite documents factory timing, zero values,
|
||||
// shared state, and caller ownership of returned objects.
|
||||
func Command[I, S any](suite Suite[I, S]) commandkit.Command {
|
||||
prepared := captureSuite(suite)
|
||||
if len(prepared.scopes) == 0 {
|
||||
@@ -67,7 +68,8 @@ func Command[I, S any](suite Suite[I, S]) commandkit.Command {
|
||||
|
||||
// AppCommand builds the state-free, input-free convenience suite for application
|
||||
// configuration. The application consumer supplies only its ConfigKit loader,
|
||||
// which runs only for a selected operation after input preflight.
|
||||
// which runs for ordinary operations and separately for each reached comparison
|
||||
// side after input preflight.
|
||||
func AppCommand[T any](load func(context.Context, Selection) (*configkit.Result[T], error)) commandkit.Command {
|
||||
var adapterLoad func(context.Context, Selection, struct{}, struct{}) (*configkit.Result[T], error)
|
||||
if load != nil {
|
||||
|
||||
Reference in New Issue
Block a user