# Sequence Identity And Combination Status: feature roadmap with OD-1 through OD-11 settled. A whole-roadmap review identified the remaining policy-lifetime clarification in OD-12 below. Resolve it and review the completed roadmap before preparing a staged implementation plan. This is not an implementation plan or an implemented contract. ## Motivation Allow configuration authors to assemble collections from independently authored records, declare their identity in configuration, and progressively extend a baseline collection through higher layers. Authors should also be able to replace the accumulated collection or replace individual records by identity. The motivating example is a prompt collection whose defaults supply some 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. Sibling inheritance through `extends` uses the same sequence operations and effective-identity defaults. ## Current Baseline The [import contract](../config.md#explicit-imports) owns current selector, destination, placement, and ordering behavior. An import with `placement: sequence-item` places each selected source mapping as one item at its effective destination. Item-local helper imports can contribute fields before placement. The application currently registers sequence identity through `Definition.SequenceCompositions`, using one literal string field at each registered mapping path. Within a strict tier, distinct identities append and duplicate identities fail. Repeated unregistered sequences conflict. Across 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. ## Requested Capabilities The proposed `configkit.sequences` block introduces a `key` declaration that accepts either one field or a list of fields for a compound identity. Fields are treated as a set; identity components may be strings, numbers, booleans, or explicitly supplied null values. Applications retain an optional interface for registering a collection and imposing its identity definition. Configuration declarations must conform to an application-owned constraint when one exists. The exact Go interface remains to be designed. ```yaml configkit: sequences: - destination: [prompts] key: [namespace, id] mode: append imports: - dir: prompts pattern: '*.yaml' destination: [prompts] placement: sequence-item ``` Each selected file would contribute a record such as: ```yaml namespace: support id: welcome text: Welcome ``` Here `mode: append` illustrates retaining a lower-layer collection and adding distinct records from the higher layer. The `mode` field expresses the operation; OD-5 defines its names and effective-identity default. Identity and combination controls belong to the collection declaration; import shorthand is deferred. Letters below denote record identities; `B*` is a higher-tier record with the same identity as `B` and a different payload. The outcomes and ordering shown are settled below. | Lower-tier sequence | Higher-tier sequence | Operation | Proposed result | | --- | --- | --- | --- | | `[A, B]` | `[C]` | `append` | `[A, B, C]` | | `[A, B]` | `[C]` | `replace` | `[C]` | | `[A, B]` | `[B*]` | `append` | Duplicate-identity error | | `[A, B]` | `[B*]` | `replace` | `[B*]` | | `[A, B]` | `[B*]` | `upsert` | `[A, B*]` | | `[A, B]` | `[B*, C]` | `upsert` | `[A, B*, C]` | Whole-sequence replacement discards the lower sequence. A repeated identity in the retained combined sequence is an error under the proposed append semantics, including when the records have identical or disjoint payloads. ## Settled Design Choices ### Collection Declarations **OD-2: settled.** Use a root `configkit.sequences` block containing a sequence of collection declarations. Each entry identifies a `destination` and may declare `key`, `mode`, or both. Application sequences remain ordinary YAML data. This declaration form serves imported items, inline records, and sequences supplied by ordinary mapping imports, including inline sequences in selected overlays. `destination` uses the existing sequence of literal mapping keys. Resolve it relative to the declaring source's placement: a fragment mounted under `catalog` can declare `[prompts]` locally. A sequence-item source can declare a nested collection within its own item without referring to an eventual numeric index. Preserve those source and item-local scope boundaries. OD-11 settles policy ownership when enclosing records are replaced or inherited. Identity and mode can be supplied independently. Omitted identity can use an application registration; an explicit matching declaration is accepted, and a 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 collection's combination instruction at source-precedence and inheritance boundaries, as detailed in OD-7. An explicit mode persists at the same applicable destination until a higher-tier declaration changes it. Gather collection declarations before composing their relevant scope so their effect does not depend on which contribution is assembled first. Identity agreement is settled in OD-3; operation agreement and omission among peers are settled in OD-4. OD-9 settles how operation controls survive source precedence for later inheritance. Permit sequence declarations in selected overlays and make their use independent of filesystem import enablement. This deliberately changes the current blanket prohibition on overlay `configkit` declarations. Enabling imports in overlays is not part of this decision. Consume sequence controls before application decoding, as with other structural directives. For example, an overlay can replace a complete record by identity: ```yaml configkit: sequences: - destination: [prompts] key: id mode: upsert prompts: - id: foo text: Revised definition ``` The explicit `mode: upsert` line can be omitted here when no different explicit mode applies from a lower tier: `key: id` then supplies the identity for inferred upsert. An overlay can instead select duplicate-rejecting append: ```yaml configkit: sequences: - destination: [prompts] key: id mode: append prompts: - id: baz text: Another prompt ``` Or it can explicitly select whole-sequence replacement: ```yaml configkit: sequences: - destination: [prompts] mode: replace prompts: - id: bar text: Bar definition - id: baz text: Baz definition ``` Explicitly selecting the default operation is valid. With no applicable explicit mode, removing the last example's `configkit` block selects replace only when no effective identity is available; an identified collection instead selects upsert. A retained explicit mode also affects omission. Explicit `mode: replace` overrides either another retained mode or inferred upsert. OD-5 defines the selection rule for `replace`, `append`, and `upsert`. Start with this common collection declaration and defer `key` and `mode` shorthand on imports. A single declaration form covers inline overlays and mixed inline/imported collections without duplicate authoring surfaces. Local wrappers around sequence values would require distinguishing application data from control mappings; the existing reserved namespace keeps that distinction clear. ### Identity Definitions And Lifetime **OD-3: settled.** #### Field Sets `key` accepts a string or a nonempty list of strings naming direct, literal fields in each record. `key: id` and `key: [id]` are equivalent. A name such as `metadata.id` denotes that literal field, not a nested lookup. Treat the selected fields as a set: remove repeated names and disregard authored field order when comparing definitions. For example, `[namespace, id]`, `[id, namespace]`, and `[namespace, id, id]` define the same identity. An empty list is invalid because it supplies no identity fields. These equivalence rules also apply when comparing configuration declarations with application registrations. Use a consistent field order internally to construct compound identity tuples. Preserve component types and tuple boundaries; concatenating unstructured values must not cause otherwise distinct identities to collide. #### Scalar Components And Equality Each identified record must be a mapping, and every designated identity field must be present. Components may be strings, numbers, booleans, or explicit null. Missing fields and mapping or sequence components are invalid. A present null is a valid component and is distinct from an absent field. Two single-field null identities are equal; in a compound identity, all components must compare equal. Strings compare exactly, with no trimming, case folding, or normalization. Empty strings remain valid. Scalar categories remain distinct: the string `"1"`, the number `1`, the boolean `true`, and null are different identities. Numbers compare by mathematical value across integer, fractional, and exponent spellings: `1`, `1.0`, and `1e0` are equal, as are `0` and `-0`. Use exact numeric normalization for identity comparison without rounding through a floating-point conversion. This comparison does not rewrite authored values or alter existing typed decoding and projection semantics. The existing parser's rejection of non-finite numeric forms remains unchanged. #### Agreement And Introduction Within a strict tier, identity declarations for the same collection must agree. Equivalent field sets coalesce; different sets produce an error. Across tiers, append and replacement by identity use one agreed definition for the records being combined: | Lower collection identity | Higher declaration | Result when combining records | | --- | --- | --- | | `id` | Omitted | Use `id` | | `id` | `id`, `[id]`, or `[id, id]` | Accept the equivalent definition | | `id` | `[namespace, id]` | Error: different identity definitions | | None | `id` | Establish `id` and validate all participating records under it | OD-10 makes applicable lower-tier YAML identity available during the higher tier's strict composition, before this precedence combination occurs. An application registration supplies identity when configuration omits it and remains authoritative over explicit declarations. If neither the application nor either participating collection supplies an identity, append and replacement by identity fail; ConfigKit does not infer an `id` convention. Introducing identity for a previously unkeyed lower sequence requires checking both lower and incoming records, including uniqueness within each contribution. #### Replacement And Policy Lifetime YAML-owned identity follows the collection that survives an operation: | Operation | Effective YAML-owned identity | | --- | --- | | Append | Retain or establish the agreed identity | | Replacement by identity | Retain or establish the agreed identity | | Whole-sequence replacement | Use the replacing tier's declaration and discard the lower collection's YAML-only identity | Without an application constraint, whole-sequence replacement may introduce a different identity, such as replacing an `id`-keyed collection with a `name`-keyed collection. A whole-sequence replacement with no new identity declaration and no application registration produces an unkeyed sequence. No separate identity removal directive is needed. Application registrations continue to constrain the replacement collection. If the application requires `id`, declaring `name` is invalid under every mode. The policy reset above applies when a sequence is actually replaced; effects of absent contributions, null collections, and kind mismatches are settled in OD-6. YAML-only identity declarations receive assembly-time enforcement, as settled in OD-1 below. ### Combination Scope, Declarations, And Ordering **OD-4: settled.** #### One Operation Per Collection Per Tier Resolve applicable collection policy, including available lower-tier identity under OD-10, before strictly composing a tier's contributions. Then apply one selected operation per collection against the accumulated lower sequence. A collection declaration governs all contributions to that collection in its tier, including imported and inline records; it does not govern only records in the declaring file. Collection scope is the resolved destination within its composition scope. Resolve relative destinations first and preserve separate item-local scopes for collections inside different imported items. Apply the same combination semantics to selected overlay contributions. For example, with an agreed identity, higher-tier fragments contributing `[C]` and `[D]` assemble `[C, D]`. Against lower `[A, B]`, append or replacement by identity produces `[A, B, C, D]`; whole-sequence replacement produces `[C, D]`. The tier operation does not sequentially replace peer source contributions. #### Operation Agreement And Omission Coalesce agreeing explicit modes for the same collection within a tier and reject conflicting explicit modes. Omission expresses no preference; apply the effective-identity default only after reconciling declarations and checking for an applicable explicit mode retained from a lower tier. | Modes declared within one tier | Effective operation | | --- | --- | | `append` and `append` | `append` | | `append` and omitted | `append` | | `replace` and omitted | `replace` | | `append` and `replace` | Error | | All omitted | Retain an applicable lower explicit mode; otherwise infer from effective identity | Explicitly selecting the default is a real instruction and can conflict with another explicit selection. Different modes in different tiers are valid; the higher tier's explicit mode replaces the lower mode, while omission retains it. Neither a root declaration nor a later declaration wins over conflicting peers. Diagnostics identify the collection destination and conflicting declaration locations. OD-5 defines mode names and the default-selection rule. #### Strict Duplicate Handling Duplicate identities among peer contributions or within one contributed list remain strict-composition errors under all three modes. For example, peer fragments contributing `[B]` and `[B*]` conflict even under replacement by identity: neither has higher precedence. Lower `[B]` and higher `[B*]` can instead produce `[B*]` at a precedence boundary. Whole-sequence replacement does not permit duplicate identities within an identified higher-tier sequence. #### Ordering Retain existing dependency-ready source scheduling within each tier and authored item order within each list. Gathering collection declarations does not change assembly order, and identity values do not sort records. Across tiers: - Append retains lower records in order, followed by higher records in assembled order. - Whole-sequence replacement retains only the higher sequence, in its assembled order. - Replacement by identity replaces matched records in their existing lower positions and appends new identities in higher-tier order. For example, lower `[A, B, C]` and higher `[C*, A*, D]` produce `[A*, B, C*, D]` under replacement by identity. Updating a record's contents preserves its position; whole-sequence replacement gives the higher tier control of the complete sequence order. OD-5 settles default selection and operation naming. OD-6 settles absent contributions, empty sequences, null, and kind mismatches. ### Mode Names And Effective-Identity Defaults **OD-5: settled.** Use the mode names `replace`, `append`, and `upsert`, with one spelling per operation: | 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 | | `upsert` | Replace matching records in full, retain unmatched lower records, and append new identities | `upsert` preserves the existing positions of matching lower records and adds new identities in higher-tier order, as settled in OD-4. It does not recursively merge fields within matching records. Select the operation at each collection's precedence boundary in this order: 1. Reconcile explicit modes within the current tier under OD-4; conflicting explicit modes fail. 2. If the current tier supplies an explicit mode, use it in place of a lower mode. 3. Otherwise, retain an applicable explicit mode from a lower tier. 4. If no explicit mode applies, select `upsert` when effective identity is available. 5. Otherwise, select `replace`. Effective identity may come from an application registration, a current-tier declaration, or the lower collection, subject to OD-3's agreement rules. Selection depends on identity availability, not on whether the current tier explicitly repeats a `key` declaration. With no applicable explicit mode, a plain overlay sequence can therefore default to `upsert` when identity was established elsewhere. New sequence values do not reset an existing explicit mode. Inferred defaults do not become persistent explicit instructions: when no explicit mode applies, determine the default from the identity available at that boundary. Determine the inferred mode using the available identity before applying the operation. `replace`, including a retained explicit mode, follows OD-3: discard the lower collection's 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 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. ### Whole-Record Replacement By Identity The `upsert` operation replaces each matching lower record with the complete higher record, retains unmatched lower records, and adds new identities. For example, given these lower and higher records: ```yaml # Lower record id: B text: Original temperature: 0.5 ``` ```yaml # Higher record id: B text: Revised ``` The resulting record at this precedence boundary contains `id` and `text`. The lower record's `temperature` is discarded. Subsequent defaulting or other lifecycle operations retain their separately defined semantics. Recursive field-by-field overlay of matching records is outside this selected operation. ### Selected Overlay Control Selected overlay authors must be able to choose any of the three operations for a sequence supplied by the overlay, including records authored inline. The operation applies against the existing effective sequence at that path. For an existing sequence `[foo, bar]`: | Overlay contribution | Selected operation | Result | | --- | --- | --- | | `[foo*]` | Replacement by identity | `[foo*, bar]` | | `[baz]` | Append | `[foo, bar, baz]` | | `[bar, baz]` | Whole-sequence replacement | `[bar, baz]` | Here `foo*` has the same identity as `foo` and supplies its complete replacement record. Append retains its duplicate-identity error semantics. The retained records, replacement behavior, and ordering shown are settled, including the OD-4 rule that matched records retain their lower positions. The settled OD-2 collection declaration supplies the overlay authoring surface. OD-5 supplies operation names and effective-identity default selection. The current [selected-overlay contract](../config.md#selected-overlays) remains the baseline until the new controls are implemented. ### Optional Application-Owned Identity Constraints Retain an interface through which applications may register a collection and impose its unique-key definition. If the application requires `key: id`, a configuration declaration of `key: [id, name]` is invalid: the compound key would permit repeated `id` values with different names. The application identity constraint applies whichever cross-tier operation configuration selects. This is an authoritative constraint, distinct from an application default that only fills an omission. Configuration can define identity for collections without an application-owned constraint. Omitted configuration identity uses a registered definition when present, and an explicit matching declaration is accepted, as settled in OD-2. OD-1 below distinguishes the final-result guarantee for application-owned constraints from assembly-time enforcement for YAML-only declarations. ### Final-Result Guarantee For Application Registrations **OD-1: settled, including the YAML-only follow-up below.** > On successful loading, the final effective collections covered by application > registrations satisfy their declared identity constraints. Retain assembly-time identity checks and validate the final effective collections before publication. This covers the loaded state after defaults, inheritance, overrides, and application resolution have taken effect. Those operations retain their separately defined combination semantics. The guarantee does not require every intermediate callback state to satisfy the constraint and does not extend to caller mutations after loading returns. Keep the promise limited to the declared identity constraints. It does not by itself require registered paths to exist or be non-null. Identity validation checks actual sequences; the application schema and validation determine whether absence, null, or another shape is acceptable, as settled in OD-6. Final validation examines effective typed values, while assembly-time checks retain their role in validating authored contributions. A final scalar value alone does not prove that the field was explicitly supplied in a source. The existing canonical final-value representation and shared publication path provide the implementation foundation. Diagnostics should identify the affected collection and item paths, using available origin information without exposing identity values. The guarantee requires neither a new mutation-history system 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, 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 structural operations they control and avoids extending their policy lifetime through later replacements, callbacks, and nested-record changes solely for final validation. ### Absence, Empty Sequences, Null, And Kind Mismatches **OD-6: settled.** At a collection's precedence boundary: | Higher-tier contribution | `replace` | `append` / `upsert` | | --- | --- | --- | | Absent | Leave the lower value unchanged | Leave the lower value unchanged | | Explicit `[]` | Clear the sequence | Contribute no records | | Explicit null or another non-sequence value | Ordinary replacement, subject to application schema | Error: the operation requires a sequence | A declaration alone does not clear a collection. An optional import selecting nothing contributes nothing; it does not erase records supplied elsewhere. An absent lower collection can be initialized by an incoming sequence under any mode, subject to identity requirements. An explicitly null or other non-sequence lower value is distinct from absence: append and upsert against it fail, while replacement remains available. An empty incoming sequence does not bypass these kind checks or the operation's identity requirements. With effective identity available and no applicable explicit mode, omission selects upsert. Consequently, `prompts: []` alone does not clear such a collection. Clearing it requires replace, selected explicitly in the current tier or retained from a lower declaration. Replacing an identified collection with null likewise requires replacement and an application schema that permits null. An application identity registration does not itself require the collection path to exist or be non-null, and does not independently reject non-sequence values. 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: the effective explicit mode wins, including one retained under OD-9; 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. OD-8 moves their application after inheritance and typed defaulting, before application resolution, secret lookup, and final validation. 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. ### CLI Precedence And Application Resolution **OD-8: settled.** CLI overrides are the highest-precedence input to application resolution. Use this lifecycle order: 1. Assemble source tiers and selected overlays. 2. Resolve sibling inheritance, then apply typed defaults and decode the assembled configuration. 3. Apply explicit CLI overrides to that configuration and check supplied values against the application schema. 4. Run application resolution against the overridden configuration. 5. Resolve effective secret references, validate the final configuration including application-registered identities, and publish it. Sequence values supplied by the CLI replace whole sequences, including sequences inside supplied mappings. Mappings retain ordinary recursive override behavior; empty sequences and permitted nulls retain their explicit replacement meaning. Configuration-selected append or upsert does not reinterpret CLI assignments. Inheritance and defaulting do not run again after CLI application. For inherited and assembled `[A, B]` overridden by CLI `[C]`, application resolution receives `[C]`; inheritance cannot reintroduce `[A, B]` afterward. Application resolution sees CLI values and their explicit-presence and source metadata. Existing `Resolution.Default` behavior preserves explicit CLI values, while normalization and recorded application transformations may still change them. CLI input is authoritative over sources, inheritance, and typed defaults; it is not immutable during application-owned resolution. For example, a derived URL can use a CLI-supplied hostname, while an explicitly supplied CLI URL can be preserved by an absence-based default. Retain existing recording and provenance requirements for those transformations. Secret lookup uses the effective references after both overrides and resolution. Final validation remains after these stages; neither CLI replacement nor application resolution bypasses identity constraints or semantic validation. Reject structural directives such as `extends` and `configkit` in CLI override paths or supplied values. CLI overrides supply application values after structural processing; they do not initiate a second inheritance pass. This deliberately changes the current ability to supply or cancel `extends` through CLI input. CLI changes cannot prevent an earlier inheritance failure or change which relationships that completed pass resolved. Likewise, because typed decoding precedes CLI application, an invalid source value that fails decoding cannot be repaired by a CLI replacement. For example, a string supplied for an integer field fails before a valid integer override can apply. This differs from the current override-before-decoding behavior. Semantic validation remains after overrides and application resolution, as specified above. This ordering supersedes the current CLI-before-inheritance lifecycle described in [ADR 0009](../adr/0009-sibling-inheritance.md). It avoids special replacement markers carried through inheritance. Current contracts remain the implemented baseline until the architectural and implementation work lands. ### Persistent Operation Policy **OD-9: settled; this revises the earlier tier-local mode rule in OD-4 and OD-5.** An explicit mode is collection policy that persists at its applicable destination until a higher-priority declaration changes it. Reconcile peers strictly within each tier, then let a higher explicit mode replace a lower one. Omission retains an applicable explicit mode regardless of whether the higher tier supplies new sequence values. Source precedence and subsequent inheritance use the same effective operation policy. | Lower explicit mode | Higher declaration | Effective mode | | --- | --- | --- | | `append` | Mode omitted | `append` | | `append` | `upsert` | `upsert` | | `upsert` | `replace` | `replace` | | None | Mode omitted, effective identity available | Inferred `upsert` | | None | Mode omitted, no effective identity | Inferred `replace` | An unrelated overlay leaves the policy intact. A mode-only declaration may change the policy without supplying records; it neither clears the collection nor retroactively recombines earlier tiers. A later source contribution or inheritance operation uses the resulting policy. Supplying values alone does not reset it. Only explicit modes persist. Inferred defaults are recomputed from effective identity when needed. Thus explicitly selecting replace for an identified collection continues to select replace in subsequent tiers until another mode is declared; an author wanting upsert afterward must select it explicitly. Identity availability and constraints still follow OD-3, including YAML-only identity removal on whole-sequence replacement. Persisting a mode does not preserve an identity that OD-3 discards. This persistence is scoped to the applicable collection. It does not transfer a parent mapping's mode automatically to another destination through `extends` or resurrect policies owned by discarded records. OD-11 addresses nested policy ownership and transfer, including the distinction between surviving records and inheritance copies. CLI overrides remain outside sequence mode selection under OD-8. Strict peer composition and all ordering rules in OD-4 are unchanged. ### Lower-Tier Identity During Strict Composition **OD-10: settled.** Allow identity established in accumulated lower tiers to inform strict composition of a higher tier. Resolve applicable collection identity before combining that tier's peer contributions, using application registrations, available lower-tier identity, and declarations gathered within the higher tier's relevant scope. Authors need not repeat a baseline identity declaration solely because the higher tier contributes the collection through multiple fragments. For example, an underlay declares `key: id` for `prompts`; two main-tier fragments contribute records `[foo]` and `[bar]` without redeclaring a key. The inherited identity enables those fragments to compose as `[foo, bar]` before the main tier combines with the accumulated lower collection. If both fragments instead contribute `foo`, strict composition fails. A selected upsert mode never grants precedence to peers within the tier. This does not turn lower YAML identity into an application-owned constraint. Determine applicability using OD-3's agreement and replacement rules: append and upsert require agreement, while whole-sequence replacement may change or discard YAML-only identity. A replacing collection must not be constrained by an obsolete lower identity merely because policy resolution precedes strict composition. Application registrations remain authoritative. Under OD-11, a replacement record also cannot borrow item-local identity owned by the discarded lower record, even if both records have the same outer identity or numeric position. Higher-tier declarations do not retroactively repair invalid lower-tier composition. Separate source acquisition from policy-aware composition, or otherwise revise assembly sequencing, so accumulated lower policy is available before higher-tier strict composition. The current main-before-underlay composition order is not a constraint on this design. Preserve the distinction between source acquisition order, strict within-tier dependency-ready scheduling, and precedence order. The implementation plan must account explicitly for source records, callbacks, main-version checks, and failure diagnostics when changing the handoffs. Retain version ownership and validation semantics; do not use higher-tier replacement to hide lower-tier structural failures. ### Nested Policy Ownership And Transfer **OD-11: settled.** Attach item-local collection policies to their owning contributions. Policies follow surviving records independently of numeric indexes. Whole-record upsert replacement discards the old record's local policies along with its fields; whole-sequence replacement likewise discards policies owned by removed records. A replacement record supplies its own local declarations. Sharing an outer identity or occupying the same final index does not transfer the discarded record's policies to its replacement. For example, a source imported as one record into `prompts` can declare: ```yaml configkit: sequences: - destination: [steps] key: id mode: append id: foo steps: - id: prepare ``` The declaration governs `steps` inside that particular `foo` record. Retaining `foo` retains its local policy, including its explicit mode under OD-9. Upserting a new `foo` discards the old `steps` and its declaration; the replacement does not inherit either merely because upsert retains the outer record's position. Distinguish inherited collection identity from operation instructions. YAML identity follows a collection copied through sibling inheritance, subject to OD-3's agreement and replacement rules. The inheriting destination selects its operation under OD-7 and OD-9; the source collection's mode does not automatically become an instruction at the new destination. For example, a source mapping's `steps` collection has `key: id` and `mode: append`. An inheriting mapping supplies local `steps` but no applicable explicit mode. The copied identity selects upsert at the inheriting destination; the source's append mode remains applicable at its own destination. An explicit append declaration at the inheriting destination instead selects append there. A destination declaration of the same key agrees; a different key conflicts when combining records, while explicit replacement can establish a new YAML identity under OD-3. Application registrations remain constraints at their registered destinations; copying a collection does not create another application registration. Policies that independently apply at the destination are not discarded merely because an individual record is replaced. Ownership determines which declarations are removed. This preserves OD-9's persistence rule for applicable explicit modes without retaining declarations owned by discarded records. The implementation plan should choose the bookkeeping needed to preserve these distinctions. ## Architectural Direction The settled collection declaration gives imported and inline records at the same destination a shared identity policy. Declarations are gathered before composing the relevant scope. OD-3 settles identity agreement and lifetime; OD-4 settles tier-wide operation selection, strict peer composition, and ordering at precedence boundaries. OD-10 requires resolving applicable lower-tier policy before higher-tier strict composition, independently of source acquisition order. This requires collection policy to survive import expansion through precedence 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. ## Scope And Decision Ownership This is narrower than the deferred [identified-record sequences proposal](future.md#1-identified-record-sequences), which also considers recursive merging of matching records and record-specific inheritance. Those capabilities remain separate candidates. Compound keys, duplicate-rejecting append, and whole-record replacement by identity do not 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), as well as sequence replacement during inheritance in [ADR 0009](../adr/0009-sibling-inheritance.md), including its CLI-before-inheritance lifecycle ordering. 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 open decisions below and review of the completed roadmap. It should cover ordinary and layered loading, item-local scopes, source-version processing, identity validation, precedence, inheritance, and inspection together. Public API design and test sequencing belong to that later plan. ## Open Decisions ### OD-12. Identity Declarations Without Sequence Values OD-9 defines a mode-only declaration without accompanying records. Clarify the corresponding behavior for `key`, including a declaration made before any sequence exists, and complete OD-3's identity-lifetime rule for non-sequence replacement. These cases must have defined results before the implementation plan chooses how to store collection policy. For example, a lower tier supplies an unkeyed `prompts` sequence and a higher tier only declares `destination: [prompts], key: id`. Does this validate and identify the retained sequence immediately? Can a declaration in an otherwise empty underlay establish identity for main-tier fragments under OD-10? Conversely, if an identified sequence is replaced by null, does its old YAML identity disappear? OD-6 specifies the resulting values but does not fully specify these policy effects. **Recommendation:** Allow identity declarations without accompanying records. Apply the declaration to a retained sequence immediately, checking identity agreement and validating its records; do not recombine earlier tiers. If the collection is absent, retain the declaration in its owning scope for later contributions without requiring the collection to exist. Merely declaring replace without supplying a replacement value does not authorize changing a retained collection's identity. Extend OD-3's replacement rule to any actual replacement of the collection by a non-sequence value: discard the lower YAML-only identity, retain any identity explicitly declared by the replacing tier, and preserve application constraints. An explicit declaration can remain pending at an absent or non-sequence destination without independently imposing a shape requirement; OD-6 still governs whether an attempted operation on a non-sequence value fails. These rules allow baseline policy declarations while keeping identity removal tied to actual replacement. Explicit mode persistence remains governed by OD-9. **Alternative:** Require a YAML identity declaration to have a sequence in the same tier. This keeps YAML identity attached only to concrete sequence values and reduces pending-policy cases, but prevents policy-only baseline files and requires authors to repeat declarations beside later contributions. It also makes identity declarations less flexible than the settled mode declarations. For non-sequence replacement, retaining the lower YAML identity until another sequence appears is another viable choice; it supports persistent schema-like policy, but conflicts with the current distinction between collection-owned YAML identity and application-owned constraints and would require revisiting OD-3.