Settle sequence inheritance and lifecycle coverage

This commit is contained in:
2026-10-22 15:16:42 +00:00
parent 6a4e57e5d3
commit 27797d2392

View File

@@ -1,11 +1,8 @@
# Sequence Identity And Cross-Tier Combination # Sequence Identity And Combination
Status: draft proposal for discussion. This document captures the requested Status: feature roadmap with OD-1 through OD-7 settled. This document captures
capabilities, settled design choices, and initial recommendations. Choices under the targeted behavior for review before preparing a staged implementation plan.
Open Decisions remain unsettled. It is not an implementation plan or an implemented contract.
It is not an implementation plan or an implemented contract. The declaration
structure is settled under OD-2; mode names and default selection are settled
under OD-5.
## Motivation ## Motivation
@@ -19,7 +16,8 @@ records and whose application or installation layers add or supersede records.
Across tiers, authors need three operations: whole-sequence replacement, Across tiers, authors need three operations: whole-sequence replacement,
duplicate-rejecting append, and whole-record replacement by identity. The latter duplicate-rejecting append, and whole-record replacement by identity. The latter
retains unmatched lower-tier records and adds higher-tier records with new retains unmatched lower-tier records and adds higher-tier records with new
identities. Matching records are replaced in full. identities. Matching records are replaced in full. Sibling inheritance through
`extends` uses the same sequence operations and effective-identity defaults.
## Current Baseline ## Current Baseline
@@ -37,6 +35,10 @@ precedence tiers, a higher sequence replaces the lower sequence wholesale.
The [composition contract](../config.md#strict-document-composition) owns these The [composition contract](../config.md#strict-document-composition) owns these
rules; [layered loading](../config.md#layered-loading) owns tier precedence. rules; [layered loading](../config.md#layered-loading) owns tier precedence.
Current [sibling inheritance](../config.md#sibling-inheritance) recursively
overlays an inheriting mapping onto its resolved parent and replaces supplied
sequences wholesale. The proposed inheritance extension is settled in OD-7.
Source-backed underlays and `Definition.Defaults` have different lifecycle Source-backed underlays and `Definition.Defaults` have different lifecycle
roles. Underlays participate in source assembly; typed defaults are applied roles. Underlays participate in source assembly; typed defaults are applied
later. Extending one does not automatically imply extending the other. later. Extending one does not automatically imply extending the other.
@@ -119,7 +121,8 @@ conflicting declaration is invalid. Whole-sequence replacement does not itself
require identity matching, but application-owned constraints still apply. require identity matching, but application-owned constraints still apply.
Identity-policy lifetime across tiers is settled in OD-3 below. Identity-policy lifetime across tiers is settled in OD-3 below.
Mode describes the current tier's combination instruction. A lower tier's Mode describes the collection's combination instruction at source-precedence
and inheritance boundaries, as detailed in OD-7. A lower tier's
`append` does not silently select append for a later overlay. Gather collection `append` does not silently select append for a later overlay. Gather collection
declarations before composing their relevant scope so their effect does not declarations before composing their relevant scope so their effect does not
depend on which contribution is assembled first. Identity agreement is settled depend on which contribution is assembled first. Identity agreement is settled
@@ -352,7 +355,7 @@ contributions, empty sequences, null, and kind mismatches.
Use the mode names `replace`, `append`, and `upsert`, with one spelling per Use the mode names `replace`, `append`, and `upsert`, with one spelling per
operation: operation:
| Mode | Behavior between tiers | | Mode | Behavior at source-precedence and inheritance boundaries |
| --- | --- | | --- | --- |
| `replace` | Replace the complete lower sequence with the assembled higher sequence | | `replace` | Replace the complete lower sequence with the assembled higher sequence |
| `append` | Retain lower records and append higher records; duplicate identities fail | | `append` | Retain lower records and append higher records; duplicate identities fail |
@@ -383,7 +386,8 @@ YAML-only identity with the lower sequence, use the replacing tier's identity
declaration if supplied, and preserve application-owned constraints. Selecting declaration if supplied, and preserve application-owned constraints. Selecting
`append` or `upsert` explicitly still requires an effective identity. `append` or `upsert` explicitly still requires an effective identity.
This default governs combination between tiers. Within a tier, identified This default governs combination between tiers and during sibling inheritance
under OD-7. Within a tier, identified
sequences append distinct records and reject duplicate identities regardless of sequences append distinct records and reject duplicate identities regardless of
mode. Unidentified sequences retain their existing strict-composition conflict mode. Unidentified sequences retain their existing strict-composition conflict
behavior; this decision does not introduce unkeyed concatenation. behavior; this decision does not introduce unkeyed concatenation.
@@ -481,12 +485,12 @@ nor exact causal reconstruction for records supplied by defaults or callbacks.
### Assembly-Time Enforcement For YAML-Only Identities ### Assembly-Time Enforcement For YAML-Only Identities
Enforce identities declared only in YAML during structural composition and Enforce identities declared only in YAML during structural composition,
precedence assembly. They do not carry a final-result guarantee after later precedence assembly, and identified collection operations during sibling
defaulting, inheritance, CLI overrides, or application resolution. Those stages inheritance. They do not carry a final-result guarantee after defaulting, CLI
may produce a collection that no longer satisfies a YAML-only identity, including overrides, or application resolution. Those operations may produce a collection
duplicate identities. OD-7 still owns whether any additional lifecycle stages that no longer satisfies a YAML-only identity, including duplicate identities.
participate in the new combination operations. OD-7 defines the combination and validation boundaries.
Applications requiring a final identity constraint register it through the Applications requiring a final identity constraint register it through the
application-owned interface. This keeps YAML declarations aligned with the application-owned interface. This keeps YAML declarations aligned with the
@@ -525,6 +529,100 @@ Identity validation checks actual sequences; application schema and validation
own the permitted shape. Null as a collection is distinct from a present null own the permitted shape. Null as a collection is distinct from a present null
identity component inside a record, which is valid under OD-3. identity component inside a record, which is valid under OD-3.
### Lifecycle Coverage And Sibling Inheritance
**OD-7: settled.**
Apply the sequence operations during source composition and precedence assembly,
selected overlays, and sibling inheritance through `extends`. Preserve the
existing combination semantics of `Definition.Defaults`, CLI overrides, and
application resolution callbacks.
#### Inheritance Operations And Controls
Complete source-tier assembly before resolving inheritance, retaining the
existing dependency-ready inheritance algorithm and scope rules. At each
inheritance combination, the resolved parent's collection is the lower value
and the inheriting mapping's local collection is the higher value. Use the same
operation selection as source precedence: an explicit mode wins; otherwise use
`upsert` with effective identity and `replace` without it. There is no separate
default-append rule for inheritance.
Use the inheriting destination collection's controls. Its selected mode governs
both source-precedence and inheritance combinations at that destination, without
separate per-phase mode settings. A mode governing the parent's source collection
does not automatically become an instruction at the inheriting destination merely
because records are inherited. Retain the relevant controls until inheritance
uses them, then keep them out of application decoding. Identity agreement,
application constraints, and replacement lifetime follow OD-3.
For example:
```yaml
configkit:
sequences:
- destination: [parent, items]
key: id
child:
items:
- id: foo
value: A
- id: bar
value: B
parent:
extends: child
items:
- id: baz
value: C
```
Despite the mapping names, `parent` inherits from `child` in this example.
The effective identity at `[parent, items]` selects `upsert`, yielding records
`[foo, bar, baz]`. If the local contribution instead supplies a revised `foo`,
the result is `[foo*, bar]`: replace the complete record in its existing position.
Adding `mode: append` would reject that repeated identity; `mode: replace` would
retain only the local sequence.
Mappings continue to combine recursively. Identified sequence records remain
whole-record replacements, not recursive field merges. Identity supplies the
matching key; ConfigKit does not infer identity from a field named `id` or from
record position. Append and upsert continue to require effective identity, and
this extension does not introduce unkeyed sequence concatenation.
Apply OD-4 ordering and OD-6 presence and kind rules at inheritance boundaries.
An omitted local sequence retains the inherited sequence. An explicit empty
sequence clears it under replace, while append and upsert contribute no records.
#### Other Lifecycle Stages
Source-backed underlays participate in the new combination model, including
application-supplied mapping sources. Typed `Definition.Defaults` remain the
initial decoded state: supplied sequences replace default sequences. Source
`mode: append` does not append to a typed default list.
CLI overrides retain explicit replacement for supplied sequences. Application
resolution retains its existing assignment and recorded-transformation semantics;
ConfigKit does not automatically combine a callback's assigned sequence with
its previous value. Application-registered identities still receive final
validation under OD-1, independently of how these stages produce their values.
#### Validation Timing
Allow item-local helper imports to complete, and consume applicable non-main
source-version headers, before checking the application payload's identity for
collection assembly. A helper may supply an identity field; a consumed header
cannot supply a component after removal. Validate each identified contribution
before combination and uniqueness in the resulting identified collection,
including inheritance operations. An upsert match across a precedence boundary
is a replacement, not a duplicate error; duplicates within a contribution remain
errors.
Later inheritance, typed defaults, or callbacks do not repair an identity missing
at an earlier assembly boundary. Final application-registered validation examines
the final effective typed collection, while YAML-only enforcement remains limited
to the structural operations described above.
## Architectural Direction ## Architectural Direction
The settled collection declaration gives imported and inline records at the same The settled collection declaration gives imported and inline records at the same
@@ -535,8 +633,9 @@ OD-3 settles identity agreement and lifetime; OD-4 settles tier-wide operation
selection, strict peer composition, and ordering at precedence boundaries. selection, strict peer composition, and ordering at precedence boundaries.
This requires collection policy to survive import expansion through precedence This requires collection policy to survive import expansion through precedence
assembly. Correctness includes final values, projected item paths, source assembly and the applicable inheritance operations. Correctness includes final
destinations, provenance, history, sensitivity, and passive resource contexts. values, projected item paths, source destinations, provenance, history,
sensitivity, and passive resource contexts.
Appending changes final indexes; replacing changes which contributions survive. Appending changes final indexes; replacing changes which contributions survive.
The implementation must account for both through the existing loading lifecycle. The implementation must account for both through the existing loading lifecycle.
@@ -551,44 +650,15 @@ require adopting them.
The proposal would extend identity declaration ownership and revise the The proposal would extend identity declaration ownership and revise the
cross-tier replacement decision in cross-tier replacement decision in
[ADR 0014](../adr/0014-sequence-placement-and-composition.md). If adopted, record [ADR 0014](../adr/0014-sequence-placement-and-composition.md), as well as sequence
replacement during inheritance in
[ADR 0009](../adr/0009-sibling-inheritance.md). Record
the architectural change in a superseding decision and reconcile affected the architectural change in a superseding decision and reconcile affected
architecture policy before implementation. The current ADR and contracts remain architecture policy before implementation. The current ADR and contracts remain
authoritative until that decision is made. This draft neither changes them nor authoritative until that decision is made. This draft neither changes them nor
selects migration machinery. selects migration machinery.
A staged implementation plan should follow resolution of the questions below. A staged implementation plan should follow review of this settled roadmap.
It should cover ordinary and layered loading, item-local scopes, source-version It should cover ordinary and layered loading, item-local scopes, source-version
processing, identity validation, precedence, and inspection together. Public API processing, identity validation, precedence, inheritance, and inspection together.
design and test sequencing belong to that later plan. Public API design and test sequencing belong to that later plan.
## Open Decisions
### OD-7. Which Lifecycle Stages Participate?
Do the new cross-tier operations extend only source-backed tiers, or also
`Definition.Defaults`, inheritance, CLI overrides, and application-created records?
At which boundaries
must identity be validated, including helper-supplied fields and consumed source
version headers?
**Initial recommendation:** Start with source-backed strict composition and
precedence assembly. Validate records at the relevant collection assembly
boundaries and uniqueness across each combined result. Preserve existing
typed-default and application-resolution semantics unless their inclusion is
explicitly chosen. Selected-overlay combination is included in the settled scope;
its declaration mechanism is settled in OD-2. Account for item-local helpers and
source-version consumption before deciding identity is available, consistent
with the current lifecycle.
The settled OD-1 guarantee covers final validation of application constraints.
Validating the final collection does not itself change how defaults, inheritance,
CLI overrides, or callbacks combine values.
**Alternative:** Extend the combination operations through defaulting,
inheritance, overrides, and application resolution. This would support
progressively extending collections across more of the lifecycle, but requires
additional combination, callback, and inspection rules. Supporting typed default
lists is a separate scope choice from extending source-backed baseline
collections; the application-owned final-result guarantee remains independent
of this combination-scope decision.