Files
commandkit/docs/adr/0012-typed-configuration-comparison-pairs.md

109 lines
5.9 KiB
Markdown
Raw Permalink Normal View History

# ADR 0012: Prepare typed selection pairs for configuration comparison
## Status
Accepted. Refines [ADR 0011](0011-captured-declarations-and-installation.md) for
two-selection configuration comparison; its other decisions remain in force.
[ADR 0008](0008-semantic-configuration-diff.md) governs native comparison and
report presentation.
## Date
2026-10-11
## Context
Native effective-configuration comparison needs two completed loads. ConfigKit
requires results of the same configuration type, which an ordinary inspection
view does not expose for pairwise comparison. A generic adapter can retain that
type without introducing result assertions or a universal core provider model.
ADR 0011 separates a selected scope's typed input from shared acquisition state.
A comparison selects the same scope twice, potentially with different roots or
overlays. Reusing one input obscures which selection a provider receives; creating
separate shared state loses the invocation-wide lifetime chosen for inspection.
## Decision
### Selections and provider ownership
Comparison selects one scope and prepares an earlier/left selection and a
later/right selection. Omitted right selection fields inherit the corresponding
left field and supplied state. An explicit right override, including an empty
value, replaces that field. Providers retain interpretation of omitted defaults
and explicit empty values. Applicable domain selector values are shared between
the two sides initially; independent per-side domain selectors may be considered
for a concrete consumer need.
Equal selections are allowed. CommandKit does not skip acquisition merely because
their selection values are equal: caller-owned loading may produce different
effective results. Exact flag spellings belong in the CLI reference when
implemented.
Use a narrow optional comparison provider owned by the integration. Its request
groups each side's selection with its typed input and supplies one shared state
value separately. The provider returns acquired native comparison results
with diagnostics and an error through the existing acquisition convention.
Reuse useful upstream public record types rather than duplicating them solely
to rename fields. Exact exported signatures belong in Go declarations and GoDoc.
The typed ConfigKit adapter invokes the supplied loader for each reached side
and passes the successful typed results to `configkit.Diff`. It retains the
configuration type inside that adapter, without reflection, result type
assertions, private core access, or a comparison-facet framework. Applications
may supply their own pair provider through the same integration contract.
Declared capabilities determine required wiring. A comparison-only scope needs
its comparison provider, without an unrelated ordinary acquisition callback.
Ordinary operations continue to use their ordinary acquisition provider.
Retained adapter construction errors still apply when capabilities are narrowed.
Other scopes and families need not support comparison under
[ADR 0009](0009-configuration-scopes.md).
### Typed input and shared state lifetime
Capture comparison declarations and applicable selector bindings under ADR 0011.
Convert supplied flag values through core once, including on help paths; applying
the values to both inputs does not parse them again.
After availability preflight, initialize each reached side's typed input
separately, apply the same applicable captured selector values, and check that
input with the selected scope identity and that side's selection. Finish both
input checks before initializing shared state once and invoking the pair
provider. Failures may stop later factories or loads. Construction, installation,
help, version, and scope discovery invoke neither input/state factories nor
acquisition/comparison providers.
Existing factory ownership rules remain unchanged: an omitted factory supplies
its type's zero value, including nil pointers. Separate factory calls do not
guarantee distinct caller-owned objects. CommandKit does not allocate arbitrary
pointer types, clone application graphs, repair caller aliases, or supply or
repair application caches. Core-owned parsed collections remain independent
when applied to the two inputs; callback effects remain caller-owned.
## Alternatives considered
| Alternative | Analysis |
| --- | --- |
| Symmetric independently resolved left/right selectors | Makes each side explicit and avoids inheritance. It adds vocabulary and repetition for common base-versus-overlay comparisons. |
| One typed input for both sides | Requires fewer factory calls, but obscures side-specific selection checks and leaves mutation isolation implicit. |
| Acquire a comparison facet with each ordinary view | Shares single-side acquisition across operations, but requires a public compatibility contract between heterogeneous facets and additional handle or assertion machinery. |
| Separate shared state for each side | Isolates acquisition state, but loses the invocation-wide sharing already selected for inspection. Applications can choose isolation within their own pair provider if needed. |
## Consequences
Pair preparation has explicit input and state lifetimes while ordinary inspection
keeps its existing lifecycle. Generic result handling stays inside the integration
adapter; core gains no owning-library dependency or universal comparison model.
Shared state permits application-owned caches. A cache used by a pair provider
should distinguish selections and any input values affecting loading to avoid
reusing the left result for a different right selection. This is integration
guidance, not a CommandKit cache policy or guarantee about caller callbacks.
The [architecture policy](../policy/architecture.md) owns normative boundaries.
ADR 0008 governs delegation to upstream comparison semantics, safe disclosure,
and CommandKit's presentation responsibility. This decision does not add a new
equality engine or strengthen application
loading, object ownership, or concurrency contracts.