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
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.