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
|
capabilities, settled design choices, and initial recommendations. Choices under
|
||||||
Open Decisions remain unsettled.
|
Open Decisions remain unsettled.
|
||||||
It is not an implementation plan or an implemented contract. The declaration
|
It is not an implementation plan or an implemented contract. The declaration
|
||||||
structure is settled under OD-2; operation names in examples remain illustrative
|
structure is settled under OD-2; mode names and default selection are settled
|
||||||
pending OD-5.
|
under OD-5.
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
|
|
||||||
@@ -75,22 +75,21 @@ text: Welcome
|
|||||||
|
|
||||||
Here `mode: append` illustrates retaining a lower-layer collection and adding
|
Here `mode: append` illustrates retaining a lower-layer collection and adding
|
||||||
distinct records from the higher layer. The `mode` field expresses the operation;
|
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.
|
controls belong to the collection declaration; import shorthand is deferred.
|
||||||
|
|
||||||
The intended results can be expressed without settling operation names. Letters
|
Letters below denote record identities; `B*` is a higher-tier record with the same
|
||||||
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
|
identity as `B` and a different payload. The outcomes and ordering shown are
|
||||||
settled below.
|
settled below.
|
||||||
|
|
||||||
| Lower-tier sequence | Higher-tier sequence | Operation | Proposed result |
|
| Lower-tier sequence | Higher-tier sequence | Operation | Proposed result |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `[A, B]` | `[C]` | Append | `[A, B, C]` |
|
| `[A, B]` | `[C]` | `append` | `[A, B, C]` |
|
||||||
| `[A, B]` | `[C]` | Whole-sequence replacement | `[C]` |
|
| `[A, B]` | `[C]` | `replace` | `[C]` |
|
||||||
| `[A, B]` | `[B*]` | Append | Duplicate-identity error |
|
| `[A, B]` | `[B*]` | `append` | Duplicate-identity error |
|
||||||
| `[A, B]` | `[B*]` | Whole-sequence replacement | `[B*]` |
|
| `[A, B]` | `[B*]` | `replace` | `[B*]` |
|
||||||
| `[A, B]` | `[B*]` | Replacement by identity | `[A, B*]` |
|
| `[A, B]` | `[B*]` | `upsert` | `[A, B*]` |
|
||||||
| `[A, B]` | `[B*, C]` | Replacement by identity | `[A, B*, C]` |
|
| `[A, B]` | `[B*, C]` | `upsert` | `[A, B*, C]` |
|
||||||
|
|
||||||
Whole-sequence replacement discards the lower sequence. A repeated identity in the
|
Whole-sequence replacement discards the lower sequence. A repeated identity in the
|
||||||
retained combined sequence is an error under the proposed append semantics,
|
retained combined sequence is an error under the proposed append semantics,
|
||||||
@@ -139,14 +138,15 @@ configkit:
|
|||||||
sequences:
|
sequences:
|
||||||
- destination: [prompts]
|
- destination: [prompts]
|
||||||
key: id
|
key: id
|
||||||
mode: replace-by-key
|
mode: upsert
|
||||||
|
|
||||||
prompts:
|
prompts:
|
||||||
- id: foo
|
- id: foo
|
||||||
text: Revised definition
|
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
|
```yaml
|
||||||
configkit:
|
configkit:
|
||||||
@@ -175,11 +175,11 @@ prompts:
|
|||||||
text: Baz definition
|
text: Baz definition
|
||||||
```
|
```
|
||||||
|
|
||||||
Explicitly selecting the default operation is valid. Under the recommended
|
Explicitly selecting the default operation is valid. Removing the last example's
|
||||||
whole-sequence replacement default, removing the last example's `configkit`
|
`configkit` block produces the same replacement behavior only when no effective
|
||||||
block produces the same result. An author may keep it to make intent explicit.
|
identity is available. For an identified collection, explicit `mode: replace`
|
||||||
The names `replace`, `append`, and `replace-by-key` illustrate the three
|
overrides the inferred `upsert`; it is not redundant. OD-5 defines the selection
|
||||||
operations; exact names and the default remain under OD-5.
|
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
|
||||||
@@ -304,14 +304,14 @@ 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 | 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
|
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; a
|
||||||
lower tier's mode does not carry forward. Neither a root declaration nor a later
|
lower tier's mode does not carry forward. Neither a root declaration nor a later
|
||||||
declaration wins over conflicting peers. Diagnostics identify the collection
|
declaration wins over conflicting peers. Diagnostics identify the collection
|
||||||
destination and conflicting declaration locations. Mode names remain
|
destination and conflicting declaration locations. OD-5 defines mode names and
|
||||||
illustrative pending OD-5.
|
the default-selection rule.
|
||||||
|
|
||||||
#### Strict Duplicate Handling
|
#### 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
|
preserves its position; whole-sequence replacement gives the higher tier control
|
||||||
of the complete sequence order.
|
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.
|
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
|
### 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.
|
complete higher record, retains unmatched lower records, and adds new identities.
|
||||||
For example, given these lower and higher records:
|
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.
|
OD-4 rule that matched records retain their lower positions.
|
||||||
|
|
||||||
The settled OD-2 collection declaration supplies the overlay authoring surface.
|
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
|
[selected-overlay contract](../config.md#selected-overlays) remains the baseline
|
||||||
until the new controls are implemented.
|
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
|
operations could produce a final collection that no longer satisfies that
|
||||||
identity declaration.
|
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?
|
### OD-6. What Do Absence, Empty Sequences, And Null Mean?
|
||||||
|
|
||||||
Can a declaration selecting nothing affect a lower collection? How do explicit
|
Can a declaration selecting nothing affect a lower collection? How do explicit
|
||||||
|
|||||||
Reference in New Issue
Block a user