diff --git a/docs/adr/0015-shared-dependency-ready-ordering.md b/docs/adr/0015-shared-dependency-ready-ordering.md new file mode 100644 index 0000000..efb4bab --- /dev/null +++ b/docs/adr/0015-shared-dependency-ready-ordering.md @@ -0,0 +1,66 @@ +# ADR 0015: Share Dependency-Ready Ordering Across Imports and Inheritance + +## Status + +Accepted. + +## Date + +2026-10-19 + +## Context + +Imports and sibling inheritance both resolve relationships between configuration +contributions. Their existing resolvers use different traversal rules, making +ordering depend on which mechanism expresses a dependency. Ordering affects +sequence contributions, provenance, and diagnostics, so a consistent rule is +part of ConfigKit's configuration model. + +The resolvers also serve distinct purposes. Imports strictly compose sources; +inheritance overlays a child on its resolved parent after source assembly. +Item-local contributions and nested inheritance introduce scope boundaries that +resolution must preserve. + +## Decision + +ConfigKit owns one shared dependency-ready scheduler for imports and sibling +inheritance. Both resolvers use Kahn's algorithm with a stable ordering key, +selecting the smallest currently eligible node after its dependencies have +completed. The shared scheduler owns eligibility, deterministic tie-breaking, +and dependency-cycle identification. Each resolver owns construction of its +dependency relationships and application of its domain operations. + +Apply the common scheduling rule within the scopes where dependencies are +available. Complete item-local contributions before item placement and resolve +enclosing inheritance before relationships in the resulting nested scopes. +Source discovery supplies the import graph; the scheduler determines resolution +order. + +Strict composition, inheritance overlay, and precedence tiers retain their +existing ownership and meanings under [ADR 0001](0001-separate-composition-and-overlay.md). +The lifecycle and scope decisions in +[ADR 0009](0009-sibling-inheritance.md) continue to govern inheritance. Import +admission retains its cycle and repeated-source rules. + +## Alternatives Considered + +- **Deterministic depth-first postorder.** Keeps dependency branches together, + but gives traversal branch selection an additional role in ordering. +- **Dependency rounds.** Groups nodes by readiness rounds, but delays newly + eligible nodes until the current round finishes. +- **Descending longest-path depth.** Prioritizes the furthest dependencies, + but adds distance from the root as an ordering policy. +- **Separate resolver algorithms.** Allows local specialization, but leaves + consumers and maintainers with different rules for analogous dependencies. + +## Consequences + +Both resolvers follow one deterministic ordering model and share responsibility +for maintaining that model. Resolver-specific scopes, combination semantics, +and source-admission rules remain explicit at their integration boundaries. + +Independent branches may interleave as nodes become eligible. Adopting this +rule changes existing traversal-dependent sequence positions and reporting +order, requiring coordinated review of source assembly, provenance, and +inheritance behavior. The configuration contract owns the implemented ordering +details. diff --git a/docs/adr/0016-independent-import-controls.md b/docs/adr/0016-independent-import-controls.md new file mode 100644 index 0000000..bcb507d --- /dev/null +++ b/docs/adr/0016-independent-import-controls.md @@ -0,0 +1,80 @@ +# ADR 0016: Separate Import Selection, Traversal, and Presence Requirements + +## Status + +Accepted. + +## Date + +2026-10-19 + +## Context + +Consumers assemble configurations from named files and collections whose layout +varies between installations. Simple imports should require little setup, while +larger collections need control over discovery, recursion, filtering, and +required contributions. Combining those choices implicitly makes declarations +harder to interpret and pushes source-selection work into applications. + +Discovery can also reach a candidate through overlapping searches or encounter +different names for one canonical source. Selection and source admission need +distinct identities to support useful search unions while preserving ConfigKit's +existing source-integrity rules. + +## Decision + +ConfigKit owns import discovery and selection within its source-loading +lifecycle. Support explicit files, directory searches, and path globs as +distinct selection forms. Keep traversal, filename filtering, and presence +requirements independently expressible. Discovery determines the selected +contributions; the shared scheduler in +[ADR 0015](0015-shared-dependency-ready-ordering.md) determines their resolution +order. + +Use optional-by-default imports with explicit requiredness controls. Selected +sources remain subject to ConfigKit's validity, containment, resource, and +composition contracts. This applies the library's +[simplicity and defaults principles](../policy/architecture.md#simplicity-defaults-and-explicit-controls) +to import absence while retaining meaningful errors for invalid contributions. + +Applications own their selected import defaults. Authored declaration values +take precedence over application defaults, which take precedence over library +defaults. Each declaration resolves applicable controls independently, +including declarations in imported sources. This gives applications a shared +baseline while preserving explicit choices in individual declarations. + +Keep declaration-local candidate identity separate from canonical source +identity. Search unions coalesce repeated candidate paths within a source +namespace before symlink resolution; filename filtering uses the selected or +discovered name. Source admission continues to use canonical identity and the +existing repeated-source rules. Distinct aliases retain their separate +inclusion routes. + +## Alternatives Considered + +- **Use path globs for all discovery.** Offers one selection form, but makes + collection traversal depend on path-pattern structure and complicates + independently controlling recursion and filename filtering. +- **Offer only explicit files and directory searches.** Reduces the selector + vocabulary, but moves wildcard directory selection into repeated declarations + or application-side discovery. +- **Require every import by default.** Detects absent contributions immediately, + but requires repeated opt-outs for installations with optional components. +- **Make application settings override authored declarations.** Provides central + enforcement, but prevents declarations from expressing local exceptions. +- **Deduplicate selections globally by canonical source identity.** Coalesces + aliases and separate inclusion routes, but changes the existing repeated-source + contract and obscures independently authored contributions. + +## Consequences + +Consumers can express simple imports and more selective collection searches +through the same loading lifecycle. Applications choose defaults and validate +their required effective configuration; ConfigKit owns consistent selection, +source admission, composition, and inspection. + +Optional absence can conceal misspelled selectors, so requiredness and +inspection provide explicit ways to detect and explain missing contributions. +Declaration-local deduplication requires the loader to preserve candidate +identity alongside canonical source identity. The configuration and public API +contracts own the implemented behavior. diff --git a/docs/roadmap/imports.md b/docs/roadmap/imports.md index 8d618e9..62bba02 100644 --- a/docs/roadmap/imports.md +++ b/docs/roadmap/imports.md @@ -1,13 +1,20 @@ # Import Ergonomics And Permissive Defaults -Status: working draft / brainstorming notes. This document captures a proposed -direction for discussion, not an implemented contract or an implementation plan. +Status: accepted design; implementation pending. This document captures planned +behavior and requirements. Implementation sequencing remains to be prepared. The selected direction separates directory searches, filename matching, recursion, and absence handling. Optional-by-default imports are the intended direction. The consumer-directed and Ansible-aligned decisions below are settled; API spelling and implementation details remain for implementation planning. All new syntax below is illustrative and unimplemented. +The durable architectural decisions are recorded in +[ADR 0015: Share Dependency-Ready Ordering Across Imports and Inheritance](../adr/0015-shared-dependency-ready-ordering.md) +and +[ADR 0016: Separate Import Selection, Traversal, and Presence Requirements](../adr/0016-independent-import-controls.md). +This roadmap owns implementation status and the detailed requirements for +carrying out those accepted decisions. + ## Guiding Philosophy ConfigKit should provide predictable configuration mechanisms and avoid imposing