Settle sequence inheritance and lifecycle coverage
This commit is contained in:
@@ -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.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user