Settle sequence mode names and identity-based defaults

This commit is contained in:
2026-10-22 14:39:40 +00:00
parent 12f6045da0
commit 29f94d89e1

View File

@@ -4,8 +4,8 @@ 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; operation names in examples remain illustrative
pending OD-5.
structure is settled under OD-2; mode names and default selection are settled
under OD-5.
## Motivation
@@ -75,22 +75,21 @@ 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;
operation names and default behavior remain under OD-5. Identity and combination
OD-5 defines its names and effective-identity default. Identity and combination
controls belong to the collection declaration; import shorthand is deferred.
The intended results can be expressed without settling operation names. Letters
below denote record identities; `B*` is a higher-tier record with the same
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]` | Whole-sequence replacement | `[C]` |
| `[A, B]` | `[B*]` | Append | Duplicate-identity error |
| `[A, B]` | `[B*]` | Whole-sequence replacement | `[B*]` |
| `[A, B]` | `[B*]` | Replacement by identity | `[A, B*]` |
| `[A, B]` | `[B*, C]` | Replacement by identity | `[A, B*, C]` |
| `[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,
@@ -139,14 +138,15 @@ configkit:
sequences:
- destination: [prompts]
key: id
mode: replace-by-key
mode: upsert
prompts:
- id: foo
text: Revised definition
```
An overlay can instead add a distinct record:
The explicit `mode: upsert` line can be omitted here because `key: id` supplies
an effective identity. An overlay can instead select duplicate-rejecting append:
```yaml
configkit:
@@ -175,11 +175,11 @@ prompts:
text: Baz definition
```
Explicitly selecting the default operation is valid. Under the recommended
whole-sequence replacement default, removing the last example's `configkit`
block produces the same result. An author may keep it to make intent explicit.
The names `replace`, `append`, and `replace-by-key` illustrate the three
operations; exact names and the default remain under OD-5.
Explicitly selecting the default operation is valid. Removing the last example's
`configkit` block produces the same replacement behavior only when no effective
identity is available. For an identified collection, explicit `mode: replace`
overrides the inferred `upsert`; it is not redundant. 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
@@ -304,14 +304,14 @@ default only after reconciling declarations.
| `append` and omitted | `append` |
| `replace` and omitted | `replace` |
| `append` and `replace` | Error |
| All omitted | Default selected under OD-5 |
| All omitted | `upsert` with effective identity; otherwise `replace` |
Explicitly selecting the default is a real instruction and can conflict with
another explicit selection. Different modes in different tiers are valid; a
lower tier's mode does not carry forward. Neither a root declaration nor a later
declaration wins over conflicting peers. Diagnostics identify the collection
destination and conflicting declaration locations. Mode names remain
illustrative pending OD-5.
destination and conflicting declaration locations. OD-5 defines mode names and
the default-selection rule.
#### Strict Duplicate Handling
@@ -342,12 +342,55 @@ For example, lower `[A, B, C]` and higher `[C*, A*, D]` produce
preserves its position; whole-sequence replacement gives the higher tier control
of the complete sequence order.
OD-5 retains default selection and operation naming. Absent contributions, empty
OD-5 settles default selection and operation naming. Absent contributions, empty
sequences, null, and kind mismatches remain under OD-6.
### Mode Names And Effective-Identity Defaults
**OD-5: settled.**
Use the mode names `replace`, `append`, and `upsert`, with one spelling per
operation:
| Mode | Behavior between tiers |
| --- | --- |
| `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 an explicit mode is supplied, use it.
3. Otherwise, select `upsert` when an effective identity is available.
4. 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. A plain overlay sequence can therefore
default to `upsert` when identity was established elsewhere. A lower tier's mode
does not carry forward.
Determine the inferred mode using the available identity before applying the
operation. Explicit `replace` still 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. 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 third cross-tier operation replaces each matching lower record with the
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:
@@ -388,7 +431,7 @@ 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 retains operation naming and default selection. The current
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.
@@ -493,27 +536,6 @@ Limiting YAML-only identity to assembly keeps policy lifetime narrower, but late
operations could produce a final collection that no longer satisfies that
identity declaration.
### OD-5. What Is The Default Operation And Its Syntax?
Choose names for the three `mode` values and decide the default operation.
OD-2 settles the declaration structure and accepts explicit selection of the
default. OD-4 settles omission as no preference among peer declarations, with the
default applied after reconciliation.
**Initial recommendation:** Keep whole-sequence replacement as the cross-tier
default and make append and replacement by identity explicit. Lists can represent
complete ordered instructions as well as extensible catalogs; an explicit append
communicates the intent to retain
lower-layer records. Use names that distinguish whole-sequence from whole-record
replacement; the examples use `replace`, `append`, and `replace-by-key`.
**Alternative:** Default identified collections to append or replacement by
identity and require explicit whole-sequence replacement. These defaults make
progressive collections concise, but retain lower-layer records unless an author
deliberately replaces the collection. For naming, `upsert` is a concise alternative
to `replace-by-key`, but requires explaining its whole-record replacement behavior
to authors unfamiliar with that term.
### OD-6. What Do Absence, Empty Sequences, And Null Mean?
Can a declaration selecting nothing affect a lower collection? How do explicit