Preserve version semantics in the layering roadmap

This commit is contained in:
2026-09-29 15:52:20 +00:00
parent 798091b276
commit e4bbedc695

View File

@@ -52,8 +52,8 @@ these proposals.
clear existing children; null is an explicit value, not omission. clear existing children; null is an explicit value, not omission.
- An explicitly configured schema-version path currently belongs to the selected - An explicitly configured schema-version path currently belongs to the selected
source. Its checker runs before overlay/CLI input, which cannot alter that path; source. Its checker runs before overlay/CLI input, which cannot alter that path;
imported fragments cannot contribute it. The target below deliberately revises imported fragments cannot contribute it. This roadmap preserves those ownership
those ownership and timing rules. and timing rules.
- CLI overrides already convert supported programmatic scalars, lists, and - CLI overrides already convert supported programmatic scalars, lists, and
string-keyed maps directly to the private document representation. They have string-keyed maps directly to the private document representation. They have
CLI-specific paths, labels, restrictions, and origins, not a general source API. CLI-specific paths, labels, restrictions, and origins, not a general source API.
@@ -69,8 +69,7 @@ these proposals.
Existing source/lifecycle contracts, ownership, secret handling, and diagnostics Existing source/lifecycle contracts, ownership, secret handling, and diagnostics
remain the compatibility baseline. This work is not permission to silently remain the compatibility baseline. This work is not permission to silently
reinterpret current `Load`, imports, selected overlays, or CLI overrides. reinterpret current `Load`, imports, selected overlays, or CLI overrides.
Effective-version validation is an explicit exception described below, not an Redesigning schema-version policy is outside this roadmap's scope.
unannounced consequence of refactoring.
## Target source model ## Target source model
@@ -138,6 +137,9 @@ input uses the same presence and combination rules. Explicitly choosing compose,
overlay, or replacement expresses different intentions; merely changing the input overlay, or replacement expresses different intentions; merely changing the input
medium must not switch between them. This applies to both ordinary `Load` and medium must not switch between them. This applies to both ordinary `Load` and
the new layered-loading interface wherever they offer the same operation. the new layered-loading interface wherever they offer the same operation.
The existing opt-in version-path ownership rule remains an explicit metadata
constraint, independent of whether its owning source is a file or programmatic
input; it is not a source-format-dependent merge rule.
Keep strict composition and intentional overriding visibly distinct: Keep strict composition and intentional overriding visibly distinct:
@@ -153,8 +155,8 @@ precedence is applied. An overlay must not hide malformed YAML or a composition
conflict in an earlier contribution. There is no automatic matching by an `id` conflict in an earlier contribution. There is no automatic matching by an `id`
field, implicit sequence merge, universal profile registry, or merge callback. field, implicit sequence merge, universal profile registry, or merge callback.
Assemble the effective input, including selected-overlay and CLI contributions, Preserve version checking after base composition and before intentional overlays
then check its configured schema version before typed defaults/decoding, and CLI contributions. Assemble the effective input before typed defaults/decoding,
application resolution, secret resolution, semantic validation, and final application resolution, secret resolution, semantic validation, and final
snapshotting. Each lifecycle phase runs once per load, not once per layer. snapshotting. Each lifecycle phase runs once per load, not once per layer.
Higher layers may replace values that would not fit the final typed schema; Higher layers may replace values that would not fit the final typed schema;
@@ -181,40 +183,34 @@ supply the final value. The metadata then attributes `retries` to defaults, not
to the replaced input. An empty replacement entry likewise removes lower-input to the replaced input. An empty replacement entry likewise removes lower-input
children without suppressing applicable typed defaults. children without suppressing applicable typed defaults.
### Effective-configuration schema version ### Preserve existing schema-version semantics
An application opts into version checking by configuring a version path. A key An application opts into version checking by configuring a version path. A key
spelled `version` has no automatic special status. The configured path follows spelled `version` has no automatic special status. When checking is configured,
the selected combination operation like any other setting: one designated input owns that declaration; fragments cannot contribute it and
overlays or CLI overrides cannot alter it, even to an equal value. New layering
operations must respect that ownership rather than bypass it through subtree
replacement. Preserve the current version-path and ancestor protections.
- Strict composition rejects conflicting scalar definitions, even if equal; Keep the checker at its existing lifecycle point: after base composition and
it is not last-wins. schema construction, before intentional overlays, CLI overrides, defaults, and
- An intentional overlay can replace an earlier version value. Imports may typed decoding. Preserve supported scalar forms, absent/null distinction,
contribute the version subject to ordinary composition rules; selected overlays diagnostics, failure propagation, and version-path integer-to-string decoding.
and CLI input are not excluded solely because a path is the version path. An absent declaration remains absent for the checker; an invalid version type
- Any selected subtree replacement has the same effect on version presence as fails without invoking it. Later input cannot mask a version-check failure.
on other values in that subtree, including removing a lower-input version.
After all input precedence operations, inspect the effective version and invoke Filesystem sources and layered loading do not require a different version
the configured checker once, before typed decoding. Preserve the existing policy. The layered API needs a way to identify the version-owning input when a
supported scalar forms, absent/null distinction, version diagnostics, and `VersionRule` is configured; Decision 4 concerns that integration only. Without
version-path integer-to-string decoding behavior. As today, an invalid effective version checking, no version owner or synthetic primary document is required.
version type produces a diagnostic rather than invoking the checker. Absent Named-overlay lookup context is a separate concern, not a reason to impose
effective input is reported as absent, not manufactured from typed defaults. version ownership on unversioned loads.
Version origins and replacement history follow the same rules as other fields.
Do not check each source's version independently or fail merely because a Consumers continue to define version meaning and acceptance. Effective-version
superseded version value would fail effective-version validation. Invalid YAML, last-wins validation, independent per-source version checks, schema selection,
source failures, and strict-composition conflicts still fail at their owning and migration are not added by this feature. A future concrete need can motivate
phases; precedence does not conceal those errors. A later version value does not a separate version-policy proposal; preserving the current contract here does
migrate earlier data. Consumers supply compatible inputs and own schema meaning; not settle that broader question permanently.
automatic migration and per-document format interpretation remain out of scope.
Apply this model consistently to existing and new loading interfaces. It
deliberately changes the current selected-source ownership restrictions and moves
checking after overlay/CLI application. Document the resulting compatibility
impact and callback timing in the feature's minor release rather than retaining
different version semantics for old and new entry points.
### Programmatic presence ### Programmatic presence
@@ -303,9 +299,9 @@ These are responsibility areas, not implementation stages:
with ordinary loading rather than building a parallel configuration system. with ordinary loading rather than building a parallel configuration system.
- Resolve the fixed operation and ownership decisions below, then extend source - Resolve the fixed operation and ownership decisions below, then extend source
records, histories, diagnostics, and rendering consistently across input kinds. records, histories, diagnostics, and rendering consistently across input kinds.
- Replace selected-source version ownership with the effective-version lifecycle - Integrate version-owner selection into layered loading while preserving the
across both loading interfaces, including import, overlay, and CLI handling. existing version lifecycle and protections. Keep filesystem-context selection
Keep filesystem-context selection independent of version checking. independent of version checking.
- Refactor mapping assembly and provenance updates where current algorithms - Refactor mapping assembly and provenance updates where current algorithms
would scale poorly under layered workloads. Keep optimization scope tied to would scale poorly under layered workloads. Keep optimization scope tied to
the new workflow rather than rewriting unrelated library subsystems. the new workflow rather than rewriting unrelated library subsystems.
@@ -317,8 +313,9 @@ These are responsibility areas, not implementation stages:
- Compare equivalent logical inputs across supported source kinds and loading - Compare equivalent logical inputs across supported source kinds and loading
interfaces. Assert consistent values, presence, operation outcomes, and origin interfaces. Assert consistent values, presence, operation outcomes, and origin
meaning while allowing genuine location/label differences. Cover defaulted and meaning while allowing genuine location/label differences. Cover defaulted and
derived values, replacement followed by typed defaults, version conflicts under derived values, replacement followed by typed defaults, and preservation of
composition, and effective-version checking after intentional overrides. version ownership/check timing across both loading interfaces. Verify that
unversioned layered loads need no synthetic version-owning root.
- Provide maintained simple and PromptKit-shaped examples: embedded defaults, - Provide maintained simple and PromptKit-shaped examples: embedded defaults,
operator configuration from another context, and labeled programmatic input. operator configuration from another context, and labeled programmatic input.
Demonstrate exact operations and resource origins without provider calls or Demonstrate exact operations and resource origins without provider calls or
@@ -330,10 +327,10 @@ These are responsibility areas, not implementation stages:
as behavior lands. Record significant boundary changes in an ADR without as behavior lands. Record significant boundary changes in an ADR without
rewriting accepted ADR history. Keep named inheritance explicitly separate. rewriting accepted ADR history. Keep named inheritance explicitly separate.
Plan a minor release for the new public capability and the deliberate change to Plan an additive minor release for the new public capability, preserving current
schema-version ownership and checking order. Explain the version-checking change version semantics. If another design choice requires changing documented behavior,
and provide migration guidance; this release is not wholly additive. Identify any identify that change expressly and provide migration guidance rather than calling
other compatibility changes expressly rather than calling them optimizations. it an internal optimization.
No release, implementation change, or current-policy revision occurs in this pass. No release, implementation change, or current-policy revision occurs in this pass.
## Completion criteria ## Completion criteria
@@ -343,8 +340,8 @@ with independently located operator configuration and explicit programmatic
values, and obtain one typed result with accurate presence, sources, history, values, and obtain one typed result with accurate presence, sources, history,
and resource context. No temporary configuration files or serialization round and resource context. No temporary configuration files or serialization round
trip or subsequent generic configuration processing is needed. Simple `Load` trip or subsequent generic configuration processing is needed. Simple `Load`
usage retains its behavior except for the explicitly selected version-policy usage retains its current behavior, including version ownership and validation
change, which is shared by both entry points. Final-value provenance covers input, timing. Layered loading uses the same version policy. Final-value provenance covers input,
defaults, and recorded domain resolution, and metadata distinguishes explicit defaults, and recorded domain resolution, and metadata distinguishes explicit
zero/false from absence even when the typed values are equal. Benchmarks zero/false from absence even when the typed values are equal. Benchmarks
demonstrate that adding inputs does not entail avoidable full-collection copying demonstrate that adding inputs does not entail avoidable full-collection copying
@@ -400,3 +397,20 @@ registry mapping IDs to their filesystems. Metadata stays capability-free and
serializable, but every consumer must maintain and correctly reconcile another serializable, but every consumer must maintain and correctly reconcile another
registry. This is viable if limiting retained filesystem capabilities proves registry. This is viable if limiting retained filesystem capabilities proves
more important than the additional integration machinery. more important than the additional integration machinery.
### 4. Selecting the version-owning input for layered loads
**Recommendation:** let callers explicitly designate one of the supplied base
inputs as the version owner when configuring a `VersionRule`. It need not be a
host file or a newly manufactured root document. Other contributions retain
fragment/override roles with respect to that path. Explicit designation avoids
making version ownership depend on incidental list order and preserves the
existing selected-source model without changing version acceptance or timing.
No designation is needed when version checking is not configured.
**Alternative:** make the first base input the version owner when checking is
configured. This reduces API ceremony and naturally extends a main-source-plus-
fragments model, but couples ownership to ordering and can make reordering
otherwise independent contributions consequential. Either choice must preserve
the existing version contract; this decision does not reopen effective-version
or per-document version validation.