Settle persistent sequence operation policy

This commit is contained in:
2026-10-22 23:47:50 +00:00
parent 8691a93ebf
commit 26caa6024e

View File

@@ -1,7 +1,7 @@
# Sequence Identity And Combination # Sequence Identity And Combination
Status: feature roadmap with OD-1 through OD-8 settled and follow-up interaction Status: feature roadmap with OD-1 through OD-9 settled and follow-up interaction
decisions OD-9 through OD-11 open. The original decisions establish the intended decisions OD-10 and OD-11 open. The original decisions establish the intended
operations; the new questions address their lifecycle and policy-scope boundaries. operations; the new questions address their lifecycle and policy-scope boundaries.
Resolve these questions before preparing a staged implementation plan. This is Resolve these questions before preparing a staged implementation plan. This is
not an implementation plan or an implemented contract. not an implementation plan or an implemented contract.
@@ -125,12 +125,12 @@ 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 collection's combination instruction at source-precedence Mode describes the collection's combination instruction at source-precedence
and inheritance boundaries, as detailed in OD-7. A lower tier's and inheritance boundaries, as detailed in OD-7. An explicit mode persists at
`append` does not silently select append for a later overlay. Gather collection the same applicable destination until a higher-tier declaration changes it.
declarations before composing their relevant scope so their effect does not Gather collection declarations before composing their relevant scope so their
depend on which contribution is assembled first. Identity agreement is settled 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. in OD-3; operation agreement and omission among peers are settled in OD-4.
OD-9 addresses which controls survive source precedence for later inheritance. OD-9 settles how operation controls survive source precedence for later inheritance.
Permit sequence declarations in selected overlays and make their use independent Permit sequence declarations in selected overlays and make their use independent
of filesystem import enablement. This deliberately changes the current blanket of filesystem import enablement. This deliberately changes the current blanket
@@ -152,8 +152,9 @@ prompts:
text: Revised definition text: Revised definition
``` ```
The explicit `mode: upsert` line can be omitted here because `key: id` supplies The explicit `mode: upsert` line can be omitted here when no different explicit
an effective identity. An overlay can instead select duplicate-rejecting append: mode applies from a lower tier: `key: id` then supplies the identity for inferred
upsert. An overlay can instead select duplicate-rejecting append:
```yaml ```yaml
configkit: configkit:
@@ -182,11 +183,12 @@ prompts:
text: Baz definition text: Baz definition
``` ```
Explicitly selecting the default operation is valid. Removing the last example's Explicitly selecting the default operation is valid. With no applicable explicit
`configkit` block produces the same replacement behavior only when no effective mode, removing the last example's `configkit` block selects replace only when no
identity is available. For an identified collection, explicit `mode: replace` effective identity is available; an identified collection instead selects upsert.
overrides the inferred `upsert`; it is not redundant. OD-5 defines the selection A retained explicit mode also affects omission. Explicit `mode: replace` overrides
rule for `replace`, `append`, and `upsert`. 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` Start with this common collection declaration and defer `key` and `mode`
shorthand on imports. A single declaration form covers inline overlays and mixed shorthand on imports. A single declaration form covers inline overlays and mixed
@@ -306,7 +308,8 @@ The tier operation does not sequentially replace peer source contributions.
Coalesce agreeing explicit modes for the same collection within a tier and Coalesce agreeing explicit modes for the same collection within a tier and
reject conflicting explicit modes. Omission expresses no preference; apply the reject conflicting explicit modes. Omission expresses no preference; apply the
default only after reconciling declarations. 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 | | Modes declared within one tier | Effective operation |
| --- | --- | | --- | --- |
@@ -314,12 +317,13 @@ default only after reconciling declarations.
| `append` and omitted | `append` | | `append` and omitted | `append` |
| `replace` and omitted | `replace` | | `replace` and omitted | `replace` |
| `append` and `replace` | Error | | `append` and `replace` | Error |
| All omitted | `upsert` with effective identity; otherwise `replace` | | 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 Explicitly selecting the default is a real instruction and can conflict with
another explicit selection. Different modes in different tiers are valid; a another explicit selection. Different modes in different tiers are valid; the
lower tier's mode does not carry forward. Neither a root declaration nor a later higher tier's explicit mode replaces the lower mode, while omission retains it.
declaration wins over conflicting peers. Diagnostics identify the collection 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 destination and conflicting declaration locations. OD-5 defines mode names and
the default-selection rule. the default-selection rule.
@@ -376,21 +380,25 @@ Select the operation at each collection's precedence boundary in this order:
1. Reconcile explicit modes within the current tier under OD-4; conflicting 1. Reconcile explicit modes within the current tier under OD-4; conflicting
explicit modes fail. explicit modes fail.
2. If an explicit mode is supplied, use it. 2. If the current tier supplies an explicit mode, use it in place of a lower mode.
3. Otherwise, select `upsert` when an effective identity is available. 3. Otherwise, retain an applicable explicit mode from a lower tier.
4. Otherwise, select `replace`. 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 Effective identity may come from an application registration, a current-tier
declaration, or the lower collection, subject to OD-3's agreement rules. declaration, or the lower collection, subject to OD-3's agreement rules.
Selection depends on identity availability, not on whether the current tier Selection depends on identity availability, not on whether the current tier
explicitly repeats a `key` declaration. A plain overlay sequence can therefore explicitly repeats a `key` declaration. With no applicable explicit mode, a plain
default to `upsert` when identity was established elsewhere. A lower tier's mode overlay sequence can therefore default to `upsert` when identity was established
does not carry forward. 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 Determine the inferred mode using the available identity before applying the
operation. Explicit `replace` still follows OD-3: discard the lower collection's operation. `replace`, including a retained explicit mode, follows OD-3: discard
YAML-only identity with the lower sequence, use the replacing tier's identity the lower collection's YAML-only identity with the lower sequence, use the
declaration if supplied, and preserve application-owned constraints. Selecting replacing tier's identity 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 and during sibling inheritance This default governs combination between tiers and during sibling inheritance
@@ -525,10 +533,11 @@ non-sequence lower value is distinct from absence: append and upsert against it
fail, while replacement remains available. An empty incoming sequence does not fail, while replacement remains available. An empty incoming sequence does not
bypass these kind checks or the operation's identity requirements. bypass these kind checks or the operation's identity requirements.
With effective identity available, an omitted mode selects upsert. Consequently, With effective identity available and no applicable explicit mode, omission
`prompts: []` alone does not clear an identified collection. Clearing it requires selects upsert. Consequently, `prompts: []` alone does not clear such a collection.
explicit `mode: replace`. Replacing an identified collection with null likewise Clearing it requires replace, selected explicitly in the current tier or retained
requires explicit replacement and an application schema that permits null. 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 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. to exist or be non-null, and does not independently reject non-sequence values.
@@ -551,8 +560,9 @@ Complete source-tier assembly before resolving inheritance, retaining the
existing dependency-ready inheritance algorithm and scope rules. At each existing dependency-ready inheritance algorithm and scope rules. At each
inheritance combination, the resolved parent's collection is the lower value 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 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 operation selection as source precedence: the effective explicit mode wins,
`upsert` with effective identity and `replace` without it. There is no separate 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. default-append rule for inheritance.
Use the inheriting destination collection's controls. Its selected mode governs Use the inheriting destination collection's controls. Its selected mode governs
@@ -681,6 +691,44 @@ in [ADR 0009](../adr/0009-sibling-inheritance.md). It avoids special replacement
markers carried through inheritance. Current contracts remain the implemented markers carried through inheritance. Current contracts remain the implemented
baseline until the architectural and implementation work lands. 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. CLI overrides remain outside sequence mode selection
under OD-8. Strict peer composition and all ordering rules in OD-4 are unchanged.
## 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
@@ -725,35 +773,6 @@ Public API design and test sequencing belong to that later plan.
## Open Decisions ## Open Decisions
### OD-9. Which Controls Survive Until Inheritance?
OD-4 prevents a lower tier's mode from selecting a later tier's operation, while
OD-7 retains destination controls for inheritance after source assembly. The
roadmap needs an explicit rule for a collection left untouched by a higher tier,
a newly supplied sequence with no mode, and declarations supplied without values.
For example, does an unrelated selected overlay erase a main source's explicit
replace instruction for a collection that later inherits records?
**Recommendation:** Distinguish untouched collections from new contributions.
Retain relevant controls for an untouched collection's later inheritance. When
a higher tier supplies a new sequence contribution, select its operation from
that tier's declarations and the effective-identity default; do not reuse the
lower mode. Permit a declaration without a sequence value to control later
inheritance without clearing the collection. Express these cases in a policy
lifetime table covering absent values, key-only and mode-only declarations,
explicit operations, and replacement of a collection or an enclosing subtree.
Identity changes must still satisfy OD-3.
This preserves intentional inheritance controls across unrelated overlays while
keeping each new sequence contribution's precedence operation local to its tier.
**Alternative:** Maintain a destination policy independently of value survival,
letting higher explicit policy fields override lower ones and omissions inherit
them. This makes declaration-only configuration straightforward, but modes can
become sticky when new values arrive. Applying that policy only to inheritance
would preserve OD-4 at the cost of two distinct policy-resolution rules; applying
it to source precedence would require revisiting OD-4.
### OD-10. Identity Availability During Strict Tier Composition ### OD-10. Identity Availability During Strict Tier Composition
Suppose an underlay declares `key: id`, while two main-tier fragments contribute Suppose an underlay declares `key: id`, while two main-tier fragments contribute