From 8ddf73ede36b38c7555faf6b823947060f1c2bf2 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Fri, 23 Oct 2026 01:09:24 +0000 Subject: [PATCH] Accept collection policy and CLI lifecycle decisions --- ...explicit-overrides-and-safe-explanation.md | 4 +- docs/adr/0007-source-backed-underlays.md | 4 +- docs/adr/0009-sibling-inheritance.md | 9 +- ...0014-sequence-placement-and-composition.md | 8 +- docs/adr/0017-collection-sequence-policy.md | 117 ++++++++++++++++++ .../0018-cli-after-structural-resolution.md | 84 +++++++++++++ docs/development.md | 2 + docs/roadmap/roadmap.md | 16 +-- 8 files changed, 230 insertions(+), 14 deletions(-) create mode 100644 docs/adr/0017-collection-sequence-policy.md create mode 100644 docs/adr/0018-cli-after-structural-resolution.md diff --git a/docs/adr/0005-explicit-overrides-and-safe-explanation.md b/docs/adr/0005-explicit-overrides-and-safe-explanation.md index 09b5c30..243e968 100644 --- a/docs/adr/0005-explicit-overrides-and-safe-explanation.md +++ b/docs/adr/0005-explicit-overrides-and-safe-explanation.md @@ -1,6 +1,8 @@ # ADR 0005: Record explicit CLI overrides and safe value explanation -Status: accepted +Status: Partially superseded by +[ADR 0018](0018-cli-after-structural-resolution.md) for override-before-decoding +ordering. The remaining ownership and safe explanation decisions remain accepted. Date: 2026-09-06 diff --git a/docs/adr/0007-source-backed-underlays.md b/docs/adr/0007-source-backed-underlays.md index 16bb745..c8cf937 100644 --- a/docs/adr/0007-source-backed-underlays.md +++ b/docs/adr/0007-source-backed-underlays.md @@ -2,7 +2,9 @@ ## Status -Proposed draft for review. Completed planning and remediation records are +Proposed draft for review; its whole-sequence precedence replacement rule is +superseded by [ADR 0017](0017-collection-sequence-policy.md). The remainder +retains its proposed status. Completed planning and remediation records are preserved in Git history at `b604aa1` under `docs/roadmap/`; the [configuration contract](../config.md#layered-loading) owns current behavior. diff --git a/docs/adr/0009-sibling-inheritance.md b/docs/adr/0009-sibling-inheritance.md index c4457c4..deb6c07 100644 --- a/docs/adr/0009-sibling-inheritance.md +++ b/docs/adr/0009-sibling-inheritance.md @@ -2,8 +2,13 @@ ## Status -Accepted and implemented. The [configuration contract](../config.md#sibling-inheritance) -owns current behavior. The completed implementation plan is preserved in Git +Partially superseded by [ADR 0017](0017-collection-sequence-policy.md) for +sequence combination and [ADR 0018](0018-cli-after-structural-resolution.md) for +CLI-before-inheritance ordering. The remaining inheritance scope, ownership, and +inspection decisions remain accepted. + +The [configuration contract](../config.md#sibling-inheritance) owns implemented +behavior. The completed implementation plan is preserved in Git history at `83c59ea`. ## Date diff --git a/docs/adr/0014-sequence-placement-and-composition.md b/docs/adr/0014-sequence-placement-and-composition.md index b78ebfd..bc7a8e0 100644 --- a/docs/adr/0014-sequence-placement-and-composition.md +++ b/docs/adr/0014-sequence-placement-and-composition.md @@ -2,8 +2,12 @@ ## Status -Accepted and implemented. The [configuration contract](../config.md#strict-document-composition) -defines current behavior, and the [consumer guide](../consumers/README.md#identified-prompt-sequences) +Partially superseded by [ADR 0017](0017-collection-sequence-policy.md) for +identity ownership and sequence combination. Explicit source placement remains +accepted. + +The [configuration contract](../config.md#strict-document-composition) +defines implemented behavior, and the [consumer guide](../consumers/README.md#identified-prompt-sequences) shows the maintained example. The completed roadmap, implementation plan, and resolved remediation record are preserved in Git history at `008d2ba` under `docs/roadmap/`; see the [development guide](../development.md) for retrieval diff --git a/docs/adr/0017-collection-sequence-policy.md b/docs/adr/0017-collection-sequence-policy.md new file mode 100644 index 0000000..1e56336 --- /dev/null +++ b/docs/adr/0017-collection-sequence-policy.md @@ -0,0 +1,117 @@ +# ADR 0017: Define Identity and Merge Rules for Each Collection + +## Status + +Accepted. + +This supersedes the decisions about who declares identity and how +sequences combine in [ADR 0014](0014-sequence-placement-and-composition.md), +and the rule that inheritance always replaces sequences in +[ADR 0009](0009-sibling-inheritance.md). The existing source-placement and +inheritance-scope rules continue to apply. It also supersedes the whole-sequence +precedence replacement rule in the proposed +[ADR 0007](0007-source-backed-underlays.md). + +## Date + +2026-10-22 + +## Context + +ConfigKit can load separate files as records in a sequence. Applications can +register an identity key so records with different identities combine and +duplicates fail. However, a higher configuration layer or an inheriting mapping +currently replaces the whole sequence. Applications that need to extend a +catalog across layers must write their own merging code and keep source and +history information consistent with its results. + +Configuration authors need to choose how records are identified and whether a +layer adds records, updates records, or replaces the collection. Applications +also need a way to require unique identities in the final loaded configuration. +These rules must work consistently for imported records, inline sequences, +overlays, and inheritance. + +## Decision + +ConfigKit manages identity and merge rules for each collection during loading. +Configuration files can declare those rules for imported and inline sequences, +including sequences in selected overlays. Applications can require a particular +identity definition, and configuration declarations must agree with it. Source +placement determines where each contribution enters the configuration. + +Keep the distinction between contributions at the same priority and overrides +from a higher layer, as established in +[ADR 0001](0001-separate-composition-and-overlay.md). Within one tier, records +with distinct identities combine; duplicate identities and conflicting +declarations fail. Determine the applicable rules before combining those +contributions, including any identity established in lower tiers. + +Across layers, support three operations: replace the whole sequence, append +records while rejecting duplicate identities, or replace whole records by +identity (`upsert`). Source layering and sibling inheritance use the same +operations. For inheritance, the rules at the inheriting destination determine +which operation applies. + +An explicitly selected operation remains in effect at its destination until a +higher layer changes it. When no explicit operation applies, use upsert if an +identity definition is available; otherwise replace the whole sequence. Authors +can declare identity and an operation before supplying any records. Keep source +acquisition order separate from layer priority and the dependency ordering +established by [ADR 0015](0015-shared-dependency-ready-ordering.md). + +Rules declared inside a record belong to that record. Retaining the record +retains its local rules; replacing it discards them. Replacing a whole collection +can discard its previous YAML identity definition, while application requirements +still apply. Inheritance can copy collection identity, but the inheriting +destination chooses its operation. Application registrations continue to govern +the paths where they were registered. The same ownership rules apply to +declarations made before a sequence exists. + +Check YAML-declared identity when combining collections during source assembly +and inheritance. Application registrations also require the final loaded +sequences to satisfy their identity rules, including after typed defaults, CLI +overrides, and application resolution. This guarantee checks sequences that +exist; the application schema and validation decide whether a collection must +exist and which value types are allowed. The guarantee applies when loading +completes, rather than to every intermediate callback state or changes made by +the caller afterward. + +Preserve explicit presence, source attribution, history, sensitivity, and +resource context through these operations, following +[ADR 0003](0003-preserve-presence-and-resolution-history.md). Typed defaults, +CLI assignments, and application resolution keep their own rules for changing +values. The public API provides registration and inspection; the implementation +chooses how to store and track collection rules internally. + +## Alternatives Considered + +- **Keep identity application-owned and always replace sequences across layers.** + Keeps the current design small, but reusable catalogs require application + changes or custom merging code. +- **Put merge rules on each import.** Keeps the rules beside the imported source, + but inline sequences and overlays need a separate way to declare them. It also + makes rules for a collection spread across several imports harder to reconcile. +- **Merge individual fields of records with matching identities.** Allows partial + record updates, but adds rules for field conflicts and retained values. + Replacing the whole record makes the update's scope clear. +- **Check every YAML identity again at the end of loading.** Gives YAML declarations + authority over values changed by defaults, CLI assignments, and application + resolution. This extends the lifetime of those declarations; application + registration provides that final guarantee when needed. + +## Consequences + +Consumers can build and customize catalogs in one load while retaining useful +inspection information. Configuration authors choose how collections combine +within application requirements. Duplicate identities among contributions at +the same priority remain errors. + +Existing registered collections use upsert across layers by default unless an +explicit operation selects otherwise. Correct loading now requires tracking +which declarations still apply as records are replaced, copied, or moved to new +positions. Lower-tier identity must be available before combining higher-tier +contributions. + +The configuration contract will define declaration syntax, identity comparison, +omission and empty-value behavior, and diagnostics when the feature is +implemented. diff --git a/docs/adr/0018-cli-after-structural-resolution.md b/docs/adr/0018-cli-after-structural-resolution.md new file mode 100644 index 0000000..3a9530a --- /dev/null +++ b/docs/adr/0018-cli-after-structural-resolution.md @@ -0,0 +1,84 @@ +# ADR 0018: Apply CLI Overrides After Inheritance and Decoding + +## Status + +Accepted. + +This supersedes the rule that CLI overrides apply before decoding in +[ADR 0005](0005-explicit-overrides-and-safe-explanation.md) and the +rule that they apply before inheritance in [ADR 0009](0009-sibling-inheritance.md). +Their remaining ownership, inheritance scope, and safe inspection decisions +continue to apply. + +## Date + +2026-10-22 + +## Context + +Explicit command-line values are the operator's highest-priority input. If they +apply before inheritance, a sequence supplied as a replacement could gain +inherited records afterward. Its final contents would then differ from the +operator's assignment. + +The application also needs these values when it fills missing settings, +normalizes values, or computes derived settings. ConfigKit needs a clear loading +order that preserves both CLI precedence and the application's role in resolving +the final configuration. + +## Decision + +ConfigKit uses this loading order: + +1. Combine sources within tiers and apply precedence between layers. +2. Resolve sibling inheritance, apply typed defaults, and decode the configuration + into the application's types. +3. Apply explicit CLI overrides and check them against the application schema. +4. Run application resolution using the overridden configuration. +5. Look up effective secret references, validate the final configuration, and + return it. + +CLI overrides are the highest-priority input to application resolution. A CLI +sequence replaces the whole sequence; mappings combine recursively. Collection +merge rules apply during the earlier source and inheritance steps. Inheritance +and typed defaulting do not run again after CLI overrides. + +Keep track of which values were explicitly supplied and which CLI input supplied +them. Applications continue to parse command-line arguments; ConfigKit applies +and validates the overrides and makes their effects inspectable. Reject +structural directives in override paths and values, so instructions such as +inheritance relationships remain part of source processing. + +Application resolution keeps its existing rules for defaults and recorded +changes under [ADR 0003](0003-preserve-presence-and-resolution-history.md). +It receives CLI values together with their presence and source information. +Defaults that only fill missing settings preserve explicit CLI values. +Application normalization and derived-value calculations can still change them, +with those changes recorded. Secret lookup and final validation use the resulting +configuration. + +## Alternatives Considered + +- **Apply CLI overrides before inheritance.** Preserves existing ordering, but + later merging needs special handling to preserve CLI replacement intent while + still combining ordinary source contributions. +- **Apply CLI overrides after inheritance but before typed decoding.** Allows an + override to fix a source value that would otherwise fail decoding, but leaves + typed defaulting after the operator's assignment. Completing defaulting and + decoding first gives CLI overrides an already resolved configuration to modify. +- **Apply CLI overrides after application resolution.** Applies assignments after + the application's changes, but derived settings still reflect earlier values + unless resolution runs again. + +## Consequences + +CLI overrides change a configuration whose inheritance and typed defaults are +already resolved. The application can then derive settings from the operator's +values. The final values, source information, history, and sensitivity handling +must remain consistent throughout loading. + +CLI input can no longer add or cancel inheritance relationships or bypass an +earlier error in source assembly or inheritance. It also cannot fix a value that +fails the earlier decoding step. Semantic validation still runs after overrides +and application resolution. The configuration contract and consumer guidance +must explain these behavior changes when they are implemented. diff --git a/docs/development.md b/docs/development.md index 1f82550..f1d9ce2 100644 --- a/docs/development.md +++ b/docs/development.md @@ -61,6 +61,8 @@ Accepted decisions: - [Place inputs at literal application mapping paths](adr/0011-input-destinations.md) - [Share dependency-ready ordering](adr/0015-shared-dependency-ready-ordering.md) - [Separate import selection controls](adr/0016-independent-import-controls.md) +- [Define identity and merge rules for each collection](adr/0017-collection-sequence-policy.md) +- [Apply CLI overrides after inheritance and decoding](adr/0018-cli-after-structural-resolution.md) For cross-cutting changes, follow every applicable row. Completed implementation and remediation plans are preserved in Git history at `cb5b435`; use current diff --git a/docs/roadmap/roadmap.md b/docs/roadmap/roadmap.md index ecc06f0..dc6ba6c 100644 --- a/docs/roadmap/roadmap.md +++ b/docs/roadmap/roadmap.md @@ -655,14 +655,14 @@ order and test sequencing defined there: selected overlays, inheritance, typed defaults, CLI, callbacks, and inspection. Update the public contract and consumer examples when behavior lands. -Before implementation, record the durable architectural changes in a superseding -decision and reconcile affected architecture policy. The feature changes identity -ownership and precedence replacement in -[ADR 0014](../adr/0014-sequence-placement-and-composition.md), and sequence -combination and CLI-before-inheritance ordering in -[ADR 0009](../adr/0009-sibling-inheritance.md). Existing ADRs and contracts remain -authoritative until that architectural and implementation work lands. This roadmap -does not select migration machinery. +The durable architectural changes are accepted in +[ADR 0017](../adr/0017-collection-sequence-policy.md) for collection policy and +[ADR 0018](../adr/0018-cli-after-structural-resolution.md) for CLI ordering. +Their scoped supersession is recorded in the affected earlier ADRs. Reconcile +architecture policy with these decisions before implementation. The accepted +ADRs govern the target architecture; the configuration contract continues to +describe implemented behavior until the feature lands. This roadmap does not +select migration machinery. No open feature decisions remain. The implementation plan should translate this end state into reviewable stages without adding new guarantees, restrictions, or