Resolve inheritance between identified records

This commit is contained in:
2026-10-23 20:48:46 +00:00
parent 268fd03579
commit 33a51606da
10 changed files with 447 additions and 31 deletions

View File

@@ -222,41 +222,55 @@ is recorded in [ADR 0011](adr/0011-input-destinations.md) and
Any input mapping may declare `extends: name` to inherit from the mapping named
`name` among its immediate siblings. Names are exact keys, including the empty
string; lookup does not search ancestor or unrelated scopes. The document root
and a sequence-element mapping have no sibling namespace for their own string
relationship, though mappings nested inside them can have one. An `extends`
string; lookup does not search ancestor or unrelated scopes. A mapping inside a
sequence can also participate in record inheritance when that sequence has an
effective identity declaration from `configkit.sequences` or an application
registration. In that case, `extends` is a mapping containing exactly the
sequence's identity fields, with scalar values; lookup is limited to that final
sequence. The document root and a sequence-element mapping without an effective
identity declaration have no sibling namespace for non-null string
relationships, though mappings nested inside them can have one. An `extends`
value of null cancels a relationship without looking up a parent. Other value
types, missing or non-mapping parents, and cycles fail the load with value-free
diagnostics.
types, incomplete or extra reference fields, missing parents, and cycles fail
the load with value-free diagnostics.
Within each sibling scope, direct mapping definitions resolve by dependency
readiness. A parent is resolved before a child; among currently eligible
definitions, the lexically smallest canonical semantic pointer is selected,
including newly eligible definitions as soon as their parent completes. This
ordering governs inheritance operations and their history, controls, and
transfers. It does not reorder the mappings in the resulting configuration.
Within each mapping sibling scope or identified sequence, direct definitions
resolve by dependency readiness. A parent is resolved before a child; among
currently eligible definitions, the lexically smallest canonical semantic
pointer is selected, including newly eligible definitions as soon as their
parent completes. This ordering governs inheritance operations and their
history, controls, and transfers. It does not reorder mappings or sequence
records in the resulting configuration.
`extends` is reserved structural input across ordinary and layered loads, every
source kind, imports, selected overlays, and explicit CLI overrides. It is
consumed before typed decoding and need not appear in the application's Go
types. Applications previously using `extends` as an ordinary YAML field must
rename that key and its field. No collection registration or keyword setup is
required.
required for mapping-sibling relationships; identified-sequence relationships
require effective identity fields for that collection.
ConfigKit completes strict composition within tiers and precedence assembly
between tiers before resolving relationships. An omitted `extends` retains a
lower-priority relationship; `extends: null` cancels it while preserving the
child's own settings. Superseded references are historical evidence, not active
relationships to validate. Each child recursively overlays its own settings
over its resolved parent: explicit zero, false, empty string, and
null values replace inherited values, while mappings combine recursively.
between tiers before resolving relationships. Only records that survive that
assembly participate in identified-sequence lookup: an upserted parent supplies
its final record, a replaced parent is unavailable, and a higher replacement
without `extends` supersedes a lower relationship. An omitted `extends` retains
a lower-priority mapping-sibling relationship; an identified record's effective
directive depends on the record that survives assembly. `extends: null` cancels
a relationship while preserving the child's own settings. Superseded references
are historical evidence, not active relationships to validate. Each child
recursively overlays its own settings over its resolved parent: explicit zero,
false, empty string, and
null values replace inherited values, while mappings combine recursively. For
identified records, the child's identity fields and their origins remain its
own; parent identity fields do not contribute to the payload.
Sequences at collection destinations use the shared collection operation with
the parent as lower input and the child as higher input. The destination's
explicit mode applies; otherwise a copied identity selects upsert and an
unkeyed destination replaces. A parent's explicit mode does not move to a
different destination. Sequences outside collection destinations remain atomic
replacements.
The child retains its key. All effective relationships resolve, including
All effective relationships resolve, including
entries the application may never select for execution. Partial parent
definitions undergo normal typed decoding and application-owned validation,
not a special structural exemption.
@@ -822,12 +836,14 @@ Identical registrations coalesce; conflicting registrations at one path and
invalid registration paths produce `options.invalid`. Unused and root registrations
are allowed and have no effect.
Registration changes strict composition only. Each underlay group and the main
tier has independent duplicate-identity state. Precedence assembly is unchanged:
a present higher-priority sequence replaces the lower sequence as one value,
including at a registered path. Overlays, CLI overrides, defaults, inheritance,
and application resolution do not run the registered identity check. The accepted
rationale is recorded in [ADR 0014](adr/0014-sequence-placement-and-composition.md).
Registration controls strict composition and supplies identity fields for parent
lookup when surviving records in that sequence use `extends`. Each underlay group
and the main tier has independent duplicate-identity state. Precedence assembly
is unchanged: a present higher-priority sequence replaces the lower sequence as
one value, including at a registered path. Registration does not add a final
identity check to defaults, application resolution, or the published typed
configuration. The accepted rationale is recorded in
[ADR 0014](adr/0014-sequence-placement-and-composition.md).
The [maintained prompt catalog](consumers/README.md#identified-prompt-sequences)
shows item path and glob imports, helper-supplied identity, and main-tier
replacement of a lower-priority sequence.