diff --git a/docs/policy/architecture.md b/docs/policy/architecture.md index a863610..6450189 100644 --- a/docs/policy/architecture.md +++ b/docs/policy/architecture.md @@ -2,7 +2,7 @@ **Base Policy Version:** 1.3 -**Last Updated**: 2026-10-18 +**Last Updated**: 2026-10-22 **Upstream Source:** [Standard Repository Policies](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/architecture.md) @@ -32,6 +32,12 @@ structure as implemented when its changes land. Constraints must reflect deliberately selected requirements and decisions. Do not promote incidental implementation choices into architectural invariants. +The collection-policy and CLI-ordering requirements below reflect accepted +[ADR 0017](../adr/0017-collection-sequence-policy.md) and +[ADR 0018](../adr/0018-cli-after-structural-resolution.md). The +[sequence roadmap](../roadmap/roadmap.md) tracks the work to implement them; +the configuration contract continues to describe implemented behavior. + ## Success Criteria ConfigKit prioritizes a coherent configuration model: consistency and @@ -183,6 +189,29 @@ The [configuration contract](../config.md#completion-and-resource-lifetime) owns the precise completion and ownership behavior. The proposed decision record is [ADR 0008](../adr/0008-complete-on-return-loading.md). +### Accepted Processing Order + +Complete source composition and precedence, including selected overlays, before +sibling inheritance. Then apply typed defaults and decode the configuration. +Apply explicit CLI overrides to that configuration and check their types before +running application resolution. Effective secret lookup and final validation +follow resolution, before publication. [ADR 0018](../adr/0018-cli-after-structural-resolution.md) +records this ordering. + +CLI overrides are the highest-priority input to application resolution. Supplied +sequences replace whole sequences, and mappings combine recursively. Inheritance +and typed defaulting do not run again after CLI application. CLI paths and values +must not introduce structural directives; earlier source, inheritance, and +decoding failures remain errors even if a CLI assignment would replace the value. +Semantic validation assesses the final configuration after overrides and resolution. + +Applications own flag parsing and domain resolution. ConfigKit owns override +application, validation, and source attribution. Resolution receives CLI values +with their explicit-presence and source information. Absence-based defaults +preserve explicit values; recorded normalization and derivation can still change +them. Typed defaults and application resolution retain their own assignment +semantics, independently of collection operations during source assembly. + ## Public API And Dependency Direction Keep one small, coherent public surface for the supported lifecycle. Simple @@ -211,41 +240,34 @@ framework on this library. ## Configuration Integrity -Within a configuration tier, independent contributions use strict composition: -shared mappings combine recursively, while overlapping non-mapping definitions -are conflicts, including equal values, except that sequences at explicitly -registered paths append records with distinct present string identities. Between -precedence tiers, intentional overlay combines mappings recursively, retains -omitted lower-priority children, -and replaces other present values according to the existing overlay rules. -Tier precedence is explicit; traversal order within a tier establishes stable -reporting, not permission to override. The distinction and its rationale are -recorded in [ADR 0001](../adr/0001-separate-composition-and-overlay.md). - -Sequence-item placement and sequence registration are explicit source and -definition controls; registration does not change precedence replacement. The -[configuration contract](../config.md#strict-document-composition) defines the -behavior, [ADR 0014](../adr/0014-sequence-placement-and-composition.md) records -the decision, and the [consumer guide](../consumers/README.md#identified-prompt-sequences) -shows the implemented subset. This feature does not authorize arbitrary -configurable merge strategies. +Within a configuration tier, independent contributions use strict composition. +Shared mappings combine recursively. Sequences with an applicable identity +combine distinct records and reject duplicate identities, including equal +records. Other overlapping non-mapping values remain conflicts, including equal +values. Conflicting identity or operation declarations among peers also fail. +Traversal order establishes stable reporting and record order; it does not grant +precedence to peers. [ADR 0001](../adr/0001-separate-composition-and-overlay.md) +records the distinction between strict composition and intentional overrides. The main document and its imports form a strictly composed tier. Explicit -underlay groups compose strictly within each group, then combine recursively -from lowest to highest beneath the main tier. Source acquisition kind does not -determine its precedence role. Input-specific constraints, including CLI path -rules and opt-in version ownership, remain part of the configuration contract. Consistent combination -semantics do not require identical acquisition or lifetime behavior from every -source kind. +underlay groups compose strictly within each group, then combine from lowest to +highest beneath the main tier. Between tiers, mappings combine recursively and +retain omitted lower-priority children. Sequence values follow collection policy; +other present values retain the established replacement rules. Source acquisition +kind does not determine precedence. Input-specific constraints, including version +ownership and path protections, remain part of the configuration contract. +Consistent combination semantics do not require identical acquisition or lifetime +behavior from every source kind. -After source precedence is complete, built-in sibling `extends` relationships -resolve structurally in the same parser-independent representation, using the -existing recursive overlay rules. This adds neither an acquired source nor a -consumer registration mechanism. Enclosing relationships precede nested -destination-local resolution; typed defaults, application resolution, and -secret lookup retain their existing lifecycle roles. The [configuration -contract](../config.md#sibling-inheritance) owns the exact syntax and presence -rules, and [ADR 0009](../adr/0009-sibling-inheritance.md) records the rationale. +Built-in sibling `extends` relationships resolve after source precedence in the +parser-independent document representation. Preserve their existing sibling +scopes and resolve enclosing relationships before nested destination-local +relationships. Mappings combine recursively; sequences use the inheriting +collection's policy. Inheritance remains built-in and creates no acquired source. +[ADR 0009](../adr/0009-sibling-inheritance.md) records the +continuing scope and ownership decisions, with sequence combination revised by +[ADR 0017](../adr/0017-collection-sequence-policy.md) and CLI ordering by +[ADR 0018](../adr/0018-cli-after-structural-resolution.md). ConfigKit must define supported YAML semantics explicitly rather than inherit parser defaults. Processing order and diagnostics must be deterministic for the @@ -254,13 +276,14 @@ configuration. Do not run application hooks on invalid typed configuration. User-controlled precedence is application defaults, ordered underlays, composed main input, selected overlay, then explicitly supplied CLI overrides. -Applications own flag parsing; ConfigKit owns overlay semantics and provenance. -Domain resolution follows these -inputs and must remain recorded, not become a hidden override channel. +This priority order is distinct from processing order: typed defaults are applied +at decoding, and application resolution follows CLI input under the lifecycle +rules above. -Preserve node-based composition until the effective input is ready for typed -decoding. Preserve presence and source information through processing. Ordinary Go zero -values must not be used to infer whether input was absent. Final configuration, +Preserve node-based composition through source assembly and inheritance until +typed decoding. Preserve presence and source information through later CLI and +application-resolution changes as well. Ordinary Go zero values must not be used +to infer whether input was absent. Final configuration, metadata, and effective inspection must agree, including application resolution changes; see [ADR 0003](../adr/0003-preserve-presence-and-resolution-history.md). Safe historical values and an explanation renderer are part of the implemented contract, @@ -277,6 +300,72 @@ comparison and disclosure behavior, the [component overview](../internal/overvie owns implementation responsibility, and [ADR 0010](../adr/0010-effective-configuration-diff.md) records the accepted decision. +## Collection Identity And Combination + +ConfigKit owns a common collection policy for imported records, inline sequences, +selected overlays, and sibling inheritance. Configuration authors may declare +identity and combination rules; applications may register authoritative identity +constraints. Configuration declarations must agree with application constraints. +Keep source placement explicit and separate from policy, retaining the placement +decision in [ADR 0014](../adr/0014-sequence-placement-and-composition.md). +[ADR 0017](../adr/0017-collection-sequence-policy.md) owns the rationale for +collection policy and its relationship to application authority. + +Gather declarations for the relevant destination and source or item-local scope +before strict composition. Applicable identity from accumulated lower tiers must +be available when composing higher-tier peers. Higher-tier declarations cannot +repair invalid lower-tier composition. Preserve the distinction between source +acquisition, dependency-ready scheduling within scopes, and precedence order. + +Strictly compose each tier's contributions before applying one operation for the +collection against its lower value. Support whole-sequence replacement, +duplicate-rejecting append, and whole-record replacement by identity (`upsert`). +Append and upsert require identity; do not infer it from record fields or position. +Duplicate identities among peers fail under every mode. Source precedence and +inheritance use the same operations and deterministic ordering rules. Whole-record +upsert replaces the matching record's fields together; recursive record merging +and unkeyed sequence concatenation are outside this operation model. + +An explicit mode persists at its applicable destination until a higher explicit +mode changes it. With no explicit mode, effective identity selects upsert and +its absence selects whole-sequence replacement. Inferred defaults do not become +persistent instructions. The inheriting destination chooses its operation; copying +a parent collection does not automatically copy its mode to that destination. + +Track YAML identity and explicit modes according to their separate lifetimes. +Actual whole-value replacement discards lower YAML identity while preserving +application constraints and any new identity declaration. Item-local policies +belong to their records: retaining a record retains its rules, and discarding it +discards those rules. Policies independently applicable at a destination remain +in effect. Inheritance can copy YAML identity subject to agreement and replacement +rules; application registrations continue to constrain their registered paths. +Numeric positions alone do not establish policy ownership. + +Allow declarations without accompanying records. A key declaration validates a +retained sequence immediately or remains pending in its owning scope when no +sequence exists. A mode-only declaration affects later combinations without +recombining earlier tiers. Neither declaration alone clears a collection, and +declaring replace alone does not authorize changing a retained collection's +identity. These rules do not independently impose path-existence or shape +requirements. + +Enforce YAML identity during source composition, precedence, and identified +inheritance operations. Application registrations additionally constrain final +effective sequences after defaults, CLI overrides, and application resolution. +The application schema and validation own existence, nullability, and allowed +shape. The final identity guarantee covers actual sequences on successful load; +it does not cover every intermediate callback state or later caller mutations. +YAML-only declarations carry no such final guarantee through defaults, CLI +assignments, or application resolution. + +Preserve source attribution, presence, history, sensitivity, and resource context +as records survive, move, or are replaced. Identity diagnostics use paths and +available origin information without exposing identity values. The guarantee +requires no new mutation-history system or exact reconstruction of causes for +records supplied by defaults or callbacks. Exact identity equality, declaration +syntax, presence cases, and operation tables belong in the configuration contract +when implemented; the roadmap owns those details until then. + ## Ownership And Confidentiality Returned configuration and metadata must not share mutable state across loads. diff --git a/docs/roadmap/roadmap.md b/docs/roadmap/roadmap.md index dc6ba6c..ba49b56 100644 --- a/docs/roadmap/roadmap.md +++ b/docs/roadmap/roadmap.md @@ -658,9 +658,9 @@ order and test sequencing defined there: 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 +Their scoped supersession is recorded in the affected earlier ADRs, and the +[architecture policy](../policy/architecture.md) reflects the accepted decisions. +These govern the target architecture; the configuration contract continues to describe implemented behavior until the feature lands. This roadmap does not select migration machinery.