Record agreed inheritance reference and presence rules
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
# Built-In Sibling Configuration Inheritance
|
||||
|
||||
Status: proposed feature design for agreement; not implemented. This document
|
||||
defines the intended end state and the remaining architectural decisions. A
|
||||
separate implementation plan will define execution steps after design agreement.
|
||||
Status: agreed feature design; not implemented. This document defines the intended
|
||||
end state. A separate implementation plan will define execution steps.
|
||||
|
||||
## Purpose and priorities
|
||||
|
||||
@@ -82,8 +81,26 @@ and final schema validation; a referenced parent must be a mapping.
|
||||
|
||||
Identity comes from the sibling key, not a copied field in the parent payload.
|
||||
The child keeps its key. Application fields such as `name` or `id` follow ordinary
|
||||
combination semantics. Reference-value details and positions without a sibling
|
||||
namespace are addressed in Open Decisions below.
|
||||
combination semantics.
|
||||
|
||||
### Reference values and positions
|
||||
|
||||
A string-valued `extends` names an exact sibling key, including an empty string
|
||||
if that key exists. Explicit `extends: null` means no parent and cancels a
|
||||
relationship supplied by a lower-precedence source or inherited nested payload.
|
||||
Omitting `extends` contributes no change to an existing relationship during
|
||||
combination; if none remains in the effective mapping, the mapping has no parent.
|
||||
Other value shapes are reference errors.
|
||||
|
||||
Cancellation retains the mapping's own assembled settings but adds no settings
|
||||
from the canceled parent. Like a string reference, the null control field is
|
||||
consumed as structural metadata before typed decoding. This follows existing
|
||||
presence and replacement rules without introducing a deletion operator.
|
||||
|
||||
A string-valued `extends` on the document root or directly on a sequence-element
|
||||
mapping has no enclosing mapping of named siblings and produces a location-bearing
|
||||
reference error. ConfigKit does not search farther up for a namespace. Mappings
|
||||
nested within those structures can still use their own sibling namespaces normally.
|
||||
|
||||
### Source precedence first, inheritance second
|
||||
|
||||
@@ -168,8 +185,8 @@ sort before or after its child without changing the meaning. Breadth-first versu
|
||||
recursive traversal is an implementation choice subject to these semantics.
|
||||
|
||||
Nested mappings inside sequences are also visited, while sequence combination
|
||||
continues to replace whole sequences. The treatment of a relationship on a
|
||||
sequence element itself is addressed below.
|
||||
continues to replace whole sequences. A relationship on a sequence element itself
|
||||
follows the reference-position rules above.
|
||||
|
||||
## Loading and validation
|
||||
|
||||
@@ -212,9 +229,17 @@ may load again explicitly using the existing source-reuse contracts.
|
||||
|
||||
Consumers must distinguish direct child input, inherited input, typed defaults,
|
||||
and recorded application-derived values. Explicit zero/false/empty/null settings
|
||||
remain distinguishable from omission. The representation of inherited presence
|
||||
in the existing query surface is an open decision below; Go zero-value inference
|
||||
is not an acceptable substitute.
|
||||
remain distinguishable from omission. Go zero-value inference is not an acceptable
|
||||
substitute.
|
||||
|
||||
An inherited value counts as present configuration input: `IsExplicit` returns
|
||||
true at its destination, while derivation metadata distinguishes inherited input
|
||||
from a direct child declaration. Presence answers whether configuration supplied
|
||||
the value; provenance explains where it came from and how it reached the destination.
|
||||
Typed defaults and application resolver defaults based on absence therefore remain
|
||||
below inherited settings, including inherited zero, false, empty, and null values.
|
||||
The API documentation must explain this effective-input meaning of explicitness;
|
||||
it does not mean the value was written directly at the destination path.
|
||||
|
||||
Each inherited value retains its originating source and source path, together
|
||||
with the relationship that placed it at the child's destination path. Chains
|
||||
@@ -268,12 +293,13 @@ remains the only consumer boundary.
|
||||
Representative examples and behavioral tests should establish source/inheritance
|
||||
ordering, chains and shared parents, enclosing-first nested resolution, independence
|
||||
from parent/child name sort order, failure diagnostics, partial bases, explicit
|
||||
values versus omission, unchanged sequence/null behavior, origin/resource
|
||||
values versus omission, cancellation of relationships with null, invalid reference
|
||||
positions and types, inherited presence during defaulting, unchanged sequence/null behavior, origin/resource
|
||||
preservation, result independence, and safe secret inspection. Both loading entry
|
||||
points and supported source representations should share those semantics.
|
||||
|
||||
A new ADR should record the selected inheritance architecture after the open
|
||||
decisions are resolved. Architecture/deferred-scope documentation must recognize
|
||||
A new ADR should record the selected inheritance architecture.
|
||||
Architecture/deferred-scope documentation must recognize
|
||||
the new structural responsibility; public API, configuration, consumer, and
|
||||
internal documentation should describe implemented behavior when it lands.
|
||||
Implementation sequencing belongs in a separate future plan. Reserving `extends`
|
||||
@@ -290,41 +316,3 @@ It can inspect whether each setting was direct, inherited, defaulted, or derived
|
||||
follow inherited resource origins, and validate final domain meaning. Missing or
|
||||
cyclic relationships fail before a usable result is returned. The consumer needs
|
||||
no separate graph resolver, generic merge pass, or provenance reconstruction.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
### 1. Reference values and positions without a sibling namespace
|
||||
|
||||
**Recommendation:** an omitted `extends` means no relationship; explicit null
|
||||
cancels a relationship supplied by a lower-precedence source or inherited nested
|
||||
payload. A string names an exact sibling key, including an empty string if that
|
||||
key exists. Other value shapes are reference errors. This follows existing
|
||||
presence and replacement rules without introducing a deletion operator.
|
||||
|
||||
A string-valued `extends` on the document root or directly on a sequence-element
|
||||
mapping has no enclosing mapping of named siblings. Report a location-bearing
|
||||
reference error rather than searching elsewhere. Mappings nested within those
|
||||
structures can still use their own sibling namespaces normally. This follows
|
||||
the selected lookup rule, rather than imposing a general ban on nested inheritance.
|
||||
|
||||
**Alternative:** require every present `extends` to be a string. This makes the
|
||||
keyword's value type simpler, but leaves no direct way to cancel an existing
|
||||
relationship while retaining the mapping's other fields. For root/sequence-element
|
||||
references, an ancestor-scope fallback could supply a namespace, but would introduce
|
||||
a positional exception to the agreed immediate-sibling rule; adopting it would
|
||||
require revisiting that decision rather than treating it as an implementation detail.
|
||||
|
||||
### 2. Meaning of inherited presence
|
||||
|
||||
**Recommendation:** an inherited value counts as present input for effective
|
||||
`IsExplicit`/defaulting behavior, with separate derivation metadata distinguishing
|
||||
it from direct child input. This treats inheritance as input expansion, keeps
|
||||
typed and resolver defaults below inherited settings, and avoids consumers
|
||||
reimplementing presence logic. The API must clearly explain that effective
|
||||
presence differs from direct declaration at the destination path.
|
||||
|
||||
**Alternative:** inherited values remain non-explicit at the child path, with
|
||||
a new effective-input-presence query/defaulting rule. This preserves a narrow
|
||||
direct-declaration meaning of explicitness, but requires two presence concepts
|
||||
through the resolver lifecycle and risks defaults overwriting inherited settings
|
||||
unless callers adopt the new query consistently.
|
||||
|
||||
Reference in New Issue
Block a user