Settle sequence mode names and identity-based defaults
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user