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
|
||||
capabilities, settled design choices, and initial recommendations. Choices under
|
||||
Open Decisions remain unsettled.
|
||||
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.
|
||||
Status: feature roadmap with OD-1 through OD-7 settled. This document captures
|
||||
the targeted behavior for review before preparing a staged implementation plan.
|
||||
It is not an implementation plan or an implemented contract.
|
||||
|
||||
## 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,
|
||||
duplicate-rejecting append, and whole-record replacement by identity. The latter
|
||||
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
|
||||
|
||||
@@ -37,6 +35,10 @@ precedence tiers, a higher sequence replaces the lower sequence wholesale.
|
||||
The [composition contract](../config.md#strict-document-composition) owns these
|
||||
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
|
||||
roles. Underlays participate in source assembly; typed defaults are applied
|
||||
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.
|
||||
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
|
||||
declarations before composing their relevant scope so their effect does not
|
||||
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
|
||||
operation:
|
||||
|
||||
| Mode | Behavior between tiers |
|
||||
| Mode | Behavior at source-precedence and inheritance boundaries |
|
||||
| --- | --- |
|
||||
| `replace` | Replace the complete lower sequence with the assembled higher sequence |
|
||||
| `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
|
||||
`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
|
||||
mode. Unidentified sequences retain their existing strict-composition conflict
|
||||
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
|
||||
|
||||
Enforce identities declared only in YAML during structural composition and
|
||||
precedence assembly. They do not carry a final-result guarantee after later
|
||||
defaulting, inheritance, CLI overrides, or application resolution. Those stages
|
||||
may produce a collection that no longer satisfies a YAML-only identity, including
|
||||
duplicate identities. OD-7 still owns whether any additional lifecycle stages
|
||||
participate in the new combination operations.
|
||||
Enforce identities declared only in YAML during structural composition,
|
||||
precedence assembly, and identified collection operations during sibling
|
||||
inheritance. They do not carry a final-result guarantee after defaulting, CLI
|
||||
overrides, or application resolution. Those operations may produce a collection
|
||||
that no longer satisfies a YAML-only identity, including duplicate identities.
|
||||
OD-7 defines the combination and validation boundaries.
|
||||
|
||||
Applications requiring a final identity constraint register it through 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
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
This requires collection policy to survive import expansion through precedence
|
||||
assembly. Correctness includes final values, projected item paths, source
|
||||
destinations, provenance, history, sensitivity, and passive resource contexts.
|
||||
assembly and the applicable inheritance operations. Correctness includes final
|
||||
values, projected item paths, source destinations, provenance, history,
|
||||
sensitivity, and passive resource contexts.
|
||||
Appending changes final indexes; replacing changes which contributions survive.
|
||||
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
|
||||
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
|
||||
architecture policy before implementation. The current ADR and contracts remain
|
||||
authoritative until that decision is made. This draft neither changes them nor
|
||||
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
|
||||
processing, identity validation, precedence, and inspection together. 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.
|
||||
processing, identity validation, precedence, inheritance, and inspection together.
|
||||
Public API design and test sequencing belong to that later plan.
|
||||
|
||||
Reference in New Issue
Block a user